mirror of https://github.com/KLayout/klayout.git
Tests, so bug fixes, some refactoring
This commit is contained in:
parent
c8548709bb
commit
e57d573a42
|
|
@ -46,7 +46,17 @@ AsIfFlatEdgePairs::AsIfFlatEdgePairs ()
|
|||
AsIfFlatEdgePairs::AsIfFlatEdgePairs (const AsIfFlatEdgePairs &other)
|
||||
: EdgePairsDelegate (other), m_bbox_valid (other.m_bbox_valid), m_bbox (other.m_bbox)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
operator= (other);
|
||||
}
|
||||
|
||||
AsIfFlatEdgePairs &
|
||||
AsIfFlatEdgePairs::operator= (const AsIfFlatEdgePairs &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
m_bbox_valid = other.m_bbox_valid;
|
||||
m_bbox = other.m_bbox;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
AsIfFlatEdgePairs::~AsIfFlatEdgePairs ()
|
||||
|
|
|
|||
|
|
@ -81,6 +81,8 @@ protected:
|
|||
void invalidate_bbox ();
|
||||
|
||||
private:
|
||||
friend class DeepEdgePairs;
|
||||
|
||||
AsIfFlatEdgePairs &operator= (const AsIfFlatEdgePairs &other);
|
||||
|
||||
mutable bool m_bbox_valid;
|
||||
|
|
|
|||
|
|
@ -532,4 +532,14 @@ void DeepEdgePairs::insert_into_as_polygons (Layout *layout, db::cell_index_type
|
|||
deep_layer ().insert_into_as_polygons (layout, into_cell, into_layer, enl);
|
||||
}
|
||||
|
||||
DeepEdgePairs &DeepEdgePairs::operator= (const DeepEdgePairs &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
AsIfFlatEdgePairs::operator= (other);
|
||||
DeepShapeCollectionDelegateBase::operator= (other);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -856,6 +856,9 @@ public:
|
|||
* line through the edge. If the edge is degenerated, the distance
|
||||
* is not defined.
|
||||
*
|
||||
* The distance is through as a distance of the point from the line
|
||||
* through the edge.
|
||||
*
|
||||
* @param p The point to test.
|
||||
*
|
||||
* @return The distance
|
||||
|
|
@ -877,6 +880,27 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the distance of the point from the edge.
|
||||
*
|
||||
* The distance is computed as the minimum distance of the point to any of the edge's
|
||||
* points.
|
||||
*
|
||||
* @param p The point whose distance is to be computed
|
||||
*
|
||||
* @return The distance
|
||||
*/
|
||||
distance_type euclidian_distance (const db::point<C> &p)
|
||||
{
|
||||
if (db::sprod_sign (p - p1 (), d ()) < 0) {
|
||||
return p1 ().distance (p);
|
||||
} else if (db::sprod_sign (p - p2 (), d ()) > 0) {
|
||||
return p2 ().distance (p);
|
||||
} else {
|
||||
return std::abs (distance (p));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Side of the point
|
||||
*
|
||||
|
|
|
|||
|
|
@ -204,6 +204,24 @@ public:
|
|||
return !equal (b);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Computes the distance of the edges in the edge pair
|
||||
*
|
||||
* The distance is the minimum distance of any of the points from
|
||||
* each edge.
|
||||
*/
|
||||
distance_type distance () const
|
||||
{
|
||||
db::edge<C> e1 = first (), e2 = second ();
|
||||
if (! e1.intersect (e2)) {
|
||||
distance_type d12 = std::min (e2.euclidian_distance (e1.p1 ()), e2.euclidian_distance (e1.p2 ()));
|
||||
distance_type d21 = std::min (e1.euclidian_distance (e2.p1 ()), e1.euclidian_distance (e2.p2 ()));
|
||||
return std::min (d12, d21);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A method binding of operator* (mainly for automation purposes)
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -71,28 +71,9 @@ EdgePairFilterByDistance::EdgePairFilterByDistance (distance_type min_distance,
|
|||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
static db::coord_traits<db::Coord>::distance_type
|
||||
distance_of_point_from_edge (const db::Edge &e, const db::Point &p)
|
||||
{
|
||||
if (db::sprod_sign (p - e.p1 (), e.d ()) < 0) {
|
||||
return e.p1 ().distance (p);
|
||||
} else if (db::sprod_sign (p - e.p2 (), e.d ()) > 0) {
|
||||
return e.p2 ().distance (p);
|
||||
} else {
|
||||
return e.distance (p);
|
||||
}
|
||||
}
|
||||
|
||||
bool EdgePairFilterByDistance::selected (const db::EdgePair &edge_pair) const
|
||||
{
|
||||
distance_type dist = 0;
|
||||
db::Edge e1 = edge_pair.first (), e2 = edge_pair.second ();
|
||||
if (! e1.intersect (e2)) {
|
||||
distance_type d12 = std::min (distance_of_point_from_edge (e2, e1.p1 ()), distance_of_point_from_edge (e2, e1.p2 ()));
|
||||
distance_type d21 = std::min (distance_of_point_from_edge (e1, e2.p1 ()), distance_of_point_from_edge (e1, e2.p2 ()));
|
||||
dist = std::min (d12, d21);
|
||||
}
|
||||
|
||||
distance_type dist = edge_pair.distance ();
|
||||
bool sel = (dist >= m_min_distance && dist < m_max_distance);
|
||||
return m_inverted ? !sel : sel;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -202,3 +202,17 @@ TEST(3_symmetric)
|
|||
eh.insert (db::EdgePair (e2, e1, true));
|
||||
EXPECT_EQ (int (eh.size ()), 1);
|
||||
}
|
||||
|
||||
TEST(4_distance)
|
||||
{
|
||||
db::Edge e1 (db::Point (0, 0), db::Point (0, 100));
|
||||
db::Edge e2 (db::Point (200, 100), db::Point (200, 0));
|
||||
db::Edge e3 (db::Point (0, 0), db::Point (100, 0));
|
||||
db::Edge e4 (db::Point (200, 0), db::Point (300, 0));
|
||||
db::Edge e5 (db::Point (200, 100), db::Point (300, 100));
|
||||
|
||||
EXPECT_EQ (db::EdgePair (e1, e1).distance (), 0);
|
||||
EXPECT_EQ (db::EdgePair (e1, e2).distance (), 200);
|
||||
EXPECT_EQ (db::EdgePair (e3, e2).distance (), 100);
|
||||
EXPECT_EQ (db::EdgePair (e3, e5).distance (), 141);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,6 +106,17 @@ TEST(2)
|
|||
EXPECT_EQ (db::Edge (10,20,110,222).distance_abs (db::Point (100, 200)), db::Edge::distance_type (1));
|
||||
EXPECT_EQ (db::Edge (10,20,110,222).contains (db::Point (0, 0)), false);
|
||||
EXPECT_EQ (db::Edge (10,20,110,222).contains (db::Point (100, 200)), false);
|
||||
|
||||
EXPECT_EQ (db::Edge (10,20,110,20).euclidian_distance (db::Point (100, 120)), 100);
|
||||
EXPECT_EQ (db::Edge (10,20,110,20).euclidian_distance (db::Point (100, -80)), 100);
|
||||
EXPECT_EQ (db::Edge (10,20,110,20).euclidian_distance (db::Point (-90, 120)), 141);
|
||||
EXPECT_EQ (db::Edge (10,20,110,20).euclidian_distance (db::Point (-90, -80)), 141);
|
||||
EXPECT_EQ (db::Edge (10,20,110,20).euclidian_distance (db::Point (210, 120)), 141);
|
||||
EXPECT_EQ (db::Edge (10,20,110,20).euclidian_distance (db::Point (210, -80)), 141);
|
||||
EXPECT_EQ (db::Edge (10,20,110,20).euclidian_distance (db::Point (-90, 20)), 100);
|
||||
EXPECT_EQ (db::Edge (10,20,110,20).euclidian_distance (db::Point (10, 20)), 0);
|
||||
EXPECT_EQ (db::Edge (10,20,110,20).euclidian_distance (db::Point (50, 20)), 0);
|
||||
EXPECT_EQ (db::Edge (10,20,110,20).euclidian_distance (db::Point (110, 20)), 0);
|
||||
}
|
||||
|
||||
TEST(3)
|
||||
|
|
|
|||
|
|
@ -706,12 +706,21 @@ CODE
|
|||
# version is similar to the first one, but allows specification of nil for min or
|
||||
# max indicating that there is no lower or upper limit.
|
||||
#
|
||||
# This method is available for edge and edge pair layers.
|
||||
#
|
||||
# When called on an edge pair layer, this method will select edge pairs if one
|
||||
# or both of the edges meet the length criterion. Use the additional argument
|
||||
# and pass "both" (plain word) to specify that both edges need to be within the given interval.
|
||||
# By default, it's sufficient for one edge to meet the criterion.
|
||||
#
|
||||
# Here are examples for "with_length" on edge pair layers:
|
||||
#
|
||||
# This method is available for edge and edge pair layers.
|
||||
# @code
|
||||
# # at least one edge needs to have a length of 1.0 <= l < 2.0
|
||||
# ep1 = edge_pairs.with_length(1.um .. 2.um)
|
||||
# # both edges need to have a length of exactly 2 um
|
||||
# ep2 = edge_pairs.with_length(2.um, both)
|
||||
# @/code
|
||||
|
||||
# %DRC%
|
||||
# @name without_length
|
||||
|
|
@ -725,6 +734,15 @@ CODE
|
|||
# not inside the given interval (first and third form).
|
||||
#
|
||||
# This method is available for edge and edge pair layers.
|
||||
#
|
||||
# A note on the "both" modifier (without_length called on edge pairs): "both" means that
|
||||
# both edges need to be "without_length". For example
|
||||
#
|
||||
# @code
|
||||
# # both edges are not exactly 1 um in length, or:
|
||||
# # the edge pair is skipped if one edge has a length of exactly 1 um
|
||||
# ep = edge_pairs.without_length(1.um, both)
|
||||
# @/code
|
||||
|
||||
%w(length).each do |f|
|
||||
[true, false].each do |inv|
|
||||
|
|
@ -862,6 +880,15 @@ CODE
|
|||
# either "both" (plain word) to indicate that both edges have to be within the given interval.
|
||||
# Without this argument, it is sufficient for one edge to meet the criterion.
|
||||
#
|
||||
# Here are examples for "with_angle" on edge pair layers:
|
||||
#
|
||||
# @code
|
||||
# # at least one edge needs to be horizontal
|
||||
# ep1 = edge_pairs.with_angle(0)
|
||||
# # both edges need to vertical
|
||||
# ep2 = edge_pairs.with_angle(90, both)
|
||||
# @/code
|
||||
#
|
||||
# A method delivering all objects not matching the angle criterion is \without_angle.
|
||||
#
|
||||
# The following images demonstrate some use cases of \with_angle and \without_angle:
|
||||
|
|
@ -888,6 +915,16 @@ CODE
|
|||
# The method basically is the inverse of \with_angle. It selects all edges
|
||||
# of the edge layer or corners of the polygons which do not have the given angle (second form) or whose angle
|
||||
# is not inside the given interval (first and third form).
|
||||
#
|
||||
# A note on the "both" modifier (without_angle called on edge pairs): "both" means that
|
||||
# both edges need to be "without_angle". For example
|
||||
#
|
||||
# @code
|
||||
# # both edges are not horizontal or:
|
||||
# # the edge pair is skipped if one edge is horizontal
|
||||
# ep = edge_pairs.without_angle(0, both)
|
||||
# @/code
|
||||
#
|
||||
|
||||
%w(angle).each do |f|
|
||||
[true, false].each do |inv|
|
||||
|
|
|
|||
|
|
@ -3182,6 +3182,15 @@ meeting the angle criterion. In this case an additional argument is accepted whi
|
|||
either "both" (plain word) to indicate that both edges have to be within the given interval.
|
||||
Without this argument, it is sufficient for one edge to meet the criterion.
|
||||
</p><p>
|
||||
Here are examples for "with_angle" on edge pair layers:
|
||||
</p><p>
|
||||
<pre>
|
||||
# at least one edge needs to be horizontal
|
||||
ep1 = edge_pairs.with_angle(0)
|
||||
# both edges need to vertical
|
||||
ep2 = edge_pairs.with_angle(90, both)
|
||||
</pre>
|
||||
</p><p>
|
||||
A method delivering all objects not matching the angle criterion is <a href="#without_angle">without_angle</a>.
|
||||
</p><p>
|
||||
The following images demonstrate some use cases of <a href="#with_angle">with_angle</a> and <a href="#without_angle:">without_angle:</a>
|
||||
|
|
@ -3424,12 +3433,21 @@ The second version selects edges with exactly the given length. The third
|
|||
version is similar to the first one, but allows specification of nil for min or
|
||||
max indicating that there is no lower or upper limit.
|
||||
</p><p>
|
||||
This method is available for edge and edge pair layers.
|
||||
</p><p>
|
||||
When called on an edge pair layer, this method will select edge pairs if one
|
||||
or both of the edges meet the length criterion. Use the additional argument
|
||||
and pass "both" (plain word) to specify that both edges need to be within the given interval.
|
||||
By default, it's sufficient for one edge to meet the criterion.
|
||||
</p><p>
|
||||
This method is available for edge and edge pair layers.
|
||||
Here are examples for "with_length" on edge pair layers:
|
||||
</p><p>
|
||||
<pre>
|
||||
# at least one edge needs to have a length of 1.0 <= l < 2.0
|
||||
ep1 = edge_pairs.with_length(1.um .. 2.um)
|
||||
# both edges need to have a length of exactly 2 um
|
||||
ep2 = edge_pairs.with_length(2.um, both)
|
||||
</pre>
|
||||
</p>
|
||||
<a name="with_perimeter"/><h2>"with_perimeter" - Selects polygons by perimeter</h2>
|
||||
<keyword name="with_perimeter"/>
|
||||
|
|
@ -3480,6 +3498,15 @@ This method is available for polygon layers only.
|
|||
The method basically is the inverse of <a href="#with_angle">with_angle</a>. It selects all edges
|
||||
of the edge layer or corners of the polygons which do not have the given angle (second form) or whose angle
|
||||
is not inside the given interval (first and third form).
|
||||
</p><p>
|
||||
A note on the "both" modifier (without_angle called on edge pairs): "both" means that
|
||||
both edges need to be "without_angle". For example
|
||||
</p><p>
|
||||
<pre>
|
||||
# both edges are not horizontal or:
|
||||
# the edge pair is skipped if one edge is horizontal
|
||||
ep = edge_pairs.without_angle(0, both)
|
||||
</pre>
|
||||
</p>
|
||||
<a name="without_area"/><h2>"without_area" - Selects polygons by area</h2>
|
||||
<keyword name="without_area"/>
|
||||
|
|
@ -3622,6 +3649,15 @@ of the edge layer which do not have the given length (second form) or are
|
|||
not inside the given interval (first and third form).
|
||||
</p><p>
|
||||
This method is available for edge and edge pair layers.
|
||||
</p><p>
|
||||
A note on the "both" modifier (without_length called on edge pairs): "both" means that
|
||||
both edges need to be "without_length". For example
|
||||
</p><p>
|
||||
<pre>
|
||||
# both edges are not exactly 1 um in length, or:
|
||||
# the edge pair is skipped if one edge has a length of exactly 1 um
|
||||
ep = edge_pairs.without_length(1.um, both)
|
||||
</pre>
|
||||
</p>
|
||||
<a name="without_perimeter"/><h2>"without_perimeter" - Selects polygons by perimeter</h2>
|
||||
<keyword name="without_perimeter"/>
|
||||
|
|
|
|||
Loading…
Reference in New Issue