More precise point/edge interaction for scanner

This commit is contained in:
Matthias Koefferlein 2018-07-22 22:52:04 +02:00
parent efd9e47c1f
commit 5741a120e9
2 changed files with 90 additions and 26 deletions

View File

@ -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<db::Point::coord_type>::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)) {

View File

@ -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<db::Polygon> 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<db::Polygon> 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)");
}