diff --git a/src/db/db/dbAsIfFlatRegion.h b/src/db/db/dbAsIfFlatRegion.h index 9353d5d80..c8d5cf92e 100644 --- a/src/db/db/dbAsIfFlatRegion.h +++ b/src/db/db/dbAsIfFlatRegion.h @@ -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; }; } diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index 8488a06c8..7cb790e09 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -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 ().begin (), m_merged_polygons.get_layer ().end ()); + return new DeepRegionIterator (begin_merged_iter ().first); } } @@ -187,10 +191,26 @@ std::pair 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 &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::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 &cc = mp_hc->clusters_per_cell (ci); + const db::local_cluster &c = cc.cluster_by_id (cid); + + std::list > merged_child_clusters; + + const db::connected_clusters::connections_type &conn = cc.connections_for_cluster (cid); + for (db::connected_clusters::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 >::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::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 m_merged_cluster; + std::set m_done; + unsigned int m_layer; + const db::hier_clusters *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 (m_deep_layer.layout ()); + + db::hier_clusters 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 &cc = hc.clusters_per_cell (c->cell_index ()); + for (db::connected_clusters::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 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 (m_merged_polygons.layout ()); + + std::auto_ptr 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 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 pts; + + std::auto_ptr 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 pts; + + std::auto_ptr 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 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 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); +} + } diff --git a/src/db/db/dbDeepRegion.h b/src/db/db/dbDeepRegion.h index 720782399..df214e093 100644 --- a/src/db/db/dbDeepRegion.h +++ b/src/db/db/dbDeepRegion.h @@ -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; }; } diff --git a/src/db/db/dbDeepShapeStore.cc b/src/db/db/dbDeepShapeStore.cc index d05ab60f8..b6b1af6bd 100644 --- a/src/db/db/dbDeepShapeStore.cc +++ b/src/db/db/dbDeepShapeStore.cc @@ -141,6 +141,13 @@ bool DeepLayer::operator== (const DeepLayer &other) const return true; } +DeepLayer +DeepLayer::new_layer() const +{ + db::DeepShapeStore *store = const_cast (mp_store.get ()); + return DeepLayer (store, m_layout, store->layout (m_layout).insert_layer ()); +} + db::Layout & DeepLayer::layout () { diff --git a/src/db/db/dbDeepShapeStore.h b/src/db/db/dbDeepShapeStore.h index f8dac096b..e1d67a337 100644 --- a/src/db/db/dbDeepShapeStore.h +++ b/src/db/db/dbDeepShapeStore.h @@ -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 mp_store; diff --git a/src/db/db/dbRegion.h b/src/db/db/dbRegion.h index 225bb7d72..77da2d894 100644 --- a/src/db/db/dbRegion.h +++ b/src/db/db/dbRegion.h @@ -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;