1
/****************************************************************************
3
** This file is part of the LibreCAD project, a 2D CAD program
5
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
6
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
9
** This file may be distributed and/or modified under the terms of the
10
** GNU General Public License version 2 as published by the Free Software
11
** Foundation and appearing in the file gpl-2.0.txt included in the
12
** packaging of this file.
14
** This program is distributed in the hope that it will be useful,
15
** but WITHOUT ANY WARRANTY; without even the implied warranty of
16
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
** GNU General Public License for more details.
19
** You should have received a copy of the GNU General Public License
20
** along with this program; if not, write to the Free Software
21
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23
** This copyright notice MUST APPEAR in all copies of the script!
25
**********************************************************************/
28
#include "rs_vector.h"
34
#include "rs_constructionline.h"
37
#include "emu_c99.h" /* remainder() */
41
* Constructor for a point with default coordinates.
43
RS_Vector::RS_Vector() {
44
//RS_DEBUG->print("RS_Vector::RS_Vector");
56
* Constructor for a point with given coordinates.
59
RS_Vector::RS_Vector(double vx, double vy) {
60
//RS_DEBUG->print("RS_Vector::RS_Vector");
64
RS_Vector::RS_Vector(double vx, double vy, double vz) {
65
//RS_DEBUG->print("RS_Vector::RS_Vector");
71
* Constructor for a unit vector with given angle
73
RS_Vector::RS_Vector(double angle) {
74
//RS_DEBUG->print("RS_Vector::RS_Vector");
85
* Constructor for a point with given coordinates in an array
88
//RS_Vector::RS_Vector(double v[]) {
89
// set(v[0], v[1], v[2]);
94
* Constructor for a point with given valid flag.
96
* @param valid true: a valid vector with default coordinates is created.
97
* false: an invalid vector is created
99
RS_Vector::RS_Vector(bool valid) {
100
//RS_DEBUG->print("RS_Vector::RS_Vector");
113
RS_Vector::~RS_Vector() {
114
//RS_DEBUG->print("RS_Vector::~RS_Vector");
119
* Sets to a unit vector by the direction angle
121
void RS_Vector::set(double angle) {
132
* Sets a new position for the vector.
135
void RS_Vector::set(double vx, double vy) {
137
void RS_Vector::set(double vx, double vy, double vz) {
149
* Sets a new position for the vector in polar coordinates.
151
void RS_Vector::setPolar(double radius, double angle) {
152
x = radius * cos(angle);
153
y = radius * sin(angle);
163
* @return The angle from zero to this vector (in rad).
165
double RS_Vector::angle() const {
166
return RS_Math::correctAngle(atan2(y,x));
168
// double m = magnitude();
171
// double dp = dotP(*this, RS_Vector(1.0, 0.0));
172
// RS_DEBUG->print("RS_Vector::angle: dp/m: %f/%f", dp, m);
176
// else if (dp/m<-1.0) {
180
// ret = acos( dp / m);
183
// ret = 2*M_PI - ret;
186
// //std::cout<<"New angle="<<fmod(2*M_PI+atan2(y,x),2*M_PI)<<"\tatan2("<<y<<','<<x<<")"<<atan2(y,x)<<std::endl;
194
* @return The angle from this and the given coordinate (in rad).
196
double RS_Vector::angleTo(const RS_Vector& v) const {
197
if (!valid || !v.valid) {
201
return (v-(*this)).angle();
206
* @return The angle from between two vectors using the current vector as the center
207
* return 0, if the angle is not well defined
209
double RS_Vector::angleBetween(const RS_Vector& v1, const RS_Vector& v2) const {
210
if (!valid || !v1.valid || !v2.valid) {
214
RS_Vector vStart(v1- (*this));
215
RS_Vector vEnd(v2- (*this));
216
// if( vStart.magnitude() < RS_TOLERANCE
217
// || vEnd.magnitude() < RS_TOLERANCE) return 0.0;
218
return RS_Math::correctAngle( atan2( vStart.x*vEnd.y-vStart.y*vEnd.x, vStart.x*vEnd.x+vStart.y*vEnd.y));
220
// std::cout<<"old algorithm:: "<<RS_Math::correctAngle(vEnd.angle() - vStart.angle())<<std::endl;
221
// return RS_Math::correctAngle(vEnd.angle() - vStart.angle());
227
* @return Magnitude (length) of the vector.
229
double RS_Vector::magnitude() const {
231
// Note that the z coordinate is also needed for 2d
232
// (due to definition of crossP())
235
ret = sqrt(x*x + y*y);
237
ret = sqrt(x*x + y*y + z*z);
245
* @return square of vector length
247
double RS_Vector::squared() const {
248
// Note that the z coordinate is also needed for 2d
249
// (due to definition of crossP())
254
return x*x + y*y + z*z;
261
* @return square of vector length
263
double RS_Vector::squaredTo(const RS_Vector& v1) const
265
if (valid && v1.valid) {
266
return (*this - v1).squared();
274
RS_Vector RS_Vector::lerp(const RS_Vector& v, double t) const {
275
return RS_Vector(x+(v.x-x)*t, y+(v.y-y)*t);
280
* @return The distance between this and the given coordinate.
282
double RS_Vector::distanceTo(const RS_Vector& v) const {
283
if (!valid || !v.valid) {
287
return (*this-v).magnitude();
294
* @return true is this vector is within the given range.
296
bool RS_Vector::isInWindow(const RS_Vector& firstCorner,
297
const RS_Vector& secondCorner) const {
298
RS_Vector vLow( std::min(firstCorner.x, secondCorner.x), std::min(firstCorner.y, secondCorner.y));
299
RS_Vector vHigh( std::max(firstCorner.x, secondCorner.x), std::max(firstCorner.y, secondCorner.y));
301
if(valid==false) return false;
302
return isInWindowOrdered(vLow,vHigh);
306
* @return true is this vector is within the given range
309
bool RS_Vector::isInWindowOrdered(const RS_Vector& vLow,
310
const RS_Vector& vHigh) const {
311
if(valid==false) return false;
312
return (x>=vLow.x && x<=vHigh.x && y>=vLow.y && y<=vHigh.y);
316
* move to the closest integer point
318
RS_Vector RS_Vector::toInteger() {
319
x= x - remainder(x,1.);
320
y= y - remainder(y,1.);
325
* Moves this vector by the given offset. Equal to the operator +=.
327
RS_Vector RS_Vector::move(const RS_Vector& offset) {
335
* Rotates this vector around 0/0 by the given angle.
337
RS_Vector RS_Vector::rotate(const double& ang) {
338
// RS_DEBUG->print("RS_Vector::rotate: angle: %f", ang);
340
// double r = magnitude();
342
// RS_DEBUG->print("RS_Vector::rotate: r: %f", r);
344
// double a = angle() + ang;
346
// RS_DEBUG->print("RS_Vector::rotate: a: %f", a);
351
// RS_DEBUG->print("RS_Vector::rotate: x/y: %f/%f", x, y);
352
// rotate by direction vector
353
rotate(RS_Vector(ang));
358
* Rotates this vector around 0/0 by the given vector
359
* if the vector is a unit, then, it's the same as rotating around
360
* 0/0 by the angle of the vector
362
RS_Vector RS_Vector::rotate(const RS_Vector& angleVector) {
363
// RS_DEBUG->print("RS_Vector::rotate: rotating Vecotr: %g/%g", x,y);
364
// RS_DEBUG->print("RS_Vector::rotate: rotating by Vecotr: %g/%g", angleVector.x,angleVector.y);
365
double x0 = x * angleVector.x - y * angleVector.y;
366
y = x * angleVector.y + y * angleVector.x;
369
// RS_DEBUG->print("RS_Vector::rotate: rotated x/y: %f/%f", x, y);
376
* Rotates this vector around the given center by the given angle.
378
RS_Vector RS_Vector::rotate(const RS_Vector& center, const double& ang) {
379
*this = center + (*this-center).rotate(ang);
382
RS_Vector RS_Vector::rotate(const RS_Vector& center, const RS_Vector& angleVector) {
383
*this = center + (*this-center).rotate(angleVector);
388
* Scales this vector by the given factors with 0/0 as center.
390
RS_Vector RS_Vector::scale(const double& factor) {
397
* Scales this vector by the given factors with 0/0 as center.
399
RS_Vector RS_Vector::scale(const RS_Vector& factor) {
406
* Scales this vector by the given factors with the given center.
408
RS_Vector RS_Vector::scale(const RS_Vector& center, const RS_Vector& factor) {
409
*this = center + (*this-center).scale(factor);
416
* Mirrors this vector at the given axis, defined by two points on axis.
418
RS_Vector RS_Vector::mirror(const RS_Vector& axisPoint1, const RS_Vector& axisPoint2) {
420
RS_ConstructionLine axis(NULL,
421
RS_ConstructionLineData(axisPoint1, axisPoint2));
423
RS_Vector xp = axis.getNearestPointOnEntity(*this);
427
RS_Vector direction(axisPoint2-axisPoint1);
428
double a= direction.squared();
429
RS_Vector ret(false);
430
if(a<RS_TOLERANCE2) {
433
ret= axisPoint1 + direction* dotP(*this - axisPoint1,direction)/a; //projection point
434
*this = ret + ret - *this;
442
* Streams the vector components to stdout. e.g.: "1/4/0"
444
std::ostream& operator << (std::ostream& os, const RS_Vector& v) {
447
os << v.x << "/" << v.y ;
449
os << v.x << "/" << v.y << "/" << v.z;
452
os << "invalid vector";
462
RS_Vector RS_Vector::operator + (const RS_Vector& v) const {
464
return RS_Vector(x + v.x, y + v.y);
466
return RS_Vector(x + v.x, y + v.y, z + v.z);
475
RS_Vector RS_Vector::operator - (const RS_Vector& v) const {
477
return RS_Vector(x - v.x, y - v.y);
479
return RS_Vector(x - v.x, y - v.y, z - v.z);
487
RS_Vector RS_Vector::operator * (const double& s) const {
489
return RS_Vector(x * s, y * s);
491
return RS_Vector(x * s, y * s, z * s);
500
RS_Vector RS_Vector::operator / (const double& s) const {
502
return RS_Vector(x / s, y / s);
504
return RS_Vector(x / s, y / s, z / s);
513
RS_Vector RS_Vector::operator - () const {
515
return RS_Vector(-x, -y);
517
return RS_Vector(-x, -y, -z);
524
* Scalarproduct (dot product).
526
double RS_Vector::dotP(const RS_Vector& v1)
528
return x*v1.x+y*v1.y;
531
double RS_Vector::dotP(const RS_Vector& v1, const RS_Vector& v2) {
533
return v1.x * v2.x + v1.y * v2.y;
535
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
540
/** switch x,y for all vectors */
541
RS_Vector RS_Vector::flipXY(void) const{
542
return RS_Vector(y,x);
546
* += operator. Assert: both vectors must be valid.
548
void RS_Vector::operator += (const RS_Vector& v) {
560
void RS_Vector::operator -= (const RS_Vector& v) {
573
void RS_Vector::operator *= (const double& s) {
583
void RS_Vector::operator /= (const double& s) {
584
if(fabs(s)>RS_TOLERANCE) {
598
bool RS_Vector::operator == (const RS_Vector& v) const {
600
return (x==v.x && y==v.y && valid==v.valid);
602
return (x==v.x && y==v.y && z==v.z && valid==v.valid);
609
* @return A vector with the minimum components from the vectors v1 and v2.
610
* These might be mixed components from both vectors.
612
RS_Vector RS_Vector::minimum (const RS_Vector& v1, const RS_Vector& v2) {
613
return RS_Vector (std::min(v1.x, v2.x),
616
, std::min(v1.z, v2.z)
624
* @return A vector with the maximum values from the vectors v1 and v2
626
RS_Vector RS_Vector::maximum (const RS_Vector& v1, const RS_Vector& v2) {
627
return RS_Vector (std::max(v1.x, v2.x),
630
, std::max(v1.z, v2.z)
638
* @return Cross product of two vectors.
639
* we don't need cross product for 2D vectors
642
RS_Vector RS_Vector::crossP(const RS_Vector& v1, const RS_Vector& v2) {
643
return RS_Vector(v1.y*v2.z - v1.z*v2.y,
644
v1.z*v2.x - v1.x*v2.z,
645
v1.x*v2.y - v1.y*v2.x);
651
* Constructor for no solution.
653
RS_VectorSolutions::RS_VectorSolutions() {
663
RS_VectorSolutions::RS_VectorSolutions(const RS_VectorSolutions& s)
665
setTangent(s.isTangent());
672
* Constructor for num solutions.
674
RS_VectorSolutions::RS_VectorSolutions(int num) {
675
#if QT_VERSION >= 0x040700
678
for(int i=vector.size();i<num;i++){
679
vector.push_back(RS_Vector(false));
687
* Constructor for one solution.
689
RS_VectorSolutions::RS_VectorSolutions(const RS_Vector& v1) {
690
vector.push_back(v1);
697
* Constructor for two solutions.
699
RS_VectorSolutions::RS_VectorSolutions(const RS_Vector& v1,
700
const RS_Vector& v2) {
701
vector.push_back(v1);
702
vector.push_back(v2);
709
* Constructor for three solutions.
711
RS_VectorSolutions::RS_VectorSolutions(const RS_Vector& v1,
713
const RS_Vector& v3) {
714
vector.push_back(v1);
715
vector.push_back(v2);
716
vector.push_back(v3);
722
* Constructor for four solutions.
724
RS_VectorSolutions::RS_VectorSolutions(const RS_Vector& v1,
727
const RS_Vector& v4) {
728
vector.push_back(v1);
729
vector.push_back(v2);
730
vector.push_back(v3);
731
vector.push_back(v4);
737
* Constructor for four solutions.
739
RS_VectorSolutions::RS_VectorSolutions(const RS_Vector& v1,
743
const RS_Vector& v5) {
744
vector.push_back(v1);
745
vector.push_back(v2);
746
vector.push_back(v3);
747
vector.push_back(v4);
748
vector.push_back(v5);
757
RS_VectorSolutions::~RS_VectorSolutions() {
763
* Allocates 'num' vectors.
765
void RS_VectorSolutions::alloc(int num) {
766
#if QT_VERSION >= 0x040700
769
if(vector.size() <num) {
770
for(int i=vector.size();i<num;i++){
771
vector.push_back(RS_Vector(false));
775
if(vector.size()>num) {
776
vector.erase(vector.begin()+num, vector.end());
782
* Deletes vector array and resets everything.
784
void RS_VectorSolutions::clear() {
792
* @return vector solution number i or an invalid vector if there
793
* are less solutions.
795
RS_Vector RS_VectorSolutions::at(int i) const {
796
if (i<vector.size()) {
799
return RS_Vector(false);
806
* @return Number of solutions available.
808
int RS_VectorSolutions::getNumber() const {
809
return vector.size();
815
* @retval true There's at least one valid solution.
816
* @retval false There's no valid solution.
818
bool RS_VectorSolutions::hasValid() const {
819
for (int i=0; i<vector.size(); i++) {
820
if (vector[i].valid) {
828
void RS_VectorSolutions::resize(size_t n){
832
QVector<RS_Vector> RS_VectorSolutions::getVector() const {
836
void RS_VectorSolutions::push_back(const RS_Vector& v) {
840
void RS_VectorSolutions::removeAt(const int i){
841
if (vector.size()> i)
845
RS_VectorSolutions RS_VectorSolutions::appendTo(const RS_VectorSolutions& v) {
846
vector += v.getVector();
851
* Sets the solution i to the given vector.
852
* If i is greater than the current number of solutions available,
855
void RS_VectorSolutions::set(int i, const RS_Vector& v) {
856
if (i<vector.size()) {
859
// RS_DEBUG->print(RS_Debug::D_ERROR, "set member in vector in RS_VectorSolutions: out of range, %d to size of %d", i,vector.size());
860
for(int j=vector.size();j<=i;j++)
868
* Sets the tangent flag.
870
void RS_VectorSolutions::setTangent(bool t) {
877
* @return true if at least one of the solutions is a double solution
880
bool RS_VectorSolutions::isTangent() const {
886
* Rotates all vectors around (0,0) by the given angle.
888
void RS_VectorSolutions::rotate(const double& ang) {
889
RS_Vector angleVector(ang);
890
for (int i=0; i<vector.size(); i++) {
891
if (vector[i].valid) {
892
vector[i].rotate(angleVector);
898
* Rotates all vectors around (0,0) by the given angleVector.
900
void RS_VectorSolutions::rotate(const RS_Vector& angleVector) {
901
for (int i=0; i<vector.size(); i++) {
902
if (vector[i].valid) {
903
//To be a real rotation, the determinant of angleVector has to be 1 for a pure rotation
904
vector[i].rotate(angleVector);
910
* Rotates all vectors around the given center by the given angle.
912
void RS_VectorSolutions::rotate(const RS_Vector& center, const double& ang) {
913
RS_Vector angleVector(ang);
914
for (int i=0; i<vector.size(); i++) {
915
if (vector[i].valid) {
916
vector[i].rotate(center,angleVector);
920
void RS_VectorSolutions::rotate(const RS_Vector& center, const RS_Vector& angleVector) {
921
for (int i=0; i<vector.size(); i++) {
922
if (vector[i].valid) {
923
vector[i].rotate(center,angleVector);
929
* Move all vectors around the given center by the given vector.
931
void RS_VectorSolutions::move(const RS_Vector& vp) {
932
for (int i=0; i<vector.size(); i++) {
933
if (vector[i].valid) vector[i].move(vp);
939
* Scales all vectors by the given factors with the given center.
941
void RS_VectorSolutions::scale(const RS_Vector& center, const RS_Vector& factor) {
942
for (int i=0; i<vector.size(); i++) {
943
if (vector[i].valid) {
944
vector[i].scale(center, factor);
948
void RS_VectorSolutions::scale( const RS_Vector& factor) {
949
for (int i=0; i<vector.size(); i++) {
950
if (vector[i].valid) {
951
vector[i].scale(factor);
958
* @return vector solution which is the closest to the given coordinate.
959
* dist will contain the distance if it doesn't point to NULL (default).
961
RS_Vector RS_VectorSolutions::getClosest(const RS_Vector& coord,
962
double* dist, int* index) const {
965
double minDist = RS_MAXDOUBLE;
966
RS_Vector closestPoint(false);
969
for (int i=0; i<vector.size(); i++) {
970
if (vector[i].valid) {
971
curDist = (coord - vector[i]).squared();
973
if (curDist<minDist) {
974
closestPoint = vector[i];
981
*dist = sqrt(minDist);
989
*@ return the closest distance from the first counts rs_vectors
990
*@coord, distance to this point
991
*@counts, only consider this many points within solution
993
double RS_VectorSolutions::getClosestDistance(const RS_Vector& coord,
996
double ret=RS_MAXDOUBLE*RS_MAXDOUBLE;
998
if (counts<i && counts>=0) i=counts;
999
for(int j=0; j<i; j++) {
1000
if(vector[j].valid) {
1001
double d=(coord - vector[j]).squared();
1008
/** switch x,y for all vectors */
1009
RS_VectorSolutions RS_VectorSolutions::flipXY(void) const
1011
RS_VectorSolutions ret;
1012
const int counts=vector.size();
1013
for(int i=0;i<counts;i++) ret.push_back(vector[i].flipXY());
1017
RS_VectorSolutions RS_VectorSolutions::operator = (const RS_VectorSolutions& s) {
1018
setTangent(s.isTangent());
1025
std::ostream& operator << (std::ostream& os,
1026
const RS_VectorSolutions& s) {
1027
for (int i=0; i<s.getNumber(); ++i) {
1028
os << "(" << s.get(i) << ")\n";
1030
os << " tangent: " << (int)s.isTangent() << "\n";