MeshKit
1.0
|
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 }