diff --git a/src/db/db/dbAsIfFlatRegion.cc b/src/db/db/dbAsIfFlatRegion.cc index aa66e3d1e..bcfcf5fcf 100644 --- a/src/db/db/dbAsIfFlatRegion.cc +++ b/src/db/db/dbAsIfFlatRegion.cc @@ -75,6 +75,23 @@ private: } +static +RegionDelegate *region_from_box (const db::Box &b, const db::PropertiesRepository *pr, db::properties_id_type prop_id) +{ + if (! b.empty () && b.width () > 0 && b.height () > 0) { + FlatRegion *new_region = new FlatRegion (); + if (prop_id != 0) { + db::PropertyMapper pm (const_cast (new_region->properties_repository ()), pr); + new_region->insert (db::BoxWithProperties (b, pm (prop_id))); + } else { + new_region->insert (b); + } + return new_region; + } else { + return new EmptyRegion (); + } +} + // ------------------------------------------------------------------------------------------------------------- // AsIfFlagRegion implementation @@ -1247,18 +1264,6 @@ AsIfFlatRegion::merged (bool min_coherence, unsigned int min_wc) const } } -RegionDelegate * -AsIfFlatRegion::region_from_box (const db::Box &b) -{ - if (! b.empty () && b.width () > 0 && b.height () > 0) { - FlatRegion *new_region = new FlatRegion (); - new_region->insert (b); - return new_region; - } else { - return new EmptyRegion (); - } -} - RegionDelegate * AsIfFlatRegion::sized (coord_type d, unsigned int mode) const { @@ -1273,11 +1278,11 @@ AsIfFlatRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const // ignore empty return new EmptyRegion (); - } else if (is_box () && begin ()->prop_id () == 0 && mode >= 2) { + } else if (is_box () && mode >= 2) { // simplified handling for a box db::Box b = bbox ().enlarged (db::Vector (dx, dy)); - return region_from_box (b); + return region_from_box (b, properties_repository (), begin ()->prop_id ()); } else if (! merged_semantics () || is_merged ()) { @@ -1364,45 +1369,85 @@ AsIfFlatRegion::and_with (const Region &other, PropertyConstraint property_const // Nothing to do return new EmptyRegion (); - } else if (pc_skip (property_constraint) && is_box () && other.is_box ()) { + } else if (is_box () && other.is_box ()) { - // @@@ TODO: implement this with property constraints as that is important for the clip implementation! + if (pc_skip (property_constraint) || pc_match (property_constraint, begin ()->prop_id (), other.begin ().prop_id ())) { - // Simplified handling for boxes - db::Box b = bbox (); - b &= other.bbox (); - return region_from_box (b); + // Simplified handling for boxes + db::Box b = bbox (); + b &= other.bbox (); - } else if (pc_skip (property_constraint) && is_box () && ! other.strict_handling ()) { + db::properties_id_type prop_id_out = pc_norm (property_constraint, begin ()->prop_id ()); - // @@@ TODO: implement this with property constraints as that is important for the clip implementation! + return region_from_box (b, properties_repository (), prop_id_out); + + } else { + return new EmptyRegion (); + } + + } else if (is_box () && ! other.strict_handling ()) { + + db::properties_id_type self_prop_id = pc_skip (property_constraint) ? 0 : begin ()->prop_id (); // map AND with box to clip .. db::Box b = bbox (); std::unique_ptr new_region (new FlatRegion (false)); + db::PropertyMapper pm (new_region->properties_repository (), properties_repository ()); + + db::properties_id_type prop_id_out = pm (pc_norm (property_constraint, self_prop_id)); std::vector clipped; for (RegionIterator p (other.begin ()); ! p.at_end (); ++p) { - clipped.clear (); - clip_poly (*p, b, clipped); - new_region->raw_polygons ().insert (clipped.begin (), clipped.end ()); + + db::properties_id_type prop_id = p.prop_id (); + if (pc_match (property_constraint, self_prop_id, prop_id)) { + + clipped.clear (); + clip_poly (*p, b, clipped); + + if (prop_id_out == 0) { + new_region->raw_polygons ().insert (clipped.begin (), clipped.end ()); + } else { + for (auto i = clipped.begin (); i != clipped.end (); ++i) { + new_region->raw_polygons ().insert (db::PolygonWithProperties (*i, prop_id_out)); + } + } + + } + } return new_region.release (); - } else if (pc_skip (property_constraint) && other.is_box () && ! strict_handling ()) { + } else if (other.is_box () && ! strict_handling ()) { - // @@@ TODO: implement this with property constraints as that is important for the clip implementation! + db::properties_id_type other_prop_id = pc_skip (property_constraint) ? 0 : other.begin ().prop_id (); // map AND with box to clip .. db::Box b = other.bbox (); std::unique_ptr new_region (new FlatRegion (false)); + db::PropertyMapper pm (new_region->properties_repository (), properties_repository ()); std::vector clipped; for (RegionIterator p (begin ()); ! p.at_end (); ++p) { - clipped.clear (); - clip_poly (*p, b, clipped); - new_region->raw_polygons ().insert (clipped.begin (), clipped.end ()); + + db::properties_id_type prop_id = p.prop_id (); + if (pc_match (property_constraint, prop_id, other_prop_id)) { + + clipped.clear (); + clip_poly (*p, b, clipped); + + db::properties_id_type prop_id_out = pm (pc_norm (property_constraint, prop_id)); + if (prop_id_out == 0) { + new_region->raw_polygons ().insert (clipped.begin (), clipped.end ()); + } else { + for (auto i = clipped.begin (); i != clipped.end (); ++i) { + new_region->raw_polygons ().insert (db::PolygonWithProperties (*i, prop_id_out)); + } + } + + } + } return new_region.release (); diff --git a/src/db/db/dbAsIfFlatRegion.h b/src/db/db/dbAsIfFlatRegion.h index 8f2fa642f..0473dceff 100644 --- a/src/db/db/dbAsIfFlatRegion.h +++ b/src/db/db/dbAsIfFlatRegion.h @@ -312,7 +312,6 @@ private: mutable db::Box m_bbox; virtual db::Box compute_bbox () const; - static RegionDelegate *region_from_box (const db::Box &b); EdgePairsDelegate *space_or_isolated_check (db::Coord d, const RegionCheckOptions &options, bool isolated) const; }; diff --git a/src/db/unit_tests/dbAsIfFlatRegionTests.cc b/src/db/unit_tests/dbAsIfFlatRegionTests.cc index 124ac5f15..d2d5a1dda 100644 --- a/src/db/unit_tests/dbAsIfFlatRegionTests.cc +++ b/src/db/unit_tests/dbAsIfFlatRegionTests.cc @@ -34,6 +34,7 @@ #include "dbCellGraphUtils.h" #include "dbTestSupport.h" #include "dbCompoundOperation.h" +#include "dbFlatRegion.h" #include "tlUnitTest.h" #include "tlStream.h" @@ -1737,6 +1738,38 @@ TEST(40_BoolWithProperties) target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (52, 1)), r1.andnot (r3, db::DifferentPropertiesConstraintDrop).first); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (53, 1)), r1.andnot (r3, db::DifferentPropertiesConstraintDrop).second); + db::Box clip (0, 8000, 10000, 15000); + db::Region clip_region; + clip_region.insert (clip); + + db::Region clip_region_wp (new db::FlatRegion ()); + db::property_names_id_type pn = clip_region_wp.properties_repository ().prop_name_id (1); + db::PropertiesRepository::properties_set ps; + ps.insert (std::make_pair (pn, 42)); + db::properties_id_type pid42 = clip_region_wp.properties_repository ().properties_id (ps); + clip_region_wp.insert (db::BoxWithProperties (clip, pid42)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (60, 0)), r1.bool_and (clip_region)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (61, 0)), r1.bool_and (clip_region_wp)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (62, 0)), clip_region.bool_and (r1)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (63, 0)), clip_region_wp.bool_and (r1)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (64, 0)), clip_region_wp.bool_and (clip_region)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (65, 0)), clip_region_wp.bool_and (clip_region_wp)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (70, 0)), r1.bool_and (clip_region, db::SamePropertiesConstraint)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (71, 0)), r1.bool_and (clip_region_wp, db::SamePropertiesConstraint)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (72, 0)), clip_region.bool_and (r1, db::SamePropertiesConstraint)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (73, 0)), clip_region_wp.bool_and (r1, db::SamePropertiesConstraint)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (74, 0)), clip_region_wp.bool_and (clip_region, db::SamePropertiesConstraint)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (75, 0)), clip_region_wp.bool_and (clip_region_wp, db::SamePropertiesConstraint)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (80, 0)), r1.bool_and (clip_region, db::SamePropertiesConstraintDrop)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (81, 0)), r1.bool_and (clip_region_wp, db::SamePropertiesConstraintDrop)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (82, 0)), clip_region.bool_and (r1, db::SamePropertiesConstraintDrop)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (83, 0)), clip_region_wp.bool_and (r1, db::SamePropertiesConstraintDrop)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (84, 0)), clip_region_wp.bool_and (clip_region, db::SamePropertiesConstraintDrop)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (85, 0)), clip_region_wp.bool_and (clip_region_wp, db::SamePropertiesConstraintDrop)); + CHECKPOINT(); db::compare_layouts (_this, target, tl::testdata () + "/algo/flat_region_au40.gds"); } diff --git a/testdata/algo/flat_region_au40.gds b/testdata/algo/flat_region_au40.gds index 682ed0746..889f3249a 100644 Binary files a/testdata/algo/flat_region_au40.gds and b/testdata/algo/flat_region_au40.gds differ