diff --git a/src/db/db/dbEdgeProcessor.cc b/src/db/db/dbEdgeProcessor.cc index 62e4443cf..72594d124 100644 --- a/src/db/db/dbEdgeProcessor.cc +++ b/src/db/db/dbEdgeProcessor.cc @@ -121,6 +121,26 @@ private: db::Coord m_y; }; +inline bool +is_point_on_exact (const db::Edge &e, const db::Point &pt) +{ + if (pt.x () < db::edge_xmin (e) || pt.x () > db::edge_xmax (e) || + pt.y () < db::edge_ymin (e) || pt.y () > db::edge_ymax (e)) { + + return false; + + } else if (e.dy () == 0 || e.dx () == 0) { + + // shortcut for orthogonal edges + return true; + + } else { + + return db::vprod_sign (pt - e.p1 (), e.p2 () - e.p1 ()) == 0; + + } +} + inline bool is_point_on_fuzzy (const db::Edge &e, const db::Point &pt) { @@ -141,9 +161,12 @@ is_point_on_fuzzy (const db::Edge &e, const db::Point &pt) } else { + bool with_equal = false; + db::Vector offset; if ((e.dx () < 0 && e.dy () > 0) || (e.dx () > 0 && e.dy () < 0)) { offset = db::Vector (1, 1); + with_equal = true; } else { offset = db::Vector (-1, 1); } @@ -152,30 +175,16 @@ is_point_on_fuzzy (const db::Edge &e, const db::Point &pt) typedef db::coord_traits::area_type area_type; area_type a1 = 2 * db::vprod (pp1, e.d ()); - if (a1 < 0) { a1 = -a1; } area_type a2 = db::vprod (offset, e.d ()); + + if ((a1 < 0) == (a2 < 0)) { + with_equal = false; + } + + if (a1 < 0) { a1 = -a1; } if (a2 < 0) { a2 = -a2; } - return a1 < a2; - } -} - -inline bool -is_point_on_exact (const db::Edge &e, const db::Point &pt) -{ - if (pt.x () < db::edge_xmin (e) || pt.x () > db::edge_xmax (e) || - pt.y () < db::edge_ymin (e) || pt.y () > db::edge_ymax (e)) { - - return false; - - } else if (e.dy () == 0 || e.dx () == 0) { - - // shortcut for orthogonal edges - return true; - - } else { - - return db::vprod_sign (pt - e.p1 (), e.p2 () - e.p1 ()) == 0; + return a1 < a2 || (a1 == a2 && with_equal); } } @@ -804,7 +813,7 @@ MergeOp::edge (bool north, bool enter, property_type p) bool inside_after = (*wcv != 0); m_zeroes += (!inside_after) - (!inside_before); #ifdef DEBUG_MERGEOP - printf ("north=%d, enter=%d, prop=%d -> %d\n", north, enter, p, m_zeroes); + printf ("north=%d, enter=%d, prop=%d -> %d\n", north, enter, int (p), int (m_zeroes)); #endif tl_assert (long (m_zeroes) >= 0); @@ -887,7 +896,7 @@ BooleanOp::edge_impl (bool north, bool enter, property_type p, const InsideFunc bool inside_after = ((p % 2) == 0 ? inside_a (*wcv) : inside_b (*wcv)); m_zeroes += (!inside_after) - (!inside_before); #ifdef DEBUG_BOOLEAN - printf ("north=%d, enter=%d, prop=%d -> %d\n", north, enter, p, m_zeroes); + printf ("north=%d, enter=%d, prop=%d -> %d\n", north, enter, int (p), int (m_zeroes)); #endif tl_assert (long (m_zeroes) >= 0); @@ -1793,7 +1802,7 @@ EdgeProcessor::process (db::EdgeSink &es, EdgeEvaluatorBase &op) size_t skip = c->data % skip_unit; size_t skip_res = c->data / skip_unit; #ifdef DEBUG_EDGE_PROCESSOR - printf ("X %ld->%d,%d\n", long(c->data), skip, skip_res); + printf ("X %ld->%d,%d\n", long (c->data), int (skip), int (skip_res)); #endif if (skip != 0 && (c + skip >= future || (c + skip)->data != 0)) { diff --git a/src/db/unit_tests/dbEdgeProcessor.cc b/src/db/unit_tests/dbEdgeProcessor.cc index ced703613..39d747682 100644 --- a/src/db/unit_tests/dbEdgeProcessor.cc +++ b/src/db/unit_tests/dbEdgeProcessor.cc @@ -2387,7 +2387,7 @@ TEST(134) EXPECT_EQ (out.size (), size_t (0)); } -TEST(135) +void run_test135a (tl::TestBase *_this, const db::Trans &t) { db::EdgeProcessor ep; @@ -2401,11 +2401,12 @@ TEST(135) db::Polygon p; p.assign_hull (&pts[0], &pts[sizeof(pts) / sizeof(pts[0])]); + p.transform (t); p.size (-2, -2, 2); ep.insert (p); - // merge the resulting polygons to get the true outer contour + // this is just supposed to work and not fail with internal error "m_open.empty()" std::vector out; db::PolygonContainer pc (out); db::PolygonGenerator pg2 (pc, false /*don't resolve holes*/, true /*min. coherence*/); @@ -2414,3 +2415,57 @@ TEST(135) EXPECT_EQ (out.size (), size_t (0)); } + +TEST(135a) +{ + run_test135a (_this, db::Trans (db::Trans::r0)); + run_test135a (_this, db::Trans (db::Trans::r90)); + run_test135a (_this, db::Trans (db::Trans::r180)); + run_test135a (_this, db::Trans (db::Trans::r270)); + run_test135a (_this, db::Trans (db::Trans::m0)); + run_test135a (_this, db::Trans (db::Trans::m45)); + run_test135a (_this, db::Trans (db::Trans::m90)); + run_test135a (_this, db::Trans (db::Trans::m135)); +} + +std::string run_test135b (tl::TestBase *_this, const db::Trans &t) +{ + db::EdgeProcessor ep; + + db::Point pts[] = { + db::Point (215, 0), + db::Point (145, 11), + db::Point (37, 31), + db::Point (36, 31), + db::Point (0, 43) + }; + + db::Polygon p; + p.assign_hull (&pts[0], &pts[sizeof(pts) / sizeof(pts[0])]); + p.transform (t); + p.size (-2, -2, 2); + + ep.insert (p); + + // this is just supposed to work and not fail with internal error "m_open.empty()" + std::vector out; + db::PolygonContainer pc (out); + db::PolygonGenerator pg2 (pc, false /*don't resolve holes*/, true /*min. coherence*/); + db::SimpleMerge op (1 /*wc>0*/); + ep.process (pg2, op); + + EXPECT_EQ (out.size (), size_t (1)); + return out.empty () ? std::string () : out.front ().to_string (); +} + +TEST(135b) +{ + EXPECT_EQ (run_test135b (_this, db::Trans (db::Trans::r0)), "(36,33;32,34;37,33)"); + EXPECT_EQ (run_test135b (_this, db::Trans (db::Trans::r90)), "(-35,32;-26,77;-33,37;-33,36)"); + EXPECT_EQ (run_test135b (_this, db::Trans (db::Trans::r180)), "(-33,-35;-78,-26;-37,-33;-36,-33)"); + EXPECT_EQ (run_test135b (_this, db::Trans (db::Trans::r270)), "(25,-78;33,-37;33,-36;34,-33)"); + EXPECT_EQ (run_test135b (_this, db::Trans (db::Trans::m0)), "(32,-35;36,-33;37,-33;77,-26)"); + EXPECT_EQ (run_test135b (_this, db::Trans (db::Trans::m45)), "(34,32;33,36;33,37)"); + EXPECT_EQ (run_test135b (_this, db::Trans (db::Trans::m90)), "(-78,25;-33,34;-36,33;-37,33)"); + EXPECT_EQ (run_test135b (_this, db::Trans (db::Trans::m135)), "(-26,-78;-35,-33;-33,-36;-33,-37)"); +}