diff --git a/src/db/db/dbPolygonTools.cc b/src/db/db/dbPolygonTools.cc index 0202ee908..db18b69d3 100644 --- a/src/db/db/dbPolygonTools.cc +++ b/src/db/db/dbPolygonTools.cc @@ -1685,6 +1685,20 @@ AreaMap::bbox () const // ------------------------------------------------------------------------- // Implementation of rasterize +static bool edge_is_partially_left_of (const db::Edge &e, const db::Edge &e_original, db::Coord x) +{ + Coord xmin = db::edge_xmin (e); + if (xmin < x) { + return true; + } else if (xmin == x && e_original.dx () != 0) { + // the skew edge is cut partially rendering a straight vertical line (due to rounding) + // which we will count as "left of" + return true; + } else { + return false; + } +} + bool rasterize (const db::Polygon &polygon, db::AreaMap &am) { @@ -1801,7 +1815,7 @@ rasterize (const db::Polygon &polygon, db::AreaMap &am) for (std::vector ::iterator e = cc; e != ff; ++e) { std::pair ec = e->clipped (left); - if (ec.first && db::edge_xmin (ec.second) < x) { + if (ec.first && edge_is_partially_left_of (ec.second, *e, x)) { a += area_type (ec.second.dy ()) * area_type (px); } @@ -1818,7 +1832,7 @@ rasterize (const db::Polygon &polygon, db::AreaMap &am) for (std::vector ::iterator e = cc; e != ff; ++e) { std::pair ec = e->clipped (cell); - if (ec.first && db::edge_xmin (ec.second) < xx) { + if (ec.first && edge_is_partially_left_of (ec.second, *e, xx)) { aa += (area_type (ec.second.dy ()) * area_type (2 * xx - (ec.second.p2 ().x () + ec.second.p1 ().x ()))) / 2; a += area_type (ec.second.dy ()) * area_type (px); } @@ -1832,7 +1846,7 @@ rasterize (const db::Polygon &polygon, db::AreaMap &am) for (std::vector ::iterator e = cc; e != ff; ++e) { std::pair ec = e->clipped (cell); - if (ec.first && db::edge_xmin (ec.second) < xx) { + if (ec.first && edge_is_partially_left_of (ec.second, *e, xx)) { aa += (area_type (ec.second.dy ()) * area_type (2 * xx - (ec.second.p2 ().x () + ec.second.p1 ().x ()))) / 2; } @@ -1843,7 +1857,7 @@ rasterize (const db::Polygon &polygon, db::AreaMap &am) for (std::vector ::iterator e = cc; e != fff; ++e) { std::pair wide_ec = e->clipped (wide_cell); - if (wide_ec.first && db::edge_xmin (wide_ec.second) < x + dx) { + if (wide_ec.first && edge_is_partially_left_of (wide_ec.second, *e, x + dx)) { a += area_type (wide_ec.second.dy ()) * area_type (px); } diff --git a/src/db/unit_tests/dbFillToolTests.cc b/src/db/unit_tests/dbFillToolTests.cc index ded8efe5b..3447929ad 100644 --- a/src/db/unit_tests/dbFillToolTests.cc +++ b/src/db/unit_tests/dbFillToolTests.cc @@ -313,3 +313,35 @@ TEST(4c) CHECKPOINT(); db::compare_layouts (_this, ly, tl::testdata () + "/algo/fill_tool_au4c.gds"); } + +// issue #1309 +TEST(5) +{ + db::Layout ly; + { + std::string fn (tl::testdata ()); + fn += "/algo/fill_tool5.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (ly); + } + + db::cell_index_type fill_cell = ly.cell_by_name ("FILL_CELL").second; + db::cell_index_type top_cell = ly.cell_by_name ("TOP").second; + unsigned int fill_layer = ly.get_layer (db::LayerProperties (1, 0)); + + db::Region fill_region (db::RecursiveShapeIterator (ly, ly.cell (top_cell), fill_layer)); + + db::Region remaining_polygons; + + db::Vector rs (50, 0); + db::Vector cs (0, 50); + db::Box fc_box (db::Point (), db::Point (rs.x (), cs.y ())); + db::fill_region (&ly.cell (top_cell), fill_region, fill_cell, fc_box, rs, cs, db::Point (), false, &remaining_polygons); + + unsigned int l100 = ly.insert_layer (db::LayerProperties (100, 0)); + remaining_polygons.insert_into (&ly, top_cell, l100); + + CHECKPOINT(); + db::compare_layouts (_this, ly, tl::testdata () + "/algo/fill_tool_au5.oas", db::WriteOAS); +} diff --git a/testdata/algo/fill_tool5.gds b/testdata/algo/fill_tool5.gds new file mode 100644 index 000000000..ca90c13e1 Binary files /dev/null and b/testdata/algo/fill_tool5.gds differ diff --git a/testdata/algo/fill_tool_au5.oas b/testdata/algo/fill_tool_au5.oas new file mode 100644 index 000000000..f4040eedc Binary files /dev/null and b/testdata/algo/fill_tool_au5.oas differ