Compare commits

...

4 Commits

Author SHA1 Message Date
Matthias Köfferlein a73c44178d
Merge ea79698f15 into 8b010d61d2 2025-10-27 08:05:53 +01:00
Matthias Koefferlein 8b010d61d2 Trying to fix unit tests 2025-10-26 22:25:28 +01:00
Matthias Koefferlein ea79698f15 Updating test data 2024-09-15 15:41:20 +02:00
Matthias Koefferlein aed3f1862b Needs testing - Improving algorithm for hole insertion
This is for the edge processor / polygon generator:
The algorithm tries to find a better place
for hooking stitch lines for holes in
"resolve_holes" mode.
2024-09-15 00:10:36 +02:00
20 changed files with 99 additions and 25 deletions

View File

@ -413,6 +413,8 @@ PolygonGenerator::begin_scanline (db::Coord y)
m_open_pos = m_open.begin (); m_open_pos = m_open.begin ();
m_y = y; m_y = y;
m_prev_stitch_index = std::numeric_limits<size_t>::max ();
#ifdef DEBUG_POLYGON_GENERATOR #ifdef DEBUG_POLYGON_GENERATOR
printf ("m_open="); printf ("m_open=");
for (open_map_type::const_iterator o = m_open.begin (); o != m_open.end (); ++o) { for (open_map_type::const_iterator o = m_open.begin (); o != m_open.end (); ++o) {
@ -823,27 +825,68 @@ PolygonGenerator::join_contours (db::Coord x)
tl_assert (c1.size () >= 2); tl_assert (c1.size () >= 2);
PGPolyContour::iterator ins = cprev.end (); PGPolyContour::iterator ins = cprev.end ();
db::Coord xprev = 0;
db::Edge eprev;
#if 1 PGPolyContour::iterator ii = ins;
--ii;
PGPolyContour::iterator iii = ii;
--iii;
// shallow analysis: insert the cutline at the end of the sequence - this may // shallow analysis: insert the cutline at the end of the sequence - this may
// cut lines collinear with contour edges // cut lines collinear with contour edges
eprev = db::Edge (*(ins - 2), *(ins - 1)); db::Edge eprev = db::Edge (*iii, *ii);
xprev = db::coord_traits<db::Coord>::rounded (edge_xaty (db::Edge (*(ins - 2), *(ins - 1)), m_y)); db::Coord xprev = db::coord_traits<db::Coord>::rounded (edge_xaty (eprev, m_y));
#else
// deep analysis: determine insertion point: pick the one where the cutline is shortest
for (PGPolyContour::iterator i = ins; i > cprev.begin () + 1; --i) { #if 1 // experimental
if (m_prev_stitch_index == iprev) {
db::Edge ecut (i[-2], i[-1]); auto i = m_prev_stitch_ins;
db::Coord xcut = db::coord_traits<db::Coord>::rounded (edge_xaty (db::Edge (i[-2], i[-1]), m_y)); ii = i;
iii = --ii;
--iii;
if (ii->y () >= m_y) {
db::Edge ecut (*iii, *ii);
db::Coord xcut = db::coord_traits<db::Coord>::rounded (edge_xaty (ecut, m_y));
if (iii->y () < m_y && xcut < c1.back ().x () && xcut > xprev) {
xprev = xcut;
eprev = ecut;
ins = i;
}
}
} else {
// deep analysis: determine insertion point: pick the one where the cutline is shortest
// CAUTION: this may introduce a O(2) complexity in the number of holes along the x axis
while (true) {
auto i = ii;
ii = iii;
if (ii == cprev.begin ()) {
break;
}
--iii;
if (ii->y () >= m_y) {
db::Edge ecut (*iii, *ii);
db::Coord xcut = db::coord_traits<db::Coord>::rounded (edge_xaty (ecut, m_y));
if (iii->y () < m_y && xcut < c1.back ().x () && xcut > xprev) {
xprev = xcut;
eprev = ecut;
ins = i;
}
}
if (ins == i || (i[-1].y () >= m_y && i[-2].y () < m_y && xcut < c1.back ().x () && xcut > xprev)) {
xprev = xcut;
eprev = ecut;
ins = i;
} }
} }
@ -867,6 +910,11 @@ PolygonGenerator::join_contours (db::Coord x)
} }
ins = cprev.insert (ins, pprev); ins = cprev.insert (ins, pprev);
// remember the insertion point - it may be a candidate to attach the next hole
m_prev_stitch_ins = ins;
m_prev_stitch_index = iprev;
++ins; ++ins;
if (eprev.p2 () != pprev) { if (eprev.p2 () != pprev) {
cprev.insert (ins, eprev.p2 ()); cprev.insert (ins, eprev.p2 ());

View File

@ -184,6 +184,8 @@ private:
db::SimplePolygon m_spoly; db::SimplePolygon m_spoly;
static bool ms_compress; static bool ms_compress;
bool m_compress; bool m_compress;
size_t m_prev_stitch_index;
std::list<db::Point>::iterator m_prev_stitch_ins;
void join_contours (db::Coord x); void join_contours (db::Coord x);
void produce_poly (const PGPolyContour &c); void produce_poly (const PGPolyContour &c);

View File

@ -1192,7 +1192,7 @@ TEST(121)
{ {
db::GDS2WriterOptions opt; db::GDS2WriterOptions opt;
opt.max_vertex_count = 4; opt.max_vertex_count = 4;
run_test (_this, "t121.oas.gz", "t121_au.gds.gz", true, opt); run_test (_this, "t121.oas.gz", "t121_au_2.gds.gz", true, opt);
} }
// Meta info // Meta info

View File

@ -33,7 +33,7 @@
#include <stdlib.h> #include <stdlib.h>
static void run_test (tl::TestBase *_this, const char *dir) static void run_test (tl::TestBase *_this, const char *dir, const char *au_file = "au.oas.gz")
{ {
if (! tl::XMLParser::is_available ()) { if (! tl::XMLParser::is_available ()) {
throw tl::CancelException (); throw tl::CancelException ();
@ -53,7 +53,7 @@ static void run_test (tl::TestBase *_this, const char *dir)
reader.read (layout, options); reader.read (layout, options);
} }
db::compare_layouts (_this, layout, tl::testdata_private () + "/pcb/" + dir + "/au.oas.gz", db::WriteOAS, 1); db::compare_layouts (_this, layout, tl::testdata_private () + "/pcb/" + dir + "/" + au_file, db::WriteOAS, 1);
} }
TEST(0_Metadata) TEST(0_Metadata)
@ -167,7 +167,7 @@ TEST(1)
TEST(2) TEST(2)
{ {
run_test (_this, "allegro"); run_test (_this, "allegro", "au_2.oas.gz");
} }
TEST(3) TEST(3)
@ -199,13 +199,13 @@ TEST(7)
TEST(8) TEST(8)
{ {
test_is_long_runner (); test_is_long_runner ();
run_test (_this, "microchip-2"); run_test (_this, "microchip-2", "au_2.oas.gz");
} }
TEST(9) TEST(9)
{ {
test_is_long_runner (); test_is_long_runner ();
run_test (_this, "microchip-3"); run_test (_this, "microchip-3", "au_2.oas.gz");
} }
TEST(10) TEST(10)
@ -236,7 +236,7 @@ TEST(14)
TEST(15) TEST(15)
{ {
run_test (_this, "gerbv_examples/polarity"); run_test (_this, "gerbv_examples/polarity", "au_2.oas.gz");
} }
TEST(16) TEST(16)
@ -294,7 +294,7 @@ TEST(25)
TEST(26) TEST(26)
{ {
test_is_long_runner (); test_is_long_runner ();
run_test (_this, "pos-neg"); run_test (_this, "pos-neg", "au_2.oas.gz");
} }
TEST(27) TEST(27)
@ -334,12 +334,12 @@ TEST(X2_2e)
TEST(X2_2f) TEST(X2_2f)
{ {
run_test (_this, "x2-2f"); run_test (_this, "x2-2f", "au_2.oas.gz");
} }
TEST(X2_2g) TEST(X2_2g)
{ {
run_test (_this, "x2-2g"); run_test (_this, "x2-2g", "au_2.oas.gz");
} }
TEST(X2_2h) TEST(X2_2h)
@ -364,7 +364,7 @@ TEST(X2_2k)
TEST(X2_3) TEST(X2_3)
{ {
run_test (_this, "x2-3"); run_test (_this, "x2-3", "au_2.oas.gz");
} }
TEST(X2_4) TEST(X2_4)

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.

View File

@ -121,6 +121,12 @@ class DBLibrary_TestClass < TestBase
def test_4_library_registration_and_rename def test_4_library_registration_and_rename
# clean up before
[ "RBA-unit-test", "RBA-unit-test2" ].each do |name|
l = RBA::Library::library_by_name(name)
l && l.unregister
end
lib = RBA::Library::new lib = RBA::Library::new
lib.description = "LIB1" lib.description = "LIB1"
lib.delete lib.delete
@ -159,6 +165,12 @@ class DBLibrary_TestClass < TestBase
def test_5_reload def test_5_reload
# clean up before
[ "RBA-unit-test", "RBA-unit-test2" ].each do |name|
l = RBA::Library::library_by_name(name)
l && l.unregister
end
lib = MyLibImpl::new lib = MyLibImpl::new
lib.description = "LIB1" lib.description = "LIB1"
lib.register("RBA-unit-test") lib.register("RBA-unit-test")
@ -178,6 +190,12 @@ class DBLibrary_TestClass < TestBase
def test_6_cells_become_defunct_after_unregister def test_6_cells_become_defunct_after_unregister
# clean up before
[ "RBA-unit-test", "RBA-unit-test2" ].each do |name|
l = RBA::Library::library_by_name(name)
l && l.unregister
end
lib = RBA::Library::new lib = RBA::Library::new
lib.description = "LIB1" lib.description = "LIB1"
lib.register("RBA-unit-test") lib.register("RBA-unit-test")
@ -209,6 +227,12 @@ class DBLibrary_TestClass < TestBase
def test_7_change_ref def test_7_change_ref
# clean up before
[ "RBA-unit-test", "RBA-unit-test2" ].each do |name|
l = RBA::Library::library_by_name(name)
l && l.unregister
end
lib = RBA::Library::new lib = RBA::Library::new
lib.description = "LIB1" lib.description = "LIB1"
lib.register("RBA-unit-test") lib.register("RBA-unit-test")