1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 /** \file
18  * \ingroup freestyle
19  * \brief Various tools for geometry
20  */
21 
22 #include "GeomUtils.h"
23 
24 namespace Freestyle {
25 
26 namespace GeomUtils {
27 
28 // This internal procedure is defined below.
29 bool intersect2dSegPoly(Vec2r *seg, Vec2r *poly, unsigned n);
30 
intersect2dSeg2dArea(const Vec2r & min,const Vec2r & max,const Vec2r & A,const Vec2r & B)31 bool intersect2dSeg2dArea(const Vec2r &min, const Vec2r &max, const Vec2r &A, const Vec2r &B)
32 {
33   Vec2r seg[2];
34   seg[0] = A;
35   seg[1] = B;
36 
37   Vec2r poly[5];
38   poly[0][0] = min[0];
39   poly[0][1] = min[1];
40   poly[1][0] = max[0];
41   poly[1][1] = min[1];
42   poly[2][0] = max[0];
43   poly[2][1] = max[1];
44   poly[3][0] = min[0];
45   poly[3][1] = max[1];
46   poly[4][0] = min[0];
47   poly[4][1] = min[1];
48 
49   return intersect2dSegPoly(seg, poly, 4);
50 }
51 
include2dSeg2dArea(const Vec2r & min,const Vec2r & max,const Vec2r & A,const Vec2r & B)52 bool include2dSeg2dArea(const Vec2r &min, const Vec2r &max, const Vec2r &A, const Vec2r &B)
53 {
54   if ((((max[0] > A[0]) && (A[0] > min[0])) && ((max[0] > B[0]) && (B[0] > min[0]))) &&
55       (((max[1] > A[1]) && (A[1] > min[1])) && ((max[1] > B[1]) && (B[1] > min[1])))) {
56     return true;
57   }
58   return false;
59 }
60 
intersect2dSeg2dSeg(const Vec2r & p1,const Vec2r & p2,const Vec2r & p3,const Vec2r & p4,Vec2r & res)61 intersection_test intersect2dSeg2dSeg(
62     const Vec2r &p1, const Vec2r &p2, const Vec2r &p3, const Vec2r &p4, Vec2r &res)
63 {
64   real a1, a2, b1, b2, c1, c2;  // Coefficients of line eqns
65   real r1, r2, r3, r4;          // 'Sign' values
66   real denom, num;              // Intermediate values
67 
68   // Compute a1, b1, c1, where line joining points p1 and p2 is "a1 x  +  b1 y  +  c1  =  0".
69   a1 = p2[1] - p1[1];
70   b1 = p1[0] - p2[0];
71   c1 = p2[0] * p1[1] - p1[0] * p2[1];
72 
73   // Compute r3 and r4.
74   r3 = a1 * p3[0] + b1 * p3[1] + c1;
75   r4 = a1 * p4[0] + b1 * p4[1] + c1;
76 
77   // Check signs of r3 and r4.  If both point 3 and point 4 lie on same side of line 1,
78   // the line segments do not intersect.
79   if (r3 != 0 && r4 != 0 && r3 * r4 > 0.0) {
80     return DONT_INTERSECT;
81   }
82 
83   // Compute a2, b2, c2
84   a2 = p4[1] - p3[1];
85   b2 = p3[0] - p4[0];
86   c2 = p4[0] * p3[1] - p3[0] * p4[1];
87 
88   // Compute r1 and r2
89   r1 = a2 * p1[0] + b2 * p1[1] + c2;
90   r2 = a2 * p2[0] + b2 * p2[1] + c2;
91 
92   // Check signs of r1 and r2.  If both point 1 and point 2 lie on same side of second line
93   // segment, the line segments do not intersect.
94   if (r1 != 0 && r2 != 0 && r1 * r2 > 0.0) {
95     return DONT_INTERSECT;
96   }
97 
98   // Line segments intersect: compute intersection point.
99   denom = a1 * b2 - a2 * b1;
100   if (fabs(denom) < M_EPSILON) {
101     return COLINEAR;
102   }
103 
104   num = b1 * c2 - b2 * c1;
105   res[0] = num / denom;
106 
107   num = a2 * c1 - a1 * c2;
108   res[1] = num / denom;
109 
110   return DO_INTERSECT;
111 }
112 
intersect2dLine2dLine(const Vec2r & p1,const Vec2r & p2,const Vec2r & p3,const Vec2r & p4,Vec2r & res)113 intersection_test intersect2dLine2dLine(
114     const Vec2r &p1, const Vec2r &p2, const Vec2r &p3, const Vec2r &p4, Vec2r &res)
115 {
116   real a1, a2, b1, b2, c1, c2;  // Coefficients of line eqns
117   real denom, num;              // Intermediate values
118 
119   // Compute a1, b1, c1, where line joining points p1 and p2 is "a1 x  +  b1 y  +  c1  =  0".
120   a1 = p2[1] - p1[1];
121   b1 = p1[0] - p2[0];
122   c1 = p2[0] * p1[1] - p1[0] * p2[1];
123 
124   // Compute a2, b2, c2
125   a2 = p4[1] - p3[1];
126   b2 = p3[0] - p4[0];
127   c2 = p4[0] * p3[1] - p3[0] * p4[1];
128 
129   // Line segments intersect: compute intersection point.
130   denom = a1 * b2 - a2 * b1;
131   if (fabs(denom) < M_EPSILON) {
132     return COLINEAR;
133   }
134 
135   num = b1 * c2 - b2 * c1;
136   res[0] = num / denom;
137 
138   num = a2 * c1 - a1 * c2;
139   res[1] = num / denom;
140 
141   return DO_INTERSECT;
142 }
143 
intersect2dSeg2dSegParametric(const Vec2r & p1,const Vec2r & p2,const Vec2r & p3,const Vec2r & p4,real & t,real & u,real epsilon)144 intersection_test intersect2dSeg2dSegParametric(const Vec2r &p1,
145                                                 const Vec2r &p2,
146                                                 const Vec2r &p3,
147                                                 const Vec2r &p4,
148                                                 real &t,
149                                                 real &u,
150                                                 real epsilon)
151 {
152   real a1, a2, b1, b2, c1, c2;  // Coefficients of line eqns
153   real r1, r2, r3, r4;          // 'Sign' values
154   real denom, num;              // Intermediate values
155 
156   // Compute a1, b1, c1, where line joining points p1 and p2 is "a1 x  +  b1 y  +  c1  =  0".
157   a1 = p2[1] - p1[1];
158   b1 = p1[0] - p2[0];
159   c1 = p2[0] * p1[1] - p1[0] * p2[1];
160 
161   // Compute r3 and r4.
162   r3 = a1 * p3[0] + b1 * p3[1] + c1;
163   r4 = a1 * p4[0] + b1 * p4[1] + c1;
164 
165   // Check signs of r3 and r4.  If both point 3 and point 4 lie on same side of line 1,
166   // the line segments do not intersect.
167   if (r3 != 0 && r4 != 0 && r3 * r4 > 0.0) {
168     return DONT_INTERSECT;
169   }
170 
171   // Compute a2, b2, c2
172   a2 = p4[1] - p3[1];
173   b2 = p3[0] - p4[0];
174   c2 = p4[0] * p3[1] - p3[0] * p4[1];
175 
176   // Compute r1 and r2
177   r1 = a2 * p1[0] + b2 * p1[1] + c2;
178   r2 = a2 * p2[0] + b2 * p2[1] + c2;
179 
180   // Check signs of r1 and r2.  If both point 1 and point 2 lie on same side of second line
181   // segment, the line segments do not intersect.
182   if (r1 != 0 && r2 != 0 && r1 * r2 > 0.0) {
183     return DONT_INTERSECT;
184   }
185 
186   // Line segments intersect: compute intersection point.
187   denom = a1 * b2 - a2 * b1;
188   if (fabs(denom) < epsilon) {
189     return COLINEAR;
190   }
191 
192   real d1, e1;
193 
194   d1 = p1[1] - p3[1];
195   e1 = p1[0] - p3[0];
196 
197   num = -b2 * d1 - a2 * e1;
198   t = num / denom;
199 
200   num = -b1 * d1 - a1 * e1;
201   u = num / denom;
202 
203   return DO_INTERSECT;
204 }
205 
206 // AABB-triangle overlap test code by Tomas Akenine-Möller
207 // Function: int triBoxOverlap(real boxcenter[3], real boxhalfsize[3],real triverts[3][3]);
208 // History:
209 //   2001-03-05: released the code in its first version
210 //   2001-06-18: changed the order of the tests, faster
211 //
212 // Acknowledgement: Many thanks to Pierre Terdiman for suggestions and discussions on how to
213 // optimize code. Thanks to David Hunt for finding a ">="-bug!
214 
215 #define X 0
216 #define Y 1
217 #define Z 2
218 
219 #define FINDMINMAX(x0, x1, x2, min, max) \
220   { \
221     min = max = x0; \
222     if (x1 < min) { \
223       min = x1; \
224     } \
225     if (x1 > max) { \
226       max = x1; \
227     } \
228     if (x2 < min) { \
229       min = x2; \
230     } \
231     if (x2 > max) { \
232       max = x2; \
233     } \
234   } \
235   (void)0
236 
237 //======================== X-tests ========================//
238 #define AXISTEST_X01(a, b, fa, fb) \
239   { \
240     p0 = a * v0[Y] - b * v0[Z]; \
241     p2 = a * v2[Y] - b * v2[Z]; \
242     if (p0 < p2) { \
243       min = p0; \
244       max = p2; \
245     } \
246     else { \
247       min = p2; \
248       max = p0; \
249     } \
250     rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z]; \
251     if (min > rad || max < -rad) { \
252       return 0; \
253     } \
254   } \
255   (void)0
256 
257 #define AXISTEST_X2(a, b, fa, fb) \
258   { \
259     p0 = a * v0[Y] - b * v0[Z]; \
260     p1 = a * v1[Y] - b * v1[Z]; \
261     if (p0 < p1) { \
262       min = p0; \
263       max = p1; \
264     } \
265     else { \
266       min = p1; \
267       max = p0; \
268     } \
269     rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z]; \
270     if (min > rad || max < -rad) { \
271       return 0; \
272     } \
273   } \
274   (void)0
275 
276 //======================== Y-tests ========================//
277 #define AXISTEST_Y02(a, b, fa, fb) \
278   { \
279     p0 = -a * v0[X] + b * v0[Z]; \
280     p2 = -a * v2[X] + b * v2[Z]; \
281     if (p0 < p2) { \
282       min = p0; \
283       max = p2; \
284     } \
285     else { \
286       min = p2; \
287       max = p0; \
288     } \
289     rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z]; \
290     if (min > rad || max < -rad) { \
291       return 0; \
292     } \
293   } \
294   (void)0
295 
296 #define AXISTEST_Y1(a, b, fa, fb) \
297   { \
298     p0 = -a * v0[X] + b * v0[Z]; \
299     p1 = -a * v1[X] + b * v1[Z]; \
300     if (p0 < p1) { \
301       min = p0; \
302       max = p1; \
303     } \
304     else { \
305       min = p1; \
306       max = p0; \
307     } \
308     rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z]; \
309     if (min > rad || max < -rad) { \
310       return 0; \
311     } \
312   } \
313   (void)0
314 
315 //======================== Z-tests ========================//
316 #define AXISTEST_Z12(a, b, fa, fb) \
317   { \
318     p1 = a * v1[X] - b * v1[Y]; \
319     p2 = a * v2[X] - b * v2[Y]; \
320     if (p2 < p1) { \
321       min = p2; \
322       max = p1; \
323     } \
324     else { \
325       min = p1; \
326       max = p2; \
327     } \
328     rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y]; \
329     if (min > rad || max < -rad) { \
330       return 0; \
331     } \
332   } \
333   (void)0
334 
335 #define AXISTEST_Z0(a, b, fa, fb) \
336   { \
337     p0 = a * v0[X] - b * v0[Y]; \
338     p1 = a * v1[X] - b * v1[Y]; \
339     if (p0 < p1) { \
340       min = p0; \
341       max = p1; \
342     } \
343     else { \
344       min = p1; \
345       max = p0; \
346     } \
347     rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y]; \
348     if (min > rad || max < -rad) { \
349       return 0; \
350     } \
351   } \
352   (void)0
353 
354 // This internal procedure is defined below.
355 bool overlapPlaneBox(Vec3r &normal, real d, Vec3r &maxbox);
356 
357 // Use separating axis theorem to test overlap between triangle and box need to test for overlap in
358 // these directions: 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle we
359 // do not even need to test these) 2) normal of the triangle 3) crossproduct(edge from tri,
360 // {x,y,z}-directin) this gives 3x3=9 more tests
overlapTriangleBox(Vec3r & boxcenter,Vec3r & boxhalfsize,Vec3r triverts[3])361 bool overlapTriangleBox(Vec3r &boxcenter, Vec3r &boxhalfsize, Vec3r triverts[3])
362 {
363   Vec3r v0, v1, v2, normal, e0, e1, e2;
364   real min, max, d, p0, p1, p2, rad, fex, fey, fez;
365 
366   // This is the fastest branch on Sun
367   // move everything so that the boxcenter is in (0, 0, 0)
368   v0 = triverts[0] - boxcenter;
369   v1 = triverts[1] - boxcenter;
370   v2 = triverts[2] - boxcenter;
371 
372   // compute triangle edges
373   e0 = v1 - v0;
374   e1 = v2 - v1;
375   e2 = v0 - v2;
376 
377   // Bullet 3:
378   // Do the 9 tests first (this was faster)
379   fex = fabs(e0[X]);
380   fey = fabs(e0[Y]);
381   fez = fabs(e0[Z]);
382   AXISTEST_X01(e0[Z], e0[Y], fez, fey);
383   AXISTEST_Y02(e0[Z], e0[X], fez, fex);
384   AXISTEST_Z12(e0[Y], e0[X], fey, fex);
385 
386   fex = fabs(e1[X]);
387   fey = fabs(e1[Y]);
388   fez = fabs(e1[Z]);
389   AXISTEST_X01(e1[Z], e1[Y], fez, fey);
390   AXISTEST_Y02(e1[Z], e1[X], fez, fex);
391   AXISTEST_Z0(e1[Y], e1[X], fey, fex);
392 
393   fex = fabs(e2[X]);
394   fey = fabs(e2[Y]);
395   fez = fabs(e2[Z]);
396   AXISTEST_X2(e2[Z], e2[Y], fez, fey);
397   AXISTEST_Y1(e2[Z], e2[X], fez, fex);
398   AXISTEST_Z12(e2[Y], e2[X], fey, fex);
399 
400   // Bullet 1:
401   // first test overlap in the {x,y,z}-directions
402   // find min, max of the triangle each direction, and test for overlap in that direction -- this
403   // is equivalent to testing a minimal AABB around the triangle against the AABB
404 
405   // test in X-direction
406   FINDMINMAX(v0[X], v1[X], v2[X], min, max);
407   if (min > boxhalfsize[X] || max < -boxhalfsize[X]) {
408     return false;
409   }
410 
411   // test in Y-direction
412   FINDMINMAX(v0[Y], v1[Y], v2[Y], min, max);
413   if (min > boxhalfsize[Y] || max < -boxhalfsize[Y]) {
414     return false;
415   }
416 
417   // test in Z-direction
418   FINDMINMAX(v0[Z], v1[Z], v2[Z], min, max);
419   if (min > boxhalfsize[Z] || max < -boxhalfsize[Z]) {
420     return false;
421   }
422 
423   // Bullet 2:
424   // test if the box intersects the plane of the triangle
425   // compute plane equation of triangle: normal * x + d = 0
426   normal = e0 ^ e1;
427   d = -(normal * v0);  // plane eq: normal.x + d = 0
428   if (!overlapPlaneBox(normal, d, boxhalfsize)) {
429     return false;
430   }
431 
432   return true;  // box and triangle overlaps
433 }
434 
435 // Fast, Minimum Storage Ray-Triangle Intersection
436 //
437 // Tomas Möller
438 // Prosolvia Clarus AB
439 // Sweden
440 // tompa@clarus.se
441 //
442 // Ben Trumbore
443 // Cornell University
444 // Ithaca, New York
445 // wbt@graphics.cornell.edu
intersectRayTriangle(const Vec3r & orig,const Vec3r & dir,const Vec3r & v0,const Vec3r & v1,const Vec3r & v2,real & t,real & u,real & v,const real epsilon)446 bool intersectRayTriangle(const Vec3r &orig,
447                           const Vec3r &dir,
448                           const Vec3r &v0,
449                           const Vec3r &v1,
450                           const Vec3r &v2,
451                           real &t,
452                           real &u,
453                           real &v,
454                           const real epsilon)
455 {
456   Vec3r edge1, edge2, tvec, pvec, qvec;
457   real det, inv_det;
458 
459   // find vectors for two edges sharing v0
460   edge1 = v1 - v0;
461   edge2 = v2 - v0;
462 
463   // begin calculating determinant - also used to calculate U parameter
464   pvec = dir ^ edge2;
465 
466   // if determinant is near zero, ray lies in plane of triangle
467   det = edge1 * pvec;
468 
469   // calculate distance from v0 to ray origin
470   tvec = orig - v0;
471   inv_det = 1.0 / det;
472 
473   qvec = tvec ^ edge1;
474 
475   if (det > epsilon) {
476     u = tvec * pvec;
477     if (u < 0.0 || u > det) {
478       return false;
479     }
480 
481     // calculate V parameter and test bounds
482     v = dir * qvec;
483     if (v < 0.0 || u + v > det) {
484       return false;
485     }
486   }
487   else if (det < -epsilon) {
488     // calculate U parameter and test bounds
489     u = tvec * pvec;
490     if (u > 0.0 || u < det) {
491       return false;
492     }
493 
494     // calculate V parameter and test bounds
495     v = dir * qvec;
496     if (v > 0.0 || u + v < det) {
497       return false;
498     }
499   }
500   else {
501     return false;  // ray is parallel to the plane of the triangle
502   }
503 
504   u *= inv_det;
505   v *= inv_det;
506   t = (edge2 * qvec) * inv_det;
507 
508   return true;
509 }
510 
511 // Intersection between plane and ray, adapted from Graphics Gems, Didier Badouel
512 // The plane is represented by a set of points P implicitly defined as dot(norm, P) + d = 0.
513 // The ray is represented as r(t) = orig + dir * t.
intersectRayPlane(const Vec3r & orig,const Vec3r & dir,const Vec3r & norm,const real d,real & t,const real epsilon)514 intersection_test intersectRayPlane(const Vec3r &orig,
515                                     const Vec3r &dir,
516                                     const Vec3r &norm,
517                                     const real d,
518                                     real &t,
519                                     const real epsilon)
520 {
521   real denom = norm * dir;
522 
523   if (fabs(denom) <= epsilon) {  // plane and ray are parallel
524     if (fabs((norm * orig) + d) <= epsilon) {
525       return COINCIDENT;  // plane and ray are coincident
526     }
527 
528     return COLINEAR;
529   }
530 
531   t = -(d + (norm * orig)) / denom;
532 
533   if (t < 0.0f) {
534     return DONT_INTERSECT;
535   }
536 
537   return DO_INTERSECT;
538 }
539 
intersectRayBBox(const Vec3r & orig,const Vec3r & dir,const Vec3r & boxMin,const Vec3r & boxMax,real t0,real t1,real & tmin,real & tmax,real)540 bool intersectRayBBox(const Vec3r &orig,
541                       const Vec3r &dir,  // ray origin and direction
542                       const Vec3r &boxMin,
543                       const Vec3r &boxMax,  // the bbox
544                       real t0,
545                       real t1,
546                       real &tmin,  // I0 = orig + tmin * dir is the first intersection
547                       real &tmax,  // I1 = orig + tmax * dir is the second intersection
548                       real /*epsilon*/)
549 {
550   float tymin, tymax, tzmin, tzmax;
551   Vec3r inv_direction(1.0 / dir[0], 1.0 / dir[1], 1.0 / dir[2]);
552   int sign[3];
553   sign[0] = (inv_direction.x() < 0);
554   sign[1] = (inv_direction.y() < 0);
555   sign[2] = (inv_direction.z() < 0);
556 
557   Vec3r bounds[2];
558   bounds[0] = boxMin;
559   bounds[1] = boxMax;
560 
561   tmin = (bounds[sign[0]].x() - orig.x()) * inv_direction.x();
562   tmax = (bounds[1 - sign[0]].x() - orig.x()) * inv_direction.x();
563   tymin = (bounds[sign[1]].y() - orig.y()) * inv_direction.y();
564   tymax = (bounds[1 - sign[1]].y() - orig.y()) * inv_direction.y();
565   if ((tmin > tymax) || (tymin > tmax)) {
566     return false;
567   }
568   if (tymin > tmin) {
569     tmin = tymin;
570   }
571   if (tymax < tmax) {
572     tmax = tymax;
573   }
574   tzmin = (bounds[sign[2]].z() - orig.z()) * inv_direction.z();
575   tzmax = (bounds[1 - sign[2]].z() - orig.z()) * inv_direction.z();
576   if ((tmin > tzmax) || (tzmin > tmax)) {
577     return false;
578   }
579   if (tzmin > tmin) {
580     tmin = tzmin;
581   }
582   if (tzmax < tmax) {
583     tmax = tzmax;
584   }
585   return ((tmin < t1) && (tmax > t0));
586 }
587 
588 // Checks whether 3D points p lies inside or outside of the triangle ABC
includePointTriangle(const Vec3r & P,const Vec3r & A,const Vec3r & B,const Vec3r & C)589 bool includePointTriangle(const Vec3r &P, const Vec3r &A, const Vec3r &B, const Vec3r &C)
590 {
591   Vec3r AB(B - A);
592   Vec3r BC(C - B);
593   Vec3r CA(A - C);
594   Vec3r AP(P - A);
595   Vec3r BP(P - B);
596   Vec3r CP(P - C);
597 
598   Vec3r N(AB ^ BC);  // triangle's normal
599 
600   N.normalize();
601 
602   Vec3r J(AB ^ AP), K(BC ^ BP), L(CA ^ CP);
603   J.normalize();
604   K.normalize();
605   L.normalize();
606 
607   if (J * N < 0) {
608     return false;  // on the right of AB
609   }
610 
611   if (K * N < 0) {
612     return false;  // on the right of BC
613   }
614 
615   if (L * N < 0) {
616     return false;  // on the right of CA
617   }
618 
619   return true;
620 }
621 
transformVertex(const Vec3r & vert,const Matrix44r & matrix,Vec3r & res)622 void transformVertex(const Vec3r &vert, const Matrix44r &matrix, Vec3r &res)
623 {
624   HVec3r hvert(vert), res_tmp;
625   real scale;
626   for (unsigned int j = 0; j < 4; j++) {
627     scale = hvert[j];
628     for (unsigned int i = 0; i < 4; i++) {
629       res_tmp[i] += matrix(i, j) * scale;
630     }
631   }
632 
633   res[0] = res_tmp.x();
634   res[1] = res_tmp.y();
635   res[2] = res_tmp.z();
636 }
637 
transformVertices(const vector<Vec3r> & vertices,const Matrix44r & trans,vector<Vec3r> & res)638 void transformVertices(const vector<Vec3r> &vertices, const Matrix44r &trans, vector<Vec3r> &res)
639 {
640   size_t i;
641   res.resize(vertices.size());
642   for (i = 0; i < vertices.size(); i++) {
643     transformVertex(vertices[i], trans, res[i]);
644   }
645 }
646 
rotateVector(const Matrix44r & mat,const Vec3r & v)647 Vec3r rotateVector(const Matrix44r &mat, const Vec3r &v)
648 {
649   Vec3r res;
650   for (unsigned int i = 0; i < 3; i++) {
651     res[i] = 0;
652     for (unsigned int j = 0; j < 3; j++) {
653       res[i] += mat(i, j) * v[j];
654     }
655   }
656   res.normalize();
657   return res;
658 }
659 
660 // This internal procedure is defined below.
661 void fromCoordAToCoordB(const Vec3r &p, Vec3r &q, const real transform[4][4]);
662 
fromWorldToCamera(const Vec3r & p,Vec3r & q,const real model_view_matrix[4][4])663 void fromWorldToCamera(const Vec3r &p, Vec3r &q, const real model_view_matrix[4][4])
664 {
665   fromCoordAToCoordB(p, q, model_view_matrix);
666 }
667 
fromCameraToRetina(const Vec3r & p,Vec3r & q,const real projection_matrix[4][4])668 void fromCameraToRetina(const Vec3r &p, Vec3r &q, const real projection_matrix[4][4])
669 {
670   fromCoordAToCoordB(p, q, projection_matrix);
671 }
672 
fromRetinaToImage(const Vec3r & p,Vec3r & q,const int viewport[4])673 void fromRetinaToImage(const Vec3r &p, Vec3r &q, const int viewport[4])
674 {
675   // winX:
676   q[0] = viewport[0] + viewport[2] * (p[0] + 1.0) / 2.0;
677 
678   // winY:
679   q[1] = viewport[1] + viewport[3] * (p[1] + 1.0) / 2.0;
680 
681   // winZ:
682   q[2] = (p[2] + 1.0) / 2.0;
683 }
684 
fromWorldToImage(const Vec3r & p,Vec3r & q,const real model_view_matrix[4][4],const real projection_matrix[4][4],const int viewport[4])685 void fromWorldToImage(const Vec3r &p,
686                       Vec3r &q,
687                       const real model_view_matrix[4][4],
688                       const real projection_matrix[4][4],
689                       const int viewport[4])
690 {
691   Vec3r p1, p2;
692   fromWorldToCamera(p, p1, model_view_matrix);
693   fromCameraToRetina(p1, p2, projection_matrix);
694   fromRetinaToImage(p2, q, viewport);
695   q[2] = p1[2];
696 }
697 
fromWorldToImage(const Vec3r & p,Vec3r & q,const real transform[4][4],const int viewport[4])698 void fromWorldToImage(const Vec3r &p, Vec3r &q, const real transform[4][4], const int viewport[4])
699 {
700   fromCoordAToCoordB(p, q, transform);
701 
702   // winX:
703   q[0] = viewport[0] + viewport[2] * (q[0] + 1.0) / 2.0;
704 
705   // winY:
706   q[1] = viewport[1] + viewport[3] * (q[1] + 1.0) / 2.0;
707 }
708 
fromImageToRetina(const Vec3r & p,Vec3r & q,const int viewport[4])709 void fromImageToRetina(const Vec3r &p, Vec3r &q, const int viewport[4])
710 {
711   q = p;
712   q[0] = 2.0 * (q[0] - viewport[0]) / viewport[2] - 1.0;
713   q[1] = 2.0 * (q[1] - viewport[1]) / viewport[3] - 1.0;
714 }
715 
fromRetinaToCamera(const Vec3r & p,Vec3r & q,real focal,const real projection_matrix[4][4])716 void fromRetinaToCamera(const Vec3r &p, Vec3r &q, real focal, const real projection_matrix[4][4])
717 {
718   if (projection_matrix[3][3] == 0.0) {  // perspective
719     q[0] = (-p[0] * focal) / projection_matrix[0][0];
720     q[1] = (-p[1] * focal) / projection_matrix[1][1];
721     q[2] = focal;
722   }
723   else {  // orthogonal
724     q[0] = p[0] / projection_matrix[0][0];
725     q[1] = p[1] / projection_matrix[1][1];
726     q[2] = focal;
727   }
728 }
729 
fromCameraToWorld(const Vec3r & p,Vec3r & q,const real model_view_matrix[4][4])730 void fromCameraToWorld(const Vec3r &p, Vec3r &q, const real model_view_matrix[4][4])
731 {
732   real translation[3] = {
733       model_view_matrix[0][3],
734       model_view_matrix[1][3],
735       model_view_matrix[2][3],
736   };
737   for (unsigned short i = 0; i < 3; i++) {
738     q[i] = 0.0;
739     for (unsigned short j = 0; j < 3; j++) {
740       q[i] += model_view_matrix[j][i] * (p[j] - translation[j]);
741     }
742   }
743 }
744 
745 //
746 // Internal code
747 //
748 /////////////////////////////////////////////////////////////////////////////
749 
750 // Copyright 2001, softSurfer (www.softsurfer.com)
751 // This code may be freely used and modified for any purpose providing that this copyright notice
752 // is included with it. SoftSurfer makes no warranty for this code, and cannot be held liable for
753 // any real or imagined damage resulting from its use. Users of this code must verify correctness
754 // for their application.
755 
756 #define PERP(u, v) ((u)[0] * (v)[1] - (u)[1] * (v)[0])  // 2D perp product
757 
intersect2dSegPoly(Vec2r * seg,Vec2r * poly,unsigned n)758 inline bool intersect2dSegPoly(Vec2r *seg, Vec2r *poly, unsigned n)
759 {
760   if (seg[0] == seg[1]) {
761     return false;
762   }
763 
764   real tE = 0;                   // the maximum entering segment parameter
765   real tL = 1;                   // the minimum leaving segment parameter
766   real t, N, D;                  // intersect parameter t = N / D
767   Vec2r dseg = seg[1] - seg[0];  // the segment direction vector
768   Vec2r e;                       // edge vector
769 
770   for (unsigned int i = 0; i < n; i++) {  // process polygon edge poly[i]poly[i+1]
771     e = poly[i + 1] - poly[i];
772     N = PERP(e, seg[0] - poly[i]);
773     D = -PERP(e, dseg);
774     if (fabs(D) < M_EPSILON) {
775       if (N < 0) {
776         return false;
777       }
778 
779       continue;
780     }
781 
782     t = N / D;
783     if (D < 0) {     // segment seg is entering across this edge
784       if (t > tE) {  // new max tE
785         tE = t;
786         if (tE > tL) {  // seg enters after leaving polygon
787           return false;
788         }
789       }
790     }
791     else {           // segment seg is leaving across this edge
792       if (t < tL) {  // new min tL
793         tL = t;
794         if (tL < tE) {  // seg leaves before entering polygon
795           return false;
796         }
797       }
798     }
799   }
800 
801   // tE <= tL implies that there is a valid intersection subsegment
802   return true;
803 }
804 
overlapPlaneBox(Vec3r & normal,real d,Vec3r & maxbox)805 inline bool overlapPlaneBox(Vec3r &normal, real d, Vec3r &maxbox)
806 {
807   Vec3r vmin, vmax;
808 
809   for (unsigned int q = X; q <= Z; q++) {
810     if (normal[q] > 0.0f) {
811       vmin[q] = -maxbox[q];
812       vmax[q] = maxbox[q];
813     }
814     else {
815       vmin[q] = maxbox[q];
816       vmax[q] = -maxbox[q];
817     }
818   }
819   if ((normal * vmin) + d > 0.0f) {
820     return false;
821   }
822   if ((normal * vmax) + d >= 0.0f) {
823     return true;
824   }
825   return false;
826 }
827 
fromCoordAToCoordB(const Vec3r & p,Vec3r & q,const real transform[4][4])828 inline void fromCoordAToCoordB(const Vec3r &p, Vec3r &q, const real transform[4][4])
829 {
830   HVec3r hp(p);
831   HVec3r hq(0, 0, 0, 0);
832 
833   for (unsigned int i = 0; i < 4; i++) {
834     for (unsigned int j = 0; j < 4; j++) {
835       hq[i] += transform[i][j] * hp[j];
836     }
837   }
838 
839   if (hq[3] == 0) {
840     q = p;
841     return;
842   }
843 
844   for (unsigned int k = 0; k < 3; k++) {
845     q[k] = hq[k] / hq[3];
846   }
847 }
848 
849 }  // end of namespace GeomUtils
850 
851 } /* namespace Freestyle */
852