mirror of https://github.com/KLayout/klayout.git
Fixing a performance issue on hole insertion for polygons with many holes
This commit is contained in:
parent
bd33640471
commit
331bb5aed4
|
|
@ -1044,6 +1044,19 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
} // namespace db
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
||||
// injecting a global std::swap for polygons into the
|
||||
// std namespace
|
||||
template <class C>
|
||||
void swap (db::polygon_contour<C> &a, db::polygon_contour<C> &b)
|
||||
{
|
||||
a.swap (b);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace db
|
||||
|
|
@ -2047,7 +2060,7 @@ public:
|
|||
* @param remove_reflected True, if reflecting spikes shall be removed on compression
|
||||
*/
|
||||
template <class I>
|
||||
void insert_hole (I start, I end, bool compress = default_compression<C> (), bool remove_reflected = false)
|
||||
void insert_hole (I start, I end, bool compress = default_compression<C> (), bool remove_reflected = false)
|
||||
{
|
||||
insert_hole (start, end, db::unit_trans<C> (), compress, remove_reflected);
|
||||
}
|
||||
|
|
@ -2073,21 +2086,17 @@ public:
|
|||
// add the hole
|
||||
contour_type &h = add_hole ();
|
||||
h.assign (start, end, op, true, compress, true /*normalize*/, remove_reflected);
|
||||
}
|
||||
|
||||
// and keep the list sorted by swapping the
|
||||
// elements and move the last one to the right
|
||||
// position
|
||||
// KLUDGE: this is probably a performance bottleneck from applications
|
||||
// with polygons with may holes ..
|
||||
if (holes () > 1) {
|
||||
typename contour_list_type::iterator ins_pos = std::lower_bound (m_ctrs.begin () + 1, m_ctrs.end () - 1, h);
|
||||
typename contour_list_type::iterator p = m_ctrs.end () - 1;
|
||||
if (ins_pos != p) {
|
||||
while (p != ins_pos) {
|
||||
p->swap (p [-1]);
|
||||
--p;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Sort the holes
|
||||
*
|
||||
* Sorting the holes makes certain algorithms more effective.
|
||||
*/
|
||||
void sort_holes ()
|
||||
{
|
||||
if (! m_ctrs.empty ()) {
|
||||
std::sort (m_ctrs.begin () + 1, m_ctrs.end ());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2884,6 +2893,16 @@ public:
|
|||
tl_assert (false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A dummy implementation of "sort_holes" provided for template instantiation
|
||||
*
|
||||
* Asserts, if begin called.
|
||||
*/
|
||||
void sort_holes ()
|
||||
{
|
||||
tl_assert (false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A dummy implementation of "hole" provided for template instantiation
|
||||
*
|
||||
|
|
@ -3530,7 +3549,7 @@ inline void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int
|
|||
namespace std
|
||||
{
|
||||
|
||||
// injecting a global std::swap for polygons into the
|
||||
// injecting a global std::swap for polygons into the
|
||||
// std namespace
|
||||
template <class C>
|
||||
void swap (db::polygon<C> &a, db::polygon<C> &b)
|
||||
|
|
|
|||
|
|
@ -865,6 +865,8 @@ PolygonGenerator::produce_poly (const PGPolyContour &c)
|
|||
|
||||
}
|
||||
|
||||
m_poly.sort_holes ();
|
||||
|
||||
}
|
||||
|
||||
mp_psink->put (m_poly);
|
||||
|
|
|
|||
|
|
@ -456,6 +456,8 @@ static bool _cut_polygon_internal (const PolygonType &input, const Edge &line, c
|
|||
}
|
||||
}
|
||||
|
||||
hull->sort_holes ();
|
||||
|
||||
right_of_line->put (*hull);
|
||||
|
||||
}
|
||||
|
|
@ -859,6 +861,8 @@ smooth (const db::Polygon &polygon, db::Coord d, bool keep_hv)
|
|||
}
|
||||
}
|
||||
|
||||
new_poly.sort_holes ();
|
||||
|
||||
}
|
||||
|
||||
return new_poly;
|
||||
|
|
@ -1351,6 +1355,8 @@ do_extract_rad (const db::polygon<C> &polygon, double &rinner, double &router, u
|
|||
|
||||
}
|
||||
|
||||
new_polygon->sort_holes ();
|
||||
|
||||
} else {
|
||||
|
||||
if (! do_extract_rad_from_contour (polygon.begin_hull (), polygon.end_hull (), rinner, router, n, (std::vector<db::point<C> > *) 0, false)) {
|
||||
|
|
@ -1542,6 +1548,8 @@ do_compute_rounded (const db::polygon<C> &polygon, double rinner, double router,
|
|||
new_poly.insert_hole (new_pts.begin (), new_pts.end (), false /*don't compress*/);
|
||||
}
|
||||
|
||||
new_poly.sort_holes ();
|
||||
|
||||
return new_poly;
|
||||
}
|
||||
|
||||
|
|
@ -2882,6 +2890,8 @@ snapped_polygon (const db::Polygon &poly, db::Coord gx, db::Coord gy, std::vecto
|
|||
|
||||
}
|
||||
|
||||
pnew.sort_holes ();
|
||||
|
||||
return pnew;
|
||||
}
|
||||
|
||||
|
|
@ -2921,6 +2931,8 @@ scaled_and_snapped_polygon (const db::Polygon &poly, db::Coord gx, db::Coord mx,
|
|||
|
||||
}
|
||||
|
||||
pnew.sort_holes ();
|
||||
|
||||
return pnew;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -926,6 +926,11 @@ struct polygon_defs
|
|||
return c->insert_hole (&pts[0], &pts[0] + sizeof (pts) / sizeof (pts[0]));
|
||||
}
|
||||
|
||||
static void sort_holes (C *c)
|
||||
{
|
||||
c->sort_holes ();
|
||||
}
|
||||
|
||||
static C *from_string (const char *s)
|
||||
{
|
||||
tl::Extractor ex (s);
|
||||
|
|
@ -1249,6 +1254,14 @@ struct polygon_defs
|
|||
"@brief Iterates over the points that make up the nth hole\n"
|
||||
"The hole number must be less than the number of holes (see \\holes)"
|
||||
) +
|
||||
method_ext ("sort_holes", &sort_holes,
|
||||
"@brief Brings the holes in a specific order\n"
|
||||
"This function is normalize the hole order so the comparison of two "
|
||||
"polygons does not depend on the order the holes were inserted. "
|
||||
"Polygons generated by KLayout's alorithms have their holes sorted.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28.8."
|
||||
) +
|
||||
method_ext ("size", &size_xy, gsi::arg ("dx"), gsi::arg ("dy"), gsi::arg ("mode"),
|
||||
"@brief Sizes the polygon (biasing)\n"
|
||||
"\n"
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ TEST(1)
|
|||
db::Polygon pp;
|
||||
pp.insert_hole (c3.begin (), c3.end ());
|
||||
pp.insert_hole (c2.begin (), c2.end ());
|
||||
pp.sort_holes ();
|
||||
pp.assign_hull (c1.begin (), c1.end ());
|
||||
EXPECT_EQ (pp.area (), 1000*100-2*380*80);
|
||||
EXPECT_EQ (pp.area2 (), 2*(1000*100-2*380*80));
|
||||
|
|
|
|||
|
|
@ -122,6 +122,8 @@ class DBPolygonTests(unittest.TestCase):
|
|||
b.assign_hole(1, [ pya.DPoint( 15, 25 ), pya.DPoint( 25, 25 ), pya.DPoint( 25, 65 ) ])
|
||||
self.assertEqual( str(b), "(0,1;1,5;1,1/10,20;20,20;20,60)" )
|
||||
b.insert_hole( [ pya.DPoint( 1, 2 ), pya.DPoint( 2, 2 ), pya.DPoint( 2, 6 ) ] )
|
||||
self.assertEqual( str(b), "(0,1;1,5;1,1/10,20;20,20;20,60/1,2;2,2;2,6)" )
|
||||
b.sort_holes()
|
||||
self.assertEqual( str(b), "(0,1;1,5;1,1/1,2;2,2;2,6/10,20;20,20;20,60)" )
|
||||
b.assign_hole(0, [ pya.DPoint( 15, 25 ), pya.DPoint( 25, 25 ), pya.DPoint( 25, 65 ) ])
|
||||
self.assertEqual( str(b), "(0,1;1,5;1,1/15,25;25,25;25,65/10,20;20,20;20,60)" )
|
||||
|
|
@ -234,6 +236,8 @@ class DBPolygonTests(unittest.TestCase):
|
|||
b.assign_hole(1, [ pya.Point( 15, 25 ), pya.Point( 25, 25 ), pya.Point( 25, 65 ) ])
|
||||
self.assertEqual( str(b), "(0,1;1,5;1,1/10,20;20,20;20,60)" )
|
||||
b.insert_hole( [ pya.Point( 1, 2 ), pya.Point( 2, 2 ), pya.Point( 2, 6 ) ] )
|
||||
self.assertEqual( str(b), "(0,1;1,5;1,1/10,20;20,20;20,60/1,2;2,2;2,6)" )
|
||||
b.sort_holes()
|
||||
self.assertEqual( str(b), "(0,1;1,5;1,1/1,2;2,2;2,6/10,20;20,20;20,60)" )
|
||||
b.assign_hole(0, [ pya.Point( 15, 25 ), pya.Point( 25, 25 ), pya.Point( 25, 65 ) ])
|
||||
self.assertEqual( str(b), "(0,1;1,5;1,1/15,25;25,25;25,65/10,20;20,20;20,60)" )
|
||||
|
|
|
|||
|
|
@ -128,6 +128,8 @@ class DBPolygon_TestClass < TestBase
|
|||
b.assign_hole(1, [ RBA::DPoint::new( 15, 25 ), RBA::DPoint::new( 25, 25 ), RBA::DPoint::new( 25, 65 ) ])
|
||||
assert_equal( b.to_s, "(0,1;1,5;1,1/10,20;20,20;20,60)" )
|
||||
b.insert_hole( [ RBA::DPoint::new( 1, 2 ), RBA::DPoint::new( 2, 2 ), RBA::DPoint::new( 2, 6 ) ] )
|
||||
assert_equal( b.to_s, "(0,1;1,5;1,1/10,20;20,20;20,60/1,2;2,2;2,6)" )
|
||||
b.sort_holes
|
||||
assert_equal( b.to_s, "(0,1;1,5;1,1/1,2;2,2;2,6/10,20;20,20;20,60)" )
|
||||
b.assign_hole(0, [ RBA::DPoint::new( 15, 25 ), RBA::DPoint::new( 25, 25 ), RBA::DPoint::new( 25, 65 ) ])
|
||||
assert_equal( b.to_s, "(0,1;1,5;1,1/15,25;25,25;25,65/10,20;20,20;20,60)" )
|
||||
|
|
@ -251,6 +253,8 @@ class DBPolygon_TestClass < TestBase
|
|||
b.assign_hole(1, [ RBA::Point::new( 15, 25 ), RBA::Point::new( 25, 25 ), RBA::Point::new( 25, 65 ) ])
|
||||
assert_equal( b.to_s, "(0,1;1,5;1,1/10,20;20,20;20,60)" )
|
||||
b.insert_hole( [ RBA::Point::new( 1, 2 ), RBA::Point::new( 2, 2 ), RBA::Point::new( 2, 6 ) ] )
|
||||
assert_equal( b.to_s, "(0,1;1,5;1,1/10,20;20,20;20,60/1,2;2,2;2,6)" )
|
||||
b.sort_holes
|
||||
assert_equal( b.to_s, "(0,1;1,5;1,1/1,2;2,2;2,6/10,20;20,20;20,60)" )
|
||||
b.assign_hole(0, [ RBA::Point::new( 15, 25 ), RBA::Point::new( 25, 25 ), RBA::Point::new( 25, 65 ) ])
|
||||
assert_equal( b.to_s, "(0,1;1,5;1,1/15,25;25,25;25,65/10,20;20,20;20,60)" )
|
||||
|
|
|
|||
Loading…
Reference in New Issue