📄 rs_vector.cpp
字号:
/****************************************************************************** $Id: rs_vector.cpp 2378 2005-05-16 17:05:15Z andrew $**** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.**** This file is part of the qcadlib Library project.**** This file may be distributed and/or modified under the terms of the** GNU General Public License version 2 as published by the Free Software** Foundation and appearing in the file LICENSE.GPL included in the** packaging of this file.**** Licensees holding valid qcadlib Professional Edition licenses may use ** this file in accordance with the qcadlib Commercial License** Agreement provided with the Software.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.**** See http://www.ribbonsoft.com for further details.**** Contact info@ribbonsoft.com if any conditions of this licensing are** not clear to you.************************************************************************/#include "rs_vector.h"//#include <values.h>#include "rs_debug.h"#include "rs_math.h"#include "rs_constructionline.h"/** * Constructor for a point with default coordinates. */RS_Vector::RS_Vector() { //RS_DEBUG->print("RS_Vector::RS_Vector"); set(0.0, 0.0, 0.0);}/** * Constructor for a point with given coordinates. */RS_Vector::RS_Vector(double vx, double vy, double vz) { //RS_DEBUG->print("RS_Vector::RS_Vector"); set(vx, vy, vz);}/** * Constructor for a point with given coordinates in an array * or three doubles. *///RS_Vector::RS_Vector(double v[]) {// set(v[0], v[1], v[2]);//}/** * Constructor for a point with given valid flag. * * @param valid true: a valid vector with default coordinates is created. * false: an invalid vector is created */RS_Vector::RS_Vector(bool valid) { //RS_DEBUG->print("RS_Vector::RS_Vector"); set(0.0, 0.0, 0.0); this->valid = valid;}/** * Destructor. */RS_Vector::~RS_Vector() { //RS_DEBUG->print("RS_Vector::~RS_Vector");}/** * Sets a new position for the vector. */void RS_Vector::set(double vx, double vy, double vz) { x = vx; y = vy; z = vz; valid = true;}/** * Sets a new position for the vector in polar coordinates. */void RS_Vector::setPolar(double radius, double angle) { x = radius * cos(angle); y = radius * sin(angle); z = 0.0; valid = true;}/** * @return The angle from zero to this vector (in rad). */double RS_Vector::angle() const { double ret = 0.0; double m = magnitude(); if (m>1.0e-6) { double dp = dotP(*this, RS_Vector(1.0, 0.0)); RS_DEBUG->print("RS_Vector::angle: dp/m: %f/%f", dp, m); if (dp/m>=1.0) { ret = 0.0; } else if (dp/m<-1.0) { ret = M_PI; } else { ret = acos( dp / m); } if (y<0.0) { ret = 2*M_PI - ret; } } return ret;}/** * @return The angle from this and the given coordinate (in rad). */double RS_Vector::angleTo(const RS_Vector& v) const { if (!valid || !v.valid) { return 0.0; } else { return (v-(*this)).angle(); }}/** * @return Magnitude (length) of the vector. */double RS_Vector::magnitude() const { double ret = 0.0; // Note that the z coordinate is also needed for 2d // (due to definition of crossP()) if (!valid) { ret = 0.0; } else { ret = sqrt(RS_Math::pow(x,2) + RS_Math::pow(y,2) + RS_Math::pow(z,2)); } return ret;}/** * */RS_Vector RS_Vector::lerp(const RS_Vector& v, double t) const { return RS_Vector(x+(v.x-x)*t, y+(v.y-y)*t);}/** * @return The distance between this and the given coordinate. */double RS_Vector::distanceTo(const RS_Vector& v) const { if (!valid || !v.valid) { return RS_MAXDOUBLE; } else { return (*this-v).magnitude(); }}/** * @return true is this vector is within the given range. */bool RS_Vector::isInWindow(const RS_Vector& firstCorner, const RS_Vector& secondCorner) { double minX = std::min(firstCorner.x, secondCorner.x); double maxX = std::max(firstCorner.x, secondCorner.x); double minY = std::min(firstCorner.y, secondCorner.y); double maxY = std::max(firstCorner.y, secondCorner.y); return (x>=minX && x<=maxX && y>=minY && y<=maxY);}/** * Moves this vector by the given offset. Equal to the operator +=. */RS_Vector RS_Vector::move(RS_Vector offset) { *this+=offset; return *this;}/** * Rotates this vector around 0/0 by the given angle. */RS_Vector RS_Vector::rotate(double ang) { RS_DEBUG->print("RS_Vector::rotate: angle: %f", ang); double r = magnitude(); RS_DEBUG->print("RS_Vector::rotate: r: %f", r); double a = angle() + ang; RS_DEBUG->print("RS_Vector::rotate: a: %f", a); x = cos(a) * r; y = sin(a) * r; RS_DEBUG->print("RS_Vector::rotate: x/y: %f/%f", x, y); return *this;}/** * Rotates this vector around the given center by the given angle. */RS_Vector RS_Vector::rotate(RS_Vector center, double ang) { *this = center + (*this-center).rotate(ang); return *this;}/** * Scales this vector by the given factors with 0/0 as center. */RS_Vector RS_Vector::scale(RS_Vector factor) { x *= factor.x; y *= factor.y; return *this;}/** * Scales this vector by the given factors with the given center. */RS_Vector RS_Vector::scale(RS_Vector center, RS_Vector factor) { *this = center + (*this-center).scale(factor); return *this;}/** * Mirrors this vector at the given axis. */RS_Vector RS_Vector::mirror(RS_Vector axisPoint1, RS_Vector axisPoint2) { /* RS_ConstructionLine axis(NULL, RS_ConstructionLineData(axisPoint1, axisPoint2)); RS_Vector xp = axis.getNearestPointOnEntity(*this); xp = xp - (*this); (*this) += (xp*2); */ double phi1 = axisPoint1.angleTo(*this); double phi2 = axisPoint1.angleTo(axisPoint2) - phi1; double r1 = axisPoint1.distanceTo(*this); double r2 = axisPoint2.distanceTo(*this); if (r1<1.0e-6 || r2<1.0e-6) { // point touches one axis point } else { setPolar(r1, phi1 + 2*phi2); (*this) += axisPoint1; } return *this;}/** * Streams the vector components to stdout. e.g.: "1/4/0" */std::ostream& operator << (std::ostream& os, const RS_Vector& v) { if(v.valid) { os << v.x << "/" << v.y << "/" << v.z; } else { os << "invalid vector"; } return os;}/** * binary + operator. */RS_Vector RS_Vector::operator + (const RS_Vector& v) const { return RS_Vector(x + v.x, y + v.y, z + v.z);}/** * binary - operator. */RS_Vector RS_Vector::operator - (const RS_Vector& v) const { return RS_Vector(x - v.x, y - v.y, z - v.z);}/** * binary * operator. */RS_Vector RS_Vector::operator * (double s) const { return RS_Vector(x * s, y * s, z * s);}/** * binary / operator. */RS_Vector RS_Vector::operator / (double s) const { return RS_Vector(x / s, y / s, z / s);}/** * unary - operator. */RS_Vector RS_Vector::operator - () const { return RS_Vector(-x, -y, -z);}/** * Scalarproduct (dot product). */double RS_Vector::dotP(const RS_Vector& v1, const RS_Vector& v2) { return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;}/** * += operator. Assert: both vectors must be valid. */void RS_Vector::operator += (const RS_Vector& v) { x += v.x; y += v.y; z += v.z;}/** * -= operator */void RS_Vector::operator -= (const RS_Vector& v) { x -= v.x; y -= v.y; z -= v.z;}/** * *= operator */void RS_Vector::operator *= (double s) { x *= s; y *= s; z *= s;}/** * == operator */bool RS_Vector::operator == (const RS_Vector& v) const { return (x==v.x && y==v.y && z==v.z && valid==v.valid);}/** * @return A vector with the minimum components from the vectors v1 and v2. * These might be mixed components from both vectors. */RS_Vector RS_Vector::minimum (const RS_Vector& v1, const RS_Vector& v2) { return RS_Vector (std::min(v1.x, v2.x), std::min(v1.y, v2.y), std::min(v1.z, v2.z));}/** * @return A vector with the maximum values from the vectors v1 and v2 */RS_Vector RS_Vector::maximum (const RS_Vector& v1, const RS_Vector& v2) { return RS_Vector (std::max(v1.x, v2.x), std::max(v1.y, v2.y), std::max(v1.z, v2.z));}/** * @return Cross product of two vectors. */RS_Vector RS_Vector::crossP(const RS_Vector& v1, const RS_Vector& v2) { return RS_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);}/** * Constructor for no solution. */RS_VectorSolutions::RS_VectorSolutions() : vector(NULL) { clean();}/** * Copy constructor */RS_VectorSolutions::RS_VectorSolutions(const RS_VectorSolutions& s) : vector(NULL) { alloc(s.getNumber()); setTangent(s.isTangent()); for (int i=0; i<s.getNumber(); ++i) { set(i, s.get(i)); }}/** * Constructor for num solutions. */RS_VectorSolutions::RS_VectorSolutions(int num) : vector(NULL) { alloc(num);}/** * Constructor for one solution. */RS_VectorSolutions::RS_VectorSolutions(const RS_Vector& v1) { num = 1; vector = new RS_Vector[num]; vector[0] = v1; tangent = false;}/** * Constructor for two solutions. */RS_VectorSolutions::RS_VectorSolutions(const RS_Vector& v1, const RS_Vector& v2) { num = 2; vector = new RS_Vector[num]; vector[0] = v1; vector[1] = v2; tangent = false;}/** * Constructor for three solutions. */RS_VectorSolutions::RS_VectorSolutions(const RS_Vector& v1, const RS_Vector& v2, const RS_Vector& v3) { num = 3; vector = new RS_Vector[num]; vector[0] = v1; vector[1] = v2; vector[2] = v3; tangent = false;}/** * Constructor for four solutions. */RS_VectorSolutions::RS_VectorSolutions(const RS_Vector& v1, const RS_Vector& v2, const RS_Vector& v3, const RS_Vector& v4) { num = 4; vector = new RS_Vector[num]; vector[0] = v1; vector[1] = v2; vector[2] = v3; vector[3] = v4; tangent = false;}/** * Constructor for four solutions. */RS_VectorSolutions::RS_VectorSolutions(const RS_Vector& v1, const RS_Vector& v2, const RS_Vector& v3, const RS_Vector& v4, const RS_Vector& v5) { num = 5; vector = new RS_Vector[num]; vector[0] = v1; vector[1] = v2; vector[2] = v3; vector[3] = v4; vector[4] = v5; tangent = false;}/** * Destructor. */RS_VectorSolutions::~RS_VectorSolutions() { clean();}/** * Allocates 'num' vectors. */void RS_VectorSolutions::alloc(int num) { clean(); this->num = num; vector = new RS_Vector[num]; for (int i=0; i<num; ++i) { vector[i] = RS_Vector(false); } tangent = false;}/** * Deletes vector array and resets everything. */void RS_VectorSolutions::clean() { if (vector!=NULL) { delete[] vector; } vector = NULL; num = 0; tangent = false;}/** * @return vector solution number i or an invalid vector if there * are less solutions. */RS_Vector RS_VectorSolutions::get(int i) const { if (i<num) { return vector[i]; } else { return RS_Vector(false); }}/** * @return Number of solutions available. */int RS_VectorSolutions::getNumber() const { return num;}/** * @retval true There's at least one valid solution. * @retval false There's no valid solution. */bool RS_VectorSolutions::hasValid() const { for (int i=0; i<num; i++) { if (vector[i].valid) { return true; } } return false;}/** * Sets the solution i to the given vector. * If i is greater than the current number of solutions available, * nothing happens. */void RS_VectorSolutions::set(int i, const RS_Vector& v) { if (i<num) { vector[i] = v; }}/** * Sets the tangent flag. */void RS_VectorSolutions::setTangent(bool t) { tangent = t;}/** * @return true if at least one of the solutions is a double solution * (tangent). */bool RS_VectorSolutions::isTangent() const { return tangent;}/** * Rotates all vectors around the given center by the given angle. */void RS_VectorSolutions::rotate(RS_Vector center, double ang) { for (int i=0; i<num; i++) { if (vector[i].valid) { vector[i].rotate(center, ang); } }}/** * Scales all vectors by the given factors with the given center. */void RS_VectorSolutions::scale(RS_Vector center, RS_Vector factor) { for (int i=0; i<num; i++) { if (vector[i].valid) { vector[i].scale(center, factor); } }}/** * @return vector solution which is the closest to the given coordinate. * dist will contain the distance if it doesn't point to NULL (default). */RS_Vector RS_VectorSolutions::getClosest(const RS_Vector& coord, double* dist, int* index) const { double curDist; double minDist = RS_MAXDOUBLE; RS_Vector closestPoint(false); for (int i=0; i<num; i++) { if (vector[i].valid) { curDist = coord.distanceTo(vector[i]); if (curDist<minDist) { closestPoint = vector[i]; minDist = curDist; if (dist!=NULL) { *dist = curDist; } if (index!=NULL) { *index = i; } } } } return closestPoint;}RS_VectorSolutions RS_VectorSolutions::operator = (const RS_VectorSolutions& s) { alloc(s.getNumber()); setTangent(s.isTangent()); for (int i=0; i<s.getNumber(); ++i) { set(i, s.get(i)); } return *this;}std::ostream& operator << (std::ostream& os, const RS_VectorSolutions& s) { for (int i=0; i<s.num; ++i) { os << "(" << s.get(i) << ")\n"; } os << " tangent: " << (int)s.isTangent() << "\n"; return os;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -