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 "dbEdgesUtils.h"
#include "dbTriangles.h"
#include "dbEdgePairRelations.h"
namespace db
{
@ -464,6 +465,24 @@ private:
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

View File

@ -436,6 +436,11 @@ static db::Region refined_delaunay (const db::Region *r, double max_area, double
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)
{
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."
"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"),
"@brief Moves the region\n"
"\n"

View File

@ -1452,6 +1452,18 @@ class DBRegion_TestClass < TestBase
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
load("test_epilogue.rb")