WIP: introduced hierarchical merge and some other hierarchical operations.

This commit is contained in:
Matthias Koefferlein 2019-02-04 23:43:19 +01:00
parent 9c0123df20
commit 981d668161
6 changed files with 762 additions and 40 deletions

View File

@ -207,6 +207,11 @@ protected:
void update_bbox (const db::Box &box);
void invalidate_bbox ();
EdgePairs run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const;
EdgePairs run_single_polygon_check (db::edge_relation_type rel, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const;
RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse) const;
RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse) const;
private:
AsIfFlatRegion &operator= (const AsIfFlatRegion &other);
@ -215,11 +220,6 @@ private:
virtual db::Box compute_bbox () const;
static RegionDelegate *region_from_box (const db::Box &b);
EdgePairs run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const;
EdgePairs run_single_polygon_check (db::edge_relation_type rel, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const;
RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse) const;
RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse) const;
};
}

View File

@ -30,6 +30,10 @@
#include "dbHierProcessor.h"
#include "dbCellMapping.h"
#include "dbLayoutUtils.h"
#include "dbHierNetworkProcessor.h"
#include "dbCellGraphUtils.h"
#include "dbPolygonTools.h"
#include "tlTimer.h"
namespace db
{
@ -92,13 +96,13 @@ private:
// DeepRegion implementation
DeepRegion::DeepRegion (const RecursiveShapeIterator &si, DeepShapeStore &dss, double area_ratio, size_t max_vertex_count)
: AsIfFlatRegion (), m_deep_layer (dss.create_polygon_layer (si, area_ratio, max_vertex_count)), m_merged_polygons (false)
: AsIfFlatRegion (), m_deep_layer (dss.create_polygon_layer (si, area_ratio, max_vertex_count)), m_merged_polygons ()
{
init ();
}
DeepRegion::DeepRegion (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans, bool merged_semantics, double area_ratio, size_t max_vertex_count)
: AsIfFlatRegion (), m_deep_layer (dss.create_polygon_layer (si, area_ratio, max_vertex_count)), m_merged_polygons (false)
: AsIfFlatRegion (), m_deep_layer (dss.create_polygon_layer (si, area_ratio, max_vertex_count)), m_merged_polygons ()
{
init ();
@ -126,16 +130,17 @@ DeepRegion::~DeepRegion ()
DeepRegion::DeepRegion (const DeepRegion &other)
: AsIfFlatRegion (other),
m_deep_layer (other.m_deep_layer.copy ()),
m_merged_polygons (other.m_merged_polygons),
m_merged_polygons_valid (other.m_merged_polygons_valid)
{
// .. nothing yet ..
if (m_merged_polygons_valid) {
m_merged_polygons = other.m_merged_polygons;
}
}
void DeepRegion::init ()
{
m_merged_polygons_valid = false;
m_merged_polygons.clear ();
m_merged_polygons = db::DeepLayer ();
}
RegionDelegate *
@ -161,8 +166,7 @@ DeepRegion::begin_merged () const
if (! merged_semantics ()) {
return begin ();
} else {
ensure_merged_polygons_valid ();
return new FlatRegionIterator (m_merged_polygons.get_layer<db::Polygon, db::unstable_layer_tag> ().begin (), m_merged_polygons.get_layer<db::Polygon, db::unstable_layer_tag> ().end ());
return new DeepRegionIterator (begin_merged_iter ().first);
}
}
@ -187,10 +191,26 @@ std::pair<db::RecursiveShapeIterator, db::ICplxTrans>
DeepRegion::begin_merged_iter () const
{
if (! merged_semantics ()) {
return begin_iter ();
} else {
ensure_merged_polygons_valid ();
return std::make_pair (db::RecursiveShapeIterator (m_merged_polygons), db::ICplxTrans ());
const db::Layout &layout = m_merged_polygons.layout ();
if (layout.cells () == 0) {
return std::make_pair (db::RecursiveShapeIterator (), db::ICplxTrans ());
} else {
const db::Cell &top_cell = layout.cell (*layout.begin_top_down ());
db::RecursiveShapeIterator iter (m_merged_polygons.layout (), top_cell, m_merged_polygons.layer ());
return std::make_pair (iter, db::ICplxTrans ());
}
}
}
@ -253,36 +273,126 @@ DeepRegion::less (const Region &other) const
}
}
namespace {
class ClusterMerger
{
public:
ClusterMerger (unsigned int layer, const db::hier_clusters<db::PolygonRef> &hc, bool min_coherence, bool report_progress, const std::string &progress_desc)
: m_layer (layer), mp_hc (&hc), m_min_coherence (min_coherence), m_ep (report_progress, progress_desc)
{
// .. nothing yet ..
}
void set_base_verbosity (int vb)
{
m_ep.set_base_verbosity (vb);
}
db::Shapes &merged (size_t cid, db::cell_index_type ci, bool initial = true)
{
std::map<size_t, db::Shapes>::iterator s = m_merged_cluster.find (cid);
// some sanity checks: initial clusters are single-use, are never generated twice and cannot be retrieved again
if (initial) {
tl_assert (s == m_merged_cluster.end ());
m_done.insert (cid);
} else {
tl_assert (m_done.find (cid) == m_done.end ());
}
if (s != m_merged_cluster.end ()) {
return s->second;
}
s = m_merged_cluster.insert (std::make_pair (cid, db::Shapes ())).first;
const db::connected_clusters<db::PolygonRef> &cc = mp_hc->clusters_per_cell (ci);
const db::local_cluster<db::PolygonRef> &c = cc.cluster_by_id (cid);
std::list<std::pair<const db::Shapes *, db::ICplxTrans> > merged_child_clusters;
const db::connected_clusters<db::PolygonRef>::connections_type &conn = cc.connections_for_cluster (cid);
for (db::connected_clusters<db::PolygonRef>::connections_type::const_iterator i = conn.begin (); i != conn.end (); ++i) {
const db::Shapes &cc_shapes = merged (i->id (), i->inst ().inst_ptr.cell_index (), false);
merged_child_clusters.push_back (std::make_pair (&cc_shapes, i->inst ().complex_trans ()));
}
m_ep.clear ();
size_t pi = 0;
for (std::list<std::pair<const db::Shapes *, db::ICplxTrans> >::const_iterator i = merged_child_clusters.begin (); i != merged_child_clusters.end (); ++i) {
for (db::Shapes::shape_iterator s = i->first->begin (db::ShapeIterator::All); ! s.at_end (); ++s) {
if (s->is_polygon ()) {
db::Polygon poly;
s->polygon (poly);
m_ep.insert (poly.transformed (i->second), pi++);
}
}
}
for (db::local_cluster<db::PolygonRef>::shape_iterator s = c.begin (m_layer); !s.at_end (); ++s) {
db::Polygon poly = s->obj ();
poly.transform (s->trans ());
m_ep.insert (poly, pi++);
}
// and run the merge step
db::MergeOp op (0);
db::ShapeGenerator pc (s->second);
db::PolygonGenerator pg (pc, false /*don't resolve holes*/, m_min_coherence);
m_ep.process (pg, op);
return s->second;
}
private:
std::map<size_t, db::Shapes> m_merged_cluster;
std::set<size_t> m_done;
unsigned int m_layer;
const db::hier_clusters<db::PolygonRef> *mp_hc;
bool m_min_coherence;
db::EdgeProcessor m_ep;
};
}
void
DeepRegion::ensure_merged_polygons_valid () const
{
if (! m_merged_polygons_valid) {
m_merged_polygons.clear ();
m_merged_polygons = m_deep_layer.new_layer ();
db::EdgeProcessor ep (report_progress (), progress_desc ());
tl::SelfTimer timer (tl::verbosity () > base_verbosity (), "Ensure merged polygons");
db::Layout &layout = const_cast<db::Layout &> (m_deep_layer.layout ());
db::hier_clusters<db::PolygonRef> hc;
db::Connectivity conn;
conn.connect (m_deep_layer);
// TODO: this uses the wrong verbosity inside ...
hc.build (layout, m_deep_layer.initial_cell (), db::ShapeIterator::Polygons, conn);
// collect the clusters and merge them into big polygons
// NOTE: using the ClusterMerger we merge bottom-up forming bigger and bigger polygons. This is
// hopefully more efficient that collecting everything and will lead to reuse of parts.
ClusterMerger cm (m_deep_layer.layer (), hc, min_coherence (), report_progress (), progress_desc ());
if (base_verbosity ()) {
ep.set_base_verbosity (base_verbosity ());
cm.set_base_verbosity (base_verbosity ());
}
// count edges and reserve memory
size_t n = 0;
for (RegionIterator p (begin ()); ! p.at_end (); ++p) {
n += p->vertices ();
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const db::connected_clusters<db::PolygonRef> &cc = hc.clusters_per_cell (c->cell_index ());
for (db::connected_clusters<db::PolygonRef>::const_iterator cl = cc.begin (); cl != cc.end (); ++cl) {
if (cc.is_root (cl->id ())) {
db::Shapes &s = cm.merged (cl->id (), c->cell_index ());
c->shapes (m_merged_polygons.layer ()).swap (s);
}
}
}
ep.reserve (n);
// insert the polygons into the processor
n = 0;
for (RegionIterator p (begin ()); ! p.at_end (); ++p, ++n) {
ep.insert (*p, n);
}
// and run the merge step
db::MergeOp op (0);
db::ShapeGenerator pc (m_merged_polygons);
db::PolygonGenerator pg (pc, false /*don't resolve holes*/, min_coherence ());
ep.process (pg, op);
m_merged_polygons_valid = true;
@ -470,4 +580,424 @@ DeepRegion::add (const Region &other) const
}
}
static int is_box_from_iter (db::RecursiveShapeIterator i)
{
if (i.at_end ()) {
return -1;
}
if (i->is_box ()) {
++i;
if (i.at_end ()) {
return 1;
}
} else if (i->is_path () || i->is_polygon ()) {
db::Polygon poly;
i->polygon (poly);
if (poly.is_box ()) {
++i;
if (i.at_end ()) {
return 1;
}
}
} else {
return -1;
}
return 0; // undecided
}
bool
DeepRegion::is_box () const
{
int f = is_box_from_iter (begin_iter ().first);
if (f != 0) {
return f > 0;
}
// fallback: merge and then look again
return is_box_from_iter (begin_merged_iter ().first) > 0;
}
size_t
DeepRegion::size () const
{
size_t n = 0;
const db::Layout &layout = m_deep_layer.layout ();
db::CellCounter cc (&layout);
for (db::Layout::top_down_const_iterator c = layout.begin_top_down (); c != layout.end_top_down (); ++c) {
n += cc.weight (*c) * layout.cell (*c).shapes (m_deep_layer.layer ()).size ();
}
return n;
}
DeepRegion::area_type
DeepRegion::area (const db::Box &box) const
{
if (box.empty ()) {
ensure_merged_polygons_valid ();
// @@@ scaled instances!
DeepRegion::area_type a = 0;
const db::Layout &layout = m_merged_polygons.layout ();
db::CellCounter cc (&layout);
for (db::Layout::top_down_const_iterator c = layout.begin_top_down (); c != layout.end_top_down (); ++c) {
DeepRegion::area_type ac = 0;
for (db::ShapeIterator s = layout.cell (*c).shapes (m_merged_polygons.layer ()).begin (db::ShapeIterator::All); ! s.at_end (); ++s) {
ac += s->area ();
}
a += cc.weight (*c) * ac;
}
return a;
} else {
return db::AsIfFlatRegion::area (box);
}
}
DeepRegion::perimeter_type
DeepRegion::perimeter (const db::Box &box) const
{
if (box.empty ()) {
ensure_merged_polygons_valid ();
// @@@ scaled instances!
DeepRegion::perimeter_type p = 0;
const db::Layout &layout = m_merged_polygons.layout ();
db::CellCounter cc (&layout);
for (db::Layout::top_down_const_iterator c = layout.begin_top_down (); c != layout.end_top_down (); ++c) {
DeepRegion::perimeter_type pc = 0;
for (db::ShapeIterator s = layout.cell (*c).shapes (m_merged_polygons.layer ()).begin (db::ShapeIterator::All); ! s.at_end (); ++s) {
pc += s->perimeter ();
}
p += cc.weight (*c) * pc;
}
return p;
} else {
return db::AsIfFlatRegion::perimeter (box);
}
}
Box
DeepRegion::bbox () const
{
return m_deep_layer.initial_cell ().bbox (m_deep_layer.layer ());
}
std::string
DeepRegion::to_string (size_t nmax) const
{
return db::AsIfFlatRegion::to_string (nmax);
}
EdgePairs
DeepRegion::grid_check (db::Coord gx, db::Coord gy) const
{
// NOTE: snap be optimized by forming grid variants etc.
return db::AsIfFlatRegion::grid_check (gx, gy);
}
EdgePairs
DeepRegion::angle_check (double min, double max, bool inverse) const
{
// NOTE: snap be optimized by forming rotation variants etc.
return db::AsIfFlatRegion::angle_check (min, max, inverse);
}
RegionDelegate *
DeepRegion::snapped (db::Coord gx, db::Coord gy)
{
// NOTE: snap be optimized by forming grid variants etc.
return db::AsIfFlatRegion::snapped (gx, gy);
}
Edges
DeepRegion::edges (const EdgeFilterBase *filter) const
{
// NOTE: needs a deep edge set for optimizing for hierarchy.
// At least the length filter is easy to optimize in the hierarchical case.
return db::AsIfFlatRegion::edges (filter);
}
RegionDelegate *
DeepRegion::filtered (const PolygonFilterBase &filter) const
{
if (filter.isotropic ()) {
ensure_merged_polygons_valid ();
// @@@ scaled instances!
db::Layout &layout = m_merged_polygons.layout ();
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.new_layer ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const db::Shapes &s = c->shapes (m_merged_polygons.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
db::Polygon poly;
si->polygon (poly);
if (filter.selected (poly)) {
st.insert (poly);
}
}
}
return res.release ();
} else {
return db::AsIfFlatRegion::filtered (filter);
}
}
RegionDelegate *
DeepRegion::merged_in_place ()
{
ensure_merged_polygons_valid ();
// NOTE: this makes both layers share the same resource
m_deep_layer = m_merged_polygons;
return this;
}
RegionDelegate *
DeepRegion::merged_in_place (bool min_coherence, unsigned int min_wc)
{
// TODO: can probably be optimized
return db::AsIfFlatRegion::merged_in_place (min_coherence, min_wc);
}
RegionDelegate *
DeepRegion::merged () const
{
ensure_merged_polygons_valid ();
db::Layout &layout = const_cast<db::Layout &> (m_merged_polygons.layout ());
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.new_layer ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
c->shapes (res->deep_layer ().layer ()) = c->shapes (m_merged_polygons.layer ());
}
res->deep_layer ().layer ();
return res.release ();
}
RegionDelegate *
DeepRegion::merged (bool min_coherence, unsigned int min_wc) const
{
// TODO: can probably be optimized
return db::AsIfFlatRegion::merged (min_coherence, min_wc);
}
RegionDelegate *
DeepRegion::strange_polygon_check () const
{
// TODO: can probably be optimized
return db::AsIfFlatRegion::strange_polygon_check ();
}
RegionDelegate *
DeepRegion::sized (coord_type d, unsigned int mode) const
{
ensure_merged_polygons_valid ();
db::Layout &layout = m_merged_polygons.layout ();
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.new_layer ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const db::Shapes &s = c->shapes (m_merged_polygons.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
db::ShapeGenerator pc (st, false /*no clear - already empty*/);
db::PolygonGenerator pg2 (pc, false /*don't resolve holes*/, true /*min. coherence*/);
db::SizingPolygonFilter siz (pg2, d, d, mode);
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
db::Polygon poly;
si->polygon (poly);
siz.put (poly);
}
}
return res.release ();
}
RegionDelegate *
DeepRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const
{
if (dx == dy) {
return sized (dx, mode);
} else {
return db::AsIfFlatRegion::sized (dx, dy, mode);
}
}
RegionDelegate *
DeepRegion::holes () const
{
ensure_merged_polygons_valid ();
db::Layout &layout = m_merged_polygons.layout ();
std::vector<db::Point> pts;
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.new_layer ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const db::Shapes &s = c->shapes (m_merged_polygons.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
for (size_t i = 0; i < si->holes (); ++i) {
db::Polygon h;
pts.clear ();
for (db::Shape::point_iterator p = si->begin_hole ((unsigned int) i); p != si->end_hole ((unsigned int) i); ++p) {
pts.push_back (*p);
}
h.assign_hull (pts.begin (), pts.end ());
st.insert (h);
}
}
}
return res.release ();
}
RegionDelegate *
DeepRegion::hulls () const
{
ensure_merged_polygons_valid ();
db::Layout &layout = m_merged_polygons.layout ();
std::vector<db::Point> pts;
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.new_layer ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const db::Shapes &s = c->shapes (m_merged_polygons.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
db::Polygon h;
pts.clear ();
for (db::Shape::point_iterator p = si->begin_hull (); p != si->end_hull (); ++p) {
pts.push_back (*p);
}
h.assign_hull (pts.begin (), pts.end ());
st.insert (h);
}
}
return res.release ();
}
RegionDelegate *
DeepRegion::in (const Region &other, bool invert) const
{
// TODO: this can be optimized maybe ...
return db::AsIfFlatRegion::in (other, invert);
}
RegionDelegate *
DeepRegion::rounded_corners (double rinner, double router, unsigned int n) const
{
ensure_merged_polygons_valid ();
// @@@ scaled instances
db::Layout &layout = m_merged_polygons.layout ();
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.new_layer ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const db::Shapes &s = c->shapes (m_merged_polygons.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
db::Polygon poly;
si->polygon (poly);
st.insert (db::compute_rounded (poly, rinner, router, n));
}
}
return res.release ();
}
RegionDelegate *
DeepRegion::smoothed (coord_type d) const
{
ensure_merged_polygons_valid ();
// @@@ scaled instances
db::Layout &layout = m_merged_polygons.layout ();
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.new_layer ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const db::Shapes &s = c->shapes (m_merged_polygons.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
db::Polygon poly;
si->polygon (poly);
st.insert (db::smooth (poly, d));
}
}
return res.release ();
}
EdgePairs
DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const
{
// TODO: implement hierarchically
return db::AsIfFlatRegion::run_check (rel, different_polygons, other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection);
}
EdgePairs
DeepRegion::run_single_polygon_check (db::edge_relation_type rel, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const
{
// TODO: implement hierarchically
return db::AsIfFlatRegion::run_single_polygon_check (rel, d, whole_edges, metrics, ignore_angle, min_projection, max_projection);
}
RegionDelegate *
DeepRegion::selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse) const
{
// TODO: implement hierarchically
return db::AsIfFlatRegion::selected_interacting_generic (other, mode, touching, inverse);
}
RegionDelegate *
DeepRegion::selected_interacting_generic (const Edges &other, bool inverse) const
{
// TODO: implement hierarchically
return db::AsIfFlatRegion::selected_interacting_generic (other, inverse);
}
}

View File

@ -78,6 +78,141 @@ public:
virtual RegionDelegate *add_in_place (const Region &other);
virtual RegionDelegate *add (const Region &other) const;
virtual bool is_box () const;
virtual size_t size () const;
virtual area_type area (const db::Box &box) const;
virtual perimeter_type perimeter (const db::Box &box) const;
virtual Box bbox () const;
virtual std::string to_string (size_t nmax) const;
EdgePairs width_check (db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const
{
return run_single_polygon_check (db::WidthRelation, d, whole_edges, metrics, ignore_angle, min_projection, max_projection);
}
EdgePairs space_check (db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const
{
return run_check (db::SpaceRelation, false, 0, d, whole_edges, metrics, ignore_angle, min_projection, max_projection);
}
EdgePairs isolated_check (db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const
{
return run_check (db::SpaceRelation, true, 0, d, whole_edges, metrics, ignore_angle, min_projection, max_projection);
}
EdgePairs notch_check (db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const
{
return run_single_polygon_check (db::SpaceRelation, d, whole_edges, metrics, ignore_angle, min_projection, max_projection);
}
EdgePairs enclosing_check (const Region &other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const
{
return run_check (db::OverlapRelation, true, &other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection);
}
EdgePairs overlap_check (const Region &other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const
{
return run_check (db::WidthRelation, true, &other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection);
}
EdgePairs separation_check (const Region &other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const
{
return run_check (db::SpaceRelation, true, &other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection);
}
EdgePairs inside_check (const Region &other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const
{
return run_check (db::InsideRelation, true, &other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection);
}
virtual EdgePairs grid_check (db::Coord gx, db::Coord gy) const;
virtual EdgePairs angle_check (double min, double max, bool inverse) const;
virtual RegionDelegate *snapped_in_place (db::Coord gx, db::Coord gy)
{
return snapped (gx, gy);
}
virtual RegionDelegate *snapped (db::Coord gx, db::Coord gy);
virtual Edges edges (const EdgeFilterBase *) const;
virtual RegionDelegate *filter_in_place (const PolygonFilterBase &filter)
{
return filtered (filter);
}
virtual RegionDelegate *filtered (const PolygonFilterBase &filter) const;
virtual RegionDelegate *merged_in_place ();
virtual RegionDelegate *merged_in_place (bool min_coherence, unsigned int min_wc);
virtual RegionDelegate *merged () const;
virtual RegionDelegate *merged (bool min_coherence, unsigned int min_wc) const;
virtual RegionDelegate *strange_polygon_check () const;
virtual RegionDelegate *sized (coord_type d, unsigned int mode) const;
virtual RegionDelegate *sized (coord_type dx, coord_type dy, unsigned int mode) const;
virtual RegionDelegate *selected_outside (const Region &other) const
{
return selected_interacting_generic (other, 1, false, false);
}
virtual RegionDelegate *selected_not_outside (const Region &other) const
{
return selected_interacting_generic (other, 1, false, true);
}
virtual RegionDelegate *selected_inside (const Region &other) const
{
return selected_interacting_generic (other, -1, true, false);
}
virtual RegionDelegate *selected_not_inside (const Region &other) const
{
return selected_interacting_generic (other, -1, true, true);
}
virtual RegionDelegate *selected_interacting (const Region &other) const
{
return selected_interacting_generic (other, 0, true, false);
}
virtual RegionDelegate *selected_not_interacting (const Region &other) const
{
return selected_interacting_generic (other, 0, true, true);
}
virtual RegionDelegate *selected_interacting (const Edges &other) const
{
return selected_interacting_generic (other, false);
}
virtual RegionDelegate *selected_not_interacting (const Edges &other) const
{
return selected_interacting_generic (other, true);
}
virtual RegionDelegate *selected_overlapping (const Region &other) const
{
return selected_interacting_generic (other, 0, false, false);
}
virtual RegionDelegate *selected_not_overlapping (const Region &other) const
{
return selected_interacting_generic (other, 0, false, true);
}
virtual RegionDelegate *holes () const;
virtual RegionDelegate *hulls () const;
virtual RegionDelegate *in (const Region &other, bool invert) const;
virtual RegionDelegate *rounded_corners (double rinner, double router, unsigned int n) const;
virtual RegionDelegate *smoothed (coord_type d) const;
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
const DeepLayer &deep_layer () const
@ -97,14 +232,17 @@ private:
DeepRegion &operator= (const DeepRegion &other);
DeepLayer m_deep_layer;
// TODO: have hierarchical merged polygons later
mutable db::Shapes m_merged_polygons;
mutable DeepLayer m_merged_polygons;
mutable bool m_merged_polygons_valid;
void init ();
void ensure_merged_polygons_valid () const;
DeepLayer and_or_not_with(const DeepRegion *other, bool and_op) const;
void add_from (const DeepLayer &dl);
EdgePairs run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const;
EdgePairs run_single_polygon_check (db::edge_relation_type rel, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const;
RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse) const;
RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse) const;
};
}

View File

@ -141,6 +141,13 @@ bool DeepLayer::operator== (const DeepLayer &other) const
return true;
}
DeepLayer
DeepLayer::new_layer() const
{
db::DeepShapeStore *store = const_cast<db::DeepShapeStore *> (mp_store.get ());
return DeepLayer (store, m_layout, store->layout (m_layout).insert_layer ());
}
db::Layout &
DeepLayer::layout ()
{

View File

@ -61,6 +61,12 @@ public:
*/
~DeepLayer ();
/**
* @brief The constructor from the detailed information
* Use this constructor if you know what you're doing.
*/
DeepLayer (DeepShapeStore *store, unsigned int layout, unsigned int layer);
/**
* @brief Conversion operator from Region to DeepLayer
* This requires the Region to be a DeepRegion. Otherwise, this constructor will assert
@ -87,6 +93,11 @@ public:
*/
bool operator== (const DeepLayer &other) const;
/**
* @brief Creates a new empty layer based on this one
*/
DeepLayer new_layer () const;
/**
* @brief Gets the layout object
* The return value is guaranteed to be non-null.
@ -156,11 +167,6 @@ public:
private:
friend class DeepShapeStore;
/**
* @brief The constructor
*/
DeepLayer (DeepShapeStore *store, unsigned int layout, unsigned int layer);
void check_dss () const;
tl::weak_ptr<DeepShapeStore> mp_store;

View File

@ -50,6 +50,7 @@ public:
virtual ~PolygonFilterBase () { }
virtual bool selected (const db::Polygon &polgon) const = 0;
virtual bool isotropic () const = 0;
};
/**
@ -96,6 +97,14 @@ struct DB_PUBLIC RegionPerimeterFilter
}
}
/**
* @brief This filter is isotropic
*/
virtual bool isotropic () const
{
return true;
}
private:
perimeter_type m_pmin, m_pmax;
bool m_inverse;
@ -141,6 +150,14 @@ struct DB_PUBLIC RegionAreaFilter
}
}
/**
* @brief This filter is isotropic
*/
virtual bool isotropic () const
{
return true;
}
private:
area_type m_amin, m_amax;
bool m_inverse;
@ -173,6 +190,14 @@ struct DB_PUBLIC RectilinearFilter
return poly.is_rectilinear () != m_inverse;
}
/**
* @brief This filter is isotropic
*/
virtual bool isotropic () const
{
return true;
}
private:
bool m_inverse;
};
@ -204,6 +229,14 @@ struct DB_PUBLIC RectangleFilter
return poly.is_box () != m_inverse;
}
/**
* @brief This filter is isotropic
*/
virtual bool isotropic () const
{
return true;
}
private:
bool m_inverse;
};
@ -278,6 +311,14 @@ struct DB_PUBLIC RegionBBoxFilter
}
}
/**
* @brief This filter is isotropic unless the parameter is width or height
*/
virtual bool isotropic () const
{
return m_parameter != BoxWidth && m_parameter != BoxHeight;
}
private:
value_type m_vmin, m_vmax;
bool m_inverse;