00001
00002 #include "geom_util.h"
00003
00004
00005
00006 bool point_in_convpoly3D(Vec3D & p, vector<Plane3D> & P)
00007 {
00008 Vec3D v;
00009 for(int i=0;i<P.size();i++)
00010 {
00011 v = p-P[i].p;
00012 if ((P[i].n*v) > 0)
00013 return false;
00014 }
00015 return true;
00016 }
00017
00018
00019
00020
00021
00022 void radial_sort2D(tPolygond &P)
00023 { int i, j, flag = 1;
00024 tPointd temp;
00025 int l = P.size();
00026
00027 short p=0;
00028
00029 for(i=1;i<P.size();i++)
00030 {
00031
00032 if (P[i][1] < P[p][1])
00033 p = i;
00034 else if (P[i][1] == P[p][1])
00035 {
00036 if (P[i][0] > P[p][0])
00037 p = i;
00038 }
00039 }
00040
00041
00042 for(i = 1; (i <=l) && flag; i++)
00043 {
00044 flag = 0;
00045 for (j=0; j <(l-1); j++)
00046 {
00047 if ( left(P[p],P[j+1],P[j]))
00048 {
00049 temp = P[j];
00050 P[j] = P[j+1];
00051 P[j+1] = temp;
00052 flag = 1;
00053 }
00054 }
00055 }
00056 return;
00057 }
00058
00059 inline double poly_area2D(tPolygond &P)
00060 {
00061 double area = 0;
00062 int i, j, k,n;
00063 n=P.size();
00064 for (i=1, j=2, k=0; i<=n; i++, j++, k++) {
00065 area += P[i%n][0] * (P[j%n][1] - P[k%n][1]);
00066 }
00067 return area / 2.0;
00068 }
00069
00070 bool point_in_convpoly2D(tPointd & p, tPolygond & P)
00071 {
00072 tPointd ne;
00073 tPointd v;
00074 int last = P.size()-1;
00075
00076 for(int i=0;i<last;i++)
00077 {
00078 ne[0] = -1.0*P[i+1][1] - P[i][1];
00079 ne[1] = P[i+1][0] - P[i][0];
00080 v = p-P[i];
00081 if ((ne*v) > 0)
00082 return false;
00083 }
00084
00085 ne[0] = -1.0*P[0][1] - P[last][1];
00086 ne[1] = P[0][0] - P[last][0];
00087 v = p-P[last];
00088 if ((ne*v) > 0)
00089 return false;
00090
00091 return true;
00092 }
00093
00094 bool poly_in_convpoly2D(tPolygond & P1, tPolygond & P2)
00095 {
00096 for(int i=0;i<P1.size();i++)
00097 {
00098 if (point_in_convpoly2D(P1[i],P2) == false)
00099 {
00100 return false;
00101 }
00102 }
00103 return true;
00104 }
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 double tri_prism_X(double tri[][3], double prism[][3], vector<Vec3D> & xpoly)
00140 {
00141 tPolygond tpoly, ppoly, xpoly2D;
00142 vector<Vec3D> xpoly3, testpoly;
00143 Vec3D temp;
00144 double area;
00145 std::vector<Vec3D> trace;
00146
00147
00148
00149 Plane3D P;
00150
00151 P.from_tri(tri);
00152
00153 const int n_edges = 9;
00154 Ray3D ray[n_edges];
00155 ray[0].set(prism[0], prism[1]);
00156 ray[1].set(prism[0], prism[2]);
00157 ray[2].set(prism[1], prism[2]);
00158
00159 ray[3].set(prism[3], prism[4]);
00160 ray[4].set(prism[3], prism[5]);
00161 ray[5].set(prism[4], prism[5]);
00162
00163 ray[6].set(prism[0], prism[3]);
00164 ray[7].set(prism[1], prism[4]);
00165 ray[8].set(prism[2], prism[5]);
00166
00167
00168 xpoly3.erase(xpoly3.begin(), xpoly3.end());
00169 for(int i=0;i<n_edges;i++)
00170 {
00171 double x = P.intersect_ray(ray[i]);
00172 if ((x>=0)&&(x<=1))
00173 {
00174
00175
00176 xpoly3.push_back(ray[i].get_point(x));
00177 }
00178 }
00179
00180
00181
00182 tpoly.resize(3);
00183 temp[0] = tri[0][0];temp[1]=tri[0][1];temp[2]=tri[0][2];
00184 P.map(temp, tpoly[0]);
00185 temp[0] = tri[1][0];temp[1]=tri[1][1];temp[2]=tri[1][2];
00186 P.map(temp, tpoly[1]);
00187 temp[0] = tri[2][0];temp[1]=tri[2][1];temp[2]=tri[2][2];
00188 P.map(temp, tpoly[2]);
00189
00190
00191 ppoly.resize(xpoly3.size());
00192 for(short i=0;i<ppoly.size();i++)
00193 {
00194 P.map(xpoly3[i], ppoly[i]);
00195 }
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 xpoly.resize(ppoly.size());
00207
00208
00209 radial_sort2D(ppoly);
00210 radial_sort2D(tpoly);
00211 bool xfound = false;
00212
00213
00214 if( poly_in_convpoly2D(ppoly, tpoly))
00215 {
00216 xfound = true;
00217 xpoly2D.resize(ppoly.size());
00218 for(int i=0;i<ppoly.size();i++)
00219 xpoly2D[i]=ppoly[i];
00220 }
00221 else if (poly_in_convpoly2D(tpoly, ppoly))
00222 {
00223 xfound = true;
00224 xpoly2D.resize(tpoly.size());
00225 for(int i=0;i<tpoly.size();i++)
00226 xpoly2D[i]=tpoly[i];
00227 }
00228
00229
00230
00231
00232 if (!xfound)
00233 {
00234 if (ppoly.size()>2)
00235 {
00236 convex_poly_X( tpoly, ppoly, xpoly2D );
00237 }
00238 else
00239 xpoly2D.erase(xpoly2D.begin(),xpoly2D.end());
00240 }
00241
00242
00243 if (xpoly2D.size()>0)
00244 erase_consecutive_dups(xpoly2D);
00245
00246
00247 if (xpoly2D.size() > 2)
00248 area = poly_area2D(xpoly2D);
00249 else
00250 area =0;
00251
00252 xpoly.erase(xpoly.begin(),xpoly.end());
00253 xpoly.resize(xpoly2D.size());
00254
00255 for(short i=0;i<xpoly2D.size();i++)
00256 {
00257
00258 P.unmap(xpoly[i], xpoly2D[i]);
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 return area;
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285 int convex_poly_X( tPolygond & P, tPolygond & Q, tPolygond & I )
00286 {
00287 int m, n;
00288 int a, b;
00289 int a1, b1;
00290 tPointd A, B;
00291 int cross;
00292 int bHA, aHB;
00293 tPointd Origin(0,0);
00294 tPointd p;
00295 tPointd q;
00296 tInFlag inflag;
00297 int aa, ba;
00298 bool FirstPoint;
00299 tPointd p0;
00300 int code;
00301 bool xfound;
00302
00303 n = P.size();
00304 m = Q.size();
00305 a = 0; b = 0; aa = 0; ba = 0;
00306 inflag = Unknown; FirstPoint = true;
00307 I.erase(I.begin(),I.end());
00308
00309 do {
00310
00311 a1 = (a + n - 1) % n;
00312 b1 = (b + m - 1) % m;
00313 Origin[0] =0;Origin[1]=0;
00314 A=P[a] - P[a1];
00315 B=Q[b] - Q[b1];
00316
00317 cross = area_sign( Origin, A, B );
00318 aHB = area_sign( Q[b1], Q[b], P[a] );
00319 bHA = area_sign( P[a1], P[a], Q[b] );
00320
00321
00322 code = seg_seg_int( P[a1], P[a], Q[b1], Q[b], p, q );
00323
00324 if ( code == '1' || code == 'v' ) {
00325 if ( inflag == Unknown && FirstPoint ) {
00326 aa = ba = 0;
00327 FirstPoint = false;
00328 p0[0] = p[0]; p0[1] = p[1];
00329 I.push_back(p0);
00330 }
00331 inflag = in_out( p, inflag, aHB, bHA, I);
00332
00333 }
00334
00335
00336
00337
00338 if ( ( code == 'e' ) && ((A*B) < 0) )
00339 {
00340 shared_seg( p, q , I);
00341 return EXIT_SUCCESS;
00342 }
00343
00344
00345 if ( (cross == 0) && ( aHB < 0) && ( bHA < 0 ) )
00346 {
00347 return EXIT_SUCCESS;
00348 }
00349
00350
00351 else if ( (cross == 0) && ( aHB == 0) && ( bHA == 0 ) ) {
00352
00353 if ( inflag == Pin )
00354 b = advance( b, &ba, m, inflag == Qin, Q[b],I );
00355 else
00356 a = advance( a, &aa, n, inflag == Pin, P[a], I );
00357 }
00358
00359
00360 else if ( cross >= 0 ) {
00361 if ( bHA > 0)
00362 a = advance( a, &aa, n, inflag == Pin, P[a], I );
00363 else
00364 b = advance( b, &ba, m, inflag == Qin, Q[b], I );
00365 }
00366 else {
00367 if ( aHB > 0)
00368 b = advance( b, &ba, m, inflag == Qin, Q[b], I );
00369 else
00370 a = advance( a, &aa, n, inflag == Pin, P[a], I );
00371 }
00372
00373
00374 } while ( ((aa < n) || (ba < m)) && (aa < 2*n) && (ba < 2*m) );
00375
00376 if ( !FirstPoint )
00377 {
00378 I.push_back(p0);
00379 }
00380
00381 if ( inflag == Unknown)
00382 {
00383 xfound = false;
00384
00385
00386 if (!xfound)
00387 {
00388 printf("%%The boundaries of P and Q do not cross.\n");
00389 I.erase(I.begin(),I.end());
00390 }
00391 }
00392
00393 return EXIT_FAILURE;
00394 }
00395
00396
00397
00398
00399 tInFlag in_out( tPointd & p, tInFlag inflag, int aHB, int bHA, tPolygond & I )
00400 {
00401 I.push_back(p);
00402
00403 if ( aHB > 0)
00404 return Pin;
00405 else if ( bHA > 0)
00406 return Qin;
00407 else
00408 return inflag;
00409 }
00410
00411
00412
00413 int advance( int a, int *aa, int n, bool inside, tPointd & v , tPolygond & I)
00414 {
00415 if ( inside )
00416 {
00417
00418 I.push_back(v);
00419 }
00420 (*aa)++;
00421 return (a+1) % n;
00422 }
00423
00424
00425
00426
00427
00428
00429
00430 int ReadPoly( tPolygond & P )
00431 {
00432 tPointd v;
00433 int n = 0;
00434 int nin;
00435 double x,y;
00436 scanf("%d", &nin);
00437
00438
00439 P.resize(nin);
00440 while (n < nin)
00441 {
00442 cin >> x;
00443 cin >> y;
00444 v[0] = x;
00445 v[1] = y;
00446 P[n]=v;
00447
00448 ++n;
00449 }
00450
00451
00452 putchar('\n');
00453
00454 return n;
00455 }
00456
00457
00458
00459
00460
00461 bool left( tPointd & a, tPointd & b, tPointd & c )
00462 {
00463 return area_sign( a, b, c ) > 0;
00464 }
00465
00466 bool left_on( tPointd & a, tPointd & b, tPointd & c )
00467 {
00468 return area_sign( a, b, c ) >= 0;
00469 }
00470
00471 bool collinear( tPointd & a, tPointd & b, tPointd & c )
00472 {
00473 return area_sign( a, b, c ) == 0;
00474 }
00475
00476 int area_sign( tPointd & a, tPointd & b, tPointd & c )
00477 {
00478 double area2;
00479
00480 area2 = ( b[0] - a[0] ) * ( c[1] - a[1] ) -
00481 ( c[0] - a[0] ) * ( b[1] - a[1] );
00482
00483
00484 if ( area2 > 0.0 ) return 1;
00485 else if ( area2 < 0.0 ) return -1;
00486 else return 0;
00487 }
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501 char seg_seg_int( tPointd & a, tPointd & b, tPointd & c,
00502 tPointd & d, tPointd & p, tPointd & q )
00503 {
00504 double s, t;
00505 double num, denom;
00506 char code = '?';
00507
00508 denom = a[0] * (double)( d[1] - c[1] ) +
00509 b[0] * (double)( c[1] - d[1] ) +
00510 d[0] * (double)( b[1] - a[1] ) +
00511 c[0] * (double)( a[1] - b[1] );
00512
00513
00514 if (denom == 0.0)
00515 return parallel_int(a, b, c, d, p, q);
00516
00517 num = a[0] * (double)( d[1] - c[1] ) +
00518 c[0] * (double)( a[1] - d[1] ) +
00519 d[0] * (double)( c[1] - a[1] );
00520 if ( (num == 0.0) || (num == denom) ) code = 'v';
00521 s = num / denom;
00522
00523 num = -( a[0] * (double)( c[1] - b[1] ) +
00524 b[0] * (double)( a[1] - c[1] ) +
00525 c[0] * (double)( b[1] - a[1] ) );
00526 if ( (num == 0.0) || (num == denom) ) code = 'v';
00527 t = num / denom;
00528
00529 if ( (0.0 < s) && (s < 1.0) &&
00530 (0.0 < t) && (t < 1.0) )
00531 code = '1';
00532 else if ( (0.0 > s) || (s > 1.0) ||
00533 (0.0 > t) || (t > 1.0) )
00534 code = '0';
00535
00536 p[0] = a[0] + s * ( b[0] - a[0] );
00537 p[1] = a[1] + s * ( b[1] - a[1] );
00538
00539 return code;
00540 }
00541
00542 char parallel_int( tPointd & a, tPointd & b, tPointd & c, tPointd & d, tPointd & p, tPointd & q )
00543 {
00544
00545 if ( !collinear( a, b, c) )
00546 return '0';
00547
00548 if ( between( a, b, c ) && between( a, b, d ) ) {
00549 p = c;
00550 q = d;
00551 return 'e';
00552 }
00553 if ( between( c, d, a ) && between( c, d, b ) ) {
00554 p = a;
00555 q = b;
00556 return 'e';
00557 }
00558 if ( between( a, b, c ) && between( c, d, b ) ) {
00559 p=c;
00560 q=b;
00561 return 'e';
00562 }
00563 if ( between( a, b, c ) && between( c, d, a ) ) {
00564 p=c;
00565 q=a;
00566 return 'e';
00567 }
00568 if ( between( a, b, d ) && between( c, d, b ) ) {
00569 p=d;
00570 q=b;
00571 return 'e';
00572 }
00573 if ( between( a, b, d ) && between( c, d, a ) ) {
00574 p=d;
00575 q=a;
00576 return 'e';
00577 }
00578 return '0';
00579 }
00580
00581
00582
00583
00584
00585 bool between( tPointd & a, tPointd & b, tPointd & c )
00586 {
00587 tPointd ba, ca;
00588
00589
00590 if ( a[0] != b[0] )
00591 return ((a[0] <= c[0]) && (c[0] <= b[0])) ||
00592 ((a[0] >= c[0]) && (c[0] >= b[0]));
00593 else
00594 return ((a[1] <= c[1]) && (c[1] <= b[1])) ||
00595 ((a[1] >= c[1]) && (c[1] >= b[1]));
00596 }
00597
00598 void shared_seg( tPointd & p, tPointd & q, tPolygond & I )
00599 {
00600 I.push_back(p);
00601 I.push_back(q);
00602 }
00603