mirror of https://github.com/KLayout/klayout.git
Fixed #134
The issue was caused by an internal error in the edge processor. Effectively the weak attractor scheme was causing this problem. As the weak attractors are making things worse rather than better I dropped them. In theory, the weak attractors render an edge undisturbed by neighboring intersection points, but in cases or parallel edges this lead to problems: omitting cut points violates the output edge configuration warranties the the polygon stitcher fails. In addition, to maintain the solution for bug #74, the cut point capture condition was relaxed, so that edge crossing the exact corner of the snapping rectangle of a point are not considered captured.
This commit is contained in:
parent
b08ccb20dc
commit
94387529d6
|
|
@ -155,7 +155,7 @@ is_point_on_fuzzy (const db::Edge &e, const db::Point &pt)
|
|||
if (a1 < 0) { a1 = -a1; }
|
||||
area_type a2 = db::vprod (offset, e.d ());
|
||||
if (a2 < 0) { a2 = -a2; }
|
||||
return a1 <= a2;
|
||||
return a1 < a2;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1345,32 +1345,17 @@ get_intersections_per_band_any (std::vector <CutPoints> &cutpoints, std::vector
|
|||
#endif
|
||||
|
||||
// The new cutpoint must be inserted into other edges as well.
|
||||
// If the cutpoint is exactly on the edge and there is just one other edge
|
||||
// the cutpoint will be a weak attractor - that is an optional cutpoint.
|
||||
// In that case we can skip the cutpoint because no related edge will move.
|
||||
ip_weak.clear ();
|
||||
size_t n_off_edge = on_edge1 ? 0 : 1;
|
||||
for (std::vector <WorkEdge>::iterator cc = c; cc != f; ++cc) {
|
||||
if ((with_h || cc->dy () != 0) && cc != c1 && cc != c2 && is_point_on_fuzzy (*cc, cp.second)) {
|
||||
ip_weak.push_back (&*cc);
|
||||
if (!is_point_on_exact (*cc, cp.second)) {
|
||||
++n_off_edge;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (std::vector <WorkEdge *>::iterator icc = ip_weak.begin (); icc != ip_weak.end (); ++icc) {
|
||||
if (n_off_edge > 1) {
|
||||
(*icc)->make_cutpoints (cutpoints)->add (cp.second, &cutpoints, true);
|
||||
#ifdef DEBUG_EDGE_PROCESSOR
|
||||
printf ("intersection point %s gives cutpoint in %s.\n", cp.second.to_string ().c_str (), (*icc)->to_string ().c_str ());
|
||||
#endif
|
||||
} else {
|
||||
CutPoints *cpp = (*icc)->make_cutpoints (cutpoints);
|
||||
cpp->add_attractor (cp.second, (*icc)->data - 1);
|
||||
#ifdef DEBUG_EDGE_PROCESSOR
|
||||
printf ("intersection point %s gives weak attractor in %s.\n", cp.second.to_string ().c_str (), (*icc)->to_string ().c_str ());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1435,38 +1420,17 @@ get_intersections_per_band_any (std::vector <CutPoints> &cutpoints, std::vector
|
|||
#endif
|
||||
|
||||
// The new cutpoint must be inserted into other edges as well.
|
||||
// If the cutpoint is exactly on the edge and there is just one other edge
|
||||
// the cutpoint will be a weak attractor - that is an optional cutpoint.
|
||||
// In that case we can skip the cutpoint because no related edge will move.
|
||||
ip_weak.clear ();
|
||||
size_t n_off_edge = 0;
|
||||
if (!on_edge1) {
|
||||
n_off_edge += 1;
|
||||
}
|
||||
if (!on_edge2) {
|
||||
n_off_edge += 1;
|
||||
}
|
||||
for (std::vector <WorkEdge>::iterator cc = c; cc != f; ++cc) {
|
||||
if ((with_h || cc->dy () != 0) && cc != c1 && cc != c2 && is_point_on_fuzzy (*cc, cp.second)) {
|
||||
ip_weak.push_back (&*cc);
|
||||
if (!is_point_on_exact (*cc, cp.second)) {
|
||||
++n_off_edge;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (std::vector <WorkEdge *>::iterator icc = ip_weak.begin (); icc != ip_weak.end (); ++icc) {
|
||||
if (n_off_edge > 1) {
|
||||
(*icc)->make_cutpoints (cutpoints)->add (cp.second, &cutpoints, true);
|
||||
#ifdef DEBUG_EDGE_PROCESSOR
|
||||
printf ("intersection point %s gives cutpoint in %s.\n", cp.second.to_string ().c_str (), (*icc)->to_string ().c_str ());
|
||||
#endif
|
||||
} else {
|
||||
CutPoints *cpp = (*icc)->make_cutpoints (cutpoints);
|
||||
cpp->add_attractor (cp.second, (*icc)->data - 1);
|
||||
#ifdef DEBUG_EDGE_PROCESSOR
|
||||
printf ("intersection point %s gives weak attractor in %s.\n", cp.second.to_string ().c_str (), (*icc)->to_string ().c_str ());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -296,7 +296,7 @@ PolygonGenerator::flush ()
|
|||
{
|
||||
#ifdef DEBUG_POLYGON_GENERATOR
|
||||
for (open_map_iterator_type i = m_open.begin (); i != m_open.end (); ++i) {
|
||||
printf ("%d:%s%c%c ", i->contour, i->point.to_string().c_str(), i->first ? '!' : ' ', i == m_open_pos ? '*' : ' ');
|
||||
printf ("%ld:%s%c%c ", i->contour, i->point.to_string().c_str(), i->first ? '!' : ' ', i == m_open_pos ? '*' : ' ');
|
||||
}
|
||||
printf ("\n");
|
||||
#endif
|
||||
|
|
@ -325,12 +325,12 @@ PolygonGenerator::begin_scanline (db::Coord y)
|
|||
#ifdef DEBUG_POLYGON_GENERATOR
|
||||
printf ("m_open=");
|
||||
for (open_map_type::const_iterator o = m_open.begin (); o != m_open.end (); ++o) {
|
||||
printf ("%d:%s ", o->contour, o->point.to_string().c_str());
|
||||
printf ("%ld:%s ", o->contour, o->point.to_string().c_str());
|
||||
}
|
||||
printf ("\n");
|
||||
printf ("contours:\n");
|
||||
for (size_t j = 0; j < mp_contours->size (); ++j) {
|
||||
printf ("c%d%s: ", j, (*mp_contours)[j].is_hole () ? "H" : "");
|
||||
printf ("c%ld%s: ", j, (*mp_contours)[j].is_hole () ? "H" : "");
|
||||
for (size_t i = 0; i < (*mp_contours)[j].size (); ++i) {
|
||||
printf ("%s ", ((*mp_contours)[j].begin () + i)->to_string().c_str ());
|
||||
}
|
||||
|
|
@ -364,7 +364,7 @@ PolygonGenerator::skip_n (size_t n)
|
|||
{
|
||||
join_contours (std::numeric_limits<db::Coord>::max ());
|
||||
#ifdef DEBUG_POLYGON_GENERATOR
|
||||
printf ("skip(%d)\n", n);
|
||||
printf ("skip(%ld)\n", n);
|
||||
#endif
|
||||
while (n-- > 0) {
|
||||
++m_open_pos;
|
||||
|
|
@ -375,9 +375,9 @@ void
|
|||
PolygonGenerator::put (const db::Edge &e)
|
||||
{
|
||||
#ifdef DEBUG_POLYGON_GENERATOR
|
||||
printf ("put(%s) y=%d m_open(%d)=", e.to_string().c_str(),m_y,std::distance (m_open.begin (), m_open_pos));
|
||||
printf ("put(%s) y=%d m_open(%ld)=", e.to_string().c_str(),m_y,std::distance (m_open.begin (), m_open_pos));
|
||||
for (open_map_iterator_type i = m_open.begin (); i != m_open.end (); ++i) {
|
||||
printf ("%d:%s%c%c ", i->contour, i->point.to_string().c_str(), i->first ? '!' : ' ', i == m_open_pos ? '*' : ' ');
|
||||
printf ("%ld:%s%c%c ", i->contour, i->point.to_string().c_str(), i->first ? '!' : ' ', i == m_open_pos ? '*' : ' ');
|
||||
}
|
||||
printf ("\n");
|
||||
#endif
|
||||
|
|
@ -438,7 +438,7 @@ PolygonGenerator::put (const db::Edge &e)
|
|||
cnew.push_back (e.p2 ());
|
||||
|
||||
#ifdef DEBUG_POLYGON_GENERATOR
|
||||
printf ("create %s %d\n", hole ? "hole" : "hull", poly_index);
|
||||
printf ("create %s %ld\n", hole ? "hole" : "hull", inew);
|
||||
#endif
|
||||
m_open.insert (m_open_pos, PGPoint (hole ? e.p1 () : e.p2 (), inew, true));
|
||||
m_open.insert (m_open_pos, PGPoint (hole ? e.p2 () : e.p1 (), inew, false));
|
||||
|
|
@ -449,7 +449,7 @@ PolygonGenerator::put (const db::Edge &e)
|
|||
|
||||
#ifdef DEBUG_POLYGON_GENERATOR
|
||||
for (open_map_iterator_type i = m_open.begin (); i != m_open.end (); ++i) {
|
||||
printf ("%d:%s%c%c ", i->contour, i->point.to_string().c_str(), i->first ? '!' : ' ', i == m_open_pos ? '*' : ' ');
|
||||
printf ("%ld:%s%c%c ", i->contour, i->point.to_string().c_str(), i->first ? '!' : ' ', i == m_open_pos ? '*' : ' ');
|
||||
}
|
||||
printf ("\n");
|
||||
#endif
|
||||
|
|
@ -552,14 +552,14 @@ PolygonGenerator::join_contours (db::Coord x)
|
|||
size_t i1 = m_open_pos->contour;
|
||||
size_t i2 = n->contour;
|
||||
#ifdef DEBUG_POLYGON_GENERATOR
|
||||
printf ("join %d and %d\n", i1, i2);
|
||||
printf ("join %ld and %ld\n", i1, i2);
|
||||
for (open_map_iterator_type i = m_open.begin (); i != m_open.end (); ++i) {
|
||||
printf ("%d:%s%c%c%c%c ", i->contour, i->point.to_string().c_str(), i->first ? '!' : ' ', i == m_open_pos ? '*' : ' ', i == n ? '+' : ' ', i == nn ? '#' : ' ');
|
||||
printf ("%ld:%s%c%c%c%c ", i->contour, i->point.to_string().c_str(), i->first ? '!' : ' ', i == m_open_pos ? '*' : ' ', i == n ? '+' : ' ', i == nn ? '#' : ' ');
|
||||
}
|
||||
printf ("\n");
|
||||
printf ("--> input contours:\n");
|
||||
for (size_t j = 0; j < mp_contours->size (); ++j) {
|
||||
printf ("--> c%d%s: ", j, (*mp_contours)[j].is_hole () ? "H" : "");
|
||||
printf ("--> c%ld%s: ", j, (*mp_contours)[j].is_hole () ? "H" : "");
|
||||
for (size_t i = 0; i < (*mp_contours)[j].size (); ++i) {
|
||||
printf ("%s ", ((*mp_contours)[j].begin () + i)->to_string().c_str ());
|
||||
}
|
||||
|
|
@ -705,7 +705,7 @@ PolygonGenerator::join_contours (db::Coord x)
|
|||
if (! c1.is_hole ()) {
|
||||
|
||||
#ifdef DEBUG_POLYGON_GENERATOR
|
||||
printf ("finish %d (hull)\n", i1);
|
||||
printf ("finish %ld (hull)\n", i1);
|
||||
#endif
|
||||
|
||||
produce_poly (c1);
|
||||
|
|
@ -775,7 +775,7 @@ PolygonGenerator::join_contours (db::Coord x)
|
|||
#ifdef DEBUG_POLYGON_GENERATOR
|
||||
printf ("--> output contours:\n");
|
||||
for (size_t j = 0; j < mp_contours->size (); ++j) {
|
||||
printf ("--> c%d%s: ", j, (*mp_contours)[j].is_hole () ? "H" : "");
|
||||
printf ("--> c%ld%s: ", j, (*mp_contours)[j].is_hole () ? "H" : "");
|
||||
for (size_t i = 0; i < (*mp_contours)[j].size (); ++i) {
|
||||
printf ("%s ", ((*mp_contours)[j].begin () + i)->to_string().c_str ());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "dbShapeProcessor.h"
|
||||
#include "dbPolygon.h"
|
||||
#include "dbPolygonGenerators.h"
|
||||
#include "dbLayout.h"
|
||||
#include "dbReader.h"
|
||||
#include "dbCommonReader.h"
|
||||
|
|
@ -1388,15 +1389,29 @@ TEST(24)
|
|||
in1.back ().assign_hull (p1 + 0, p1 + sizeof (p1) / sizeof (p1[0]));
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<db::Polygon> out;
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
ep.simple_merge (in1, out, false, false);
|
||||
|
||||
EXPECT_EQ (out.size (), size_t (2));
|
||||
EXPECT_EQ (out.size (), size_t (1));
|
||||
std::sort (out.begin (), out.end ());
|
||||
EXPECT_EQ (out[0].to_string (), "(0,-9;0,0;3,0;3,-2;1,0;1,-9)");
|
||||
EXPECT_EQ (out[1].to_string (), "(-2,1;-2,3;0,1;0,10;1,10;1,1)");
|
||||
EXPECT_EQ (out[0].to_string (), "(0,-9;0,0;-2,1;-2,3;0,1;0,10;1,10;1,1;3,0;3,-2;1,0;1,-9/1,0;1,1;0,1)");
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<db::Polygon> out;
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
ep.simple_merge (in1, out, false, true);
|
||||
|
||||
EXPECT_EQ (out.size (), size_t (3));
|
||||
std::sort (out.begin (), out.end ());
|
||||
EXPECT_EQ (out[0].to_string (), "(0,-9;0,0;-2,1;-2,3;1,0;1,-9)");
|
||||
EXPECT_EQ (out[1].to_string (), "(3,-2;1,0;1,1;3,0)");
|
||||
EXPECT_EQ (out[2].to_string (), "(0,1;0,10;1,10;1,1)");
|
||||
}
|
||||
}
|
||||
|
||||
TEST(25)
|
||||
|
|
@ -2346,3 +2361,28 @@ TEST(102)
|
|||
EXPECT_EQ (out.size (), size_t (1));
|
||||
EXPECT_EQ (out[0].to_string (), "(0,0;0,200;100,200;100,100;200,100;200,200;500,200;500,100;600,100;600,200;0,200;0,1000;1000,1000;1000,0)");
|
||||
}
|
||||
|
||||
// Bug 134
|
||||
TEST(134)
|
||||
{
|
||||
const char *pd = "(30,-7957;0,0;56,-4102;30,-7921)";
|
||||
|
||||
db::Coord dx = 0;
|
||||
db::Coord dy = -3999;
|
||||
unsigned int mode = 3;
|
||||
|
||||
db::Polygon p;
|
||||
tl::from_string (pd, p);
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
db::Polygon ps (p.sized (dx, dy, mode));
|
||||
ep.insert (ps);
|
||||
|
||||
db::SimpleMerge op (1 /*wc>0*/);
|
||||
std::vector<db::Polygon> out;
|
||||
db::PolygonContainer pc (out);
|
||||
db::PolygonGenerator pg (pc);
|
||||
ep.process (pg, op);
|
||||
|
||||
EXPECT_EQ (out.size (), size_t (0));
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue