88 #include "Primitive.h"
89 #include "AxisAlignedBox.h"
90 #include "PrimitivePositioning.h"
99 double PrimitivePositioning::_EPS = 0.00001 ;
104 int PrimitivePositioning::computeRelativePosition(
const Primitive *p1,
const Primitive *p2)
111 if( bb1.maxi().x() < bb2.mini().x() || bb1.mini().x() > bb2.maxi().x())
return Independent ;
112 if( bb1.maxi().y() < bb2.mini().y() || bb1.mini().y() > bb2.maxi().y())
return Independent ;
116 if(p1->nbVertices() >= 3)
117 if(p2->nbVertices() >= 3)
118 return computeRelativePosition( dynamic_cast<const Polygone *>(p1),
dynamic_cast<const Polygone *
>(p2)) ;
119 else if(p2->nbVertices() == 2)
120 return computeRelativePosition( dynamic_cast<const Polygone *>(p1),
dynamic_cast<const Segment *
>(p2)) ;
122 return computeRelativePosition( dynamic_cast<const Polygone *>(p1),dynamic_cast<const Point *>(p2)) ;
123 else if(p1->nbVertices() == 2)
124 if(p2->nbVertices() >= 3)
125 return inverseRP(computeRelativePosition( dynamic_cast<const Polygone *>(p2),dynamic_cast<const Segment *>(p1))) ;
126 else if(p2->nbVertices() == 2)
127 return computeRelativePosition( dynamic_cast<const Segment *>(p1),
dynamic_cast<const Segment *
>(p2)) ;
131 if(p2->nbVertices() >= 3)
132 return inverseRP(computeRelativePosition( dynamic_cast<const Polygone *>(p2),dynamic_cast<const Point *>(p1))) ;
133 else if(p2->nbVertices() == 2)
141 int PrimitivePositioning::computeRelativePosition(
const Polygone *Q,
const Point *P)
143 if(pointOutOfPolygon_XY(P->vertex(0),Q,(double)_EPS))
148 if(Q->equation(P->vertex(0)) >= 0)
156 int PrimitivePositioning::computeRelativePosition(
const Polygone *P,
const Segment *S)
164 vector<double> intersections ;
166 if(!pointOutOfPolygon_XY(S->vertex(0),P,_EPS)) intersections.push_back(0.0);
167 if(!pointOutOfPolygon_XY(S->vertex(1),P,_EPS)) intersections.push_back(1.0);
171 for(
unsigned int i=0;i<P->nbVertices();++i)
173 intersections.push_back(t1) ;
178 double tmin = FLT_MAX ;
179 double tmax = -FLT_MAX ;
181 for(
unsigned int j=0;j<intersections.size();++j)
183 tmin =
min(tmin,intersections[j]) ;
184 tmax =
max(tmax,intersections[j]) ;
187 if(tmax - tmin < 2*_EPS)
193 int res = Independent ;
195 for(
unsigned int k=0;k<intersections.size();++k)
197 Vector3 v( (1-intersections[k])*S->vertex(0) + intersections[k]*S->vertex(1) ) ;
199 if(P->equation(v) < -_EPS) res |= Lower ;
200 if(P->equation(v) > _EPS) res |= Upper ;
203 if(intersections.size() > 1 && res == Independent)
211 int PrimitivePositioning::computeRelativePosition(
const Polygone *P1,
const Polygone *P2)
224 gpc_polygon_clip(GPC_INT,&gpc_p1,&gpc_p2,&gpc_int) ;
226 gpc_free_polygon(&gpc_p1) ;
227 gpc_free_polygon(&gpc_p2) ;
234 int res = Independent ;
236 if (gpc_int.num_contours != 1)
238 gpc_free_polygon(&gpc_int) ;
248 for(
int i=0;i<gpc_int.contour[0].num_vertices && (res < (Upper | Lower));++i)
250 if(P1->normal().z() == 0.0)
throw runtime_error(
"could not project point. Unexpected case !") ;
251 if(P2->normal().z() == 0.0)
throw runtime_error(
"could not project point. Unexpected case !") ;
255 double f1 = P1->normal().x() * gpc_int.contour[0].vertex[i].x + P1->normal().y() * gpc_int.contour[0].vertex[i].y - P1->c() ;
256 double f2 = P2->normal().x() * gpc_int.contour[0].vertex[i].x + P2->normal().y() * gpc_int.contour[0].vertex[i].y - P2->c() ;
258 Vector3 v1(gpc_int.contour[0].vertex[i].x,gpc_int.contour[0].vertex[i].y, -f1/P1->normal().z()) ;
259 Vector3 v2(gpc_int.contour[0].vertex[i].x,gpc_int.contour[0].vertex[i].y, -f2/P2->normal().z()) ;
261 if(P1->equation(v2) < -_EPS) res |= Lower ;
262 if(P1->equation(v2) > _EPS) res |= Upper ;
263 if(P2->equation(v1) < -_EPS) res |= Upper ;
264 if(P2->equation(v1) > _EPS) res |= Lower ;
266 gpc_free_polygon(&gpc_int) ;
272 int PrimitivePositioning::computeRelativePosition(
const Segment *S1,
const Segment *S2)
276 if(!intersectSegments_XY(
Vector2(S1->vertex(0)),
Vector2(S1->vertex(1)),
278 -(
double)_EPS,t1,t2 ))
282 double z1 = (1.0 - t1)*S1->vertex(0).z() + t1*S1->vertex(1).z() ;
283 double z2 = (1.0 - t2)*S2->vertex(0).z() + t2*S2->vertex(1).z() ;
299 bool PrimitivePositioning::pointOutOfPolygon_XY(
const Vector3& P,
const Polygone *Q,
double I_EPS)
301 int nq = Q->nbVertices() ;
304 FLOAT MaxZ = -FLT_MAX ;
305 FLOAT MinZ = FLT_MAX ;
307 for(
int j=0;j<nq;j++)
312 double Z = (q1-p)^(q2-p) ;
318 if((MaxZ <= -I_EPS*I_EPS)||(MinZ >= I_EPS*I_EPS))
324 int PrimitivePositioning::inverseRP(
int pos)
330 case Independent:
return Independent ;
331 case Lower:
return Upper ;
332 case Upper:
return Lower ;
333 case Upper | Lower:
return Upper | Lower ;
335 throw runtime_error(
"Unexpected value.") ;
344 bool PrimitivePositioning::intersectSegments_XY(
const Vector2& P1,
const Vector2& Q1,
347 double & t1,
double & t2)
358 double a2 = -(Q2y - P2y) ;
359 double b2 = (Q2x - P2x) ;
360 double c2 = P2x*a2+P2y*b2 ;
362 double a1 = -(Q1y - P1y) ;
363 double b1 = (Q1x - P1x) ;
364 double c1 = P1x*a1+P1y*b1 ;
366 double d2 = a2*(Q1x-P1x)+b2*(Q1y-P1y) ;
367 double d1 = a1*(Q2x-P2x)+b1*(Q2y-P2y) ;
369 if((fabs(d2) <= fabs(I_EPS))||(fabs(d1) <= fabs(I_EPS)))
371 if(fabs(a2*P1x + b2*P1y - c2) >= I_EPS)
378 tP1 = (P2x-P1x)/(Q1x-P1x) ;
379 tQ1 = (Q2x-P1x)/(Q1x-P1x) ;
383 tP1 = (P2y-P1y)/(Q1y-P1y) ;
384 tQ1 = (Q2y-P1y)/(Q1y-P1y) ;
389 printf(
"IntersectSegments2D:: Error ! One segment has length 0\n") ;
390 printf(
"This special case is not treated yet.\n") ;
395 double tPQM =
max(tP1,tQ1) ;
396 double tPQm =
min(tP1,tQ1) ;
398 if(( tPQM < -I_EPS) || (tPQm > 1.0+I_EPS))
410 t2 = (P1x-P2x)/(Q2x-P2x) ;
412 t2 = (P1y-P2y)/(Q2y-P2y) ;
416 printf(
"IntersectSegments2D:: Error ! One segment has length 0\n") ;
417 printf(
"This special case is not treated yet.\n") ;
427 t2 = (c1 - a1*P2x - b1*P2y)/d1 ;
428 t1 = (c2 - a2*P1x - b2*P1y)/d2 ;
430 if((t2 > 1+I_EPS)||(t2 < -I_EPS)||(t1 > 1+I_EPS)||(t1 < -I_EPS))
447 gpc_p_verts->num_vertices = P->nbVertices() ;
448 gpc_p_verts->vertex =
new gpc_vertex[P->nbVertices()] ;
450 for(
unsigned int i=0;i<P->nbVertices();++i)
452 gpc_p_verts->vertex[i].x = P->vertex(i).x() ;
453 gpc_p_verts->vertex[i].y = P->vertex(i).y() ;
456 gpc_add_contour(&p,gpc_p_verts,
false) ;
461 void PrimitivePositioning::getsigns(
const Primitive *P,
const NVector3& v,
double C,
462 vector<int>& signs,vector<double>& zvals,
int& Smin,
int& Smax,
double I_EPS)
465 throw runtime_error(
"Null primitive in getsigns !") ;
467 int n = P->nbVertices() ;
474 double zmax = -FLT_MAX ;
475 double zmin = FLT_MAX ;
480 double Z = P->vertex(i) * v - C ;
482 if(Z > zmax) zmax = Z ;
483 if(Z < zmin) zmin = Z ;
492 if(zvals[j] < -I_EPS)
494 else if(zvals[j] > I_EPS)
499 if(Smin > signs[j]) Smin = signs[j] ;
500 if(Smax < signs[j]) Smax = signs[j] ;
507 vector<double> Zvals ;
515 getsigns(P,v,C,Signs,Zvals,Smin,Smax,_EPS) ;
517 int n = P->nbVertices() ;
519 if((Smin == 0)&&(Smax == 0)){ P_moins = P ; P_plus = NULL ; return ; }
520 if(Smin == 1) { P_plus = P ; P_moins = NULL ; return ; }
521 if(Smax == -1) { P_plus = NULL ; P_moins = P ; return ; }
523 if((Smin == -1)&&(Smax == 0)) { P_plus = NULL ; P_moins = P ; return ; }
524 if((Smin == 0)&&(Smax == 1)) { P_plus = P ; P_moins = NULL ; return ; }
528 vector<Feedback3DColor> Ps ;
529 vector<Feedback3DColor> Ms ;
542 if(Signs[(i+1)%n] == 0)
548 if((nZero > 2)||(nconsZero > 0)) { P_moins = P ; P_plus = NULL ; return ; }
550 int dep=0 ;
while(Signs[dep] == 0) dep++ ;
551 int prev_sign = Signs[dep] ;
553 for(
int j=1;j<=n;j++)
555 int sign = Signs[(j+dep)%n] ;
557 if(sign == prev_sign)
559 if(sign == 1) Ps.push_back(P->sommet3DColor(j+dep)) ;
560 if(sign == -1) Ms.push_back(P->sommet3DColor(j+dep)) ;
562 else if(sign == -prev_sign)
567 double Z1 = Zvals[(j+dep-1)%n] ;
568 double Z2 = Zvals[(j+dep)%n] ;
570 double t = fabs(Z1/(Z2 - Z1)) ;
572 if((t < 0.0)||(t > 1.0))
574 if(t > 1.0) t = 1.0 ;
575 if(t < 0.0) t = 0.0 ;
577 Feedback3DColor newVertex((1-t)*P->sommet3DColor(j+dep-1) + t*P->sommet3DColor(j+dep)) ;
579 Ps.push_back(newVertex) ;
580 Ms.push_back(newVertex) ;
583 Ps.push_back(P->sommet3DColor(j+dep)) ;
586 Ms.push_back(P->sommet3DColor(j+dep)) ;
594 Ps.push_back(newVertex) ;
595 Ms.push_back(newVertex) ;
597 prev_sign = -prev_sign ;
601 if(Ps.size() > 100 || Ms.size() > 100 )
602 printf(
"Primitive::split: Error. nPs = %d, nMs = %d.\n",
int(Ps.size()),
int(Ms.size())) ;
607 P_plus =
new Point(Ps[0]) ;
608 else if(Ps.size() == 2)
609 P_plus =
new Segment(Ps[0],Ps[1]) ;
614 P_moins =
new Point(Ms[0]) ;
615 else if(Ms.size() == 2)
616 P_moins =
new Segment(Ms[0],Ms[1]) ;
623 if(v*P->vertex(0)-C > -_EPS)
638 vector<double> Zvals ;
646 getsigns(S,v,C,Signs,Zvals,Smin,Smax,_EPS) ;
648 int n = S->nbVertices() ;
650 if((Smin == 0)&&(Smax == 0)) { P_moins = S ; P_plus = NULL ; return ; }
651 if(Smin == 1) { P_plus = S ; P_moins = NULL ; return ; }
652 if(Smax == -1) { P_plus = NULL ; P_moins = S ; return ; }
654 if((Smin == -1)&&(Smax == 0)) { P_plus = NULL ; P_moins = S ; return ; }
655 if((Smin == 0)&&(Smax == 1)) { P_plus = S ; P_moins = NULL ; return ; }
669 if(Signs[(i+1)%n] == 0)
675 if((nZero > 2)||(nconsZero > 0)) { P_moins = S ; P_plus = NULL ; return ; }
677 double Z1 = Zvals[0] ;
678 double Z2 = Zvals[1] ;
680 double t = fabs(Z1/(Z2 - Z1)) ;
682 if((t < 0.0)||(t > 1.0))
684 if(t > 1.0) t = 1.0 ;
685 if(t < 0.0) t = 0.0 ;
688 Feedback3DColor newVertex = S->sommet3DColor(0) * (1-t) + S->sommet3DColor(1) * t ;
692 P_plus =
new Segment(newVertex,S->sommet3DColor(1)) ;
693 P_moins =
new Segment(S->sommet3DColor(0),newVertex) ;
697 P_plus =
new Segment(S->sommet3DColor(0),newVertex) ;
698 P_moins =
new Segment(newVertex,S->sommet3DColor(1)) ;
707 Polygone *p1 =
dynamic_cast<Polygone *
>(P) ;
if(p1 != NULL) PrimitivePositioning::split(p1,v,c,prim_up,prim_lo) ;
708 Segment *p2 =
dynamic_cast<Segment *
>(P) ;
if(p2 != NULL) PrimitivePositioning::split(p2,v,c,prim_up,prim_lo) ;
709 Point *p3 =
dynamic_cast<Point *
>(P) ;
if(p3 != NULL) PrimitivePositioning::split(p3,v,c,prim_up,prim_lo) ;
FARSA_UTIL_TEMPLATE const T max(const T &t1, const U &t2)
FARSA_UTIL_TEMPLATE const T min(const T &t1, const U &t2)