mirror of https://github.com/KLayout/klayout.git
Major enhancements for DRC feature (universal DRC)
Main issue: universal DRC scheme and rectangle filtering/opposite filtering/shielding. The space function required some enhancements to accomodate symmetric interactions. Now there are symmetric edge pairs. Space initially runs twofold (primary to foreign) but produces symmetric edge pairs. These are filtered later unless converted before.
This commit is contained in:
parent
fd90e66ee1
commit
9cf0a9e659
|
|
@ -1257,7 +1257,7 @@ AsIfFlatRegion::run_single_polygon_check (db::edge_relation_type rel, db::Coord
|
|||
check.set_min_projection (options.min_projection);
|
||||
check.set_max_projection (options.max_projection);
|
||||
|
||||
edge2edge_check_negative_or_positive<db::FlatEdgePairs> edge_check (check, *result, options.negative, false /*=same polygons*/, false /*=same layers*/, options.shielded);
|
||||
edge2edge_check_negative_or_positive<db::FlatEdgePairs> edge_check (check, *result, options.negative, false /*=same polygons*/, false /*=same layers*/, options.shielded, true /*symmetric edge pairs*/);
|
||||
poly2poly_check<db::Polygon> poly_check (edge_check);
|
||||
|
||||
do {
|
||||
|
|
|
|||
|
|
@ -1494,7 +1494,7 @@ DeepRegion::run_single_polygon_check (db::edge_relation_type rel, db::Coord d, c
|
|||
|
||||
for (db::Shapes::shape_iterator s = shapes.begin (db::ShapeIterator::Polygons); ! s.at_end (); ++s) {
|
||||
|
||||
edge2edge_check_negative_or_positive<db::Shapes> edge_check (check, result, options.negative, false, false, options.shielded);
|
||||
edge2edge_check_negative_or_positive<db::Shapes> edge_check (check, result, options.negative, false /*does not require different polygons*/, false /*does not require different layers*/, options.shielded, true /*symmetric edge pairs*/);
|
||||
poly2poly_check<db::Polygon> poly_check (edge_check);
|
||||
|
||||
db::Polygon poly;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,16 @@
|
|||
|
||||
namespace db {
|
||||
|
||||
/**
|
||||
* @brief A pair of edges
|
||||
*
|
||||
* An edge pair is a pair of edges which usually is used to mark a DRC violation. It flags the relationship of two edges.
|
||||
* It's a compoisition of two edges: first and second.
|
||||
*
|
||||
* By default, an edge pair is directed: first and second are not commutable and indicate a relationship ("from first towards second").
|
||||
* The edge pair carries a flag which allows indicating symmetric mode: in this mode, the first and second edge are commutable.
|
||||
* As a consequence, when the symmetric flag is used, edge_pair(e1, e2, true) == edge_pair(e2, e1, true).
|
||||
*/
|
||||
template <class C>
|
||||
class DB_PUBLIC_TEMPLATE edge_pair
|
||||
{
|
||||
|
|
@ -61,7 +71,7 @@ public:
|
|||
* The default constructor creates an edge pair with two default edges.
|
||||
*/
|
||||
edge_pair ()
|
||||
: m_first (), m_second ()
|
||||
: m_first (), m_second (), m_symmetric (false)
|
||||
{
|
||||
// .. nothing else ..
|
||||
}
|
||||
|
|
@ -71,10 +81,11 @@ public:
|
|||
*
|
||||
* @param first The first edge
|
||||
* @param second The second edge
|
||||
* @param symmetric True, if the edge pair is symmetric
|
||||
*/
|
||||
template <class D>
|
||||
edge_pair (const db::edge<D> &first, const db::edge<D> &second)
|
||||
: m_first (first), m_second (second)
|
||||
edge_pair (const db::edge<D> &first, const db::edge<D> &second, bool symmetric = false)
|
||||
: m_first (first), m_second (second), m_symmetric (symmetric)
|
||||
{
|
||||
// .. nothing else ..
|
||||
}
|
||||
|
|
@ -84,11 +95,27 @@ public:
|
|||
*/
|
||||
template <class D>
|
||||
edge_pair (const edge_pair<D> &e)
|
||||
: m_first (e.first ()), m_second (e.second ())
|
||||
: m_first (e.first ()), m_second (e.second ()), m_symmetric (e.is_symmetric ())
|
||||
{
|
||||
// .. nothing else ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the symmetric flag
|
||||
*/
|
||||
bool is_symmetric () const
|
||||
{
|
||||
return m_symmetric;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the symmetric flag
|
||||
*/
|
||||
void set_symmetric (bool s)
|
||||
{
|
||||
m_symmetric = s;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The (dummy) translation operator
|
||||
*/
|
||||
|
|
@ -112,7 +139,15 @@ public:
|
|||
*/
|
||||
bool operator< (const edge_pair<C> &b) const
|
||||
{
|
||||
return m_first < b.m_first || (m_first == b.m_first && m_second < b.m_second);
|
||||
if (m_symmetric != b.m_symmetric) {
|
||||
return m_symmetric < b.m_symmetric;
|
||||
}
|
||||
|
||||
const edge_type &l = lesser ();
|
||||
const edge_type &g = greater ();
|
||||
const edge_type &bl = b.lesser ();
|
||||
const edge_type &bg = b.greater ();
|
||||
return l < bl || (l == bl && g < bg);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -120,7 +155,10 @@ public:
|
|||
*/
|
||||
bool operator== (const edge_pair<C> &b) const
|
||||
{
|
||||
return m_first == b.m_first && m_second == b.m_second;
|
||||
if (m_symmetric != b.m_symmetric) {
|
||||
return false;
|
||||
}
|
||||
return lesser () == b.lesser () && greater () == b.greater ();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -136,7 +174,15 @@ public:
|
|||
*/
|
||||
bool less (const edge_pair<C> &b) const
|
||||
{
|
||||
return m_first.less (b.m_first) || (m_first.equal (b.m_first) && m_second.less (b.m_second));
|
||||
if (m_symmetric != b.m_symmetric) {
|
||||
return m_symmetric < b.m_symmetric;
|
||||
}
|
||||
|
||||
const edge_type &l = lesser ();
|
||||
const edge_type &g = greater ();
|
||||
const edge_type &bl = b.lesser ();
|
||||
const edge_type &bg = b.greater ();
|
||||
return l.less (bl) || (l.equal (bl) && g.less (bg));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -144,7 +190,10 @@ public:
|
|||
*/
|
||||
bool equal (const edge_pair<C> &b) const
|
||||
{
|
||||
return m_first.equal (b.m_first) && m_second.equal (b.m_second);
|
||||
if (m_symmetric != b.m_symmetric) {
|
||||
return false;
|
||||
}
|
||||
return lesser ().equal (b.lesser ()) && greater ().equal (b.greater ());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -160,7 +209,7 @@ public:
|
|||
*/
|
||||
edge_pair<C> scaled (double s) const
|
||||
{
|
||||
return edge_pair<C> (edge_type (first () * s), edge_type (second () * s));
|
||||
return edge_pair<C> (edge_type (first () * s), edge_type (second () * s), m_symmetric);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -193,7 +242,7 @@ public:
|
|||
template <class Tr>
|
||||
edge_pair<C> &transform (const Tr &t)
|
||||
{
|
||||
*this = edge_pair<C> (t * m_first, t * m_second);
|
||||
*this = edge_pair<C> (t * m_first, t * m_second, m_symmetric);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -210,7 +259,7 @@ public:
|
|||
template <class Tr>
|
||||
edge_pair<typename Tr::target_coord_type> transformed (const Tr &t) const
|
||||
{
|
||||
return edge_pair<typename Tr::target_coord_type> (t * m_first, t * m_second);
|
||||
return edge_pair<typename Tr::target_coord_type> (t * m_first, t * m_second, m_symmetric);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -278,6 +327,32 @@ public:
|
|||
return m_second;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The "lesser" edge.
|
||||
* This feature is used for comparing symmetric edge pairs.
|
||||
*/
|
||||
const edge_type &lesser () const
|
||||
{
|
||||
if (m_symmetric) {
|
||||
return m_first < m_second ? m_first : m_second;
|
||||
} else {
|
||||
return m_first;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The "greater" edge.
|
||||
* This feature is used for comparing symmetric edge pairs.
|
||||
*/
|
||||
const edge_type &greater () const
|
||||
{
|
||||
if (m_symmetric) {
|
||||
return m_second < m_first ? m_first : m_second;
|
||||
} else {
|
||||
return m_second;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief returns the bounding box
|
||||
*/
|
||||
|
|
@ -310,7 +385,7 @@ public:
|
|||
*/
|
||||
std::string to_string (double dbu) const
|
||||
{
|
||||
return m_first.to_string (dbu) + "/" + m_second.to_string (dbu);
|
||||
return lesser ().to_string (dbu) + (m_symmetric ? "|" : "/") + greater ().to_string (dbu);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -466,6 +541,7 @@ public:
|
|||
|
||||
private:
|
||||
edge_type m_first, m_second;
|
||||
bool m_symmetric;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -89,6 +89,9 @@ public:
|
|||
void process(const EdgePair &ep, std::vector<db::Edge> &res) const
|
||||
{
|
||||
res.push_back (ep.first ());
|
||||
if (ep.is_symmetric ()) {
|
||||
res.push_back (ep.second ());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -102,7 +105,9 @@ public:
|
|||
|
||||
void process(const EdgePair &ep, std::vector<db::Edge> &res) const
|
||||
{
|
||||
res.push_back (ep.second ());
|
||||
if (! ep.is_symmetric ()) {
|
||||
res.push_back (ep.second ());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ namespace std
|
|||
{
|
||||
size_t operator() (const db::edge_pair<C> &o) const
|
||||
{
|
||||
return hfunc (o.first (), hfunc (o.second ()));
|
||||
return hfunc (o.lesser (), hfunc (o.greater (), hfunc (int (o.is_symmetric ()))));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -723,10 +723,12 @@ shape_interactions<TS, TI>::intruder_shape (unsigned int id) const
|
|||
// explicit instantiations
|
||||
template class DB_PUBLIC shape_interactions<db::Polygon, db::Polygon>;
|
||||
template class DB_PUBLIC shape_interactions<db::Polygon, db::Text>;
|
||||
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::Edge>;
|
||||
template class DB_PUBLIC shape_interactions<db::Polygon, db::TextRef>;
|
||||
template class DB_PUBLIC shape_interactions<db::Polygon, db::Edge>;
|
||||
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::TextRef>;
|
||||
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::Text>;
|
||||
template class DB_PUBLIC shape_interactions<db::PolygonRef, db::Edge>;
|
||||
template class DB_PUBLIC shape_interactions<db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC shape_interactions<db::Edge, db::PolygonRef>;
|
||||
template class DB_PUBLIC shape_interactions<db::TextRef, db::TextRef>;
|
||||
|
|
|
|||
|
|
@ -89,17 +89,27 @@ void local_operation<TS, TI, TR>::compute_local (db::Layout *layout, const shape
|
|||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC local_operation<db::Polygon, db::Polygon, db::Polygon>;
|
||||
template class DB_PUBLIC local_operation<db::Polygon, db::Polygon, db::Edge>;
|
||||
template class DB_PUBLIC local_operation<db::Polygon, db::Text, db::Polygon>;
|
||||
template class DB_PUBLIC local_operation<db::Polygon, db::Text, db::Text>;
|
||||
template class DB_PUBLIC local_operation<db::Polygon, db::Edge, db::Polygon>;
|
||||
template class DB_PUBLIC local_operation<db::Polygon, db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_operation<db::PolygonRef, db::Text, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_operation<db::PolygonRef, db::TextRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_operation<db::PolygonRef, db::TextRef, db::TextRef>;
|
||||
template class DB_PUBLIC local_operation<db::PolygonRef, db::Edge, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_operation<db::PolygonRef, db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC local_operation<db::PolygonRef, db::PolygonRef, db::EdgePair>;
|
||||
template class DB_PUBLIC local_operation<db::PolygonRef, db::PolygonRef, db::Edge>;
|
||||
template class DB_PUBLIC local_operation<db::Polygon, db::Polygon, db::EdgePair>;
|
||||
template class DB_PUBLIC local_operation<db::Polygon, db::TextRef, db::TextRef>;
|
||||
template class DB_PUBLIC local_operation<db::Edge, db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC local_operation<db::Edge, db::PolygonRef, db::Edge>;
|
||||
template class DB_PUBLIC local_operation<db::Edge, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_operation<db::Edge, db::Edge, db::EdgePair>;
|
||||
template class DB_PUBLIC local_operation<db::TextRef, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_operation<db::TextRef, db::PolygonRef, db::TextRef>;
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// BoolAndOrNotLocalOperation implementation
|
||||
|
|
|
|||
|
|
@ -202,7 +202,10 @@ check_local_operation<TS, TI>::do_compute_local (db::Layout *layout, const shape
|
|||
tl_assert (results.size () == 1);
|
||||
std::unordered_set<db::EdgePair> result, intra_polygon_result;
|
||||
|
||||
edge2edge_check_negative_or_positive<std::unordered_set<db::EdgePair> > edge_check (m_check, result, intra_polygon_result, m_options.negative, m_different_polygons, m_has_other, m_options.shielded);
|
||||
// NOTE: the rectangle and opposite filters are unsymmetric
|
||||
bool symmetric_edge_pairs = ! m_has_other && m_options.opposite_filter == db::NoOppositeFilter && m_options.rect_filter == RectFilter::NoSideAllowed;
|
||||
|
||||
edge2edge_check_negative_or_positive<std::unordered_set<db::EdgePair> > edge_check (m_check, result, intra_polygon_result, m_options.negative, m_different_polygons, m_has_other, m_options.shielded, symmetric_edge_pairs);
|
||||
poly2poly_check<TS> poly_check (edge_check);
|
||||
|
||||
std::list<TS> heap;
|
||||
|
|
@ -302,7 +305,6 @@ check_local_operation<TS, TI>::do_compute_local (db::Layout *layout, const shape
|
|||
scanner.process (poly_check, m_check.distance (), db::box_convert<TS> ());
|
||||
} while (edge_check.prepare_next_pass ());
|
||||
|
||||
|
||||
// detect and remove parts of the result which have or do not have results "opposite"
|
||||
// ("opposite" is defined by the projection of edges "through" the subject shape)
|
||||
if (m_options.opposite_filter != db::NoOppositeFilter && (! result.empty () || ! intra_polygon_result.empty ())) {
|
||||
|
|
@ -313,6 +315,8 @@ check_local_operation<TS, TI>::do_compute_local (db::Layout *layout, const shape
|
|||
|
||||
if (m_has_other) {
|
||||
|
||||
tl_assert (intra_polygon_result.empty ());
|
||||
|
||||
// filter out opposite edges: this is the case of two-layer checks where we can maintain the edge pairs but
|
||||
// strip them of the filtered-out part.
|
||||
|
||||
|
|
|
|||
|
|
@ -32,9 +32,14 @@ namespace db
|
|||
// -------------------------------------------------------------------------------------
|
||||
// Edge2EdgeCheckBase implementation
|
||||
|
||||
Edge2EdgeCheckBase::Edge2EdgeCheckBase (const EdgeRelationFilter &check, bool different_polygons, bool requires_different_layers, bool with_shielding)
|
||||
Edge2EdgeCheckBase::Edge2EdgeCheckBase (const EdgeRelationFilter &check, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric_edges)
|
||||
: mp_check (&check), m_requires_different_layers (requires_different_layers), m_different_polygons (different_polygons),
|
||||
m_first_pseudo (std::numeric_limits<size_t>::max ()), m_with_shielding (with_shielding), m_has_edge_pair_output (true), m_has_negative_edge_output (false), m_pass (0)
|
||||
m_first_pseudo (std::numeric_limits<size_t>::max ()),
|
||||
m_with_shielding (with_shielding),
|
||||
m_symmetric_edges (symmetric_edges),
|
||||
m_has_edge_pair_output (true),
|
||||
m_has_negative_edge_output (false),
|
||||
m_pass (0)
|
||||
{
|
||||
m_distance = check.distance ();
|
||||
}
|
||||
|
|
@ -159,13 +164,42 @@ Edge2EdgeCheckBase::feed_pseudo_edges (db::box_scanner<db::Edge, size_t> &scanne
|
|||
}
|
||||
}
|
||||
|
||||
inline bool edges_considered (bool requires_different_polygons, bool requires_different_layers, size_t p1, size_t p2)
|
||||
{
|
||||
if (p1 == p2) {
|
||||
if (requires_different_polygons) {
|
||||
return false;
|
||||
} else if ((p1 & size_t (1)) != 0) {
|
||||
// edges from the same polygon are only considered on first layer.
|
||||
// Reasoning: this case happens when "intruder" polygons are put on layer 1
|
||||
// while "subject" polygons are put on layer 0. We don't want "intruders"
|
||||
// to generate intra-polygon markers.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (((p1 ^ p2) & size_t (1)) == 0) {
|
||||
if (requires_different_layers) {
|
||||
return false;
|
||||
} else if ((p1 & size_t (1)) != 0) {
|
||||
// edges on the same layer are only considered on first layer.
|
||||
// Reasoning: this case happens when "intruder" polygons are put on layer 1
|
||||
// while "subject" polygons are put on layer 0. We don't want "intruders"
|
||||
// to generate inter-polygon markers between them.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Edge2EdgeCheckBase::add (const db::Edge *o1, size_t p1, const db::Edge *o2, size_t p2)
|
||||
{
|
||||
if (m_pass == 0) {
|
||||
|
||||
// Overlap or inside checks require input from different layers
|
||||
if ((! m_different_polygons || p1 != p2) && (! m_requires_different_layers || ((p1 ^ p2) & 1) != 0)) {
|
||||
if (edges_considered (m_different_polygons, m_requires_different_layers, p1, p2)) {
|
||||
|
||||
// ensure that the first check argument is of layer 1 and the second of
|
||||
// layer 2 (unless both are of the same layer)
|
||||
|
|
@ -180,6 +214,8 @@ Edge2EdgeCheckBase::add (const db::Edge *o1, size_t p1, const db::Edge *o2, size
|
|||
db::EdgePair ep;
|
||||
if (mp_check->check (*o1, *o2, &ep)) {
|
||||
|
||||
ep.set_symmetric (m_symmetric_edges);
|
||||
|
||||
// found a violation: store inside the local buffer for now. In the second
|
||||
// pass we will eliminate those which are shielded completely (with shielding)
|
||||
// and/or compute the negative edges.
|
||||
|
|
@ -266,7 +302,7 @@ Edge2EdgeCheckBase::add (const db::Edge *o1, size_t p1, const db::Edge *o2, size
|
|||
(m_pseudo_edges.find (std::make_pair (*o1, p1)) != m_pseudo_edges.end ()) != (m_pseudo_edges.find (std::make_pair (*o2, p2)) != m_pseudo_edges.end ())) {
|
||||
|
||||
// Overlap or inside checks require input from different layers
|
||||
if ((! m_different_polygons || p1 != p2) && (! m_requires_different_layers || ((p1 ^ p2) & 1) != 0)) {
|
||||
if (edges_considered (m_different_polygons, m_requires_different_layers, p1, p2)) {
|
||||
|
||||
// ensure that the first check argument is of layer 1 and the second of
|
||||
// layer 2 (unless both are of the same layer)
|
||||
|
|
@ -756,7 +792,7 @@ SinglePolygonCheck::process (const db::Polygon &polygon, std::vector<db::EdgePai
|
|||
check.set_min_projection (m_options.min_projection);
|
||||
check.set_max_projection (m_options.max_projection);
|
||||
|
||||
edge2edge_check_negative_or_positive <std::unordered_set<db::EdgePair> > edge_check (check, result, m_options.negative, false /*=same polygons*/, false /*=same layers*/, m_options.shielded);
|
||||
edge2edge_check_negative_or_positive <std::unordered_set<db::EdgePair> > edge_check (check, result, m_options.negative, false /*=same polygons*/, false /*=same layers*/, m_options.shielded, true /*=symmetric*/);
|
||||
poly2poly_check<db::Polygon> poly_check (edge_check);
|
||||
|
||||
do {
|
||||
|
|
|
|||
|
|
@ -544,7 +544,7 @@ class DB_PUBLIC Edge2EdgeCheckBase
|
|||
: public db::box_scanner_receiver<db::Edge, size_t>
|
||||
{
|
||||
public:
|
||||
Edge2EdgeCheckBase (const EdgeRelationFilter &check, bool different_polygons, bool requires_different_layers, bool with_shielding);
|
||||
Edge2EdgeCheckBase (const EdgeRelationFilter &check, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric_edges);
|
||||
|
||||
/**
|
||||
* @brief Call this to initiate a new pass until the return value is false
|
||||
|
|
@ -630,6 +630,7 @@ private:
|
|||
size_t m_first_pseudo;
|
||||
std::vector<bool> m_ep_discarded, m_ep_intra_polygon;
|
||||
bool m_with_shielding;
|
||||
bool m_symmetric_edges;
|
||||
bool m_has_edge_pair_output;
|
||||
bool m_has_negative_edge_output;
|
||||
unsigned int m_pass;
|
||||
|
|
@ -645,14 +646,14 @@ class DB_PUBLIC_TEMPLATE edge2edge_check
|
|||
: public Edge2EdgeCheckBase
|
||||
{
|
||||
public:
|
||||
edge2edge_check (const EdgeRelationFilter &check, Output &output, bool different_polygons, bool requires_different_layers, bool with_shielding)
|
||||
: Edge2EdgeCheckBase (check, different_polygons, requires_different_layers, with_shielding), mp_output_inter (&output), mp_output_intra (0)
|
||||
edge2edge_check (const EdgeRelationFilter &check, Output &output, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric_edges)
|
||||
: Edge2EdgeCheckBase (check, different_polygons, requires_different_layers, with_shielding, symmetric_edges), mp_output_inter (&output), mp_output_intra (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
edge2edge_check (const EdgeRelationFilter &check, Output &output_inter, Output &output_intra, bool different_polygons, bool requires_different_layers, bool with_shielding)
|
||||
: Edge2EdgeCheckBase (check, different_polygons, requires_different_layers, with_shielding), mp_output_inter (&output_inter), mp_output_intra (&output_intra)
|
||||
edge2edge_check (const EdgeRelationFilter &check, Output &output_inter, Output &output_intra, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric_edges)
|
||||
: Edge2EdgeCheckBase (check, different_polygons, requires_different_layers, with_shielding, symmetric_edges), mp_output_inter (&output_inter), mp_output_intra (&output_intra)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -683,16 +684,16 @@ class DB_PUBLIC_TEMPLATE edge2edge_check_with_negative_output
|
|||
: public edge2edge_check<Output>
|
||||
{
|
||||
public:
|
||||
edge2edge_check_with_negative_output (const EdgeRelationFilter &check, Output &output, NegativeEdgeOutput &l1_negative_output, NegativeEdgeOutput &l2_negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding)
|
||||
: edge2edge_check<Output> (check, output, different_polygons, requires_different_layers, with_shielding),
|
||||
edge2edge_check_with_negative_output (const EdgeRelationFilter &check, Output &output, NegativeEdgeOutput &l1_negative_output, NegativeEdgeOutput &l2_negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric_edges)
|
||||
: edge2edge_check<Output> (check, output, different_polygons, requires_different_layers, with_shielding, symmetric_edges),
|
||||
mp_l1_negative_output (&l1_negative_output),
|
||||
mp_l2_negative_output (&l2_negative_output)
|
||||
{
|
||||
edge2edge_check<Output>::set_has_negative_edge_output (true);
|
||||
}
|
||||
|
||||
edge2edge_check_with_negative_output (const EdgeRelationFilter &check, Output &output_inter, Output &output_intra, NegativeEdgeOutput &l1_negative_output, NegativeEdgeOutput &l2_negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding)
|
||||
: edge2edge_check<Output> (check, output_inter, output_intra, different_polygons, requires_different_layers, with_shielding),
|
||||
edge2edge_check_with_negative_output (const EdgeRelationFilter &check, Output &output_inter, Output &output_intra, NegativeEdgeOutput &l1_negative_output, NegativeEdgeOutput &l2_negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric_edges)
|
||||
: edge2edge_check<Output> (check, output_inter, output_intra, different_polygons, requires_different_layers, with_shielding, symmetric_edges),
|
||||
mp_l1_negative_output (&l1_negative_output),
|
||||
mp_l2_negative_output (&l2_negative_output)
|
||||
{
|
||||
|
|
@ -726,7 +727,7 @@ class DB_PUBLIC_TEMPLATE edge2edge_check_negative
|
|||
{
|
||||
public:
|
||||
edge2edge_check_negative (const EdgeRelationFilter &check, NegativeEdgeOutput &l1_negative_output, NegativeEdgeOutput &l2_negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding)
|
||||
: Edge2EdgeCheckBase (check, different_polygons, requires_different_layers, with_shielding),
|
||||
: Edge2EdgeCheckBase (check, different_polygons, requires_different_layers, with_shielding, false),
|
||||
mp_l1_negative_output (&l1_negative_output),
|
||||
mp_l2_negative_output (&l2_negative_output)
|
||||
{
|
||||
|
|
@ -761,15 +762,15 @@ class DB_PUBLIC_TEMPLATE edge2edge_check_negative_or_positive
|
|||
: public edge2edge_check<Output>
|
||||
{
|
||||
public:
|
||||
edge2edge_check_negative_or_positive (const EdgeRelationFilter &check, Output &output, bool negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding)
|
||||
: edge2edge_check<Output> (check, output, different_polygons, requires_different_layers, with_shielding)
|
||||
edge2edge_check_negative_or_positive (const EdgeRelationFilter &check, Output &output, bool negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric)
|
||||
: edge2edge_check<Output> (check, output, different_polygons, requires_different_layers, with_shielding, symmetric)
|
||||
{
|
||||
edge2edge_check<Output>::set_has_negative_edge_output (negative_output);
|
||||
edge2edge_check<Output>::set_has_edge_pair_output (! negative_output);
|
||||
}
|
||||
|
||||
edge2edge_check_negative_or_positive (const EdgeRelationFilter &check, Output &output_inter, Output &output_intra, bool negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding)
|
||||
: edge2edge_check<Output> (check, output_inter, output_intra, different_polygons, requires_different_layers, with_shielding)
|
||||
edge2edge_check_negative_or_positive (const EdgeRelationFilter &check, Output &output_inter, Output &output_intra, bool negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding, bool symmetric)
|
||||
: edge2edge_check<Output> (check, output_inter, output_intra, different_polygons, requires_different_layers, with_shielding, symmetric)
|
||||
{
|
||||
edge2edge_check<Output>::set_has_negative_edge_output (negative_output);
|
||||
edge2edge_check<Output>::set_has_edge_pair_output (! negative_output);
|
||||
|
|
|
|||
|
|
@ -54,9 +54,9 @@ struct edge_pair_defs
|
|||
return new C ();
|
||||
}
|
||||
|
||||
static C *new_ee (const edge_type &first, const edge_type &second)
|
||||
static C *new_ee (const edge_type &first, const edge_type &second, bool symmetric)
|
||||
{
|
||||
return new C (first, second);
|
||||
return new C (first, second, symmetric);
|
||||
}
|
||||
|
||||
static size_t hash_value (const C *ep)
|
||||
|
|
@ -72,10 +72,11 @@ struct edge_pair_defs
|
|||
"\n"
|
||||
"This constructor creates an default edge pair.\n"
|
||||
) +
|
||||
constructor ("new", &new_ee,
|
||||
constructor ("new", &new_ee, gsi::arg ("first"), gsi::arg ("second"), gsi::arg ("symmetric", false),
|
||||
"@brief Constructor from two edges\n"
|
||||
"\n"
|
||||
"This constructor creates an edge pair from the two edges given.\n"
|
||||
"See \\symmetric? for a description of this attribute."
|
||||
) +
|
||||
method ("first", (const edge_type &(C::*) () const) &C::first,
|
||||
"@brief Gets the first edge\n"
|
||||
|
|
@ -89,7 +90,34 @@ struct edge_pair_defs
|
|||
method ("second=", &C::set_second, gsi::arg ("edge"),
|
||||
"@brief Sets the second edge\n"
|
||||
) +
|
||||
method ("normalized", &C::normalized,
|
||||
method ("symmetric?", &C::is_symmetric,
|
||||
"@brief Returns a value indicating whether the edge pair is symmetric\n"
|
||||
"For symmetric edge pairs, the edges are commutable. Specifically, a symmetric edge pair with (e1,e2) is identical to (e2,e1). "
|
||||
"Symmetric edge pairs are generated by some checks for which there is no directed error marker (width, space, notch, isolated).\n"
|
||||
"\n"
|
||||
"Symmetric edge pairs have been introduced in version 0.27.\n"
|
||||
) +
|
||||
method ("symmetric=", &C::set_symmetric,
|
||||
"@brief Sets a value indicating whether the edge pair is symmetric\n"
|
||||
"See \\symmetric? for a description of this attribute.\n"
|
||||
"\n"
|
||||
"Symmetric edge pairs have been introduced in version 0.27.\n"
|
||||
) +
|
||||
method ("lesser", (const edge_type &(C::*) () const) &C::lesser,
|
||||
"@brief Gets the 'lesser' edge for symmetric edge pairs\n"
|
||||
"As first and second edges are commutable for symmetric edge pairs (see \\symmetric?), this accessor allows "
|
||||
"retrieving a 'first' edge in a way independent on the actual assignment.\n"
|
||||
"\n"
|
||||
"This read-only attribute has been introduced in version 0.27.\n"
|
||||
) +
|
||||
method ("greater", (const edge_type &(C::*) () const) &C::greater,
|
||||
"@brief Gets the 'greater' edge for symmetric edge pairs\n"
|
||||
"As first and second edges are commutable for symmetric edge pairs (see \\symmetric?), this accessor allows "
|
||||
"retrieving a 'second' edge in a way independent on the actual assignment.\n"
|
||||
"\n"
|
||||
"This read-only attribute has been introduced in version 0.27.\n"
|
||||
) +
|
||||
method ("normalized", &C::normalized,
|
||||
"@brief Normalizes the edge pair\n"
|
||||
"This method normalized the edge pair such that when connecting the edges at their \n"
|
||||
"start and end points a closed loop is formed which is oriented clockwise. To "
|
||||
|
|
|
|||
|
|
@ -23,8 +23,12 @@
|
|||
|
||||
|
||||
#include "dbEdgePair.h"
|
||||
#include "dbHash.h"
|
||||
#include "tlUnitTest.h"
|
||||
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
|
||||
TEST(1)
|
||||
{
|
||||
db::EdgePair ep;
|
||||
|
|
@ -147,3 +151,56 @@ TEST(2)
|
|||
EXPECT_EQ (ep.normalized ().to_polygon (1).to_string (), "(1,-1;-1,19;-1,31;1,11)");
|
||||
}
|
||||
|
||||
TEST(3_symmetric)
|
||||
{
|
||||
db::Edge e1 (db::Point (0, 0), db::Point (0, 100));
|
||||
db::Edge e2 (db::Point (200, 100), db::Point (200, 0));
|
||||
|
||||
EXPECT_EQ (db::EdgePair (e1, e2, false) == db::EdgePair (e1, e2, false), true);
|
||||
EXPECT_EQ (db::EdgePair (e1, e2, false) == db::EdgePair (e2, e1, false), false);
|
||||
EXPECT_EQ (db::EdgePair (e1, e2, true) == db::EdgePair (e1, e2, false), false);
|
||||
EXPECT_EQ (db::EdgePair (e1, e2, true) == db::EdgePair (e1, e2, true), true);
|
||||
EXPECT_EQ (db::EdgePair (e1, e2, true) == db::EdgePair (e2, e1, true), true);
|
||||
|
||||
EXPECT_EQ (db::EdgePair (e1, e2, false) < db::EdgePair (e1, e2, false), false);
|
||||
EXPECT_EQ (db::EdgePair (e1, e2, false) < db::EdgePair (e2, e1, false), true);
|
||||
EXPECT_EQ (db::EdgePair (e2, e1, false) < db::EdgePair (e2, e1, false), false);
|
||||
EXPECT_EQ (db::EdgePair (e1, e2, false) < db::EdgePair (e1, e2, true), true);
|
||||
EXPECT_EQ (db::EdgePair (e1, e2, true) < db::EdgePair (e1, e2, false), false);
|
||||
EXPECT_EQ (db::EdgePair (e1, e2, true) < db::EdgePair (e1, e2, true), false);
|
||||
EXPECT_EQ (db::EdgePair (e1, e2, true) < db::EdgePair (e2, e1, true), false);
|
||||
|
||||
std::set<db::EdgePair> es;
|
||||
|
||||
es.clear ();
|
||||
es.insert (db::EdgePair (e1, e2, false));
|
||||
es.insert (db::EdgePair (e1, e2, true));
|
||||
EXPECT_EQ (int (es.size ()), 2);
|
||||
|
||||
es.clear ();
|
||||
es.insert (db::EdgePair (e1, e2, false));
|
||||
es.insert (db::EdgePair (e2, e1, false));
|
||||
EXPECT_EQ (int (es.size ()), 2);
|
||||
|
||||
es.clear ();
|
||||
es.insert (db::EdgePair (e1, e2, true));
|
||||
es.insert (db::EdgePair (e2, e1, true));
|
||||
EXPECT_EQ (int (es.size ()), 1);
|
||||
|
||||
std::unordered_set<db::EdgePair> eh;
|
||||
|
||||
eh.clear ();
|
||||
eh.insert (db::EdgePair (e1, e2, false));
|
||||
eh.insert (db::EdgePair (e1, e2, true));
|
||||
EXPECT_EQ (int (eh.size ()), 2);
|
||||
|
||||
eh.clear ();
|
||||
eh.insert (db::EdgePair (e1, e2, false));
|
||||
eh.insert (db::EdgePair (e2, e1, false));
|
||||
EXPECT_EQ (int (eh.size ()), 2);
|
||||
|
||||
eh.clear ();
|
||||
eh.insert (db::EdgePair (e1, e2, true));
|
||||
eh.insert (db::EdgePair (e2, e1, true));
|
||||
EXPECT_EQ (int (eh.size ()), 1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -505,14 +505,14 @@ TEST(15a)
|
|||
db::Box bb[3] = { db::Box (db::Point (0, 0), db::Point (10, 10)), db::Box (), db::Box (db::Point (20, 20), db::Point (40, 50)) };
|
||||
db::Region r (bb + 0, bb + 3);
|
||||
|
||||
EXPECT_EQ (r.width_check (15).to_string (), "(0,0;0,10)/(10,10;10,0);(0,10;10,10)/(10,0;0,0)");
|
||||
EXPECT_EQ (r.width_check (15).to_string (), "(0,0;0,10)|(10,10;10,0);(10,0;0,0)|(0,10;10,10)");
|
||||
EXPECT_EQ (r.width_check (5).to_string (), "");
|
||||
EXPECT_EQ (r.width_check (5, db::RegionCheckOptions (false, db::Euclidian, 91)).to_string (), "(0,5;0,10)/(0,10;5,10);(0,0;0,5)/(5,0;0,0);(5,10;10,10)/(10,10;10,5);(10,5;10,0)/(10,0;5,0);(20,45;20,50)/(20,50;25,50);(20,20;20,25)/(25,20;20,20);(35,50;40,50)/(40,50;40,45);(40,25;40,20)/(40,20;35,20)");
|
||||
EXPECT_EQ (r.space_check (15, db::RegionCheckOptions (false, db::Euclidian, 91)).to_string (), "(20,20;20,21)/(9,10;10,10);(20,20;20,21)/(10,10;10,9);(21,20;20,20)/(9,10;10,10);(21,20;20,20)/(10,10;10,9)");
|
||||
EXPECT_EQ (r.space_check (15, db::RegionCheckOptions (false, db::Square, 91)).to_string (), "(20,20;20,25)/(5,10;10,10);(20,20;20,25)/(10,10;10,5);(25,20;20,20)/(5,10;10,10);(25,20;20,20)/(10,10;10,5)");
|
||||
EXPECT_EQ (r.space_check (15).to_string (), "(20,20;20,21)/(10,10;10,9);(21,20;20,20)/(9,10;10,10)");
|
||||
EXPECT_EQ (r.space_check (15, db::RegionCheckOptions (true)).to_string (), "(20,20;20,50)/(10,10;10,0);(40,20;20,20)/(0,10;10,10)");
|
||||
EXPECT_EQ (r.space_check (15, db::RegionCheckOptions (false, db::Square)).to_string (), "(20,20;20,25)/(10,10;10,5);(25,20;20,20)/(5,10;10,10)");
|
||||
EXPECT_EQ (r.width_check (5, db::RegionCheckOptions (false, db::Euclidian, 91)).to_string (), "(0,5;0,10)|(0,10;5,10);(0,0;0,5)|(5,0;0,0);(5,10;10,10)|(10,10;10,5);(10,0;5,0)|(10,5;10,0);(20,45;20,50)|(20,50;25,50);(20,20;20,25)|(25,20;20,20);(35,50;40,50)|(40,50;40,45);(40,20;35,20)|(40,25;40,20)");
|
||||
EXPECT_EQ (r.space_check (15, db::RegionCheckOptions (false, db::Euclidian, 91)).to_string (), "(9,10;10,10)|(20,20;20,21);(10,10;10,9)|(20,20;20,21);(9,10;10,10)|(21,20;20,20);(10,10;10,9)|(21,20;20,20)");
|
||||
EXPECT_EQ (r.space_check (15, db::RegionCheckOptions (false, db::Square, 91)).to_string (), "(5,10;10,10)|(20,20;20,25);(10,10;10,5)|(20,20;20,25);(5,10;10,10)|(25,20;20,20);(10,10;10,5)|(25,20;20,20)");
|
||||
EXPECT_EQ (r.space_check (15).to_string (), "(10,10;10,9)|(20,20;20,21);(9,10;10,10)|(21,20;20,20)");
|
||||
EXPECT_EQ (r.space_check (15, db::RegionCheckOptions (true)).to_string (), "(10,10;10,0)|(20,20;20,50);(0,10;10,10)|(40,20;20,20)");
|
||||
EXPECT_EQ (r.space_check (15, db::RegionCheckOptions (false, db::Square)).to_string (), "(10,10;10,5)|(20,20;20,25);(5,10;10,10)|(25,20;20,20)");
|
||||
|
||||
r.clear ();
|
||||
db::Point pts[] = {
|
||||
|
|
@ -533,7 +533,7 @@ TEST(15a)
|
|||
poly.assign_hull(pts + 0, pts + sizeof(pts)/sizeof(pts[0]));
|
||||
|
||||
r.insert (poly);
|
||||
EXPECT_EQ (r.width_check (70000).to_string (), "(20550000,-18950000;20550000,-18920000)/(20570000,-18880000;20570000,-18890000);(20550000,-18920000;20530000,-18920000)/(20550000,-18880000;20570000,-18880000);(20550000,-18920000;20530000,-18920000)/(20570000,-18890000;20613246,-18890000);(20530000,-18920000;20530000,-18910000)/(20550000,-18850000;20550000,-18880000);(20530000,-18920000;20530000,-18910000)/(20570000,-18880000;20570000,-18890000);(20530000,-18910000;20450000,-18910000)/(20450000,-18850000;20550000,-18850000);(20530000,-18910000;20486754,-18910000)/(20550000,-18880000;20570000,-18880000);(20530000,-18910000;20502918,-18910000)/(20570000,-18890000;20597082,-18890000);(20570000,-18890000;20650000,-18890000)/(20650000,-18950000;20550000,-18950000)");
|
||||
EXPECT_EQ (r.width_check (70000).to_string (), "(20550000,-18950000;20550000,-18920000)|(20570000,-18880000;20570000,-18890000);(20550000,-18920000;20530000,-18920000)|(20550000,-18880000;20570000,-18880000);(20550000,-18920000;20530000,-18920000)|(20570000,-18890000;20613246,-18890000);(20530000,-18920000;20530000,-18910000)|(20550000,-18850000;20550000,-18880000);(20530000,-18920000;20530000,-18910000)|(20570000,-18880000;20570000,-18890000);(20530000,-18910000;20450000,-18910000)|(20450000,-18850000;20550000,-18850000);(20530000,-18910000;20486754,-18910000)|(20550000,-18880000;20570000,-18880000);(20530000,-18910000;20502918,-18910000)|(20570000,-18890000;20597082,-18890000);(20650000,-18950000;20550000,-18950000)|(20570000,-18890000;20650000,-18890000)");
|
||||
}
|
||||
|
||||
TEST(15b)
|
||||
|
|
@ -544,10 +544,10 @@ TEST(15b)
|
|||
r.insert (db::Box (db::Point (300, 300), db::Point (500, 500)));
|
||||
r.insert (db::Box (db::Point (400, 200), db::Point (500, 300)));
|
||||
|
||||
EXPECT_EQ (r.width_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(400,200;400,300)/(500,300;500,200)");
|
||||
EXPECT_EQ (r.space_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(300,0;300,200)/(200,200;200,0);(300,300;300,500)/(200,500;200,300);(300,200;400,200)/(400,300;300,300)");
|
||||
EXPECT_EQ (r.notch_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(300,200;400,200)/(400,300;300,300)");
|
||||
EXPECT_EQ (r.isolated_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(200,200;200,0)/(300,0;300,200);(200,500;200,300)/(300,300;300,500)");
|
||||
EXPECT_EQ (r.width_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(400,200;400,300)|(500,300;500,200)");
|
||||
EXPECT_EQ (r.space_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(300,0;300,200)|(200,200;200,0);(300,300;300,500)|(200,500;200,300);(300,200;400,200)|(400,300;300,300)");
|
||||
EXPECT_EQ (r.notch_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(300,200;400,200)|(400,300;300,300)");
|
||||
EXPECT_EQ (r.isolated_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(300,0;300,200)|(200,200;200,0);(300,300;300,500)|(200,500;200,300)");
|
||||
}
|
||||
|
||||
TEST(15c)
|
||||
|
|
@ -562,10 +562,10 @@ TEST(15c)
|
|||
r.insert (db::Box (db::Point (400, 200), db::Point (500, 250)));
|
||||
r.insert (db::Box (db::Point (400, 250), db::Point (500, 300)));
|
||||
|
||||
EXPECT_EQ (r.width_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(400,200;400,300)/(500,300;500,200)");
|
||||
EXPECT_EQ (r.space_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(300,0;300,200)/(200,200;200,0);(300,300;300,500)/(200,500;200,300);(300,200;400,200)/(400,300;300,300)");
|
||||
EXPECT_EQ (r.notch_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(300,200;400,200)/(400,300;300,300)");
|
||||
EXPECT_EQ (r.isolated_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(200,200;200,0)/(300,0;300,200);(200,500;200,300)/(300,300;300,500)");
|
||||
EXPECT_EQ (r.width_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(400,200;400,300)|(500,300;500,200)");
|
||||
EXPECT_EQ (r.space_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(300,0;300,200)|(200,200;200,0);(300,300;300,500)|(200,500;200,300);(300,200;400,200)|(400,300;300,300)");
|
||||
EXPECT_EQ (r.notch_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(300,200;400,200)|(400,300;300,300)");
|
||||
EXPECT_EQ (r.isolated_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (), "(300,0;300,200)|(200,200;200,0);(300,300;300,500)|(200,500;200,300)");
|
||||
}
|
||||
|
||||
TEST(15d)
|
||||
|
|
@ -581,12 +581,12 @@ TEST(15d)
|
|||
r.insert (db::Box (db::Point (0, 140), db::Point (350, 160)));
|
||||
|
||||
EXPECT_EQ (r.space_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (),
|
||||
"(100,140;0,140)/(0,100;100,100);"
|
||||
"(350,140;300,140)/(300,100;350,100);"
|
||||
"(100,200;0,200)/(0,160;100,160);"
|
||||
"(400,200;300,200)/(300,100;400,100);"
|
||||
"(350,200;300,200)/(300,160;350,160);"
|
||||
"(700,200;600,200)/(600,100;700,100)"
|
||||
"(300,100;350,100)|(350,140;300,140);"
|
||||
"(0,100;100,100)|(100,140;0,140);"
|
||||
"(0,160;100,160)|(100,200;0,200);"
|
||||
"(300,160;350,160)|(350,200;300,200);"
|
||||
"(300,100;400,100)|(400,200;300,200);"
|
||||
"(600,100;700,100)|(700,200;600,200)"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -635,7 +635,7 @@ TEST(15e)
|
|||
r.insert (poly);
|
||||
}
|
||||
|
||||
EXPECT_EQ (r.space_check (1000).to_string (), "(20857,3600;20857,66000)/(19957,66000;19957,3600)");
|
||||
EXPECT_EQ (r.space_check (1000).to_string (), "(20857,3600;20857,66000)|(19957,66000;19957,3600)");
|
||||
}
|
||||
|
||||
TEST(15g)
|
||||
|
|
@ -1235,14 +1235,14 @@ TEST(20)
|
|||
|
||||
{
|
||||
db::Region r1 (db::RecursiveShapeIterator (ly, ly.cell (top), l2));
|
||||
EXPECT_EQ (r1.width_check (20).to_string (), "(60,10;60,20)/(70,20;70,10);(60,20;70,20)/(70,10;60,10)");
|
||||
EXPECT_EQ (r1.width_check (50).to_string (), "(60,10;60,20)/(70,20;70,10);(60,20;70,20)/(70,10;60,10);(10,10;10,40)/(40,40;40,10);(10,40;40,40)/(40,10;10,10);(80,70;140,70)/(140,40;80,40)");
|
||||
EXPECT_EQ (r1.width_check (20).to_string (), "(60,10;60,20)|(70,20;70,10);(70,10;60,10)|(60,20;70,20)");
|
||||
EXPECT_EQ (r1.width_check (50).to_string (), "(60,10;60,20)|(70,20;70,10);(70,10;60,10)|(60,20;70,20);(10,10;10,40)|(40,40;40,10);(40,10;10,10)|(10,40;40,40);(140,40;80,40)|(80,70;140,70)");
|
||||
}
|
||||
|
||||
{
|
||||
db::Region r1 (db::RecursiveShapeIterator (ly, ly.cell (top), l2));
|
||||
EXPECT_EQ (r1.has_valid_polygons (), false);
|
||||
EXPECT_EQ (r1.space_check (30).to_string (), "(40,40;40,10)/(60,10;60,20);(80,40;80,48)/(70,20;70,12);(92,40;80,40)/(60,20;70,20)");
|
||||
EXPECT_EQ (r1.space_check (30).to_string (), "(60,10;60,20)|(40,40;40,10);(70,20;70,12)|(80,40;80,48);(60,20;70,20)|(92,40;80,40)");
|
||||
EXPECT_EQ (r1.space_check (2).to_string (), "");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,40 @@ TEST(1_SimpleLShape)
|
|||
|
||||
db::EdgeRelationFilter er (db::WidthRelation, 1001, db::Projection);
|
||||
|
||||
db::edge2edge_check_with_negative_output<std::set<db::EdgePair>, std::set<db::Edge> > e2e (er, ep, ee1, ee2, false, false, false);
|
||||
db::edge2edge_check_with_negative_output<std::set<db::EdgePair>, std::set<db::Edge> > e2e (er, ep, ee1, ee2, false, false, false, true);
|
||||
|
||||
db::Point pts[] = {
|
||||
db::Point (0, 0),
|
||||
db::Point (0, 2000),
|
||||
db::Point (2000, 2000),
|
||||
db::Point (2000, 1000),
|
||||
db::Point (1000, 1000),
|
||||
db::Point (1000, 0)
|
||||
};
|
||||
|
||||
db::Polygon poly;
|
||||
poly.assign_hull (pts, pts + sizeof (pts) / sizeof (pts[0]));
|
||||
|
||||
db::poly2poly_check<db::Polygon> poly_check (e2e);
|
||||
|
||||
do {
|
||||
// single polygon check
|
||||
poly_check.enter (poly, 0);
|
||||
} while (e2e.prepare_next_pass ());
|
||||
|
||||
EXPECT_EQ (tl::to_string (ep), "(0,0;0,1000)|(1000,1000;1000,0),(2000,1000;1000,1000)|(1000,2000;2000,2000)");
|
||||
EXPECT_EQ (tl::to_string (ee1), "");
|
||||
EXPECT_EQ (tl::to_string (ee2), "");
|
||||
}
|
||||
|
||||
TEST(1s_SimpleLShape)
|
||||
{
|
||||
std::set<db::EdgePair> ep;
|
||||
std::set<db::Edge> ee1, ee2;
|
||||
|
||||
db::EdgeRelationFilter er (db::WidthRelation, 1001, db::Projection);
|
||||
|
||||
db::edge2edge_check_with_negative_output<std::set<db::EdgePair>, std::set<db::Edge> > e2e (er, ep, ee1, ee2, false, false, false, false);
|
||||
|
||||
db::Point pts[] = {
|
||||
db::Point (0, 0),
|
||||
|
|
@ -103,7 +136,7 @@ TEST(2_SimpleLWithBigPart)
|
|||
|
||||
db::EdgeRelationFilter er (db::WidthRelation, 1001, db::Projection);
|
||||
|
||||
db::edge2edge_check_with_negative_output<std::set<db::EdgePair>, std::set<db::Edge> > e2e (er, ep, ee1, ee2, false, false, false);
|
||||
db::edge2edge_check_with_negative_output<std::set<db::EdgePair>, std::set<db::Edge> > e2e (er, ep, ee1, ee2, false, false, false, true);
|
||||
|
||||
db::Point pts[] = {
|
||||
db::Point (0, 0),
|
||||
|
|
@ -124,7 +157,7 @@ TEST(2_SimpleLWithBigPart)
|
|||
poly_check.enter (poly, 0);
|
||||
} while (e2e.prepare_next_pass ());
|
||||
|
||||
EXPECT_EQ (tl::to_string (ep), "(0,0;0,1000)/(1000,1000;1000,0)");
|
||||
EXPECT_EQ (tl::to_string (ep), "(0,0;0,1000)|(1000,1000;1000,0)");
|
||||
EXPECT_EQ (tl::to_string (ee1), "(0,1000;0,2500),(2000,1000;1000,1000),(0,2500;2000,2500),(2000,2500;2000,1000)");
|
||||
EXPECT_EQ (tl::to_string (ee2), "");
|
||||
}
|
||||
|
|
@ -136,7 +169,7 @@ TEST(3_SimpleTWithBigPart)
|
|||
|
||||
db::EdgeRelationFilter er (db::WidthRelation, 1001, db::Projection);
|
||||
|
||||
db::edge2edge_check_with_negative_output<std::set<db::EdgePair>, std::set<db::Edge> > e2e (er, ep, ee1, ee2, false, false, false);
|
||||
db::edge2edge_check_with_negative_output<std::set<db::EdgePair>, std::set<db::Edge> > e2e (er, ep, ee1, ee2, false, false, false, true);
|
||||
|
||||
db::Point pts[] = {
|
||||
db::Point (0, 0),
|
||||
|
|
@ -159,7 +192,7 @@ TEST(3_SimpleTWithBigPart)
|
|||
poly_check.enter (poly, 0);
|
||||
} while (e2e.prepare_next_pass ());
|
||||
|
||||
EXPECT_EQ (tl::to_string (ep), "(0,0;0,1000)/(1000,1000;1000,0),(0,2500;0,3500)/(1000,3500;1000,2500)");
|
||||
EXPECT_EQ (tl::to_string (ep), "(0,0;0,1000)|(1000,1000;1000,0),(0,2500;0,3500)|(1000,3500;1000,2500)");
|
||||
EXPECT_EQ (tl::to_string (ee1), "(0,1000;0,2500),(2000,1000;1000,1000),(1000,2500;2000,2500),(2000,2500;2000,1000)");
|
||||
EXPECT_EQ (tl::to_string (ee2), "");
|
||||
}
|
||||
|
|
@ -171,7 +204,7 @@ TEST(4_SimpleNotch)
|
|||
|
||||
db::EdgeRelationFilter er (db::SpaceRelation, 1001, db::Projection);
|
||||
|
||||
db::edge2edge_check_with_negative_output<std::set<db::EdgePair>, std::set<db::Edge> > e2e (er, ep, ee1, ee2, false, false, false);
|
||||
db::edge2edge_check_with_negative_output<std::set<db::EdgePair>, std::set<db::Edge> > e2e (er, ep, ee1, ee2, false, false, false, true);
|
||||
|
||||
db::Point pts[] = {
|
||||
db::Point (0, 0),
|
||||
|
|
@ -194,7 +227,7 @@ TEST(4_SimpleNotch)
|
|||
poly_check.enter (poly, 0);
|
||||
} while (e2e.prepare_next_pass ());
|
||||
|
||||
EXPECT_EQ (tl::to_string (ep), "(2000,2000;1000,2000)/(1000,1000;2000,1000)");
|
||||
EXPECT_EQ (tl::to_string (ep), "(1000,1000;2000,1000)|(2000,2000;1000,2000)");
|
||||
EXPECT_EQ (tl::to_string (ee1), "(0,0;0,3000),(2000,0;0,0),(2000,1000;2000,0),(0,3000;2000,3000),(2000,3000;2000,2000)");
|
||||
EXPECT_EQ (tl::to_string (ee2), "");
|
||||
}
|
||||
|
|
@ -206,7 +239,7 @@ TEST(5_LShapeNotch)
|
|||
|
||||
db::EdgeRelationFilter er (db::SpaceRelation, 1001, db::Projection);
|
||||
|
||||
db::edge2edge_check_with_negative_output<std::set<db::EdgePair>, std::set<db::Edge> > e2e (er, ep, ee1, ee2, false, false, false);
|
||||
db::edge2edge_check_with_negative_output<std::set<db::EdgePair>, std::set<db::Edge> > e2e (er, ep, ee1, ee2, false, false, false, true);
|
||||
|
||||
db::Point pts[] = {
|
||||
db::Point (0, 0),
|
||||
|
|
@ -231,7 +264,7 @@ TEST(5_LShapeNotch)
|
|||
poly_check.enter (poly, 0);
|
||||
} while (e2e.prepare_next_pass ());
|
||||
|
||||
EXPECT_EQ (tl::to_string (ep), "(1500,1500;1500,2500)/(500,2500;500,1500),(2000,1500;1500,1500)/(1500,500;2000,500)");
|
||||
EXPECT_EQ (tl::to_string (ep), "(1500,500;2000,500)|(2000,1500;1500,1500),(1500,1500;1500,2500)|(500,2500;500,1500)");
|
||||
EXPECT_EQ (tl::to_string (ee1), "(0,0;0,3000),(2000,0;0,0),(2000,500;2000,0),(0,3000;2000,3000),(2000,3000;2000,1500)");
|
||||
EXPECT_EQ (tl::to_string (ee2), "");
|
||||
}
|
||||
|
|
@ -243,7 +276,7 @@ TEST(6_SeparationLvsBox)
|
|||
|
||||
db::EdgeRelationFilter er (db::SpaceRelation, 1001, db::Projection);
|
||||
|
||||
db::edge2edge_check_with_negative_output<std::set<db::EdgePair>, std::set<db::Edge> > e2e (er, ep, ee1, ee2, false, true /*different layers*/, false);
|
||||
db::edge2edge_check_with_negative_output<std::set<db::EdgePair>, std::set<db::Edge> > e2e (er, ep, ee1, ee2, false, true /*different layers*/, false, false);
|
||||
|
||||
db::Point pts1[] = {
|
||||
db::Point (0, 0),
|
||||
|
|
|
|||
|
|
@ -1112,6 +1112,9 @@ CODE
|
|||
#
|
||||
# This method acts on edge pair expressions and returns the first edges of the
|
||||
# edge pairs delivered by the expression.
|
||||
#
|
||||
# Some checks deliver symmetric edge pairs (e.g. space, width, etc.) for which the
|
||||
# edges are commutable. "first_edges" will deliver both edges for such edge pairs.
|
||||
|
||||
# %DRC%
|
||||
# @name second_edges
|
||||
|
|
@ -1120,6 +1123,10 @@ CODE
|
|||
#
|
||||
# This method acts on edge pair expressions and returns the second edges of the
|
||||
# edge pairs delivered by the expression.
|
||||
#
|
||||
# Some checks deliver symmetric edge pairs (e.g. space, width, etc.) for which the
|
||||
# edges are commutable. "second_edges" will not deliver edges for such edge pairs.
|
||||
# Instead, "first_edges" will deliver both.
|
||||
|
||||
def first_edges
|
||||
DRCOpNodeFilter::new(@engine, self, :new_edge_pair_to_first_edges, "first_edges")
|
||||
|
|
|
|||
|
|
@ -2755,6 +2755,9 @@ CODE
|
|||
#
|
||||
# Applies to edge pair collections only.
|
||||
# Returns the first edges of the edge pairs in the collection.
|
||||
#
|
||||
# Some checks deliver symmetric edge pairs (e.g. space, width, etc.) for which the
|
||||
# edges are commutable. "first_edges" will deliver both edges for such edge pairs.
|
||||
|
||||
# %DRC%
|
||||
# @name second_edges
|
||||
|
|
@ -2763,6 +2766,10 @@ CODE
|
|||
#
|
||||
# Applies to edge pair collections only.
|
||||
# Returns the second edges of the edge pairs in the collection.
|
||||
#
|
||||
# Some checks deliver symmetric edge pairs (e.g. space, width, etc.) for which the
|
||||
# edges are commutable. "second_edges" will not deliver edges for such edge pairs.
|
||||
# Instead, "first_edges" will deliver both.
|
||||
|
||||
%w(first_edges second_edges).each do |f|
|
||||
eval <<"CODE"
|
||||
|
|
|
|||
|
|
@ -553,6 +553,9 @@ The plain function is equivalent to "primary.extents".
|
|||
<p>
|
||||
This method acts on edge pair expressions and returns the first edges of the
|
||||
edge pairs delivered by the expression.
|
||||
</p><p>
|
||||
Some checks deliver symmetric edge pairs (e.g. space, width, etc.) for which the
|
||||
edges are commutable. "first_edges" will deliver both edges for such edge pairs.
|
||||
</p>
|
||||
<a name="holes"/><h2>"holes" - Selects all holes from the input polygons</h2>
|
||||
<keyword name="holes"/>
|
||||
|
|
@ -860,6 +863,10 @@ The plain function is equivalent to "primary.rounded_corners".
|
|||
<p>
|
||||
This method acts on edge pair expressions and returns the second edges of the
|
||||
edge pairs delivered by the expression.
|
||||
</p><p>
|
||||
Some checks deliver symmetric edge pairs (e.g. space, width, etc.) for which the
|
||||
edges are commutable. "second_edges" will not deliver edges for such edge pairs.
|
||||
Instead, "first_edges" will deliver both.
|
||||
</p>
|
||||
<a name="sized"/><h2>"sized" - Returns the sized version of the input</h2>
|
||||
<keyword name="sized"/>
|
||||
|
|
|
|||
|
|
@ -1032,6 +1032,9 @@ The following images show the effect of the extents method:
|
|||
<p>
|
||||
Applies to edge pair collections only.
|
||||
Returns the first edges of the edge pairs in the collection.
|
||||
</p><p>
|
||||
Some checks deliver symmetric edge pairs (e.g. space, width, etc.) for which the
|
||||
edges are commutable. "first_edges" will deliver both edges for such edge pairs.
|
||||
</p>
|
||||
<a name="flatten"/><h2>"flatten" - Flattens the layer</h2>
|
||||
<keyword name="flatten"/>
|
||||
|
|
@ -2178,6 +2181,10 @@ The following images shows the effect of the "scaled" method:
|
|||
<p>
|
||||
Applies to edge pair collections only.
|
||||
Returns the second edges of the edge pairs in the collection.
|
||||
</p><p>
|
||||
Some checks deliver symmetric edge pairs (e.g. space, width, etc.) for which the
|
||||
edges are commutable. "second_edges" will not deliver edges for such edge pairs.
|
||||
Instead, "first_edges" will deliver both.
|
||||
</p>
|
||||
<a name="select"/><h2>"select" - Selects edges, edge pairs or polygons based on evaluation of a block</h2>
|
||||
<keyword name="select"/>
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ l1.drc((space(projection) < 1.0).polygons).output(100, 0)
|
|||
l1.drc((space(projection) < 1.0).edges).output(101, 0)
|
||||
l1.drc((space(projection) < 1.0).first_edges).output(102, 0)
|
||||
l1.drc((space(projection) < 1.0).second_edges).output(103, 0)
|
||||
l1.drc((sep(l2, projection) < 1.0).first_edges).output(104, 0)
|
||||
l1.drc((sep(l2, projection) < 1.0).second_edges).output(105, 0)
|
||||
|
||||
l2.drc(primary.edges).output(110, 0)
|
||||
l2.drc(primary.edges.extended_in(0.1)).output(111, 0)
|
||||
|
|
|
|||
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.
|
|
@ -163,6 +163,53 @@ class DBEdgePair_TestClass < TestBase
|
|||
|
||||
end
|
||||
|
||||
# Symmetric edge pairs
|
||||
def test_5
|
||||
|
||||
b1 = RBA::DEdgePair::new(RBA::DEdge::new(1, 2, 3, 4), RBA::DEdge::new(11, 12, 13, 14), false)
|
||||
b1x = RBA::DEdgePair::new(RBA::DEdge::new(11, 12, 13, 14), RBA::DEdge::new(1, 2, 3, 4), false)
|
||||
b2a = RBA::DEdgePair::new(RBA::DEdge::new(1, 2, 3, 4), RBA::DEdge::new(11, 12, 13, 14), true)
|
||||
b2b = RBA::DEdgePair::new(RBA::DEdge::new(11, 12, 13, 14), RBA::DEdge::new(1, 2, 3, 4), true)
|
||||
|
||||
assert_equal(b1.hash == b1x.hash, false)
|
||||
assert_equal(b1.hash == b2a.hash, false)
|
||||
assert_equal(b1.hash == b2b.hash, false)
|
||||
assert_equal(b2a.hash == b2b.hash, true)
|
||||
|
||||
assert_equal(b1 < b1x, true)
|
||||
assert_equal(b1 == b1x, false)
|
||||
assert_equal(b1 < b2a, true)
|
||||
assert_equal(b1 == b2a, false)
|
||||
assert_equal(b1 < b2b, true)
|
||||
assert_equal(b2a < b2b, false)
|
||||
assert_equal(b2a == b2b, true)
|
||||
assert_equal(b2b < b2a, false)
|
||||
|
||||
assert_equal(b1.to_s, "(1,2;3,4)/(11,12;13,14)")
|
||||
assert_equal(b1x.to_s, "(11,12;13,14)/(1,2;3,4)")
|
||||
assert_equal(b2a.to_s, "(1,2;3,4)|(11,12;13,14)")
|
||||
assert_equal(b2b.to_s, "(1,2;3,4)|(11,12;13,14)")
|
||||
|
||||
h = {}
|
||||
h[b1] = 1
|
||||
h[b1x] = 2
|
||||
assert_equal(h.size, 2)
|
||||
assert_equal(h.keys.collect(&:to_s).join(","), "(1,2;3,4)/(11,12;13,14),(11,12;13,14)/(1,2;3,4)")
|
||||
|
||||
h = {}
|
||||
h[b1] = 1
|
||||
h[b2a] = 2
|
||||
assert_equal(h.size, 2)
|
||||
assert_equal(h.keys.collect(&:to_s).join(","), "(1,2;3,4)/(11,12;13,14),(1,2;3,4)|(11,12;13,14)")
|
||||
|
||||
h = {}
|
||||
h[b2a] = 1
|
||||
h[b2b] = 2
|
||||
assert_equal(h.size, 1)
|
||||
assert_equal(h.keys.collect(&:to_s).join(","), "(1,2;3,4)|(11,12;13,14)")
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
load("test_epilogue.rb")
|
||||
|
|
|
|||
|
|
@ -478,38 +478,38 @@ class DBRegion_TestClass < TestBase
|
|||
assert_equal(r3b.overlap_check(r1, 15, false, RBA::Region::Projection, nil, 380, 500).to_s, "")
|
||||
assert_equal(r3b.overlap_check(r1, 15, false, RBA::Region::Projection, nil, 0, 300).to_s, "(0,10;10,10)/(10,0;0,0);(10,10;10,0)/(0,0;0,10)")
|
||||
|
||||
assert_equal((r1 | r2).merged.isolated_check(25).to_s, "(120,20;120,380)/(100,395;100,5)")
|
||||
assert_equal((r1 | r2).merged.isolated_check(25, false, RBA::Region::Projection, nil, nil, nil).to_s, "(120,20;120,380)/(100,380;100,20)")
|
||||
assert_equal((r1 | r2).merged.isolated_check(25, false, RBA::Region::Square, nil, nil, nil).to_s, "(120,20;120,380)/(100,400;100,0)")
|
||||
assert_equal((r1 | r2).merged.isolated_check(25, false, RBA::Region::Euclidian, nil, nil, nil).to_s, "(120,20;120,380)/(100,395;100,5)")
|
||||
assert_equal((r1 | r2).merged.isolated_check(25, true, RBA::Region::Euclidian, nil, nil, nil).to_s, "(120,20;120,380)/(100,400;100,0)")
|
||||
assert_equal((r1 | r2).merged.isolated_check(25).to_s, "(120,20;120,380)|(100,395;100,5)")
|
||||
assert_equal((r1 | r2).merged.isolated_check(25, false, RBA::Region::Projection, nil, nil, nil).to_s, "(120,20;120,380)|(100,380;100,20)")
|
||||
assert_equal((r1 | r2).merged.isolated_check(25, false, RBA::Region::Square, nil, nil, nil).to_s, "(120,20;120,380)|(100,400;100,0)")
|
||||
assert_equal((r1 | r2).merged.isolated_check(25, false, RBA::Region::Euclidian, nil, nil, nil).to_s, "(120,20;120,380)|(100,395;100,5)")
|
||||
assert_equal((r1 | r2).merged.isolated_check(25, true, RBA::Region::Euclidian, nil, nil, nil).to_s, "(120,20;120,380)|(100,400;100,0)")
|
||||
assert_equal((r1 | r2).merged.isolated_check(25, false, RBA::Region::Euclidian, 0.0, nil, nil).to_s, "")
|
||||
assert_equal((r1 | r2).merged.isolated_check(25, false, RBA::Region::Euclidian, nil, 0, 300).to_s, "")
|
||||
assert_equal((r1 | r2).merged.isolated_check(25, false, RBA::Region::Euclidian, nil, 300, 500).to_s, "(120,20;120,380)/(100,395;100,5)")
|
||||
assert_equal((r1 | r2).merged.isolated_check(25, false, RBA::Region::Euclidian, nil, 300, nil).to_s, "(120,20;120,380)/(100,395;100,5)")
|
||||
assert_equal((r1 | r2).merged.isolated_check(25, false, RBA::Region::Euclidian, nil, 300, 500).to_s, "(120,20;120,380)|(100,395;100,5)")
|
||||
assert_equal((r1 | r2).merged.isolated_check(25, false, RBA::Region::Euclidian, nil, 300, nil).to_s, "(120,20;120,380)|(100,395;100,5)")
|
||||
|
||||
assert_equal((r1 | r2).merged.notch_check(25).to_s, "(0,200;50,200)/(50,220;10,220)")
|
||||
assert_equal((r1 | r2).merged.notch_check(25, false, RBA::Region::Projection, nil, nil, nil).to_s, "(10,200;50,200)/(50,220;10,220)")
|
||||
assert_equal((r1 | r2).merged.notch_check(25, true, RBA::Region::Projection, nil, nil, nil).to_s, "(0,200;50,200)/(50,220;10,220)")
|
||||
assert_equal((r1 | r2).merged.notch_check(25).to_s, "(0,200;50,200)|(50,220;10,220)")
|
||||
assert_equal((r1 | r2).merged.notch_check(25, false, RBA::Region::Projection, nil, nil, nil).to_s, "(10,200;50,200)|(50,220;10,220)")
|
||||
assert_equal((r1 | r2).merged.notch_check(25, true, RBA::Region::Projection, nil, nil, nil).to_s, "(0,200;50,200)|(50,220;10,220)")
|
||||
assert_equal((r1 | r2).merged.notch_check(25, true, RBA::Region::Projection, 0.0, nil, nil).to_s, "")
|
||||
assert_equal((r1 | r2).merged.notch_check(25, true, RBA::Region::Projection, nil, 40, nil).to_s, "(0,200;50,200)/(50,220;10,220)")
|
||||
assert_equal((r1 | r2).merged.notch_check(25, true, RBA::Region::Projection, nil, 40, nil).to_s, "(0,200;50,200)|(50,220;10,220)")
|
||||
assert_equal((r1 | r2).merged.notch_check(25, true, RBA::Region::Projection, nil, 50, nil).to_s, "")
|
||||
assert_equal((r1 | r2).merged.notch_check(25, true, RBA::Region::Projection, nil, 40, 50).to_s, "(0,200;50,200)/(50,220;10,220)")
|
||||
assert_equal((r1 | r2).merged.notch_check(25, true, RBA::Region::Projection, nil, 40, 50).to_s, "(0,200;50,200)|(50,220;10,220)")
|
||||
assert_equal((r1 | r2).merged.notch_check(25, true, RBA::Region::Projection, nil, nil, 40).to_s, "")
|
||||
|
||||
assert_equal((r1 | r2).merged.space_check(25).to_s, "(100,395;100,5)/(120,20;120,380);(0,200;50,200)/(50,220;10,220)")
|
||||
assert_equal((r1 | r2).merged.space_check(25, false, RBA::Region::Projection, nil, nil, nil).to_s, "(100,380;100,20)/(120,20;120,380);(10,200;50,200)/(50,220;10,220)")
|
||||
assert_equal((r1 | r2).merged.space_check(25, true, RBA::Region::Projection, nil, nil, nil).to_s, "(100,400;100,0)/(120,20;120,380);(0,200;50,200)/(50,220;10,220)")
|
||||
assert_equal((r1 | r2).merged.space_check(25).to_s, "(120,20;120,380)|(100,395;100,5);(0,200;50,200)|(50,220;10,220)")
|
||||
assert_equal((r1 | r2).merged.space_check(25, false, RBA::Region::Projection, nil, nil, nil).to_s, "(120,20;120,380)|(100,380;100,20);(10,200;50,200)|(50,220;10,220)")
|
||||
assert_equal((r1 | r2).merged.space_check(25, true, RBA::Region::Projection, nil, nil, nil).to_s, "(120,20;120,380)|(100,400;100,0);(0,200;50,200)|(50,220;10,220)")
|
||||
assert_equal((r1 | r2).merged.space_check(25, true, RBA::Region::Projection, 0.0, nil, nil).to_s, "")
|
||||
assert_equal((r1 | r2).merged.space_check(25, true, RBA::Region::Projection, nil, 50, nil).to_s, "(100,400;100,0)/(120,20;120,380)")
|
||||
assert_equal((r1 | r2).merged.space_check(25, true, RBA::Region::Projection, nil, nil, 50).to_s, "(0,200;50,200)/(50,220;10,220)")
|
||||
assert_equal((r1 | r2).merged.space_check(25, true, RBA::Region::Projection, nil, 50, nil).to_s, "(120,20;120,380)|(100,400;100,0)")
|
||||
assert_equal((r1 | r2).merged.space_check(25, true, RBA::Region::Projection, nil, nil, 50).to_s, "(0,200;50,200)|(50,220;10,220)")
|
||||
|
||||
assert_equal((r1 | r2).merged.width_check(60).to_s, "(120,20;120,380)/(130,380;130,20);(50,200;50,220)/(100,253;100,167)")
|
||||
assert_equal((r1 | r2).merged.width_check(60, false, RBA::Region::Projection, nil, nil, nil).to_s, "(120,20;120,380)/(130,380;130,20);(50,200;50,220)/(100,220;100,200)")
|
||||
assert_equal((r1 | r2).merged.width_check(60, true, RBA::Region::Projection, nil, nil, nil).to_s, "(120,20;120,380)/(130,380;130,20);(50,200;50,220)/(100,400;100,0)")
|
||||
assert_equal((r1 | r2).merged.width_check(60).to_s, "(120,20;120,380)|(130,380;130,20);(50,200;50,220)|(100,253;100,167)")
|
||||
assert_equal((r1 | r2).merged.width_check(60, false, RBA::Region::Projection, nil, nil, nil).to_s, "(120,20;120,380)|(130,380;130,20);(50,200;50,220)|(100,220;100,200)")
|
||||
assert_equal((r1 | r2).merged.width_check(60, true, RBA::Region::Projection, nil, nil, nil).to_s, "(120,20;120,380)|(130,380;130,20);(50,200;50,220)|(100,400;100,0)")
|
||||
assert_equal((r1 | r2).merged.width_check(60, true, RBA::Region::Projection, 0.0, nil, nil).to_s, "")
|
||||
assert_equal((r1 | r2).merged.width_check(60, true, RBA::Region::Projection, nil, 50, nil).to_s, "(120,20;120,380)/(130,380;130,20)")
|
||||
assert_equal((r1 | r2).merged.width_check(60, true, RBA::Region::Projection, nil, nil, 50).to_s, "(50,200;50,220)/(100,400;100,0)")
|
||||
assert_equal((r1 | r2).merged.width_check(60, true, RBA::Region::Projection, nil, 50, nil).to_s, "(120,20;120,380)|(130,380;130,20)")
|
||||
assert_equal((r1 | r2).merged.width_check(60, true, RBA::Region::Projection, nil, nil, 50).to_s, "(50,200;50,220)|(100,400;100,0)")
|
||||
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue