diff --git a/src/db/db/dbAsIfFlatEdges.cc b/src/db/db/dbAsIfFlatEdges.cc index 40f0ae8d3..76498ca37 100644 --- a/src/db/db/dbAsIfFlatEdges.cc +++ b/src/db/db/dbAsIfFlatEdges.cc @@ -960,10 +960,15 @@ AsIfFlatEdges::insert_into (Layout *layout, db::cell_index_type into_cell, unsig { // improves performance when inserting an original layout into the same layout db::LayoutLocker locker (layout); + db::PropertyMapper pm (&layout->properties_repository (), properties_repository ()); db::Shapes &shapes = layout->cell (into_cell).shapes (into_layer); for (EdgesIterator e (begin ()); ! e.at_end (); ++e) { - shapes.insert (*e); + if (e.prop_id () != 0) { + shapes.insert (db::EdgeWithProperties (*e, pm (e.prop_id ()))); + } else { + shapes.insert (*e); + } } } diff --git a/src/db/db/dbAsIfFlatRegion.cc b/src/db/db/dbAsIfFlatRegion.cc index 939588633..7042bb121 100644 --- a/src/db/db/dbAsIfFlatRegion.cc +++ b/src/db/db/dbAsIfFlatRegion.cc @@ -130,6 +130,7 @@ EdgesDelegate * AsIfFlatRegion::edges (const EdgeFilterBase *filter) const { std::unique_ptr result (new FlatEdges ()); + db::PropertyMapper pm (result->properties_repository (), properties_repository ()); size_t n = 0; for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) { @@ -138,10 +139,11 @@ AsIfFlatRegion::edges (const EdgeFilterBase *filter) const result->reserve (n); for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) { + db::properties_id_type prop_id = p.prop_id (); for (db::Polygon::polygon_edge_iterator e = p->begin_edge (); ! e.at_end (); ++e) { if (! filter || filter->selected (*e)) { - if (p.prop_id () != 0) { - result->insert (db::EdgeWithProperties (*e, p.prop_id ())); + if (prop_id != 0) { + result->insert (db::EdgeWithProperties (*e, pm (prop_id))); } else { result->insert (*e); } @@ -1707,7 +1709,7 @@ AsIfFlatRegion::xor_with (const Region &other, PropertyConstraint prop_constrain } RegionDelegate * -AsIfFlatRegion::or_with (const Region &other, PropertyConstraint prop_constraint) const +AsIfFlatRegion::or_with (const Region &other, PropertyConstraint /*prop_constraint*/) const { if (empty () && ! other.strict_handling ()) { @@ -1807,10 +1809,15 @@ AsIfFlatRegion::insert_into (Layout *layout, db::cell_index_type into_cell, unsi { // improves performance when inserting an original layout into the same layout db::LayoutLocker locker (layout); + db::PropertyMapper pm (&layout->properties_repository (), properties_repository ()); db::Shapes &shapes = layout->cell (into_cell).shapes (into_layer); for (RegionIterator p (begin ()); ! p.at_end (); ++p) { - shapes.insert (*p); + if (p.prop_id () != 0) { + shapes.insert (db::PolygonWithProperties (*p, pm (p.prop_id ()))); + } else { + shapes.insert (*p); + } } } diff --git a/src/db/db/dbDeepEdges.cc b/src/db/db/dbDeepEdges.cc index 489efcc19..499096a24 100644 --- a/src/db/db/dbDeepEdges.cc +++ b/src/db/db/dbDeepEdges.cc @@ -219,12 +219,17 @@ void DeepEdges::merged_semantics_changed () // .. nothing yet .. } -void DeepEdges::do_insert (const db::Edge &edge) +void DeepEdges::do_insert (const db::Edge &edge, db::properties_id_type prop_id) { db::Layout &layout = deep_layer ().layout (); if (layout.begin_top_down () != layout.end_top_down ()) { db::Cell &top_cell = layout.cell (*layout.begin_top_down ()); - top_cell.shapes (deep_layer ().layer ()).insert (edge); + db::Shapes &shapes = top_cell.shapes (deep_layer ().layer ()); + if (prop_id == 0) { + shapes.insert (edge); + } else { + shapes.insert (db::EdgeWithProperties (edge, prop_id)); + } } invalidate_bbox (); diff --git a/src/db/db/dbDeepEdges.h b/src/db/db/dbDeepEdges.h index 0e252b4e5..7944e1b57 100644 --- a/src/db/db/dbDeepEdges.h +++ b/src/db/db/dbDeepEdges.h @@ -62,7 +62,7 @@ public: virtual void reserve (size_t n); - virtual void do_insert (const db::Edge &edge); + virtual void do_insert (const db::Edge &edge, properties_id_type prop_id); EdgesDelegate *clone () const; diff --git a/src/db/db/dbFlatEdges.cc b/src/db/db/dbFlatEdges.cc index ec0023b0c..e3c9dfa99 100644 --- a/src/db/db/dbFlatEdges.cc +++ b/src/db/db/dbFlatEdges.cc @@ -88,7 +88,8 @@ void FlatEdges::init () void FlatEdges::insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const { - layout->cell (into_cell).shapes (into_layer).insert (*mp_edges); + db::PropertyMapper pm (&layout->properties_repository (), mp_properties_repository.get_const ()); + layout->cell (into_cell).shapes (into_layer).insert (*mp_edges, pm); } void FlatEdges::merged_semantics_changed () @@ -355,11 +356,16 @@ const db::PropertiesRepository *FlatEdges::properties_repository () const } void -FlatEdges::do_insert (const db::Edge &edge) +FlatEdges::do_insert (const db::Edge &edge, db::properties_id_type prop_id) { m_is_merged = empty (); - mp_edges->insert (edge); + if (prop_id == 0) { + mp_edges->insert (edge); + } else { + mp_edges->insert (db::EdgeWithProperties (edge, prop_id)); + } + invalidate_cache (); } diff --git a/src/db/db/dbFlatEdges.h b/src/db/db/dbFlatEdges.h index 538099130..ac24652d9 100644 --- a/src/db/db/dbFlatEdges.h +++ b/src/db/db/dbFlatEdges.h @@ -96,7 +96,7 @@ public: virtual db::PropertiesRepository *properties_repository (); virtual const db::PropertiesRepository *properties_repository () const; - void do_insert (const db::Edge &edge); + void do_insert (const db::Edge &edge, properties_id_type prop_id); void do_transform (const db::Trans &t) { diff --git a/src/db/db/dbMutableEdges.cc b/src/db/db/dbMutableEdges.cc index 4c4e6166c..2ce7efc41 100644 --- a/src/db/db/dbMutableEdges.cc +++ b/src/db/db/dbMutableEdges.cc @@ -50,10 +50,21 @@ void MutableEdges::insert (const db::Box &box) { if (! box.empty () && box.width () > 0 && box.height () > 0) { - do_insert (db::Edge (box.lower_left (), box.upper_left ())); - do_insert (db::Edge (box.upper_left (), box.upper_right ())); - do_insert (db::Edge (box.upper_right (), box.lower_right ())); - do_insert (db::Edge (box.lower_right (), box.lower_left ())); + do_insert (db::Edge (box.lower_left (), box.upper_left ()), 0); + do_insert (db::Edge (box.upper_left (), box.upper_right ()), 0); + do_insert (db::Edge (box.upper_right (), box.lower_right ()), 0); + do_insert (db::Edge (box.lower_right (), box.lower_left ()), 0); + } +} + +void +MutableEdges::insert (const db::BoxWithProperties &box) +{ + if (! box.empty () && box.width () > 0 && box.height () > 0) { + do_insert (db::Edge (box.lower_left (), box.upper_left ()), box.properties_id ()); + do_insert (db::Edge (box.upper_left (), box.upper_right ()), box.properties_id ()); + do_insert (db::Edge (box.upper_right (), box.lower_right ()), box.properties_id ()); + do_insert (db::Edge (box.lower_right (), box.lower_left ()), box.properties_id ()); } } @@ -65,12 +76,30 @@ MutableEdges::insert (const db::Path &path) } } +void +MutableEdges::insert (const db::PathWithProperties &path) +{ + if (path.points () > 0) { + insert (db::PolygonWithProperties (path.polygon (), path.properties_id ())); + } +} + void MutableEdges::insert (const db::Polygon &polygon) { if (polygon.holes () > 0 || polygon.vertices () > 0) { for (db::Polygon::polygon_edge_iterator e = polygon.begin_edge (); ! e.at_end (); ++e) { - do_insert (*e); + do_insert (*e, 0); + } + } +} + +void +MutableEdges::insert (const db::PolygonWithProperties &polygon) +{ + if (polygon.holes () > 0 || polygon.vertices () > 0) { + for (db::Polygon::polygon_edge_iterator e = polygon.begin_edge (); ! e.at_end (); ++e) { + do_insert (*e, polygon.properties_id ()); } } } @@ -80,7 +109,17 @@ MutableEdges::insert (const db::SimplePolygon &polygon) { if (polygon.vertices () > 0) { for (db::SimplePolygon::polygon_edge_iterator e = polygon.begin_edge (); ! e.at_end (); ++e) { - do_insert (*e); + do_insert (*e, 0); + } + } +} + +void +MutableEdges::insert (const db::SimplePolygonWithProperties &polygon) +{ + if (polygon.vertices () > 0) { + for (db::SimplePolygon::polygon_edge_iterator e = polygon.begin_edge (); ! e.at_end (); ++e) { + do_insert (*e, polygon.properties_id ()); } } } @@ -88,17 +127,21 @@ MutableEdges::insert (const db::SimplePolygon &polygon) void MutableEdges::insert (const db::Shape &shape) { + db::properties_id_type prop_id = shape.prop_id (); + if (shape.is_polygon () || shape.is_path () || shape.is_box ()) { db::Polygon poly; shape.polygon (poly); - insert (poly); + for (auto e = poly.begin_edge (); ! e.at_end (); ++e) { + do_insert (*e, prop_id); + } } else if (shape.is_edge ()) { db::Edge edge; shape.edge (edge); - do_insert (edge); + do_insert (edge, prop_id); } } diff --git a/src/db/db/dbMutableEdges.h b/src/db/db/dbMutableEdges.h index 206161e36..40b097999 100644 --- a/src/db/db/dbMutableEdges.h +++ b/src/db/db/dbMutableEdges.h @@ -54,7 +54,7 @@ public: virtual void reserve (size_t n) = 0; - virtual void do_insert (const db::Edge &edge) = 0; + virtual void do_insert (const db::Edge &edge, db::properties_id_type prop_id) = 0; void transform (const db::UnitTrans &) { } void transform (const db::Disp &t) { do_transform (db::Trans (t)); } @@ -63,29 +63,37 @@ public: void transform (const db::IMatrix2d &t) { do_transform (t); } void transform (const db::IMatrix3d &t) { do_transform (t); } - void insert (const db::Edge &edge) { do_insert (edge); } + void insert (const db::Edge &edge) { do_insert (edge, 0); } + void insert (const db::EdgeWithProperties &edge) { do_insert (edge, edge.properties_id ()); } void insert (const db::Box &box); + void insert (const db::BoxWithProperties &box); void insert (const db::Path &path); + void insert (const db::PathWithProperties &path); void insert (const db::SimplePolygon &polygon); + void insert (const db::SimplePolygonWithProperties &polygon); void insert (const db::Polygon &polygon); + void insert (const db::PolygonWithProperties &polygon); void insert (const db::Shape &shape); template void insert (const db::Shape &shape, const T &trans) { + db::properties_id_type prop_id = shape.prop_id (); + if (shape.is_polygon () || shape.is_path () || shape.is_box ()) { db::Polygon poly; shape.polygon (poly); - poly.transform (trans); - insert (poly); + for (auto e = poly.begin_edge (); ! e.at_end (); ++e) { + do_insert ((*e).transformed (trans), prop_id); + } } else if (shape.is_edge ()) { db::Edge edge; shape.edge (edge); edge.transform (trans); - insert (edge); + do_insert (edge, prop_id); } } diff --git a/src/db/unit_tests/dbAsIfFlatRegionTests.cc b/src/db/unit_tests/dbAsIfFlatRegionTests.cc index 9c5549d75..5e6ab2f60 100644 --- a/src/db/unit_tests/dbAsIfFlatRegionTests.cc +++ b/src/db/unit_tests/dbAsIfFlatRegionTests.cc @@ -1716,3 +1716,57 @@ TEST(40_BoolWithProperties) db::compare_layouts (_this, target, tl::testdata () + "/algo/flat_region_au40.gds"); } +TEST(41_EdgesWithProperties) +{ + db::Layout ly; + { + std::string fn (tl::testdata ()); + fn += "/algo/deep_region_40.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (ly); + } + + db::cell_index_type top_cell_index = *ly.begin_top_down (); + db::Cell &top_cell = ly.cell (top_cell_index); + + unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0)); + unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0)); + unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0)); // empty + + db::RecursiveShapeIterator si1 (ly, top_cell, l1); + si1.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties); + db::Region r1wp (si1); + db::Region r1wp_nomerge = r1wp; + r1wp_nomerge.set_merged_semantics (false); + + si1.shape_flags (db::ShapeIterator::All); + db::Region r1 (si1); + + db::RecursiveShapeIterator si2 (ly, top_cell, l2); + si2.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties); + db::Region r2wp (si2); + db::Region r2wp_nomerge = r2wp; + r2wp_nomerge.set_merged_semantics (false); + + si2.shape_flags (db::ShapeIterator::All); + db::Region r2 (si2); + + db::Layout target; + unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (1, 0)), r1wp); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (2, 0)), r2wp); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r1.edges ()); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r1wp.edges ()); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r1wp_nomerge.edges ()); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r2.edges ()); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), r2wp.edges ()); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (22, 0)), r2wp_nomerge.edges ()); + + CHECKPOINT(); + db::compare_layouts (_this, target, tl::testdata () + "/algo/flat_region_au41.gds"); +} + diff --git a/src/db/unit_tests/dbDeepRegionTests.cc b/src/db/unit_tests/dbDeepRegionTests.cc index 1d162d43a..8d9ae2c2e 100644 --- a/src/db/unit_tests/dbDeepRegionTests.cc +++ b/src/db/unit_tests/dbDeepRegionTests.cc @@ -2204,6 +2204,62 @@ TEST(40_BoolWithProperties) db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_region_au40.gds"); } +TEST(41_EdgesWithProperties) +{ + db::Layout ly; + { + std::string fn (tl::testdata ()); + fn += "/algo/deep_region_40.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (ly); + } + + db::cell_index_type top_cell_index = *ly.begin_top_down (); + db::Cell &top_cell = ly.cell (top_cell_index); + + db::DeepShapeStore dss; + + unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0)); + unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0)); + unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0)); // empty + + db::RecursiveShapeIterator si1 (ly, top_cell, l1); + si1.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties); + db::Region r1wp (si1, dss); + db::Region r1wp_nomerge = r1wp; + r1wp_nomerge.set_merged_semantics (false); + + si1.shape_flags (db::ShapeIterator::All); + db::Region r1 (si1, dss); + + db::RecursiveShapeIterator si2 (ly, top_cell, l2); + si2.shape_flags (db::ShapeIterator::All | db::ShapeIterator::RegardProperties); + db::Region r2wp (si2, dss); + db::Region r2wp_nomerge = r2wp; + r2wp_nomerge.set_merged_semantics (false); + + si2.shape_flags (db::ShapeIterator::All); + db::Region r2 (si2, dss); + + db::Layout target; + unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (1, 0)), r1wp); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (2, 0)), r2wp); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r1.edges ()); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r1wp.edges ()); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r1wp_nomerge.edges ()); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r2.edges ()); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), r2wp.edges ()); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (22, 0)), r2wp_nomerge.edges ()); + + CHECKPOINT(); + db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_region_au41.gds"); +} + TEST(100_Integration) { db::Layout ly; diff --git a/testdata/algo/deep_region_au41.gds b/testdata/algo/deep_region_au41.gds new file mode 100644 index 000000000..7e84f976d Binary files /dev/null and b/testdata/algo/deep_region_au41.gds differ diff --git a/testdata/algo/flat_region_au41.gds b/testdata/algo/flat_region_au41.gds new file mode 100644 index 000000000..848b02bbf Binary files /dev/null and b/testdata/algo/flat_region_au41.gds differ