⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rs_vector.cpp

📁 qcad2.05可用于windows和linux的源码
💻 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 + -