/* KLayout Layout Viewer Copyright (C) 2006-2025 Matthias Koefferlein This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "dbPolygon.h" #include "dbPolygonTools.h" #include "dbEdgeProcessor.h" #include "dbPolygonGenerators.h" #include "tlUnitTest.h" TEST(1) { db::Box box (0, 0, 1000, 1000); db::Polygon in (box); std::vector right_of; db::cut_polygon (in, db::Edge (db::Point (0, 500), db::Point (1, 500)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (1)); EXPECT_EQ (right_of[0].to_string (), "(0,0;0,500;1000,500;1000,0)"); right_of.clear (); db::cut_polygon (in, db::Edge (db::Point (0, -100), db::Point (1, -100)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (0)); right_of.clear (); db::cut_polygon (in, db::Edge (db::Point (0, 0), db::Point (1, 0)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (0)); right_of.clear (); db::cut_polygon (in, db::Edge (db::Point (0, 1000), db::Point (1, 1000)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (1)); EXPECT_EQ (right_of[0].to_string (), "(0,0;0,1000;1000,1000;1000,0)"); right_of.clear (); db::cut_polygon (in, db::Edge (db::Point (0, 1001), db::Point (1, 1001)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (1)); EXPECT_EQ (right_of[0].to_string (), "(0,0;0,1000;1000,1000;1000,0)"); } TEST(2) { std::vector c; c.push_back (db::Point (0, 0)); c.push_back (db::Point (0, 400)); c.push_back (db::Point (400, 400)); c.push_back (db::Point (400, 100)); c.push_back (db::Point (600, 100)); c.push_back (db::Point (600, 300)); c.push_back (db::Point (700, 300)); c.push_back (db::Point (700, 0)); c.push_back (db::Point (300, 0)); c.push_back (db::Point (300, 300)); c.push_back (db::Point (100, 300)); c.push_back (db::Point (100, 100)); c.push_back (db::Point (200, 100)); c.push_back (db::Point (200, 0)); db::Polygon in; in.assign_hull (c.begin (), c.end ()); std::vector right_of; db::cut_polygon (in, db::Edge (db::Point (0, 200), db::Point (1, 200)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (2)); EXPECT_EQ (right_of[0].to_string (), "(0,0;0,200;100,200;100,100;200,100;200,0)"); EXPECT_EQ (right_of[1].to_string (), "(300,0;300,200;400,200;400,100;600,100;600,200;700,200;700,0)"); right_of.clear (); db::cut_polygon (in, db::Edge (db::Point (0, 100), db::Point (1, 100)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (2)); EXPECT_EQ (right_of[0].to_string (), "(0,0;0,100;200,100;200,0)"); EXPECT_EQ (right_of[1].to_string (), "(300,0;300,100;700,100;700,0)"); right_of.clear (); db::cut_polygon (in, db::Edge (db::Point (0, 50), db::Point (1, 50)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (2)); EXPECT_EQ (right_of[0].to_string (), "(0,0;0,50;200,50;200,0)"); EXPECT_EQ (right_of[1].to_string (), "(300,0;300,50;700,50;700,0)"); right_of.clear (); db::cut_polygon (in, db::Edge (db::Point (0, 300), db::Point (1, 300)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (2)); EXPECT_EQ (right_of[0].to_string (), "(0,0;0,300;100,300;100,100;200,100;200,0)"); EXPECT_EQ (right_of[1].to_string (), "(300,0;300,300;400,300;400,100;600,100;600,300;700,300;700,0)"); right_of.clear (); db::cut_polygon (in, db::Edge (db::Point (0, 400), db::Point (1, 400)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (1)); EXPECT_EQ (right_of[0].to_string (), "(0,0;0,400;400,400;400,100;600,100;600,300;700,300;700,0;300,0;300,300;100,300;100,100;200,100;200,0)"); right_of.clear (); db::cut_polygon (in, db::Edge (db::Point (0, 500), db::Point (1, 500)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (1)); EXPECT_EQ (right_of[0].to_string (), "(0,0;0,400;400,400;400,100;600,100;600,300;700,300;700,0;300,0;300,300;100,300;100,100;200,100;200,0)"); } TEST(3) { db::Box box (0, 0, 1000, 1000); db::Polygon in (box); std::vector c; c.push_back (db::Point (100, 100)); c.push_back (db::Point (100, 400)); c.push_back (db::Point (200, 400)); c.push_back (db::Point (200, 100)); in.insert_hole (c.begin (), c.end ()); c.clear (); c.push_back (db::Point (400, 100)); c.push_back (db::Point (400, 400)); c.push_back (db::Point (500, 400)); c.push_back (db::Point (500, 100)); in.insert_hole (c.begin (), c.end ()); std::vector right_of; db::cut_polygon (in, db::Edge (db::Point (0, 200), db::Point (1, 200)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (1)); EXPECT_EQ (right_of[0].to_string (), "(0,0;0,200;100,200;100,100;200,100;200,200;400,200;400,100;500,100;500,200;1000,200;1000,0)"); right_of.clear (); db::cut_polygon (in, db::Edge (db::Point (0, 50), db::Point (1, 50)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (1)); EXPECT_EQ (right_of[0].to_string (), "(0,0;0,50;1000,50;1000,0)"); right_of.clear (); db::cut_polygon (in, db::Edge (db::Point (0, 500), db::Point (1, 500)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (1)); EXPECT_EQ (right_of[0].to_string (), "(0,0;0,500;1000,500;1000,0/100,100;200,100;200,400;100,400/400,100;500,100;500,400;400,400)"); } TEST(4) { std::vector c; c.push_back (db::Point (0, 0)); c.push_back (db::Point (0, 400)); c.push_back (db::Point (400, 400)); c.push_back (db::Point (400, 200)); c.push_back (db::Point (300, 200)); c.push_back (db::Point (300, 100)); c.push_back (db::Point (400, 100)); c.push_back (db::Point (400, 400)); c.push_back (db::Point (600, 400)); c.push_back (db::Point (600, 0)); db::Polygon in; in.assign_hull (c.begin (), c.end ()); std::vector right_of; db::cut_polygon (in, db::Edge (db::Point (0, 300), db::Point (1, 300)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (1)); EXPECT_EQ (right_of[0].to_string (), "(0,0;0,300;400,300;400,200;300,200;300,100;400,100;400,300;600,300;600,0)"); right_of.clear (); db::cut_polygon (in, db::Edge (db::Point (1, 300), db::Point (0, 300)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (2)); EXPECT_EQ (right_of[0].to_string (), "(400,300;400,400;600,400;600,300)"); EXPECT_EQ (right_of[1].to_string (), "(0,300;0,400;400,400;400,300)"); right_of.clear (); db::cut_polygon (in, db::Edge (db::Point (0, 50), db::Point (1, 50)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (1)); EXPECT_EQ (right_of[0].to_string (), "(0,0;0,50;600,50;600,0)"); right_of.clear (); db::cut_polygon (in, db::Edge (db::Point (0, 100), db::Point (1, 100)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (1)); EXPECT_EQ (right_of[0].to_string (), "(0,0;0,100;600,100;600,0)"); right_of.clear (); db::cut_polygon (in, db::Edge (db::Point (0, 150), db::Point (1, 150)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (1)); EXPECT_EQ (right_of[0].to_string (), "(0,0;0,150;300,150;300,100;400,100;400,150;600,150;600,0)"); right_of.clear (); db::cut_polygon (in, db::Edge (db::Point (0, 200), db::Point (1, 200)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (1)); EXPECT_EQ (right_of[0].to_string (), "(0,0;0,200;300,200;300,100;400,100;400,200;600,200;600,0)"); } TEST(5) { std::vector c; c.push_back (db::Point (0, 0)); c.push_back (db::Point (0, 884)); c.push_back (db::Point (1010, 884)); c.push_back (db::Point (1010, 396)); c.push_back (db::Point (565, 396)); c.push_back (db::Point (565, 372)); c.push_back (db::Point (568, 372)); c.push_back (db::Point (568, 396)); c.push_back (db::Point (1010, 396)); c.push_back (db::Point (1010, 332)); c.push_back (db::Point (72, 332)); c.push_back (db::Point (72, 313)); c.push_back (db::Point (89, 313)); c.push_back (db::Point (89, 332)); c.push_back (db::Point (1010, 332)); c.push_back (db::Point (1010, 327)); c.push_back (db::Point (173, 327)); c.push_back (db::Point (173, 304)); c.push_back (db::Point (211, 304)); c.push_back (db::Point (211, 327)); c.push_back (db::Point (1010, 327)); c.push_back (db::Point (1010, 302)); c.push_back (db::Point (174, 302)); c.push_back (db::Point (174, 275)); c.push_back (db::Point (212, 275)); c.push_back (db::Point (212, 302)); c.push_back (db::Point (1010, 302)); c.push_back (db::Point (1010, 268)); c.push_back (db::Point (47, 268)); c.push_back (db::Point (47, 257)); c.push_back (db::Point (62, 257)); c.push_back (db::Point (62, 268)); c.push_back (db::Point (1010, 268)); c.push_back (db::Point (1010, 243)); c.push_back (db::Point (49, 243)); c.push_back (db::Point (49, 231)); c.push_back (db::Point (63, 231)); c.push_back (db::Point (63, 243)); c.push_back (db::Point (1010, 243)); c.push_back (db::Point (1010, 214)); c.push_back (db::Point (72, 214)); c.push_back (db::Point (72, 194)); c.push_back (db::Point (93, 194)); c.push_back (db::Point (93, 214)); c.push_back (db::Point (1010, 214)); c.push_back (db::Point (1010, 77)); c.push_back (db::Point (5, 77)); c.push_back (db::Point (5, 15)); c.push_back (db::Point (67, 15)); c.push_back (db::Point (67, 77)); c.push_back (db::Point (1010, 77)); c.push_back (db::Point (1010, 38)); c.push_back (db::Point (328, 38)); c.push_back (db::Point (328, 17)); c.push_back (db::Point (405, 17)); c.push_back (db::Point (405, 38)); c.push_back (db::Point (1010, 38)); c.push_back (db::Point (1010, 0)); db::Polygon in; in.assign_hull (c.begin (), c.end ()); std::vector right_of; db::cut_polygon (in, db::Edge (db::Point (565, 1), db::Point (565, 0)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (1)); EXPECT_EQ (right_of[0].to_string (), "(0,0;0,884;565,884;565,332;72,332;72,313;89,313;89,332;565,332;565,327;173,327;173,304;211,304;211,327;565,327;565,302;174,302;174,275;212,275;212,302;565,302;565,268;47,268;47,257;62,257;62,268;565,268;565,243;49,243;49,231;63,231;63,243;565,243;565,214;72,214;72,194;93,194;93,214;565,214;565,77;5,77;5,15;67,15;67,77;565,77;565,38;328,38;328,17;405,17;405,38;565,38;565,0)"); } TEST(6) { std::vector c; c.push_back (db::Point (0, 0)); c.push_back (db::Point (0, 100)); c.push_back (db::Point (100, 100)); c.push_back (db::Point (200, 200)); c.push_back (db::Point (300, 100)); c.push_back (db::Point (400, 100)); c.push_back (db::Point (400, 400)); c.push_back (db::Point (500, 400)); c.push_back (db::Point (500, 0)); db::Polygon in; in.assign_hull (c.begin (), c.end ()); std::vector right_of; db::cut_polygon (in, db::Edge (db::Point (0, 200), db::Point (1, 200)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (1)); EXPECT_EQ (right_of[0].to_string (), "(0,0;0,100;100,100;200,200;300,100;400,100;400,200;500,200;500,0)"); c.push_back (db::Point ()); } TEST(7) { std::vector c; c.push_back (db::Point (0, 0)); c.push_back (db::Point (0, 1)); c.push_back (db::Point (3, 1)); c.push_back (db::Point (3, 0)); c.push_back (db::Point (0, 1)); c.push_back (db::Point (2, 0)); db::Polygon in; in.assign_hull (c.begin (), c.end ()); std::vector right_of; db::cut_polygon (in, db::Edge (db::Point (2, 0), db::Point (2, 1)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (1)); EXPECT_EQ (right_of[0].to_string (), "(2,0;2,1;3,1;3,0)"); right_of.clear (); db::cut_polygon (in, db::Edge (db::Point (2, 1), db::Point (2, 0)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (1)); EXPECT_EQ (right_of[0].to_string (), "(0,0;0,1;2,1;2,0)"); } TEST(8) { std::vector c; c.push_back (db::Point (0, 0)); c.push_back (db::Point (0, 300)); c.push_back (db::Point (300, 300)); c.push_back (db::Point (200, 200)); c.push_back (db::Point (100, 200)); c.push_back (db::Point (100, 100)); c.push_back (db::Point (200, 200)); c.push_back (db::Point (150, 50)); c.push_back (db::Point (300, 50)); c.push_back (db::Point (300, 0)); db::Polygon in; in.assign_hull (c.begin (), c.end ()); std::vector right_of; db::cut_polygon (in, db::Edge (db::Point (200, 0), db::Point (200, 1)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (2)); EXPECT_EQ (right_of[0].to_string (), "(200,0;200,50;300,50;300,0)"); EXPECT_EQ (right_of[1].to_string (), "(200,200;200,300;300,300)"); right_of.clear (); db::cut_polygon (in, db::Edge (db::Point (200, 1), db::Point (200, 0)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (1)); EXPECT_EQ (right_of[0].to_string (), "(0,0;0,300;200,300;200,200;100,200;100,100;200,200;150,50;200,50;200,0)"); } TEST(9) { std::vector c; c.push_back (db::Point (0, 0)); c.push_back (db::Point (0, 200)); c.push_back (db::Point (250, 200)); c.push_back (db::Point (250, 100)); c.push_back (db::Point (300, 100)); c.push_back (db::Point (300, 200)); c.push_back (db::Point (0, 200)); c.push_back (db::Point (0, 500)); c.push_back (db::Point (400, 500)); c.push_back (db::Point (400, 400)); c.push_back (db::Point (100, 400)); c.push_back (db::Point (100, 300)); c.push_back (db::Point (150, 300)); c.push_back (db::Point (150, 400)); c.push_back (db::Point (400, 400)); c.push_back (db::Point (400, 0)); db::Polygon in; in.assign_hull (c.begin (), c.end ()); std::vector right_of; db::cut_polygon (in, db::Edge (db::Point (200, 0), db::Point (200, 1)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (2)); EXPECT_EQ (right_of[0].to_string (), "(200,0;200,200;250,200;250,100;300,100;300,200;200,200;200,400;400,400;400,0)"); EXPECT_EQ (right_of[1].to_string (), "(200,400;200,500;400,500;400,400)"); right_of.clear (); db::cut_polygon (in, db::Edge (db::Point (200, 1), db::Point (200, 0)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (2)); EXPECT_EQ (right_of[0].to_string (), "(0,200;0,500;200,500;200,400;100,400;100,300;150,300;150,400;200,400;200,200)"); EXPECT_EQ (right_of[1].to_string (), "(0,0;0,200;200,200;200,0)"); } TEST(9a) { std::vector c; c.push_back (db::Point (942, 10230)); c.push_back (db::Point (943, 10272)); c.push_back (db::Point (988, 10278)); c.push_back (db::Point (999, 10278)); c.push_back (db::Point (1002, 10280)); c.push_back (db::Point (1034, 10280)); c.push_back (db::Point (1032, 10285)); c.push_back (db::Point (1090, 10285)); c.push_back (db::Point (1090, 10302)); c.push_back (db::Point (1043, 10302)); c.push_back (db::Point (1041, 10286)); c.push_back (db::Point (1036, 10285)); c.push_back (db::Point (1031, 10297)); c.push_back (db::Point (1027, 10297)); c.push_back (db::Point (1032, 10285)); c.push_back (db::Point (1022, 10283)); c.push_back (db::Point (1024, 10288)); c.push_back (db::Point (1011, 10288)); c.push_back (db::Point (1017, 10283)); c.push_back (db::Point (1003, 10281)); c.push_back (db::Point (1011, 10288)); c.push_back (db::Point (1024, 10288)); c.push_back (db::Point (1027, 10297)); c.push_back (db::Point (1031, 10297)); c.push_back (db::Point (1029, 10302)); c.push_back (db::Point (1027, 10297)); c.push_back (db::Point (1026, 10300)); c.push_back (db::Point (1028, 10302)); c.push_back (db::Point (994, 10302)); c.push_back (db::Point (1002, 10280)); c.push_back (db::Point (988, 10278)); c.push_back (db::Point (983, 10281)); c.push_back (db::Point (942, 10281)); c.push_back (db::Point (942, 10230)); c.push_back (db::Point (1019, 10230)); c.push_back (db::Point (1017, 10237)); c.push_back (db::Point (1027, 10252)); c.push_back (db::Point (1090, 10252)); c.push_back (db::Point (1090, 10285)); c.push_back (db::Point (1036, 10285)); c.push_back (db::Point (1039, 10277)); c.push_back (db::Point (1038, 10269)); c.push_back (db::Point (1034, 10280)); c.push_back (db::Point (1021, 10280)); c.push_back (db::Point (1037, 10266)); c.push_back (db::Point (1027, 10252)); c.push_back (db::Point (1014, 10260)); c.push_back (db::Point (1016, 10265)); c.push_back (db::Point (1007, 10265)); c.push_back (db::Point (1014, 10260)); c.push_back (db::Point (1012, 10252)); c.push_back (db::Point (1007, 10265)); c.push_back (db::Point (1016, 10265)); c.push_back (db::Point (1021, 10280)); c.push_back (db::Point (1002, 10280)); c.push_back (db::Point (1007, 10265)); c.push_back (db::Point (994, 10274)); c.push_back (db::Point (999, 10278)); c.push_back (db::Point (988, 10278)); c.push_back (db::Point (994, 10274)); db::Polygon in; db::Polygon::contour_type contour; contour.assign (c.begin (), c.end (), false, false, true); in.assign_hull (contour); std::vector right_of; db::cut_polygon (in, db::Edge (db::Point (1016, 0), db::Point (1016, 1)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (4)); EXPECT_EQ (right_of[0].to_string (), "(1016,10230;1016,10259;1027,10252;1037,10266;1021,10280;1034,10280;1038,10269;1039,10277;1036,10285;1090,10285;1090,10252;1027,10252;1017,10237;1019,10230)"); EXPECT_EQ (right_of[1].to_string (), "(1016,10265;1016,10280;1021,10280)"); EXPECT_EQ (right_of[2].to_string (), "(1016,10280;1016,10283;1017,10283;1016,10284;1016,10288;1024,10288;1022,10283;1032,10285;1027,10297;1031,10297;1036,10285;1041,10286;1043,10302;1090,10302;1090,10285;1032,10285;1034,10280)"); EXPECT_EQ (right_of[3].to_string (), "(1016,10288;1016,10302;1028,10302;1026,10300;1027,10297;1029,10302;1031,10297;1027,10297;1024,10288)"); right_of.clear (); db::cut_polygon (in, db::Edge (db::Point (1016, 1), db::Point (1016, 0)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (2)); EXPECT_EQ (right_of[0].to_string (), "(942,10230;994,10274;988,10278;999,10278;994,10274;1007,10265;1002,10280;1016,10280;1016,10265;1007,10265;1012,10252;1014,10260;1007,10265;1016,10265;1014,10260;1016,10259;1016,10230;942,10230;942,10281;983,10281;988,10278;1002,10280;994,10302;1016,10302;1016,10288;1011,10288;1003,10281;1016,10283;1016,10280;1002,10280;999,10278;988,10278;943,10272)"); EXPECT_EQ (right_of[1].to_string (), "(1016,10284;1011,10288;1016,10288)"); } TEST(9b) { std::vector c; c.push_back (db::Point (942, 10230)); c.push_back (db::Point (942, 10265)); c.push_back (db::Point (943, 10265)); c.push_back (db::Point (942, 10230)); c.push_back (db::Point (983, 10265)); c.push_back (db::Point (1007, 10265)); c.push_back (db::Point (1012, 10252)); c.push_back (db::Point (1014, 10260)); c.push_back (db::Point (1007, 10265)); c.push_back (db::Point (1016, 10265)); c.push_back (db::Point (1014, 10260)); c.push_back (db::Point (1016, 10259)); c.push_back (db::Point (1016, 10230)); db::Polygon in; db::Polygon::contour_type contour; contour.assign (c.begin (), c.end (), false, false, true); in.assign_hull (contour); std::vector right_of; db::cut_polygon (in, db::Edge (db::Point (1007, 0), db::Point (1007, 1)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (1)); EXPECT_EQ (right_of[0].to_string (), "(1007,10230;1007,10265;1012,10252;1014,10260;1007,10265;1016,10265;1014,10260;1016,10259;1016,10230)"); right_of.clear (); db::cut_polygon (in, db::Edge (db::Point (1007, 1), db::Point (1007, 0)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (1)); EXPECT_EQ (right_of[0].to_string (), "(942,10230;942,10265;943,10265;942,10230;983,10265;1007,10265;1007,10230)"); } TEST(9c) { std::vector c; c.push_back (db::Point (14335, 8265)); c.push_back (db::Point (14335, 10265)); c.push_back (db::Point (17335, 10265)); c.push_back (db::Point (15335, 10265)); c.push_back (db::Point (15335, 9765)); c.push_back (db::Point (15668, 9932)); c.push_back (db::Point (15335, 10265)); c.push_back (db::Point (17335, 10265)); c.push_back (db::Point (17335, 10015)); c.push_back (db::Point (15835, 10015)); c.push_back (db::Point (15668, 9932)); c.push_back (db::Point (15835, 9765)); c.push_back (db::Point (16002, 9932)); c.push_back (db::Point (15835, 10015)); c.push_back (db::Point (17335, 10015)); c.push_back (db::Point (17335, 9765)); c.push_back (db::Point (15335, 9765)); c.push_back (db::Point (14335, 9265)); c.push_back (db::Point (15335, 9265)); c.push_back (db::Point (15335, 9765)); c.push_back (db::Point (17335, 9765)); c.push_back (db::Point (17335, 8265)); c.push_back (db::Point (16335, 9265)); c.push_back (db::Point (15335, 9265)); db::Polygon in; db::Polygon::contour_type contour; contour.assign (c.begin (), c.end (), false, false, true); in.assign_hull (contour); std::vector right_of; db::cut_polygon (in, db::Edge (db::Point (15835, 0), db::Point (15835, 1)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (1)); EXPECT_EQ (right_of[0].to_string (), "(17335,8265;16335,9265;15835,9265;15835,9765;16002,9932;15835,10015;15835,10265;17335,10265)"); right_of.clear (); db::cut_polygon (in, db::Edge (db::Point (15835, 1), db::Point (15835, 0)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (4)); if (right_of.size () >= 4) { EXPECT_EQ (right_of[0].to_string (), "(14335,8265;14335,9265;15335,9265)"); EXPECT_EQ (right_of[1].to_string (), "(15335,9265;15335,9765;15668,9932;15835,9765;15835,9265)"); EXPECT_EQ (right_of[2].to_string (), "(14335,9265;14335,10265;15335,10265;15335,9765)"); EXPECT_EQ (right_of[3].to_string (), "(15668,9932;15335,10265;15835,10265;15835,10015)"); } } TEST(9d) { std::vector c; c.push_back (db::Point (17335, 8265)); c.push_back (db::Point (16335, 9265)); c.push_back (db::Point (15335, 9265)); c.push_back (db::Point (15335, 9765)); c.push_back (db::Point (15668, 9932)); c.push_back (db::Point (15835, 9765)); c.push_back (db::Point (16002, 9932)); c.push_back (db::Point (15835, 10015)); c.push_back (db::Point (15668, 9932)); c.push_back (db::Point (15335, 10265)); c.push_back (db::Point (17335, 10265)); db::Polygon in; db::Polygon::contour_type contour; contour.assign (c.begin (), c.end (), false, false, true); in.assign_hull (contour); std::vector right_of; db::cut_polygon (in, db::Edge (db::Point (16002, 0), db::Point (16002, 1)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (1)); EXPECT_EQ (right_of[0].to_string (), "(17335,8265;16335,9265;16002,9265;16002,10265;17335,10265)"); right_of.clear (); db::cut_polygon (in, db::Edge (db::Point (16002, 1), db::Point (16002, 0)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (2)); EXPECT_EQ (right_of[0].to_string (), "(15668,9932;15335,10265;16002,10265;16002,9932;15835,10015)"); EXPECT_EQ (right_of[1].to_string (), "(15335,9265;15335,9765;15668,9932;15835,9765;16002,9932;16002,9265)"); } TEST(10) { // Simple test for polygon-box/edge interaction (integer coordinates) db::Polygon poly; db::Point p[] = { db::Point (0, 100), db::Point (100, 100), db::Point (0, 0) }; poly.assign_hull (p, p + sizeof (p) / sizeof (p[0])); EXPECT_EQ (interact (poly, db::Edge (-10, -10, -1, -1)), false); EXPECT_EQ (interact (poly, db::Edge (-10, -10, 0, 0)), true); EXPECT_EQ (interact (poly, db::Edge (-10, -10, 1, 1)), true); EXPECT_EQ (interact (poly, db::Edge (-10, -10, 20, 10)), false); EXPECT_EQ (interact (poly, db::Edge (-10, -10, 10, 20)), true); EXPECT_EQ (interact (poly, db::Edge (10, 20, 20, 30)), true); EXPECT_EQ (interact (poly, db::Edge (10, 20, 15, 25)), true); EXPECT_EQ (interact (poly, db::Edge (30, 10, 40, 20)), false); EXPECT_EQ (interact (poly, db::Edge (30, 20, 40, 50)), true); EXPECT_EQ (interact (poly, db::Edge (-10, 20, 0, 30)), true); EXPECT_EQ (interact (poly, db::Edge (-10, 20, -5, 30)), false); EXPECT_EQ (interact (poly, db::Edge (-10, 100, -5, 110)), false); EXPECT_EQ (interact (poly, db::Edge (-10, 100, 0, 110)), false); EXPECT_EQ (interact (poly, db::Edge (-10, 100, 5, 100)), true); EXPECT_EQ (interact (db::Box (0, 0, 100, 100), db::Box (-10, 100, 5, 110)), true); EXPECT_EQ (interact (db::Box (0, 0, 100, 100), db::Box (-10, -10, 110, 110)), true); EXPECT_EQ (interact (db::Box (0, 0, 100, 100), db::Box (-10, -10, 50, 110)), true); EXPECT_EQ (interact (db::Box (0, 0, 100, 100), db::Box ()), false); EXPECT_EQ (interact (poly, db::Box (-10, -10, -1, -1)), false); EXPECT_EQ (interact (poly, db::Box (-10, -10, 0, 0)), true); EXPECT_EQ (interact (poly, db::Box (-10, -10, 1, 1)), true); EXPECT_EQ (interact (poly, db::Box (-10, -10, 20, 10)), true); EXPECT_EQ (interact (poly, db::Box (10, 20, 20, 30)), true); EXPECT_EQ (interact (poly, db::Box (10, 20, 15, 25)), true); EXPECT_EQ (interact (poly, db::Box (30, 10, 40, 20)), false); EXPECT_EQ (interact (poly, db::Box (30, 20, 40, 30)), true); EXPECT_EQ (interact (poly, db::Box (-10, 20, 0, 30)), true); EXPECT_EQ (interact (poly, db::Box (-10, 20, -5, 30)), false); EXPECT_EQ (interact (poly, db::Box (-10, 100, -5, 110)), false); EXPECT_EQ (interact (poly, db::Box (-10, 100, 0, 110)), true); EXPECT_EQ (interact (poly, db::Box (-10, 100, 5, 110)), true); EXPECT_EQ (interact (db::Polygon (db::Box (0, 0, 100, 100)), db::Box (-10, 100, 5, 110)), true); EXPECT_EQ (interact (db::Polygon (db::Box (0, 0, 100, 100)), db::Box (-10, -10, 110, 110)), true); EXPECT_EQ (interact (db::Polygon (db::Box (0, 0, 100, 100)), db::Box (-10, -10, 50, 110)), true); EXPECT_EQ (interact (db::Polygon (db::Box (0, 0, 100, 100)), db::Box ()), false); EXPECT_EQ (interact (db::Polygon (), db::Box (-10, -10, 50, 110)), false); EXPECT_EQ (interact (poly, db::Polygon (db::Box (-10, -10, -1, -1))), false); EXPECT_EQ (interact (poly, db::Polygon (db::Box (-10, -10, 0, 0))), true); EXPECT_EQ (interact (poly, db::Polygon (db::Box (-10, -10, 1, 1))), true); EXPECT_EQ (interact (poly, db::Polygon (db::Box (-10, -10, 20, 10))), true); EXPECT_EQ (interact (poly, db::Polygon (db::Box (10, 20, 20, 30))), true); EXPECT_EQ (interact (poly, db::Polygon (db::Box (10, 20, 15, 25))), true); EXPECT_EQ (interact (poly, db::Polygon (db::Box (30, 10, 40, 20))), false); EXPECT_EQ (interact (poly, db::Polygon (db::Box (30, 20, 40, 30))), true); EXPECT_EQ (interact (poly, db::Polygon (db::Box (-10, 20, 0, 30))), true); EXPECT_EQ (interact (poly, db::Polygon (db::Box (-10, 20, -5, 30))), false); EXPECT_EQ (interact (poly, db::Polygon (db::Box (-10, 100, -5, 110))), false); EXPECT_EQ (interact (poly, db::Polygon (db::Box (-10, 100, 0, 110))), true); EXPECT_EQ (interact (poly, db::Polygon (db::Box (-10, 100, 5, 110))), true); EXPECT_EQ (interact (db::Polygon (db::Box (0, 0, 100, 100)), db::Polygon (db::Box (-10, 100, 5, 110))), true); EXPECT_EQ (interact (db::Polygon (db::Box (0, 0, 100, 100)), db::Polygon (db::Box (-10, -10, 110, 110))), true); EXPECT_EQ (interact (db::Polygon (db::Box (0, 0, 100, 100)), db::Polygon (db::Box (-10, -10, 50, 110))), true); EXPECT_EQ (interact (db::Polygon (), db::Polygon (db::Box (-10, -10, 50, 110))), false); EXPECT_EQ (interact (db::Polygon (db::Box (0, 0, 100, 100)), db::Polygon ()), false); EXPECT_EQ (interact (db::Polygon (db::Box (0, 0, 100, 100)), db::Polygon (db::Box ())), false); EXPECT_EQ (interact (db::Polygon (db::Box (-10, -10, -1, -1)), poly), false); EXPECT_EQ (interact (db::Polygon (db::Box (-10, -10, 0, 0)), poly), true); EXPECT_EQ (interact (db::Polygon (db::Box (-10, -10, 1, 1)), poly), true); EXPECT_EQ (interact (db::Polygon (db::Box (-10, -10, 20, 10)), poly), true); EXPECT_EQ (interact (db::Polygon (db::Box (10, 20, 20, 30)), poly), true); EXPECT_EQ (interact (db::Polygon (db::Box (10, 20, 15, 25)), poly), true); EXPECT_EQ (interact (db::Polygon (db::Box (30, 10, 40, 20)), poly), false); EXPECT_EQ (interact (db::Polygon (db::Box (30, 20, 40, 30)), poly), true); EXPECT_EQ (interact (db::Polygon (db::Box (-10, 20, 0, 30)), poly), true); EXPECT_EQ (interact (db::Polygon (db::Box (-10, 20, -5, 30)), poly), false); EXPECT_EQ (interact (db::Polygon (db::Box (-10, 100, -5, 110)), poly), false); EXPECT_EQ (interact (db::Polygon (db::Box (-10, 100, 0, 110)), poly), true); EXPECT_EQ (interact (db::Polygon (db::Box (-10, 100, 5, 110)), poly), true); EXPECT_EQ (interact (db::Polygon (db::Box (-10, 100, 5, 110)), db::Polygon (db::Box (0, 0, 100, 100))), true); EXPECT_EQ (interact (db::Polygon (db::Box (-10, -10, 110, 110)), db::Polygon (db::Box (0, 0, 100, 100))), true); EXPECT_EQ (interact (db::Polygon (db::Box (-10, -10, 50, 110)), db::Polygon (db::Box (0, 0, 100, 100))), true); } TEST(11) { // Simple test for polygon-box interaction (double coordinates) db::DPolygon poly; db::DPoint p[] = { db::DPoint (0, 100), db::DPoint (100, 100), db::DPoint (0, 0) }; poly.assign_hull (p, p + sizeof (p) / sizeof (p[0])); EXPECT_EQ (interact (poly, db::DEdge (-1.0, -1.0, -0.1, -0.1)), false); EXPECT_EQ (interact (poly, db::DEdge (-10, -10, 0, 0)), true); EXPECT_EQ (interact (poly, db::DEdge (-0.01, -0.01, 0.001, 0.001)), true); EXPECT_EQ (interact (poly, db::DEdge (-10, -10, 20, 10)), false); EXPECT_EQ (interact (poly, db::DEdge (-10, -10, 10, 20)), true); EXPECT_EQ (interact (poly, db::DEdge (10, 20, 20, 30)), true); EXPECT_EQ (interact (poly, db::DEdge (10, 20, 15, 25)), true); EXPECT_EQ (interact (poly, db::DEdge (30, 10, 40, 20)), false); EXPECT_EQ (interact (poly, db::DEdge (30, 20, 40, 50)), true); EXPECT_EQ (interact (poly, db::DEdge (-10, 20, 0, 30)), true); EXPECT_EQ (interact (poly, db::DEdge (-10, 20, -5, 30)), false); EXPECT_EQ (interact (poly, db::DEdge (-10, 100, -5, 110)), false); EXPECT_EQ (interact (poly, db::DEdge (-10.0, 100.0, 0.0, 100.5)), false); EXPECT_EQ (interact (poly, db::DEdge (-10, 100, 5, 100)), true); EXPECT_EQ (interact (db::DBox (0, 0, 100, 100), db::DBox (-10, 100, 5, 110)), true); EXPECT_EQ (interact (db::DBox (0, 0, 100, 100), db::DBox (-10, -10, 110, 110)), true); EXPECT_EQ (interact (db::DBox (0, 0, 100, 100), db::DBox (-10, -10, 50, 110)), true); EXPECT_EQ (interact (db::DBox (0, 0, 100, 100), db::DBox ()), false); EXPECT_EQ (interact (poly, db::DBox (-10, -10, -1, -1)), false); EXPECT_EQ (interact (poly, db::DBox (-10, -10, 0, 0)), true); EXPECT_EQ (interact (poly, db::DBox (-10, -10, 1, 1)), true); EXPECT_EQ (interact (poly, db::DBox (-10, -10, 20, 10)), true); EXPECT_EQ (interact (poly, db::DBox (10, 20, 20, 30)), true); EXPECT_EQ (interact (poly, db::DBox (10, 20, 15, 25)), true); EXPECT_EQ (interact (poly, db::DBox (30, 10, 40, 20)), false); EXPECT_EQ (interact (poly, db::DBox (30, 20, 40, 30)), true); EXPECT_EQ (interact (poly, db::DBox (-10, 20, 0, 30)), true); EXPECT_EQ (interact (poly, db::DBox (-10, 20, -5, 30)), false); EXPECT_EQ (interact (poly, db::DBox (-10, 100, -5, 110)), false); EXPECT_EQ (interact (poly, db::DBox (-10, 100, 0, 110)), true); EXPECT_EQ (interact (poly, db::DBox (-10, 100, 5, 110)), true); EXPECT_EQ (interact (db::DPolygon (db::DBox (0, 0, 100, 100)), db::DBox (-10, 100, 5, 110)), true); EXPECT_EQ (interact (db::DPolygon (db::DBox (0, 0, 100, 100)), db::DBox (-10, -10, 110, 110)), true); EXPECT_EQ (interact (db::DPolygon (db::DBox (0, 0, 100, 100)), db::DBox (-10, -10, 50, 110)), true); EXPECT_EQ (interact (db::DPolygon (db::DBox (0, 0, 100, 100)), db::DBox ()), false); EXPECT_EQ (interact (db::DPolygon (), db::DBox (-10, -10, 50, 110)), false); EXPECT_EQ (interact (poly, db::DPolygon (db::DBox (-10, -10, -1, -1))), false); EXPECT_EQ (interact (poly, db::DPolygon (db::DBox (-10, -10, 0, 0))), true); EXPECT_EQ (interact (poly, db::DPolygon (db::DBox (-10, -10, 1, 1))), true); EXPECT_EQ (interact (poly, db::DPolygon (db::DBox (-10, -10, 20, 10))), true); EXPECT_EQ (interact (poly, db::DPolygon (db::DBox (10, 20, 20, 30))), true); EXPECT_EQ (interact (poly, db::DPolygon (db::DBox (10, 20, 15, 25))), true); EXPECT_EQ (interact (poly, db::DPolygon (db::DBox (30, 10, 40, 20))), false); // That is a numerical problem: this test fails // EXPECT_EQ (interact (poly, db::DPolygon (db::DBox (30, 20, 40, 30))), true); EXPECT_EQ (interact (poly, db::DPolygon (db::DBox (-10, 20, 0, 30))), true); EXPECT_EQ (interact (poly, db::DPolygon (db::DBox (-10, 20, -5, 30))), false); EXPECT_EQ (interact (poly, db::DPolygon (db::DBox (-10, 100, -5, 110))), false); EXPECT_EQ (interact (poly, db::DPolygon (db::DBox (-10, 100, 0, 110))), true); EXPECT_EQ (interact (poly, db::DPolygon (db::DBox (-10, 100, 5, 110))), true); EXPECT_EQ (interact (db::DPolygon (db::DBox (0, 0, 100, 100)), db::DPolygon (db::DBox (-10, 100, 5, 110))), true); EXPECT_EQ (interact (db::DPolygon (db::DBox (0, 0, 100, 100)), db::DPolygon (db::DBox (-10, -10, 110, 110))), true); EXPECT_EQ (interact (db::DPolygon (db::DBox (0, 0, 100, 100)), db::DPolygon (db::DBox (-10, -10, 50, 110))), true); EXPECT_EQ (interact (db::DPolygon (), db::DPolygon (db::DBox (-10, -10, 50, 110))), false); EXPECT_EQ (interact (db::DPolygon (db::DBox (0, 0, 100, 100)), db::DPolygon ()), false); EXPECT_EQ (interact (db::DPolygon (db::DBox (0, 0, 100, 100)), db::DPolygon (db::DBox ())), false); EXPECT_EQ (interact (db::DPolygon (db::DBox (-10, -10, -1, -1)), poly), false); EXPECT_EQ (interact (db::DPolygon (db::DBox (-10, -10, 0, 0)), poly), true); EXPECT_EQ (interact (db::DPolygon (db::DBox (-10, -10, 1, 1)), poly), true); EXPECT_EQ (interact (db::DPolygon (db::DBox (-10, -10, 20, 10)), poly), true); EXPECT_EQ (interact (db::DPolygon (db::DBox (10, 20, 20, 30)), poly), true); EXPECT_EQ (interact (db::DPolygon (db::DBox (10, 20, 15, 25)), poly), true); EXPECT_EQ (interact (db::DPolygon (db::DBox (30, 10, 40, 20)), poly), false); // That is a numerical problem: this test fails // EXPECT_EQ (interact (db::DPolygon (db::DBox (30, 20, 40, 30)), poly), true); EXPECT_EQ (interact (db::DPolygon (db::DBox (-10, 20, 0, 30)), poly), true); EXPECT_EQ (interact (db::DPolygon (db::DBox (-10, 20, -5, 30)), poly), false); EXPECT_EQ (interact (db::DPolygon (db::DBox (-10, 100, -5, 110)), poly), false); EXPECT_EQ (interact (db::DPolygon (db::DBox (-10, 100, 0, 110)), poly), true); EXPECT_EQ (interact (db::DPolygon (db::DBox (-10, 100, 5, 110)), poly), true); EXPECT_EQ (interact (db::DPolygon (db::DBox (-10, 100, 5, 110)), db::DPolygon (db::DBox (0, 0, 100, 100))), true); EXPECT_EQ (interact (db::DPolygon (db::DBox (-10, -10, 110, 110)), db::DPolygon (db::DBox (0, 0, 100, 100))), true); EXPECT_EQ (interact (db::DPolygon (db::DBox (-10, -10, 50, 110)), db::DPolygon (db::DBox (0, 0, 100, 100))), true); } TEST(12) { // Simple test for polygon-box interaction (integer coordinates) db::Polygon poly; db::Point p[] = { db::Point (3595000+960,3812000+680), db::Point (3595000+960,3812000+1080), db::Point (3595000+680,3812000+1080), db::Point (3595000+680,3812000+1320), db::Point (3595000+1720,3812000+1320), db::Point (3595000+1720,3812000+1080), db::Point (3595000+1240,3812000+1080), db::Point (3595000+1240,3812000+680) }; poly.assign_hull (p, p + sizeof (p) / sizeof (p[0])); db::Polygon poly2; db::Point p2[] = { db::Point (3595000+660-1000,3812000+480-1000), db::Point (3595000+660-1000,3812000+520), db::Point (3595000+480,3812000+520), db::Point (3595000+480,3812000+880), db::Point (3595000+760,3812000+880), db::Point (3595000+760,3812000+520), db::Point (3595000+1460,3812000+520), db::Point (3595000+1460,3812000+830), db::Point (3595000+1720,3812000+830), db::Point (3595000+1720,3812000+520), db::Point (3595000+1940,3812000+520), db::Point (3595000+1940,3812000+480-1000) }; poly2.assign_hull (p2, p2 + sizeof (p2) / sizeof (p2[0])); EXPECT_EQ (interact (poly, poly2), false); EXPECT_EQ (interact (poly2, poly), false); } static std::string am_to_string (const db::AreaMap &am) { std::string r; for (size_t i = 0; i < am.ny (); ++i) { if (i > 0) { r += ","; } r += "("; for (size_t j = 0; j < am.nx (); ++j) { if (j > 0) { r += ","; } r += tl::to_string (am.get (j, i)); } r += ")"; } return r; } TEST(20) { db::Box box (100, 100, 500, 500); db::Polygon in (box); db::AreaMap am (db::Point (0, 0), db::Vector (200, 200), 3, 3); db::rasterize (in, am); EXPECT_EQ (am_to_string (am), "(10000,20000,10000),(20000,40000,20000),(10000,20000,10000)"); } TEST(21) { db::Box box (200, 200, 400, 400); db::Polygon in (box); db::AreaMap am (db::Point (0, 0), db::Vector (200, 200), 3, 3); db::rasterize (in, am); EXPECT_EQ (am_to_string (am), "(0,0,0),(0,40000,0),(0,0,0)"); } TEST(22) { db::Box box (250, 250, 350, 350); db::Polygon in (box); db::AreaMap am (db::Point (0, 0), db::Vector (200, 200), 3, 3); db::rasterize (in, am); EXPECT_EQ (am_to_string (am), "(0,0,0),(0,10000,0),(0,0,0)"); } TEST(23) { db::Box box (-1000, -500, 2000, 3000); db::Polygon in (box); db::AreaMap am (db::Point (0, 0), db::Vector (200, 200), 3, 3); db::rasterize (in, am); EXPECT_EQ (am_to_string (am), "(40000,40000,40000),(40000,40000,40000),(40000,40000,40000)"); } TEST(24) { db::Point p[3] = { db::Point (0, 100), db::Point (500, 500), db::Point (0, 0) }; db::Polygon in; in.assign_hull (&p[0], &p[3]); db::AreaMap am (db::Point (0, 0), db::Vector (100, 100), 5, 5); db::rasterize (in, am); EXPECT_EQ (am_to_string (am), "(5000,0,0,0,0),(4000,4750,0,0,0),(0,2250,4000,0,0),(0,0,1000,2750,0),(0,0,0,250,1000)"); EXPECT_EQ (am.total_area (), 25000); } TEST(25) { db::Point p[3] = { db::Point (0, 100), db::Point (600, 500), db::Point (300, 0) }; db::Polygon in; in.assign_hull (&p[0], &p[3]); db::AreaMap am (db::Point (0, 0), db::Vector (100, 100), 5, 5); db::rasterize (in, am); EXPECT_EQ (am_to_string (am), "(1650,5000,8350,3000,0),(3350,9175,10000,8660,330),(0,825,6650,10000,5000),(0,0,0,3350,8845),(0,0,0,0,825)"); EXPECT_EQ (am.total_area (), 85010); am.reinitialize (db::Point (0, 0), db::Vector (100, 100), db::Vector (50, 50), 5, 5); db::rasterize (in, am); EXPECT_EQ (am_to_string (am), "(0,0,1250,750,0),(825,2500,2500,2500,0),(0,0,2287,2500,1750),(0,0,0,825,2500),(0,0,0,0,0)"); EXPECT_EQ (am.total_area (), 20187); am.reinitialize (db::Point (200, 0), db::Vector (100, 100), db::Vector (50, 50), 1, 1); db::rasterize (in, am); EXPECT_EQ (am_to_string (am), "(1250)"); am.reinitialize (db::Point (300, 0), db::Vector (100, 100), db::Vector (50, 50), 1, 1); db::rasterize (in, am); EXPECT_EQ (am_to_string (am), "(750)"); am.reinitialize (db::Point (400, 0), db::Vector (100, 100), db::Vector (50, 50), 1, 1); db::rasterize (in, am); EXPECT_EQ (am_to_string (am), "(0)"); am.reinitialize (db::Point (400, 100), db::Vector (100, 100), db::Vector (50, 50), 1, 1); db::rasterize (in, am); EXPECT_EQ (am_to_string (am), "(0)"); am.reinitialize (db::Point (400, 200), db::Vector (100, 100), db::Vector (50, 50), 1, 1); db::rasterize (in, am); EXPECT_EQ (am_to_string (am), "(1750)"); } TEST(26) { db::Point p[10] = { db::Point (0, 300), db::Point (300, 300), db::Point (300, 0), db::Point (100, 0), db::Point (100, 100), db::Point (200, 100), db::Point (200, 200), db::Point (100, 200), db::Point (100, 0), db::Point (0, 0) }; db::Polygon in; in.assign_hull (&p[0], &p[10]); db::AreaMap am (db::Point (0, 0), db::Vector (100, 100), 3, 3); db::rasterize (in, am); EXPECT_EQ (am_to_string (am), "(10000,10000,10000),(10000,0,10000),(10000,10000,10000)"); } TEST(27) { db::Point p[10] = { db::Point (-100, 400), db::Point (400, 400), db::Point (400, -100), db::Point (100, -100), db::Point (100, 100), db::Point (200, 100), db::Point (200, 200), db::Point (100, 200), db::Point (100, -100), db::Point (-100, -100) }; db::Polygon in; in.assign_hull (&p[0], &p[10]); db::AreaMap am (db::Point (0, 0), db::Vector (100, 100), 3, 3); db::rasterize (in, am); EXPECT_EQ (am_to_string (am), "(10000,10000,10000),(10000,0,10000),(10000,10000,10000)"); } TEST(28) { db::Point p[10] = { db::Point (-100, 400), db::Point (400, 400), db::Point (400, -100), db::Point (120, -100), db::Point (120, 120), db::Point (180, 120), db::Point (180, 180), db::Point (120, 180), db::Point (120, -100), db::Point (-100, -100) }; db::Polygon in; in.assign_hull (&p[0], &p[10]); db::AreaMap am (db::Point (0, 0), db::Vector (100, 100), 3, 3); db::rasterize (in, am); EXPECT_EQ (am_to_string (am), "(10000,10000,10000),(10000,6400,10000),(10000,10000,10000)"); } TEST(29) { db::Point p[] = { db::Point (1600,7009), db::Point (1600,7351), db::Point (1335,8538), db::Point (1341,8545), db::Point (1669,8545), db::Point (1669,7009) }; db::Polygon in; in.assign_hull (&p[0], &p[sizeof(p)/sizeof(p[0])]); db::AreaMap am (db::Point (1360,7038), db::Vector (60,60), 6, 26); db::rasterize (in, am); EXPECT_EQ (am_to_string (am), "(0,0,0,0,3600,540),(0,0,0,0,3600,540),(0,0,0,0,3600,540),(0,0,0,0,3600,540),(0,0,0,0,3600,540),(0,0,0,235,3600,540),(0,0,0,1020,3600,540),(0,0,0,1830,3600,540),(0,0,0,2640,3600,540),(0,0,36,3411,3600,540),(0,0,630,3600,3600,540),(0,0,1440,3600,3600,540),(0,0,2250,3600,3600,540),(0,0,3060,3600,3600,540),(0,269,3589,3600,3600,540),(0,1050,3600,3600,3600,540),(0,1860,3600,3600,3600,540),(0,2670,3600,3600,3600,540),(52,3424,3600,3600,3600,540),(690,3600,3600,3600,3600,540),(1470,3600,3600,3600,3600,540),(2280,3600,3600,3600,3600,540),(3090,3600,3600,3600,3600,540),(3592,3600,3600,3600,3600,540),(3600,3600,3600,3600,3600,540),(420,420,420,420,420,63)"); } TEST(30) { db::Point p[] = { db::Point (7161,-9547), db::Point (7128,-9531), db::Point (7128,-9198), db::Point (7398,-9198), db::Point (7398,-8928), db::Point (7668,-8928), db::Point (7668,-8658), db::Point (7938,-8658), db::Point (7938,-8388), db::Point (8208,-8388), db::Point (8208,-8118), db::Point (8478,-8118), db::Point (8478,-7848), db::Point (8748,-7848), db::Point (8748,-7578), db::Point (9045,-7578), db::Point (9061,-7610), db::Point (8951,-7759), db::Point (8550,-8245), db::Point (8121,-8703), db::Point (7661,-9133) }; db::Polygon in; in.assign_hull (&p[0], &p[sizeof(p)/sizeof(p[0])]); db::AreaMap am (db::Point (7128,-9547), db::Vector (81,82), 24, 25); db::rasterize (in, am); EXPECT_EQ (am_to_string (am), "(5418,1071,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),(6642,6267,1967,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),(6642,6642,6582,3119,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),(6642,6642,6642,6642,4317,240,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),(1701,1701,1701,4995,6642,5303,735,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,4428,6642,6642,5952,1127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,4428,6642,6642,6642,6178,1484,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,2430,3645,3645,4644,6642,6355,1859,0,0,0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,2214,6642,6642,6489,2275,0,0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,2214,6642,6642,6642,6582,2698,0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,1863,5589,5589,5589,6642,6632,2994,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,6642,6642,6624,2698,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,6642,6642,6642,6587,2379,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,6642,6642,6642,6642,6537,2111,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,891,891,891,4725,6642,6471,1859,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0,0,4428,6642,6642,6378,1570,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0,0,4428,6642,6642,6642,6166,960,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0,0,1890,2835,2835,4104,6642,5617,432,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2214,6642,6642,4860,104,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2214,6642,6642,6642,3854,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1593,4779,4779,4779,6642,2788,0,0),(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6642,6538,1777,0),(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6642,6642,6110,704),(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6642,6642,6642,4539),(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,81,81,81,55)"); } TEST(41) { db::Point pattern [] = { db::Point (0, -100), db::Point (0, -50), db::Point (-100, -75), db::Point (0, 100), db::Point (50, 50), db::Point (100, 75), db::Point (100, 0), db::Point (100, -50) }; db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); db::Polygon pout = minkowski_sum (p, db::Edge (db::Point (10, 10), db::Point (210, 110)), true); EXPECT_EQ (pout.to_string (), "(10,-90;10,-40;-90,-65;10,110;210,210;260,160;310,185;310,60)"); pout = minkowski_sum (p, db::Edge (db::Point (10, 10), db::Point (10, 110)), true); EXPECT_EQ (pout.to_string (), "(10,-90;10,-40;-90,-65;-90,35;10,210;60,160;110,185;110,-40)"); pout = minkowski_sum (p, db::Edge (db::Point (10, 110), db::Point (10, 10)), true); EXPECT_EQ (pout.to_string (), "(10,-90;10,-40;-90,-65;-90,35;10,210;60,160;110,185;110,-40)"); pout = minkowski_sum (p, db::Edge (db::Point (10, 10), db::Point (210, 10)), true); EXPECT_EQ (pout.to_string (), "(10,-90;10,-65;-90,-65;10,110;210,110;235,85;310,85;310,-40;210,-90)"); pout = minkowski_sum (p, db::Edge (db::Point (210, 10), db::Point (10, 10)), true); EXPECT_EQ (pout.to_string (), "(10,-90;10,-65;-90,-65;10,110;210,110;235,85;310,85;310,-40;210,-90)"); pout = minkowski_sum (p, db::Edge (db::Point (10, 10), db::Point (210, -90)), true); EXPECT_EQ (pout.to_string (), "(210,-190;143,-157;110,-165;-90,-65;10,110;85,72;110,85;310,-15;310,-140)"); std::vector c; c.push_back (db::Point (10, 10)); c.push_back (db::Point (10, 110)); c.push_back (db::Point (210, 110)); c.push_back (db::Point (210, 10)); c.push_back (db::Point (10, 10)); pout = minkowski_sum (p, c, true); EXPECT_EQ (pout.to_string (), "(10,-90;10,-65;-90,-65;-90,35;10,210;210,210;235,185;310,185;310,-40;210,-90)"); c.clear (); c.push_back (db::Point (10, 10)); c.push_back (db::Point (10, 310)); c.push_back (db::Point (510, 310)); c.push_back (db::Point (510, 10)); c.push_back (db::Point (10, 10)); pout = minkowski_sum (p, c, true); EXPECT_EQ (pout.to_string (), "(10,-90;10,-65;-90,-65;-90,210;110,210;110,110;410,110;410,210;-90,210;-90,235;10,410;510,410;535,385;610,385;610,-40;510,-90)"); // test hole resolution btw EXPECT_EQ (db::resolve_holes (pout).to_string (), "(10,-90;10,-65;-90,-65;-90,210;110,210;110,110;410,110;410,210;-90,210;-90,235;10,410;510,410;535,385;610,385;610,-40;510,-90)"); EXPECT_EQ (db::polygon_to_simple_polygon (pout).to_string (), "(10,-90;10,-65;-90,-65;-90,210;110,210;110,110;410,110;410,210;-90,210;-90,235;10,410;510,410;535,385;610,385;610,-40;510,-90)"); pout = minkowski_sum (p, c, false); EXPECT_EQ (pout.to_string (), "(10,-90;10,-65;-90,-65;-90,235;10,410;510,410;535,385;610,385;610,-40;510,-90/110,110;410,110;410,210;110,210)"); // test hole resolution btw EXPECT_EQ (db::resolve_holes (pout).to_string (), "(10,-90;10,-65;-90,-65;-90,210;110,210;110,110;410,110;410,210;-90,210;-90,235;10,410;510,410;535,385;610,385;610,-40;510,-90)"); EXPECT_EQ (db::polygon_to_simple_polygon (pout).to_string (), "(10,-90;10,-65;-90,-65;-90,210;110,210;110,110;410,110;410,210;-90,210;-90,235;10,410;510,410;535,385;610,385;610,-40;510,-90)"); EXPECT_EQ (db::simple_polygon_to_polygon (db::polygon_to_simple_polygon (pout)).to_string (), "(10,-90;10,-65;-90,-65;-90,210;110,210;110,110;410,110;410,210;-90,210;-90,235;10,410;510,410;535,385;610,385;610,-40;510,-90)"); pout = minkowski_sum (p, db::Box (db::Point (10, 10), db::Point (210, 110)), true); EXPECT_EQ (pout.to_string (), "(10,-90;10,-65;-90,-65;-90,35;10,210;210,210;235,185;310,185;310,-40;210,-90)"); pout = minkowski_sum (p, db::Box (db::Point (10, 10), db::Point (510, 310)), false); EXPECT_EQ (pout.to_string (), "(10,-90;10,-65;-90,-65;-90,235;10,410;510,410;535,385;610,385;610,-40;510,-90)"); } TEST(42) { db::Point pattern [] = { db::Point (0, -100), db::Point (0, -50), db::Point (-100, -75), db::Point (0, 100), db::Point (50, 50), db::Point (100, 75), db::Point (100, 0), db::Point (100, -50) }; db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); db::Point hole [] = { db::Point (20, -67), db::Point (20, -30), db::Point (15, -26), db::Point (-60, -45), db::Point (4, 68), db::Point (46, 26), db::Point (80, 43), db::Point (80, -37) }; p.insert_hole (&hole[0], &hole[0] + sizeof (hole) / sizeof (hole[0])); db::Polygon pout = minkowski_sum (p, db::Edge (db::Point (10, 10), db::Point (30, 10)), true); EXPECT_EQ (pout.to_string (), "(10,-90;10,-45;-70,-65;-90,-65;-15,65;27,65;-27,-29;25,-16;45,-16;50,-20;50,-47;90,-27;90,43;76,36;56,36;27,65;-15,65;-8,78;10,110;30,110;73,67;110,85;130,85;130,-40;30,-90)"); pout = minkowski_sum (p, db::Edge (db::Point (10, 10), db::Point (110, 110)), true); EXPECT_EQ (pout.to_string (), "(10,-90;10,-40;-90,-65;-8,78;10,110;110,210;160,160;210,185;210,60;110,-40)"); pout = minkowski_sum (p, db::Edge (db::Point (10, 10), db::Point (50, 10)), true); EXPECT_EQ (pout.to_string (), "(10,-90;10,-50;-50,-65;-90,-65;-23,52;40,52;-3,-23;25,-16;65,-16;70,-20;70,-37;90,-27;90,36;56,36;40,52;-23,52;-8,78;10,110;50,110;87,73;110,85;150,85;150,-40;50,-90)"); } // smoothing TEST(100) { db::Point pattern [] = { db::Point (0, -100), db::Point (0, 0), db::Point (50, 10), db::Point (100, -10), db::Point (150, 0), db::Point (150, -100), }; db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); EXPECT_EQ (smooth (p, 5, true).to_string (), "(0,-100;0,0;50,10;100,-10;150,0;150,-100)"); EXPECT_EQ (smooth (p, 20, true).to_string (), "(0,-100;0,0;150,0;150,-100)"); } // smoothing TEST(101) { db::Point pattern [] = { db::Point (0, 0), db::Point (50, 10), db::Point (100, -10), db::Point (150, 0), db::Point (150, 100), db::Point (0, 100), }; db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); EXPECT_EQ (smooth (p, 5, true).to_string (), "(100,-10;50,10;0,0;0,100;150,100;150,0)"); EXPECT_EQ (smooth (p, 20, true).to_string (), "(0,0;0,100;150,100;150,0)"); } // smoothing TEST(102) { db::Point pattern [] = { db::Point (0, 0), db::Point (50, 10), db::Point (100, -10), db::Point (150, 0), }; db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); EXPECT_EQ (smooth (p, 20, true).to_string (), "()"); EXPECT_EQ (smooth (p, 5, true).to_string (), "(100,-10;150,0;0,0;50,10)"); } // smoothing TEST(103) { db::Point pattern [] = { db::Point (56852, -237283), db::Point (56961, -237258), db::Point (60061, -236492), db::Point (63152, -235686), db::Point (66231, -234839), db::Point (69300, -233952), db::Point (69407, -233919), db::Point (73105, -246382), db::Point (72992, -246417), db::Point (69760, -247351), db::Point (66516, -248243), db::Point (63261, -249092), db::Point (59995, -249899), db::Point (59881, -249925) }; db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); EXPECT_EQ (smooth (p, 0, true).to_string (), "(59881,-249925;56852,-237283;56961,-237258;60061,-236492;63152,-235686;66231,-234839;69300,-233952;69407,-233919;73105,-246382;72992,-246417;69760,-247351;66516,-248243;63261,-249092;59995,-249899)"); EXPECT_EQ (smooth (p, 50, true).to_string (), "(59881,-249925;56852,-237283;63152,-235686;69407,-233919;73105,-246382;69760,-247351)"); EXPECT_EQ (smooth (p, 5000, true).to_string (), "(59881,-249925;56852,-237283;69407,-233919;73105,-246382)"); } // smoothing TEST(104) { db::Point pattern [] = { db::Point (-245, -942), db::Point (-942, -247), db::Point (-942, -246), db::Point (247, 943), db::Point (248, 943), db::Point (943, 246), db::Point (-244, -942) }; db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); EXPECT_EQ (smooth (p, 12, false).to_string (), "(-244,-942;-942,-246;248,943;943,246)"); EXPECT_EQ (smooth (p, 12, true).to_string (), "(-245,-942;-942,-247;-942,-246;247,943;248,943;943,246;-244,-942)"); } // smoothing TEST(105) { db::Point pattern [] = { db::Point (0, 0), db::Point (0, 1000), db::Point (100, 1000), db::Point (100, 1100), db::Point (800, 1100), db::Point (800, 1000), db::Point (2000, 1000), db::Point (2000, 0) }; db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); EXPECT_EQ (smooth (p, 0, false).to_string (), "(0,0;0,1000;100,1000;100,1100;800,1100;800,1000;2000,1000;2000,0)"); EXPECT_EQ (smooth (p, 50, false).to_string (), "(0,0;0,1000;100,1000;100,1100;800,1100;800,1000;2000,1000;2000,0)"); EXPECT_EQ (smooth (p, 80, false).to_string (), "(0,0;0,1000;100,1100;800,1100;800,1000;2000,1000;2000,0)"); EXPECT_EQ (smooth (p, 90, false).to_string (), "(0,0;0,1000;800,1100;800,1000;2000,1000;2000,0)"); EXPECT_EQ (smooth (p, 100, false).to_string (), "(0,0;0,1000;2000,1000;2000,0)"); EXPECT_EQ (smooth (p, 100, true).to_string (), "(0,0;0,1000;100,1000;100,1100;800,1100;800,1000;2000,1000;2000,0)"); } // smoothing TEST(106) { db::Point pattern [] = { db::Point (0, 0), db::Point (0, 73235), db::Point (100, 74568), db::Point (700, 82468), db::Point (1200, 90468), db::Point (2000, 106468), db::Point (2300, 114468), db::Point (2700, 130468), db::Point (2800, 138468), db::Point (2800, 154468), db::Point (2700, 162468), db::Point (2300, 178468), db::Point (2000, 186468), db::Point (1200, 202468), db::Point (700, 210468), db::Point (100, 218368), db::Point (0, 219701), db::Point (0, 272971), db::Point (126450, 272971), db::Point (126450, 0), }; db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); EXPECT_EQ (smooth (p, 0, false).to_string (), "(0,0;0,73235;100,74568;700,82468;1200,90468;2000,106468;2300,114468;2700,130468;2800,138468;2800,154468;2700,162468;2300,178468;2000,186468;1200,202468;700,210468;100,218368;0,219701;0,272971;126450,272971;126450,0)"); EXPECT_EQ (smooth (p, 100, false).to_string (), "(0,0;100,74568;1200,90468;2300,114468;2800,138468;2700,162468;2000,186468;700,210468;0,219701;0,272971;126450,272971;126450,0)"); EXPECT_EQ (smooth (p, 100, true).to_string (), "(0,0;0,73235;1200,90468;2300,114468;2800,138468;2800,154468;2000,186468;700,210468;0,219701;0,272971;126450,272971;126450,0)"); } // rounding TEST(200) { db::Point pattern [] = { db::Point (0, 0), db::Point (100000, 0), db::Point (100000, 100000), db::Point (0, 100000), }; db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); { double rinner = 0.0, router = 0.0; unsigned int n; db::Polygon pr; db::Polygon pp = compute_rounded (p, 0, 20000, 200); EXPECT_EQ (pp.hull ().size (), size_t (200)); EXPECT_EQ (extract_rad (pp, rinner, router, n, &pr), true); EXPECT_EQ (tl::to_string (rinner), "0"); EXPECT_EQ (tl::to_string (router), "20000"); EXPECT_EQ (tl::to_string (n), "200"); EXPECT_EQ (pr.to_string (), "(0,0;0,100000;100000,100000;100000,0)"); } { double rinner = 0.0, router = 0.0; unsigned int n; db::Polygon pr; db::Polygon pp = compute_rounded (p, 0, 50000, 200); EXPECT_EQ (pp.hull ().size (), size_t (200)); EXPECT_EQ (extract_rad (pp, rinner, router, n, &pr), true); EXPECT_EQ (tl::to_string (rinner), "0"); EXPECT_EQ (tl::to_string (router), "50000"); EXPECT_EQ (tl::to_string (n), "200"); EXPECT_EQ (pr.to_string (), "(0,0;0,100000;100000,100000;100000,0)"); } { double rinner = 0.0, router = 0.0; unsigned int n; db::Polygon pr; db::Polygon pp = compute_rounded (p, 0, 70000, 200); EXPECT_EQ (pp.hull ().size (), size_t (200)); EXPECT_EQ (extract_rad (pp, rinner, router, n, &pr), true); EXPECT_EQ (tl::to_string (rinner), "0"); EXPECT_EQ (tl::to_string (router), "50000"); EXPECT_EQ (tl::to_string (n), "200"); EXPECT_EQ (pr.to_string (), "(0,0;0,100000;100000,100000;100000,0)"); } } // rounding TEST(201) { db::Point pattern [] = { db::Point (0, 0), db::Point (50000, 0), db::Point (50000, 100000), db::Point (0, 100000), }; db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); { double rinner = 0.0, router = 0.0; unsigned int n; db::Polygon pr; db::Polygon pp = compute_rounded (p, 0, 50000, 200); EXPECT_EQ (pp.hull ().size (), size_t (200)); EXPECT_EQ (extract_rad (pp, rinner, router, n, &pr), true); EXPECT_EQ (tl::to_string (rinner), "0"); EXPECT_EQ (tl::to_string (router), "25000"); EXPECT_EQ (tl::to_string (n), "200"); EXPECT_EQ (pr.to_string (), "(0,0;0,100000;50000,100000;50000,0)"); } } // rounding TEST(202) { db::Point pattern [] = { db::Point (0, 0), db::Point (0, 600000), db::Point (400000, 600000), db::Point (400000, 400000), db::Point (600000, 400000), db::Point (600000, 0), }; db::Point hole [] = { db::Point (100000, 100000), db::Point (100000, 500000), db::Point (300000, 500000), db::Point (300000, 300000), db::Point (500000, 300000), db::Point (500000, 100000), }; db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); p.insert_hole (&hole[0], &hole[0] + sizeof (hole) / sizeof (hole[0])); { double rinner = 0.0, router = 0.0; unsigned int n; db::Polygon pr; db::Polygon pp = compute_rounded (p, 50000, 150000, 200); EXPECT_EQ (pp.hull ().size (), size_t (300)); EXPECT_EQ (extract_rad (pp, rinner, router, n, &pr), true); EXPECT_EQ (tl::to_string (rinner), "50000"); EXPECT_EQ (tl::to_string (router), "150000"); EXPECT_EQ (tl::to_string (n), "200"); EXPECT_EQ (pr.to_string (), "(0,0;0,600000;400000,600000;400000,400000;600000,400000;600000,0/100000,100000;500000,100000;500000,300000;300000,300000;300000,500000;100000,500000)"); } { double rinner = 0.0, router = 0.0; unsigned int n; db::Polygon pr; db::Polygon pp = compute_rounded (p, 100000, 150000, 200); EXPECT_EQ (pp.hull ().size (), size_t (300)); EXPECT_EQ (extract_rad (pp, rinner, router, n, &pr), true); EXPECT_EQ (tl::to_string (rinner), "92000"); EXPECT_EQ (tl::to_string (router), "120000"); EXPECT_EQ (tl::to_string (n), "200"); EXPECT_EQ (pr.to_string (), "(0,0;0,600000;400000,600000;400000,400000;600000,400000;600000,0/100000,100000;500000,100000;500000,300000;300000,300000;300000,500000;100000,500000)"); } { double rinner = 0.0, router = 0.0; unsigned int n; db::Polygon pr; db::Polygon pp = compute_rounded (p, 50000, 150000, 200); db::EdgeProcessor ep; std::vector in, out; in.push_back (pp); ep.simple_merge (in, out, true /*insert cut line*/); pp = out.front (); in.clear (); out.clear (); in.push_back (pp); ep.simple_merge (in, out, false /*no cut line*/); pp = out.front (); EXPECT_EQ (pp.hull ().size (), size_t (301)); EXPECT_EQ (extract_rad (pp, rinner, router, n, &pr), true); EXPECT_EQ (tl::to_string (rinner), "50000"); EXPECT_EQ (tl::to_string (router), "150000"); EXPECT_EQ (tl::to_string (n), "200"); EXPECT_EQ (pr.to_string (), "(0,0;0,600000;400000,600000;400000,400000;600000,400000;600000,0/100000,100000;500000,100000;500000,300000;300000,300000;300000,500000;100000,500000)"); } } // rounding TEST(203) { db::Point pattern [] = { db::Point (0, 0), db::Point (0, 60000), db::Point (40000, 60000), db::Point (40000, 40000), db::Point (60000, 40000), db::Point (60000, 0), }; db::Point hole [] = { db::Point (10000, 10000), db::Point (10000, 50000), db::Point (30000, 50000), db::Point (30000, 30000), db::Point (50000, 30000), db::Point (50000, 10000), }; db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); p.insert_hole (&hole[0], &hole[0] + sizeof (hole) / sizeof (hole[0])); double rinner = 0.0, router = 0.0; unsigned int n; db::Polygon pr; db::Polygon pp = compute_rounded (p, 5000, 15000, 200); db::EdgeProcessor ep; std::vector in, out; in.push_back (pp); ep.simple_merge (in, out, true /*insert cut line*/); pp = out.front (); in.clear (); out.clear (); in.push_back (pp); ep.simple_merge (in, out, false /*no cut line*/); pp = out.front (); pp = smooth (pp, 1, true); EXPECT_EQ (pp.hull ().size (), size_t (300)); EXPECT_EQ (extract_rad (pp, rinner, router, n, &pr), true); EXPECT_EQ (tl::to_string (rinner), "5000"); EXPECT_EQ (tl::to_string (router), "15000"); EXPECT_EQ (tl::to_string (n), "200"); EXPECT_EQ (pr.to_string (), "(0,0;0,60000;40000,60000;40000,40000;60000,40000;60000,0/10000,10000;50000,10000;50000,30000;30000,30000;30000,50000;10000,50000)"); } // rounding TEST(204) { db::Point pattern [] = { db::Point (0, 0), db::Point (0, 40000), db::Point (40000, 40000), db::Point (40000, 0), }; db::Point hole [] = { db::Point (10000, 10000), db::Point (10000, 30000), db::Point (30000, 30000), db::Point (30000, 10000), }; db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); p.insert_hole (&hole[0], &hole[0] + sizeof (hole) / sizeof (hole[0])); double rinner = 0.0, router = 0.0; unsigned int n; db::Polygon pr; db::Polygon pp = compute_rounded (p, 10000, 20000, 200); db::EdgeProcessor ep; std::vector in, out; in.push_back (pp); ep.simple_merge (in, out, true /*insert cut line*/); pp = out.front (); in.clear (); out.clear (); in.push_back (pp); ep.simple_merge (in, out, false /*no cut line*/); pp = out.front (); pp = smooth (pp, 1, true); EXPECT_EQ (pp.hull ().size (), size_t (200)); EXPECT_EQ (extract_rad (pp, rinner, router, n, &pr), true); EXPECT_EQ (tl::to_string (rinner), "10000"); EXPECT_EQ (tl::to_string (router), "20000"); EXPECT_EQ (tl::to_string (n), "200"); EXPECT_EQ (pr.to_string (), "(0,0;0,40000;40000,40000;40000,0/10000,10000;30000,10000;30000,30000;10000,30000)"); } // rounding TEST(205_issue318) { db::Point pattern [] = { db::Point (0, 0), db::Point (0, 420000), db::Point (400000, 400000), db::Point (400000, 0), }; db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); double rinner = 0.0, router = 0.0; unsigned int n; db::Polygon pr; db::Polygon pp = compute_rounded (p, 100000, 200000, 64); EXPECT_EQ (extract_rad (pp, rinner, router, n, &pr), true); EXPECT_EQ (tl::to_string (rinner), "0"); EXPECT_EQ (tl::to_string (router), "200000"); EXPECT_EQ (tl::to_string (n), "64"); // slight rounding errors, but still a good approximation ... EXPECT_EQ (pr.to_string (), "(0,0;0,419998;400000,400002;400000,0)"); pp = compute_rounded (p, 50000, 100000, 64); EXPECT_EQ (extract_rad (pp, rinner, router, n, &pr), true); EXPECT_EQ (tl::to_string (rinner), "0"); EXPECT_EQ (tl::to_string (router), "100000"); EXPECT_EQ (tl::to_string (n), "64"); // slight rounding issue due to ... EXPECT_EQ (pr.to_string (), "(0,0;0,420001;400000,400000;400000,0)"); } // rounding TEST(206_issue318) { db::Point pattern [] = { db::Point (0, 0), db::Point (0, 40000000), db::Point (400000, 400000), db::Point (400000, 0), }; db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); double rinner = 0.0, router = 0.0; unsigned int n; db::Polygon pr; db::Polygon pp = compute_rounded (p, 100000, 200000, 64); EXPECT_EQ (extract_rad (pp, rinner, router, n, &pr), true); EXPECT_EQ (tl::to_string (rinner), "0"); EXPECT_EQ (tl::to_string (router), "199992"); EXPECT_EQ (tl::to_string (n), "65"); // good approximation of a top edge ... EXPECT_EQ (pr.to_string (), "(0,0;0,618467;400000,581242;400000,0)"); pp = compute_rounded (p, 50000, 100000, 64); EXPECT_EQ (extract_rad (pp, rinner, router, n, &pr), true); EXPECT_EQ (tl::to_string (rinner), "0"); EXPECT_EQ (tl::to_string (router), "100000"); EXPECT_EQ (tl::to_string (n), "64"); // the acute corner is split into two parts EXPECT_EQ (pr.to_string (), "(0,0;0,20309228;199083,20290710;400000,400000;400000,0)"); } // rounding TEST(207_issue318) { db::Point pattern [] = { db::Point(-2523825, -4693678), db::Point(-2627783, -4676814), db::Point(-2705532, -4629488), db::Point(-2747861, -4559084), db::Point(-2750596, -4499543), db::Point(-2753284, -4335751), db::Point(-2764621, -4271381), db::Point(-2828260, -4154562), db::Point(-2808940, -4144038), db::Point(-2743579, -4264019), db::Point(-2731316, -4333649), db::Point(-2728604, -4498857), db::Point(-2726139, -4552516), db::Point(-2689468, -4613512), db::Point(-2620017, -4655786), db::Point(-2529175, -4670522), db::Point(-2468652, -4627768), db::Point(-2437469, -4536777), db::Point(-2434902, -4384723), db::Point(-2436252, -4320529), db::Point(-2395450, -4234678), db::Point(-2338494, -4144716), db::Point(-2319906, -4156484), db::Point(-2376150, -4245322), db::Point(-2414148, -4325271), db::Point(-2412898, -4384677), db::Point(-2415531, -4540623), db::Point(-2450148, -4641632) }; db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); double rinner = 0.0, router = 0.0; unsigned int n; db::Polygon pr; // this polygon should not be recognized as rounded - it kind of looks like ... EXPECT_EQ (extract_rad (p, rinner, router, n, &pr), false); } // is_convex TEST(300) { db::Point pattern [] = { db::Point (0, 0), db::Point (0, 40000), db::Point (40000, 40000), db::Point (40000, 0), }; db::Point hole [] = { db::Point (10000, 10000), db::Point (10000, 30000), db::Point (30000, 30000), db::Point (30000, 10000), }; db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); EXPECT_EQ (db::is_convex (p), true); EXPECT_EQ (db::is_convex (db::polygon_to_simple_polygon (p)), true); p.insert_hole (&hole[0], &hole[0] + sizeof (hole) / sizeof (hole[0])); EXPECT_EQ (db::is_convex (p), false); EXPECT_EQ (db::is_convex (db::polygon_to_simple_polygon (p)), false); EXPECT_EQ (db::is_convex (db::simple_polygon_to_polygon (db::polygon_to_simple_polygon (p))), false); } struct TestPolygonSink : db::SimplePolygonSink { void put (const db::SimplePolygon &p) { if (! s.empty ()) { s += "\n"; } s += p.to_string (); } std::string s; }; // decompose_to_convex TEST(310) { db::Point pattern [] = { db::Point (0, 0), db::Point (0, 40000), db::Point (40000, 40000), db::Point (40000, 0), }; db::Point hole [] = { db::Point (10000, 10000), db::Point (10000, 30000), db::Point (30000, 30000), db::Point (30000, 10000), }; db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); TestPolygonSink ps; db::decompose_convex (p, db::PO_any, ps); EXPECT_EQ (ps.s, "(0,0;0,40000;40000,40000;40000,0)"); ps.s.clear (); db::decompose_convex (db::polygon_to_simple_polygon (p), db::PO_any, ps); EXPECT_EQ (ps.s, "(0,0;0,40000;40000,40000;40000,0)"); p.insert_hole (&hole[0], &hole[0] + sizeof (hole) / sizeof (hole[0])); ps.s.clear (); db::decompose_convex (p, db::PO_any, ps); EXPECT_EQ (ps.s, "(0,10000;0,30000;10000,30000;10000,10000)\n" "(0,30000;0,40000;30000,40000;30000,30000)\n" "(30000,10000;30000,40000;40000,40000;40000,10000)\n" "(0,0;0,10000;40000,10000;40000,0)" ); ps.s.clear (); db::decompose_convex (db::polygon_to_simple_polygon (p), db::PO_any, ps); EXPECT_EQ (ps.s, "(0,30000;0,40000;30000,40000;30000,30000)\n" "(30000,10000;30000,40000;40000,40000;40000,10000)\n" "(10000,0;10000,10000;40000,10000;40000,0)\n" "(0,0;0,30000;10000,30000;10000,0)" ); ps.s.clear (); db::decompose_convex (db::simple_polygon_to_polygon (db::polygon_to_simple_polygon (p)), db::PO_any, ps); EXPECT_EQ (ps.s, "(0,10000;0,30000;10000,30000;10000,10000)\n" "(0,30000;0,40000;30000,40000;30000,30000)\n" "(30000,10000;30000,40000;40000,40000;40000,10000)\n" "(0,0;0,10000;40000,10000;40000,0)" ); } // decompose_to_convex TEST(311) { db::Point pattern [] = { db::Point (0, 0), db::Point (0, 40000), db::Point (40000, 40000), db::Point (40000, 0), }; db::Point hole [] = { db::Point (10000, 10000), db::Point (10000, 30000), db::Point (30000, 30000), db::Point (30000, 10000), }; db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); TestPolygonSink ps; db::decompose_convex (p, db::PO_horizontal, ps); EXPECT_EQ (ps.s, "(0,0;0,40000;40000,40000;40000,0)"); ps.s.clear (); db::decompose_convex (db::polygon_to_simple_polygon (p), db::PO_horizontal, ps); EXPECT_EQ (ps.s, "(0,0;0,40000;40000,40000;40000,0)"); p.insert_hole (&hole[0], &hole[0] + sizeof (hole) / sizeof (hole[0])); ps.s.clear (); db::decompose_convex (p, db::PO_horizontal, ps); EXPECT_EQ (ps.s, "(0,10000;0,30000;10000,30000;10000,10000)\n" "(0,30000;0,40000;40000,40000;40000,30000)\n" "(30000,10000;30000,30000;40000,30000;40000,10000)\n" "(0,0;0,10000;40000,10000;40000,0)" ); ps.s.clear (); db::decompose_convex (db::polygon_to_simple_polygon (p), db::PO_horizontal, ps); EXPECT_EQ (ps.s, "(0,30000;0,40000;40000,40000;40000,30000)\n" "(30000,10000;30000,30000;40000,30000;40000,10000)\n" "(0,0;0,10000;40000,10000;40000,0)\n" "(0,10000;0,30000;10000,30000;10000,10000)" ); ps.s.clear (); db::decompose_convex (db::simple_polygon_to_polygon (db::polygon_to_simple_polygon (p)), db::PO_horizontal, ps); EXPECT_EQ (ps.s, "(0,10000;0,30000;10000,30000;10000,10000)\n" "(0,30000;0,40000;40000,40000;40000,30000)\n" "(30000,10000;30000,30000;40000,30000;40000,10000)\n" "(0,0;0,10000;40000,10000;40000,0)" ); } // decompose_to_convex TEST(312) { db::Point pattern [] = { db::Point (0, 0), db::Point (0, 40000), db::Point (40000, 40000), db::Point (40000, 0), }; db::Point hole [] = { db::Point (10000, 10000), db::Point (10000, 30000), db::Point (30000, 30000), db::Point (30000, 10000), }; db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); TestPolygonSink ps; db::decompose_convex (p, db::PO_htrapezoids, ps); EXPECT_EQ (ps.s, "(0,0;0,40000;40000,40000;40000,0)"); ps.s.clear (); db::decompose_convex (db::polygon_to_simple_polygon (p), db::PO_htrapezoids, ps); EXPECT_EQ (ps.s, "(0,0;0,40000;40000,40000;40000,0)"); p.insert_hole (&hole[0], &hole[0] + sizeof (hole) / sizeof (hole[0])); ps.s.clear (); db::decompose_convex (p, db::PO_htrapezoids, ps); EXPECT_EQ (ps.s, "(0,10000;0,30000;10000,30000;10000,10000)\n" "(0,30000;0,40000;30000,40000;30000,30000)\n" "(30000,10000;30000,40000;40000,40000;40000,10000)\n" "(0,0;0,10000;40000,10000;40000,0)" ); ps.s.clear (); db::decompose_convex (db::polygon_to_simple_polygon (p), db::PO_htrapezoids, ps); EXPECT_EQ (ps.s, "(0,30000;0,40000;30000,40000;30000,30000)\n" "(30000,10000;30000,40000;40000,40000;40000,10000)\n" "(10000,0;10000,10000;40000,10000;40000,0)\n" "(0,0;0,30000;10000,30000;10000,0)" ); ps.s.clear (); db::decompose_convex (db::simple_polygon_to_polygon (db::polygon_to_simple_polygon (p)), db::PO_htrapezoids, ps); EXPECT_EQ (ps.s, "(0,10000;0,30000;10000,30000;10000,10000)\n" "(0,30000;0,40000;30000,40000;30000,30000)\n" "(30000,10000;30000,40000;40000,40000;40000,10000)\n" "(0,0;0,10000;40000,10000;40000,0)" ); } // decompose_to_convex TEST(313) { db::Point pattern [] = { db::Point (0, 0), db::Point (0, 40000), db::Point (40000, 40000), db::Point (40000, 0), }; db::Point hole [] = { db::Point (10000, 10000), db::Point (10000, 30000), db::Point (30000, 30000), db::Point (30000, 10000), }; db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); TestPolygonSink ps; db::decompose_convex (p, db::PO_vertical, ps); EXPECT_EQ (ps.s, "(0,0;0,40000;40000,40000;40000,0)"); ps.s.clear (); db::decompose_convex (db::polygon_to_simple_polygon (p), db::PO_vertical, ps); EXPECT_EQ (ps.s, "(0,0;0,40000;40000,40000;40000,0)"); p.insert_hole (&hole[0], &hole[0] + sizeof (hole) / sizeof (hole[0])); ps.s.clear (); db::decompose_convex (p, db::PO_vertical, ps); EXPECT_EQ (ps.s, "(10000,0;10000,10000;30000,10000;30000,0)\n" "(0,0;0,40000;10000,40000;10000,0)\n" "(10000,30000;10000,40000;30000,40000;30000,30000)\n" "(30000,0;30000,40000;40000,40000;40000,0)" ); ps.s.clear (); db::decompose_convex (db::polygon_to_simple_polygon (p), db::PO_vertical, ps); EXPECT_EQ (ps.s, "(0,30000;0,40000;30000,40000;30000,30000)\n" "(30000,0;30000,40000;40000,40000;40000,0)\n" "(10000,0;10000,10000;30000,10000;30000,0)\n" "(0,0;0,30000;10000,30000;10000,0)" ); ps.s.clear (); db::decompose_convex (db::simple_polygon_to_polygon (db::polygon_to_simple_polygon (p)), db::PO_vertical, ps); EXPECT_EQ (ps.s, "(10000,0;10000,10000;30000,10000;30000,0)\n" "(0,0;0,40000;10000,40000;10000,0)\n" "(10000,30000;10000,40000;30000,40000;30000,30000)\n" "(30000,0;30000,40000;40000,40000;40000,0)" ); } // decompose_to_convex TEST(314) { db::Point pattern [] = { db::Point (0, 0), db::Point (0, 40000), db::Point (40000, 40000), db::Point (40000, 0), }; db::Point hole [] = { db::Point (10000, 10000), db::Point (10000, 30000), db::Point (30000, 30000), db::Point (30000, 10000), }; db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); TestPolygonSink ps; db::decompose_convex (p, db::PO_vtrapezoids, ps); EXPECT_EQ (ps.s, "(0,0;0,40000;40000,40000;40000,0)"); ps.s.clear (); db::decompose_convex (db::polygon_to_simple_polygon (p), db::PO_vtrapezoids, ps); EXPECT_EQ (ps.s, "(0,0;0,40000;40000,40000;40000,0)"); p.insert_hole (&hole[0], &hole[0] + sizeof (hole) / sizeof (hole[0])); ps.s.clear (); db::decompose_convex (p, db::PO_vtrapezoids, ps); EXPECT_EQ (ps.s, "(10000,0;10000,10000;30000,10000;30000,0)\n" "(0,0;0,30000;10000,30000;10000,0)\n" "(0,30000;0,40000;30000,40000;30000,30000)\n" "(30000,0;30000,40000;40000,40000;40000,0)" ); ps.s.clear (); db::decompose_convex (db::polygon_to_simple_polygon (p), db::PO_vtrapezoids, ps); EXPECT_EQ (ps.s, "(0,30000;0,40000;30000,40000;30000,30000)\n" "(30000,10000;30000,40000;40000,40000;40000,10000)\n" "(10000,0;10000,10000;40000,10000;40000,0)\n" "(0,0;0,30000;10000,30000;10000,0)" ); ps.s.clear (); db::decompose_convex (db::simple_polygon_to_polygon (db::polygon_to_simple_polygon (p)), db::PO_vtrapezoids, ps); EXPECT_EQ (ps.s, "(10000,0;10000,10000;30000,10000;30000,0)\n" "(0,0;0,30000;10000,30000;10000,0)\n" "(0,30000;0,40000;30000,40000;30000,30000)\n" "(30000,0;30000,40000;40000,40000;40000,0)" ); } // decompose_to_trapezoids TEST(320) { db::Point pattern [] = { db::Point (0, 0), db::Point (0, 40000), db::Point (40000, 40000), db::Point (40000, 0), }; db::Point hole [] = { db::Point (10000, 10000), db::Point (10000, 30000), db::Point (30000, 30000), db::Point (30000, 10000), }; db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); TestPolygonSink ps; db::decompose_trapezoids (p, db::TD_simple, ps); EXPECT_EQ (ps.s, "(0,0;0,40000;40000,40000;40000,0)"); ps.s.clear (); db::decompose_trapezoids (db::polygon_to_simple_polygon (p), db::TD_simple, ps); EXPECT_EQ (ps.s, "(0,0;0,40000;40000,40000;40000,0)"); p.insert_hole (&hole[0], &hole[0] + sizeof (hole) / sizeof (hole[0])); ps.s.clear (); db::decompose_trapezoids (p, db::TD_simple, ps); EXPECT_EQ (ps.s, "(0,0;0,10000;40000,10000;40000,0)\n" "(0,10000;0,30000;10000,30000;10000,10000)\n" "(30000,10000;30000,30000;40000,30000;40000,10000)\n" "(0,30000;0,40000;40000,40000;40000,30000)" ); ps.s.clear (); db::decompose_trapezoids (db::polygon_to_simple_polygon (p), db::TD_simple, ps); EXPECT_EQ (ps.s, "(0,0;0,10000;40000,10000;40000,0)\n" "(0,10000;0,30000;10000,30000;10000,10000)\n" "(30000,10000;30000,30000;40000,30000;40000,10000)\n" "(0,30000;0,40000;40000,40000;40000,30000)" ); ps.s.clear (); db::decompose_trapezoids (db::simple_polygon_to_polygon (db::polygon_to_simple_polygon (p)), db::TD_simple, ps); EXPECT_EQ (ps.s, "(0,0;0,10000;40000,10000;40000,0)\n" "(0,10000;0,30000;10000,30000;10000,10000)\n" "(30000,10000;30000,30000;40000,30000;40000,10000)\n" "(0,30000;0,40000;40000,40000;40000,30000)" ); } // decompose_to_trapezoids TEST(321) { db::Point pattern [] = { db::Point (0, 0), db::Point (0, 40000), db::Point (40000, 40000), db::Point (40000, 0), }; db::Point hole [] = { db::Point (10000, 10000), db::Point (10000, 30000), db::Point (30000, 30000), db::Point (30000, 10000), }; db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); TestPolygonSink ps; db::decompose_trapezoids (p, db::TD_htrapezoids, ps); EXPECT_EQ (ps.s, "(0,0;0,40000;40000,40000;40000,0)"); ps.s.clear (); db::decompose_trapezoids (db::polygon_to_simple_polygon (p), db::TD_htrapezoids, ps); EXPECT_EQ (ps.s, "(0,0;0,40000;40000,40000;40000,0)"); p.insert_hole (&hole[0], &hole[0] + sizeof (hole) / sizeof (hole[0])); ps.s.clear (); db::decompose_trapezoids (p, db::TD_htrapezoids, ps); EXPECT_EQ (ps.s, "(0,10000;0,30000;10000,30000;10000,10000)\n" "(0,30000;0,40000;30000,40000;30000,30000)\n" "(30000,10000;30000,40000;40000,40000;40000,10000)\n" "(0,0;0,10000;40000,10000;40000,0)" ); ps.s.clear (); db::decompose_trapezoids (db::polygon_to_simple_polygon (p), db::TD_htrapezoids, ps); EXPECT_EQ (ps.s, "(0,30000;0,40000;30000,40000;30000,30000)\n" "(30000,10000;30000,40000;40000,40000;40000,10000)\n" "(10000,0;10000,10000;40000,10000;40000,0)\n" "(0,0;0,30000;10000,30000;10000,0)" ); ps.s.clear (); db::decompose_trapezoids (db::simple_polygon_to_polygon (db::polygon_to_simple_polygon (p)), db::TD_htrapezoids, ps); EXPECT_EQ (ps.s, "(0,10000;0,30000;10000,30000;10000,10000)\n" "(0,30000;0,40000;30000,40000;30000,30000)\n" "(30000,10000;30000,40000;40000,40000;40000,10000)\n" "(0,0;0,10000;40000,10000;40000,0)" ); } // decompose_to_trapezoids TEST(322) { db::Point pattern [] = { db::Point (0, 0), db::Point (0, 40000), db::Point (40000, 40000), db::Point (40000, 0), }; db::Point hole [] = { db::Point (10000, 10000), db::Point (10000, 30000), db::Point (30000, 30000), db::Point (30000, 10000), }; db::Polygon p; p.assign_hull (&pattern[0], &pattern[0] + sizeof (pattern) / sizeof (pattern[0])); TestPolygonSink ps; db::decompose_trapezoids (p, db::TD_vtrapezoids, ps); EXPECT_EQ (ps.s, "(0,0;0,40000;40000,40000;40000,0)"); ps.s.clear (); db::decompose_trapezoids (db::polygon_to_simple_polygon (p), db::TD_vtrapezoids, ps); EXPECT_EQ (ps.s, "(0,0;0,40000;40000,40000;40000,0)"); p.insert_hole (&hole[0], &hole[0] + sizeof (hole) / sizeof (hole[0])); ps.s.clear (); db::decompose_trapezoids (p, db::TD_vtrapezoids, ps); EXPECT_EQ (ps.s, "(10000,0;10000,10000;30000,10000;30000,0)\n" "(0,0;0,30000;10000,30000;10000,0)\n" "(0,30000;0,40000;30000,40000;30000,30000)\n" "(30000,0;30000,40000;40000,40000;40000,0)" ); ps.s.clear (); db::decompose_trapezoids (db::polygon_to_simple_polygon (p), db::TD_vtrapezoids, ps); EXPECT_EQ (ps.s, "(0,30000;0,40000;30000,40000;30000,30000)\n" "(30000,10000;30000,40000;40000,40000;40000,10000)\n" "(10000,0;10000,10000;40000,10000;40000,0)\n" "(0,0;0,30000;10000,30000;10000,0)" ); ps.s.clear (); db::decompose_trapezoids (db::simple_polygon_to_polygon (db::polygon_to_simple_polygon (p)), db::TD_vtrapezoids, ps); EXPECT_EQ (ps.s, "(10000,0;10000,10000;30000,10000;30000,0)\n" "(0,0;0,30000;10000,30000;10000,0)\n" "(0,30000;0,40000;30000,40000;30000,30000)\n" "(30000,0;30000,40000;40000,40000;40000,0)" ); } // cut self-overlapping polygon TEST(400) { std::vector c; c.push_back (db::Point (0, 0)); c.push_back (db::Point (0, 100)); c.push_back (db::Point (1000, 100)); c.push_back (db::Point (1000, 1000)); c.push_back (db::Point (0, 1000)); c.push_back (db::Point (0, 900)); c.push_back (db::Point (900, 900)); c.push_back (db::Point (900, 0)); { db::Polygon in; in.assign_hull (c.begin (), c.end ()); std::vector right_of; db::cut_polygon (in, db::Edge (db::Point (500, 0), db::Point (500, 1)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (2)); EXPECT_EQ (right_of[0].to_string (), "(500,0;500,100;900,100;900,0)"); EXPECT_EQ (right_of[1].to_string (), "(900,100;900,900;500,900;500,1000;1000,1000;1000,100)"); right_of.clear (); db::cut_polygon (in, db::Edge (db::Point (500, 1), db::Point (500, 0)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (2)); EXPECT_EQ (right_of[0].to_string (), "(0,0;0,100;500,100;500,0)"); EXPECT_EQ (right_of[1].to_string (), "(0,900;0,1000;500,1000;500,900)"); } { db::SimplePolygon in; in.assign_hull (c.begin (), c.end ()); std::vector right_of; db::cut_polygon (in, db::Edge (db::Point (500, 0), db::Point (500, 1)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (2)); EXPECT_EQ (right_of[0].to_string (), "(500,0;500,100;900,100;900,0)"); EXPECT_EQ (right_of[1].to_string (), "(900,100;900,900;500,900;500,1000;1000,1000;1000,100)"); right_of.clear (); db::cut_polygon (in, db::Edge (db::Point (500, 1), db::Point (500, 0)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (2)); EXPECT_EQ (right_of[0].to_string (), "(0,0;0,100;500,100;500,0)"); EXPECT_EQ (right_of[1].to_string (), "(0,900;0,1000;500,1000;500,900)"); } } // cut self-overlapping polygon (with double types) TEST(401) { std::vector c; c.push_back (db::DPoint (0, 0)); c.push_back (db::DPoint (0, 100)); c.push_back (db::DPoint (1000, 100)); c.push_back (db::DPoint (1000, 1000)); c.push_back (db::DPoint (0, 1000)); c.push_back (db::DPoint (0, 900)); c.push_back (db::DPoint (900, 900)); c.push_back (db::DPoint (900, 0)); { db::DPolygon in; in.assign_hull (c.begin (), c.end ()); std::vector right_of; db::cut_polygon (in, db::DEdge (db::DPoint (500, 0), db::DPoint (500, 1)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (2)); EXPECT_EQ (right_of[0].to_string (), "(500,0;500,100;900,100;900,0)"); EXPECT_EQ (right_of[1].to_string (), "(900,100;900,900;500,900;500,1000;1000,1000;1000,100)"); right_of.clear (); db::cut_polygon (in, db::DEdge (db::DPoint (500, 1), db::DPoint (500, 0)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (2)); EXPECT_EQ (right_of[0].to_string (), "(0,0;0,100;500,100;500,0)"); EXPECT_EQ (right_of[1].to_string (), "(0,900;0,1000;500,1000;500,900)"); } { db::DSimplePolygon in; in.assign_hull (c.begin (), c.end ()); std::vector right_of; db::cut_polygon (in, db::DEdge (db::DPoint (500, 0), db::DPoint (500, 1)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (2)); EXPECT_EQ (right_of[0].to_string (), "(500,0;500,100;900,100;900,0)"); EXPECT_EQ (right_of[1].to_string (), "(900,100;900,900;500,900;500,1000;1000,1000;1000,100)"); right_of.clear (); db::cut_polygon (in, db::DEdge (db::DPoint (500, 1), db::DPoint (500, 0)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (2)); EXPECT_EQ (right_of[0].to_string (), "(0,0;0,100;500,100;500,0)"); EXPECT_EQ (right_of[1].to_string (), "(0,900;0,1000;500,1000;500,900)"); } } // cut empty polygons TEST(402) { { db::Polygon in; std::vector right_of; db::cut_polygon (in, db::Edge (db::Point (500, 0), db::Point (500, 1)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (0)); } { db::SimplePolygon in; std::vector right_of; db::cut_polygon (in, db::Edge (db::Point (500, 0), db::Point (500, 1)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (0)); } { db::DPolygon in; std::vector right_of; db::cut_polygon (in, db::DEdge (db::DPoint (500, 0), db::DPoint (500, 1)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (0)); } { db::DSimplePolygon in; std::vector right_of; db::cut_polygon (in, db::DEdge (db::DPoint (500, 0), db::DPoint (500, 1)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (0)); } } // cut point-like polygons TEST(403) { { db::Polygon in (db::Box (1000, 0, 1000, 0)); std::vector right_of; db::cut_polygon (in, db::Edge (db::Point (500, 0), db::Point (500, 1)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (1)); EXPECT_EQ (right_of[0].to_string (), "()"); // bad, but no contour available :-( right_of.clear (); db::cut_polygon (in, db::Edge (db::Point (500, 1), db::Point (500, 0)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (0)); } { db::SimplePolygon in (db::Box (1000, 0, 1000, 0)); std::vector right_of; db::cut_polygon (in, db::Edge (db::Point (500, 0), db::Point (500, 1)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (1)); EXPECT_EQ (right_of[0].to_string (), "()"); // bad, but no contour available :-( right_of.clear (); db::cut_polygon (in, db::Edge (db::Point (500, 1), db::Point (500, 0)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (0)); } { db::DPolygon in (db::DBox (1000, 0, 1000, 0)); std::vector right_of; db::cut_polygon (in, db::DEdge (db::DPoint (500, 0), db::DPoint (500, 1)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (1)); EXPECT_EQ (right_of[0].to_string (), "()"); // bad, but no contour available :-( right_of.clear (); db::cut_polygon (in, db::DEdge (db::DPoint (500, 1), db::DPoint (500, 0)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (0)); } { db::DSimplePolygon in (db::DBox (1000, 0, 1000, 0)); std::vector right_of; db::cut_polygon (in, db::DEdge (db::DPoint (500, 0), db::DPoint (500, 1)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (1)); EXPECT_EQ (right_of[0].to_string (), "()"); // bad, but no contour available :-( right_of.clear (); db::cut_polygon (in, db::DEdge (db::DPoint (500, 1), db::DPoint (500, 0)), std::back_inserter (right_of)); EXPECT_EQ (right_of.size (), size_t (0)); } } // issue 166 TEST(404) { db::Polygon poly; std::string s ("(390,0;438,936;176,874;0,832;438,937;541,961;821,102)"); tl::Extractor ex (s.c_str ()); ex.read (poly); std::vector sp; db::split_polygon (poly, sp); EXPECT_EQ (sp.size (), size_t (2)); if (sp.size () >= 2) { EXPECT_EQ (sp[0].to_string (), "(390,0;438,936;390,925;438,937;541,961;821,102)"); EXPECT_EQ (sp[1].to_string (), "(0,832;176,874;390,925)"); } } TEST(405) { db::Polygon poly; std::string s ("(0,0;0,1126;30,1126;30,30;3044,30;3044,1126;5782,1126;5782,30;8796,30;8796,1126;0,1126;0,1141;3009,1141;3009,1156;3194,1156;3194,1141;8826,1141;8826,0;5742,0;5742,1126;3084,1126;3084,0)"); tl::Extractor ex (s.c_str ()); ex.read (poly); std::vector sp; db::split_polygon (poly, sp); EXPECT_EQ (sp.size (), size_t (2)); if (sp.size () >= 2) { EXPECT_EQ (sp[0].to_string (), "(5742,0;5742,1126;5782,1126;5782,30;8796,30;8796,1126;3194,1126;3194,1141;8826,1141;8826,0)"); EXPECT_EQ (sp[1].to_string (), "(0,0;0,1126;30,1126;30,30;3044,30;3044,1126;0,1126;0,1141;3009,1141;3009,1156;3194,1156;3194,1126;3084,1126;3084,0)"); } } static db::Polygon str2poly (const std::string &s) { db::Polygon poly; tl::Extractor ex (s.c_str ()); ex.read (poly); return poly; } // self-overlapping, non-orientable check TEST(500) { std::string ps; std::vector parts; // null polygon ps = "()"; EXPECT_EQ (db::is_strange_polygon (str2poly (ps)), false); EXPECT_EQ (db::is_non_orientable_polygon (str2poly (ps)), false); // triangle ps = "(0,0;1000,0;1000,1000)"; EXPECT_EQ (db::is_strange_polygon (str2poly (ps)), false); EXPECT_EQ (db::is_non_orientable_polygon (str2poly (ps)), false); // rectangle counter-clockwise ps = "(0,0;1000,0;1000,1000;0,1000)"; EXPECT_EQ (db::is_strange_polygon (str2poly (ps)), false); EXPECT_EQ (db::is_non_orientable_polygon (str2poly (ps)), false); // rectangle clockwise ps = "(0,0;0,1000;1000,1000;1000,0)"; EXPECT_EQ (db::is_strange_polygon (str2poly (ps)), false); EXPECT_EQ (db::is_non_orientable_polygon (str2poly (ps)), false); // "8" shape ps = "(0,0;1000,1000;0,1000;1000,0)"; EXPECT_EQ (db::is_strange_polygon (str2poly (ps)), true); EXPECT_EQ (db::is_non_orientable_polygon (str2poly (ps)), true); parts.clear (); EXPECT_EQ (db::is_strange_polygon (str2poly (ps), &parts), true); EXPECT_EQ (parts.size (), size_t (1)); if (! parts.empty ()) { EXPECT_EQ (parts[0].to_string (), "(0,0;500,500;1000,0)"); } parts.clear (); EXPECT_EQ (db::is_non_orientable_polygon (str2poly (ps), &parts), true); EXPECT_EQ (parts.size (), size_t (1)); if (! parts.empty ()) { EXPECT_EQ (parts[0].to_string (), "(0,0;500,500;1000,0)"); } // self-touching ps = "(0,0;0,2000;1000,2000;1000,1000;3000,1000;3000,3000;1000,3000;1000,2000;0,2000;0,4000;4000,4000;4000,0)"; EXPECT_EQ (db::is_strange_polygon (str2poly (ps)), false); EXPECT_EQ (db::is_non_orientable_polygon (str2poly (ps)), false); // self-overlap ps = "(0,0;0,2500;1000,2500;1000,1000;3000,1000;3000,3000;1000,3000;1000,2000;0,2000;0,4000;4000,4000;4000,0)"; EXPECT_EQ (db::is_strange_polygon (str2poly (ps)), true); EXPECT_EQ (db::is_non_orientable_polygon (str2poly (ps)), false); parts.clear (); EXPECT_EQ (db::is_strange_polygon (str2poly (ps), &parts), true); EXPECT_EQ (parts.size (), size_t (1)); if (! parts.empty ()) { EXPECT_EQ (parts[0].to_string (), "(0,2000;0,2500;1000,2500;1000,2000)"); } // inner loop twisted ps = "(0,0;0,2000;1000,2000;1000,3000;3000,3000;3000,1000;1000,1000;1000,2000;0,2000;0,4000;4000,4000;4000,0)"; EXPECT_EQ (db::is_strange_polygon (str2poly (ps)), true); // This is a double loop, so it's orientable EXPECT_EQ (db::is_non_orientable_polygon (str2poly (ps)), false); // non-orientable hole ps = "(0,0;0,4000;4000,4000;4000,0/1000,1000;3000,3000;1000,3000;3000,1000)"; EXPECT_EQ (db::is_strange_polygon (str2poly (ps)), true); // NOTE: a non-orientable holes does not generate -1 wrapcount, but just 0. So the polygon is "orientable" // as a whole. Which isn't good for detecting invalid input polygons, but as those are hull-only for GDS and // OASIS and most other formats (except DXF), we don't care too much here: EXPECT_EQ (db::is_non_orientable_polygon (str2poly (ps)), false); // hole outside hull ps = "(0,0;0,4000;4000,4000;4000,0/1000,1000;5000,1000;5000,3000;1000,3000)"; EXPECT_EQ (db::is_strange_polygon (str2poly (ps)), true); EXPECT_EQ (db::is_non_orientable_polygon (str2poly (ps)), true); }