Region#drc_hull for generating DRC space forbidding region visualizations

This commit is contained in:
Matthias Koefferlein 2024-03-30 22:01:39 +01:00
parent 6c8ff49bc7
commit 03d77bbff6
4 changed files with 168 additions and 0 deletions

View File

@ -346,4 +346,125 @@ TriangulationProcessor::process (const db::Polygon &poly, std::vector<db::Polygo
} }
} }
// -----------------------------------------------------------------------------------
// DRCHullProcessor implementation
DRCHullProcessor::DRCHullProcessor (db::Coord d, db::metrics_type metrics, size_t n_circle)
: m_d (d), m_metrics (metrics), m_n_circle (n_circle)
{
// .. nothing yet ..
}
static void create_edge_segment_euclidian (std::vector<db::Point> &points, const db::Edge &e, db::Coord dist, size_t n_circle)
{
db::Vector d (e.d ());
db::Vector n (-d.y (), d.x ());
if (d.x () == 0 && d.y () == 0) {
return;
}
double da = M_PI * 2.0 / n_circle;
double f = dist / n.double_length ();
double f2 = f / cos (0.5 * da);
points.push_back (e.p1 ());
points.push_back (e.p1 () + db::Vector (d * -f));
for (size_t i = 0; i < n_circle / 4; ++i) {
double a = (i + 0.5) * da;
points.push_back (e.p1 () + db::Vector (d * (-f2 * cos (a)) + n * (f2 * sin (a))));
}
points.push_back (e.p1 () + db::Vector (n * f));
points.push_back (e.p2 () + db::Vector (n * f));
for (size_t i = 0; i < n_circle / 4; ++i) {
double a = (i + 0.5) * da;
points.push_back (e.p2 () + db::Vector (d * (f2 * sin (a)) + n * (f2 * cos (a))));
}
points.push_back (e.p2 () + db::Vector (d * f));
}
static void create_edge_segment_square (std::vector<db::Point> &points, const db::Edge &e, db::Coord dist)
{
db::Vector d (e.d ());
db::Vector n (-d.y (), d.x ());
if (d.x () == 0 && d.y () == 0) {
return;
}
double f = dist / n.double_length ();
points.push_back (e.p1 ());
points.push_back (e.p1 () + db::Vector (d * -f));
points.push_back (e.p1 () + db::Vector (d * -f + n * f));
points.push_back (e.p2 () + db::Vector (d * f + n * f));
points.push_back (e.p2 () + db::Vector (d * f));
}
static void create_edge_segment_projection (std::vector<db::Point> &points, const db::Edge &e, db::Coord dist)
{
db::Vector d (e.d ());
db::Vector n (-d.y (), d.x ());
if (d.x () == 0 && d.y () == 0) {
return;
}
double f = dist / n.double_length ();
points.push_back (e.p1 ());
points.push_back (e.p1 () + db::Vector (n * f));
points.push_back (e.p2 () + db::Vector (n * f));
}
static void create_edge_segment (std::vector<db::Point> &points, db::metrics_type metrics, const db::Edge &e, db::Coord d, size_t n_circle)
{
if (metrics == db::Euclidian) {
create_edge_segment_euclidian (points, e, d, n_circle);
} else if (metrics == db::Square) {
create_edge_segment_square (points, e, d);
} else if (metrics == db::Projection) {
create_edge_segment_projection (points, e, d);
}
}
void
DRCHullProcessor::process (const db::Polygon &poly, std::vector<db::Polygon> &result) const
{
result.push_back (db::Polygon ());
for (unsigned int i = 0; i < poly.holes () + 1; ++i) {
auto c = poly.contour (i);
if (c.size () < 2) {
continue;
}
std::vector<db::Point> points;
for (auto p = c.begin (); p != c.end (); ++p) {
auto pp = p;
++pp;
if (pp == c.end ()) {
pp = c.begin ();
}
create_edge_segment (points, m_metrics, db::Edge (*p, *pp), m_d, m_n_circle);
}
if (i == 0) {
result.back ().assign_hull (points.begin (), points.end ());
} else {
result.back ().insert_hole (points.begin (), points.end ());
}
}
}
} }

View File

@ -29,6 +29,7 @@
#include "dbPolygonTools.h" #include "dbPolygonTools.h"
#include "dbEdgesUtils.h" #include "dbEdgesUtils.h"
#include "dbTriangles.h" #include "dbTriangles.h"
#include "dbEdgePairRelations.h"
namespace db namespace db
{ {
@ -464,6 +465,24 @@ private:
db::MagnificationAndOrientationReducer m_vars; db::MagnificationAndOrientationReducer m_vars;
}; };
/**
* @brief Computes DRC hulls for DRC space visualization
*/
class DB_PUBLIC_TEMPLATE DRCHullProcessor
: public db::PolygonProcessorBase
{
public:
DRCHullProcessor (db::Coord d, db::metrics_type metrics, size_t n_circle = 64);
void process (const db::Polygon &poly, std::vector<db::Polygon> &result) const;
private:
db::Coord m_d;
db::metrics_type m_metrics;
size_t m_n_circle;
};
} }
#endif #endif

View File

@ -436,6 +436,11 @@ static db::Region refined_delaunay (const db::Region *r, double max_area, double
return res; return res;
} }
static db::Region drc_hull (const db::Region *r, db::metrics_type metrics, db::Coord space, size_t n_circle)
{
return r->processed (db::DRCHullProcessor (space, metrics, n_circle));
}
static db::Region minkowski_sum_pe (const db::Region *r, const db::Edge &e) static db::Region minkowski_sum_pe (const db::Region *r, const db::Edge &e)
{ {
return r->processed (db::minkowski_sum_computation<db::Edge> (e)); return r->processed (db::minkowski_sum_computation<db::Edge> (e));
@ -2782,6 +2787,17 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"The resulting polygons are not merged. In order to remove overlaps, use the \\merge or \\merged method." "The resulting polygons are not merged. In order to remove overlaps, use the \\merge or \\merged method."
"Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n" "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n"
) + ) +
method_ext ("drc_hull", &drc_hull, gsi::arg ("metrics"), gsi::arg ("space"), gsi::arg ("n_circle", size_t (64)),
"@brief Computes a visualization of the forbidden region for a DRC space check\n"
"\n"
"@param metrics The metrics to apply\n"
"@param space The space value to apply\n"
"@param n_circle The full-circle number of points for the Euclidian space visualization\n"
"\n"
"@return The new polygons representing the forbidden region.\n"
"\n"
"This method has been introduced in version 0.29.\n"
) +
method_ext ("move", &move_p, gsi::arg ("v"), method_ext ("move", &move_p, gsi::arg ("v"),
"@brief Moves the region\n" "@brief Moves the region\n"
"\n" "\n"

View File

@ -1452,6 +1452,18 @@ class DBRegion_TestClass < TestBase
end end
# DRC hull
def test_drc_hull
r = RBA::Region::new()
r.insert(RBA::Polygon::new([[0, 0], [1000, 1000], [1500, 0]]))
assert_equal(r.drc_hull(RBA::Region::Euclidian, 200, 8).merged.to_s, "(-83,-200;-200,-83;-200,83;-141,141;859,1141;917,1200;953,1200;985,1216;1033,1200;1083,1200;1107,1176;1142,1164;1179,1089;1716,15;1700,-33;1700,-83;1675,-108;1664,-142;1619,-164;1583,-200)")
assert_equal(r.drc_hull(RBA::Region::Square, 200).merged.to_s, "(-200,-200;-200,-82;-283,0;1000,1283;1039,1243;1089,1268;1768,-89;1700,-123;1700,-200)")
assert_equal(r.drc_hull(RBA::Region::Projection, 200).merged.to_s, "(0,-200;0,0;-141,141;859,1141;1000,1000;1179,1089;1679,89;1500,0;1500,-200)")
end
end end
load("test_epilogue.rb") load("test_epilogue.rb")