MeshKit  1.0
freeZone.cpp
Go to the documentation of this file.
00001 
00019 // C++
00020 #include <iostream>
00021 #include <list>
00022 
00023 // MeshKit
00024 #include "meshkit/AF2FreeZone.hpp"
00025 #include "meshkit/AF2Point2D.hpp"
00026 
00027 // MeshKit test utilities
00028 #include "TestUtil.hpp"
00029 
00030 AF2FreeZone makeSquareFreeZone();
00031 AF2FreeZone makePentagonFreeZone();
00032 AF2FreeZone makeDiamondFreeZone();
00033 void testSquareConvex();
00034 void testPentagonConvex();
00035 void testClockwiseSquare();
00036 void testLocalNonConvex();
00037 void testGlobalNonConvex();
00038 void testSquareContains();
00039 void testSquareContainsVertex();
00040 void testSquareNotContains();
00041 void testPentagonContains();
00042 void testPentagonNotContains();
00043 void testPentagonNotContainsVertex();
00044 void testDiamondNearContains();
00045 void testDiamondNotContainsVertex();
00046 void testSquareIntersect();
00047 void testSquareNotIntersect();
00048 void testSquareNotIntersectSegment();
00049 void testSquareIntersectOutwardRay();
00050 void testPentagonIntersect();
00051 void testPentagonNearIntersect();
00052 void testPentagonNotIntersectBB();
00053 void testPentagonNotIntersectCW();
00054 void testPentagonNotIntersectZoneCW();
00055 void testPentagonNotIntersectZoneCCW();
00056 void testPentagonIntersectSegment();
00057 void testPentagonNotIntersectOutwardRay();
00058 void testPentagonIntersectInwardRay();
00059 void testDiamondNotIntersectSegment();
00060 void testDiamondNotIntersectOutwardRay();
00061 void testDiamondIntersectInwardRay();
00062 void testRegressionAlpha();
00063 
00064 int main(int argc, char **argv)
00065 {
00066 
00067   int num_fail = 0;
00068 
00069   num_fail += RUN_TEST(testSquareConvex);
00070   num_fail += RUN_TEST(testPentagonConvex);
00071   num_fail += RUN_TEST(testClockwiseSquare);
00072   num_fail += RUN_TEST(testLocalNonConvex);
00073   num_fail += RUN_TEST(testGlobalNonConvex);
00074   num_fail += RUN_TEST(testSquareContains);
00075   num_fail += RUN_TEST(testSquareContainsVertex);
00076   num_fail += RUN_TEST(testSquareNotContains);
00077   num_fail += RUN_TEST(testPentagonContains);
00078   num_fail += RUN_TEST(testPentagonNotContains);
00079   num_fail += RUN_TEST(testPentagonNotContainsVertex);
00080   num_fail += RUN_TEST(testDiamondNearContains);
00081   num_fail += RUN_TEST(testDiamondNotContainsVertex);
00082   num_fail += RUN_TEST(testSquareIntersect);
00083   num_fail += RUN_TEST(testSquareNotIntersect);
00084   num_fail += RUN_TEST(testSquareNotIntersectSegment);
00085   num_fail += RUN_TEST(testSquareIntersectOutwardRay);
00086   num_fail += RUN_TEST(testPentagonIntersect);
00087   num_fail += RUN_TEST(testPentagonNearIntersect);
00088   num_fail += RUN_TEST(testPentagonNotIntersectBB);
00089   num_fail += RUN_TEST(testPentagonNotIntersectCW);
00090   num_fail += RUN_TEST(testPentagonNotIntersectZoneCW);
00091   num_fail += RUN_TEST(testPentagonNotIntersectZoneCCW);
00092   num_fail += RUN_TEST(testPentagonIntersectSegment);
00093   num_fail += RUN_TEST(testPentagonNotIntersectOutwardRay);
00094   num_fail += RUN_TEST(testPentagonIntersectInwardRay);
00095   num_fail += RUN_TEST(testDiamondNotIntersectSegment);
00096   num_fail += RUN_TEST(testDiamondNotIntersectOutwardRay);
00097   num_fail += RUN_TEST(testDiamondIntersectInwardRay);
00098   num_fail += RUN_TEST(testRegressionAlpha);
00099 
00100   return num_fail;
00101 }
00102 
00103 AF2FreeZone makeSquareFreeZone()
00104 {
00105   std::list<AF2Point2D> squareBndryPnts;
00106   AF2Point2D alpha(0, 0);
00107   AF2Point2D bravo(1, 0);
00108   AF2Point2D charlie(1, 1);
00109   AF2Point2D delta(0, 1);
00110   squareBndryPnts.push_back(alpha);
00111   squareBndryPnts.push_back(bravo);
00112   squareBndryPnts.push_back(charlie);
00113   squareBndryPnts.push_back(delta);
00114 
00115   AF2FreeZone squareFreeZone(squareBndryPnts);
00116   return squareFreeZone;
00117 }
00118 
00119 AF2FreeZone makePentagonFreeZone()
00120 {
00121   // make a free zone in roughtly the shape of a regular pentagon
00122   // first two points at (0, 0) and (1e-14, 0)
00123   std::list<AF2Point2D> pentBndryPnts;
00124   AF2Point2D alpha(0, 0);
00125   AF2Point2D bravo(1e-14, 0);
00126   AF2Point2D charlie(1.39735982487e-14, 1.1091842589e-14);
00127   AF2Point2D delta(0.5e-14, 1.74370722192e-14);
00128   AF2Point2D echo(-0.39735982487e-14, 1.1091842589e-14);
00129   pentBndryPnts.push_back(alpha);
00130   pentBndryPnts.push_back(bravo);
00131   pentBndryPnts.push_back(charlie);
00132   pentBndryPnts.push_back(delta);
00133   pentBndryPnts.push_back(echo);
00134 
00135   AF2FreeZone pentFreeZone(pentBndryPnts);
00136   return pentFreeZone;
00137 }
00138 
00139 AF2FreeZone makeDiamondFreeZone()
00140 {
00141   std::list<AF2Point2D> diamondBndryPnts;
00142   AF2Point2D alpha(0, 0);
00143   AF2Point2D bravo(0.5e40, 0.5e40);
00144   AF2Point2D charlie(0, 1e40);
00145   AF2Point2D delta(-0.5e40, 0.5e40);
00146   diamondBndryPnts.push_back(alpha);
00147   diamondBndryPnts.push_back(bravo);
00148   diamondBndryPnts.push_back(charlie);
00149   diamondBndryPnts.push_back(delta);
00150 
00151   AF2FreeZone diamondFreeZone(diamondBndryPnts);
00152   return diamondFreeZone;
00153 }
00154 
00155 void testSquareConvex()
00156 {
00157   AF2FreeZone convexFreeZone = makeSquareFreeZone();
00158   CHECK(convexFreeZone.isConvex());
00159   std::cout << "PASS: The square free zone is convex." << std::endl;
00160 }
00161 
00162 void testPentagonConvex()
00163 {
00164   AF2FreeZone convexFreeZone = makePentagonFreeZone();
00165   CHECK(convexFreeZone.isConvex());
00166   std::cout << "PASS: The pentagon free zone is convex." << std::endl;
00167 }
00168 
00169 void testClockwiseSquare()
00170 {
00171   std::list<AF2Point2D> squareBndryPnts;
00172   AF2Point2D alpha(0, 0);
00173   AF2Point2D bravo(0, 1);
00174   AF2Point2D charlie(1, 1);
00175   AF2Point2D delta(1, 0);
00176   squareBndryPnts.push_back(alpha);
00177   squareBndryPnts.push_back(bravo);
00178   squareBndryPnts.push_back(charlie);
00179   squareBndryPnts.push_back(delta);
00180 
00181   AF2FreeZone clockwiseSquareFreeZone(squareBndryPnts);
00182   CHECK(!clockwiseSquareFreeZone.isConvex());
00183   std::cout <<
00184      "PASS: The clockwise traversal of the square is considered nonconvex."
00185      << std::endl;
00186 }
00187 
00188 void testLocalNonConvex()
00189 {
00190   std::list<AF2Point2D> nonConvexBndryPnts;
00191   AF2Point2D alpha(0, 0);
00192   AF2Point2D bravo(1, 0);
00193   AF2Point2D charlie(0.9999, 0.5);
00194   AF2Point2D delta(0.9999, 1);
00195   AF2Point2D echo(0, 1);
00196   nonConvexBndryPnts.push_back(alpha);
00197   nonConvexBndryPnts.push_back(bravo);
00198   nonConvexBndryPnts.push_back(charlie);
00199   nonConvexBndryPnts.push_back(delta);
00200   nonConvexBndryPnts.push_back(echo);
00201 
00202   AF2FreeZone nonConvexFreeZone(nonConvexBndryPnts);
00203   CHECK(!nonConvexFreeZone.isConvex());
00204   std::cout << "PASS: The counterclockwise traversal of a nonconvex region\n"
00205      << "  is considered nonconvex."
00206      << std::endl;
00207 }
00208 
00215 void testGlobalNonConvex()
00216 {
00217   std::list<AF2Point2D> nonConvexBndryPnts;
00218   AF2Point2D alpha(0, 0);
00219   AF2Point2D bravo(1, 0);
00220   AF2Point2D charlie(0.5, 1);
00221   AF2Point2D delta(-0.125, 0.25);
00222   AF2Point2D echo(0.375, -0.25);
00223   AF2Point2D foxtrot(0.875, 0.75);
00224   AF2Point2D golf(0, 1);
00225   nonConvexBndryPnts.push_back(alpha);
00226   nonConvexBndryPnts.push_back(bravo);
00227   nonConvexBndryPnts.push_back(charlie);
00228   nonConvexBndryPnts.push_back(delta);
00229   nonConvexBndryPnts.push_back(echo);
00230   nonConvexBndryPnts.push_back(foxtrot);
00231   nonConvexBndryPnts.push_back(golf);
00232 
00233   AF2FreeZone nonConvexFreeZone(nonConvexBndryPnts);
00234   CHECK(!nonConvexFreeZone.isConvex());
00235   std::cout << "PASS: The counterclockwise traversal of a nonconvex region\n"
00236      << "  is considered nonconvex, even if every consecutive triple is\n"
00237      << "  counterclockwise."
00238      << std::endl;
00239 }
00240 
00241 void testSquareContains()
00242 {
00243   AF2FreeZone squareFreeZone = makeSquareFreeZone();
00244   AF2Point2D myPoint(0.75, 0.875);
00245   CHECK(squareFreeZone.nearContains(myPoint));
00246   std::cout << "PASS: The square free zone contains " << myPoint
00247       << "." << std::endl;
00248 }
00249 
00250 void testSquareContainsVertex()
00251 {
00252   AF2FreeZone squareFreeZone = makeSquareFreeZone();
00253   AF2Point2D myPoint(1, 0);
00254   CHECK(squareFreeZone.nearContains(myPoint, true));
00255   std::cout << "PASS: The square free zone contains " << myPoint
00256       << "\n  when passed an argument to contain boundary points."
00257       << std::endl;
00258 }
00259 
00260 void testSquareNotContains()
00261 {
00262   AF2FreeZone squareFreeZone = makeSquareFreeZone();
00263   AF2Point2D myPoint(0, 1.0625);
00264   CHECK(!squareFreeZone.nearContains(myPoint));
00265   std::cout << "PASS: The square free zone does not contain " << myPoint
00266       << "." << std::endl;
00267 }
00268 
00269 void testDiamondNearContains()
00270 {
00271   AF2FreeZone diamondFreeZone = makeDiamondFreeZone();
00272   AF2Point2D myPoint(0.25e40, 0.249999999999999e40);
00273   CHECK(diamondFreeZone.nearContains(myPoint));
00274   std::cout << "PASS: The diamond free zone nearly contains\n"
00275       << "  (0.25e40, 0.249999999999999e40)." << std::endl;
00276 }
00277 
00278 void testDiamondNotContainsVertex()
00279 {
00280   AF2FreeZone diamondFreeZone = makeDiamondFreeZone();
00281   AF2Point2D myPoint(0.0, 9.9999999999999e39);
00282   CHECK(!diamondFreeZone.nearContains(myPoint));
00283   std::cout << "PASS: The diamond free zone says it does not contain\n"
00284       << "  (0, 9.9999999999999e39) because it is near a boundary vertex"
00285       << std::endl;
00286 }
00287 
00288 void testPentagonContains()
00289 {
00290   AF2FreeZone pentFreeZone = makePentagonFreeZone();
00291   AF2Point2D myPoint(0.625e-14, 1.25e-14);
00292   CHECK(pentFreeZone.nearContains(myPoint));
00293   std::cout << "PASS: The pentagon free zone contains " << myPoint
00294       << "." << std::endl;
00295 }
00296 
00297 void testPentagonNotContains()
00298 {
00299   AF2FreeZone pentFreeZone = makePentagonFreeZone();
00300   AF2Point2D myPoint(1.25e-14, 0.125e-14);
00301   CHECK(!pentFreeZone.nearContains(myPoint));
00302   std::cout
00303       << "PASS: The pentagon free zone does not contain " << myPoint
00304       << "." << std::endl;
00305 }
00306 
00307 void testPentagonNotContainsVertex()
00308 {
00309   AF2FreeZone pentFreeZone = makePentagonFreeZone();
00310   AF2Point2D myPoint(1.39735982487e-14, 1.1091842589e-14);
00311   CHECK(!pentFreeZone.nearContains(myPoint));
00312   std::cout
00313       << "PASS: The pentagon free zone says it does not contain\n"
00314       << "  (1.39735982487e-14, 1.1091842589e-14)\n"
00315       << "  because it is a boundary vertex" << std::endl;
00316 }
00317 
00318 void testSquareIntersect()
00319 {
00320   AF2FreeZone squareFreeZone = makeSquareFreeZone();
00321   AF2Point2D startEdge(1.2499999, 0.75);
00322   AF2Point2D endEdge(0.75, 1.25);
00323   CHECK(squareFreeZone.nearIntersects(startEdge, endEdge));
00324   std::cout << "PASS: The square free zone intersects an edge from\n"
00325       << "  (1.2499999, 0.75) to (0.75, 1.25)" << std::endl;
00326 }
00327 
00328 void testSquareNotIntersect()
00329 {
00330   AF2FreeZone squareFreeZone = makeSquareFreeZone();
00331   AF2Point2D startEdge(1.2500001, 0.75);
00332   AF2Point2D endEdge(0.75, 1.25);
00333   CHECK(!squareFreeZone.nearIntersects(startEdge, endEdge));
00334   std::cout << "PASS: The square free zone does not intersect an edge from\n"
00335       << "  (1.2500001, 0.75) to (0.75, 1.25)" << std::endl;
00336 }
00337 
00338 void testSquareNotIntersectSegment()
00339 {
00340   AF2FreeZone squareFreeZone = makeSquareFreeZone();
00341   AF2Point2D startEdge(1, 1);
00342   AF2Point2D endEdge(0, 1);
00343   CHECK(!squareFreeZone.nearIntersects(startEdge, endEdge));
00344   std::cout << "PASS: The square free zone says it does not intersect "
00345       << "an edge from\n  (1, 1) to (0, 1) because it is a boundary segment"
00346       << std::endl;
00347 }
00348 
00349 void testSquareIntersectOutwardRay()
00350 {
00351   AF2FreeZone squareFreeZone = makeSquareFreeZone();
00352   AF2Point2D startEdge(1, 1);
00353   AF2Point2D endEdge(1.5, 1.5);
00354   CHECK(squareFreeZone.nearIntersects(startEdge, endEdge, true));
00355   std::cout << "PASS: The square free zone intersects an edge from\n"
00356       << "  (1, 1) to (1.5, 1.5) when passed an argument to contain its "
00357       << "boundary" << std::endl;
00358 }
00359 
00360 void testPentagonIntersect()
00361 {
00362   AF2FreeZone pentFreeZone = makePentagonFreeZone();
00363   AF2Point2D startEdge(1.0e-14, 1.75e-14);
00364   AF2Point2D endEdge(0.5e-14, 1.7437e-14);
00365   CHECK(pentFreeZone.nearIntersects(startEdge, endEdge));
00366   std::cout << "PASS: The pentagon free zone intersects an edge from\n"
00367       << "  (1.0e-14, 1.75e-14) to (0.5e-14, 1.7437e-14)" << std::endl;
00368 }
00369 
00370 void testPentagonNearIntersect()
00371 {
00372   AF2FreeZone pentFreeZone = makePentagonFreeZone();
00373   AF2Point2D startEdge(1.0e-14, 1.75e-14);
00374   AF2Point2D endEdge(0.500010213437881e-14, 1.7437e-14);
00375   // As of 02/17/2016, computations in the code suggested that the
00376   // actual change from intersection to non-intersection is between
00377   // 0.5000102134378802e-14 and 0.5000102134378803e-14, but the
00378   // rounding error involved means this might be just noise.
00379   // Values between 0.50001021343788022e-14 and 0.50001021343788029e-14
00380   // inclusive produced a result of 0, i.e., on the boundary of intersection.
00381   CHECK(pentFreeZone.nearIntersects(startEdge, endEdge));
00382   std::cout << "PASS: The pentagon free zone nearly intersects an edge from\n"
00383       << "  (1.0e-14, 1.75e-14) to (0.500010213437881e-14, 1.7437e-14)"
00384       << std::endl;
00385 }
00386 
00387 void testPentagonNotIntersectBB()
00388 {
00389   AF2FreeZone pentFreeZone = makePentagonFreeZone();
00390   AF2Point2D startEdge(-0.39735982488e-14, 1.0-14);
00391   AF2Point2D endEdge(-0.39735982488e-14, -1.0e-14);
00392   CHECK(!pentFreeZone.nearIntersects(startEdge, endEdge));
00393   std::cout << "PASS: The pentagon free zone does not intersect an edge from\n"
00394       << "  (-0.39735982488e-14, 1.0e-14) to "
00395       << "(-0.39735982488e-14, -1.0e-14)" << std::endl;
00396 }
00397 
00398 void testPentagonNotIntersectCW()
00399 {
00400   AF2FreeZone pentFreeZone = makePentagonFreeZone();
00401   AF2Point2D startEdge(1.0e-14, 1.75e-14);
00402   AF2Point2D endEdge(0.50002e-14, 1.7437e-14);
00403   CHECK(!pentFreeZone.nearIntersects(startEdge, endEdge));
00404   std::cout << "PASS: The pentagon free zone does not intersect an edge from\n"
00405       << "  (1.0e-14, 1.75e-14) to (0.50002e-14, 1.7437e-14)" << std::endl;
00406 }
00407 
00408 void testPentagonNotIntersectZoneCW()
00409 {
00410   AF2FreeZone pentFreeZone = makePentagonFreeZone();
00411   AF2Point2D startEdge(1.3e-14, 1.3e-14);
00412   AF2Point2D endEdge(1.5e-14, 0.95e-14);
00413   CHECK(!pentFreeZone.nearIntersects(startEdge, endEdge));
00414   std::cout << "PASS: The pentagon free zone does not intersect an edge from\n"
00415       << "  (1.3e-14, 1.3e-14) to (1.5e-14, 0.95e-14)" << std::endl;
00416 }
00417 
00418 void testPentagonNotIntersectZoneCCW()
00419 {
00420   AF2FreeZone pentFreeZone = makePentagonFreeZone();
00421   AF2Point2D startEdge(1.5e-14, 0.95e-14);
00422   AF2Point2D endEdge(1.3e-14, 1.3e-14);
00423   CHECK(!pentFreeZone.nearIntersects(startEdge, endEdge));
00424   std::cout << "PASS: The pentagon free zone does not intersect an edge from\n"
00425       << "  (1.5e-14, 0.95e-14) to (1.3e-14, 1.3e-14)" << std::endl;
00426 }
00427 
00428 void testPentagonIntersectSegment()
00429 {
00430   AF2FreeZone pentFreeZone = makePentagonFreeZone();
00431   AF2Point2D startEdge(1.39735982487e-14, 1.1091842589e-14);
00432   AF2Point2D endEdge(0.5e-14, 1.74370722192e-14);
00433   CHECK(pentFreeZone.nearIntersects(startEdge, endEdge, true));
00434   std::cout << "PASS: The pentagon free zone intersects an edge from\n"
00435       << "  (1.39735982487e-14, 1.1091842589e-14) to"
00436       << " (0.5e-14, 1.74370722192e-14)\n"
00437       << "  when passed an argument to contain boundary segments."
00438       << std::endl;
00439 }
00440 
00441 void testPentagonNotIntersectOutwardRay()
00442 {
00443   AF2FreeZone pentFreeZone = makePentagonFreeZone();
00444   AF2Point2D startEdge(5.0e-15, 1.74370722192e-14);
00445   AF2Point2D endEdge(7.0e-15, 3.0e-14);
00446   CHECK(!pentFreeZone.nearIntersects(startEdge, endEdge));
00447   std::cout << "PASS: The pentagon free zone says it does not intersect "
00448       << "an edge from\n"
00449       << "  (5.0e-15, 1.74370722192e-14) to (7.0e-15, 3.0e-14)\n"
00450       << "  because the only intersection is near an endpoint that is\n"
00451       << "  near a boundary point."
00452       << std::endl;
00453 }
00454 
00455 void testPentagonIntersectInwardRay()
00456 {
00457   AF2FreeZone pentFreeZone = makePentagonFreeZone();
00458   AF2Point2D startEdge(5.0e-15, 1.74370722192e-14);
00459   AF2Point2D endEdge(6.0e-15, 1.1e-14);
00460   CHECK(pentFreeZone.nearIntersects(startEdge, endEdge));
00461   std::cout << "PASS: The pentagon free zone intersects an edge from\n"
00462       << "  (5.0e-15, 1.74370722192e-14) to (6.0e-15, 1.1e-14)."
00463       << std::endl;
00464 }
00465 
00466 void testDiamondNotIntersectSegment()
00467 {
00468   AF2FreeZone diamondFreeZone = makeDiamondFreeZone();
00469   AF2Point2D startEdge(0.0, 9.9999999999999e39);
00470   AF2Point2D endEdge(5.0e39, 5.0e39);
00471   CHECK(!diamondFreeZone.nearIntersects(startEdge, endEdge));
00472   std::cout << "PASS: The diamond free zone says it does not intersect\n"
00473       << "  an edge from (0.0, 9.9999999999999e39) to (5.0e39, 5.0e39)\n"
00474       << "  because it is approximately equal to a boundary edge." << std::endl;
00475 }
00476 
00477 void testDiamondNotIntersectOutwardRay()
00478 {
00479   AF2FreeZone diamondFreeZone = makeDiamondFreeZone();
00480   AF2Point2D startEdge(-1.0e39, 1.4e40);
00481   AF2Point2D endEdge(0.0, 9.9999999999999e39);
00482   CHECK(!diamondFreeZone.nearIntersects(startEdge, endEdge));
00483   std::cout << "PASS: The diamond free zone says it does not intersect "
00484       << "an edge from\n  " << startEdge
00485       << " to (0.0, 9.9999999999999e39)\n"
00486       << "  because the only intersection is near an endpoint that is\n"
00487       << "  near a boundary point." << std::endl;
00488 }
00489 
00490 void testDiamondIntersectInwardRay()
00491 {
00492   AF2FreeZone diamondFreeZone = makeDiamondFreeZone();
00493   AF2Point2D startEdge(-1.0e39, 6.1e39);
00494   AF2Point2D endEdge(0.0, 9.9999999999999e39);
00495   CHECK(diamondFreeZone.nearIntersects(startEdge, endEdge));
00496   std::cout << "PASS: The diamond free zone intersects an edge from\n  "
00497       << startEdge << " to (0.0, 9.9999999999999e39)\n" << std::endl;
00498 }
00499 
00511 void testRegressionAlpha()
00512 {
00513   std::list<AF2Point2D> bndryPnts;
00514   AF2Point2D alpha(0, 0);
00515   AF2Point2D bravo(1.0, 0);
00516   AF2Point2D charlie(1.4, 0.7);
00517   AF2Point2D delta(0.5, sqrt(3.0)/2.0);
00518   AF2Point2D echo(-0.4, 0.7);
00519   bndryPnts.push_back(alpha);
00520   bndryPnts.push_back(bravo);
00521   bndryPnts.push_back(charlie);
00522   bndryPnts.push_back(delta);
00523   bndryPnts.push_back(echo);
00524 
00525   AF2FreeZone freeZone(bndryPnts);
00526 
00527   AF2Point2D startEdge(1.0, 0);
00528   AF2Point2D endEdge(1.5, sqrt(3.0)/2.0);
00529   CHECK(!freeZone.nearIntersects(startEdge, endEdge));
00530   std::cout << "PASS: The free zone does not intersects an edge from\n  "
00531       << startEdge << " to (1.5, sqrt(3.0)/2.0)\n" << std::endl;
00532 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines