/**************************************************************************** ** ** This file is part of the LibreCAD project, a 2D CAD program ** ** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl) ** Copyright (C) 2001-2003 RibbonSoft. All rights reserved. ** ** ** 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 gpl-2.0.txt included in the ** packaging of this file. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ** ** This copyright notice MUST APPEAR in all copies of the script! ** **********************************************************************/ #include "rs_vector.h" //#include #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"); #ifdef RS_VECTOR2D set(0.0, 0.0); #else set(0.0, 0.0, 0.0); #endif } /** * Constructor for a point with given coordinates. */ #ifdef RS_VECTOR2D RS_Vector::RS_Vector(double vx, double vy) { //RS_DEBUG->print("RS_Vector::RS_Vector"); set(vx, vy); } #else RS_Vector::RS_Vector(double vx, double vy, double vz) { //RS_DEBUG->print("RS_Vector::RS_Vector"); set(vx, vy, vz); } #endif /** * Constructor for a unit vector with given angle */ RS_Vector::RS_Vector(double angle) { //RS_DEBUG->print("RS_Vector::RS_Vector"); x = cos(angle); y = sin(angle); #ifndef RS_VECTOR2D z = 0.0; #endif valid = true; } /** * 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"); #ifdef RS_VECTOR2D set(0.0, 0.0); #else set(0.0, 0.0, 0.0); #endif this->valid = valid; } /** * Destructor. */ RS_Vector::~RS_Vector() { //RS_DEBUG->print("RS_Vector::~RS_Vector"); } /** * Sets to a unit vector by the direction angle */ void RS_Vector::set(double angle) { x = cos(angle); y = sin(angle); #ifndef RS_VECTOR2D z = 0.; #endif valid = true; } /** * Sets a new position for the vector. */ #ifdef RS_VECTOR2D void RS_Vector::set(double vx, double vy) { #else void RS_Vector::set(double vx, double vy, double vz) { #endif x = vx; y = vy; #ifndef RS_VECTOR2D z = vz; #endif 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); #ifndef RS_VECTOR2D z = 0.0; #endif valid = true; } /** * @return The angle from zero to this vector (in rad). */ double RS_Vector::angle() const { return RS_Math::correctAngle(atan2(y,x)); // 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; // } // } // //std::cout<<"New angle="<=vLow.x && x<=vHigh.x && y>=vLow.y && y<=vHigh.y); } /** * move to the closest integer point */ RS_Vector RS_Vector::toInteger() { x= x - remainder(x,1.); y= y - remainder(y,1.); return *this; } /** * Moves this vector by the given offset. Equal to the operator +=. */ RS_Vector RS_Vector::move(const RS_Vector& offset) { *this+=offset; return *this; } /** * Rotates this vector around 0/0 by the given angle. */ RS_Vector RS_Vector::rotate(const 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); // rotate by direction vector rotate(RS_Vector(ang)); return *this; } /** * Rotates this vector around 0/0 by the given vector * if the vector is a unit, then, it's the same as rotating around * 0/0 by the angle of the vector */ RS_Vector RS_Vector::rotate(const RS_Vector& angleVector) { // RS_DEBUG->print("RS_Vector::rotate: rotating Vecotr: %g/%g", x,y); // RS_DEBUG->print("RS_Vector::rotate: rotating by Vecotr: %g/%g", angleVector.x,angleVector.y); double x0 = x * angleVector.x - y * angleVector.y; y = x * angleVector.y + y * angleVector.x; x = x0; // RS_DEBUG->print("RS_Vector::rotate: rotated x/y: %f/%f", x, y); return *this; } /** * Rotates this vector around the given center by the given angle. */ RS_Vector RS_Vector::rotate(const RS_Vector& center, const double& ang) { *this = center + (*this-center).rotate(ang); return *this; } RS_Vector RS_Vector::rotate(const RS_Vector& center, const RS_Vector& angleVector) { *this = center + (*this-center).rotate(angleVector); return *this; } /** * Scales this vector by the given factors with 0/0 as center. */ RS_Vector RS_Vector::scale(const double& factor) { x *= factor; y *= factor; return *this; } /** * Scales this vector by the given factors with 0/0 as center. */ RS_Vector RS_Vector::scale(const 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(const RS_Vector& center, const RS_Vector& factor) { *this = center + (*this-center).scale(factor); return *this; } /** * Mirrors this vector at the given axis, defined by two points on axis. */ RS_Vector RS_Vector::mirror(const RS_Vector& axisPoint1, const RS_Vector& axisPoint2) { /* RS_ConstructionLine axis(NULL, RS_ConstructionLineData(axisPoint1, axisPoint2)); RS_Vector xp = axis.getNearestPointOnEntity(*this); xp = xp - (*this); (*this) += (xp*2); */ RS_Vector direction(axisPoint2-axisPoint1); double a= direction.squared(); RS_Vector ret(false); if(aRS_TOLERANCE) { x /= s; y /= s; #ifndef RS_VECTOR2D z /= s; #endif } } /** * == operator */ bool RS_Vector::operator == (const RS_Vector& v) const { #ifdef RS_VECTOR2D return (x==v.x && y==v.y && valid==v.valid); #else return (x==v.x && y==v.y && z==v.z && valid==v.valid); #endif } /** * @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) #ifndef RS_VECTOR2D , std::min(v1.z, v2.z) #endif ); } /** * @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) #ifndef RS_VECTOR2D , std::max(v1.z, v2.z) #endif ); } /** * @return Cross product of two vectors. * we don't need cross product for 2D vectors */ #ifndef RS_VECTOR2D 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); } #endif /** * Constructor for no solution. */ RS_VectorSolutions::RS_VectorSolutions() { vector.clear(); tangent=false; } /** * Copy constructor */ RS_VectorSolutions::RS_VectorSolutions(const RS_VectorSolutions& s) { setTangent(s.isTangent()); vector=s.vector; } /** * Constructor for num solutions. */ RS_VectorSolutions::RS_VectorSolutions(int num) { #if QT_VERSION >= 0x040700 vector.reserve(num); #else for(int i=vector.size();i= 0x040700 vector.reserve(num); #else if(vector.size() num) { vector.erase(vector.begin()+num, vector.end()); } // tangent = false; } /** * Deletes vector array and resets everything. */ void RS_VectorSolutions::clean() { vector.clear(); 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 RS_VectorSolutions::getList() const { return vector; } void RS_VectorSolutions::push_back(const RS_Vector& v) { vector.push_back(v); } RS_VectorSolutions RS_VectorSolutions::appendTo(const RS_VectorSolutions& v) { vector += v.getList(); return *this; } /** * 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 (iprint(RS_Debug::D_ERROR, "set member in vector in RS_VectorSolutions: out of range, %d to size of %d", i,vector.size()); for(int j=vector.size();j<=i;j++) vector.push_back(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 (0,0) by the given angle. */ void RS_VectorSolutions::rotate(const double& ang) { RS_Vector angleVector(ang); for (int i=0; i=0) i=counts; for(int j=0; j