diff --git a/src/db/db/dbAsIfFlatRegion.cc b/src/db/db/dbAsIfFlatRegion.cc index 5445550ec..03782957f 100644 --- a/src/db/db/dbAsIfFlatRegion.cc +++ b/src/db/db/dbAsIfFlatRegion.cc @@ -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 +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 (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 (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 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 +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 (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 (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 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) diff --git a/src/db/db/dbAsIfFlatRegion.h b/src/db/db/dbAsIfFlatRegion.h index f3dfec779..c414dafa0 100644 --- a/src/db/db/dbAsIfFlatRegion.h +++ b/src/db/db/dbAsIfFlatRegion.h @@ -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 + static void produce_markers_for_grid_check (const db::Polygon &poly, const Trans &tr, db::Coord gx, db::Coord gy, db::Shapes &shapes); + template + 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 &heap); private: diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index 7ad2960b7..e4b6c82da 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -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 &vv = vars.variants (c->cell_index ()); for (std::map::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 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 * diff --git a/src/db/db/dbFlatEdgePairs.h b/src/db/db/dbFlatEdgePairs.h index f77074c0e..b1d5cfef6 100644 --- a/src/db/db/dbFlatEdgePairs.h +++ b/src/db/db/dbFlatEdgePairs.h @@ -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; diff --git a/src/db/unit_tests/dbDeepRegionTests.cc b/src/db/unit_tests/dbDeepRegionTests.cc index 16bb37458..fc398e7de 100644 --- a/src/db/unit_tests/dbDeepRegionTests.cc +++ b/src/db/unit_tests/dbDeepRegionTests.cc @@ -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; diff --git a/testdata/algo/angle_check_l1.gds b/testdata/algo/angle_check_l1.gds new file mode 100644 index 000000000..0c539f083 Binary files /dev/null and b/testdata/algo/angle_check_l1.gds differ diff --git a/testdata/algo/deep_region_au20.gds b/testdata/algo/deep_region_au20.gds new file mode 100644 index 000000000..e0a4ec139 Binary files /dev/null and b/testdata/algo/deep_region_au20.gds differ