Merge branch 'master' into pull_feature

This commit is contained in:
Matthias Koefferlein 2019-10-03 14:32:25 +02:00
commit 5ed41cc345
4 changed files with 119 additions and 10 deletions

View File

@ -571,7 +571,12 @@ void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Shape &shape
if (! trans.is_unity ()) { if (! trans.is_unity ()) {
poly.transform (trans); poly.transform (trans);
} }
target->insert (db::PolygonRef (poly, mp_layout->shape_repository ()));
// NOTE: as this is a specialized receiver for the purpose of building region
// representations we don't need empty polygons here
if (poly.area2 () > 0) {
target->insert (db::PolygonRef (poly, mp_layout->shape_repository ()));
}
} else if (shape.is_text () && m_text_enlargement >= 0) { } else if (shape.is_text () && m_text_enlargement >= 0) {
@ -598,12 +603,16 @@ void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Shape &shape
void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target) void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
{ {
target->insert (db::PolygonRef (db::Polygon (shape.transformed (trans)), mp_layout->shape_repository ())); if (shape.area () > 0) {
target->insert (db::PolygonRef (db::Polygon (shape.transformed (trans)), mp_layout->shape_repository ()));
}
} }
void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target) void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
{ {
target->insert (db::PolygonRef (shape.transformed (trans), mp_layout->shape_repository ())); if (shape.area2 () > 0) {
target->insert (db::PolygonRef (shape.transformed (trans), mp_layout->shape_repository ()));
}
} }
// --------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------

View File

@ -758,6 +758,16 @@ public:
* @brief The area of the contour * @brief The area of the contour
*/ */
area_type area () const area_type area () const
{
return area2 () / 2;
}
/**
* @brief The area of the contour times 2
* For integer area types, this is the more precise value as the division
* by 2 might round off.
*/
area_type area2 () const
{ {
size_type n = size (); size_type n = size ();
if (n < 3) { if (n < 3) {
@ -771,10 +781,10 @@ public:
a += db::vprod (pp - point_type (), pl - point_type ()); a += db::vprod (pp - point_type (), pl - point_type ());
pl = pp; pl = pp;
} }
return a / 2; return a;
} }
/** /**
* @brief The perimeter of the contour * @brief The perimeter of the contour
*/ */
perimeter_type perimeter () const perimeter_type perimeter () const
@ -1682,7 +1692,13 @@ public:
*/ */
double area_ratio () const double area_ratio () const
{ {
return double (box ().area ()) / double (area ()); area_type a = area2 ();
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);
}
} }
/** /**
@ -2135,7 +2151,21 @@ public:
return a; return a;
} }
/** /**
* @brief The area of the polygon times 2
* For integer area types, this is the more precise value as the division
* by 2 might round off.
*/
area_type area2 () const
{
area_type a = 0;
for (typename contour_list_type::const_iterator h = m_ctrs.begin (); h != m_ctrs.end (); ++h) {
a += h->area2 ();
}
return a;
}
/**
* @brief The perimeter of the polygon * @brief The perimeter of the polygon
*/ */
perimeter_type perimeter () const perimeter_type perimeter () const
@ -2861,7 +2891,17 @@ public:
return m_hull.area (); return m_hull.area ();
} }
/** /**
* @brief The area of the polygon times 2
* For integer area types, this is the more precise value as the division
* by 2 might round off.
*/
area_type area2 () const
{
return m_hull.area2 ();
}
/**
* @brief The perimeter of the polygon * @brief The perimeter of the polygon
*/ */
perimeter_type perimeter () const perimeter_type perimeter () const
@ -2977,7 +3017,13 @@ public:
*/ */
double area_ratio () const double area_ratio () const
{ {
return double (box ().area ()) / double (area ()); area_type a = area2 ();
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 void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self = false, void *parent = 0) const
@ -3154,7 +3200,17 @@ public:
return this->obj ().area (); return this->obj ().area ();
} }
/** /**
* @brief The area of the polygon times 2
* For integer area types, this is the more precise value as the division
* by 2 might round off.
*/
area_type area2 () const
{
return this->obj ().area2 ();
}
/**
* @brief The perimeter of the polygon * @brief The perimeter of the polygon
*/ */
perimeter_type perimeter () const perimeter_type perimeter () const

View File

@ -184,6 +184,16 @@ struct simple_polygon_defs
return poly->area (); return poly->area ();
} }
#if defined(HAVE_64BIT_COORD)
// workaround for missing 128bit binding of GSI
static double area2 (const C *poly)
#else
static area_type area2 (const C *poly)
#endif
{
return poly->area2 ();
}
static std::vector<tl::Variant> extract_rad (const C *sp) static std::vector<tl::Variant> extract_rad (const C *sp)
{ {
db::polygon<coord_type> p, pnew; db::polygon<coord_type> p, pnew;
@ -513,6 +523,13 @@ struct simple_polygon_defs
"@brief Gets the area of the polygon\n" "@brief Gets the area of the polygon\n"
"The area is correct only if the polygon is not self-overlapping and the polygon is oriented clockwise." "The area is correct only if the polygon is not self-overlapping and the polygon is oriented clockwise."
) + ) +
method_ext ("area2", &area2,
"@brief Gets the double area of the polygon\n"
"This method is provided because the area for an integer-type polygon is a multiple of 1/2. "
"Hence the double area can be expresses precisely as an integer for these types.\n"
"\n"
"This method has been introduced in version 0.26.1\n"
) +
method ("perimeter", &C::perimeter, method ("perimeter", &C::perimeter,
"@brief Gets the perimeter of the polygon\n" "@brief Gets the perimeter of the polygon\n"
"The perimeter is sum of the lengths of all edges making up the polygon." "The perimeter is sum of the lengths of all edges making up the polygon."
@ -1022,6 +1039,16 @@ struct polygon_defs
return poly->area (); return poly->area ();
} }
#if defined(HAVE_64BIT_COORD)
// workaround for missing 128bit binding of GSI
static double area2 (const C *poly)
#else
static area_type area2 (const C *poly)
#endif
{
return poly->area2 ();
}
static std::vector<tl::Variant> extract_rad (const C *p) static std::vector<tl::Variant> extract_rad (const C *p)
{ {
C pnew; C pnew;
@ -1492,6 +1519,13 @@ struct polygon_defs
"The area is correct only if the polygon is not self-overlapping and the polygon is oriented clockwise." "The area is correct only if the polygon is not self-overlapping and the polygon is oriented clockwise."
"Orientation is ensured automatically in most cases.\n" "Orientation is ensured automatically in most cases.\n"
) + ) +
method_ext ("area2", &area2,
"@brief Gets the double area of the polygon\n"
"This method is provided because the area for an integer-type polygon is a multiple of 1/2. "
"Hence the double area can be expresses precisely as an integer for these types.\n"
"\n"
"This method has been introduced in version 0.26.1\n"
) +
method ("perimeter", &C::perimeter, method ("perimeter", &C::perimeter,
"@brief Gets the perimeter of the polygon\n" "@brief Gets the perimeter of the polygon\n"
"The perimeter is sum of the lengths of all edges making up the polygon.\n" "The perimeter is sum of the lengths of all edges making up the polygon.\n"

View File

@ -79,6 +79,8 @@ TEST(1)
b = p.box (); b = p.box ();
EXPECT_EQ (p.holes (), size_t (0)); EXPECT_EQ (p.holes (), size_t (0));
EXPECT_EQ (p.area (), 1000*100); EXPECT_EQ (p.area (), 1000*100);
EXPECT_EQ (p.area2 (), 2*1000*100);
EXPECT_EQ (tl::to_string (p.area_ratio ()), "1");
EXPECT_EQ (p.perimeter (), db::Polygon::perimeter_type (2200)); EXPECT_EQ (p.perimeter (), db::Polygon::perimeter_type (2200));
EXPECT_EQ (p.is_box (), true); EXPECT_EQ (p.is_box (), true);
@ -103,6 +105,8 @@ TEST(1)
EXPECT_EQ (ip.vertices (), size_t (12)); EXPECT_EQ (ip.vertices (), size_t (12));
EXPECT_EQ (p.area (), 1000*100-2*380*80); EXPECT_EQ (p.area (), 1000*100-2*380*80);
EXPECT_EQ (p.area2 (), 2*(1000*100-2*380*80));
EXPECT_EQ (tl::to_string (p.area_ratio (), 6), "2.55102");
EXPECT_EQ (p.perimeter (), db::Polygon::perimeter_type (2000+200+4*(380+80))); EXPECT_EQ (p.perimeter (), db::Polygon::perimeter_type (2000+200+4*(380+80)));
EXPECT_EQ (p.is_box (), false); EXPECT_EQ (p.is_box (), false);
EXPECT_EQ (p.box (), b); EXPECT_EQ (p.box (), b);
@ -121,6 +125,7 @@ TEST(1)
pp.insert_hole (c2.begin (), c2.end ()); pp.insert_hole (c2.begin (), c2.end ());
pp.assign_hull (c1.begin (), c1.end ()); pp.assign_hull (c1.begin (), c1.end ());
EXPECT_EQ (pp.area (), 1000*100-2*380*80); EXPECT_EQ (pp.area (), 1000*100-2*380*80);
EXPECT_EQ (pp.area2 (), 2*(1000*100-2*380*80));
EXPECT_EQ (pp.box (), b); EXPECT_EQ (pp.box (), b);
EXPECT_EQ (p, pp); EXPECT_EQ (p, pp);
@ -163,6 +168,8 @@ TEST(2)
b = p.box (); b = p.box ();
EXPECT_EQ (p.holes (), size_t (0)); EXPECT_EQ (p.holes (), size_t (0));
EXPECT_EQ (p.area (), 1000*100); EXPECT_EQ (p.area (), 1000*100);
EXPECT_EQ (p.area2 (), 2*1000*100);
EXPECT_EQ (tl::to_string (p.area_ratio ()), "1");
EXPECT_EQ (p.perimeter (), db::SimplePolygon::perimeter_type (2000+200)); EXPECT_EQ (p.perimeter (), db::SimplePolygon::perimeter_type (2000+200));
EXPECT_EQ (p.is_box (), true); EXPECT_EQ (p.is_box (), true);
@ -460,8 +467,11 @@ TEST(5)
} }
EXPECT_EQ (p.area (), 100*1000-10*100); EXPECT_EQ (p.area (), 100*1000-10*100);
EXPECT_EQ (p.area2 (), 2*(100*1000-10*100));
EXPECT_EQ (tl::to_string (p.area_ratio (), 6), "1.0101");
EXPECT_EQ (p.perimeter (), db::Polygon::perimeter_type (200+2000+20+200)); EXPECT_EQ (p.perimeter (), db::Polygon::perimeter_type (200+2000+20+200));
EXPECT_EQ (pref.area (), 100*1000-10*100); EXPECT_EQ (pref.area (), 100*1000-10*100);
EXPECT_EQ (pref.area2 (), 2*(100*1000-10*100));
EXPECT_EQ (pref.perimeter (), db::Polygon::perimeter_type (200+2000+20+200)); EXPECT_EQ (pref.perimeter (), db::Polygon::perimeter_type (200+2000+20+200));
} }