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 // (C) 2010 Underground Software
8 // JLH = James L. Hammons <jlhamm@acm.org>
11 // --- ---------- -----------------------------------------------------------
12 // JLH 05/21/2010 Added this text. :-)
21 * Constructor for a point with default coordinates.
25 //RS_DEBUG->print("Vector::Vector");
30 * Constructor for a point with given coordinates.
32 Vector::Vector(double vx, double vy, double vz)
34 //RS_DEBUG->print("Vector::Vector");
39 * Constructor for a point with given coordinates in an array
42 //Vector::Vector(double v[]) {
43 // set(v[0], v[1], v[2]);
47 * Constructor for a point with given valid flag.
49 * @param valid true: a valid vector with default coordinates is created.
50 * false: an invalid vector is created
52 Vector::Vector(bool valid)
54 //RS_DEBUG->print("Vector::Vector");
64 //RS_DEBUG->print("Vector::~Vector");
68 * Sets a new position for the vector.
70 void Vector::set(double vx, double vy, double vz)
79 * Sets a new position for the vector in polar coordinates.
81 void Vector::setPolar(double radius, double angle)
83 x = radius * cos(angle);
84 y = radius * sin(angle);
90 * @return The angle from zero to this vector (in rad).
92 double Vector::angle() const
95 double m = magnitude();
99 double dp = dotP(*this, Vector(1.0, 0.0));
100 RS_DEBUG->print("Vector::angle: dp/m: %f/%f", dp, m);
104 else if (dp / m < -1.0)
110 ret = 2 * M_PI - ret;
117 * @return The angle from this and the given coordinate (in rad).
119 double Vector::angleTo(const Vector & v) const
121 if (!valid || !v.valid)
124 return (v - (*this)).angle();
128 * @return Magnitude (length) of the vector.
130 double Vector::magnitude() const
133 // Note that the z coordinate is also needed for 2d
134 // (due to definition of crossP())
141 ret = sqrt(RS_Math::pow(x, 2) + RS_Math::pow(y, 2) + RS_Math::pow(z, 2));
150 Vector Vector::lerp(const Vector& v, double t) const
152 return Vector(x + (v.x - x) * t, y + (v.y - y) * t);
156 * @return The distance between this and the given coordinate.
158 double Vector::distanceTo(const Vector & v) const
160 if (!valid || !v.valid)
166 return (*this - v).magnitude();
171 * @return true is this vector is within the given range.
173 bool Vector::isInWindow(const Vector & firstCorner, const Vector & secondCorner)
175 double minX = std::min(firstCorner.x, secondCorner.x);
176 double maxX = std::max(firstCorner.x, secondCorner.x);
177 double minY = std::min(firstCorner.y, secondCorner.y);
178 double maxY = std::max(firstCorner.y, secondCorner.y);
180 return (x >= minX && x <= maxX && y >= minY && y <= maxY);
184 * Moves this vector by the given offset. Equal to the operator +=.
186 Vector Vector::move(Vector offset)
193 * Rotates this vector around 0/0 by the given angle.
195 Vector Vector::rotate(double ang)
197 RS_DEBUG->print("Vector::rotate: angle: %f", ang);
199 double r = magnitude();
201 RS_DEBUG->print("Vector::rotate: r: %f", r);
203 double a = angle() + ang;
205 RS_DEBUG->print("Vector::rotate: a: %f", a);
210 RS_DEBUG->print("Vector::rotate: x/y: %f/%f", x, y);
216 * Rotates this vector around the given center by the given angle.
218 Vector Vector::rotate(Vector center, double ang)
220 *this = center + (*this - center).rotate(ang);
225 * Scales this vector by the given factors with 0/0 as center.
227 Vector Vector::scale(Vector factor)
235 * Scales this vector by the given factors with the given center.
237 Vector Vector::scale(Vector center, Vector factor)
239 *this = center + (*this - center).scale(factor);
244 * Mirrors this vector at the given axis.
246 Vector Vector::mirror(Vector axisPoint1, Vector axisPoint2)
249 RS_ConstructionLine axis(NULL,
250 RS_ConstructionLineData(axisPoint1, axisPoint2));
252 Vector xp = axis.getNearestPointOnEntity(*this);
257 double phi1 = axisPoint1.angleTo(*this);
258 double phi2 = axisPoint1.angleTo(axisPoint2) - phi1;
259 double r1 = axisPoint1.distanceTo(*this);
260 double r2 = axisPoint2.distanceTo(*this);
262 if (r1 < 1.0e-6 || r2 < 1.0e-6)
264 // point touches one axis point
268 setPolar(r1, phi1 + 2 * phi2);
269 (*this) += axisPoint1;
276 * Streams the vector components to stdout. e.g.: "1/4/0"
278 std::ostream & operator<<(std::ostream & os, const Vector & v)
281 os << v.x << "/" << v.y << "/" << v.z;
283 os << "invalid vector";
291 Vector Vector::operator+(const Vector & v) const
293 return Vector(x + v.x, y + v.y, z + v.z);
299 Vector Vector::operator-(const Vector & v) const
301 return Vector(x - v.x, y - v.y, z - v.z);
307 Vector Vector::operator*(double s) const
309 return Vector(x * s, y * s, z * s);
315 Vector Vector::operator/(double s) const
317 return Vector(x / s, y / s, z / s);
323 Vector Vector::operator-() const
325 return Vector(-x, -y, -z);
329 * Scalarproduct (dot product).
331 double Vector::dotP(const Vector & v1, const Vector & v2)
333 return (v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z);
337 * += operator. Assert: both vectors must be valid.
339 void Vector::operator+=(const Vector & v)
349 void Vector::operator-=(const Vector & v)
359 void Vector::operator*=(double s)
369 bool Vector::operator==(const Vector & v) const
371 return (x == v.x && y == v.y && z == v.z && valid == v.valid);
374 bool Vector::operator!=(const Vector & v) const
376 return !operator==(v);
380 * @return A vector with the minimum components from the vectors v1 and v2.
381 * These might be mixed components from both vectors.
383 Vector Vector::minimum (const Vector& v1, const Vector& v2)
385 return Vector (std::min(v1.x, v2.x), std::min(v1.y, v2.y), std::min(v1.z, v2.z));
389 * @return A vector with the maximum values from the vectors v1 and v2
391 Vector Vector::maximum (const Vector& v1, const Vector& v2)
393 return Vector (std::max(v1.x, v2.x), std::max(v1.y, v2.y), std::max(v1.z, v2.z));
397 * @return Cross product of two vectors.
399 Vector Vector::crossP(const Vector & v1, const Vector & v2)
401 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);