diff --git a/scripts/create_drc_samples.rb b/scripts/create_drc_samples.rb
index 962c026ac..b8ea6665a 100644
--- a/scripts/create_drc_samples.rb
+++ b/scripts/create_drc_samples.rb
@@ -2,9 +2,45 @@
# Run with:
# ./klayout -z -r ./create_drc_samples.rb -t -c klayoutrc_drc_samples
+class QRCGenerator
+
+ def res_path
+ "src/lay/lay"
+ end
+
+ def img_path
+ "doc/images"
+ end
+
+ def initialize
+ @path = res_path + "/" + "layDRCLVSHelpResources.qrc"
+ @file = File.open(@path, "w")
+ @file.puts("")
+ @file.puts(" ")
+ end
+
+ def <<(str)
+ @file.puts(str)
+ end
+
+ def finish
+ @file.puts(" ")
+ @file.puts("")
+ @file.close
+ puts "---> resource file written to #{@path}"
+ end
+
+ def self.instance
+ @@inst ||= QRCGenerator::new
+ @@inst
+ end
+
+end
+
def run_demo(gen, cmd, out)
- img_path = "src/lay/lay/doc/images"
+ res_path = QRCGenerator::instance.res_path
+ img_path = QRCGenerator::instance.img_path
mw = RBA::Application::instance::main_window
@@ -81,7 +117,9 @@ def run_demo(gen, cmd, out)
input1 = input(1, 0)
input = input1
input2 = input(2, 0)
- #{cmd}.data
+ labels1 = labels(1, 0)
+ labels = labels1
+ (#{cmd}).data
SCRIPT
if data.is_a?(RBA::Region)
@@ -101,15 +139,19 @@ SCRIPT
elsif data.is_a?(RBA::EdgePairs)
cell.shapes(lout_poly).insert_as_polygons(data, 1)
cell.shapes(lout).insert(data.edges)
+ elsif data.is_a?(RBA::Texts)
+ cell.shapes(lout).insert(data)
end
view.update_content
- view.save_image(img_path + "/" + out, 400, 400)
+ view.save_image(res_path + "/" + img_path + "/" + out, 400, 400)
- puts "---> written #{img_path}/#{out}"
+ puts "---> written #{res_path}/#{img_path}/#{out}"
mw.close_all
+ QRCGenerator::instance << " #{img_path}/#{out}"
+
end
class Gen
@@ -631,3 +673,41 @@ run_demo gen, "input.corners.sized(0.1)", "drc_corners1.png"
run_demo gen, "input.corners(90.0).sized(0.1)", "drc_corners2.png"
run_demo gen, "input.corners(-90.0 .. -45.0).sized(0.1)", "drc_corners3.png"
+
+class Gen
+ def produce(s1, s2)
+ s1.insert(RBA::Text::new("ABC", RBA::Trans::new(RBA::Vector::new(0, 2000))))
+ s1.insert(RBA::Text::new("A", RBA::Trans::new(RBA::Vector::new(0, 6000))))
+ s1.insert(RBA::Text::new("XYZ", RBA::Trans::new(RBA::Vector::new(4000, 2000))))
+ s1.insert(RBA::Text::new("A*", RBA::Trans::new(RBA::Vector::new(4000, 6000))))
+ end
+end
+
+gen = Gen::new
+
+run_demo gen, "labels.texts(\"A*\")", "drc_texts1.png"
+run_demo gen, "labels.texts(text(\"A*\"))", "drc_texts2.png"
+
+class Gen
+ def produce(s1, s2)
+ s1.insert(RBA::Text::new("T1", RBA::Trans::new(RBA::Vector::new(0, 2000))))
+ s1.insert(RBA::Text::new("T2", RBA::Trans::new(RBA::Vector::new(2000, 2000))))
+ s1.insert(RBA::Text::new("T3", RBA::Trans::new(RBA::Vector::new(4000, 2000))))
+ pts = [
+ RBA::Point::new(2000, 0),
+ RBA::Point::new(2000, 4000),
+ RBA::Point::new(6000, 4000),
+ RBA::Point::new(6000, 0)
+ ];
+ s2.insert(RBA::Polygon::new(pts))
+ end
+end
+
+gen = Gen::new
+
+run_demo gen, "labels & input2", "drc_textpoly1.png"
+run_demo gen, "labels - input2", "drc_textpoly2.png"
+
+
+QRCGenerator::instance.finish
+
diff --git a/src/db/db/db.pro b/src/db/db/db.pro
index ea36ff395..6ee1e93fd 100644
--- a/src/db/db/db.pro
+++ b/src/db/db/db.pro
@@ -184,7 +184,19 @@ SOURCES = \
dbLayoutVsSchematic.cc \
gsiDeclDbNetlistCrossReference.cc \
gsiDeclDbLayoutVsSchematic.cc \
- dbNetlistObject.cc
+ dbNetlistObject.cc \
+ gsiDeclDbTexts.cc \
+ dbTexts.cc \
+ dbDeepTexts.cc \
+ dbAsIfFlatTexts.cc \
+ dbTextsDelegate.cc \
+ dbEmptyTexts.cc \
+ dbFlatTexts.cc \
+ dbTextsUtils.cc \
+ dbOriginalLayerTexts.cc \
+ dbNetShape.cc \
+ dbShapeCollection.cc \
+ gsiDeclDbShapeCollection.cc
HEADERS = \
dbArray.h \
@@ -331,7 +343,17 @@ HEADERS = \
dbLayoutVsSchematicReader.h \
dbLayoutVsSchematicFormatDefs.h \
dbLayoutVsSchematic.h \
- dbNetlistObject.h
+ dbNetlistObject.h \
+ dbTexts.h \
+ dbDeepTexts.h \
+ dbAsIfFlatTexts.h \
+ dbTextsDelegate.h \
+ dbEmptyTexts.h \
+ dbFlatTexts.h \
+ dbTextsUtils.h \
+ dbOriginalLayerTexts.h \
+ dbNetShape.h \
+ dbShapeCollection.h
!equals(HAVE_QT, "0") {
diff --git a/src/db/db/dbAsIfFlatEdgePairs.cc b/src/db/db/dbAsIfFlatEdgePairs.cc
index bac1a9495..4ed4ee3e9 100644
--- a/src/db/db/dbAsIfFlatEdgePairs.cc
+++ b/src/db/db/dbAsIfFlatEdgePairs.cc
@@ -75,7 +75,7 @@ AsIfFlatEdgePairs::in (const EdgePairs &other, bool invert) const
op.insert (*o);
}
- std::auto_ptr new_edge_pairs (new FlatEdgePairs (false));
+ std::auto_ptr new_edge_pairs (new FlatEdgePairs ());
for (EdgePairsIterator o (begin ()); ! o.at_end (); ++o) {
if ((op.find (*o) == op.end ()) == invert) {
diff --git a/src/db/db/dbAsIfFlatEdges.cc b/src/db/db/dbAsIfFlatEdges.cc
index 26bfe7689..588eaf462 100644
--- a/src/db/db/dbAsIfFlatEdges.cc
+++ b/src/db/db/dbAsIfFlatEdges.cc
@@ -59,6 +59,16 @@ AsIfFlatEdges::~AsIfFlatEdges ()
// .. nothing yet ..
}
+AsIfFlatEdges &
+AsIfFlatEdges::operator= (const AsIfFlatEdges &other)
+{
+ if (this != &other) {
+ m_bbox_valid = other.m_bbox_valid;
+ m_bbox = other.m_bbox;
+ }
+ return *this;
+}
+
std::string
AsIfFlatEdges::to_string (size_t nmax) const
{
@@ -170,7 +180,7 @@ AsIfFlatEdges::pull_generic (const Edges &edges) const
{
db::box_scanner scanner (report_progress (), progress_desc ());
- AddressableEdgeDelivery e (begin (), true);
+ AddressableEdgeDelivery e (begin (), has_valid_edges ());
for ( ; ! e.at_end (); ++e) {
scanner.insert (e.operator-> (), 1);
@@ -497,7 +507,7 @@ AsIfFlatEdges::run_check (db::edge_relation_type rel, const Edges *other, db::Co
db::box_scanner scanner (report_progress (), progress_desc ());
scanner.reserve (size () + (other ? other->size () : 0));
- AddressableEdgeDelivery e (begin_merged (), has_valid_edges ());
+ AddressableEdgeDelivery e (begin_merged (), has_valid_merged_edges ());
size_t n = 0;
for ( ; ! e.at_end (); ++e) {
diff --git a/src/db/db/dbAsIfFlatEdges.h b/src/db/db/dbAsIfFlatEdges.h
index 7a94c35c5..55c79ade0 100644
--- a/src/db/db/dbAsIfFlatEdges.h
+++ b/src/db/db/dbAsIfFlatEdges.h
@@ -185,10 +185,9 @@ protected:
virtual RegionDelegate *pull_generic (const Region ®ion) const;
virtual EdgesDelegate *selected_interacting_generic (const Edges &edges, bool inverse) const;
virtual EdgesDelegate *selected_interacting_generic (const Region ®ion, bool inverse) const;
-
-private:
AsIfFlatEdges &operator= (const AsIfFlatEdges &other);
+private:
mutable bool m_bbox_valid;
mutable db::Box m_bbox;
diff --git a/src/db/db/dbAsIfFlatRegion.cc b/src/db/db/dbAsIfFlatRegion.cc
index 0a9278df1..047137407 100644
--- a/src/db/db/dbAsIfFlatRegion.cc
+++ b/src/db/db/dbAsIfFlatRegion.cc
@@ -25,6 +25,7 @@
#include "dbFlatRegion.h"
#include "dbFlatEdgePairs.h"
#include "dbFlatEdges.h"
+#include "dbFlatTexts.h"
#include "dbEmptyRegion.h"
#include "dbEmptyEdgePairs.h"
#include "dbEmptyEdges.h"
@@ -55,6 +56,17 @@ AsIfFlatRegion::~AsIfFlatRegion ()
// .. nothing yet ..
}
+AsIfFlatRegion &
+AsIfFlatRegion::operator= (const AsIfFlatRegion &other)
+{
+ if (this != &other) {
+ m_bbox_valid = other.m_bbox_valid;
+ m_bbox = other.m_bbox;
+ }
+
+ return *this;
+}
+
std::string
AsIfFlatRegion::to_string (size_t nmax) const
{
@@ -364,6 +376,50 @@ AsIfFlatRegion::selected_interacting_generic (const Edges &other, bool inverse)
return output.release ();
}
+RegionDelegate *
+AsIfFlatRegion::selected_interacting_generic (const Texts &other, bool inverse) const
+{
+ if (other.empty ()) {
+ if (! inverse) {
+ return new EmptyRegion ();
+ } else {
+ return clone ();
+ }
+ } else if (empty ()) {
+ return clone ();
+ }
+
+ db::box_scanner2 scanner (report_progress (), progress_desc ());
+ scanner.reserve1 (size ());
+ scanner.reserve2 (other.size ());
+
+ std::auto_ptr output (new FlatRegion (true));
+ region_to_text_interaction_filter filter (*output, inverse);
+
+ AddressablePolygonDelivery p (begin_merged (), has_valid_merged_polygons ());
+
+ for ( ; ! p.at_end (); ++p) {
+ scanner.insert1 (p.operator-> (), 0);
+ if (inverse) {
+ filter.preset (p.operator-> ());
+ }
+ }
+
+ AddressableTextDelivery e (other.addressable_texts ());
+
+ for ( ; ! e.at_end (); ++e) {
+ scanner.insert2 (e.operator-> (), 0);
+ }
+
+ scanner.process (filter, 1, db::box_convert (), db::box_convert ());
+
+ if (inverse) {
+ filter.fill_output ();
+ }
+
+ return output.release ();
+}
+
RegionDelegate *
AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse) const
{
@@ -440,7 +496,7 @@ AsIfFlatRegion::pull_generic (const Edges &other) const
std::auto_ptr output (new FlatEdges (false));
region_to_edge_interaction_filter filter (output->raw_edges (), false);
- AddressablePolygonDelivery p (begin (), has_valid_merged_polygons ());
+ AddressablePolygonDelivery p (begin (), has_valid_polygons ());
for ( ; ! p.at_end (); ++p) {
scanner.insert1 (p.operator-> (), 0);
@@ -457,6 +513,39 @@ AsIfFlatRegion::pull_generic (const Edges &other) const
return output.release ();
}
+TextsDelegate *
+AsIfFlatRegion::pull_generic (const Texts &other) const
+{
+ if (other.empty ()) {
+ return other.delegate ()->clone ();
+ } else if (empty ()) {
+ return new EmptyTexts ();
+ }
+
+ db::box_scanner2 scanner (report_progress (), progress_desc ());
+ scanner.reserve1 (size ());
+ scanner.reserve2 (other.size ());
+
+ std::auto_ptr output (new FlatTexts (false));
+ region_to_text_interaction_filter filter (output->raw_texts (), false);
+
+ AddressablePolygonDelivery p (begin (), has_valid_polygons ());
+
+ for ( ; ! p.at_end (); ++p) {
+ scanner.insert1 (p.operator-> (), 0);
+ }
+
+ AddressableTextDelivery e (other.addressable_texts ());
+
+ for ( ; ! e.at_end (); ++e) {
+ scanner.insert2 (e.operator-> (), 0);
+ }
+
+ scanner.process (filter, 1, db::box_convert (), db::box_convert ());
+
+ return output.release ();
+}
+
RegionDelegate *
AsIfFlatRegion::pull_generic (const Region &other, int mode, bool touching) const
{
diff --git a/src/db/db/dbAsIfFlatRegion.h b/src/db/db/dbAsIfFlatRegion.h
index ed232d858..631026f4d 100644
--- a/src/db/db/dbAsIfFlatRegion.h
+++ b/src/db/db/dbAsIfFlatRegion.h
@@ -202,6 +202,16 @@ public:
return selected_interacting_generic (other, true);
}
+ virtual RegionDelegate *selected_interacting (const Texts &other) const
+ {
+ return selected_interacting_generic (other, false);
+ }
+
+ virtual RegionDelegate *selected_not_interacting (const Texts &other) const
+ {
+ return selected_interacting_generic (other, true);
+ }
+
virtual RegionDelegate *selected_overlapping (const Region &other) const
{
return selected_interacting_generic (other, 0, false, false);
@@ -227,6 +237,11 @@ public:
return pull_generic (other);
}
+ virtual TextsDelegate *pull_interacting (const Texts &other) const
+ {
+ return pull_generic (other);
+ }
+
virtual RegionDelegate *pull_overlapping (const Region &other) const
{
return pull_generic (other, 0, false);
@@ -247,17 +262,20 @@ protected:
EdgePairsDelegate *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;
virtual RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse) const;
virtual RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse) const;
+ virtual RegionDelegate *selected_interacting_generic (const Texts &other, bool inverse) const;
virtual RegionDelegate *pull_generic (const Region &other, int mode, bool touching) const;
virtual EdgesDelegate *pull_generic (const Edges &other) const;
+ virtual TextsDelegate *pull_generic (const Texts &other) const;
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);
-private:
AsIfFlatRegion &operator= (const AsIfFlatRegion &other);
+private:
+
mutable bool m_bbox_valid;
mutable db::Box m_bbox;
diff --git a/src/db/db/dbAsIfFlatTexts.cc b/src/db/db/dbAsIfFlatTexts.cc
new file mode 100644
index 000000000..fe9c86da3
--- /dev/null
+++ b/src/db/db/dbAsIfFlatTexts.cc
@@ -0,0 +1,384 @@
+
+/*
+
+ KLayout Layout Viewer
+ Copyright (C) 2006-2020 Matthias Koefferlein
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+
+#include "dbAsIfFlatTexts.h"
+#include "dbFlatTexts.h"
+#include "dbFlatRegion.h"
+#include "dbFlatEdges.h"
+#include "dbEmptyTexts.h"
+#include "dbEmptyRegion.h"
+#include "dbTexts.h"
+#include "dbBoxConvert.h"
+#include "dbRegion.h"
+#include "dbTextsUtils.h"
+
+#include
+
+namespace db
+{
+
+// -------------------------------------------------------------------------------------------------------------
+// AsIfFlagTexts implementation
+
+AsIfFlatTexts::AsIfFlatTexts ()
+ : TextsDelegate (), m_bbox_valid (false)
+{
+ // .. nothing yet ..
+}
+
+AsIfFlatTexts::~AsIfFlatTexts ()
+{
+ // .. nothing yet ..
+}
+
+AsIfFlatTexts &
+AsIfFlatTexts::operator= (const AsIfFlatTexts &other)
+{
+ if (this != &other) {
+ m_bbox_valid = other.m_bbox_valid;
+ m_bbox = other.m_bbox;
+ }
+ return *this;
+}
+
+std::string
+AsIfFlatTexts::to_string (size_t nmax) const
+{
+ std::ostringstream os;
+ TextsIterator p (begin ());
+ bool first = true;
+ for ( ; ! p.at_end () && nmax != 0; ++p, --nmax) {
+ if (! first) {
+ os << ";";
+ }
+ first = false;
+ os << p->to_string ();
+ }
+ if (! p.at_end ()) {
+ os << "...";
+ }
+ return os.str ();
+}
+
+TextsDelegate *
+AsIfFlatTexts::in (const Texts &other, bool invert) const
+{
+ std::set op;
+ for (TextsIterator o (other.begin ()); ! o.at_end (); ++o) {
+ op.insert (*o);
+ }
+
+ std::auto_ptr new_texts (new FlatTexts ());
+
+ for (TextsIterator o (begin ()); ! o.at_end (); ++o) {
+ if ((op.find (*o) == op.end ()) == invert) {
+ new_texts->insert (*o);
+ }
+ }
+
+ return new_texts.release ();
+}
+
+size_t
+AsIfFlatTexts::size () const
+{
+ size_t n = 0;
+ for (TextsIterator t (begin ()); ! t.at_end (); ++t) {
+ ++n;
+ }
+ return n;
+}
+
+Box AsIfFlatTexts::bbox () const
+{
+ if (! m_bbox_valid) {
+ m_bbox = compute_bbox ();
+ m_bbox_valid = true;
+ }
+ return m_bbox;
+}
+
+Box AsIfFlatTexts::compute_bbox () const
+{
+ db::Box b;
+ for (TextsIterator t (begin ()); ! t.at_end (); ++t) {
+ b += t->box ();
+ }
+ return b;
+}
+
+void AsIfFlatTexts::update_bbox (const db::Box &b)
+{
+ m_bbox = b;
+ m_bbox_valid = true;
+}
+
+void AsIfFlatTexts::invalidate_bbox ()
+{
+ m_bbox_valid = false;
+}
+
+TextsDelegate *
+AsIfFlatTexts::filtered (const TextFilterBase &filter) const
+{
+ std::auto_ptr new_texts (new FlatTexts ());
+
+ for (TextsIterator p (begin ()); ! p.at_end (); ++p) {
+ if (filter.selected (*p)) {
+ new_texts->insert (*p);
+ }
+ }
+
+ return new_texts.release ();
+}
+
+RegionDelegate *
+AsIfFlatTexts::polygons (db::Coord e) const
+{
+ std::auto_ptr output (new FlatRegion ());
+
+ for (TextsIterator tp (begin ()); ! tp.at_end (); ++tp) {
+ db::Box box = tp->box ();
+ box.enlarge (db::Vector (e, e));
+ output->insert (db::Polygon (box));
+ }
+
+ return output.release ();
+}
+
+EdgesDelegate *
+AsIfFlatTexts::edges () const
+{
+ std::auto_ptr output (new FlatEdges ());
+
+ for (TextsIterator tp (begin ()); ! tp.at_end (); ++tp) {
+ db::Box box = tp->box ();
+ output->insert (db::Edge (box.p1 (), box.p2 ()));
+ }
+
+ return output.release ();
+}
+
+TextsDelegate *
+AsIfFlatTexts::add (const Texts &other) const
+{
+ FlatTexts *other_flat = dynamic_cast (other.delegate ());
+ if (other_flat) {
+
+ std::auto_ptr new_texts (new FlatTexts (*other_flat));
+ new_texts->invalidate_cache ();
+
+ size_t n = new_texts->raw_texts ().size () + size ();
+
+ new_texts->reserve (n);
+
+ for (TextsIterator p (begin ()); ! p.at_end (); ++p) {
+ new_texts->raw_texts ().insert (*p);
+ }
+
+ return new_texts.release ();
+
+ } else {
+
+ std::auto_ptr new_texts (new FlatTexts ());
+
+ size_t n = size () + other.size ();
+
+ new_texts->reserve (n);
+
+ for (TextsIterator p (begin ()); ! p.at_end (); ++p) {
+ new_texts->raw_texts ().insert (*p);
+ }
+ for (TextsIterator p (other.begin ()); ! p.at_end (); ++p) {
+ new_texts->raw_texts ().insert (*p);
+ }
+
+ return new_texts.release ();
+
+ }
+}
+
+bool
+AsIfFlatTexts::equals (const Texts &other) const
+{
+ if (empty () != other.empty ()) {
+ return false;
+ }
+ if (size () != other.size ()) {
+ return false;
+ }
+ TextsIterator o1 (begin ());
+ TextsIterator o2 (other.begin ());
+ while (! o1.at_end () && ! o2.at_end ()) {
+ if (*o1 != *o2) {
+ return false;
+ }
+ ++o1;
+ ++o2;
+ }
+ return true;
+}
+
+bool
+AsIfFlatTexts::less (const Texts &other) const
+{
+ if (empty () != other.empty ()) {
+ return empty () < other.empty ();
+ }
+ if (size () != other.size ()) {
+ return (size () < other.size ());
+ }
+ TextsIterator o1 (begin ());
+ TextsIterator o2 (other.begin ());
+ while (! o1.at_end () && ! o2.at_end ()) {
+ if (*o1 != *o2) {
+ return *o1 < *o2;
+ }
+ ++o1;
+ ++o2;
+ }
+ return false;
+}
+
+void
+AsIfFlatTexts::insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
+{
+ // improves performance when inserting an original layout into the same layout
+ db::LayoutLocker locker (layout);
+
+ db::Shapes &shapes = layout->cell (into_cell).shapes (into_layer);
+ for (TextsIterator t (begin ()); ! t.at_end (); ++t) {
+ shapes.insert (*t);
+ }
+}
+
+void
+AsIfFlatTexts::insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const
+{
+ // improves performance when inserting an original layout into the same layout
+ db::LayoutLocker locker (layout);
+
+ db::Shapes &shapes = layout->cell (into_cell).shapes (into_layer);
+ for (TextsIterator t (begin ()); ! t.at_end (); ++t) {
+ db::Box box = t->box ();
+ box.enlarge (db::Vector (enl, enl));
+ shapes.insert (db::SimplePolygon (box));
+ }
+}
+
+TextsDelegate *
+AsIfFlatTexts::selected_interacting_generic (const Region &other, bool inverse) const
+{
+ // shortcuts
+ if (other.empty () || empty ()) {
+ return new EmptyTexts ();
+ }
+
+ db::box_scanner2 scanner (report_progress (), progress_desc ());
+
+ AddressableTextDelivery e (begin (), has_valid_texts ());
+
+ for ( ; ! e.at_end (); ++e) {
+ scanner.insert1 (e.operator-> (), 0);
+ }
+
+ AddressablePolygonDelivery p = other.addressable_polygons ();
+
+ for ( ; ! p.at_end (); ++p) {
+ scanner.insert2 (p.operator-> (), 1);
+ }
+
+ std::auto_ptr output (new FlatTexts ());
+
+ if (! inverse) {
+
+ text_to_region_interaction_filter filter (*output);
+ scanner.process (filter, 1, db::box_convert (), db::box_convert ());
+
+ } else {
+
+ std::set interacting;
+ text_to_region_interaction_filter, db::Text> filter (interacting);
+ scanner.process (filter, 1, db::box_convert (), db::box_convert ());
+
+ for (TextsIterator o (begin ()); ! o.at_end (); ++o) {
+ if (interacting.find (*o) == interacting.end ()) {
+ output->insert (*o);
+ }
+ }
+
+ }
+
+ return output.release ();
+}
+
+RegionDelegate *
+AsIfFlatTexts::pull_generic (const Region &other) const
+{
+ // shortcuts
+ if (other.empty () || empty ()) {
+ return new EmptyRegion ();
+ }
+
+ db::box_scanner2 scanner (report_progress (), progress_desc ());
+
+ AddressableTextDelivery e (begin (), has_valid_texts ());
+
+ for ( ; ! e.at_end (); ++e) {
+ scanner.insert1 (e.operator-> (), 0);
+ }
+
+ AddressablePolygonDelivery p = other.addressable_merged_polygons ();
+
+ for ( ; ! p.at_end (); ++p) {
+ scanner.insert2 (p.operator-> (), 1);
+ }
+
+ std::auto_ptr output (new FlatRegion (true));
+
+ text_to_region_interaction_filter filter (*output);
+ scanner.process (filter, 1, db::box_convert (), db::box_convert ());
+
+ return output.release ();
+}
+
+RegionDelegate *
+AsIfFlatTexts::pull_interacting (const Region &other) const
+{
+ return pull_generic (other);
+}
+
+TextsDelegate *
+AsIfFlatTexts::selected_interacting (const Region &other) const
+{
+ return selected_interacting_generic (other, false);
+}
+
+TextsDelegate *
+AsIfFlatTexts::selected_not_interacting (const Region &other) const
+{
+ return selected_interacting_generic (other, true);
+}
+
+}
+
diff --git a/src/db/db/dbAsIfFlatTexts.h b/src/db/db/dbAsIfFlatTexts.h
new file mode 100644
index 000000000..b0f4611fe
--- /dev/null
+++ b/src/db/db/dbAsIfFlatTexts.h
@@ -0,0 +1,96 @@
+
+/*
+
+ KLayout Layout Viewer
+ Copyright (C) 2006-2020 Matthias Koefferlein
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+
+#ifndef HDR_dbAsIfFlatTexts
+#define HDR_dbAsIfFlatTexts
+
+#include "dbCommon.h"
+
+#include "dbTextsDelegate.h"
+
+namespace db {
+
+class Region;
+
+/**
+ * @brief Provides default flat implementations
+ */
+class DB_PUBLIC AsIfFlatTexts
+ : public TextsDelegate
+{
+public:
+ AsIfFlatTexts ();
+ virtual ~AsIfFlatTexts ();
+
+ virtual size_t size () const;
+ virtual std::string to_string (size_t) const;
+ virtual Box bbox () const;
+
+ virtual TextsDelegate *filter_in_place (const TextFilterBase &filter)
+ {
+ return filtered (filter);
+ }
+
+ virtual TextsDelegate *filtered (const TextFilterBase &) const;
+
+ virtual TextsDelegate *add_in_place (const Texts &other)
+ {
+ return add (other);
+ }
+
+ virtual TextsDelegate *add (const Texts &other) const;
+
+ virtual RegionDelegate *polygons (db::Coord e) const;
+ virtual EdgesDelegate *edges () const;
+
+ virtual TextsDelegate *in (const Texts &, bool) const;
+
+ virtual bool equals (const Texts &other) const;
+ virtual bool less (const Texts &other) const;
+
+ virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
+ virtual void insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const;
+
+ virtual RegionDelegate *pull_interacting (const Region &) const;
+ virtual TextsDelegate *selected_interacting (const Region &other) const;
+ virtual TextsDelegate *selected_not_interacting (const Region &other) const;
+
+protected:
+ void update_bbox (const db::Box &box);
+ void invalidate_bbox ();
+ AsIfFlatTexts &operator= (const AsIfFlatTexts &other);
+
+private:
+
+ mutable bool m_bbox_valid;
+ mutable db::Box m_bbox;
+
+ virtual db::Box compute_bbox () const;
+ virtual TextsDelegate *selected_interacting_generic (const Region &other, bool inverse) const;
+ virtual RegionDelegate *pull_generic (const Region &other) const;
+};
+
+}
+
+#endif
+
diff --git a/src/db/db/dbDeepEdgePairs.cc b/src/db/db/dbDeepEdgePairs.cc
index f0138a17c..95d105d91 100644
--- a/src/db/db/dbDeepEdgePairs.cc
+++ b/src/db/db/dbDeepEdgePairs.cc
@@ -86,34 +86,33 @@ private:
DeepEdgePairs::DeepEdgePairs ()
- : AsIfFlatEdgePairs (), m_deep_layer ()
+ : AsIfFlatEdgePairs ()
{
// .. nothing yet ..
}
DeepEdgePairs::DeepEdgePairs (const RecursiveShapeIterator &si, DeepShapeStore &dss)
- : AsIfFlatEdgePairs (), m_deep_layer (dss.create_edge_pair_layer (si))
+ : AsIfFlatEdgePairs ()
{
- // .. nothing yet ..
+ set_deep_layer (dss.create_edge_pair_layer (si));
}
DeepEdgePairs::DeepEdgePairs (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans)
- : AsIfFlatEdgePairs (), m_deep_layer (dss.create_edge_pair_layer (si, trans))
+ : AsIfFlatEdgePairs ()
{
- // .. nothing yet ..
+ set_deep_layer (dss.create_edge_pair_layer (si, trans));
}
DeepEdgePairs::DeepEdgePairs (const DeepEdgePairs &other)
- : AsIfFlatEdgePairs (other),
- m_deep_layer (other.m_deep_layer.copy ())
+ : AsIfFlatEdgePairs (other), db::DeepShapeCollectionDelegateBase (other)
{
// .. nothing yet ..
}
DeepEdgePairs::DeepEdgePairs (const DeepLayer &dl)
- : AsIfFlatEdgePairs (), m_deep_layer (dl)
+ : AsIfFlatEdgePairs ()
{
- // .. nothing yet ..
+ set_deep_layer (dl);
}
DeepEdgePairs::~DeepEdgePairs ()
@@ -133,7 +132,7 @@ EdgePairsIteratorDelegate *DeepEdgePairs::begin () const
std::pair DeepEdgePairs::begin_iter () const
{
- const db::Layout &layout = m_deep_layer.layout ();
+ const db::Layout &layout = deep_layer ().layout ();
if (layout.cells () == 0) {
return std::make_pair (db::RecursiveShapeIterator (), db::ICplxTrans ());
@@ -141,7 +140,7 @@ std::pair DeepEdgePairs::begin_iter
} else {
const db::Cell &top_cell = layout.cell (*layout.begin_top_down ());
- db::RecursiveShapeIterator iter (m_deep_layer.layout (), top_cell, m_deep_layer.layer ());
+ db::RecursiveShapeIterator iter (deep_layer ().layout (), top_cell, deep_layer ().layer ());
return std::make_pair (iter, db::ICplxTrans ());
}
@@ -151,10 +150,10 @@ size_t DeepEdgePairs::size () const
{
size_t n = 0;
- const db::Layout &layout = m_deep_layer.layout ();
+ const db::Layout &layout = 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 ();
+ n += cc.weight (*c) * layout.cell (*c).shapes (deep_layer ().layer ()).size ();
}
return n;
@@ -167,7 +166,7 @@ std::string DeepEdgePairs::to_string (size_t nmax) const
Box DeepEdgePairs::bbox () const
{
- return m_deep_layer.initial_cell ().bbox (m_deep_layer.layer ());
+ return deep_layer ().initial_cell ().bbox (deep_layer ().layer ());
}
bool DeepEdgePairs::empty () const
@@ -243,12 +242,12 @@ EdgePairsDelegate *DeepEdgePairs::filtered (const EdgePairFilterBase &filter) co
RegionDelegate *DeepEdgePairs::polygons (db::Coord e) const
{
- db::DeepLayer new_layer = m_deep_layer.derived ();
- db::Layout &layout = const_cast (m_deep_layer.layout ());
+ db::DeepLayer new_layer = deep_layer ().derived ();
+ db::Layout &layout = const_cast (deep_layer ().layout ());
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
db::Shapes &output = c->shapes (new_layer.layer ());
- for (db::Shapes::shape_iterator s = c->shapes (m_deep_layer.layer ()).begin (db::ShapeIterator::EdgePairs); ! s.at_end (); ++s) {
+ for (db::Shapes::shape_iterator s = c->shapes (deep_layer ().layer ()).begin (db::ShapeIterator::EdgePairs); ! s.at_end (); ++s) {
db::Polygon poly = s->edge_pair ().normalized ().to_polygon (e);
if (poly.vertices () >= 3) {
output.insert (db::PolygonRef (poly, layout.shape_repository ()));
@@ -261,12 +260,12 @@ RegionDelegate *DeepEdgePairs::polygons (db::Coord e) const
EdgesDelegate *DeepEdgePairs::generic_edges (bool first, bool second) const
{
- db::DeepLayer new_layer = m_deep_layer.derived ();
- db::Layout &layout = const_cast (m_deep_layer.layout ());
+ db::DeepLayer new_layer = deep_layer ().derived ();
+ db::Layout &layout = const_cast (deep_layer ().layout ());
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
db::Shapes &output = c->shapes (new_layer.layer ());
- for (db::Shapes::shape_iterator s = c->shapes (m_deep_layer.layer ()).begin (db::ShapeIterator::EdgePairs); ! s.at_end (); ++s) {
+ for (db::Shapes::shape_iterator s = c->shapes (deep_layer ().layer ()).begin (db::ShapeIterator::EdgePairs); ! s.at_end (); ++s) {
db::EdgePair ep = s->edge_pair ();
if (first) {
output.insert (ep.first ());
@@ -304,8 +303,8 @@ EdgePairsDelegate *DeepEdgePairs::in (const EdgePairs &other, bool invert) const
bool DeepEdgePairs::equals (const EdgePairs &other) const
{
const DeepEdgePairs *other_delegate = dynamic_cast (other.delegate ());
- if (other_delegate && &other_delegate->m_deep_layer.layout () == &m_deep_layer.layout ()
- && other_delegate->m_deep_layer.layer () == m_deep_layer.layer ()) {
+ if (other_delegate && &other_delegate->deep_layer ().layout () == &deep_layer ().layout ()
+ && other_delegate->deep_layer ().layer () == deep_layer ().layer ()) {
return true;
} else {
return AsIfFlatEdgePairs::equals (other);
@@ -315,8 +314,8 @@ bool DeepEdgePairs::equals (const EdgePairs &other) const
bool DeepEdgePairs::less (const EdgePairs &other) const
{
const DeepEdgePairs *other_delegate = dynamic_cast (other.delegate ());
- if (other_delegate && &other_delegate->m_deep_layer.layout () == &m_deep_layer.layout ()) {
- return other_delegate->m_deep_layer.layer () < m_deep_layer.layer ();
+ if (other_delegate && &other_delegate->deep_layer ().layout () == &deep_layer ().layout ()) {
+ return other_delegate->deep_layer ().layer () < deep_layer ().layer ();
} else {
return AsIfFlatEdgePairs::less (other);
}
@@ -324,13 +323,12 @@ bool DeepEdgePairs::less (const EdgePairs &other) const
void DeepEdgePairs::insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
{
- m_deep_layer.insert_into (layout, into_cell, into_layer);
+ deep_layer ().insert_into (layout, into_cell, into_layer);
}
void DeepEdgePairs::insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const
{
- m_deep_layer.insert_into_as_polygons (layout, into_cell, into_layer, enl);
+ deep_layer ().insert_into_as_polygons (layout, into_cell, into_layer, enl);
}
-
}
diff --git a/src/db/db/dbDeepEdgePairs.h b/src/db/db/dbDeepEdgePairs.h
index a6d0732f1..c75355a35 100644
--- a/src/db/db/dbDeepEdgePairs.h
+++ b/src/db/db/dbDeepEdgePairs.h
@@ -36,7 +36,7 @@ namespace db {
* @brief Provides hierarchical edges implementation
*/
class DB_PUBLIC DeepEdgePairs
- : public db::AsIfFlatEdgePairs
+ : public db::AsIfFlatEdgePairs, public db::DeepShapeCollectionDelegateBase
{
public:
DeepEdgePairs ();
@@ -80,21 +80,14 @@ public:
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
virtual void insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const;
- const DeepLayer &deep_layer () const
+ virtual DeepShapeCollectionDelegateBase *deep ()
{
- return m_deep_layer;
- }
-
- DeepLayer &deep_layer ()
- {
- return m_deep_layer;
+ return this;
}
private:
DeepEdgePairs &operator= (const DeepEdgePairs &other);
- DeepLayer m_deep_layer;
-
void init ();
EdgesDelegate *generic_edges (bool first, bool second) const;
};
diff --git a/src/db/db/dbDeepEdges.cc b/src/db/db/dbDeepEdges.cc
index 4b9eec059..d9c3fe21c 100644
--- a/src/db/db/dbDeepEdges.cc
+++ b/src/db/db/dbDeepEdges.cc
@@ -96,14 +96,16 @@ private:
// DeepEdges implementation
DeepEdges::DeepEdges (const RecursiveShapeIterator &si, DeepShapeStore &dss, bool as_edges)
- : AsIfFlatEdges (), m_deep_layer (dss.create_edge_layer (si, as_edges)), m_merged_edges ()
+ : AsIfFlatEdges (), m_merged_edges ()
{
+ set_deep_layer (dss.create_edge_layer (si, as_edges));
init ();
}
DeepEdges::DeepEdges (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans, bool as_edges, bool merged_semantics)
- : AsIfFlatEdges (), m_deep_layer (dss.create_edge_layer (si, as_edges, trans)), m_merged_edges ()
+ : AsIfFlatEdges (), m_merged_edges ()
{
+ set_deep_layer (dss.create_edge_layer (si, as_edges, trans));
init ();
set_merged_semantics (merged_semantics);
}
@@ -111,7 +113,7 @@ DeepEdges::DeepEdges (const RecursiveShapeIterator &si, DeepShapeStore &dss, con
DeepEdges::DeepEdges (const db::Edges &other, DeepShapeStore &dss)
: AsIfFlatEdges (), m_merged_edges ()
{
- m_deep_layer = dss.create_from_flat (other);
+ set_deep_layer (dss.create_from_flat (other));
init ();
set_merged_semantics (other.merged_semantics ());
@@ -124,8 +126,9 @@ DeepEdges::DeepEdges ()
}
DeepEdges::DeepEdges (const DeepLayer &dl)
- : AsIfFlatEdges (), m_deep_layer (dl)
+ : AsIfFlatEdges ()
{
+ set_deep_layer (dl);
init ();
}
@@ -135,8 +138,7 @@ DeepEdges::~DeepEdges ()
}
DeepEdges::DeepEdges (const DeepEdges &other)
- : AsIfFlatEdges (other),
- m_deep_layer (other.m_deep_layer.copy ()),
+ : AsIfFlatEdges (other), DeepShapeCollectionDelegateBase (other),
m_merged_edges_valid (other.m_merged_edges_valid),
m_is_merged (other.m_is_merged)
{
@@ -145,6 +147,25 @@ DeepEdges::DeepEdges (const DeepEdges &other)
}
}
+DeepEdges &
+DeepEdges::operator= (const DeepEdges &other)
+{
+ if (this != &other) {
+
+ AsIfFlatEdges::operator= (other);
+ DeepShapeCollectionDelegateBase::operator= (other);
+
+ m_merged_edges_valid = other.m_merged_edges_valid;
+ m_is_merged = other.m_is_merged;
+ if (m_merged_edges_valid) {
+ m_merged_edges = other.m_merged_edges;
+ }
+
+ }
+
+ return *this;
+}
+
void DeepEdges::init ()
{
m_merged_edges_valid = false;
@@ -182,7 +203,7 @@ DeepEdges::begin_merged () const
std::pair
DeepEdges::begin_iter () const
{
- const db::Layout &layout = m_deep_layer.layout ();
+ const db::Layout &layout = deep_layer ().layout ();
if (layout.cells () == 0) {
return std::make_pair (db::RecursiveShapeIterator (), db::ICplxTrans ());
@@ -190,7 +211,7 @@ DeepEdges::begin_iter () const
} else {
const db::Cell &top_cell = layout.cell (*layout.begin_top_down ());
- db::RecursiveShapeIterator iter (m_deep_layer.layout (), top_cell, m_deep_layer.layer ());
+ db::RecursiveShapeIterator iter (deep_layer ().layout (), top_cell, deep_layer ().layer ());
return std::make_pair (iter, db::ICplxTrans ());
}
@@ -262,8 +283,8 @@ DeepEdges::iter () const
bool DeepEdges::equals (const Edges &other) const
{
const DeepEdges *other_delegate = dynamic_cast (other.delegate ());
- if (other_delegate && &other_delegate->m_deep_layer.layout () == &m_deep_layer.layout ()
- && other_delegate->m_deep_layer.layer () == m_deep_layer.layer ()) {
+ if (other_delegate && &other_delegate->deep_layer ().layout () == &deep_layer ().layout ()
+ && other_delegate->deep_layer ().layer () == deep_layer ().layer ()) {
return true;
} else {
return AsIfFlatEdges::equals (other);
@@ -273,8 +294,8 @@ bool DeepEdges::equals (const Edges &other) const
bool DeepEdges::less (const Edges &other) const
{
const DeepEdges *other_delegate = dynamic_cast (other.delegate ());
- if (other_delegate && &other_delegate->m_deep_layer.layout () == &m_deep_layer.layout ()) {
- return other_delegate->m_deep_layer.layer () < m_deep_layer.layer ();
+ if (other_delegate && &other_delegate->deep_layer ().layout () == &deep_layer ().layout ()) {
+ return other_delegate->deep_layer ().layer () < deep_layer ().layer ();
} else {
return AsIfFlatEdges::less (other);
}
@@ -384,27 +405,27 @@ DeepEdges::ensure_merged_edges_valid () const
if (m_is_merged) {
// NOTE: this will reuse the deep layer reference
- m_merged_edges = m_deep_layer;
+ m_merged_edges = deep_layer ();
} else {
- m_merged_edges = m_deep_layer.derived ();
+ m_merged_edges = deep_layer ().derived ();
tl::SelfTimer timer (tl::verbosity () > base_verbosity (), "Ensure merged polygons");
- db::Layout &layout = const_cast (m_deep_layer.layout ());
+ db::Layout &layout = const_cast (deep_layer ().layout ());
db::hier_clusters hc;
db::Connectivity conn;
- conn.connect (m_deep_layer);
+ conn.connect (deep_layer ());
hc.set_base_verbosity (base_verbosity() + 10);
- hc.build (layout, m_deep_layer.initial_cell (), db::ShapeIterator::Edges, conn);
+ hc.build (layout, deep_layer ().initial_cell (), 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, report_progress (), progress_desc ());
+ ClusterMerger cm (deep_layer ().layer (), hc, report_progress (), progress_desc ());
cm.set_base_verbosity (base_verbosity () + 10);
// TODO: iterate only over the called cells?
@@ -436,17 +457,17 @@ DeepEdges::set_is_merged (bool f)
void
DeepEdges::insert_into (db::Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
{
- m_deep_layer.insert_into (layout, into_cell, into_layer);
+ deep_layer ().insert_into (layout, into_cell, into_layer);
}
size_t DeepEdges::size () const
{
size_t n = 0;
- const db::Layout &layout = m_deep_layer.layout ();
+ const db::Layout &layout = 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 ();
+ n += cc.weight (*c) * layout.cell (*c).shapes (deep_layer ().layer ()).size ();
}
return n;
@@ -454,7 +475,7 @@ size_t DeepEdges::size () const
Box DeepEdges::bbox () const
{
- return m_deep_layer.initial_cell ().bbox (m_deep_layer.layer ());
+ return deep_layer ().initial_cell ().bbox (deep_layer ().layer ());
}
DeepEdges::length_type DeepEdges::length (const db::Box &box) const
@@ -650,11 +671,18 @@ EdgesDelegate *
DeepEdges::filter_in_place (const EdgeFilterBase &filter)
{
// TODO: implement to be really in-place
- return filtered (filter);
+ *this = *apply_filter (filter);
+ return this;
}
EdgesDelegate *
DeepEdges::filtered (const EdgeFilterBase &filter) const
+{
+ return apply_filter (filter);
+}
+
+DeepEdges *
+DeepEdges::apply_filter (const EdgeFilterBase &filter) const
{
const db::DeepLayer &edges = filter.requires_raw_input () ? deep_layer () : merged_deep_layer ();
@@ -730,7 +758,7 @@ EdgesDelegate *DeepEdges::merged_in_place ()
ensure_merged_edges_valid ();
// NOTE: this makes both layers share the same resource
- m_deep_layer = m_merged_edges;
+ set_deep_layer (m_merged_edges);
return this;
}
@@ -753,17 +781,17 @@ EdgesDelegate *DeepEdges::merged () const
DeepLayer
DeepEdges::and_or_not_with (const DeepEdges *other, EdgeBoolOp op) const
{
- DeepLayer dl_out (m_deep_layer.derived ());
+ DeepLayer dl_out (deep_layer ().derived ());
db::EdgeBoolAndOrNotLocalOperation local_op (op);
- db::local_processor proc (const_cast (&m_deep_layer.layout ()), const_cast (&m_deep_layer.initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell ());
+ db::local_processor proc (const_cast (&deep_layer ().layout ()), const_cast (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell ());
proc.set_base_verbosity (base_verbosity ());
- proc.set_threads (m_deep_layer.store ()->threads ());
- proc.set_area_ratio (m_deep_layer.store ()->max_area_ratio ());
- proc.set_max_vertex_count (m_deep_layer.store ()->max_vertex_count ());
+ proc.set_threads (deep_layer ().store ()->threads ());
+ proc.set_area_ratio (deep_layer ().store ()->max_area_ratio ());
+ proc.set_max_vertex_count (deep_layer ().store ()->max_vertex_count ());
- proc.run (&local_op, m_deep_layer.layer (), other->deep_layer ().layer (), dl_out.layer ());
+ proc.run (&local_op, deep_layer ().layer (), other->deep_layer ().layer (), dl_out.layer ());
return dl_out;
}
@@ -771,17 +799,17 @@ DeepEdges::and_or_not_with (const DeepEdges *other, EdgeBoolOp op) const
DeepLayer
DeepEdges::edge_region_op (const DeepRegion *other, bool outside, bool include_borders) const
{
- DeepLayer dl_out (m_deep_layer.derived ());
+ DeepLayer dl_out (deep_layer ().derived ());
db::EdgeToPolygonLocalOperation op (outside, include_borders);
- db::local_processor proc (const_cast (&m_deep_layer.layout ()), const_cast (&m_deep_layer.initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell ());
+ db::local_processor proc (const_cast (&deep_layer ().layout ()), const_cast (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell ());
proc.set_base_verbosity (base_verbosity ());
- proc.set_threads (m_deep_layer.store ()->threads ());
- proc.set_area_ratio (m_deep_layer.store ()->max_area_ratio ());
- proc.set_max_vertex_count (m_deep_layer.store ()->max_vertex_count ());
+ proc.set_threads (deep_layer ().store ()->threads ());
+ proc.set_area_ratio (deep_layer ().store ()->max_area_ratio ());
+ proc.set_max_vertex_count (deep_layer ().store ()->max_vertex_count ());
- proc.run (&op, m_deep_layer.layer (), other->deep_layer ().layer (), dl_out.layer ());
+ proc.run (&op, deep_layer ().layer (), other->deep_layer ().layer (), dl_out.layer ());
return dl_out;
}
@@ -1051,7 +1079,7 @@ RegionDelegate *DeepEdges::extended (coord_type ext_b, coord_type ext_e, coord_t
db::Connectivity conn (db::Connectivity::EdgesConnectByPoints);
conn.connect (edges);
hc.set_base_verbosity (base_verbosity () + 10);
- hc.build (layout, edges.initial_cell (), db::ShapeIterator::Edges, conn);
+ hc.build (layout, edges.initial_cell (), conn);
// TODO: iterate only over the called cells?
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
@@ -1278,7 +1306,7 @@ public:
}
}
- for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
+ for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
const db::Edge &subject = interactions.subject_shape (i->first);
scanner.insert1 (&subject, 0);
}
@@ -1295,7 +1323,7 @@ public:
edge_to_region_interaction_filter > filter (interacting);
scanner.process (filter, 1, db::box_convert (), db::box_convert ());
- for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
+ for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
const db::Edge &subject = interactions.subject_shape (i->first);
if (interacting.find (subject) == interacting.end ()) {
result.insert (subject);
@@ -1374,7 +1402,7 @@ public:
}
}
- for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
+ for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
const db::Edge &subject = interactions.subject_shape (i->first);
scanner.insert1 (&subject, 1);
}
diff --git a/src/db/db/dbDeepEdges.h b/src/db/db/dbDeepEdges.h
index 662ac5cd1..8ed87c971 100644
--- a/src/db/db/dbDeepEdges.h
+++ b/src/db/db/dbDeepEdges.h
@@ -40,7 +40,7 @@ class DeepRegion;
* @brief Provides hierarchical edges implementation
*/
class DB_PUBLIC DeepEdges
- : public db::AsIfFlatEdges
+ : public db::AsIfFlatEdges, public db::DeepShapeCollectionDelegateBase
{
public:
DeepEdges ();
@@ -144,14 +144,9 @@ public:
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
- const DeepLayer &deep_layer () const
+ virtual DeepShapeCollectionDelegateBase *deep ()
{
- return m_deep_layer;
- }
-
- DeepLayer &deep_layer ()
- {
- return m_deep_layer;
+ return this;
}
protected:
@@ -163,7 +158,6 @@ private:
DeepEdges &operator= (const DeepEdges &other);
- DeepLayer m_deep_layer;
mutable DeepLayer m_merged_edges;
mutable bool m_merged_edges_valid;
bool m_is_merged;
@@ -178,6 +172,8 @@ private:
virtual RegionDelegate *pull_generic (const Region ®ion) const;
virtual EdgesDelegate *selected_interacting_generic (const Edges &edges, bool invert) const;
virtual EdgesDelegate *selected_interacting_generic (const Region ®ion, bool invert) const;
+ DeepEdges *apply_filter (const EdgeFilterBase &filter) const;
+
template OutputContainer *processed_impl (const edge_processor &filter) const;
};
diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc
index 078924859..e0ba85dc5 100644
--- a/src/db/db/dbDeepRegion.cc
+++ b/src/db/db/dbDeepRegion.cc
@@ -28,6 +28,7 @@
#include "dbRegionUtils.h"
#include "dbDeepEdges.h"
#include "dbDeepEdgePairs.h"
+#include "dbDeepTexts.h"
#include "dbShapeProcessor.h"
#include "dbFlatRegion.h"
#include "dbHierProcessor.h"
@@ -101,14 +102,16 @@ 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 ()
+ : AsIfFlatRegion (), m_merged_polygons ()
{
+ set_deep_layer (dss.create_polygon_layer (si, area_ratio, max_vertex_count));
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, trans)), m_merged_polygons ()
+ : AsIfFlatRegion (), m_merged_polygons ()
{
+ set_deep_layer (dss.create_polygon_layer (si, area_ratio, max_vertex_count, trans));
init ();
set_merged_semantics (merged_semantics);
}
@@ -116,7 +119,7 @@ DeepRegion::DeepRegion (const RecursiveShapeIterator &si, DeepShapeStore &dss, c
DeepRegion::DeepRegion (const db::Region &other, DeepShapeStore &dss)
: AsIfFlatRegion (), m_merged_polygons ()
{
- m_deep_layer = dss.create_from_flat (other, false);
+ set_deep_layer (dss.create_from_flat (other, false));
init ();
set_merged_semantics (other.merged_semantics ());
@@ -129,8 +132,9 @@ DeepRegion::DeepRegion ()
}
DeepRegion::DeepRegion (const DeepLayer &dl)
- : AsIfFlatRegion (), m_deep_layer (dl)
+ : AsIfFlatRegion ()
{
+ set_deep_layer (dl);
init ();
}
@@ -140,8 +144,7 @@ DeepRegion::~DeepRegion ()
}
DeepRegion::DeepRegion (const DeepRegion &other)
- : AsIfFlatRegion (other),
- m_deep_layer (other.m_deep_layer.copy ()),
+ : AsIfFlatRegion (other), DeepShapeCollectionDelegateBase (other),
m_merged_polygons_valid (other.m_merged_polygons_valid),
m_is_merged (other.m_is_merged)
{
@@ -150,6 +153,25 @@ DeepRegion::DeepRegion (const DeepRegion &other)
}
}
+DeepRegion &
+DeepRegion::operator= (const DeepRegion &other)
+{
+ if (this != &other) {
+
+ AsIfFlatRegion::operator= (other);
+ DeepShapeCollectionDelegateBase::operator= (other);
+
+ m_merged_polygons_valid = other.m_merged_polygons_valid;
+ m_is_merged = other.m_is_merged;
+ if (m_merged_polygons_valid) {
+ m_merged_polygons = other.m_merged_polygons;
+ }
+
+ }
+
+ return *this;
+}
+
void DeepRegion::init ()
{
m_merged_polygons_valid = false;
@@ -192,7 +214,7 @@ DeepRegion::begin_merged () const
std::pair
DeepRegion::begin_iter () const
{
- const db::Layout &layout = m_deep_layer.layout ();
+ const db::Layout &layout = deep_layer ().layout ();
if (layout.cells () == 0) {
return std::make_pair (db::RecursiveShapeIterator (), db::ICplxTrans ());
@@ -200,7 +222,7 @@ DeepRegion::begin_iter () const
} else {
const db::Cell &top_cell = layout.cell (*layout.begin_top_down ());
- db::RecursiveShapeIterator iter (m_deep_layer.layout (), top_cell, m_deep_layer.layer ());
+ db::RecursiveShapeIterator iter (deep_layer ().layout (), top_cell, deep_layer ().layer ());
return std::make_pair (iter, db::ICplxTrans ());
}
@@ -273,8 +295,8 @@ bool
DeepRegion::equals (const Region &other) const
{
const DeepRegion *other_delegate = dynamic_cast (other.delegate ());
- if (other_delegate && &other_delegate->m_deep_layer.layout () == &m_deep_layer.layout ()
- && other_delegate->m_deep_layer.layer () == m_deep_layer.layer ()) {
+ if (other_delegate && &other_delegate->deep_layer ().layout () == &deep_layer ().layout ()
+ && other_delegate->deep_layer ().layer () == deep_layer ().layer ()) {
return true;
} else {
return AsIfFlatRegion::equals (other);
@@ -285,8 +307,8 @@ bool
DeepRegion::less (const Region &other) const
{
const DeepRegion *other_delegate = dynamic_cast (other.delegate ());
- if (other_delegate && &other_delegate->m_deep_layer.layout () == &m_deep_layer.layout ()) {
- return other_delegate->m_deep_layer.layer () < m_deep_layer.layer ();
+ if (other_delegate && &other_delegate->deep_layer ().layout () == &deep_layer ().layout ()) {
+ return other_delegate->deep_layer ().layer () < deep_layer ().layer ();
} else {
return AsIfFlatRegion::less (other);
}
@@ -421,27 +443,27 @@ DeepRegion::ensure_merged_polygons_valid () const
if (m_is_merged) {
// NOTE: this will reuse the deep layer reference
- m_merged_polygons = m_deep_layer;
+ m_merged_polygons = deep_layer ();
} else {
- m_merged_polygons = m_deep_layer.derived ();
+ m_merged_polygons = deep_layer ().derived ();
tl::SelfTimer timer (tl::verbosity () > base_verbosity (), "Ensure merged polygons");
- db::Layout &layout = const_cast (m_deep_layer.layout ());
+ db::Layout &layout = const_cast (deep_layer ().layout ());
db::hier_clusters hc;
db::Connectivity conn;
- conn.connect (m_deep_layer);
+ conn.connect (deep_layer ());
hc.set_base_verbosity (base_verbosity () + 10);
- hc.build (layout, m_deep_layer.initial_cell (), db::ShapeIterator::Polygons, conn);
+ hc.build (layout, deep_layer ().initial_cell (), 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 (), layout, hc, min_coherence (), report_progress (), progress_desc ());
+ ClusterMerger cm (deep_layer ().layer (), layout, hc, min_coherence (), report_progress (), progress_desc ());
cm.set_base_verbosity (base_verbosity () + 10);
// TODO: iterate only over the called cells?
@@ -473,7 +495,7 @@ DeepRegion::set_is_merged (bool f)
void
DeepRegion::insert_into (db::Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
{
- m_deep_layer.insert_into (layout, into_cell, into_layer);
+ deep_layer ().insert_into (layout, into_cell, into_layer);
}
RegionDelegate *
@@ -523,17 +545,17 @@ DeepRegion::not_with (const Region &other) const
DeepLayer
DeepRegion::and_or_not_with (const DeepRegion *other, bool and_op) const
{
- DeepLayer dl_out (m_deep_layer.derived ());
+ DeepLayer dl_out (deep_layer ().derived ());
db::BoolAndOrNotLocalOperation op (and_op);
- db::local_processor proc (const_cast (&m_deep_layer.layout ()), const_cast (&m_deep_layer.initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell (), m_deep_layer.breakout_cells (), other->deep_layer ().breakout_cells ());
+ db::local_processor proc (const_cast (&deep_layer ().layout ()), const_cast (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell (), deep_layer ().breakout_cells (), other->deep_layer ().breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
- proc.set_threads (m_deep_layer.store ()->threads ());
- proc.set_area_ratio (m_deep_layer.store ()->max_area_ratio ());
- proc.set_max_vertex_count (m_deep_layer.store ()->max_vertex_count ());
+ proc.set_threads (deep_layer ().store ()->threads ());
+ proc.set_area_ratio (deep_layer ().store ()->max_area_ratio ());
+ proc.set_max_vertex_count (deep_layer ().store ()->max_vertex_count ());
- proc.run (&op, m_deep_layer.layer (), other->deep_layer ().layer (), dl_out.layer ());
+ proc.run (&op, deep_layer ().layer (), other->deep_layer ().layer (), dl_out.layer ());
return dl_out;
}
@@ -648,10 +670,10 @@ DeepRegion::size () const
{
size_t n = 0;
- const db::Layout &layout = m_deep_layer.layout ();
+ const db::Layout &layout = 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 ();
+ n += cc.weight (*c) * layout.cell (*c).shapes (deep_layer ().layer ()).size ();
}
return n;
@@ -726,7 +748,7 @@ DeepRegion::perimeter (const db::Box &box) const
Box
DeepRegion::bbox () const
{
- return m_deep_layer.initial_cell ().bbox (m_deep_layer.layer ());
+ return deep_layer ().initial_cell ().bbox (deep_layer ().layer ());
}
std::string
@@ -1085,11 +1107,18 @@ RegionDelegate *
DeepRegion::filter_in_place (const PolygonFilterBase &filter)
{
// TODO: implement to be really in-place
- return filtered (filter);
+ *this = *apply_filter (filter);
+ return this;
}
RegionDelegate *
DeepRegion::filtered (const PolygonFilterBase &filter) const
+{
+ return apply_filter (filter);
+}
+
+DeepRegion *
+DeepRegion::apply_filter (const PolygonFilterBase &filter) const
{
const db::DeepLayer &polygons = filter.requires_raw_input () ? deep_layer () : merged_deep_layer ();
@@ -1170,7 +1199,7 @@ DeepRegion::merged_in_place ()
ensure_merged_polygons_valid ();
// NOTE: this makes both layers share the same resource
- m_deep_layer = m_merged_polygons;
+ set_deep_layer (m_merged_polygons);
set_is_merged (true);
return this;
@@ -1205,21 +1234,21 @@ DeepRegion::merged (bool min_coherence, unsigned int min_wc) const
{
tl::SelfTimer timer (tl::verbosity () > base_verbosity (), "Ensure merged polygons");
- db::Layout &layout = const_cast (m_deep_layer.layout ());
+ db::Layout &layout = const_cast (deep_layer ().layout ());
db::hier_clusters hc;
db::Connectivity conn;
- conn.connect (m_deep_layer);
+ conn.connect (deep_layer ());
hc.set_base_verbosity (base_verbosity () + 10);
- hc.build (layout, m_deep_layer.initial_cell (), db::ShapeIterator::Polygons, conn);
+ hc.build (layout, deep_layer ().initial_cell (), 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.
- DeepLayer dl_out (m_deep_layer.derived ());
+ DeepLayer dl_out (deep_layer ().derived ());
- ClusterMerger cm (m_deep_layer.layer (), layout, hc, min_coherence, report_progress (), progress_desc ());
+ ClusterMerger cm (deep_layer ().layer (), layout, hc, min_coherence, report_progress (), progress_desc ());
cm.set_base_verbosity (base_verbosity () + 10);
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
@@ -1502,7 +1531,7 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons
const_cast (&polygons.initial_cell ()),
other_deep ? &other_deep->deep_layer ().layout () : const_cast (&polygons.layout ()),
other_deep ? &other_deep->deep_layer ().initial_cell () : const_cast (&polygons.initial_cell ()),
- m_deep_layer.breakout_cells (),
+ deep_layer ().breakout_cells (),
other_deep ? other_deep->deep_layer ().breakout_cells () : 0);
proc.set_base_verbosity (base_verbosity ());
@@ -1870,6 +1899,143 @@ public:
}
};
+struct TextResultInserter
+{
+ typedef db::TextRef value_type;
+
+ TextResultInserter (std::unordered_set &result)
+ : mp_result (&result)
+ {
+ // .. nothing yet ..
+ }
+
+ void insert (const db::TextRef &e)
+ {
+ (*mp_result).insert (e);
+ }
+
+private:
+ std::unordered_set *mp_result;
+};
+
+class PullWithTextLocalOperation
+ : public local_operation
+{
+public:
+ PullWithTextLocalOperation ()
+ {
+ // .. nothing yet ..
+ }
+
+ virtual db::Coord dist () const
+ {
+ // touching is sufficient
+ return 1;
+ }
+
+ virtual void compute_local (db::Layout *, const shape_interactions &interactions, std::unordered_set &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const
+ {
+ db::box_scanner2 scanner;
+
+ TextResultInserter inserter (result);
+ region_to_text_interaction_filter filter (inserter, false);
+
+ for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
+ for (shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
+ scanner.insert2 (& interactions.intruder_shape (*j), 0);
+ }
+ }
+
+ std::list heap;
+ for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
+
+ const db::PolygonRef &subject = interactions.subject_shape (i->first);
+ heap.push_back (subject.obj ().transformed (subject.trans ()));
+
+ scanner.insert1 (&heap.back (), 0);
+
+ }
+
+ scanner.process (filter, 1, db::box_convert (), db::box_convert ());
+ }
+
+ virtual on_empty_intruder_mode on_empty_intruder_hint () const
+ {
+ return Drop;
+ }
+
+ virtual std::string description () const
+ {
+ return tl::to_string (tr ("Pull texts from second by their geometric relation to first"));
+ }
+};
+
+class InteractingWithTextLocalOperation
+ : public local_operation
+{
+public:
+ InteractingWithTextLocalOperation (bool inverse)
+ : m_inverse (inverse)
+ {
+ // .. nothing yet ..
+ }
+
+ virtual db::Coord dist () const
+ {
+ // touching is sufficient
+ return 1;
+ }
+
+ virtual void compute_local (db::Layout *layout, const shape_interactions &interactions, std::unordered_set &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const
+ {
+ db::box_scanner2 scanner;
+
+ ResultInserter inserter (layout, result);
+ region_to_text_interaction_filter filter (inserter, m_inverse);
+
+ for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
+ for (shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
+ scanner.insert2 (& interactions.intruder_shape (*j), 0);
+ }
+ }
+
+ std::list heap;
+ for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
+
+ const db::PolygonRef &subject = interactions.subject_shape (i->first);
+ heap.push_back (subject.obj ().transformed (subject.trans ()));
+
+ scanner.insert1 (&heap.back (), 0);
+ if (m_inverse) {
+ filter.preset (&heap.back ());
+ }
+
+ }
+
+ scanner.process (filter, 1, db::box_convert (), db::box_convert ());
+ if (m_inverse) {
+ filter.fill_output ();
+ }
+ }
+
+ virtual on_empty_intruder_mode on_empty_intruder_hint () const
+ {
+ if (!m_inverse) {
+ return Drop;
+ } else {
+ return Copy;
+ }
+ }
+
+ virtual std::string description () const
+ {
+ return tl::to_string (tr ("Select regions by their geometric relation to texts"));
+ }
+
+private:
+ bool m_inverse;
+};
+
}
RegionDelegate *
@@ -2016,4 +2182,70 @@ DeepRegion::pull_generic (const Edges &other) const
return res;
}
+TextsDelegate *
+DeepRegion::pull_generic (const Texts &other) const
+{
+ std::auto_ptr dr_holder;
+ const db::DeepTexts *other_deep = dynamic_cast (other.delegate ());
+ if (! other_deep) {
+ // if the other region isn't deep, turn into a top-level only deep region to facilitate re-hierarchisation
+ dr_holder.reset (new db::DeepTexts (other, const_cast (*deep_layer ().store ())));
+ other_deep = dr_holder.get ();
+ }
+
+ // in "inside" mode, the first argument needs to be merged too
+ const db::DeepLayer &polygons = deep_layer ();
+ const db::DeepLayer &other_texts = other_deep->deep_layer ();
+
+ DeepLayer dl_out (polygons.derived ());
+
+ db::PullWithTextLocalOperation op;
+
+ db::local_processor proc (const_cast (&polygons.layout ()), const_cast (&polygons.initial_cell ()), &other_texts.layout (), &other_texts.initial_cell (), polygons.breakout_cells (), other_texts.breakout_cells ());
+ proc.set_base_verbosity (base_verbosity ());
+ proc.set_threads (polygons.store ()->threads ());
+ proc.run (&op, polygons.layer (), other_texts.layer (), dl_out.layer ());
+
+ db::DeepTexts *res = new db::DeepTexts (dl_out);
+ res->set_is_merged (is_merged ());
+ return res;
+}
+
+RegionDelegate *
+DeepRegion::selected_interacting_generic (const Texts &other, bool inverse) const
+{
+ // with these flag set to true, the resulting polygons are broken again.
+ bool split_after = false;
+
+ std::auto_ptr dr_holder;
+ const db::DeepTexts *other_deep = dynamic_cast (other.delegate ());
+ if (! other_deep) {
+ // if the other region isn't deep, turn into a top-level only deep region to facilitate re-hierarchisation
+ dr_holder.reset (new db::DeepTexts (other, const_cast (*deep_layer ().store ())));
+ other_deep = dr_holder.get ();
+ }
+
+ const db::DeepLayer &polygons = merged_deep_layer ();
+
+ DeepLayer dl_out (polygons.derived ());
+
+ db::InteractingWithTextLocalOperation op (inverse);
+
+ db::local_processor proc (const_cast (&polygons.layout ()), const_cast (&polygons.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), polygons.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
+ proc.set_base_verbosity (base_verbosity ());
+ proc.set_threads (polygons.store ()->threads ());
+ if (split_after) {
+ proc.set_area_ratio (polygons.store ()->max_area_ratio ());
+ proc.set_max_vertex_count (polygons.store ()->max_vertex_count ());
+ }
+
+ proc.run (&op, polygons.layer (), other_deep->deep_layer ().layer (), dl_out.layer ());
+
+ db::DeepRegion *res = new db::DeepRegion (dl_out);
+ if (! split_after) {
+ res->set_is_merged (merged_semantics () || is_merged ());
+ }
+ return res;
+}
+
}
diff --git a/src/db/db/dbDeepRegion.h b/src/db/db/dbDeepRegion.h
index c1665d658..28dcdf0f8 100644
--- a/src/db/db/dbDeepRegion.h
+++ b/src/db/db/dbDeepRegion.h
@@ -35,7 +35,7 @@ namespace db {
* @brief A deep, polygon-set delegate
*/
class DB_PUBLIC DeepRegion
- : public AsIfFlatRegion
+ : public AsIfFlatRegion, public DeepShapeCollectionDelegateBase
{
public:
typedef db::layer polygon_layer_type;
@@ -159,14 +159,9 @@ public:
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
- const DeepLayer &deep_layer () const
+ virtual DeepShapeCollectionDelegateBase *deep ()
{
- return m_deep_layer;
- }
-
- DeepLayer &deep_layer ()
- {
- return m_deep_layer;
+ return this;
}
protected:
@@ -176,10 +171,10 @@ protected:
private:
friend class DeepEdges;
+ friend class DeepTexts;
DeepRegion &operator= (const DeepRegion &other);
- DeepLayer m_deep_layer;
mutable DeepLayer m_merged_polygons;
mutable bool m_merged_polygons_valid;
bool m_is_merged;
@@ -192,8 +187,11 @@ private:
EdgePairsDelegate *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;
virtual RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse) const;
virtual RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse) const;
+ virtual RegionDelegate *selected_interacting_generic (const Texts &other, bool inverse) const;
virtual RegionDelegate *pull_generic (const Region &other, int mode, bool touching) const;
virtual EdgesDelegate *pull_generic (const Edges &other) const;
+ virtual TextsDelegate *pull_generic (const Texts &other) const;
+ DeepRegion *apply_filter (const PolygonFilterBase &filter) const;
template OutputContainer *processed_impl (const polygon_processor &filter) const;
};
diff --git a/src/db/db/dbDeepShapeStore.cc b/src/db/db/dbDeepShapeStore.cc
index c1fcb9009..a2e11a840 100644
--- a/src/db/db/dbDeepShapeStore.cc
+++ b/src/db/db/dbDeepShapeStore.cc
@@ -25,7 +25,14 @@
#include "dbCellMapping.h"
#include "dbLayoutUtils.h"
#include "dbRegion.h"
+#include "dbEdges.h"
+#include "dbEdgePairs.h"
+#include "dbTexts.h"
#include "dbDeepRegion.h"
+#include "dbDeepEdges.h"
+#include "dbDeepEdgePairs.h"
+#include "dbDeepTexts.h"
+#include "dbShapeCollection.h"
#include "tlTimer.h"
@@ -48,6 +55,30 @@ DeepLayer::DeepLayer (const Region ®ion)
*this = dr->deep_layer ();
}
+DeepLayer::DeepLayer (const Texts &texts)
+ : mp_store (), m_layout (0), m_layer (0)
+{
+ const db::DeepTexts *dr = dynamic_cast (texts.delegate ());
+ tl_assert (dr != 0);
+ *this = dr->deep_layer ();
+}
+
+DeepLayer::DeepLayer (const Edges &edges)
+ : mp_store (), m_layout (0), m_layer (0)
+{
+ const db::DeepEdges *dr = dynamic_cast (edges.delegate ());
+ tl_assert (dr != 0);
+ *this = dr->deep_layer ();
+}
+
+DeepLayer::DeepLayer (const EdgePairs &edge_pairs)
+ : mp_store (), m_layout (0), m_layer (0)
+{
+ const db::DeepEdgePairs *dr = dynamic_cast (edge_pairs.delegate ());
+ tl_assert (dr != 0);
+ *this = dr->deep_layer ();
+}
+
DeepLayer::DeepLayer (const DeepLayer &x)
: mp_store (x.mp_store), m_layout (x.m_layout), m_layer (x.m_layer)
{
@@ -459,9 +490,39 @@ DeepLayer DeepShapeStore::create_from_flat (const db::Edges &edges, const db::IC
return dl;
}
-std::pair DeepShapeStore::layer_for_flat (const db::Region ®ion) const
+DeepLayer DeepShapeStore::create_from_flat (const db::Texts &texts, const db::ICplxTrans &trans)
{
- return layer_for_flat (tl::id_of (region.delegate ()));
+ // reuse existing layer
+ std::pair lff = layer_for_flat (tl::id_of (texts.delegate ()));
+ if (lff.first) {
+ return lff.second;
+ }
+
+ require_singular ();
+
+ unsigned int layer = layout ().insert_layer ();
+
+ db::Shapes *shapes = &initial_cell ().shapes (layer);
+ db::Box world = db::Box::world ();
+
+ db::TextBuildingHierarchyBuilderShapeReceiver tb (&layout ());
+
+ std::pair ii = texts.begin_iter ();
+ db::ICplxTrans ttop = trans * ii.second;
+ while (! ii.first.at_end ()) {
+ tb.push (*ii.first, ttop * ii.first.trans (), world, 0, shapes);
+ ++ii.first;
+ }
+
+ DeepLayer dl (this, 0 /*singular layout index*/, layer);
+ m_layers_for_flat [tl::id_of (texts.delegate ())] = std::make_pair (dl.layout_index (), dl.layer ());
+ m_flat_region_id [std::make_pair (dl.layout_index (), dl.layer ())] = tl::id_of (texts.delegate ());
+ return dl;
+}
+
+std::pair DeepShapeStore::layer_for_flat (const ShapeCollection &coll) const
+{
+ return layer_for_flat (tl::id_of (coll.get_delegate ()));
}
std::pair DeepShapeStore::layer_for_flat (size_t region_id) const
@@ -807,64 +868,23 @@ DeepLayer DeepShapeStore::create_copy (const DeepLayer &source, HierarchyBuilder
DeepLayer DeepShapeStore::create_edge_layer (const db::RecursiveShapeIterator &si, bool as_edges, const db::ICplxTrans &trans)
{
- unsigned int layout_index = layout_for_iter (si, trans);
-
- db::Layout &layout = m_layouts[layout_index]->layout;
- db::HierarchyBuilder &builder = m_layouts[layout_index]->builder;
-
- unsigned int layer_index = init_layer (layout, si);
- builder.set_target_layer (layer_index);
-
- // The chain of operators for producing edges
db::EdgeBuildingHierarchyBuilderShapeReceiver refs (as_edges);
-
- // Build the working hierarchy from the recursive shape iterator
- try {
-
- tl::SelfTimer timer (tl::verbosity () >= 41, tl::to_string (tr ("Building working hierarchy")));
- db::LayoutLocker ll (&layout, true /*no update*/);
-
- builder.set_shape_receiver (&refs);
- db::RecursiveShapeIterator (si).push (& builder);
- builder.set_shape_receiver (0);
-
- } catch (...) {
- builder.set_shape_receiver (0);
- throw;
- }
-
- return DeepLayer (this, layout_index, layer_index);
+ return create_custom_layer (si, &refs, trans);
}
DeepLayer DeepShapeStore::create_edge_pair_layer (const db::RecursiveShapeIterator &si, const db::ICplxTrans &trans)
{
- unsigned int layout_index = layout_for_iter (si, trans);
-
- db::Layout &layout = m_layouts[layout_index]->layout;
- db::HierarchyBuilder &builder = m_layouts[layout_index]->builder;
-
- unsigned int layer_index = init_layer (layout, si);
- builder.set_target_layer (layer_index);
-
- // The chain of operators for producing the edge pairs
db::EdgePairBuildingHierarchyBuilderShapeReceiver refs;
+ return create_custom_layer (si, &refs, trans);
+}
- // Build the working hierarchy from the recursive shape iterator
- try {
+DeepLayer DeepShapeStore::create_text_layer (const db::RecursiveShapeIterator &si, const db::ICplxTrans &trans)
+{
+ unsigned int layout_index = layout_for_iter (si, trans);
+ db::Layout &layout = m_layouts[layout_index]->layout;
- tl::SelfTimer timer (tl::verbosity () >= 41, tl::to_string (tr ("Building working hierarchy")));
- db::LayoutLocker ll (&layout, true /*no update*/);
-
- builder.set_shape_receiver (&refs);
- db::RecursiveShapeIterator (si).push (& builder);
- builder.set_shape_receiver (0);
-
- } catch (...) {
- builder.set_shape_receiver (0);
- throw;
- }
-
- return DeepLayer (this, layout_index, layer_index);
+ db::TextBuildingHierarchyBuilderShapeReceiver refs (&layout);
+ return create_custom_layer (si, &refs, trans);
}
void
@@ -1123,6 +1143,12 @@ DeepShapeStore::insert_as_polygons (const DeepLayer &deep_layer, db::Layout *int
s->polygon (poly);
out.insert (poly);
+ } else if (s->is_text ()) {
+
+ db::Text t;
+ s->text (t);
+ out.insert (db::SimplePolygon (t.box ().enlarged (db::Vector (enl, enl))));
+
}
}
diff --git a/src/db/db/dbDeepShapeStore.h b/src/db/db/dbDeepShapeStore.h
index 3290d5573..9e6d30dad 100644
--- a/src/db/db/dbDeepShapeStore.h
+++ b/src/db/db/dbDeepShapeStore.h
@@ -43,6 +43,9 @@ class DeepShapeStore;
class DeepShapeStoreState;
class Region;
class Edges;
+class EdgePairs;
+class Texts;
+class ShapeCollection;
/**
* @brief Represents a shape collection from the deep shape store
@@ -75,6 +78,24 @@ public:
*/
DeepLayer (const Region ®ion);
+ /**
+ * @brief Conversion operator from texts collection to DeepLayer
+ * This requires the texts to be a DeepTexts. Otherwise, this constructor will assert
+ */
+ DeepLayer (const Texts ®ion);
+
+ /**
+ * @brief Conversion operator from edges collection to DeepLayer
+ * This requires the edges to be a DeepEdges. Otherwise, this constructor will assert
+ */
+ DeepLayer (const Edges ®ion);
+
+ /**
+ * @brief Conversion operator from edge pairs collection to DeepLayer
+ * This requires the edge pairs to be a DeepEdgePairs. Otherwise, this constructor will assert
+ */
+ DeepLayer (const EdgePairs ®ion);
+
/**
* @brief Copy constructor
*/
@@ -338,15 +359,26 @@ public:
* After a flat layer has been created for a region, it can be retrieved
* from the region later with layer_for_flat (region).
*/
- DeepLayer create_from_flat (const db::Edges ®ion, const db::ICplxTrans &trans = db::ICplxTrans ());
+ DeepLayer create_from_flat (const db::Edges &edges, const db::ICplxTrans &trans = db::ICplxTrans ());
/**
- * @brief Gets the layer for a given flat region.
+ * @brief Creates a new layer from a flat text collection (or the text collection is made flat)
+ *
+ * This method is intended for use with singular-created DSS objects (see
+ * singular constructor).
+ *
+ * After a flat layer has been created for a region, it can be retrieved
+ * from the region later with layer_for_flat (region).
+ */
+ DeepLayer create_from_flat (const db::Texts &texts, const db::ICplxTrans &trans = db::ICplxTrans ());
+
+ /**
+ * @brief Gets the layer for a given flat collection (Region, Edges, Texts, EdgePairs)
*
* If a layer has been created for a flat region with create_from_flat, it can be retrieved with this method.
* The first return value is true in this case.
*/
- std::pair layer_for_flat (const db::Region ®ion) const;
+ std::pair layer_for_flat (const ShapeCollection &coll) const;
/**
* @brief Same as layer_for_flat, but takes a region Id
@@ -395,6 +427,15 @@ public:
*/
DeepLayer create_edge_pair_layer (const db::RecursiveShapeIterator &si, const ICplxTrans &trans = db::ICplxTrans ());
+ /**
+ * @brief Inserts an text layer into the deep shape store
+ *
+ * This method will create a new layer inside the deep shape store as a
+ * working copy of the original layer. This method creates a layer
+ * for texts.
+ */
+ DeepLayer create_text_layer (const db::RecursiveShapeIterator &si, const ICplxTrans &trans = db::ICplxTrans ());
+
/**
* @brief Inserts a polygon layer into the deep shape store using a custom preparation pipeline
*
diff --git a/src/db/db/dbDeepTexts.cc b/src/db/db/dbDeepTexts.cc
new file mode 100644
index 000000000..50f6e2623
--- /dev/null
+++ b/src/db/db/dbDeepTexts.cc
@@ -0,0 +1,613 @@
+
+/*
+
+ KLayout Layout Viewer
+ Copyright (C) 2006-2020 Matthias Koefferlein
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+
+#include "dbDeepTexts.h"
+#include "dbCellGraphUtils.h"
+#include "dbDeepEdges.h"
+#include "dbDeepRegion.h"
+#include "dbCellMapping.h"
+#include "dbLayoutUtils.h"
+#include "dbLocalOperation.h"
+#include "dbTextsUtils.h"
+#include "dbHierProcessor.h"
+#include "dbRegion.h"
+
+#include
+#include
+
+namespace db
+{
+
+/**
+ * @brief An iterator delegate for the deep text collection
+ * TODO: this is kind of redundant with OriginalLayerIterator ..
+ */
+class DB_PUBLIC DeepTextsIterator
+ : public TextsIteratorDelegate
+{
+public:
+ DeepTextsIterator (const db::RecursiveShapeIterator &iter)
+ : m_iter (iter)
+ {
+ set ();
+ }
+
+ virtual ~DeepTextsIterator () { }
+
+ virtual bool at_end () const
+ {
+ return m_iter.at_end ();
+ }
+
+ virtual void increment ()
+ {
+ ++m_iter;
+ set ();
+ }
+
+ virtual const value_type *get () const
+ {
+ return &m_text;
+ }
+
+ virtual TextsIteratorDelegate *clone () const
+ {
+ return new DeepTextsIterator (*this);
+ }
+
+private:
+ friend class Texts;
+
+ db::RecursiveShapeIterator m_iter;
+ mutable value_type m_text;
+
+ void set () const {
+ if (! m_iter.at_end ()) {
+ m_iter.shape ().text (m_text);
+ m_text.transform (m_iter.trans ());
+ }
+ }
+};
+
+
+DeepTexts::DeepTexts ()
+ : AsIfFlatTexts ()
+{
+ // .. nothing yet ..
+}
+
+DeepTexts::DeepTexts (const db::Texts &other, DeepShapeStore &dss)
+ : AsIfFlatTexts ()
+{
+ set_deep_layer (dss.create_from_flat (other));
+}
+
+DeepTexts::DeepTexts (const RecursiveShapeIterator &si, DeepShapeStore &dss)
+ : AsIfFlatTexts ()
+{
+ set_deep_layer (dss.create_text_layer (si));
+}
+
+DeepTexts::DeepTexts (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans)
+ : AsIfFlatTexts ()
+{
+ set_deep_layer (dss.create_text_layer (si, trans));
+}
+
+DeepTexts::DeepTexts (const DeepTexts &other)
+ : AsIfFlatTexts (other), DeepShapeCollectionDelegateBase (other)
+{
+ // .. nothing yet ..
+}
+
+DeepTexts &
+DeepTexts::operator= (const DeepTexts &other)
+{
+ if (this != &other) {
+ AsIfFlatTexts::operator= (other);
+ DeepShapeCollectionDelegateBase::operator= (other);
+ }
+ return *this;
+}
+
+DeepTexts::DeepTexts (const DeepLayer &dl)
+ : AsIfFlatTexts ()
+{
+ set_deep_layer (dl);
+}
+
+DeepTexts::~DeepTexts ()
+{
+ // .. nothing yet ..
+}
+
+TextsDelegate *DeepTexts::clone () const
+{
+ return new DeepTexts (*this);
+}
+
+TextsIteratorDelegate *DeepTexts::begin () const
+{
+ return new DeepTextsIterator (begin_iter ().first);
+}
+
+std::pair DeepTexts::begin_iter () const
+{
+ const db::Layout &layout = deep_layer ().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 (deep_layer ().layout (), top_cell, deep_layer ().layer ());
+ return std::make_pair (iter, db::ICplxTrans ());
+
+ }
+}
+
+size_t DeepTexts::size () const
+{
+ size_t n = 0;
+
+ const db::Layout &layout = 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 (deep_layer ().layer ()).size ();
+ }
+
+ return n;
+}
+
+std::string DeepTexts::to_string (size_t nmax) const
+{
+ return db::AsIfFlatTexts::to_string (nmax);
+}
+
+Box DeepTexts::bbox () const
+{
+ return deep_layer ().initial_cell ().bbox (deep_layer ().layer ());
+}
+
+bool DeepTexts::empty () const
+{
+ return begin_iter ().first.at_end ();
+}
+
+const db::Text *DeepTexts::nth (size_t) const
+{
+ throw tl::Exception (tl::to_string (tr ("Random access to texts is available only for flat text collections")));
+}
+
+bool DeepTexts::has_valid_texts () const
+{
+ return false;
+}
+
+const db::RecursiveShapeIterator *DeepTexts::iter () const
+{
+ return 0;
+}
+
+TextsDelegate *
+DeepTexts::add_in_place (const Texts &other)
+{
+ if (other.empty ()) {
+ return this;
+ }
+
+ const DeepTexts *other_deep = dynamic_cast (other.delegate ());
+ if (other_deep) {
+
+ deep_layer ().add_from (other_deep->deep_layer ());
+
+ } else {
+
+ // non-deep to deep merge (flat)
+
+ db::Shapes &shapes = deep_layer ().initial_cell ().shapes (deep_layer ().layer ());
+ for (db::Texts::const_iterator p = other.begin (); ! p.at_end (); ++p) {
+ shapes.insert (*p);
+ }
+
+ }
+
+ return this;
+}
+
+TextsDelegate *DeepTexts::add (const Texts &other) const
+{
+ if (other.empty ()) {
+ return clone ();
+ } else if (empty ()) {
+ return other.delegate ()->clone ();
+ } else {
+ DeepTexts *new_texts = dynamic_cast (clone ());
+ new_texts->add_in_place (other);
+ return new_texts;
+ }
+}
+
+TextsDelegate *DeepTexts::filter_in_place (const TextFilterBase &filter)
+{
+ // TODO: implement as really in place
+ *this = *apply_filter (filter);
+ return this;
+}
+
+TextsDelegate *DeepTexts::filtered (const TextFilterBase &filter) const
+{
+ return apply_filter (filter);
+}
+
+DeepTexts *DeepTexts::apply_filter (const TextFilterBase &filter) const
+{
+ const db::DeepLayer &texts = deep_layer ();
+
+ std::auto_ptr vars;
+ if (filter.vars ()) {
+
+ vars.reset (new db::VariantsCollectorBase (filter.vars ()));
+
+ vars->collect (texts.layout (), texts.initial_cell ());
+
+ if (filter.wants_variants ()) {
+ const_cast (texts).separate_variants (*vars);
+ }
+
+ }
+
+ db::Layout &layout = const_cast (texts.layout ());
+ std::map > to_commit;
+
+ std::auto_ptr res (new db::DeepTexts (texts.derived ()));
+ for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
+
+ const db::Shapes &s = c->shapes (texts.layer ());
+
+ if (vars.get ()) {
+
+ const std::map &vv = vars->variants (c->cell_index ());
+ for (std::map::const_iterator v = vv.begin (); v != vv.end (); ++v) {
+
+ db::Shapes *st;
+ if (vv.size () == 1) {
+ st = & c->shapes (res->deep_layer ().layer ());
+ } else {
+ st = & to_commit [c->cell_index ()] [v->first];
+ }
+
+ const db::ICplxTrans &tr = v->first;
+
+ for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Texts); ! si.at_end (); ++si) {
+ db::Text text;
+ si->text (text);
+ if (filter.selected (text.transformed (tr))) {
+ st->insert (*si);
+ }
+ }
+
+ }
+
+ } else {
+
+ db::Shapes &st = c->shapes (res->deep_layer ().layer ());
+
+ for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Texts); ! si.at_end (); ++si) {
+ db::Text text;
+ si->text (text);
+ if (filter.selected (text)) {
+ st.insert (*si);
+ }
+ }
+
+ }
+
+ }
+
+ if (! to_commit.empty () && vars.get ()) {
+ res->deep_layer ().commit_shapes (*vars, to_commit);
+ }
+
+ return res.release ();
+}
+
+RegionDelegate *DeepTexts::polygons (db::Coord e) const
+{
+ db::DeepLayer new_layer = deep_layer ().derived ();
+ db::Layout &layout = const_cast (deep_layer ().layout ());
+
+ for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
+ db::Shapes &output = c->shapes (new_layer.layer ());
+ for (db::Shapes::shape_iterator s = c->shapes (deep_layer ().layer ()).begin (db::ShapeIterator::Texts); ! s.at_end (); ++s) {
+ db::Box box = s->bbox ();
+ box.enlarge (db::Vector (e, e));
+ db::Polygon poly (box);
+ output.insert (db::PolygonRef (poly, layout.shape_repository ()));
+ }
+ }
+
+ return new db::DeepRegion (new_layer);
+}
+
+EdgesDelegate *DeepTexts::edges () const
+{
+ db::DeepLayer new_layer = deep_layer ().derived ();
+ db::Layout &layout = const_cast (deep_layer ().layout ());
+
+ for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
+ db::Shapes &output = c->shapes (new_layer.layer ());
+ for (db::Shapes::shape_iterator s = c->shapes (deep_layer ().layer ()).begin (db::ShapeIterator::Texts); ! s.at_end (); ++s) {
+ db::Box box = s->bbox ();
+ output.insert (db::Edge (box.p1 (), box.p2 ()));
+ }
+ }
+
+ return new db::DeepEdges (new_layer);
+}
+
+TextsDelegate *DeepTexts::in (const Texts &other, bool invert) const
+{
+ // TODO: implement
+ return AsIfFlatTexts::in (other, invert);
+}
+
+bool DeepTexts::equals (const Texts &other) const
+{
+ const DeepTexts *other_delegate = dynamic_cast (other.delegate ());
+ if (other_delegate && &other_delegate->deep_layer ().layout () == &deep_layer ().layout ()
+ && other_delegate->deep_layer ().layer () == deep_layer ().layer ()) {
+ return true;
+ } else {
+ return AsIfFlatTexts::equals (other);
+ }
+}
+
+bool DeepTexts::less (const Texts &other) const
+{
+ const DeepTexts *other_delegate = dynamic_cast (other.delegate ());
+ if (other_delegate && &other_delegate->deep_layer ().layout () == &deep_layer ().layout ()) {
+ return other_delegate->deep_layer ().layer () < deep_layer ().layer ();
+ } else {
+ return AsIfFlatTexts::less (other);
+ }
+}
+
+void DeepTexts::insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
+{
+ deep_layer ().insert_into (layout, into_cell, into_layer);
+}
+
+void DeepTexts::insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const
+{
+ deep_layer ().insert_into_as_polygons (layout, into_cell, into_layer, enl);
+}
+
+namespace {
+
+class Text2PolygonInteractingLocalOperation
+ : public local_operation
+{
+public:
+ Text2PolygonInteractingLocalOperation (bool inverse)
+ : m_inverse (inverse)
+ {
+ // .. nothing yet ..
+ }
+
+ virtual db::Coord dist () const
+ {
+ // touching is sufficient
+ return 1;
+ }
+
+ virtual void compute_local (db::Layout * /*layout*/, const shape_interactions &interactions, std::unordered_set &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const
+ {
+ db::box_scanner2 scanner;
+
+ std::set others;
+ for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
+ for (shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
+ others.insert (interactions.intruder_shape (*j));
+ }
+ }
+
+ for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
+ const db::TextRef &subject = interactions.subject_shape (i->first);
+ scanner.insert1 (&subject, 0);
+ }
+
+ std::list heap;
+ for (std::set::const_iterator o = others.begin (); o != others.end (); ++o) {
+ heap.push_back (o->obj ().transformed (o->trans ()));
+ scanner.insert2 (& heap.back (), 1);
+ }
+
+ if (m_inverse) {
+
+ std::unordered_set interacting;
+ text_to_region_interaction_filter, db::TextRef> filter (interacting);
+ scanner.process (filter, 1, db::box_convert (), db::box_convert ());
+
+ for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
+ const db::TextRef &subject = interactions.subject_shape (i->first);
+ if (interacting.find (subject) == interacting.end ()) {
+ result.insert (subject);
+ }
+ }
+
+ } else {
+
+ text_to_region_interaction_filter, db::TextRef> filter (result);
+ scanner.process (filter, 1, db::box_convert (), db::box_convert ());
+
+ }
+ }
+
+ virtual on_empty_intruder_mode on_empty_intruder_hint () const
+ {
+ if (m_inverse) {
+ return Copy;
+ } else {
+ return Drop;
+ }
+ }
+
+ virtual std::string description () const
+ {
+ return tl::to_string (tr ("Select interacting texts"));
+ }
+
+private:
+ bool m_inverse;
+};
+
+struct ResultInserter
+{
+ typedef db::Polygon value_type;
+
+ ResultInserter (db::Layout *layout, std::unordered_set &result)
+ : mp_layout (layout), mp_result (&result)
+ {
+ // .. nothing yet ..
+ }
+
+ void insert (const db::Polygon &p)
+ {
+ (*mp_result).insert (db::PolygonRef (p, mp_layout->shape_repository ()));
+ }
+
+private:
+ db::Layout *mp_layout;
+ std::unordered_set *mp_result;
+};
+
+class Text2PolygonPullLocalOperation
+ : public local_operation
+{
+public:
+ Text2PolygonPullLocalOperation ()
+ {
+ // .. nothing yet ..
+ }
+
+ virtual db::Coord dist () const
+ {
+ // touching is sufficient
+ return 1;
+ }
+
+ virtual void compute_local (db::Layout *layout, const shape_interactions &interactions, std::unordered_set &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const
+ {
+ db::box_scanner2 scanner;
+
+ std::set others;
+ for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
+ for (shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
+ others.insert (interactions.intruder_shape (*j));
+ }
+ }
+
+ for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) {
+ const db::TextRef &subject = interactions.subject_shape (i->first);
+ scanner.insert1 (&subject, 1);
+ }
+
+ std::list heap;
+ for (std::set::const_iterator o = others.begin (); o != others.end (); ++o) {
+ heap.push_back (o->obj ().transformed (o->trans ()));
+ scanner.insert2 (& heap.back (), 0);
+ }
+
+ ResultInserter inserter (layout, result);
+ text_to_region_interaction_filter filter (inserter);
+ scanner.process (filter, 1, db::box_convert (), db::box_convert ());
+ }
+
+ virtual on_empty_intruder_mode on_empty_intruder_hint () const
+ {
+ return Drop;
+ }
+
+ virtual std::string description () const
+ {
+ return tl::to_string (tr ("Select interacting regions"));
+ }
+};
+
+}
+
+TextsDelegate *
+DeepTexts::selected_interacting_generic (const Region &other, bool inverse) const
+{
+ std::auto_ptr dr_holder;
+ const db::DeepRegion *other_deep = dynamic_cast (other.delegate ());
+ if (! other_deep) {
+ // if the other region isn't deep, turn into a top-level only deep region to facilitate re-hierarchisation
+ dr_holder.reset (new db::DeepRegion (other, const_cast (*deep_layer ().store ())));
+ other_deep = dr_holder.get ();
+ }
+
+ const db::DeepLayer &texts = deep_layer ();
+
+ DeepLayer dl_out (texts.derived ());
+
+ db::Text2PolygonInteractingLocalOperation op (inverse);
+
+ db::local_processor proc (const_cast (&texts.layout ()), const_cast (&texts.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ());
+ proc.set_base_verbosity (other.base_verbosity ());
+ proc.set_threads (texts.store ()->threads ());
+
+ proc.run (&op, texts.layer (), other_deep->deep_layer ().layer (), dl_out.layer ());
+
+ return new db::DeepTexts (dl_out);
+}
+
+RegionDelegate *DeepTexts::pull_generic (const Region &other) const
+{
+ std::auto_ptr dr_holder;
+ const db::DeepRegion *other_deep = dynamic_cast (other.delegate ());
+ if (! other_deep) {
+ // if the other region isn't deep, turn into a top-level only deep region to facilitate re-hierarchisation
+ dr_holder.reset (new db::DeepRegion (other, const_cast (*deep_layer ().store ())));
+ other_deep = dr_holder.get ();
+ }
+
+ const db::DeepLayer &texts = deep_layer ();
+ const db::DeepLayer &other_polygons = other_deep->merged_deep_layer ();
+
+ DeepLayer dl_out (other_polygons.derived ());
+
+ db::Text2PolygonPullLocalOperation op;
+
+ db::local_processor proc (const_cast (&texts.layout ()), const_cast (&texts.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell ());
+ proc.set_base_verbosity (other.base_verbosity ());
+ proc.set_threads (texts.store ()->threads ());
+
+ proc.run (&op, texts.layer (), other_polygons.layer (), dl_out.layer ());
+
+ return new db::DeepRegion (dl_out);
+}
+
+}
diff --git a/src/db/db/dbDeepTexts.h b/src/db/db/dbDeepTexts.h
new file mode 100644
index 000000000..812582b0d
--- /dev/null
+++ b/src/db/db/dbDeepTexts.h
@@ -0,0 +1,100 @@
+
+/*
+
+ KLayout Layout Viewer
+ Copyright (C) 2006-2020 Matthias Koefferlein
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+
+#ifndef HDR_dbDeepTexts
+#define HDR_dbDeepTexts
+
+#include "dbCommon.h"
+
+#include "dbAsIfFlatTexts.h"
+#include "dbDeepShapeStore.h"
+#include "dbTexts.h"
+
+namespace db {
+
+/**
+ * @brief Provides hierarchical edges implementation
+ */
+class DB_PUBLIC DeepTexts
+ : public db::AsIfFlatTexts, public db::DeepShapeCollectionDelegateBase
+{
+public:
+ DeepTexts ();
+ DeepTexts (const db::Texts &other, DeepShapeStore &dss);
+ DeepTexts (const RecursiveShapeIterator &si, DeepShapeStore &dss);
+ DeepTexts (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans);
+
+ DeepTexts (const DeepTexts &other);
+ DeepTexts (const DeepLayer &dl);
+
+ virtual ~DeepTexts ();
+
+ TextsDelegate *clone () const;
+
+ virtual TextsIteratorDelegate *begin () const;
+ virtual std::pair begin_iter () const;
+
+ virtual size_t size () const;
+ virtual std::string to_string (size_t) const;
+ virtual Box bbox () const;
+ virtual bool empty () const;
+ virtual const db::Text *nth (size_t n) const;
+ virtual bool has_valid_texts () const;
+ virtual const db::RecursiveShapeIterator *iter () const;
+
+ virtual TextsDelegate *filter_in_place (const TextFilterBase &filter);
+ virtual TextsDelegate *filtered (const TextFilterBase &) const;
+
+ virtual TextsDelegate *add_in_place (const Texts &other);
+ virtual TextsDelegate *add (const Texts &other) const;
+
+ virtual RegionDelegate *polygons (db::Coord e) const;
+ virtual EdgesDelegate *edges () const;
+
+ virtual TextsDelegate *in (const Texts &, bool) const;
+
+ virtual bool equals (const Texts &other) const;
+ virtual bool less (const Texts &other) const;
+
+ virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
+ virtual void insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const;
+
+ virtual DeepShapeCollectionDelegateBase *deep ()
+ {
+ return this;
+ }
+
+private:
+ DeepTexts &operator= (const DeepTexts &other);
+
+ void init ();
+ DeepTexts *apply_filter (const TextFilterBase &filter) const;
+
+ virtual TextsDelegate *selected_interacting_generic (const Region &other, bool inverse) const;
+ virtual RegionDelegate *pull_generic (const Region &other) const;
+};
+
+}
+
+#endif
+
diff --git a/src/db/db/dbEdgePairs.cc b/src/db/db/dbEdgePairs.cc
index 5a6c97f4c..fbafdcdff 100644
--- a/src/db/db/dbEdgePairs.cc
+++ b/src/db/db/dbEdgePairs.cc
@@ -57,7 +57,7 @@ EdgePairs::EdgePairs (EdgePairsDelegate *delegate)
}
EdgePairs::EdgePairs (const EdgePairs &other)
- : gsi::ObjectBase (), mp_delegate (other.mp_delegate->clone ())
+ : db::ShapeCollection (), mp_delegate (other.mp_delegate->clone ())
{
// .. nothing yet ..
}
diff --git a/src/db/db/dbEdgePairs.h b/src/db/db/dbEdgePairs.h
index 2dac4e52c..07947deaf 100644
--- a/src/db/db/dbEdgePairs.h
+++ b/src/db/db/dbEdgePairs.h
@@ -27,8 +27,7 @@
#include "dbEdgePairsDelegate.h"
#include "dbShape.h"
#include "dbRecursiveShapeIterator.h"
-
-#include "gsiObject.h"
+#include "dbShapeCollection.h"
#include
@@ -230,7 +229,7 @@ public:
* can be converted to polygons or to individual edges.
*/
class DB_PUBLIC EdgePairs
- : public gsi::ObjectBase
+ : public db::ShapeCollection
{
public:
typedef db::Coord coord_type;
@@ -339,6 +338,14 @@ public:
*/
explicit EdgePairs (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans);
+ /**
+ * @brief Implementation of the ShapeCollection interface
+ */
+ ShapeCollectionDelegateBase *get_delegate () const
+ {
+ return mp_delegate;
+ }
+
/**
* @brief Gets the underlying delegate object
*/
diff --git a/src/db/db/dbEdgePairsDelegate.cc b/src/db/db/dbEdgePairsDelegate.cc
index d2b93d626..94e78bf38 100644
--- a/src/db/db/dbEdgePairsDelegate.cc
+++ b/src/db/db/dbEdgePairsDelegate.cc
@@ -34,7 +34,7 @@ EdgePairsDelegate::EdgePairsDelegate ()
}
EdgePairsDelegate::EdgePairsDelegate (const EdgePairsDelegate &other)
- : tl::UniqueId ()
+ : ShapeCollectionDelegateBase ()
{
operator= (other);
}
diff --git a/src/db/db/dbEdgePairsDelegate.h b/src/db/db/dbEdgePairsDelegate.h
index 3eeb340ce..0cd9798b6 100644
--- a/src/db/db/dbEdgePairsDelegate.h
+++ b/src/db/db/dbEdgePairsDelegate.h
@@ -25,9 +25,8 @@
#define HDR_dbEdgePairsDelegate
#include "dbCommon.h"
-
#include "dbEdgePair.h"
-#include "tlUniqueId.h"
+#include "dbShapeCollection.h"
namespace db {
@@ -59,7 +58,7 @@ public:
* @brief The delegate for the actual edge set implementation
*/
class DB_PUBLIC EdgePairsDelegate
- : public tl::UniqueId
+ : public ShapeCollectionDelegateBase
{
public:
typedef db::Coord coord_type;
diff --git a/src/db/db/dbEdges.cc b/src/db/db/dbEdges.cc
index a2b0fbdde..aebcbaf0e 100644
--- a/src/db/db/dbEdges.cc
+++ b/src/db/db/dbEdges.cc
@@ -97,7 +97,7 @@ Edges::Edges (EdgesDelegate *delegate)
}
Edges::Edges (const Edges &other)
- : gsi::ObjectBase (), mp_delegate (other.mp_delegate->clone ())
+ : db::ShapeCollection (), mp_delegate (other.mp_delegate->clone ())
{
// .. nothing yet ..
}
diff --git a/src/db/db/dbEdges.h b/src/db/db/dbEdges.h
index 3634e5d4e..aa76642db 100644
--- a/src/db/db/dbEdges.h
+++ b/src/db/db/dbEdges.h
@@ -27,8 +27,7 @@
#include "dbEdgesDelegate.h"
#include "dbRecursiveShapeIterator.h"
#include "dbCellVariants.h"
-
-#include "gsiObject.h"
+#include "dbShapeCollection.h"
#include
@@ -215,7 +214,7 @@ class Edges;
*/
class DB_PUBLIC Edges
- : public gsi::ObjectBase
+ : public db::ShapeCollection
{
public:
typedef db::Coord coord_type;
@@ -359,6 +358,14 @@ public:
*/
explicit Edges (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans, bool as_edges = true, bool merged_semantics = true);
+ /**
+ * @brief Implementation of the ShapeCollection interface
+ */
+ ShapeCollectionDelegateBase *get_delegate () const
+ {
+ return mp_delegate;
+ }
+
/**
* @brief Gets the underlying delegate object
*/
@@ -1301,6 +1308,7 @@ public:
private:
friend class EdgePairs;
+ friend class Texts;
EdgesDelegate *mp_delegate;
diff --git a/src/db/db/dbEdgesDelegate.cc b/src/db/db/dbEdgesDelegate.cc
index ea9c7ff45..982d6350a 100644
--- a/src/db/db/dbEdgesDelegate.cc
+++ b/src/db/db/dbEdgesDelegate.cc
@@ -37,7 +37,7 @@ EdgesDelegate::EdgesDelegate ()
}
EdgesDelegate::EdgesDelegate (const EdgesDelegate &other)
- : tl::UniqueId ()
+ : ShapeCollectionDelegateBase ()
{
operator= (other);
}
diff --git a/src/db/db/dbEdgesDelegate.h b/src/db/db/dbEdgesDelegate.h
index 18213bc58..7b2ff0b18 100644
--- a/src/db/db/dbEdgesDelegate.h
+++ b/src/db/db/dbEdgesDelegate.h
@@ -29,7 +29,7 @@
#include "dbEdge.h"
#include "dbEdgePairs.h"
#include "dbEdgePairRelations.h"
-#include "tlUniqueId.h"
+#include "dbShapeCollection.h"
#include
@@ -181,7 +181,7 @@ public:
* @brief The delegate for the actual edge set implementation
*/
class DB_PUBLIC EdgesDelegate
- : public tl::UniqueId
+ : public ShapeCollectionDelegateBase
{
public:
typedef db::Coord coord_type;
diff --git a/src/db/db/dbEmptyRegion.h b/src/db/db/dbEmptyRegion.h
index 5ab62f825..ec40deffa 100644
--- a/src/db/db/dbEmptyRegion.h
+++ b/src/db/db/dbEmptyRegion.h
@@ -27,6 +27,7 @@
#include "dbCommon.h"
#include "dbRegionDelegate.h"
#include "dbEmptyEdges.h"
+#include "dbEmptyTexts.h"
namespace db {
@@ -107,11 +108,14 @@ public:
virtual RegionDelegate *selected_not_interacting (const Region &) const { return new EmptyRegion (); }
virtual RegionDelegate *selected_interacting (const Edges &) const { return new EmptyRegion (); }
virtual RegionDelegate *selected_not_interacting (const Edges &) const { return new EmptyRegion (); }
+ virtual RegionDelegate *selected_interacting (const Texts &) const { return new EmptyRegion (); }
+ virtual RegionDelegate *selected_not_interacting (const Texts &) const { return new EmptyRegion (); }
virtual RegionDelegate *selected_overlapping (const Region &) const { return new EmptyRegion (); }
virtual RegionDelegate *selected_not_overlapping (const Region &) const { return new EmptyRegion (); }
virtual RegionDelegate *pull_inside (const Region &) const { return new EmptyRegion (); }
virtual RegionDelegate *pull_interacting (const Region &) const { return new EmptyRegion (); }
virtual EdgesDelegate *pull_interacting (const Edges &) const { return new EmptyEdges (); }
+ virtual TextsDelegate *pull_interacting (const Texts &) const { return new EmptyTexts (); }
virtual RegionDelegate *pull_overlapping (const Region &) const { return new EmptyRegion (); }
virtual RegionDelegate *in (const Region &, bool) const { return new EmptyRegion (); }
diff --git a/src/db/db/dbEmptyTexts.cc b/src/db/db/dbEmptyTexts.cc
new file mode 100644
index 000000000..9ef48abc2
--- /dev/null
+++ b/src/db/db/dbEmptyTexts.cc
@@ -0,0 +1,106 @@
+
+/*
+
+ KLayout Layout Viewer
+ Copyright (C) 2006-2020 Matthias Koefferlein
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+
+#include "dbEmptyTexts.h"
+#include "dbEmptyRegion.h"
+#include "dbEmptyEdges.h"
+#include "dbTexts.h"
+
+namespace db
+{
+
+// -------------------------------------------------------------------------------------------------------------
+
+EmptyTexts::EmptyTexts ()
+{
+ // .. nothing yet ..
+}
+
+EmptyTexts::EmptyTexts (const EmptyTexts &other)
+ : TextsDelegate (other)
+{
+ // .. nothing yet ..
+}
+
+TextsDelegate *
+EmptyTexts::clone () const
+{
+ return new EmptyTexts (*this);
+}
+
+RegionDelegate *
+EmptyTexts::polygons (db::Coord) const
+{
+ return new EmptyRegion ();
+}
+
+EdgesDelegate *
+EmptyTexts::edges () const
+{
+ return new EmptyEdges ();
+}
+
+TextsDelegate *
+EmptyTexts::add_in_place (const Texts &other)
+{
+ return add (other);
+}
+
+TextsDelegate *
+EmptyTexts::add (const Texts &other) const
+{
+ return other.delegate ()->clone ();
+}
+
+bool
+EmptyTexts::equals (const Texts &other) const
+{
+ return other.empty ();
+}
+
+bool
+EmptyTexts::less (const Texts &other) const
+{
+ return other.empty () ? false : true;
+}
+
+RegionDelegate *
+EmptyTexts::pull_interacting (const Region &) const
+{
+ return new EmptyRegion ();
+}
+
+TextsDelegate *
+EmptyTexts::selected_interacting (const Region &) const
+{
+ return new EmptyTexts ();
+}
+
+TextsDelegate *
+EmptyTexts::selected_not_interacting (const Region &) const
+{
+ return new EmptyTexts ();
+}
+
+}
+
diff --git a/src/db/db/dbEmptyTexts.h b/src/db/db/dbEmptyTexts.h
new file mode 100644
index 000000000..99b1623ac
--- /dev/null
+++ b/src/db/db/dbEmptyTexts.h
@@ -0,0 +1,89 @@
+
+/*
+
+ KLayout Layout Viewer
+ Copyright (C) 2006-2020 Matthias Koefferlein
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+
+#ifndef HDR_dbEmptyTexts
+#define HDR_dbEmptyTexts
+
+#include "dbCommon.h"
+
+#include "dbTextsDelegate.h"
+#include "dbRecursiveShapeIterator.h"
+
+namespace db {
+
+/**
+ * @brief The delegate for the actual edge set implementation
+ */
+class DB_PUBLIC EmptyTexts
+ : public TextsDelegate
+{
+public:
+ EmptyTexts ();
+ EmptyTexts (const EmptyTexts &other);
+
+ virtual TextsDelegate *clone () const;
+
+ virtual std::string to_string (size_t) const { return std::string (); }
+
+ virtual TextsIteratorDelegate *begin () const { return 0; }
+ virtual std::pair begin_iter () const { return std::make_pair (db::RecursiveShapeIterator (), db::ICplxTrans ()); }
+
+ virtual bool empty () const { return true; }
+ virtual size_t size () const { return 0; }
+
+ virtual Box bbox () const { return Box (); }
+
+ virtual TextsDelegate *filter_in_place (const TextFilterBase &) { return this; }
+ virtual TextsDelegate *filtered (const TextFilterBase &) const { return new EmptyTexts (); }
+
+ virtual RegionDelegate *polygons (db::Coord e) const;
+ virtual EdgesDelegate *edges () const;
+
+ virtual TextsDelegate *add_in_place (const Texts &other);
+ virtual TextsDelegate *add (const Texts &other) const;
+
+ virtual TextsDelegate *in (const Texts &, bool) const { return new EmptyTexts (); }
+
+ virtual const db::Text *nth (size_t) const { tl_assert (false); }
+ virtual bool has_valid_texts () const { return true; }
+
+ virtual const db::RecursiveShapeIterator *iter () const { return 0; }
+
+ virtual bool equals (const Texts &other) const;
+ virtual bool less (const Texts &other) const;
+
+ virtual void insert_into (Layout *, db::cell_index_type, unsigned int) const { }
+ virtual void insert_into_as_polygons (Layout *, db::cell_index_type, unsigned int, db::Coord) const { }
+
+ virtual RegionDelegate *pull_interacting (const Region &) const;
+ virtual TextsDelegate *selected_interacting (const Region &) const;
+ virtual TextsDelegate *selected_not_interacting (const Region &) const;
+
+private:
+ EmptyTexts &operator= (const EmptyTexts &other);
+};
+
+}
+
+#endif
+
diff --git a/src/db/db/dbFlatTexts.cc b/src/db/db/dbFlatTexts.cc
new file mode 100644
index 000000000..96668a150
--- /dev/null
+++ b/src/db/db/dbFlatTexts.cc
@@ -0,0 +1,220 @@
+
+/*
+
+ KLayout Layout Viewer
+ Copyright (C) 2006-2020 Matthias Koefferlein
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+
+#include "dbFlatTexts.h"
+#include "dbEmptyTexts.h"
+#include "dbTexts.h"
+
+namespace db
+{
+
+// -------------------------------------------------------------------------------------------------------------
+// FlatTexts implementation
+
+FlatTexts::FlatTexts ()
+ : AsIfFlatTexts (), m_texts (false)
+{
+ // .. nothing yet ..
+}
+
+FlatTexts::~FlatTexts ()
+{
+ // .. nothing yet ..
+}
+
+FlatTexts::FlatTexts (const FlatTexts &other)
+ : AsIfFlatTexts (other), m_texts (false)
+{
+ m_texts = other.m_texts;
+}
+
+FlatTexts::FlatTexts (const db::Shapes &texts)
+ : AsIfFlatTexts (), m_texts (texts)
+{
+ // .. nothing yet ..
+}
+
+void FlatTexts::invalidate_cache ()
+{
+ invalidate_bbox ();
+}
+
+void FlatTexts::reserve (size_t n)
+{
+ m_texts.reserve (db::Text::tag (), n);
+}
+
+TextsIteratorDelegate *FlatTexts::begin () const
+{
+ return new FlatTextsIterator (m_texts.get_layer ().begin (), m_texts.get_layer ().end ());
+}
+
+std::pair FlatTexts::begin_iter () const
+{
+ return std::make_pair (db::RecursiveShapeIterator (m_texts), db::ICplxTrans ());
+}
+
+bool FlatTexts::empty () const
+{
+ return m_texts.empty ();
+}
+
+size_t FlatTexts::size () const
+{
+ return m_texts.size ();
+}
+
+Box FlatTexts::compute_bbox () const
+{
+ m_texts.update_bbox ();
+ return m_texts.bbox ();
+}
+
+TextsDelegate *
+FlatTexts::filter_in_place (const TextFilterBase &filter)
+{
+ text_iterator_type pw = m_texts.get_layer ().begin ();
+ for (TextsIterator p (begin ()); ! p.at_end (); ++p) {
+ if (filter.selected (*p)) {
+ if (pw == m_texts.get_layer ().end ()) {
+ m_texts.get_layer ().insert (*p);
+ pw = m_texts.get_layer ().end ();
+ } else {
+ m_texts.get_layer ().replace (pw++, *p);
+ }
+ }
+ }
+
+ m_texts.get_layer ().erase (pw, m_texts.get_layer ().end ());
+
+ return this;
+}
+
+TextsDelegate *FlatTexts::add (const Texts &other) const
+{
+ std::auto_ptr new_texts (new FlatTexts (*this));
+ new_texts->invalidate_cache ();
+
+ FlatTexts *other_flat = dynamic_cast (other.delegate ());
+ if (other_flat) {
+
+ new_texts->raw_texts ().insert (other_flat->raw_texts ().get_layer ().begin (), other_flat->raw_texts ().get_layer ().end ());
+
+ } else {
+
+ size_t n = new_texts->raw_texts ().size ();
+ for (TextsIterator p (other.begin ()); ! p.at_end (); ++p) {
+ ++n;
+ }
+
+ new_texts->raw_texts ().reserve (db::Text::tag (), n);
+
+ for (TextsIterator p (other.begin ()); ! p.at_end (); ++p) {
+ new_texts->raw_texts ().insert (*p);
+ }
+
+ }
+
+ return new_texts.release ();
+}
+
+TextsDelegate *FlatTexts::add_in_place (const Texts &other)
+{
+ invalidate_cache ();
+
+ FlatTexts *other_flat = dynamic_cast (other.delegate ());
+ if (other_flat) {
+
+ m_texts.insert (other_flat->raw_texts ().get_layer ().begin (), other_flat->raw_texts ().get_layer ().end ());
+
+ } else {
+
+ size_t n = m_texts.size ();
+ for (TextsIterator p (other.begin ()); ! p.at_end (); ++p) {
+ ++n;
+ }
+
+ m_texts.reserve (db::Text::tag (), n);
+
+ for (TextsIterator p (other.begin ()); ! p.at_end (); ++p) {
+ m_texts.insert (*p);
+ }
+
+ }
+
+ return this;
+}
+
+const db::Text *FlatTexts::nth (size_t n) const
+{
+ return n < m_texts.size () ? &m_texts.get_layer ().begin () [n] : 0;
+}
+
+bool FlatTexts::has_valid_texts () const
+{
+ return true;
+}
+
+const db::RecursiveShapeIterator *FlatTexts::iter () const
+{
+ return 0;
+}
+
+void
+FlatTexts::insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const
+{
+ db::Shapes &out = layout->cell (into_cell).shapes (into_layer);
+ for (TextsIterator p (begin ()); ! p.at_end (); ++p) {
+ db::Box box = p->box ();
+ box.enlarge (db::Vector (enl, enl));
+ out.insert (db::SimplePolygon (box));
+ }
+}
+
+void
+FlatTexts::insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
+{
+ layout->cell (into_cell).shapes (into_layer).insert (m_texts);
+}
+
+void
+FlatTexts::insert (const db::Text &t)
+{
+ m_texts.insert (t);
+ invalidate_cache ();
+}
+
+void
+FlatTexts::insert (const db::Shape &shape)
+{
+ if (shape.is_text ()) {
+
+ db::Text t;
+ shape.text (t);
+ insert (t);
+
+ }
+}
+
+}
+
diff --git a/src/db/db/dbFlatTexts.h b/src/db/db/dbFlatTexts.h
new file mode 100644
index 000000000..90b3e9b24
--- /dev/null
+++ b/src/db/db/dbFlatTexts.h
@@ -0,0 +1,173 @@
+
+/*
+
+ KLayout Layout Viewer
+ Copyright (C) 2006-2020 Matthias Koefferlein
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+
+#ifndef HDR_dbFlatTexts
+#define HDR_dbFlatTexts
+
+#include "dbCommon.h"
+
+#include "dbAsIfFlatTexts.h"
+#include "dbShapes.h"
+
+namespace db {
+
+/**
+ * @brief An iterator delegate for the flat text set
+ */
+class DB_PUBLIC FlatTextsIterator
+ : public TextsIteratorDelegate
+{
+public:
+ typedef db::layer edge_pair_layer_type;
+ typedef edge_pair_layer_type::iterator iterator_type;
+
+ FlatTextsIterator (iterator_type from, iterator_type to)
+ : m_from (from), m_to (to)
+ {
+ // .. nothing yet ..
+ }
+
+ virtual bool at_end () const
+ {
+ return m_from == m_to;
+ }
+
+ virtual void increment ()
+ {
+ ++m_from;
+ }
+
+ virtual const value_type *get () const
+ {
+ return m_from.operator-> ();
+ }
+
+ virtual TextsIteratorDelegate *clone () const
+ {
+ return new FlatTextsIterator (*this);
+ }
+
+private:
+ friend class Texts;
+
+ iterator_type m_from, m_to;
+};
+
+/**
+ * @brief The delegate for the actual text set implementation
+ */
+class DB_PUBLIC FlatTexts
+ : public AsIfFlatTexts
+{
+public:
+ typedef db::Text value_type;
+
+ typedef db::layer text_layer_type;
+ typedef text_layer_type::iterator text_iterator_type;
+
+ FlatTexts ();
+ FlatTexts (const db::Shapes &texts);
+
+ FlatTexts (const FlatTexts &other);
+
+ virtual ~FlatTexts ();
+
+ TextsDelegate *clone () const
+ {
+ return new FlatTexts (*this);
+ }
+
+ void reserve (size_t);
+
+ virtual TextsIteratorDelegate *begin () const;
+ virtual std::pair begin_iter () const;
+
+ virtual bool empty () const;
+ virtual size_t size () const;
+
+ virtual TextsDelegate *filter_in_place (const TextFilterBase &filter);
+
+ virtual TextsDelegate *add_in_place (const Texts &other);
+ virtual TextsDelegate *add (const Texts &other) const;
+
+ virtual const db::Text *nth (size_t n) const;
+ virtual bool has_valid_texts () const;
+
+ virtual const db::RecursiveShapeIterator *iter () const;
+
+ virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
+ virtual void insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const;
+
+ void insert (const db::Text &text);
+ void insert (const db::Shape &shape);
+
+ template
+ void insert (const db::Shape &shape, const T &trans)
+ {
+ if (shape.is_edge_pair ()) {
+
+ db::Text t;
+ shape.text (t);
+ t.transform (trans);
+ insert (t);
+
+ }
+ }
+
+ template
+ void insert_seq (const Iter &seq)
+ {
+ for (Iter i = seq; ! i.at_end (); ++i) {
+ insert (*i);
+ }
+ }
+
+ template
+ void transform (const Trans &trans)
+ {
+ if (! trans.is_unity ()) {
+ for (text_iterator_type p = m_texts.template get_layer ().begin (); p != m_texts.template get_layer ().end (); ++p) {
+ m_texts.get_layer ().replace (p, p->transformed (trans));
+ }
+ invalidate_cache ();
+ }
+ }
+
+ db::Shapes &raw_texts () { return m_texts; }
+
+protected:
+ virtual Box compute_bbox () const;
+ void invalidate_cache ();
+
+private:
+ friend class AsIfFlatTexts;
+
+ FlatTexts &operator= (const FlatTexts &other);
+
+ mutable db::Shapes m_texts;
+};
+
+}
+
+#endif
+
diff --git a/src/db/db/dbHierNetworkProcessor.cc b/src/db/db/dbHierNetworkProcessor.cc
index 08ca4d269..f2d4dd92e 100644
--- a/src/db/db/dbHierNetworkProcessor.cc
+++ b/src/db/db/dbHierNetworkProcessor.cc
@@ -29,6 +29,7 @@
#include "dbPolygonTools.h"
#include "dbBoxScanner.h"
#include "dbDeepRegion.h"
+#include "dbNetShape.h"
#include "tlProgress.h"
#include "tlLog.h"
#include "tlTimer.h"
@@ -43,9 +44,9 @@ namespace db
// ------------------------------------------------------------------------------
-template void insert_transformed (db::Layout &layout, Container &shapes, const Shape &s, const Trans &t);
+template void insert_transformed (db::Layout &layout, db::Shapes &shapes, const Shape &s, const Trans &t);
-template void insert_transformed (db::Layout &layout, Container &shapes, const db::PolygonRef &s, const Trans &t)
+template void insert_transformed (db::Layout &layout, db::Shapes &shapes, const db::PolygonRef &s, const Trans &t)
{
db::Polygon poly = s.obj ();
poly.transform (s.trans ());
@@ -55,7 +56,32 @@ template void insert_transformed (db::Layout &lay
shapes.insert (db::PolygonRef (poly, layout.shape_repository ()));
}
-template void insert_transformed (db::Layout & /*layout*/, Container &shapes, const db::Edge &s, const Trans &t)
+template void insert_transformed (db::Layout &layout, db::Shapes &shapes, const db::NetShape &s, const Trans &t)
+{
+ if (s.type () == db::NetShape::Polygon) {
+
+ db::PolygonRef pr = s.polygon_ref ();
+ db::Polygon poly = pr.obj ();
+ poly.transform (pr.trans ());
+ if (! t.is_unity ()) {
+ poly.transform (t);
+ }
+ shapes.insert (db::PolygonRef (poly, layout.shape_repository ()));
+
+ } else if (s.type () == db::NetShape::Text) {
+
+ db::TextRef tr = s.text_ref ();
+ db::Text text = tr.obj ();
+ text.transform (tr.trans ());
+ if (! t.is_unity ()) {
+ text.transform (t);
+ }
+ shapes.insert (db::TextRef (text, layout.shape_repository ()));
+
+ }
+}
+
+template void insert_transformed (db::Layout & /*layout*/, db::Shapes &shapes, const db::Edge &s, const Trans &t)
{
shapes.insert (s.transformed (t));
}
@@ -237,6 +263,20 @@ interaction_test (const db::PolygonRef &a, const db::PolygonRef &b, const db::un
}
}
+template
+static bool
+interaction_test (const db::NetShape &a, const db::NetShape &b, const Trans &trans, db::Connectivity::edge_connectivity_type)
+{
+ return a.interacts_with_transformed (b, trans);
+}
+
+template
+static bool
+interaction_test (const db::NetShape &a, const db::NetShape &b, const db::unit_trans &, db::Connectivity::edge_connectivity_type)
+{
+ return a.interacts_with (b);
+}
+
template
static bool
interaction_test (const db::Edge &a, const db::Edge &b, const Trans &trans, db::Connectivity::edge_connectivity_type ec)
@@ -272,6 +312,8 @@ bool Connectivity::interacts (const T &a, unsigned int la, const T &b, unsigned
}
// explicit instantiations
+template DB_PUBLIC bool Connectivity::interacts (const db::NetShape &a, unsigned int la, const db::NetShape &b, unsigned int lb, const db::UnitTrans &trans) const;
+template DB_PUBLIC bool Connectivity::interacts (const db::NetShape &a, unsigned int la, const db::NetShape &b, unsigned int lb, const db::ICplxTrans &trans) const;
template DB_PUBLIC bool Connectivity::interacts (const db::PolygonRef &a, unsigned int la, const db::PolygonRef &b, unsigned int lb, const db::UnitTrans &trans) const;
template DB_PUBLIC bool Connectivity::interacts (const db::PolygonRef &a, unsigned int la, const db::PolygonRef &b, unsigned int lb, const db::ICplxTrans &trans) const;
template DB_PUBLIC bool Connectivity::interacts