mirror of https://github.com/KLayout/klayout.git
Enhancing polygon splitting
With this enhancement, the area ratio in DRC can be configured as a negative value. This indicates to take the outer manhattan approximation of the polygons. This way, skinny diagonals are not resolved into many small triangles.
This commit is contained in:
parent
ca9b1d779d
commit
e2718c5a54
|
|
@ -405,7 +405,7 @@ private:
|
|||
// ----------------------------------------------------------------------------------
|
||||
|
||||
DeepShapeStoreState::DeepShapeStoreState ()
|
||||
: m_threads (1), m_max_area_ratio (3.0), m_max_vertex_count (16), m_reject_odd_polygons (false), m_text_property_name (), m_text_enlargement (-1), m_subcircuit_hierarchy_for_nets (false)
|
||||
: m_threads (1), m_max_area_ratio (-3.0), m_max_vertex_count (16), m_reject_odd_polygons (false), m_text_property_name (), m_text_enlargement (-1), m_subcircuit_hierarchy_for_nets (false)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
|
|||
|
|
@ -654,7 +654,7 @@ ReducingHierarchyBuilderShapeReceiver::reduce (const db::Polygon &poly, db::prop
|
|||
|
||||
// NOTE: only halfmanhattan polygons are guaranteed not to generate grid snap artefacts when splitting.
|
||||
// This is important to maintain the connection integrity of shape clusters.
|
||||
if (poly.is_halfmanhattan () && ((m_max_vertex_count >= 4 && poly.vertices () > m_max_vertex_count) || (m_area_ratio > 2.0 && poly.area_ratio () > m_area_ratio))) {
|
||||
if (poly.is_halfmanhattan () && db::suggest_split_polygon (poly, m_max_vertex_count, m_area_ratio)) {
|
||||
|
||||
std::vector <db::Polygon> split_polygons;
|
||||
db::split_polygon (poly, split_polygons);
|
||||
|
|
|
|||
|
|
@ -689,8 +689,7 @@ scale_and_snap (db::Layout &layout, db::Cell &cell, db::Coord g, db::Coord m, db
|
|||
|
||||
static bool split_polygon (bool first, db::Polygon &poly, size_t max_vertex_count, double max_area_ratio, std::vector<db::Polygon> &parts)
|
||||
{
|
||||
if ((max_vertex_count > 0 && poly.vertices () > max_vertex_count) ||
|
||||
(max_area_ratio > 0 && poly.area_ratio () > max_area_ratio)) {
|
||||
if (db::suggest_split_polygon (poly, max_vertex_count, max_area_ratio)) {
|
||||
|
||||
std::vector<db::Polygon> sp;
|
||||
db::split_polygon (poly, sp);
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ PolygonSplitter::PolygonSplitter (PolygonSink &sink, double max_area_ratio, size
|
|||
void
|
||||
PolygonSplitter::put (const db::Polygon &poly)
|
||||
{
|
||||
if ((m_max_vertex_count > 0 && poly.vertices () > m_max_vertex_count) || (m_max_area_ratio > 0.0 && poly.area_ratio () > m_max_area_ratio)) {
|
||||
if (db::suggest_split_polygon (poly, m_max_vertex_count, m_max_area_ratio)) {
|
||||
|
||||
std::vector <db::Polygon> split_polygons;
|
||||
db::split_polygon (poly, split_polygons);
|
||||
|
|
|
|||
|
|
@ -785,6 +785,14 @@ public:
|
|||
return area2 () / 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The upper bound area for a manhattan approximation of the contour times
|
||||
*/
|
||||
area_type area_upper_manhattan_bound () const
|
||||
{
|
||||
return area_upper_manhattan_bound2 () / 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The area of the contour times 2
|
||||
* For integer area types, this is the more precise value as the division
|
||||
|
|
@ -807,6 +815,52 @@ public:
|
|||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The upper bound area for a manhattan approximation of the contour times 2
|
||||
* This area takes non-manhattan edges as being manhattan-interpolated to the outside.
|
||||
*/
|
||||
area_type area_upper_manhattan_bound2 () const
|
||||
{
|
||||
size_type n = size ();
|
||||
if (n < 3) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
area_type a = 0;
|
||||
point_type pl = (*this) [n - 1];
|
||||
for (size_type p = 0; p < n; ++p) {
|
||||
|
||||
point_type pp = (*this) [p];
|
||||
|
||||
int sdx = pp.x () < pl.x () ? -1 : (pp.x () == pl.x () ? 0 : 1);
|
||||
int sdy = pp.y () < pl.y () ? -1 : (pp.y () == pl.y () ? 0 : 1);
|
||||
|
||||
if (sdx != 0 && sdy != 0) {
|
||||
|
||||
point_type pm;
|
||||
|
||||
// determine an interpolation point
|
||||
if (sdx * sdy < 0) {
|
||||
pm = point_type (pp.x (), pl.y ());
|
||||
} else {
|
||||
pm = point_type (pl.x (), pp.y ());
|
||||
}
|
||||
|
||||
a += db::vprod (pm - point_type (), pl - point_type ());
|
||||
a += db::vprod (pp - point_type (), pm - point_type ());
|
||||
|
||||
} else {
|
||||
|
||||
a += db::vprod (pp - point_type (), pl - point_type ());
|
||||
|
||||
}
|
||||
|
||||
pl = pp;
|
||||
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The perimeter of the contour
|
||||
*/
|
||||
|
|
@ -1747,6 +1801,26 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the area ratio between the polygon's bounding box and upper manhattan approximation bound
|
||||
*
|
||||
* This number is a measure how well the polygon is approximated by the bounding box,
|
||||
* while assuming an outer manhattan approximation is a good measure for the polygon's
|
||||
* area.
|
||||
* Values are bigger than 1 for well-formed polygons. Bigger values mean worse
|
||||
* approximation.
|
||||
*/
|
||||
double area_upper_manhattan_bound_ratio () const
|
||||
{
|
||||
area_type a = this->area_upper_manhattan_bound2 ();
|
||||
if (a == 0) {
|
||||
// By our definition, an empty polygon has an area ratio of 0
|
||||
return 0.0;
|
||||
} else {
|
||||
return double (box ().area ()) / (0.5 * a);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The hull "begin" point iterator
|
||||
*
|
||||
|
|
@ -2184,7 +2258,7 @@ public:
|
|||
/**
|
||||
* @brief The area of the polygon
|
||||
*/
|
||||
area_type area () const
|
||||
area_type area () const
|
||||
{
|
||||
area_type a = 0;
|
||||
for (typename contour_list_type::const_iterator h = m_ctrs.begin (); h != m_ctrs.end (); ++h) {
|
||||
|
|
@ -2193,6 +2267,21 @@ public:
|
|||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The area of the polygon - upper manhattan bound
|
||||
*
|
||||
* This gives the upper area bound for a manhattan approximation of the
|
||||
* polygon.
|
||||
*/
|
||||
area_type area_upper_manhattan_bound () const
|
||||
{
|
||||
area_type a = 0;
|
||||
for (typename contour_list_type::const_iterator h = m_ctrs.begin (); h != m_ctrs.end (); ++h) {
|
||||
a += h->area_upper_manhattan_bound ();
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The area of the polygon times 2
|
||||
* For integer area types, this is the more precise value as the division
|
||||
|
|
@ -2207,6 +2296,21 @@ public:
|
|||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The area of the polygon - upper manhattan bound times 2
|
||||
*
|
||||
* This gives the upper area bound for a manhattan approximation of the
|
||||
* polygon.
|
||||
*/
|
||||
area_type area_upper_manhattan_bound2 () const
|
||||
{
|
||||
area_type a = 0;
|
||||
for (typename contour_list_type::const_iterator h = m_ctrs.begin (); h != m_ctrs.end (); ++h) {
|
||||
a += h->area_upper_manhattan_bound2 ();
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The perimeter of the polygon
|
||||
*/
|
||||
|
|
@ -2966,6 +3070,17 @@ public:
|
|||
return m_hull.area ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The area of the polygon - upper manhattan bound
|
||||
*
|
||||
* This gives the upper area bound for a manhattan approximation of the
|
||||
* polygon.
|
||||
*/
|
||||
area_type area_upper_manhattan_bound () const
|
||||
{
|
||||
return m_hull.area_upper_manhattan_bound ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The area of the polygon times 2
|
||||
* For integer area types, this is the more precise value as the division
|
||||
|
|
@ -2976,6 +3091,17 @@ public:
|
|||
return m_hull.area2 ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The area of the polygon - upper manhattan bound times 2
|
||||
*
|
||||
* This gives the upper area bound for a manhattan approximation of the
|
||||
* polygon.
|
||||
*/
|
||||
area_type area_upper_manhattan_bound2 () const
|
||||
{
|
||||
return m_hull.area_upper_manhattan_bound2 ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The perimeter of the polygon
|
||||
*/
|
||||
|
|
@ -3101,6 +3227,26 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the area ratio between the polygon's bounding box and upper manhattan approximation bound
|
||||
*
|
||||
* This number is a measure how well the polygon is approximated by the bounding box,
|
||||
* while assuming an outer manhattan approximation is a good measure for the polygon's
|
||||
* area.
|
||||
* Values are bigger than 1 for well-formed polygons. Bigger values mean worse
|
||||
* approximation.
|
||||
*/
|
||||
double area_upper_manhattan_bound_ratio () const
|
||||
{
|
||||
area_type a = this->area_upper_manhattan_bound2 ();
|
||||
if (a == 0) {
|
||||
// By our definition, an empty polygon has an area ratio of 0
|
||||
return 0.0;
|
||||
} else {
|
||||
return double (box ().area ()) / (0.5 * a);
|
||||
}
|
||||
}
|
||||
|
||||
void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self = false, void *parent = 0) const
|
||||
{
|
||||
db::mem_stat (stat, purpose, cat, m_hull, no_self, parent);
|
||||
|
|
|
|||
|
|
@ -633,6 +633,32 @@ template<> DB_PUBLIC void cut_polygon_internal (const db::DSimplePolygon &polygo
|
|||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Implementation of suggest_split_polygon
|
||||
|
||||
template <class PolygonType>
|
||||
bool
|
||||
suggest_split_polygon (const PolygonType &polygon, size_t max_vertex_count, double max_area_ratio)
|
||||
{
|
||||
size_t v = polygon.vertices ();
|
||||
if (v <= 4) {
|
||||
return false;
|
||||
} else if (max_vertex_count > 0 && v > max_vertex_count) {
|
||||
return true;
|
||||
} else if (max_area_ratio > 0 && polygon.area_ratio () > max_area_ratio) {
|
||||
return true;
|
||||
} else if (max_area_ratio < 0 && polygon.area_upper_manhattan_bound_ratio () > -max_area_ratio) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template DB_PUBLIC bool suggest_split_polygon<> (const db::Polygon &polygon, size_t max_vertex_count, double max_area_ratio);
|
||||
template DB_PUBLIC bool suggest_split_polygon<> (const db::SimplePolygon &polygon, size_t max_vertex_count, double max_area_ratio);
|
||||
template DB_PUBLIC bool suggest_split_polygon<> (const db::DPolygon &polygon, size_t max_vertex_count, double max_area_ratio);
|
||||
template DB_PUBLIC bool suggest_split_polygon<> (const db::DSimplePolygon &polygon, size_t max_vertex_count, double max_area_ratio);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Implementation of split_polygon
|
||||
|
||||
|
|
|
|||
|
|
@ -129,6 +129,21 @@ void cut_polygon (const PolygonType &input, const typename PolygonType::edge_typ
|
|||
template <class PolygonType>
|
||||
void DB_PUBLIC split_polygon (const PolygonType &polygon, std::vector<PolygonType> &output);
|
||||
|
||||
/**
|
||||
* @brief Determines whether a polygon needs to be split according to the given max_vertex and area_ratio criteron
|
||||
*
|
||||
* If max_vertex is 0, there is no vertex limit.
|
||||
* If max_vertex is >0, the function returns true, if the vertex limit is exceeded.
|
||||
*
|
||||
* If area_ratio is 0, there is no area ratio limit.
|
||||
* If area_ratio is >0, the function returns true, if the bounding box area is larger than area_ratio times the polygon area.
|
||||
* If area_ratio is <0, the function returns true, if the bounding box area is larger than -area_ratio times the polygon
|
||||
* manhattan approximation upper area bound.
|
||||
* (the latter definition is useful to prevent splitting of thin diagonal lines).
|
||||
*/
|
||||
template <class PolygonType>
|
||||
bool DB_PUBLIC suggest_split_polygon (const PolygonType &polygon, size_t max_vertex, double area_ratio);
|
||||
|
||||
/**
|
||||
* @brief Determines whether a polygon and a box interact
|
||||
*
|
||||
|
|
|
|||
|
|
@ -266,8 +266,7 @@ void TrapezoidDecomposition::process (const db::Polygon &poly, std::vector<db::P
|
|||
|
||||
void PolygonBreaker::process (const db::Polygon &poly, std::vector<db::Polygon> &result) const
|
||||
{
|
||||
if ((m_max_vertex_count > 0 && poly.vertices () > m_max_vertex_count) ||
|
||||
(m_max_area_ratio > 0 && poly.area_ratio () > m_max_area_ratio)) {
|
||||
if (db::suggest_split_polygon (poly, m_max_vertex_count, m_max_area_ratio)) {
|
||||
|
||||
std::vector<db::Polygon> split_polygons;
|
||||
db::split_polygon (poly, split_polygons);
|
||||
|
|
|
|||
|
|
@ -42,8 +42,7 @@ static std::vector<C> split_poly (const C *p)
|
|||
template <class C>
|
||||
static void break_polygon (const C &poly, size_t max_vertex_count, double max_area_ratio, std::vector<C> &result)
|
||||
{
|
||||
if ((max_vertex_count > 0 && poly.vertices () > max_vertex_count) ||
|
||||
(max_area_ratio > 0 && poly.area_ratio () > max_area_ratio)) {
|
||||
if (db::suggest_split_polygon (poly, max_vertex_count, max_area_ratio)) {
|
||||
|
||||
std::vector<C> split_polygons;
|
||||
db::split_polygon (poly, split_polygons);
|
||||
|
|
@ -222,6 +221,26 @@ struct simple_polygon_defs
|
|||
return poly->area2 ();
|
||||
}
|
||||
|
||||
#if defined(HAVE_64BIT_COORD)
|
||||
// workaround for missing 128bit binding of GSI
|
||||
static double area_upper_manhattan_bound (const C *poly)
|
||||
#else
|
||||
static area_type area_upper_manhattan_bound (const C *poly)
|
||||
#endif
|
||||
{
|
||||
return poly->area_upper_manhattan_bound ();
|
||||
}
|
||||
|
||||
#if defined(HAVE_64BIT_COORD)
|
||||
// workaround for missing 128bit binding of GSI
|
||||
static double area_upper_manhattan_bound2 (const C *poly)
|
||||
#else
|
||||
static area_type area_upper_manhattan_bound2 (const C *poly)
|
||||
#endif
|
||||
{
|
||||
return poly->area_upper_manhattan_bound2 ();
|
||||
}
|
||||
|
||||
static std::vector<tl::Variant> extract_rad (const C *sp)
|
||||
{
|
||||
db::polygon<coord_type> p, pnew;
|
||||
|
|
@ -572,6 +591,12 @@ struct simple_polygon_defs
|
|||
"\n"
|
||||
"This method has been introduced in version 0.26.1\n"
|
||||
) +
|
||||
method_ext ("area_upper_manhattan_bound", &area_upper_manhattan_bound,
|
||||
"@hide" // too special
|
||||
) +
|
||||
method_ext ("area_upper_manhattan_bound2", &area_upper_manhattan_bound2,
|
||||
"@hide" // too special
|
||||
) +
|
||||
method ("perimeter", &C::perimeter,
|
||||
"@brief Gets the perimeter of the polygon\n"
|
||||
"The perimeter is sum of the lengths of all edges making up the polygon."
|
||||
|
|
@ -1091,6 +1116,26 @@ struct polygon_defs
|
|||
return poly->area2 ();
|
||||
}
|
||||
|
||||
#if defined(HAVE_64BIT_COORD)
|
||||
// workaround for missing 128bit binding of GSI
|
||||
static double area_upper_manhattan_bound (const C *poly)
|
||||
#else
|
||||
static area_type area_upper_manhattan_bound (const C *poly)
|
||||
#endif
|
||||
{
|
||||
return poly->area_upper_manhattan_bound ();
|
||||
}
|
||||
|
||||
#if defined(HAVE_64BIT_COORD)
|
||||
// workaround for missing 128bit binding of GSI
|
||||
static double area_upper_manhattan_bound2 (const C *poly)
|
||||
#else
|
||||
static area_type area_upper_manhattan_bound2 (const C *poly)
|
||||
#endif
|
||||
{
|
||||
return poly->area_upper_manhattan_bound2 ();
|
||||
}
|
||||
|
||||
static std::vector<tl::Variant> extract_rad (const C *p)
|
||||
{
|
||||
C pnew;
|
||||
|
|
@ -1592,6 +1637,12 @@ struct polygon_defs
|
|||
"\n"
|
||||
"This method has been introduced in version 0.26.1\n"
|
||||
) +
|
||||
method_ext ("area_upper_manhattan_bound", &area_upper_manhattan_bound,
|
||||
"@hide" // too special
|
||||
) +
|
||||
method_ext ("area_upper_manhattan_bound2", &area_upper_manhattan_bound2,
|
||||
"@hide" // too special
|
||||
) +
|
||||
method ("perimeter", &C::perimeter,
|
||||
"@brief Gets the perimeter of the polygon\n"
|
||||
"The perimeter is sum of the lengths of all edges making up the polygon.\n"
|
||||
|
|
|
|||
|
|
@ -1298,7 +1298,26 @@ module DRC
|
|||
# In deep mode, polygons with a bounding box to polygon area ratio bigger than the given number
|
||||
# will be split into smaller chunks to optimize performance (which gets better if the polygon's
|
||||
# bounding boxes do not cover a lot of empty space).
|
||||
# The default threshold is 3.0 which means fairly compact polygons. Use this method with a numeric
|
||||
#
|
||||
# The area ratio is a signed value. Negative values indicate a area ratio, taking the outer
|
||||
# manhattan approximation of the polygons for the area ratio.
|
||||
# The sign of the value indicates the mode (manhattan approximation or real polygon) - the actual area
|
||||
# ratio checked is the absolute value.
|
||||
#
|
||||
# For manhattan polygons, an area ratio of -3.0 gives the same results than a positive 3.0.
|
||||
# For non-manhattan polygons, the area used for the polygon is larger than
|
||||
# the actual polygon area. So splitting is less likely in these cases. This avoids degeneration
|
||||
# of the split polygon which can otherwise happen for thin diagonal lines. These are often
|
||||
# resolved into a large number of small triangles which does not provide any benefit for
|
||||
# the algorithms.
|
||||
#
|
||||
# With a negative area ratio, triangles are equivalent to their bounding box and always
|
||||
# have an area ratio of 1.0.
|
||||
#
|
||||
# The default threshold is -3.0 which gives fairly compact polygons and using their outer
|
||||
# manhattan approximation. Skinny diagonals will be maintained.
|
||||
#
|
||||
# Use this method with a numeric
|
||||
# argument to set the value and without an argument to get the current maximum area ratio.
|
||||
# Set the value to zero to disable splitting by area ratio.
|
||||
#
|
||||
|
|
|
|||
|
|
@ -1978,3 +1978,8 @@ TEST(131d_edge_pair_interactions)
|
|||
{
|
||||
run_test (_this, "131", true);
|
||||
}
|
||||
|
||||
TEST(132d_sensitive_breaking)
|
||||
{
|
||||
run_test (_this, "132", true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1451,7 +1451,7 @@ NetTracer::determine_interactions (const db::Polygon &seed, const NetTracerShape
|
|||
{
|
||||
int area_ratio = 2;
|
||||
|
||||
db::Polygon::area_type poly_area = seed.area ();
|
||||
db::Polygon::area_type poly_area = seed.area_upper_manhattan_bound ();
|
||||
db::Polygon::area_type box_area = seed.box ().area ();
|
||||
|
||||
if (poly_area == box_area && seed.vertices () == 4) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue