diff --git a/src/db/db/dbTriangles.cc b/src/db/db/dbTriangles.cc index e6aff5ee5..9837f5104 100644 --- a/src/db/db/dbTriangles.cc +++ b/src/db/db/dbTriangles.cc @@ -1455,10 +1455,14 @@ Triangles::create_constrained_delaunay (const db::Region ®ion, const CplxTran } void -Triangles::create_constrained_delaunay (const db::Polygon &p, const CplxTrans &trans) +Triangles::create_constrained_delaunay (const db::Polygon &p, const std::vector &vertexes, const CplxTrans &trans) { clear (); + for (auto v = vertexes.begin (); v != vertexes.end (); ++v) { + insert_point (trans * *v); + } + std::vector > edge_contours; make_contours (p, trans, edge_contours); @@ -1466,12 +1470,16 @@ Triangles::create_constrained_delaunay (const db::Polygon &p, const CplxTrans &t } void -Triangles::create_constrained_delaunay (const db::DPolygon &p) +Triangles::create_constrained_delaunay (const db::DPolygon &p, const std::vector &vertexes, const DCplxTrans &trans) { clear (); + for (auto v = vertexes.begin (); v != vertexes.end (); ++v) { + insert_point (trans * *v); + } + std::vector > edge_contours; - make_contours (p, db::DUnitTrans (), edge_contours); + make_contours (p, trans, edge_contours); constrain (edge_contours); } @@ -1529,28 +1537,46 @@ Triangles::triangulate (const db::Region ®ion, const TriangulateParameters &p void Triangles::triangulate (const db::Polygon &poly, const TriangulateParameters ¶meters, double dbu) +{ + triangulate (poly, std::vector (), parameters, dbu); +} + +void +Triangles::triangulate (const db::Polygon &poly, const std::vector &vertexes, const TriangulateParameters ¶meters, double dbu) { tl::SelfTimer timer (tl::verbosity () > parameters.base_verbosity, "Triangles::triangulate"); - create_constrained_delaunay (poly, db::CplxTrans (dbu)); + create_constrained_delaunay (poly, vertexes, db::CplxTrans (dbu)); refine (parameters); } void Triangles::triangulate (const db::Polygon &poly, const TriangulateParameters ¶meters, const db::CplxTrans &trans) +{ + triangulate (poly, std::vector (), parameters, trans); +} + +void +Triangles::triangulate (const db::Polygon &poly, const std::vector &vertexes, const TriangulateParameters ¶meters, const db::CplxTrans &trans) { tl::SelfTimer timer (tl::verbosity () > parameters.base_verbosity, "Triangles::triangulate"); - create_constrained_delaunay (poly, trans); + create_constrained_delaunay (poly, vertexes, trans); refine (parameters); } void -Triangles::triangulate (const db::DPolygon &poly, const TriangulateParameters ¶meters) +Triangles::triangulate (const db::DPolygon &poly, const TriangulateParameters ¶meters, const DCplxTrans &trans) +{ + triangulate (poly, std::vector (), parameters, trans); +} + +void +Triangles::triangulate (const db::DPolygon &poly, const std::vector &vertexes, const TriangulateParameters ¶meters, const DCplxTrans &trans) { tl::SelfTimer timer (tl::verbosity () > parameters.base_verbosity, "Triangles::triangulate"); - create_constrained_delaunay (poly); + create_constrained_delaunay (poly, vertexes, trans); refine (parameters); } diff --git a/src/db/db/dbTriangles.h b/src/db/db/dbTriangles.h index f86f77c1c..f026ce820 100644 --- a/src/db/db/dbTriangles.h +++ b/src/db/db/dbTriangles.h @@ -160,14 +160,17 @@ public: void triangulate (const db::Region ®ion, const TriangulateParameters ¶meters, double dbu = 1.0); // more versions - void triangulate (const db::Polygon &poly, const TriangulateParameters ¶meters, double dbu = 1.0); void triangulate (const db::Region ®ion, const TriangulateParameters ¶meters, const db::CplxTrans &trans = db::CplxTrans ()); + void triangulate (const db::Polygon &poly, const TriangulateParameters ¶meters, double dbu = 1.0); + void triangulate (const db::Polygon &poly, const std::vector &vertexes, const TriangulateParameters ¶meters, double dbu = 1.0); void triangulate (const db::Polygon &poly, const TriangulateParameters ¶meters, const db::CplxTrans &trans = db::CplxTrans ()); + void triangulate (const db::Polygon &poly, const std::vector &vertexes, const TriangulateParameters ¶meters, const db::CplxTrans &trans = db::CplxTrans ()); /** * @brief Triangulates a floating-point polygon */ - void triangulate (const db::DPolygon &poly, const TriangulateParameters ¶meters); + void triangulate (const db::DPolygon &poly, const TriangulateParameters ¶meters, const db::DCplxTrans &trans = db::DCplxTrans ()); + void triangulate (const db::DPolygon &poly, const std::vector &vertexes, const TriangulateParameters ¶meters, const db::DCplxTrans &trans = db::DCplxTrans ()); /** * @brief Statistics: number of flips (fixing) @@ -289,12 +292,12 @@ protected: /** * @brief Creates a constrained Delaunay triangulation from the given Polygon */ - void create_constrained_delaunay (const db::Polygon &poly, const db::CplxTrans &trans = db::CplxTrans ()); + void create_constrained_delaunay (const db::Polygon &poly, const std::vector &vertexes, const db::CplxTrans &trans = db::CplxTrans ()); /** * @brief Creates a constrained Delaunay triangulation from the given DPolygon */ - void create_constrained_delaunay (const db::DPolygon &poly); + void create_constrained_delaunay (const db::DPolygon &poly, const std::vector &vertexes, const DCplxTrans &trans); /** * @brief Returns a value indicating whether the edge is "illegal" (violates the Delaunay criterion) diff --git a/src/db/db/gsiDeclDbPolygon.cc b/src/db/db/gsiDeclDbPolygon.cc index 4ebb782a0..8282198ab 100644 --- a/src/db/db/gsiDeclDbPolygon.cc +++ b/src/db/db/gsiDeclDbPolygon.cc @@ -28,10 +28,124 @@ #include "dbPolygonTools.h" #include "dbPolygonGenerators.h" #include "dbHash.h" +#include "dbTriangles.h" namespace gsi { +template +static db::Region region_from_triangles (const db::Triangles &tri, const T &trans) +{ + db::Region result; + + 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); + } + + return result; +} + +template +static std::vector

polygons_from_triangles (const db::Triangles &tri, const T &trans) +{ + std::vector

result; + result.reserve (tri.num_triangles ()); + + 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); + } + + return result; +} + +template +static db::polygon to_polygon (const db::simple_polygon &sp) +{ + db::polygon p; + p.assign_hull (sp.begin_hull (), sp.end_hull ()); + return p; +} + +template +static db::polygon to_polygon (const db::polygon &p) +{ + return p; +} + +template +static db::Region triangulate_ipolygon (const P *p, double max_area = 0.0, double min_b = 0.0, double dbu = 0.001) +{ + db::Triangles tris; + db::Triangles::TriangulateParameters param; + param.min_b = min_b; + param.max_area = max_area * dbu * dbu; + + db::CplxTrans trans = db::CplxTrans (dbu) * db::ICplxTrans (db::Trans (db::Point () - p->box ().center ())); + + tris.triangulate (to_polygon (*p), param, trans); + + return region_from_triangles (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) +{ + db::Triangles tris; + db::Triangles::TriangulateParameters param; + param.min_b = min_b; + param.max_area = max_area * dbu * dbu; + + db::CplxTrans trans = db::CplxTrans (dbu) * db::ICplxTrans (db::Trans (db::Point () - p->box ().center ())); + + tris.triangulate (to_polygon (*p), vertexes, param, trans); + + return region_from_triangles (tris, trans.inverted ()); +} + +template +static std::vector

triangulate_dpolygon (const P *p, double max_area = 0.0, double min_b = 0.0) +{ + db::Triangles tris; + db::Triangles::TriangulateParameters param; + param.min_b = min_b; + param.max_area = max_area; + + db::DCplxTrans trans = db::DCplxTrans (db::DTrans (db::DPoint () - p->box ().center ())); + + tris.triangulate (to_polygon (*p), param, trans); + + return polygons_from_triangles (tris, trans.inverted ()); +} + +template +static std::vector

triangulate_dpolygon_v (const P *p, const std::vector &vertexes, double max_area = 0.0, double min_b = 0.0) +{ + db::Triangles tris; + db::Triangles::TriangulateParameters param; + param.min_b = min_b; + param.max_area = max_area; + + db::DCplxTrans trans = db::DCplxTrans (db::DTrans (db::DPoint () - p->box ().center ())); + + tris.triangulate (to_polygon (*p), vertexes, param, trans); + + return polygons_from_triangles (tris, trans.inverted ()); +} + template static std::vector split_poly (const C *p) { @@ -766,6 +880,37 @@ Class decl_SimplePolygon ("db", "SimplePolygon", "\n" "This method has been introduced in version 0.18.\n" ) + + 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." + ) + + 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." + ) + simple_polygon_defs::methods (), "@brief A simple polygon class\n" "\n" @@ -861,6 +1006,33 @@ Class decl_DSimplePolygon ("db", "DSimplePolygon", "\n" "This method has been introduced in version 0.25.\n" ) + + 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" + "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), + "@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." + ) + simple_polygon_defs::methods (), "@brief A simple polygon class\n" "\n" @@ -2035,6 +2207,37 @@ Class decl_Polygon ("db", "Polygon", "\n" "This method was introduced in version 0.18.\n" ) + + 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." + ) + + 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." + ) + polygon_defs::methods (), "@brief A polygon class\n" "\n" @@ -2157,6 +2360,33 @@ Class decl_DPolygon ("db", "DPolygon", "\n" "This method has been introduced in version 0.25.\n" ) + + 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" + "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), + "@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." + ) + polygon_defs::methods (), "@brief A polygon class\n" "\n"