3 // Part of the Architektonas Project
4 // Originally part of QCad Community Edition by Andrew Mustun
5 // Extensively rewritten and refactored by James L. Hammons
6 // Portions copyright (C) 2001-2003 RibbonSoft
7 // Copyright (C) 2010 Underground Software
8 // See the README and GPLv2 files for licensing and warranty information
10 // JLH = James L. Hammons <jlhamm@acm.org>
13 // --- ---------- -----------------------------------------------------------
14 // JLH 05/21/2010 Added this text. :-)
19 #include "enums.h" // For RS_MIN/MAXDOUBLE (!)
21 #include "mathextra.h"
24 * Constructor for a point with default coordinates.
28 //DEBUG->print("Vector::Vector");
33 * Constructor for a point with given coordinates.
35 Vector::Vector(double vx, double vy, double vz)
37 //DEBUG->print("Vector::Vector");
42 * Constructor for a point with given coordinates in an array
45 //Vector::Vector(double v[]) {
46 // set(v[0], v[1], v[2]);
50 * Constructor for a point with given valid flag.
52 * @param valid true: a valid vector with default coordinates is created.
53 * false: an invalid vector is created
55 Vector::Vector(bool valid)
57 //DEBUG->print("Vector::Vector");
67 //DEBUG->print("Vector::~Vector");
71 * Sets a new position for the vector.
73 void Vector::set(double vx, double vy, double vz)
82 * Sets a new position for the vector in polar coordinates.
84 void Vector::setPolar(double radius, double angle)
86 x = radius * cos(angle);
87 y = radius * sin(angle);
93 * @return The angle from zero to this vector (in rad).
95 double Vector::angle() const
98 double m = magnitude();
102 double dp = dotP(*this, Vector(1.0, 0.0));
103 DEBUG->print("Vector::angle: dp/m: %f/%f", dp, m);
107 else if (dp / m < -1.0)
113 ret = 2 * M_PI - ret;
120 * @return The angle from this and the given coordinate (in rad).
122 double Vector::angleTo(const Vector & v) const
124 if (!valid || !v.valid)
127 return (v - (*this)).angle();
131 * @return Magnitude (length) of the vector.
133 double Vector::magnitude() const
136 // Note that the z coordinate is also needed for 2d
137 // (due to definition of crossP())
144 ret = sqrt(Math::pow(x, 2) + Math::pow(y, 2) + Math::pow(z, 2));
153 Vector Vector::lerp(const Vector& v, double t) const
155 return Vector(x + (v.x - x) * t, y + (v.y - y) * t);
159 * @return The distance between this and the given coordinate.
161 double Vector::distanceTo(const Vector & v) const
163 if (!valid || !v.valid)
169 return (*this - v).magnitude();
174 * @return true is this vector is within the given range.
176 bool Vector::isInWindow(const Vector & firstCorner, const Vector & secondCorner)
178 double minX = std::min(firstCorner.x, secondCorner.x);
179 double maxX = std::max(firstCorner.x, secondCorner.x);
180 double minY = std::min(firstCorner.y, secondCorner.y);
181 double maxY = std::max(firstCorner.y, secondCorner.y);
183 return (x >= minX && x <= maxX && y >= minY && y <= maxY);
187 * Moves this vector by the given offset. Equal to the operator +=.
189 Vector Vector::move(Vector offset)
196 * Rotates this vector around 0/0 by the given angle.
198 Vector Vector::rotate(double ang)
200 DEBUG->print("Vector::rotate: angle: %f", ang);
202 double r = magnitude();
204 DEBUG->print("Vector::rotate: r: %f", r);
206 double a = angle() + ang;
208 DEBUG->print("Vector::rotate: a: %f", a);
213 DEBUG->print("Vector::rotate: x/y: %f/%f", x, y);
219 * Rotates this vector around the given center by the given angle.
221 Vector Vector::rotate(Vector center, double ang)
223 *this = center + (*this - center).rotate(ang);
228 * Scales this vector by the given factors with 0/0 as center.
230 Vector Vector::scale(Vector factor)
238 * Scales this vector by the given factors with the given center.
240 Vector Vector::scale(Vector center, Vector factor)
242 *this = center + (*this - center).scale(factor);
247 * Mirrors this vector at the given axis.
249 Vector Vector::mirror(Vector axisPoint1, Vector axisPoint2)
252 ConstructionLine axis(NULL,
253 ConstructionLineData(axisPoint1, axisPoint2));
255 Vector xp = axis.getNearestPointOnEntity(*this);
260 double phi1 = axisPoint1.angleTo(*this);
261 double phi2 = axisPoint1.angleTo(axisPoint2) - phi1;
262 double r1 = axisPoint1.distanceTo(*this);
263 double r2 = axisPoint2.distanceTo(*this);
265 if (r1 < 1.0e-6 || r2 < 1.0e-6)
267 // point touches one axis point
271 setPolar(r1, phi1 + 2 * phi2);
272 (*this) += axisPoint1;
279 * Streams the vector components to stdout. e.g.: "1/4/0"
281 std::ostream & operator<<(std::ostream & os, const Vector & v)
284 os << v.x << "/" << v.y << "/" << v.z;
286 os << "invalid vector";
294 Vector Vector::operator+(const Vector & v) const
296 return Vector(x + v.x, y + v.y, z + v.z);
302 Vector Vector::operator-(const Vector & v) const
304 return Vector(x - v.x, y - v.y, z - v.z);
310 Vector Vector::operator*(double s) const
312 return Vector(x * s, y * s, z * s);
318 Vector Vector::operator/(double s) const
320 return Vector(x / s, y / s, z / s);
326 Vector Vector::operator-() const
328 return Vector(-x, -y, -z);
332 * Scalarproduct (dot product).
334 double Vector::dotP(const Vector & v1, const Vector & v2)
336 return (v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z);
340 * += operator. Assert: both vectors must be valid.
342 void Vector::operator+=(const Vector & v)
352 void Vector::operator-=(const Vector & v)
362 void Vector::operator*=(double s)
372 bool Vector::operator==(const Vector & v) const
374 return (x == v.x && y == v.y && z == v.z && valid == v.valid);
377 bool Vector::operator!=(const Vector & v) const
379 return !operator==(v);
383 * @return A vector with the minimum components from the vectors v1 and v2.
384 * These might be mixed components from both vectors.
386 Vector Vector::minimum (const Vector& v1, const Vector& v2)
388 return Vector (std::min(v1.x, v2.x), std::min(v1.y, v2.y), std::min(v1.z, v2.z));
392 * @return A vector with the maximum values from the vectors v1 and v2
394 Vector Vector::maximum (const Vector& v1, const Vector& v2)
396 return Vector (std::max(v1.x, v2.x), std::max(v1.y, v2.y), std::max(v1.z, v2.z));
400 * @return Cross product of two vectors.
402 Vector Vector::crossP(const Vector & v1, const Vector & v2)
404 return Vector(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x);