diff --git a/src/db/db/dbPLCConvexDecomposition.cc b/src/db/db/dbPLCConvexDecomposition.cc index 45eda37ed..a6dcff7c4 100644 --- a/src/db/db/dbPLCConvexDecomposition.cc +++ b/src/db/db/dbPLCConvexDecomposition.cc @@ -433,13 +433,8 @@ ConvexDecomposition::decompose (const db::Polygon &poly, const std::vector &vertexes, const ConvexDecompositionParameters ¶meters, const db::CplxTrans &trans) { - // start with a triangulation - TriangulationParameters param; - param.max_area = 0.0; - param.min_b = 0.0; - Triangulation tri (mp_graph); - tri.triangulate (poly, vertexes, param, trans); + tri.triangulate (poly, vertexes, parameters.tri_param, trans); hertel_mehlhorn_decomposition (tri, parameters); } @@ -461,13 +451,8 @@ ConvexDecomposition::decompose (const db::Polygon &poly, const std::vector &vertexes, const ConvexDecompositionParameters ¶meters, const db::DCplxTrans &trans) { - // start with a triangulation - TriangulationParameters param; - param.max_area = 0.0; - param.min_b = 0.0; - Triangulation tri (mp_graph); - tri.triangulate (poly, vertexes, param, trans); + tri.triangulate (poly, vertexes, parameters.tri_param, trans); hertel_mehlhorn_decomposition (tri, parameters); } @@ -495,13 +475,8 @@ ConvexDecomposition::decompose (const db::Region ®ion, const ConvexDecomposit void ConvexDecomposition::decompose (const db::Region ®ion, const ConvexDecompositionParameters ¶meters, const db::CplxTrans &trans) { - // start with a triangulation - TriangulationParameters param; - param.max_area = 0.0; - param.min_b = 0.0; - Triangulation tri (mp_graph); - tri.triangulate (region, param, trans); + tri.triangulate (region, parameters.tri_param, trans); hertel_mehlhorn_decomposition (tri, parameters); } diff --git a/src/db/db/dbPLCConvexDecomposition.h b/src/db/db/dbPLCConvexDecomposition.h index 03a6949bb..1fa9ce805 100644 --- a/src/db/db/dbPLCConvexDecomposition.h +++ b/src/db/db/dbPLCConvexDecomposition.h @@ -25,6 +25,7 @@ #include "dbCommon.h" #include "dbPLC.h" +#include "dbPLCTriangulation.h" #include #include @@ -37,15 +38,21 @@ namespace db namespace plc { -class Triangulation; - struct DB_PUBLIC ConvexDecompositionParameters { ConvexDecompositionParameters () : with_segments (false), split_edges (false), base_verbosity (30) - { } + { + tri_param.max_area = 0.0; + tri_param.min_b = 0.0; + } + + /** + * @brief The parameters used for the triangulation + */ + TriangulationParameters tri_param; /** * @brief Introduce new segments diff --git a/src/db/db/gsiDeclDbPolygon.cc b/src/db/db/gsiDeclDbPolygon.cc index 1a4fa5335..a5cb6f994 100644 --- a/src/db/db/gsiDeclDbPolygon.cc +++ b/src/db/db/gsiDeclDbPolygon.cc @@ -29,44 +29,76 @@ #include "dbPolygonGenerators.h" #include "dbHash.h" #include "dbPLCTriangulation.h" +#include "dbPLCConvexDecomposition.h" namespace gsi { +const std::string hm_docstring = + "The Hertel-Mehlhorn decomposition starts with a Delaunay triangulation of the polygons and recombines the " + "triangles into convex polygons.\n" + "\n" + "The decomposition is controlled by two parameters: 'with_segments' and 'split_edges'.\n" + "\n" + "If 'with_segments' is true (the default), new segments are introduced perpendicular to the edges forming " + "a concave corner. If false, only diagonals (edges connecting original vertexes) are used.\n" + "\n" + "If 'split_edges' is true, the algorithm is allowed to create collinear edges in the output. In this case, " + "the resulting polygons may contain edges that are split into collinear partial edges. Such edges usually recombine " + "into longer edges when processing the polygon further. When such a recombination happens, the edges no " + "longer correspond to original edges or diagonals. When 'split_edges' is false (the default), the resulting " + "polygons will not contain collinear edges, but the decomposition will be constrained to fewer cut lines." + "\n" + "'max_area' and 'min_b' are the corresponding parameters used for the triangulation (see \\delaunay).\n" +; + +const std::string delaunay_docstring = + "Refinement is implemented by Chew's second algorithm. A maximum area can be given. Triangles " + "larger than this area will be split. In addition 'skinny' triangles will be resolved where " + "possible. 'skinny' is defined in terms of shortest edge to circumcircle radius ratio (b). " + "A minimum number for b can be given. A value of 1.0 corresponds to a minimum angle of 30 degree " + "and is usually a good choice. The algorithm is stable up to roughly 1.2 which corresponds to " + "a minimum angle of abouth 37 degree.\n" + "\n" + "The minimum angle of the resulting triangles relates to the 'b' parameter as: @t min_angle = arcsin(B/2) @/t.\n" + "\n" + "Picking a value of 0.0 for max_area and min_b will " + "make the implementation skip the refinement step. In that case, the results are identical to " + "the standard constrained Delaunay triangulation.\n" +; + +const std::string dbu_docstring = + "The 'dbu' parameter a numerical scaling parameter. It should be choosen in a way that the polygon dimensions " + "are \"in the order of 1\" (very roughly) after multiplication with the dbu parameter. A value of 0.001 is suitable " + "for polygons with typical dimensions in the order to 1000 DBU. Usually the default value is good enough.\n" +; + template -static db::Region region_from_triangles (const db::plc::Graph &tri, const T &trans) +static db::Region region_from_graph (const db::plc::Graph &plc, const T &trans) { db::Region result; + result.set_merged_semantics (false); - db::Point pts [3]; - - for (auto t = tri.begin (); t != tri.end (); ++t) { - for (int i = 0; i < 3; ++i) { - pts [i] = trans * *t->vertex (i); - } - db::SimplePolygon poly; - poly.assign_hull (pts + 0, pts + 3); - result.insert (poly); + for (auto t = plc.begin (); t != plc.end (); ++t) { + db::DPolygon dp = t->polygon (); + db::SimplePolygon sp; + sp.assign_hull (dp.hull ().begin (), dp.hull ().end (), trans, false); + result.insert (sp); } return result; } template -static std::vector

polygons_from_triangles (const db::plc::Graph &tri, const T &trans) +static std::vector

polygons_from_graph (const db::plc::Graph &plc, const T &trans) { std::vector

result; - result.reserve (tri.num_polygons ()); + result.reserve (plc.num_polygons ()); - typename P::point_type pts [3]; - - for (auto t = tri.begin (); t != tri.end (); ++t) { - for (int i = 0; i < 3; ++i) { - pts [i] = trans * *t->vertex (i); - } - P poly; - poly.assign_hull (pts + 0, pts + 3); - result.push_back (poly); + for (auto t = plc.begin (); t != plc.end (); ++t) { + db::DPolygon dp = t->polygon (); + result.push_back (P ()); + result.back ().assign_hull (dp.hull ().begin (), dp.hull ().end (), trans, false); } return result; @@ -87,7 +119,43 @@ static db::polygon to_polygon (const db::polygon &p) } template -static db::Region triangulate_ipolygon (const P *p, double max_area = 0.0, double min_b = 0.0, double dbu = 0.001) +static db::Region hm_decompose_ipolygon (const P *p, bool with_segments, bool split_edges, double max_area, double min_b, double dbu) +{ + db::plc::Graph plc; + db::plc::ConvexDecomposition decomp (&plc); + db::plc::ConvexDecompositionParameters param; + param.with_segments = with_segments; + param.split_edges = split_edges; + param.tri_param.max_area = max_area; + param.tri_param.min_b = min_b; + + db::CplxTrans trans = db::CplxTrans (dbu) * db::ICplxTrans (db::Trans (db::Point () - p->box ().center ())); + + decomp.decompose (to_polygon (*p), param, trans); + + return region_from_graph (plc, trans.inverted ()); +} + +template +static std::vector

hm_decompose_dpolygon (const P *p, bool with_segments, bool split_edges, double max_area, double min_b) +{ + db::plc::Graph plc; + db::plc::ConvexDecomposition decomp (&plc); + db::plc::ConvexDecompositionParameters param; + param.with_segments = with_segments; + param.split_edges = split_edges; + param.tri_param.max_area = max_area; + param.tri_param.min_b = min_b; + + db::DCplxTrans trans = db::DCplxTrans (db::DTrans (db::DPoint () - p->box ().center ())); + + decomp.decompose (to_polygon (*p), param, trans); + + return polygons_from_graph (plc, trans.inverted ()); +} + +template +static db::Region triangulate_ipolygon (const P *p, double max_area, double min_b, double dbu) { db::plc::Graph tris; db::plc::Triangulation triangulation (&tris); @@ -99,11 +167,11 @@ static db::Region triangulate_ipolygon (const P *p, double max_area = 0.0, doubl triangulation.triangulate (to_polygon (*p), param, trans); - return region_from_triangles (tris, trans.inverted ()); + return region_from_graph (tris, trans.inverted ()); } template -static db::Region triangulate_ipolygon_v (const P *p, const std::vector &vertexes, double max_area = 0.0, double min_b = 0.0, double dbu = 0.001) +static db::Region triangulate_ipolygon_v (const P *p, const std::vector &vertexes, double max_area, double min_b, double dbu) { db::plc::Graph tris; db::plc::Triangulation triangulation (&tris); @@ -115,7 +183,7 @@ static db::Region triangulate_ipolygon_v (const P *p, const std::vector @@ -131,7 +199,7 @@ static std::vector

triangulate_dpolygon (const P *p, double max_area = 0.0, d triangulation.triangulate (to_polygon (*p), param, trans); - return polygons_from_triangles (tris, trans.inverted ()); + return polygons_from_graph (tris, trans.inverted ()); } template @@ -147,7 +215,7 @@ static std::vector

triangulate_dpolygon_v (const P *p, const std::vector (tris, trans.inverted ()); + return polygons_from_graph (tris, trans.inverted ()); } template @@ -884,36 +952,35 @@ Class decl_SimplePolygon ("db", "SimplePolygon", "\n" "This method has been introduced in version 0.18.\n" ) + + method_ext ("hm_decomposition", &hm_decompose_ipolygon, + gsi::arg ("with_segments", true), gsi::arg ("split_edges", false), + gsi::arg ("max_area", 0.0), gsi::arg ("min_b", 0.0), + gsi::arg ("dbu", 0.001), + "@brief Performs a Hertel-Mehlhorn convex decomposition.\n" + "\n" + "@return A \\Region holding the polygons of the decomposition.\n" + "The resulting region is in 'no merged semantics' mode, " + "to avoid re-merging of the polygons during following operations.\n" + "\n" + hm_docstring + "\n" + dbu_docstring + "\n" + "This method has been introduced in version 0.30.1." + ) + method_ext ("delaunay", &triangulate_ipolygon, gsi::arg ("max_area", 0.0), gsi::arg ("min_b", 0.0), gsi::arg ("dbu", 0.001), "@brief Performs a Delaunay triangulation of the polygon.\n" "\n" "@return A \\Region holding the triangles of the refined, constrained Delaunay triangulation.\n" - "\n" - "Refinement is implemented by Chew's second algorithm. A maximum area can be given. Triangles " - "larger than this area will be split. In addition 'skinny' triangles will be resolved where " - "possible. 'skinny' is defined in terms of shortest edge to circumcircle radius ratio (b). " - "A minimum number for b can be given. A value of 1.0 corresponds to a minimum angle of 30 degree " - "and is usually a good choice. The algorithm is stable up to roughly 1.2 which corresponds to " - "a minimum angle of abouth 37 degree.\n" - "\n" - "The minimum angle of the resulting triangles relates to the 'b' parameter as: @t min_angle = arcsin(B/2) @/t.\n" - "\n" - "The area value is given in terms of DBU units. Picking a value of 0.0 for area and min b will " - "make the implementation skip the refinement step. In that case, the results are identical to " - "the standard constrained Delaunay triangulation.\n" - "\n" - "The 'dbu' parameter a numerical scaling parameter. It should be choosen in a way that the polygon dimensions " - "are \"in the order of 1\" (very roughly) after multiplication with the dbu parameter. A value of 0.001 is suitable " - "for polygons with typical dimensions in the order to 1000 DBU. Usually the default value is good enough.\n" - "\n" - "This method has been introduced in version 0.30." + "\n" + delaunay_docstring + "\n" + "The area value is given in terms of DBU units.\n" + "\n" + dbu_docstring + "\n" + "This method has been introduced in version 0.30. Since version 0.30.1, the resulting region is in 'no merged semantics' mode, " + "to avoid re-merging of the triangles during following operations." ) + method_ext ("delaunay", &triangulate_ipolygon_v, gsi::arg ("vertexes"), gsi::arg ("max_area", 0.0), gsi::arg ("min_b", 0.0), gsi::arg ("dbu", 0.001), "@brief Performs a Delaunay triangulation of the polygon.\n" "\n" "This variant of the triangulation function accepts an array of additional vertexes for the triangulation.\n" "\n" - "This method has been introduced in version 0.30." + "This method has been introduced in version 0.30. Since version 0.30.1, the resulting region is in 'no merged semantics' mode, " + "to avoid re-merging of the triangles during following operations." ) + simple_polygon_defs::methods (), "@brief A simple polygon class\n" @@ -1010,24 +1077,20 @@ Class decl_DSimplePolygon ("db", "DSimplePolygon", "\n" "This method has been introduced in version 0.25.\n" ) + + method_ext ("hm_decomposition", &hm_decompose_dpolygon, + gsi::arg ("with_segments", true), gsi::arg ("split_edges", false), + gsi::arg ("max_area", 0.0), gsi::arg ("min_b", 0.0), + "@brief Performs a Hertel-Mehlhorn convex decomposition.\n" + "\n" + "@return An array holding the polygons of the decomposition.\n" + "\n" + hm_docstring + "\n" + "This method has been introduced in version 0.30.1." + ) + method_ext ("delaunay", &triangulate_dpolygon, gsi::arg ("max_area", 0.0), gsi::arg ("min_b", 0.0), "@brief Performs a Delaunay triangulation of the polygon.\n" "\n" "@return An array of triangular polygons of the refined, constrained Delaunay triangulation.\n" - "\n" - "Refinement is implemented by Chew's second algorithm. A maximum area can be given. Triangles " - "larger than this area will be split. In addition 'skinny' triangles will be resolved where " - "possible. 'skinny' is defined in terms of shortest edge to circumcircle radius ratio (b). " - "A minimum number for b can be given. A value of 1.0 corresponds to a minimum angle of 30 degree " - "and is usually a good choice. The algorithm is stable up to roughly 1.2 which corresponds to " - "a minimum angle of abouth 37 degree.\n" - "\n" - "The minimum angle of the resulting triangles relates to the 'b' parameter as: @t min_angle = arcsin(B/2) @/t.\n" - "\n" - "Picking a value of 0.0 for max area and min b will " - "make the implementation skip the refinement step. In that case, the results are identical to " - "the standard constrained Delaunay triangulation.\n" - "\n" + "\n" + delaunay_docstring + "\n" "This method has been introduced in version 0.30." ) + method_ext ("delaunay", &triangulate_dpolygon_v, gsi::arg ("vertexes"), gsi::arg ("max_area", 0.0), gsi::arg ("min_b", 0.0), @@ -2211,36 +2274,36 @@ Class decl_Polygon ("db", "Polygon", "\n" "This method was introduced in version 0.18.\n" ) + + method_ext ("hm_decomposition", &hm_decompose_ipolygon, + gsi::arg ("with_segments", true), gsi::arg ("split_edges", false), + gsi::arg ("max_area", 0.0), gsi::arg ("min_b", 0.0), + gsi::arg ("dbu", 0.001), + "@brief Performs a Hertel-Mehlhorn convex decomposition.\n" + "\n" + "@return A \\Region holding the polygons of the decomposition.\n" + "\n" + "The resulting region is in 'no merged semantics' mode, " + "to avoid re-merging of the polygons during following operations.\n" + "\n" + hm_docstring + "\n" + dbu_docstring + "\n" + "This method has been introduced in version 0.30.1." + ) + method_ext ("delaunay", &triangulate_ipolygon, gsi::arg ("max_area", 0.0), gsi::arg ("min_b", 0.0), gsi::arg ("dbu", 0.001), "@brief Performs a Delaunay triangulation of the polygon.\n" "\n" "@return A \\Region holding the triangles of the refined, constrained Delaunay triangulation.\n" - "\n" - "Refinement is implemented by Chew's second algorithm. A maximum area can be given. Triangles " - "larger than this area will be split. In addition 'skinny' triangles will be resolved where " - "possible. 'skinny' is defined in terms of shortest edge to circumcircle radius ratio (b). " - "A minimum number for b can be given. A value of 1.0 corresponds to a minimum angle of 30 degree " - "and is usually a good choice. The algorithm is stable up to roughly 1.2 which corresponds to " - "a minimum angle of abouth 37 degree.\n" - "\n" - "The minimum angle of the resulting triangles relates to the 'b' parameter as: @t min_angle = arcsin(B/2) @/t.\n" - "\n" - "The area value is given in terms of DBU units. Picking a value of 0.0 for area and min b will " - "make the implementation skip the refinement step. In that case, the results are identical to " - "the standard constrained Delaunay triangulation.\n" - "\n" - "The 'dbu' parameter a numerical scaling parameter. It should be choosen in a way that the polygon dimensions " - "are \"in the order of 1\" (very roughly) after multiplication with the dbu parameter. A value of 0.001 is suitable " - "for polygons with typical dimensions in the order to 1000 DBU. Usually the default value is good enough.\n" - "\n" - "This method has been introduced in version 0.30." + "\n" + delaunay_docstring + "\n" + "The area value is given in terms of DBU units.\n" + "\n" + dbu_docstring + "\n" + "This method has been introduced in version 0.30. Since version 0.30.1, the resulting region is in 'no merged semantics' mode, " + "to avoid re-merging of the triangles during following operations." ) + method_ext ("delaunay", &triangulate_ipolygon_v, gsi::arg ("vertexes"), gsi::arg ("max_area", 0.0), gsi::arg ("min_b", 0.0), gsi::arg ("dbu", 0.001), "@brief Performs a Delaunay triangulation of the polygon.\n" "\n" "This variant of the triangulation function accepts an array of additional vertexes for the triangulation.\n" "\n" - "This method has been introduced in version 0.30." + "This method has been introduced in version 0.30. Since version 0.30.1, the resulting region is in 'no merged semantics' mode, " + "to avoid re-merging of the triangles during following operations." ) + polygon_defs::methods (), "@brief A polygon class\n" @@ -2364,24 +2427,20 @@ Class decl_DPolygon ("db", "DPolygon", "\n" "This method has been introduced in version 0.25.\n" ) + + method_ext ("hm_decomposition", &hm_decompose_dpolygon, + gsi::arg ("with_segments", true), gsi::arg ("split_edges", false), + gsi::arg ("max_area", 0.0), gsi::arg ("min_b", 0.0), + "@brief Performs a Hertel-Mehlhorn convex decomposition.\n" + "\n" + "@return An array holding the polygons of the decomposition.\n" + "\n" + hm_docstring + "\n" + "This method has been introduced in version 0.30.1." + ) + method_ext ("delaunay", &triangulate_dpolygon, gsi::arg ("max_area", 0.0), gsi::arg ("min_b", 0.0), "@brief Performs a Delaunay triangulation of the polygon.\n" "\n" "@return An array of triangular polygons of the refined, constrained Delaunay triangulation.\n" - "\n" - "Refinement is implemented by Chew's second algorithm. A maximum area can be given. Triangles " - "larger than this area will be split. In addition 'skinny' triangles will be resolved where " - "possible. 'skinny' is defined in terms of shortest edge to circumcircle radius ratio (b). " - "A minimum number for b can be given. A value of 1.0 corresponds to a minimum angle of 30 degree " - "and is usually a good choice. The algorithm is stable up to roughly 1.2 which corresponds to " - "a minimum angle of abouth 37 degree.\n" - "\n" - "The minimum angle of the resulting triangles relates to the 'b' parameter as: @t min_angle = arcsin(B/2) @/t.\n" - "\n" - "Picking a value of 0.0 for max area and min b will " - "make the implementation skip the refinement step. In that case, the results are identical to " - "the standard constrained Delaunay triangulation.\n" - "\n" + "\n" + delaunay_docstring + "\n" "This method has been introduced in version 0.30." ) + method_ext ("delaunay", &triangulate_dpolygon_v, gsi::arg ("vertexes"), gsi::arg ("max_area", 0.0), gsi::arg ("min_b", 0.0), diff --git a/testdata/ruby/dbPolygonTest.rb b/testdata/ruby/dbPolygonTest.rb index 3ac9c74e4..c9de10f8e 100644 --- a/testdata/ruby/dbPolygonTest.rb +++ b/testdata/ruby/dbPolygonTest.rb @@ -1006,6 +1006,32 @@ class DBPolygon_TestClass < TestBase end + def sorted_polygons(arr) + arr.each.collect { |p| p.downcast.to_s }.sort.join(";") + end + + def sorted_dpolygons(arr) + arr.each.collect { |p| p.to_s }.sort.join(";") + end + + def test_hm_decomposition + + p = RBA::Polygon::new([ [0, 0], [0, 100], [1000, 100], [1000, 1000], [1100, 1000], [1100, 100], [2200, 100], [2200, 0] ]) + assert_equal(sorted_polygons(p.hm_decomposition(false, false)), "(0,0;0,100;1000,100);(0,0;1000,100;1100,100);(0,0;1100,100;2200,100;2200,0);(1000,100;1000,1000;1100,1000;1100,100)") + assert_equal(sorted_polygons(p.hm_decomposition(true, false)), "(0,0;0,100;1000,100;1000,0);(1000,0;1000,100;1100,100;1100,0);(1000,100;1000,1000;1100,1000;1100,100);(1100,0;1100,100;2200,100;2200,0)") + assert_equal(sorted_polygons(p.hm_decomposition(false, true)), "(0,0;0,100;1000,100;1100,100;2200,100;2200,0);(1000,100;1000,1000;1100,1000;1100,100)") + assert_equal(sorted_polygons(p.hm_decomposition(true, true)), "(0,0;0,100;1000,100;1000,0);(1000,0;1000,100;1000,1000;1100,1000;1100,100;1100,0);(1100,0;1100,100;2200,100;2200,0)") + assert_equal(sorted_polygons(p.hm_decomposition(false, false, 0.0, 0.5)), "(0,0;0,100;500,100;1000,100;1100,0;825,0;550,0;275,0);(1000,100;1000,550;1000,775;1000,1000;1100,1000;1100,550;1100,325;1100,100);(1100,0;1000,100;1100,100);(1100,0;1100,100;1650,100;1925,100;2200,100;2200,0;1650,0;1375,0)") + + p = RBA::DPolygon::new([ [0, 0], [0, 100], [1000, 100], [1000, 1000], [1100, 1000], [1100, 100], [2200, 100], [2200, 0] ]) + assert_equal(sorted_dpolygons(p.hm_decomposition(false, false)), "(0,0;0,100;1000,100);(0,0;1000,100;1100,100);(0,0;1100,100;2200,100;2200,0);(1000,100;1000,1000;1100,1000;1100,100)") + assert_equal(sorted_dpolygons(p.hm_decomposition(true, false)), "(0,0;0,100;1000,100;1000,0);(1000,0;1000,100;1100,100;1100,0);(1000,100;1000,1000;1100,1000;1100,100);(1100,0;1100,100;2200,100;2200,0)") + assert_equal(sorted_dpolygons(p.hm_decomposition(false, true)), "(0,0;0,100;1000,100;1100,100;2200,100;2200,0);(1000,100;1000,1000;1100,1000;1100,100)") + assert_equal(sorted_dpolygons(p.hm_decomposition(true, true)), "(0,0;0,100;1000,100;1000,0);(1000,0;1000,100;1000,1000;1100,1000;1100,100;1100,0);(1100,0;1100,100;2200,100;2200,0)") + assert_equal(sorted_dpolygons(p.hm_decomposition(false, false, 0.0, 0.5)), "(0,0;0,100;500,100;1000,100;1100,0;825,0;550,0;275,0);(1000,100;1000,550;1000,775;1000,1000;1100,1000;1100,550;1100,325;1100,100);(1100,0;1000,100;1100,100);(1100,0;1100,100;1650,100;1925,100;2200,100;2200,0;1650,0;1375,0)") + + end + end load("test_epilogue.rb") diff --git a/testdata/ruby/dbSimplePolygonTest.rb b/testdata/ruby/dbSimplePolygonTest.rb index 268d675ca..ee30323fe 100644 --- a/testdata/ruby/dbSimplePolygonTest.rb +++ b/testdata/ruby/dbSimplePolygonTest.rb @@ -438,6 +438,31 @@ class DBSimplePolygon_TestClass < TestBase end + def sorted_polygons(arr) + arr.each.collect { |p| p.downcast.to_s }.sort.join(";") + end + + def sorted_dpolygons(arr) + arr.each.collect { |p| p.to_s }.sort.join(";") + end + + def test_hm_decomposition + + p = RBA::SimplePolygon::new([ [0, 0], [0, 100], [1000, 100], [1000, 1000], [1100, 1000], [1100, 100], [2200, 100], [2200, 0] ]) + assert_equal(sorted_polygons(p.hm_decomposition(false, false)), "(0,0;0,100;1000,100);(0,0;1000,100;1100,100);(0,0;1100,100;2200,100;2200,0);(1000,100;1000,1000;1100,1000;1100,100)") + assert_equal(sorted_polygons(p.hm_decomposition(true, false)), "(0,0;0,100;1000,100;1000,0);(1000,0;1000,100;1100,100;1100,0);(1000,100;1000,1000;1100,1000;1100,100);(1100,0;1100,100;2200,100;2200,0)") + assert_equal(sorted_polygons(p.hm_decomposition(false, true)), "(0,0;0,100;1000,100;1100,100;2200,100;2200,0);(1000,100;1000,1000;1100,1000;1100,100)") + assert_equal(sorted_polygons(p.hm_decomposition(true, true)), "(0,0;0,100;1000,100;1000,0);(1000,0;1000,100;1000,1000;1100,1000;1100,100;1100,0);(1100,0;1100,100;2200,100;2200,0)") + assert_equal(sorted_polygons(p.hm_decomposition(false, false, 0.0, 0.5)), "(0,0;0,100;500,100;1000,100;1100,0;825,0;550,0;275,0);(1000,100;1000,550;1000,775;1000,1000;1100,1000;1100,550;1100,325;1100,100);(1100,0;1000,100;1100,100);(1100,0;1100,100;1650,100;1925,100;2200,100;2200,0;1650,0;1375,0)") + + p = RBA::DSimplePolygon::new([ [0, 0], [0, 100], [1000, 100], [1000, 1000], [1100, 1000], [1100, 100], [2200, 100], [2200, 0] ]) + assert_equal(sorted_dpolygons(p.hm_decomposition(false, false)), "(0,0;0,100;1000,100);(0,0;1000,100;1100,100);(0,0;1100,100;2200,100;2200,0);(1000,100;1000,1000;1100,1000;1100,100)") + assert_equal(sorted_dpolygons(p.hm_decomposition(true, false)), "(0,0;0,100;1000,100;1000,0);(1000,0;1000,100;1100,100;1100,0);(1000,100;1000,1000;1100,1000;1100,100);(1100,0;1100,100;2200,100;2200,0)") + assert_equal(sorted_dpolygons(p.hm_decomposition(false, true)), "(0,0;0,100;1000,100;1100,100;2200,100;2200,0);(1000,100;1000,1000;1100,1000;1100,100)") + assert_equal(sorted_dpolygons(p.hm_decomposition(true, true)), "(0,0;0,100;1000,100;1000,0);(1000,0;1000,100;1000,1000;1100,1000;1100,100;1100,0);(1100,0;1100,100;2200,100;2200,0)") + assert_equal(sorted_dpolygons(p.hm_decomposition(false, false, 0.0, 0.5)), "(0,0;0,100;500,100;1000,100;1100,0;825,0;550,0;275,0);(1000,100;1000,550;1000,775;1000,1000;1100,1000;1100,550;1100,325;1100,100);(1100,0;1000,100;1100,100);(1100,0;1100,100;1650,100;1925,100;2200,100;2200,0;1650,0;1375,0)") + + end end load("test_epilogue.rb")