mirror of https://github.com/KLayout/klayout.git
Hierarchical angle check.
This commit is contained in:
parent
a7bfaac424
commit
8e5bffcf18
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "dbAsIfFlatRegion.h"
|
||||
#include "dbFlatRegion.h"
|
||||
#include "dbFlatEdgePairs.h"
|
||||
#include "dbEmptyRegion.h"
|
||||
#include "dbRegion.h"
|
||||
#include "dbShapeProcessor.h"
|
||||
|
|
@ -404,39 +405,48 @@ AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, boo
|
|||
return output.release ();
|
||||
}
|
||||
|
||||
EdgePairs
|
||||
AsIfFlatRegion::grid_check (db::Coord gx, db::Coord gy) const
|
||||
template <class Trans>
|
||||
void
|
||||
AsIfFlatRegion::produce_markers_for_grid_check (const db::Polygon &poly, const Trans &tr, db::Coord gx, db::Coord gy, db::Shapes &shapes)
|
||||
{
|
||||
EdgePairs out;
|
||||
|
||||
gx = std::max (db::Coord (1), gx);
|
||||
gy = std::max (db::Coord (1), gy);
|
||||
|
||||
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) {
|
||||
for (size_t i = 0; i < poly.holes () + 1; ++i) {
|
||||
|
||||
for (size_t i = 0; i < p->holes () + 1; ++i) {
|
||||
db::Polygon::polygon_contour_iterator b, e;
|
||||
|
||||
db::Polygon::polygon_contour_iterator b, e;
|
||||
if (i == 0) {
|
||||
b = poly.begin_hull ();
|
||||
e = poly.end_hull ();
|
||||
} else {
|
||||
b = poly.begin_hole ((unsigned int) (i - 1));
|
||||
e = poly.end_hole ((unsigned int) (i - 1));
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
b = p->begin_hull ();
|
||||
e = p->end_hull ();
|
||||
} else {
|
||||
b = p->begin_hole ((unsigned int) (i - 1));
|
||||
e = p->end_hole ((unsigned int) (i - 1));
|
||||
for (db::Polygon::polygon_contour_iterator pt = b; pt != e; ++pt) {
|
||||
db::Point p = tr * *pt;
|
||||
if ((p.x () % gx) != 0 || (p.y () % gy) != 0) {
|
||||
shapes.insert (EdgePair (db::Edge (p, p), db::Edge (p, p)));
|
||||
}
|
||||
|
||||
for (db::Polygon::polygon_contour_iterator pt = b; pt != e; ++pt) {
|
||||
if (((*pt).x () % gx) != 0 || ((*pt).y () % gy) != 0) {
|
||||
out.insert (EdgePair (db::Edge (*pt, *pt), db::Edge (*pt, *pt)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
template void AsIfFlatRegion::produce_markers_for_grid_check<db::ICplxTrans> (const db::Polygon &poly, const db::ICplxTrans &tr, db::Coord gx, db::Coord gy, db::Shapes &shapes);
|
||||
template void AsIfFlatRegion::produce_markers_for_grid_check<db::UnitTrans> (const db::Polygon &poly, const db::UnitTrans &tr, db::Coord gx, db::Coord gy, db::Shapes &shapes);
|
||||
|
||||
EdgePairs
|
||||
AsIfFlatRegion::grid_check (db::Coord gx, db::Coord gy) const
|
||||
{
|
||||
std::auto_ptr<db::FlatEdgePairs> res (new db::FlatEdgePairs ());
|
||||
|
||||
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) {
|
||||
produce_markers_for_grid_check (*p, db::UnitTrans (), gx, gy, res->raw_edge_pairs ());
|
||||
}
|
||||
|
||||
return EdgePairs (res.release ());
|
||||
}
|
||||
|
||||
static bool ac_less (double cos_a, bool gt180_a, double cos_b, bool gt180_b)
|
||||
|
|
@ -452,50 +462,61 @@ static bool ac_less (double cos_a, bool gt180_a, double cos_b, bool gt180_b)
|
|||
}
|
||||
}
|
||||
|
||||
EdgePairs
|
||||
AsIfFlatRegion::angle_check (double min, double max, bool inverse) const
|
||||
template <class Trans>
|
||||
void
|
||||
AsIfFlatRegion::produce_markers_for_angle_check (const db::Polygon &poly, const Trans &tr, double min, double max, bool inverse, db::Shapes &shapes)
|
||||
{
|
||||
EdgePairs out;
|
||||
|
||||
double cos_min = cos (std::max (0.0, std::min (360.0, min)) / 180.0 * M_PI);
|
||||
double cos_max = cos (std::max (0.0, std::min (360.0, max)) / 180.0 * M_PI);
|
||||
bool gt180_min = min > 180.0;
|
||||
bool gt180_max = max > 180.0;
|
||||
|
||||
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) {
|
||||
for (size_t i = 0; i < poly.holes () + 1; ++i) {
|
||||
|
||||
for (size_t i = 0; i < p->holes () + 1; ++i) {
|
||||
const db::Polygon::contour_type *h = 0;
|
||||
if (i == 0) {
|
||||
h = &poly.hull ();
|
||||
} else {
|
||||
h = &poly.hole ((unsigned int) (i - 1));
|
||||
}
|
||||
|
||||
const db::Polygon::contour_type *h = 0;
|
||||
if (i == 0) {
|
||||
h = &p->hull ();
|
||||
} else {
|
||||
h = &p->hole ((unsigned int) (i - 1));
|
||||
}
|
||||
size_t np = h->size ();
|
||||
|
||||
size_t np = h->size ();
|
||||
for (size_t j = 0; j < np; ++j) {
|
||||
|
||||
for (size_t j = 0; j < np; ++j) {
|
||||
db::Edge e ((*h) [j], (*h) [(j + 1) % np]);
|
||||
e.transform (tr);
|
||||
db::Edge ee (e.p2 (), (*h) [(j + 2) % np]);
|
||||
ee.transform (tr);
|
||||
|
||||
db::Edge e ((*h) [j], (*h) [(j + 1) % np]);
|
||||
db::Edge ee (e.p2 (), (*h) [(j + 2) % np]);
|
||||
double le = e.double_length ();
|
||||
double lee = ee.double_length ();
|
||||
double le = e.double_length ();
|
||||
double lee = ee.double_length ();
|
||||
|
||||
double cos_a = -db::sprod (e, ee) / (le * lee);
|
||||
bool gt180_a = db::vprod_sign (e, ee) > 0;
|
||||
|
||||
if ((ac_less (cos_a, gt180_a, cos_max, gt180_max) && !ac_less (cos_a, gt180_a, cos_min, gt180_min)) == !inverse) {
|
||||
out.insert (EdgePair (e, ee));
|
||||
}
|
||||
double cos_a = -db::sprod (e, ee) / (le * lee);
|
||||
bool gt180_a = db::vprod_sign (e, ee) > 0;
|
||||
|
||||
if ((ac_less (cos_a, gt180_a, cos_max, gt180_max) && !ac_less (cos_a, gt180_a, cos_min, gt180_min)) == !inverse) {
|
||||
shapes.insert (EdgePair (e, ee));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
template void AsIfFlatRegion::produce_markers_for_angle_check<db::ICplxTrans> (const db::Polygon &poly, const db::ICplxTrans &tr, double min, double max, bool inverse, db::Shapes &shapes);
|
||||
template void AsIfFlatRegion::produce_markers_for_angle_check<db::UnitTrans> (const db::Polygon &poly, const db::UnitTrans &tr, double min, double max, bool inverse, db::Shapes &shapes);
|
||||
|
||||
EdgePairs
|
||||
AsIfFlatRegion::angle_check (double min, double max, bool inverse) const
|
||||
{
|
||||
std::auto_ptr<db::FlatEdgePairs> res (new db::FlatEdgePairs ());
|
||||
|
||||
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) {
|
||||
produce_markers_for_angle_check (*p, db::UnitTrans (), min, max, inverse, res->raw_edge_pairs ());
|
||||
}
|
||||
|
||||
return EdgePairs (res.release ());
|
||||
}
|
||||
|
||||
static inline db::Coord snap_to_grid (db::Coord c, db::Coord g)
|
||||
|
|
|
|||
|
|
@ -542,6 +542,10 @@ protected:
|
|||
RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse) const;
|
||||
|
||||
static void produce_shape_for_strange_polygon (const db::Polygon &poly, db::Shapes &shapes);
|
||||
template <class Trans>
|
||||
static void produce_markers_for_grid_check (const db::Polygon &poly, const Trans &tr, db::Coord gx, db::Coord gy, db::Shapes &shapes);
|
||||
template <class Trans>
|
||||
static void produce_markers_for_angle_check (const db::Polygon &poly, const Trans &tr, double min, double max, bool inverse, db::Shapes &shapes);
|
||||
static db::Polygon snapped_polygon (const db::Polygon &poly, db::Coord gx, db::Coord gy, std::vector<db::Point> &heap);
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -713,38 +713,6 @@ DeepRegion::to_string (size_t nmax) const
|
|||
return db::AsIfFlatRegion::to_string (nmax);
|
||||
}
|
||||
|
||||
static void produce_offgrid_markers (db::Shapes &markers, const db::Shapes &shapes, const db::ICplxTrans &tr, db::Coord g)
|
||||
{
|
||||
for (db::Shapes::shape_iterator si = shapes.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
|
||||
|
||||
db::Polygon poly;
|
||||
si->polygon (poly);
|
||||
|
||||
for (size_t i = 0; i < poly.holes () + 1; ++i) {
|
||||
|
||||
db::Polygon::polygon_contour_iterator b, e;
|
||||
|
||||
if (i == 0) {
|
||||
b = poly.begin_hull ();
|
||||
e = poly.end_hull ();
|
||||
} else {
|
||||
b = poly.begin_hole ((unsigned int) (i - 1));
|
||||
e = poly.end_hole ((unsigned int) (i - 1));
|
||||
}
|
||||
|
||||
for (db::Polygon::polygon_contour_iterator p = b; p != e; ++p) {
|
||||
db::Point pt = tr * *p;
|
||||
if ((pt.x () % g) != 0 || (pt.y () % g) != 0) {
|
||||
markers.insert (EdgePair (db::Edge (pt, pt), db::Edge (pt, pt)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
EdgePairs
|
||||
DeepRegion::grid_check (db::Coord gx, db::Coord gy) const
|
||||
{
|
||||
|
|
@ -769,6 +737,8 @@ DeepRegion::grid_check (db::Coord gx, db::Coord gy) const
|
|||
|
||||
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
|
||||
|
||||
const db::Shapes &shapes = c->shapes (m_merged_polygons.layer ());
|
||||
|
||||
const std::map<db::ICplxTrans, size_t> &vv = vars.variants (c->cell_index ());
|
||||
for (std::map<db::ICplxTrans, size_t>::const_iterator v = vv.begin (); v != vv.end (); ++v) {
|
||||
|
||||
|
|
@ -779,7 +749,14 @@ DeepRegion::grid_check (db::Coord gx, db::Coord gy) const
|
|||
markers = & to_commit [c->cell_index ()] [v->first];
|
||||
}
|
||||
|
||||
produce_offgrid_markers (*markers, c->shapes (m_merged_polygons.layer ()), v->first, gx);
|
||||
for (db::Shapes::shape_iterator si = shapes.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
|
||||
|
||||
db::Polygon poly;
|
||||
si->polygon (poly);
|
||||
|
||||
AsIfFlatRegion::produce_markers_for_grid_check (poly, v->first, gx, gy, *markers);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -794,8 +771,26 @@ DeepRegion::grid_check (db::Coord gx, db::Coord gy) const
|
|||
EdgePairs
|
||||
DeepRegion::angle_check (double min, double max, bool inverse) const
|
||||
{
|
||||
// TODO: snap be optimized by forming rotation variants etc.
|
||||
return db::AsIfFlatRegion::angle_check (min, max, inverse);
|
||||
ensure_merged_polygons_valid ();
|
||||
|
||||
db::Layout &layout = m_merged_polygons.layout ();
|
||||
|
||||
std::auto_ptr<db::DeepEdgePairs> res (new db::DeepEdgePairs (m_merged_polygons.derived ()));
|
||||
|
||||
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
|
||||
|
||||
const db::Shapes &shapes = c->shapes (m_merged_polygons.layer ());
|
||||
db::Shapes &markers = c->shapes (res->deep_layer ().layer ());
|
||||
|
||||
for (db::Shapes::shape_iterator si = shapes.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
|
||||
db::Polygon poly;
|
||||
si->polygon (poly);
|
||||
AsIfFlatRegion::produce_markers_for_angle_check (poly, db::UnitTrans (), min, max, inverse, markers);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return db::EdgePairs (res.release ());
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
|
|
|
|||
|
|
@ -150,6 +150,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
db::Shapes &raw_edge_pairs () { return m_edge_pairs; }
|
||||
|
||||
protected:
|
||||
virtual Box compute_bbox () const;
|
||||
void invalidate_cache ();
|
||||
|
|
@ -157,8 +159,6 @@ protected:
|
|||
private:
|
||||
friend class AsIfFlatEdgePairs;
|
||||
|
||||
db::Shapes &raw_edge_pairs () { return m_edge_pairs; }
|
||||
|
||||
FlatEdgePairs &operator= (const FlatEdgePairs &other);
|
||||
|
||||
mutable db::Shapes m_edge_pairs;
|
||||
|
|
|
|||
|
|
@ -1048,6 +1048,39 @@ TEST(19_GridCheck)
|
|||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au19.gds");
|
||||
}
|
||||
|
||||
TEST(19_AngleCheck)
|
||||
{
|
||||
db::Layout ly;
|
||||
{
|
||||
std::string fn (tl::testsrc ());
|
||||
fn += "/testdata/algo/angle_check_l1.gds";
|
||||
tl::InputStream stream (fn);
|
||||
db::Reader reader (stream);
|
||||
reader.read (ly);
|
||||
}
|
||||
|
||||
db::cell_index_type top_cell_index = *ly.begin_top_down ();
|
||||
db::Cell &top_cell = ly.cell (top_cell_index);
|
||||
|
||||
db::DeepShapeStore dss;
|
||||
|
||||
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
|
||||
|
||||
db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1), dss);
|
||||
db::EdgePairs ep1_ac1 = r1.angle_check (0, 91, true);
|
||||
db::EdgePairs ep1_ac2 = r1.angle_check (0, 45, false);
|
||||
|
||||
db::Layout target;
|
||||
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (1, 0)), r1);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (2, 0)), ep1_ac1);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (3, 0)), ep1_ac2);
|
||||
|
||||
CHECKPOINT();
|
||||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au20.gds");
|
||||
}
|
||||
|
||||
TEST(100_Integration)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue