WIP: Polygon#delaunay and variants

This commit is contained in:
Matthias Koefferlein 2025-03-23 09:55:08 +01:00
parent 21bfe7a632
commit 593678e228
3 changed files with 270 additions and 11 deletions

View File

@ -1455,10 +1455,14 @@ Triangles::create_constrained_delaunay (const db::Region &region, 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<Point> &vertexes, const CplxTrans &trans)
{
clear ();
for (auto v = vertexes.begin (); v != vertexes.end (); ++v) {
insert_point (trans * *v);
}
std::vector<std::vector<db::Vertex *> > 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<DPoint> &vertexes, const DCplxTrans &trans)
{
clear ();
for (auto v = vertexes.begin (); v != vertexes.end (); ++v) {
insert_point (trans * *v);
}
std::vector<std::vector<db::Vertex *> > 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 &region, const TriangulateParameters &p
void
Triangles::triangulate (const db::Polygon &poly, const TriangulateParameters &parameters, double dbu)
{
triangulate (poly, std::vector<db::Point> (), parameters, dbu);
}
void
Triangles::triangulate (const db::Polygon &poly, const std::vector<db::Point> &vertexes, const TriangulateParameters &parameters, 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 &parameters, const db::CplxTrans &trans)
{
triangulate (poly, std::vector<db::Point> (), parameters, trans);
}
void
Triangles::triangulate (const db::Polygon &poly, const std::vector<db::Point> &vertexes, const TriangulateParameters &parameters, 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 &parameters)
Triangles::triangulate (const db::DPolygon &poly, const TriangulateParameters &parameters, const DCplxTrans &trans)
{
triangulate (poly, std::vector<db::DPoint> (), parameters, trans);
}
void
Triangles::triangulate (const db::DPolygon &poly, const std::vector<db::DPoint> &vertexes, const TriangulateParameters &parameters, 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);
}

View File

@ -160,14 +160,17 @@ public:
void triangulate (const db::Region &region, const TriangulateParameters &parameters, double dbu = 1.0);
// more versions
void triangulate (const db::Polygon &poly, const TriangulateParameters &parameters, double dbu = 1.0);
void triangulate (const db::Region &region, const TriangulateParameters &parameters, const db::CplxTrans &trans = db::CplxTrans ());
void triangulate (const db::Polygon &poly, const TriangulateParameters &parameters, double dbu = 1.0);
void triangulate (const db::Polygon &poly, const std::vector<db::Point> &vertexes, const TriangulateParameters &parameters, double dbu = 1.0);
void triangulate (const db::Polygon &poly, const TriangulateParameters &parameters, const db::CplxTrans &trans = db::CplxTrans ());
void triangulate (const db::Polygon &poly, const std::vector<db::Point> &vertexes, const TriangulateParameters &parameters, const db::CplxTrans &trans = db::CplxTrans ());
/**
* @brief Triangulates a floating-point polygon
*/
void triangulate (const db::DPolygon &poly, const TriangulateParameters &parameters);
void triangulate (const db::DPolygon &poly, const TriangulateParameters &parameters, const db::DCplxTrans &trans = db::DCplxTrans ());
void triangulate (const db::DPolygon &poly, const std::vector<db::DPoint> &vertexes, const TriangulateParameters &parameters, 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<db::Point> &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<DPoint> &vertexes, const DCplxTrans &trans);
/**
* @brief Returns a value indicating whether the edge is "illegal" (violates the Delaunay criterion)

View File

@ -28,10 +28,124 @@
#include "dbPolygonTools.h"
#include "dbPolygonGenerators.h"
#include "dbHash.h"
#include "dbTriangles.h"
namespace gsi
{
template <class T>
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 <class P, class T>
static std::vector<P> polygons_from_triangles (const db::Triangles &tri, const T &trans)
{
std::vector<P> 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 <class C>
static db::polygon<C> to_polygon (const db::simple_polygon<C> &sp)
{
db::polygon<C> p;
p.assign_hull (sp.begin_hull (), sp.end_hull ());
return p;
}
template <class C>
static db::polygon<C> to_polygon (const db::polygon<C> &p)
{
return p;
}
template <class P>
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 <class P>
static db::Region triangulate_ipolygon_v (const P *p, const std::vector<db::Point> &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 <class P>
static std::vector<P> 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<P, db::DCplxTrans> (tris, trans.inverted ());
}
template <class P>
static std::vector<P> triangulate_dpolygon_v (const P *p, const std::vector<db::DPoint> &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<P, db::DCplxTrans> (tris, trans.inverted ());
}
template <class C>
static std::vector<C> split_poly (const C *p)
{
@ -766,6 +880,37 @@ Class<db::SimplePolygon> decl_SimplePolygon ("db", "SimplePolygon",
"\n"
"This method has been introduced in version 0.18.\n"
) +
method_ext ("delaunay", &triangulate_ipolygon<db::SimplePolygon>, 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<db::SimplePolygon>, 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<db::SimplePolygon>::methods (),
"@brief A simple polygon class\n"
"\n"
@ -861,6 +1006,33 @@ Class<db::DSimplePolygon> decl_DSimplePolygon ("db", "DSimplePolygon",
"\n"
"This method has been introduced in version 0.25.\n"
) +
method_ext ("delaunay", &triangulate_dpolygon<db::DSimplePolygon>, 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<db::DSimplePolygon>, 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<db::DSimplePolygon>::methods (),
"@brief A simple polygon class\n"
"\n"
@ -2035,6 +2207,37 @@ Class<db::Polygon> decl_Polygon ("db", "Polygon",
"\n"
"This method was introduced in version 0.18.\n"
) +
method_ext ("delaunay", &triangulate_ipolygon<db::Polygon>, 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<db::Polygon>, 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<db::Polygon>::methods (),
"@brief A polygon class\n"
"\n"
@ -2157,6 +2360,33 @@ Class<db::DPolygon> decl_DPolygon ("db", "DPolygon",
"\n"
"This method has been introduced in version 0.25.\n"
) +
method_ext ("delaunay", &triangulate_dpolygon<db::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<db::DPolygon>, 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<db::DPolygon>::methods (),
"@brief A polygon class\n"
"\n"