TexGen
mymath.h
Go to the documentation of this file.
1/*=============================================================================
2TexGen: Geometric textile modeller.
3Copyright (C) 2006 Martin Sherburn
4
5This program is free software; you can redistribute it and/or
6modify it under the terms of the GNU General Public License
7as published by the Free Software Foundation; either version 2
8of the License, or (at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18=============================================================================*/
19
20#pragma once
21
22#include <cmath>
23#include <assert.h>
24#include <stdlib.h>
25#include <memory.h>
26#include <ostream>
27#include <istream>
28#include <algorithm>
29
30#define PI 3.1415926535897932384626433832795
32namespace TexGen
33{
34 struct XYZ;
35
37 struct WXYZ
38 {
39 double w, x, y, z;
41 WXYZ() {w=x=y=z=0.0;}
43 WXYZ(double W, double X, double Y, double Z) {w=W;x=X;y=Y;z=Z;}
45 WXYZ(double Coords[4]) {w=Coords[0];x=Coords[1];y=Coords[2];z=Coords[3];}
47 WXYZ(XYZ Axis, double dAngle);
49 WXYZ(XYZ X, XYZ Y, XYZ Z);
51 WXYZ(double dAzimuth, double dElevation, double dTilt);
52 };
53
55 struct XYZ
56 {
57 double x, y, z;
59 double operator =(double right)
60 {
61 x = right;
62 y = right;
63 z = right;
64 return right;
65 }
67 bool operator !() const
68 {
69 return (!x && !y && !z);
70 }
71 operator bool() const
72 {
73 return (x || y || z);
74 }
75 double &operator [](int i)
76 {
77 return *(&x+i);
78 }
79 const double &operator [](int i) const
80 {
81 return *(&x+i);
82 }
85 {
86 XYZ ReturnVal;
87 ReturnVal.x = -x;
88 ReturnVal.y = -y;
89 ReturnVal.z = -z;
90 return ReturnVal;
91 }
92
94 XYZ() {x=y=z=0.0;}
96 XYZ(double X, double Y, double Z) {x=X;y=Y;z=Z;}
98 XYZ(double Coords[3]) {x=Coords[0];y=Coords[1];z=Coords[2];}
99 };
100
102 struct XY
103 {
104 double x, y;
106 XY() {x=y=0;}
108 XY(double X, double Y) {x=X; y=Y;}
110 XY(double Coords[2]) {x=Coords[0];y=Coords[1];}
112 bool operator ==(const XY &right) const
113 {
114 return x == right.x && y == right.y;
115 }
117 bool operator !() const
118 {
119 return (!x && !y);
120 }
121 operator bool() const
122 {
123 return (x || y);
124 }
125 double &operator [](int i)
126 {
127 return *(&x+i);
128 }
129 const double &operator [](int i) const
130 {
131 return *(&x+i);
132 }
133
136 {
137 XY ReturnVal;
138 ReturnVal.x = -x;
139 ReturnVal.y = -y;
140 return ReturnVal;
141 }
142 };
143
144 inline XY Convert(const XYZ &Val)
145 {
146 return XY(Val.x, Val.y);
147 }
148
149 inline bool operator == (const XYZ &left, const XYZ &right)
150 {
151 return (left.x==right.x && left.y==right.y && left.z==right.z);
152 }
153
154 inline bool operator == (const XYZ &left, const double &value)
155 {
156 return (left.x==value && left.y==value && left.z==value);
157 }
158
159 inline bool operator == (const XYZ &left, const int &value)
160 {
161 return (left.x==value && left.y==value && left.z==value);
162 }
163
164 inline WXYZ operator + (const WXYZ &left, const WXYZ &right)
165 {
166 WXYZ ReturnVal;
167 ReturnVal.w = left.w + right.w;
168 ReturnVal.x = left.x + right.x;
169 ReturnVal.y = left.y + right.y;
170 ReturnVal.z = left.z + right.z;
171 return ReturnVal;
172 }
173
174 inline XYZ operator + (const XYZ &left, const XYZ &right)
175 {
176 XYZ ReturnVal;
177 ReturnVal.x = left.x + right.x;
178 ReturnVal.y = left.y + right.y;
179 ReturnVal.z = left.z + right.z;
180 return ReturnVal;
181 }
182
183 inline XY operator + (const XY &left, const XY &right)
184 {
185 XY ReturnVal;
186 ReturnVal.x = left.x + right.x;
187 ReturnVal.y = left.y + right.y;
188 return ReturnVal;
189 }
190
191 inline WXYZ &operator += (WXYZ &left, const WXYZ &right)
192 {
193 left.w += right.w;
194 left.x += right.x;
195 left.y += right.y;
196 left.z += right.z;
197 return left;
198 }
199
200 inline XYZ &operator += (XYZ &left, const XYZ &right)
201 {
202 left.x += right.x;
203 left.y += right.y;
204 left.z += right.z;
205 return left;
206 }
207
208 inline XY &operator += (XY &left, const XY &right)
209 {
210 left.x += right.x;
211 left.y += right.y;
212 return left;
213 }
214
215 inline WXYZ operator - (const WXYZ &left, const WXYZ &right)
216 {
217 WXYZ ReturnVal;
218 ReturnVal.w = left.w - right.w;
219 ReturnVal.x = left.x - right.x;
220 ReturnVal.y = left.y - right.y;
221 ReturnVal.z = left.z - right.z;
222 return ReturnVal;
223 }
224
225 inline XYZ operator - (const XYZ &left, const XYZ &right)
226 {
227 XYZ ReturnVal;
228 ReturnVal.x = left.x - right.x;
229 ReturnVal.y = left.y - right.y;
230 ReturnVal.z = left.z - right.z;
231 return ReturnVal;
232 }
233
234 inline XY operator - (const XY &left, const XY &right)
235 {
236 XY ReturnVal;
237 ReturnVal.x = left.x - right.x;
238 ReturnVal.y = left.y - right.y;
239 return ReturnVal;
240 }
241
242 inline WXYZ &operator -= (WXYZ &left, const WXYZ &right)
243 {
244 left.w -= right.w;
245 left.x -= right.x;
246 left.y -= right.y;
247 left.z -= right.z;
248 return left;
249 }
250
251 inline XYZ &operator -= (XYZ &left, const XYZ &right)
252 {
253 left.x -= right.x;
254 left.y -= right.y;
255 left.z -= right.z;
256 return left;
257 }
258
259 inline XY &operator -= (XY &left, const XY &right)
260 {
261 left.x -= right.x;
262 left.y -= right.y;
263 return left;
264 }
265
267 inline WXYZ operator * (const WXYZ &left, const WXYZ &right)
268 {
269 WXYZ Quaternion;
270 Quaternion.w = left.w * right.w - left.x * right.x - left.y * right.y - left.z * right.z;
271 Quaternion.x = left.w * right.x + left.x * right.w + left.y * right.z - left.z * right.y;
272 Quaternion.y = left.w * right.y + left.y * right.w + left.z * right.x - left.x * right.z;
273 Quaternion.z = left.w * right.z + left.z * right.w + left.x * right.y - left.y * right.x;
274 return Quaternion;
275 }
276
277 inline XYZ operator * (const XYZ &left, const XYZ &right)
278 {
279 XYZ ReturnVal;
280 ReturnVal.x = left.x * right.x;
281 ReturnVal.y = left.y * right.y;
282 ReturnVal.z = left.z * right.z;
283 return ReturnVal;
284 }
285
286 inline XY operator * (const XY &left, const XY &right)
287 {
288 XY ReturnVal;
289 ReturnVal.x = left.x * right.x;
290 ReturnVal.y = left.y * right.y;
291 return ReturnVal;
292 }
293
295 inline XYZ operator / (const XYZ &left, const XYZ &right)
296 {
297 XYZ ReturnVal;
298 ReturnVal.x = left.x / right.x;
299 ReturnVal.y = left.y / right.y;
300 ReturnVal.z = left.z / right.z;
301 return ReturnVal;
302 }
303
305 inline WXYZ &operator *= (WXYZ &left, const WXYZ &right)
306 {
307 WXYZ Quaternion;
308 Quaternion.w = left.w * right.w - left.x * right.x - left.y * right.y - left.z * right.z;
309 Quaternion.x = left.w * right.x + left.x * right.w + left.y * right.z - left.z * right.y;
310 Quaternion.y = left.w * right.y + left.y * right.w + left.z * right.x - left.x * right.z;
311 Quaternion.z = left.w * right.z + left.z * right.w + left.x * right.y - left.y * right.x;
312 left = Quaternion;
313 return left;
314 }
315
316 inline XYZ &operator *= (XYZ &left, const XYZ &right)
317 {
318 left.x *= right.x;
319 left.y *= right.y;
320 left.z *= right.z;
321 return left;
322 }
323
324 inline XY &operator *= (XY &left, const XY &right)
325 {
326 left.x *= right.x;
327 left.y *= right.y;
328 return left;
329 }
330
331 inline XYZ operator * (const XYZ &left, const double &right)
332 {
333 XYZ ReturnVal;
334 ReturnVal.x = left.x * right;
335 ReturnVal.y = left.y * right;
336 ReturnVal.z = left.z * right;
337 return ReturnVal;
338 }
339
340 inline XYZ operator * (const XYZ &left, const float &right)
341 {
342 XYZ ReturnVal;
343 ReturnVal.x = left.x * right;
344 ReturnVal.y = left.y * right;
345 ReturnVal.z = left.z * right;
346 return ReturnVal;
347 }
348
349 inline XYZ operator * (const XYZ &left, const int &right)
350 {
351 XYZ ReturnVal;
352 ReturnVal.x = left.x * right;
353 ReturnVal.y = left.y * right;
354 ReturnVal.z = left.z * right;
355 return ReturnVal;
356 }
357
358 inline XY operator * (const XY &left, const double &right)
359 {
360 XY ReturnVal;
361 ReturnVal.x = left.x * right;
362 ReturnVal.y = left.y * right;
363 return ReturnVal;
364 }
365
366 inline XYZ operator * (const double &left, const XYZ &right)
367 {
368 XYZ ReturnVal;
369 ReturnVal.x = right.x * left;
370 ReturnVal.y = right.y * left;
371 ReturnVal.z = right.z * left;
372 return ReturnVal;
373 }
374
375 inline XYZ operator * (const float &left, const XYZ &right)
376 {
377 XYZ ReturnVal;
378 ReturnVal.x = right.x * left;
379 ReturnVal.y = right.y * left;
380 ReturnVal.z = right.z * left;
381 return ReturnVal;
382 }
383
384 inline XYZ operator * (const int &left, const XYZ &right)
385 {
386 XYZ ReturnVal;
387 ReturnVal.x = right.x * left;
388 ReturnVal.y = right.y * left;
389 ReturnVal.z = right.z * left;
390 return ReturnVal;
391 }
392
393 inline XY operator * (const double &left, const XY &right)
394 {
395 XY ReturnVal;
396 ReturnVal.x = right.x * left;
397 ReturnVal.y = right.y * left;
398 return ReturnVal;
399 }
400
401 inline XYZ operator / (const XYZ &left, const double &right)
402 {
403 XYZ ReturnVal;
404 ReturnVal.x = left.x / right;
405 ReturnVal.y = left.y / right;
406 ReturnVal.z = left.z / right;
407 return ReturnVal;
408 }
409
410 inline XY operator / (const XY &left, const double &right)
411 {
412 XY ReturnVal;
413 ReturnVal.x = left.x / right;
414 ReturnVal.y = left.y / right;
415 return ReturnVal;
416 }
417
418 inline WXYZ &operator /= (WXYZ &left, const double &right)
419 {
420 double dDivisor = 1/right;
421 left.w *= dDivisor;
422 left.x *= dDivisor;
423 left.y *= dDivisor;
424 left.z *= dDivisor;
425 return left;
426 }
427
428 inline XYZ &operator /= (XYZ &left, const double &right)
429 {
430 double dDivisor = 1/right;
431 left.x *= dDivisor;
432 left.y *= dDivisor;
433 left.z *= dDivisor;
434 return left;
435 }
436
437 inline XY &operator /= (XY &left, const double &right)
438 {
439 double dDivisor = 1/right;
440 left.x *= dDivisor;
441 left.y *= dDivisor;
442 return left;
443 }
444
445 inline XYZ &operator *= (XYZ &left, const double &right)
446 {
447 left.x = left.x * right;
448 left.y = left.y * right;
449 left.z = left.z * right;
450 return left;
451 }
452
453 inline XY &operator *= (XY &left, const double &right)
454 {
455 left.x = left.x * right;
456 left.y = left.y * right;
457 return left;
458 }
459
460 inline XYZ operator / (const XYZ &left, const int &right)
461 {
462 XYZ ReturnVal;
463 ReturnVal.x = left.x / right;
464 ReturnVal.y = left.y / right;
465 ReturnVal.z = left.z / right;
466 return ReturnVal;
467 }
468
469 inline std::ostream &operator << (std::ostream &output, const WXYZ &Quat)
470 {
471 output << Quat.w << ", " << Quat.x << ", " << Quat.y << ", " << Quat.z;
472 return output;
473 }
474
475 inline std::ostream &operator << (std::ostream &output, const XYZ &Vector)
476 {
477 output << Vector.x << ", " << Vector.y << ", " << Vector.z;
478 return output;
479 }
480
481 inline std::ostream &operator << (std::ostream &output, const XY &Vector)
482 {
483 output << Vector.x << ", " << Vector.y;
484 return output;
485 }
486
487 inline std::istream &operator >> (std::istream &input, WXYZ &Quat)
488 {
489 input >> Quat.w; input.ignore(); // ignore the comma
490 input >> Quat.x; input.ignore(); // ignore the comma
491 input >> Quat.y; input.ignore(); // ignore the comma
492 input >> Quat.z;
493 return input;
494 }
495
496 inline std::istream &operator >> (std::istream &input, XYZ &Vector)
497 {
498 input >> Vector.x; input.ignore(); // ignore the comma
499 input >> Vector.y; input.ignore(); // ignore the comma
500 input >> Vector.z;
501 return input;
502 }
503
504 inline std::istream &operator >> (std::istream &input, XY &Vector)
505 {
506 input >> Vector.x; input.ignore(); // ignore the comma
507 input >> Vector.y;
508 return input;
509 }
510
512 inline double DotProduct(const XYZ &left, const XYZ &right)
513 {
514 return (left.x*right.x + left.y*right.y + left.z*right.z);
515 }
516
518 inline double DotProduct(const XY &left, const XY &right)
519 {
520 return (left.x*right.x + left.y*right.y);
521 }
522
524 inline XYZ CrossProduct(const XYZ &left, const XYZ &right)
525 {
526 XYZ ReturnVal;
527 ReturnVal.x = left.y*right.z - right.y*left.z;
528 ReturnVal.y = left.z*right.x - right.z*left.x;
529 ReturnVal.z = left.x*right.y - right.x*left.y;
530 return ReturnVal;
531 }
532
534 inline double RandomNumber(double dMin, double dMax)
535 {
536 return ((double(rand())/RAND_MAX)*(dMax-dMin))+dMin;
537 }
538
540 inline double GetLength(const XYZ &Point1, const XYZ &Point2)
541 {
542 return sqrt((Point2.x-Point1.x)*(Point2.x-Point1.x)+
543 (Point2.y-Point1.y)*(Point2.y-Point1.y)+
544 (Point2.z-Point1.z)*(Point2.z-Point1.z));
545 }
546
548 inline double GetLengthSquared(const XYZ &Point1, const XYZ &Point2)
549 {
550 return ((Point2.x-Point1.x)*(Point2.x-Point1.x)+
551 (Point2.y-Point1.y)*(Point2.y-Point1.y)+
552 (Point2.z-Point1.z)*(Point2.z-Point1.z));
553 }
554
556 inline double GetLength(const XY &Point1, const XY &Point2)
557 {
558 return sqrt((Point2.x-Point1.x)*(Point2.x-Point1.x)+
559 (Point2.y-Point1.y)*(Point2.y-Point1.y));
560 }
561
563 inline double GetLengthSquared(const XY &Point1, const XY &Point2)
564 {
565 return ((Point2.x-Point1.x)*(Point2.x-Point1.x)+
566 (Point2.y-Point1.y)*(Point2.y-Point1.y));
567 }
568
570 inline double GetLength(const WXYZ &Quaternion)
571 {
572 return sqrt((Quaternion.w)*(Quaternion.w)+
573 (Quaternion.x)*(Quaternion.x)+
574 (Quaternion.y)*(Quaternion.y)+
575 (Quaternion.z)*(Quaternion.z));
576 }
577
579 inline double GetLength(const XYZ &Vector)
580 {
581 return sqrt((Vector.x)*(Vector.x)+
582 (Vector.y)*(Vector.y)+
583 (Vector.z)*(Vector.z));
584 }
585
587 inline double GetLength(const XY &Vector)
588 {
589 return sqrt((Vector.x)*(Vector.x)+
590 (Vector.y)*(Vector.y));
591 }
592
594 inline double GetLengthSquared(const XYZ &Point)
595 {
596 return ((Point.x)*(Point.x)+
597 (Point.y)*(Point.y)+
598 (Point.z)*(Point.z));
599 }
600
602 inline double GetLengthSquared(const XY &Point)
603 {
604 return ((Point.x)*(Point.x)+
605 (Point.y)*(Point.y));
606 }
607
609 inline WXYZ &Normalise(WXYZ &Quaternion)
610 {
611 double dLength = GetLength(Quaternion);
612 if (dLength)
613 Quaternion /= dLength;
614 else
615 assert(false);
616 return Quaternion;
617 }
618
620 inline XYZ &Normalise(XYZ &Vector)
621 {
622 double dLength = GetLength(Vector);
623 if (dLength)
624 Vector /= dLength;
625 else
626 assert(false);
627 return Vector;
628 }
629
631 inline XY &Normalise(XY &Vector)
632 {
633 double dLength = GetLength(Vector);
634 if (dLength)
635 Vector /= dLength;
636 else
637 assert(false);
638 return Vector;
639 }
640
642 inline double Max( XYZ &Vector )
643 {
644 double max = Vector.x;
645 if ( Vector.y > max )
646 max = Vector.y;
647 if ( Vector.z > max )
648 max = Vector.z;
649 return max;
650 }
651
653 inline WXYZ::WXYZ(XYZ Axis, double dAngle)
654 {
655 w = cos(0.5*dAngle);
656 double dCoeff = sin(0.5*dAngle);
657 x = Axis.x*dCoeff;
658 y = Axis.y*dCoeff;
659 z = Axis.z*dCoeff;
660 }
661
663 inline WXYZ::WXYZ(XYZ X, XYZ Y, XYZ Z)
664 {
665 double dTrace = 1 + X.x + Y.y + Z.z;
666 double S;
667 if (dTrace > 1e-6)
668 {
669 S = 1/(2*sqrt(dTrace));
670 w = 1/(4*S);
671 x = (Y.z - Z.y)*S;
672 y = (Z.x - X.z)*S;
673 z = (X.y - Y.x)*S;
674 }
675 else
676 {
677 // NOTE: This part has not been tested, may not work correctly
678 if ((X.x > Y.y)&&(X.x > Z.z))
679 {
680 S = sqrt( 1.0 + X.x - Y.y - Z.z ) * 2; // S=4*qx
681 x = 0.25 * S;
682 y = (Y.x + X.y ) / S;
683 z = (Z.x + X.z ) / S;
684 w = (Y.z - Z.y ) / S;
685 }
686 else if (Y.y > Z.z)
687 {
688 S = sqrt( 1.0 + Y.y - X.x - Z.z ) * 2; // S=4*qy
689 x = (Y.x + X.y ) / S;
690 y = 0.25 * S;
691 z = (Z.y + Y.z ) / S;
692 w = (Z.x - X.z ) / S;
693 }
694 else
695 {
696 S = sqrt( 1.0 + Z.z - X.x - Y.y ) * 2; // S=4*qz
697 x = (Z.x + X.z ) / S;
698 y = (Z.y + Y.z ) / S;
699 z = 0.25 * S;
700 w = (X.y - Y.x ) / S;
701 }
702 }
703 }
704
706
712 inline WXYZ::WXYZ(double dAzimuth, double dElevation, double dTilt)
713 {
714 double c1 = cos(dAzimuth / 2);
715 double c2 = cos(dElevation / 2);
716 double c3 = cos(dTilt / 2);
717 double s1 = sin(dAzimuth / 2);
718 double s2 = sin(dElevation / 2);
719 double s3 = sin(dTilt / 2);
720 w = c1*c2*c3 - s1*s2*s3;
721 x = s1*s2*c3 + c1*c2*s3;
722 y = c1*s2*c3 - s1*c2*s3;
723 z = s1*c2*c3 + c1*s2*s3;
724 }
725
727 inline XYZ operator * (const WXYZ &left, const XYZ &right)
728 {
729 // nVidia SDK implementation
730 XYZ uv, uuv;
731 XYZ qvec(left.x, left.y, left.z);
732 uv = CrossProduct(qvec, right);
733 uuv = CrossProduct(qvec, uv);
734 uv *= (2.0f * left.w);
735 uuv *= 2.0f;
736
737 return right + uv + uuv;
738 }
739
741 inline bool SphereSphereIntersect(const XYZ &p1, const XYZ &p2, double dRadii)
742 {
743 return (GetLength(p1, p2) <= dRadii);
744 }
745
749 inline XYZ ShortestDistPointLine(const XYZ &Point, const XYZ &LineStart, const XYZ &LineEnd, double &dU)
750 {
751 double dLineLengthSquared;
752 XYZ Intersection;
753
754 dLineLengthSquared = GetLengthSquared(LineEnd, LineStart);
755
756 dU = DotProduct(Point-LineStart, LineEnd-LineStart) / ( dLineLengthSquared );
757
758 Intersection = LineStart + dU * ( LineEnd - LineStart );
759
760 return Intersection;
761 }
762
768 inline bool SphereCylinderIntersect(const XYZ &Point, const XYZ &LineStart, const XYZ &LineEnd, double dRadii, double* pdUReturn = NULL)
769 {
770 double dU;
771 XYZ Intersection;
772
773 Intersection = ShortestDistPointLine(Point, LineStart, LineEnd, dU);
774
775 // If the closest point on the line to the sphere is outside the line segment
776 // do an intersection test with the sphere created at the end or start
777 // of the line segment depending on which side it lies.
778 if (dU < 0)
779 {
780 if (pdUReturn)
781 *pdUReturn = 0;
782 return SphereSphereIntersect(LineStart, Point, dRadii);
783 }
784 if (dU > 1)
785 {
786 if (pdUReturn)
787 *pdUReturn = 1;
788 return SphereSphereIntersect(LineEnd, Point, dRadii);
789 }
790
791 if (pdUReturn)
792 *pdUReturn = dU;
793 // Check that the distance between the intersection and the point is less than the radius
794 return SphereSphereIntersect(Intersection, Point, dRadii);
795 }
796
797 inline bool LineLineIntersect2D(const XY &p1, const XY &p2, const XY &p3, const XY &p4, double &dU1, double &dU2)
798 {
799 double denom;
800 denom = (p4.y-p3.y)*(p2.x-p1.x) - (p4.x-p3.x)*(p2.y-p1.y);
801 if (!denom)
802 return false;
803 dU1 = (p4.x-p3.x)*(p1.y-p3.y)-(p4.y-p3.y)*(p1.x-p3.x);
804 dU2 = (p2.x-p1.x)*(p1.y-p3.y)-(p2.y-p1.y)*(p1.x-p3.x);
805 dU1 /= denom;
806 dU2 /= denom;
807 if (dU1 < 0 || dU1 > 1 ||
808 dU2 < 0 || dU2 > 1)
809 return false;
810 return true;
811 }
812
818 inline bool ShortestDistLineLine(const XYZ &p1, const XYZ &p2, const XYZ &p3, const XYZ &p4, double &dU1, double &dU2, XYZ &pa, XYZ &pb)
819 {
820 // XYZ pa, pb;
821 XYZ p13,p43,p21;
822 double d1343,d4321,d1321,d4343,d2121;
823 double numer,denom;
824 // double mua, mub;
825
826 p13 = p1 - p3;
827 p43 = p4 - p3;
828 // If the length of line 2 is 0 return false
829 if (!p43)
830 return false;
831 p21 = p2 - p1;
832 // If the length of line 1 is 0 return false
833 if (!p21)
834 return false;
835
836 d1343 = DotProduct(p13, p43);
837 d4321 = DotProduct(p43, p21);
838 d1321 = DotProduct(p13, p21);
839 d4343 = DotProduct(p43, p43);
840 d2121 = DotProduct(p21, p21);
841
842 denom = d2121 * d4343 - d4321 * d4321;
843 // If the denominator is 0 then the lines are parallel in which case
844 if (!denom)
845 return false;
846
847 numer = d1343 * d4321 - d1321 * d4343;
848
849 dU1 = numer / denom;
850 dU2 = (d1343 + d4321 * dU1) / d4343;
851
852 pa = p1 + dU1 * (p2 - p1);
853 pb = p3 + dU2 * (p4 - p3);
854
855 return true;
856 }
857
862 inline bool RoundedCylinderIntersect(const XYZ &p1, const XYZ &p2, const XYZ &p3, const XYZ &p4, double dRadii, double* pdU1 = NULL, double* pdU2 = NULL)
863 {
864 double mua, mub;
865 XYZ pa, pb;
866
867 if (!ShortestDistLineLine(p1, p2, p3, p4, mua, mub, pa, pb))
868 return false;
869
870 if (pdU1)
871 *pdU1 = mua;
872 if (pdU2)
873 *pdU2 = mub;
874
875 if (!SphereSphereIntersect(pa, pb, dRadii))
876 return false;
877 int iCase = 0;
878
879 if (mua < 0)
880 {
881 if (pdU1)
882 *pdU1 = 0;
883 iCase |= 1<<0;
884 }
885 if (mua > 1)
886 {
887 if (pdU1)
888 *pdU1 = 1;
889 iCase |= 1<<1;
890 }
891 if (mub < 0)
892 {
893 if (pdU2)
894 *pdU2 = 0;
895 iCase |= 1<<2;
896 }
897 if (mub > 1)
898 {
899 if (pdU2)
900 *pdU2 = 1;
901 iCase |= 1<<3;
902 }
903
904 /* CASE:
905 =====
906
907 0 : mua & mub are within bounds
908
909 1 : mua < 0
910 2 : mua > 1
911 4 : mub < 0
912 8 : mub > 1
913
914 5 : mua < 0 & mub < 0
915 6 : mua > 1 & mub < 0
916 9 : mua < 0 & mub > 1
917 10: mua > 1 & mub > 1
918
919 3, 15 : Impossible (mua or mub can't be bigger than 1 AND smaller than 0)
920 */
921 double dOverlap1, dOverlap2;
922
923 switch (iCase)
924 {
925 case 0: // mua & mub are within bounds
926 return true; // We already checked if the distance between points was less than radius
927 // return SphereSphereIntersect(pa, pb, dRadii);
928 case 1: // mua < 0
929 return SphereCylinderIntersect(p1, p3, p4, dRadii, pdU2);
930 case 2: // mua > 1
931 return SphereCylinderIntersect(p2, p3, p4, dRadii, pdU2);
932 case 4: // mub < 0
933 return SphereCylinderIntersect(p3, p1, p2, dRadii, pdU1);
934 case 8: // mub > 1
935 return SphereCylinderIntersect(p4, p1, p2, dRadii, pdU1);
936 case 5: // mua < 0 & mub < 0
937 dOverlap1 = GetLength(p2 - p1) * -mua;
938 dOverlap2 = GetLength(p4 - p3) * -mub;
939 if (dOverlap1 > dOverlap2)
940 return SphereCylinderIntersect(p1, p3, p4, dRadii, pdU2);
941 else
942 return SphereCylinderIntersect(p3, p1, p2, dRadii, pdU1);
943 case 6: // mua > 1 & mub < 0
944 dOverlap1 = GetLength(p2 - p1) * (mua-1);
945 dOverlap2 = GetLength(p4 - p3) * -mub;
946 if (dOverlap1 > dOverlap2)
947 return SphereCylinderIntersect(p2, p3, p4, dRadii, pdU2);
948 else
949 return SphereCylinderIntersect(p3, p1, p2, dRadii, pdU1);
950 case 9: // mua < 0 & mub > 1
951 dOverlap1 = GetLength(p2 - p1) * -mua;
952 dOverlap2 = GetLength(p4 - p3) * (mub-1);
953 if (dOverlap1 > dOverlap2)
954 return SphereCylinderIntersect(p1, p3, p4, dRadii, pdU2);
955 else
956 return SphereCylinderIntersect(p4, p1, p2, dRadii, pdU1);
957 case 10: // mua > 1 & mub > 1
958 dOverlap1 = GetLength(p2 - p1) * (mua-1);
959 dOverlap2 = GetLength(p4 - p3) * (mub-1);
960 if (dOverlap1 > dOverlap2)
961 return SphereCylinderIntersect(p2, p3, p4, dRadii, pdU2);
962 else
963 return SphereCylinderIntersect(p4, p1, p2, dRadii, pdU1);
964 }
965 assert(false); // Should never reach this point
966 return false;
967 }
968
970 inline bool BoundingBoxIntersect(const XYZ &BBox1Min, const XYZ &BBox1Max, const XYZ &BBox2Min, const XYZ &BBox2Max, double dTolerance = 0)
971 {
972 if (BBox1Min.x > BBox2Max.x + dTolerance)
973 return false;
974 if (BBox1Max.x < BBox2Min.x - dTolerance)
975 return false;
976 if (BBox1Min.y > BBox2Max.y + dTolerance)
977 return false;
978 if (BBox1Max.y < BBox2Min.y - dTolerance)
979 return false;
980 if (BBox1Min.z > BBox2Max.z + dTolerance)
981 return false;
982 if (BBox1Max.z < BBox2Min.z - dTolerance)
983 return false;
984 return true;
985 }
986
988 inline bool PointInsideBox(const XYZ &Point, const XYZ &BoxMin, const XYZ &BoxMax, double dTolerance = 0)
989 {
990 if (Point.x > BoxMax.x + dTolerance)
991 return false;
992 if (Point.x < BoxMin.x - dTolerance)
993 return false;
994 if (Point.y > BoxMax.y + dTolerance)
995 return false;
996 if (Point.y < BoxMin.y - dTolerance)
997 return false;
998 if (Point.z > BoxMax.z + dTolerance)
999 return false;
1000 if (Point.z < BoxMin.z - dTolerance)
1001 return false;
1002 return true;
1003 }
1004
1007 inline void GetLocalCoordinateSystem(XYZ &LocalX, XYZ &LocalY, XYZ &LocalZ, const XYZ &Point1, const XYZ &Point2)
1008 {
1009 XYZ GlobalZ(0,0,1);
1010 XYZ GlobalY(0,1,0);
1011 LocalX = Point2-Point1;
1012 Normalise(LocalX);
1013 LocalY = CrossProduct(GlobalZ, LocalX);
1014 // If LocalX is exactly in line with GlobalZ then we have a problem
1015 // just choose a random axis and take cross product of LocalX with it
1016 // to get LocalY. It doesn't matter what the axis LocalY/Z are as long
1017 // as they are perpendicular to LocalX and each other
1018 if (LocalY == 0)
1019 LocalY = CrossProduct(GlobalY, LocalX);
1020 Normalise(LocalY);
1021 LocalZ = CrossProduct(LocalX, LocalY);
1022 }
1023
1025 inline bool GetIntersectionLinePlane(const XYZ &p1, const XYZ &p2, const XYZ &p3, const XYZ &N, XYZ &Intersection, double *pdU = NULL)
1026 {
1027 double dU;
1028 double dNumer, dDenom;
1029 dNumer = DotProduct(N, p3-p1);
1030 dDenom = DotProduct(N, p2-p1);
1031 if (!dDenom)
1032 return false;
1033 dU = dNumer/dDenom;
1034 Intersection = p1 + (p2-p1)*dU;
1035 if (pdU)
1036 {
1037 *pdU = dU;
1038 }
1039 return true;
1040 }
1041
1043 inline void GetRandomColor(double &r, double &g, double &b)
1044 {
1045 const int iMaxIndex = 12;
1046 double ColorArray[iMaxIndex][3] =
1047 {
1048 { 1, 0, 0 },
1049 { 0, 1, 0 },
1050 { 0, 0, 1 },
1051 { 1, 1, 0 },
1052 { 0, 1, 1 },
1053 { 1, 0, 1 },
1054 { 1, 0.5, 0 },
1055 { 1, 0, 0.5 },
1056 { 0.5, 1, 0 },
1057 { 0, 1, 0.5 },
1058 { 0.5, 0, 1 },
1059 { 0, 0.5, 1 },
1060 };
1061
1062 int iIndex;
1063 do
1064 {
1065 iIndex = int(RandomNumber(0, iMaxIndex));
1066 } while (iIndex < 0 || iIndex >= iMaxIndex);
1067
1068 r = ColorArray[iIndex][0];
1069 g = ColorArray[iIndex][1];
1070 b = ColorArray[iIndex][2];
1071 }
1072
1077 inline void GetFractionColor(double dFraction, double &r, double &g, double &b)
1078 {
1079 if (dFraction<0)
1080 {
1081 dFraction = 0;
1082 }
1083 else if (dFraction>1)
1084 {
1085 dFraction = 1;
1086 }
1087
1088 r = g = b = 0.0f;
1089 if (dFraction > 0.75f)
1090 r = 1.0f;
1091 else if (dFraction > 0.5f)
1092 r = (dFraction-0.5f)*4;
1093
1094 if (dFraction < 0.25f)
1095 b = 1.0f;
1096 else if (dFraction < 0.5f)
1097 b = (0.5f-dFraction)*4;
1098
1099 if (dFraction > 0.75f)
1100 g = (1.0f-dFraction)*4;
1101 else if (dFraction > 0.25f)
1102 g = 1;
1103 else
1104 g = dFraction*4;
1105 }
1106
1109 inline bool GetCircleCenter(const XYZ &A, const XYZ &B, const XYZ &C, XYZ &Center)
1110 {
1111 XYZ E, F, G, H, N;
1112 N = CrossProduct(A-B, C-B);
1113 if (GetLength(N) < 0.000001)
1114 return false;
1115 Normalise(N);
1116 E = (A+B)/2;
1117 G = (B+C)/2;
1118 F = E + CrossProduct(A-B, N);
1119 H = G + CrossProduct(C-B, N);
1120 double dU1, dU2;
1121 XYZ I1, I2;
1122 if (!ShortestDistLineLine(E, F, G, H, dU1, dU2, I1, I2))
1123 return false;
1124 // assert(GetLength(I1, I2)<0.000001);
1125 if (GetLength(I1, I2)>0.000001)
1126 return false;
1127 Center = (I1+I2)/2;
1128 return true;
1129 }
1130
1132 inline XYZ Max(const XYZ &P1, const XYZ &P2)
1133 {
1134 XYZ Return;
1135 Return.x = P1.x > P2.x ? P1.x : P2.x;
1136 Return.y = P1.y > P2.y ? P1.y : P2.y;
1137 Return.z = P1.z > P2.z ? P1.z : P2.z;
1138 return Return;
1139 }
1140
1142 inline XYZ Min(const XYZ &P1, const XYZ &P2)
1143 {
1144 XYZ Return;
1145 Return.x = P1.x < P2.x ? P1.x : P2.x;
1146 Return.y = P1.y < P2.y ? P1.y : P2.y;
1147 Return.z = P1.z < P2.z ? P1.z : P2.z;
1148 return Return;
1149 }
1150
1152 inline XY Max(const XY &P1, const XY &P2)
1153 {
1154 XY Return;
1155 Return.x = P1.x > P2.x ? P1.x : P2.x;
1156 Return.y = P1.y > P2.y ? P1.y : P2.y;
1157 return Return;
1158 }
1159
1161 inline XY Min(const XY &P1, const XY &P2)
1162 {
1163 XY Return;
1164 Return.x = P1.x < P2.x ? P1.x : P2.x;
1165 Return.y = P1.y < P2.y ? P1.y : P2.y;
1166 return Return;
1167 }
1168
1169 inline int Round(double dValue)
1170 {
1171 return int(dValue + (dValue > 0 ? 0.5 : -0.5));
1172 }
1173
1174 template<typename T>
1175 inline T CalculateBezierPoint(T p1, T p2, T p3, T p4, double mu)
1176 { // from http://astronomy.swin.edu.au/~pbourke/curves/bezier/ Now http://local.wasp.uwa.edu.au/~pbourke/geometry/bezier/index2.html
1177 double mum1 = 1 - mu;
1178
1179 return (mum1*mum1*mum1)*p1 + (3*mu*mum1*mum1)*p2 + (3*mu*mu*mum1)*p3 + (mu*mu*mu)*p4;
1180 }
1181
1182 template<typename T>
1183 inline T CalculateBezierTangent(T p1, T p2, T p3, T p4, double mu)
1184 { // This is the partial derivative of the above function with respect to mu
1185 double mum1 = 1 - mu;
1186
1187 return (-3*mum1*mum1)*p1 + (3*((mum1*mum1)-2*mu*mum1))*p2 + (3*(2*mu*mum1-mu*mu))*p3 + (3*mu*mu)*p4;
1188 }
1189
1190 inline double RandomNormalDistribution(double dStandrdDeviation = 1, double dAverage = 0)
1191 { // from http://home.online.no/~pjacklam/notes/invnorm/
1192 const double A1 = -3.969683028665376e+01;
1193 const double A2 = 2.209460984245205e+02;
1194 const double A3 = -2.759285104469687e+02;
1195 const double A4 = 1.383577518672690e+02;
1196 const double A5 = -3.066479806614716e+01;
1197 const double A6 = 2.506628277459239e+00;
1198
1199 const double B1 = -5.447609879822406e+01;
1200 const double B2 = 1.615858368580409e+02;
1201 const double B3 = -1.556989798598866e+02;
1202 const double B4 = 6.680131188771972e+01;
1203 const double B5 = -1.328068155288572e+01;
1204
1205 const double C1 = -7.784894002430293e-03;
1206 const double C2 = -3.223964580411365e-01;
1207 const double C3 = -2.400758277161838e+00;
1208 const double C4 = -2.549732539343734e+00;
1209 const double C5 = 4.374664141464968e+00;
1210 const double C6 = 2.938163982698783e+00;
1211
1212 const double D1 = 7.784695709041462e-03;
1213 const double D2 = 3.224671290700398e-01;
1214 const double D3 = 2.445134137142996e+00;
1215 const double D4 = 3.754408661907416e+00;
1216
1217 const double P_LOW = 0.02425;
1218 const double P_HIGH = 0.97575; // P_high = 1 - p_low
1219
1220 double q, r, x;
1221
1222 double p;
1223 do
1224 {
1225 p = RandomNumber(0, 1); // Get a random number between 0 and 1
1226 } while (p <= 0 || p >= 1); // Repeat making sure p is not 0 or 1
1227
1228 if (p > 0 && p < P_LOW){
1229 q = sqrt(-2*log(p));
1230 x = (((((C1*q+C2)*q+C3)*q+C4)*q+C5)*q+C6) / ((((D1*q+D2)*q+D3)*q+D4)*q+1);
1231 }
1232 else if (p >= P_LOW && p <= P_HIGH)
1233 {
1234 q = p - 0.5;
1235 r = q*q;
1236 x = (((((A1*r+A2)*r+A3)*r+A4)*r+A5)*r+A6)*q /(((((B1*r+B2)*r+B3)*r+B4)*r+B5)*r+1);
1237 }
1238 else if (p > P_HIGH && p < 1){
1239 q = sqrt(-2*log(1-p));
1240 x = -(((((C1*q+C2)*q+C3)*q+C4)*q+C5)*q+C6) / ((((D1*q+D2)*q+D3)*q+D4)*q+1);
1241 }
1242 return x*dStandrdDeviation+dAverage;
1243 }
1244
1245 inline double GetArea(XYZ Points[], int iNumPoints)
1246 {
1247 double dArea = 0;
1248 int i;
1249 XYZ Point1, Point2;
1250 for (i=0; i<iNumPoints; ++i)
1251 {
1252 Point1 = Points[i];
1253 Point2 = Points[(i+1)%iNumPoints];
1254 dArea += (Point1.x-Point2.x)*(Point1.y+Point2.y);
1255 }
1256 return 0.5*dArea;
1257 }
1258
1260 inline bool PointInsideTriangle(const XYZ &P1, const XYZ &P2, const XYZ &P3, const XYZ &P)
1261 {
1262 const double dTolerance = 1e-6;
1263 XYZ N = CrossProduct(P2 - P1, P3 - P1);
1264 XYZ vert0p = P1 - P; XYZ vert1p = P2 - P;
1265 if (DotProduct(CrossProduct(vert0p, vert1p), N) < -dTolerance) return false;
1266 XYZ vert2p = P3 - P;
1267 if (DotProduct(CrossProduct(vert1p, vert2p), N) < -dTolerance) return false;
1268 if (DotProduct(CrossProduct(vert2p, vert0p), N) < -dTolerance) return false;
1269 return true;
1270 }
1271
1273 inline bool PointInsideTriangle(const XYZ &P1, const XYZ &P2, const XYZ &P3, const XYZ &P, const XYZ &N)
1274 {
1275 const double dTolerance = 1e-6;
1276 XYZ vert0p = P1 - P; XYZ vert1p = P2 - P;
1277 if (DotProduct(CrossProduct(vert0p, vert1p), N) < -dTolerance) return false;
1278 XYZ vert2p = P3 - P;
1279 if (DotProduct(CrossProduct(vert1p, vert2p), N) < -dTolerance) return false;
1280 if (DotProduct(CrossProduct(vert2p, vert0p), N) < -dTolerance) return false;
1281 return true;
1282 }
1283
1285 inline double PointInsideTriangleAccuracy(const XYZ &P1, const XYZ &P2, const XYZ &P3, const XYZ &P, const XYZ &N)
1286 {
1287 XYZ vert0p = P1 - P; XYZ vert1p = P2 - P;
1288 XYZ vert2p = P3 - P;
1289 double dMin = DotProduct(CrossProduct(vert0p, vert1p), N);
1290 dMin = std::min(dMin, DotProduct(CrossProduct(vert1p, vert2p), N));
1291 dMin = std::min(dMin, DotProduct(CrossProduct(vert2p, vert0p), N));
1292 return dMin;
1293 }
1294
1296 inline bool PointInsideTriangle2D(const XYZ &P1, const XYZ &P2, const XYZ &P3, const XYZ &P, const XYZ *pNormal = NULL)
1297 {
1298 double dN;
1299 if (!pNormal)
1300 dN = (P2.x-P1.x)*(P3.y-P1.y) - (P3.x-P1.x)*(P2.y-P1.y);
1301 else
1302 dN = pNormal->z;
1303 XYZ V1 = P1 - P;
1304 XYZ V2 = P2 - P;
1305 if ((V1.x*V2.y-V2.x*V1.y) * dN < 0.0)
1306 return false;
1307 XYZ V3 = P3 - P;
1308 if ((V2.x*V3.y-V3.x*V2.y) * dN < 0.0)
1309 return false;
1310 if ((V3.x*V1.y-V1.x*V3.y) * dN < 0.0)
1311 return false;
1312 return true;
1313 }
1314
1316 inline double ShortestDistPointTriangle(const XYZ &P1, const XYZ &P2, const XYZ &P3, const XYZ &P, XYZ *pTrianglePoint = NULL, XYZ *pNormal = NULL)
1317 {
1318 // First find the closest distance between the point and the plane
1319
1320 XYZ Normal;
1321
1322 if (pNormal)
1323 {
1324 Normal = *pNormal;
1325 }
1326 else
1327 {
1328 Normal = CrossProduct(P2-P1, P3-P1);
1329 Normalise(Normal);
1330 }
1331
1332 XYZ ClosestPlanePoint;
1333
1334 double dDist = DotProduct(Normal, P1 - P);
1335 ClosestPlanePoint = P+Normal*dDist;
1336
1337 // Check that the point on the plane lies inside the triangle
1338
1339 if (PointInsideTriangle(P1, P2, P3, ClosestPlanePoint))
1340 {
1341 if (pTrianglePoint)
1342 *pTrianglePoint = ClosestPlanePoint;
1343 return fabs(dDist);
1344 }
1345
1346 // If not find the closest distance between each of the edges of the lines
1347 // also making sure that the closest point lies within the triangle boundaries
1348
1349 XYZ X1, X2, X3;
1350 double u1, u2, u3;
1351
1352 X1 = ShortestDistPointLine(P, P1, P2, u1);
1353 X2 = ShortestDistPointLine(P, P2, P3, u2);
1354 X3 = ShortestDistPointLine(P, P3, P1, u3);
1355
1356 double dShortestDist = -1;
1357
1358 if (u1 >= 0 && u1 <= 1)
1359 {
1360 dDist = GetLength(X1, P);
1361 if (dDist < dShortestDist || dShortestDist < 0)
1362 {
1363 dShortestDist = dDist;
1364 if (pTrianglePoint)
1365 *pTrianglePoint = X1;
1366 }
1367 }
1368
1369 if (u2 >= 0 && u2 <= 1)
1370 {
1371 dDist = GetLength(X2, P);
1372 if (dDist < dShortestDist || dShortestDist < 0)
1373 {
1374 dShortestDist = dDist;
1375 if (pTrianglePoint)
1376 *pTrianglePoint = X2;
1377 }
1378 }
1379
1380 if (u3 >= 0 && u3 <= 1)
1381 {
1382 dDist = GetLength(X3, P);
1383 if (dDist < dShortestDist || dShortestDist < 0)
1384 {
1385 dShortestDist = dDist;
1386 if (pTrianglePoint)
1387 *pTrianglePoint = X3;
1388 }
1389 }
1390
1391 // Also check for the closest corner, and take the shortest of all
1392
1393 dDist = GetLength(P1, P);
1394 if (dDist < dShortestDist || dShortestDist < 0)
1395 {
1396 dShortestDist = dDist;
1397 if (pTrianglePoint)
1398 *pTrianglePoint = P1;
1399 }
1400
1401 dDist = GetLength(P2, P);
1402 if (dDist < dShortestDist || dShortestDist < 0)
1403 {
1404 dShortestDist = dDist;
1405 if (pTrianglePoint)
1406 *pTrianglePoint = P2;
1407 }
1408
1409 dDist = GetLength(P3, P);
1410 if (dDist < dShortestDist || dShortestDist < 0)
1411 {
1412 dShortestDist = dDist;
1413 if (pTrianglePoint)
1414 *pTrianglePoint = P3;
1415 }
1416
1417 return dShortestDist;
1418 }
1419
1421 inline XYZ GetBarycentricCoordinates(const XY &P1, const XY &P2, const XY &P3, const XY &P)
1422 {
1423 XYZ Coordinates;
1424 double denom = (-P1.x * P3.y - P2.x * P1.y + P2.x * P3.y + P1.y * P3.x + P2.y * P1.x - P2.y * P3.x);
1425
1426 if (fabs(denom) >= 1e-6)
1427 {
1428 Coordinates.x = (P2.x * P3.y - P2.y * P3.x - P.x * P3.y + P3.x * P.y - P2.x * P.y + P2.y * P.x) / denom;
1429 Coordinates.y = -(-P1.x * P.y + P1.x * P3.y + P1.y * P.x - P.x * P3.y + P3.x * P.y - P1.y * P3.x) / denom;
1430 // Coordinates.z = (-P1.x * P.y + P2.y * P1.x + P2.x * P.y - P2.x * P1.y - P2.y * P.x + P1.y * P.x) / denom;
1431 }
1432 Coordinates.z = 1 - Coordinates.x - Coordinates.y;
1433
1434 return Coordinates;
1435 }
1436
1439 inline int GetClosestPointIndex( const std::vector<XY> &Points, const XY Position)
1440 {
1441 std::vector<XY>::const_iterator itPoint;
1442 double dClosestDistSqrd = -1;
1443 double dDistSqrd;
1444 int iClosestIndex = -1, i;
1445 for (itPoint = Points.begin(), i=0; itPoint != Points.end(); ++itPoint, ++i)
1446 {
1447 dDistSqrd = GetLengthSquared(Position, *itPoint);
1448 if ( dDistSqrd < dClosestDistSqrd || dClosestDistSqrd == -1 )
1449 {
1450 dClosestDistSqrd = dDistSqrd;
1451 iClosestIndex = i;
1452 }
1453 }
1454 return iClosestIndex;
1455 }
1456
1459 inline int GetClosestPointWithinTol(const std::vector<XY> &Points, const XY Position, double dTol )
1460 {
1461 std::vector<XY>::const_iterator itPoint;
1462 double dClosestDistSqrd = -1;
1463 double dDistSqrd;
1464 int iClosestIndex = -1, i;
1465 for (itPoint = Points.begin(), i=0; itPoint != Points.end(); ++itPoint, ++i)
1466 {
1467 dDistSqrd = GetLengthSquared(Position, *itPoint);
1468 if ( dDistSqrd < dClosestDistSqrd || dClosestDistSqrd == -1 )
1469 {
1470 dClosestDistSqrd = dDistSqrd;
1471 if ( dClosestDistSqrd <= dTol )
1472 iClosestIndex = i;
1473 }
1474 }
1475 return iClosestIndex;
1476 }
1477
1480 inline XY GetClosestPoint( const std::vector<XY> &Points, const XY Position)
1481 {
1482 int index = GetClosestPointIndex( Points, Position );
1483 int iSize = (int)Points.size();
1484 int iNextInd = (index+1)%iSize;
1485 int iPrevInd;
1486 XYZ Pos(Position.x, Position.y, 0);
1487 XYZ p1(Points[index].x, Points[index].y, 0);
1488
1489 XYZ p2(Points[iNextInd].x, Points[iNextInd].y, 0);
1490
1491 if ( index )
1492 iPrevInd = index-1;
1493 else
1494 iPrevInd = Points[0] == Points[iSize-1] ? iSize-2 : iSize-1; // Check if closed loop
1495 XYZ p3(Points[iPrevInd].x, Points[iPrevInd].y, 0);
1496
1497 double dDist1 = GetLength(Pos, p2);
1498 double dDist2 = GetLength(Pos, p3);
1499 XYZ comp = dDist1 < dDist2 ? p2 : p3;
1500 double dU = 0.0;
1501
1502 XYZ pClosest = ShortestDistPointLine( Pos, p1, comp, dU );
1503 return XY(pClosest.x, pClosest.y);
1504 }
1505
1508 inline int GetClosestPointIndex( const std::vector<XYZ> &Points, const XYZ Position)
1509 {
1510 std::vector<XYZ>::const_iterator itPoint;
1511 double dClosestDistSqrd = -1;
1512 double dDistSqrd;
1513 int iClosestIndex = -1, i;
1514 for (itPoint = Points.begin(), i=0; itPoint != Points.end(); ++itPoint, ++i)
1515 {
1516 dDistSqrd = GetLengthSquared(Position, *itPoint);
1517 if ( dDistSqrd < dClosestDistSqrd || dClosestDistSqrd == -1 )
1518 {
1519 dClosestDistSqrd = dDistSqrd;
1520 iClosestIndex = i;
1521 }
1522 }
1523 return iClosestIndex;
1524 }
1525
1528 inline int GetClosestPointWithinTol(const std::vector<XYZ> &Points, const XYZ Position, double dTol )
1529 {
1530 std::vector<XYZ>::const_iterator itPoint;
1531 double dClosestDistSqrd = -1;
1532 double dDistSqrd;
1533 int iClosestIndex = -1, i;
1534 for (itPoint = Points.begin(), i=0; itPoint != Points.end(); ++itPoint, ++i)
1535 {
1536 dDistSqrd = GetLengthSquared(Position, *itPoint);
1537 if ( dDistSqrd < dClosestDistSqrd || dClosestDistSqrd == -1 )
1538 {
1539 dClosestDistSqrd = dDistSqrd;
1540 if ( dClosestDistSqrd <= dTol )
1541 iClosestIndex = i;
1542 }
1543 }
1544 return iClosestIndex;
1545 }
1546
1549 inline XYZ GetClosestPoint( const std::vector<XYZ> &Points, const XYZ Position)
1550 {
1551 int index = GetClosestPointIndex( Points, Position );
1552 int iSize = (int)Points.size();
1553 int iNextInd = (index+1)%iSize;
1554 int iPrevInd;
1555
1556 XYZ p1(Points[index].x, Points[index].y, Points[index].z);
1557
1558 XYZ p2(Points[iNextInd].x, Points[iNextInd].y, Points[iNextInd].z);
1559
1560 if ( index )
1561 iPrevInd = index-1;
1562 else
1563 iPrevInd = Points[0] == Points[iSize-1] ? iSize-2 : iSize-1; // Check if closed loop
1564 XYZ p3(Points[iPrevInd].x, Points[iPrevInd].y, Points[iPrevInd].z);
1565
1566 double dDist1 = GetLength(Position, p2);
1567 double dDist2 = GetLength(Position, p3);
1568 XYZ comp = dDist1 < dDist2 ? p2 : p3;
1569 double dU = 0.0;
1570
1571 return ShortestDistPointLine( Position, p1, comp, dU );
1572 }
1573
1574 inline bool PointInside(const XY &Point, const std::vector<XY> &Nodes)
1575 {
1576 // Algorithm borrowed from http://paulbourke.net/geometry/polygonmesh/
1577
1578 int counter = 0;
1579 int i, N = (int)Nodes.size();
1580 double xinters;
1581 XY p1, p2;
1582 p1 = Nodes[0];
1583 for (i = 1;i <= N;i++)
1584 {
1585 p2 = Nodes[i % N];
1586 if (Point.y > std::min(p1.y, p2.y))
1587 {
1588 if (Point.y <= std::max(p1.y, p2.y))
1589 {
1590 if (Point.x <= std::max(p1.x, p2.x))
1591 {
1592 if (p1.y != p2.y)
1593 {
1594 xinters = (Point.y - p1.y)*(p2.x - p1.x) / (p2.y - p1.y) + p1.x;
1595 if (p1.x == p2.x || Point.x <= xinters)
1596 counter++;
1597 }
1598 }
1599 }
1600 }
1601 p1 = p2;
1602 }
1603
1604 if (counter % 2 == 1)
1605 return true;
1606 else
1607 return false;
1608 }
1609
1610 inline bool PointInside(const XY &Point, std::vector<XYZ> &Nodes)
1611 {
1612 // Algorithm borrowed from http://paulbourke.net/geometry/polygonmesh/
1613
1614 int counter = 0;
1615 int i, N = (int)Nodes.size();
1616 double xinters;
1617 XYZ p1, p2;
1618 p1 = Nodes[0];
1619 for (i = 1;i <= N;i++)
1620 {
1621 p2 = Nodes[i % N];
1622 if (Point.y > std::min(p1.y, p2.y))
1623 {
1624 if (Point.y <= std::max(p1.y, p2.y))
1625 {
1626 if (Point.x <= std::max(p1.x, p2.x))
1627 {
1628 if (p1.y != p2.y)
1629 {
1630 xinters = (Point.y - p1.y)*(p2.x - p1.x) / (p2.y - p1.y) + p1.x;
1631 if (p1.x == p2.x || Point.x <= xinters)
1632 counter++;
1633 }
1634 }
1635 }
1636 }
1637 p1 = p2;
1638 }
1639
1640 if (counter % 2 == 1)
1641 return true;
1642 else
1643 return false;
1644 }
1645
1646}; // namespace TexGen
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
#define NULL
Definition: ShinyConfig.h:50
Namespace containing a series of customised math operations not found in the standard c++ library.
double PointInsideTriangleAccuracy(const XYZ &P1, const XYZ &P2, const XYZ &P3, const XYZ &P, const XYZ &N)
P1, P2, P3 are the three triangle corners, P is the points to be tested, N is the normal to the trian...
Definition: mymath.h:1285
bool SphereSphereIntersect(const XYZ &p1, const XYZ &p2, double dRadii)
Check if two spheres intersect given their center points and combined radii.
Definition: mymath.h:741
void GetFractionColor(double dFraction, double &r, double &g, double &b)
Definition: mymath.h:1077
bool SphereCylinderIntersect(const XYZ &Point, const XYZ &LineStart, const XYZ &LineEnd, double dRadii, double *pdUReturn=NULL)
Definition: mymath.h:768
XYZ GetBarycentricCoordinates(const XY &P1, const XY &P2, const XY &P3, const XY &P)
Get the barycentric coordinates of a point lying on a triangle.
Definition: mymath.h:1421
bool GetCircleCenter(const XYZ &A, const XYZ &B, const XYZ &C, XYZ &Center)
Definition: mymath.h:1109
double GetLengthSquared(const XYZ &Point1, const XYZ &Point2)
Get the length squared between two points.
Definition: mymath.h:548
double RandomNormalDistribution(double dStandrdDeviation=1, double dAverage=0)
Definition: mymath.h:1190
WXYZ & operator-=(WXYZ &left, const WXYZ &right)
Definition: mymath.h:242
WXYZ & operator*=(WXYZ &left, const WXYZ &right)
Grassmann product multiplication between two quaternions.
Definition: mymath.h:305
bool RoundedCylinderIntersect(const XYZ &p1, const XYZ &p2, const XYZ &p3, const XYZ &p4, double dRadii, double *pdU1=NULL, double *pdU2=NULL)
Definition: mymath.h:862
void GetRandomColor(double &r, double &g, double &b)
Create a random color from a set of pre-defined colors.
Definition: mymath.h:1043
WXYZ & operator+=(WXYZ &left, const WXYZ &right)
Definition: mymath.h:191
XYZ operator/(const XYZ &left, const XYZ &right)
Do a simple divide of all members, perhaps not mathematically correct but usefull.
Definition: mymath.h:295
bool GetIntersectionLinePlane(const XYZ &p1, const XYZ &p2, const XYZ &p3, const XYZ &N, XYZ &Intersection, double *pdU=NULL)
P1 and P2 are two points on the line, P3 is a point on the plane, N is the plane normal,...
Definition: mymath.h:1025
std::istream & operator>>(std::istream &input, WXYZ &Quat)
Definition: mymath.h:487
XYZ ShortestDistPointLine(const XYZ &Point, const XYZ &LineStart, const XYZ &LineEnd, double &dU)
Definition: mymath.h:749
int Round(double dValue)
Definition: mymath.h:1169
void GetLocalCoordinateSystem(XYZ &LocalX, XYZ &LocalY, XYZ &LocalZ, const XYZ &Point1, const XYZ &Point2)
Definition: mymath.h:1007
WXYZ operator+(const WXYZ &left, const WXYZ &right)
Definition: mymath.h:164
XYZ operator*(const CMatrix &Transform, const XYZ &Vector)
Definition: MatrixUtils.h:49
bool LineLineIntersect2D(const XY &p1, const XY &p2, const XY &p3, const XY &p4, double &dU1, double &dU2)
Definition: mymath.h:797
XY GetClosestPoint(const std::vector< XY > &Points, const XY Position)
Definition: mymath.h:1480
bool operator==(const XYZ &left, const XYZ &right)
Definition: mymath.h:149
int GetClosestPointWithinTol(const std::vector< XY > &Points, const XY Position, double dTol)
Definition: mymath.h:1459
bool PointInside(const XY &Point, const std::vector< XY > &Nodes)
Definition: mymath.h:1574
WXYZ & operator/=(WXYZ &left, const double &right)
Definition: mymath.h:418
double RandomNumber(double dMin, double dMax)
Generate a random number between the limits given.
Definition: mymath.h:534
WXYZ operator-(const WXYZ &left, const WXYZ &right)
Definition: mymath.h:215
int GetClosestPointIndex(const std::vector< XY > &Points, const XY Position)
Definition: mymath.h:1439
double Max(XYZ &Vector)
Get maximum element of vector and return it.
Definition: mymath.h:642
bool PointInsideBox(const XYZ &Point, const XYZ &BoxMin, const XYZ &BoxMax, double dTolerance=0)
Find if a point is inside an Axis Aligned Bounding Box with given tolerance.
Definition: mymath.h:988
bool PointInsideTriangle2D(const XYZ &P1, const XYZ &P2, const XYZ &P3, const XYZ &P, const XYZ *pNormal=NULL)
P1, P2, P3 are the three triangle corners, P is the points to be tested, ignoring the z component.
Definition: mymath.h:1296
bool ShortestDistLineLine(const XYZ &p1, const XYZ &p2, const XYZ &p3, const XYZ &p4, double &dU1, double &dU2, XYZ &pa, XYZ &pb)
Definition: mymath.h:818
XY Convert(const XYZ &Val)
Definition: mymath.h:144
double GetLength(const XYZ &Point1, const XYZ &Point2)
Get the length between two points.
Definition: mymath.h:540
T CalculateBezierTangent(T p1, T p2, T p3, T p4, double mu)
Definition: mymath.h:1183
XYZ Min(const XYZ &P1, const XYZ &P2)
Given two points, return a new point who's coordinates are the smaller of the two.
Definition: mymath.h:1142
ostream & operator<<(ostream &output, CMatrix &Matrix)
Definition: Matrix.h:455
WXYZ & Normalise(WXYZ &Quaternion)
Normalise the quaternion and return it.
Definition: mymath.h:609
bool BoundingBoxIntersect(const XYZ &BBox1Min, const XYZ &BBox1Max, const XYZ &BBox2Min, const XYZ &BBox2Max, double dTolerance=0)
Find if two AABBs intersect with given tolerance.
Definition: mymath.h:970
double ShortestDistPointTriangle(const XYZ &P1, const XYZ &P2, const XYZ &P3, const XYZ &P, XYZ *pTrianglePoint=NULL, XYZ *pNormal=NULL)
P1, P2, P3 are the three triangle corners, P is the points to be tested.
Definition: mymath.h:1316
double DotProduct(const XYZ &left, const XYZ &right)
Get the dot product of two vectors.
Definition: mymath.h:512
XYZ CrossProduct(const XYZ &left, const XYZ &right)
Get the cross product of two vectors.
Definition: mymath.h:524
double GetArea(XYZ Points[], int iNumPoints)
Definition: mymath.h:1245
T CalculateBezierPoint(T p1, T p2, T p3, T p4, double mu)
Definition: mymath.h:1175
bool PointInsideTriangle(const XYZ &P1, const XYZ &P2, const XYZ &P3, const XYZ &P)
P1, P2, P3 are the three triangle corners, P is the points to be tested.
Definition: mymath.h:1260
Struct for representing a quaternion.
Definition: mymath.h:38
double z
Definition: mymath.h:39
WXYZ(double Coords[4])
Set coordinates to those specified in the constructor.
Definition: mymath.h:45
WXYZ(double W, double X, double Y, double Z)
Set coordinates to those specified in the constructor.
Definition: mymath.h:43
double w
Definition: mymath.h:39
double y
Definition: mymath.h:39
double x
Definition: mymath.h:39
WXYZ()
Set all coordinates to 0 as default constructor.
Definition: mymath.h:41
Struct for representing points in 2D space.
Definition: mymath.h:103
XY()
Set all coordinates to 0 as default constructor.
Definition: mymath.h:106
XY operator-()
Reverse all coordinates.
Definition: mymath.h:135
double x
Definition: mymath.h:104
XY(double X, double Y)
Set coordinates to those specified in the constructor.
Definition: mymath.h:108
bool operator==(const XY &right) const
Overload to see if two XY coordinates are the same.
Definition: mymath.h:112
double & operator[](int i)
Definition: mymath.h:125
double y
Definition: mymath.h:104
XY(double Coords[2])
Set coordinates to those specified in the constructor.
Definition: mymath.h:110
bool operator!() const
Check if all the coordinates are 0.
Definition: mymath.h:117
Struct for representing points in 3D space.
Definition: mymath.h:56
XYZ(double Coords[3])
Set coordinates to those specified in the constructor.
Definition: mymath.h:98
XYZ(double X, double Y, double Z)
Set coordinates to those specified in the constructor.
Definition: mymath.h:96
bool operator!() const
Check if all the coordinates are 0.
Definition: mymath.h:67
double z
Definition: mymath.h:57
double & operator[](int i)
Definition: mymath.h:75
double operator=(double right)
Set all coordinates equal to value.
Definition: mymath.h:59
XYZ operator-()
Reverse all coordinates.
Definition: mymath.h:84
double x
Definition: mymath.h:57
double y
Definition: mymath.h:57
XYZ()
Set all coordinates to 0 as default constructor.
Definition: mymath.h:94