diff --git a/src/db/db/dbDeepEdges.cc b/src/db/db/dbDeepEdges.cc index e3b40b063..b75948ba6 100644 --- a/src/db/db/dbDeepEdges.cc +++ b/src/db/db/dbDeepEdges.cc @@ -171,7 +171,7 @@ DeepEdges::DeepEdges (const DeepEdges &other) m_is_merged (other.m_is_merged) { if (m_merged_edges_valid) { - m_merged_edges = other.m_merged_edges; + m_merged_edges = other.m_merged_edges.copy (); } } @@ -186,7 +186,7 @@ DeepEdges::operator= (const DeepEdges &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; + m_merged_edges = other.m_merged_edges.copy (); } } @@ -227,20 +227,52 @@ void DeepEdges::do_insert (const db::Edge &edge) template static void transform_deep_layer (db::DeepLayer &deep_layer, const Trans &t) { - // TODO: this is a pretty cheap implementation. At least a plain move can be done with orientation variants. + if (t.equal (Trans (db::Disp (t.disp ())))) { - db::Layout &layout = deep_layer.layout (); - if (layout.begin_top_down () != layout.end_top_down ()) { + // Plain move - db::Cell &top_cell = layout.cell (*layout.begin_top_down ()); + // build cell variants for different orientations + db::OrientationReducer same_orientation; + + db::VariantsCollectorBase vars (&same_orientation); + vars.collect (deep_layer.layout (), deep_layer.initial_cell ()); + deep_layer.separate_variants (vars); + + // process the variants + db::Layout &layout = deep_layer.layout (); + + for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { + + const std::map &v = vars.variants (c->cell_index ()); + tl_assert (v.size () == size_t (1)); + + db::Trans tr (v.begin ()->first.inverted () * t.disp ()); + + db::Shapes &shapes = c->shapes (deep_layer.layer ()); + db::Shapes new_shapes (layout.manager (), c.operator-> (), layout.is_editable ()); + new_shapes.insert_transformed (shapes, tr); + shapes.swap (new_shapes); - db::Shapes flat_shapes (layout.is_editable ()); - for (db::RecursiveShapeIterator iter (layout, top_cell, deep_layer.layer ()); !iter.at_end (); ++iter) { - flat_shapes.insert (iter->edge ().transformed (iter.trans ()).transformed (t)); } - layout.clear_layer (deep_layer.layer ()); - top_cell.shapes (deep_layer.layer ()).swap (flat_shapes); + } else { + + // General transformation -> note that this is a flat implementation! + + 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 ()); + + db::Shapes flat_shapes (layout.is_editable ()); + for (db::RecursiveShapeIterator iter (layout, top_cell, deep_layer.layer ()); !iter.at_end (); ++iter) { + flat_shapes.insert (iter->edge ().transformed (iter.trans ()).transformed (t)); + } + + layout.clear_layer (deep_layer.layer ()); + top_cell.shapes (deep_layer.layer ()).swap (flat_shapes); + + } } } @@ -248,24 +280,36 @@ static void transform_deep_layer (db::DeepLayer &deep_layer, const Trans &t) void DeepEdges::do_transform (const db::Trans &t) { transform_deep_layer (deep_layer (), t); + if (m_merged_edges_valid && m_merged_edges.layer () != deep_layer ().layer ()) { + transform_deep_layer (m_merged_edges, t); + } invalidate_bbox (); } void DeepEdges::do_transform (const db::ICplxTrans &t) { transform_deep_layer (deep_layer (), t); + if (m_merged_edges_valid && m_merged_edges.layer () != deep_layer ().layer ()) { + transform_deep_layer (m_merged_edges, t); + } invalidate_bbox (); } void DeepEdges::do_transform (const db::IMatrix2d &t) { transform_deep_layer (deep_layer (), t); + if (m_merged_edges_valid && m_merged_edges.layer () != deep_layer ().layer ()) { + transform_deep_layer (m_merged_edges, t); + } invalidate_bbox (); } void DeepEdges::do_transform (const db::IMatrix3d &t) { transform_deep_layer (deep_layer (), t); + if (m_merged_edges_valid && m_merged_edges.layer () != deep_layer ().layer ()) { + transform_deep_layer (m_merged_edges, t); + } invalidate_bbox (); } diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index 350e10fe2..1dde5fdc6 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -174,7 +174,7 @@ DeepRegion::DeepRegion (const DeepRegion &other) m_is_merged (other.m_is_merged) { if (m_merged_polygons_valid) { - m_merged_polygons = other.m_merged_polygons; + m_merged_polygons = other.m_merged_polygons.copy (); } } @@ -189,7 +189,7 @@ DeepRegion::operator= (const DeepRegion &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; + m_merged_polygons = other.m_merged_polygons.copy (); } } @@ -235,22 +235,56 @@ void DeepRegion::do_insert (const db::Polygon &polygon) template static void transform_deep_layer (db::DeepLayer &deep_layer, const Trans &t) { - // TODO: this is a pretty cheap implementation. At least a plain move can be done with orientation variants. + if (t.equal (Trans (db::Disp (t.disp ())))) { - db::Layout &layout = deep_layer.layout (); - if (layout.begin_top_down () != layout.end_top_down ()) { + // Plain move - db::Cell &top_cell = layout.cell (*layout.begin_top_down ()); + // build cell variants for different orientations + db::OrientationReducer same_orientation; + + db::VariantsCollectorBase vars (&same_orientation); + vars.collect (deep_layer.layout (), deep_layer.initial_cell ()); + deep_layer.separate_variants (vars); + + // process the variants + db::Layout &layout = deep_layer.layout (); + + for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { + + const std::map &v = vars.variants (c->cell_index ()); + tl_assert (v.size () == size_t (1)); + + db::Trans tr (v.begin ()->first.inverted () * t.disp ()); + + db::Shapes &shapes = c->shapes (deep_layer.layer ()); + db::Shapes new_shapes (layout.manager (), c.operator-> (), layout.is_editable ()); + new_shapes.insert_transformed (shapes, tr); + shapes.swap (new_shapes); - db::Shapes flat_shapes (layout.is_editable ()); - for (db::RecursiveShapeIterator iter (layout, top_cell, deep_layer.layer ()); !iter.at_end (); ++iter) { - db::Polygon poly; - iter->polygon (poly); - flat_shapes.insert (poly.transformed (iter.trans ()).transformed (t)); } - layout.clear_layer (deep_layer.layer ()); - top_cell.shapes (deep_layer.layer ()).swap (flat_shapes); + } else { + + // General transformation -> note that this is a flat implementation! + + 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 ()); + + db::Shapes flat_shapes (layout.manager (), &top_cell, layout.is_editable ()); + for (db::RecursiveShapeIterator iter (layout, top_cell, deep_layer.layer ()); !iter.at_end (); ++iter) { + db::Polygon poly; + iter->polygon (poly); + poly.transform (iter.trans ()); + poly.transform (t); + flat_shapes.insert (db::PolygonRef (poly, layout.shape_repository ())); + } + + layout.clear_layer (deep_layer.layer ()); + top_cell.shapes (deep_layer.layer ()).swap (flat_shapes); + + } } } @@ -258,24 +292,36 @@ static void transform_deep_layer (db::DeepLayer &deep_layer, const Trans &t) void DeepRegion::do_transform (const db::Trans &t) { transform_deep_layer (deep_layer (), t); + if (m_merged_polygons_valid && m_merged_polygons.layer () != deep_layer ().layer ()) { + transform_deep_layer (m_merged_polygons, t); + } invalidate_bbox (); } void DeepRegion::do_transform (const db::ICplxTrans &t) { transform_deep_layer (deep_layer (), t); + if (m_merged_polygons_valid && m_merged_polygons.layer () != deep_layer ().layer ()) { + transform_deep_layer (m_merged_polygons, t); + } invalidate_bbox (); } void DeepRegion::do_transform (const db::IMatrix2d &t) { transform_deep_layer (deep_layer (), t); + if (m_merged_polygons_valid && m_merged_polygons.layer () != deep_layer ().layer ()) { + transform_deep_layer (m_merged_polygons, t); + } invalidate_bbox (); } void DeepRegion::do_transform (const db::IMatrix3d &t) { transform_deep_layer (deep_layer (), t); + if (m_merged_polygons_valid && m_merged_polygons.layer () != deep_layer ().layer ()) { + transform_deep_layer (m_merged_polygons, t); + } invalidate_bbox (); } diff --git a/src/drc/unit_tests/drcSimpleTests.cc b/src/drc/unit_tests/drcSimpleTests.cc index ab37a7f8a..51992e3f4 100644 --- a/src/drc/unit_tests/drcSimpleTests.cc +++ b/src/drc/unit_tests/drcSimpleTests.cc @@ -1386,3 +1386,13 @@ TEST(58d_in_and_out) { run_test (_this, "58", true); } + +TEST(60_issue1216) +{ + run_test (_this, "60", false); +} + +TEST(60d_issue1216) +{ + run_test (_this, "60", true); +} diff --git a/testdata/drc/drcSimpleTests_60.drc b/testdata/drc/drcSimpleTests_60.drc new file mode 100644 index 000000000..0dcb1fa03 --- /dev/null +++ b/testdata/drc/drcSimpleTests_60.drc @@ -0,0 +1,30 @@ + +# Moved implementation + +source($drc_test_source) +target($drc_test_target) + +if $drc_test_deep + deep +end + +l8 = input(8, 0) +l9 = input(9, 0) + +l8.output(8, 0) +l9.output(9, 0) + +# NOTE: "sized" tests issue #1216 +l8.sized(0.1, 0).moved(-0.1, 0).sized(0, 0.1).moved(0, -0.1).output(108, 0) +l9.sized(0.1, 0).moved(-0.1, 0).sized(0, 0.1).moved(0, -0.1).output(109, 0) + +l8.edges.moved(-0.1, -0.1).extended_out(0.05).output(118, 0) +l9.edges.moved(-0.1, -0.1).extended_out(0.05).output(119, 0) + +# NOTE: "sized" tests issue #1216 +l8.rotated(90.0).sized(0, 0.1).output(208, 0) +l9.rotated(90.0).sized(0, 0.1).output(209, 0) + +l8.edges.rotated(90.0).extended_out(0.05).output(218, 0) +l9.edges.rotated(90.0).extended_out(0.05).output(219, 0) + diff --git a/testdata/drc/drcSimpleTests_60.gds b/testdata/drc/drcSimpleTests_60.gds new file mode 100644 index 000000000..0d195b044 Binary files /dev/null and b/testdata/drc/drcSimpleTests_60.gds differ diff --git a/testdata/drc/drcSimpleTests_au60.gds b/testdata/drc/drcSimpleTests_au60.gds new file mode 100644 index 000000000..acb2b4b88 Binary files /dev/null and b/testdata/drc/drcSimpleTests_au60.gds differ