Hierarchical angle check.

This commit is contained in:
Matthias Koefferlein 2019-02-17 11:42:30 +01:00
parent a7bfaac424
commit 8e5bffcf18
7 changed files with 136 additions and 83 deletions

View File

@ -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)

View File

@ -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:

View File

@ -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 *

View File

@ -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;

View File

@ -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;

BIN
testdata/algo/angle_check_l1.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/deep_region_au20.gds vendored Normal file

Binary file not shown.