mirror of https://github.com/KLayout/klayout.git
Region#drc_hull for generating DRC space forbidding region visualizations
This commit is contained in:
parent
6c8ff49bc7
commit
03d77bbff6
|
|
@ -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 ());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
Loading…
Reference in New Issue