mirror of https://github.com/KLayout/klayout.git
Implemented edge pair filters, DRC: with(out)_angle, with(out)_length and with(out)_distance
This commit is contained in:
parent
931b3ef1ce
commit
c8548709bb
|
|
@ -24,6 +24,7 @@ SOURCES = \
|
|||
dbCompoundOperation.cc \
|
||||
dbEdge.cc \
|
||||
dbEdgePair.cc \
|
||||
dbEdgePairFilters.cc \
|
||||
dbEdgePairRelations.cc \
|
||||
dbEdgePairs.cc \
|
||||
dbEdgeProcessor.cc \
|
||||
|
|
@ -233,6 +234,7 @@ HEADERS = \
|
|||
dbCompoundOperation.h \
|
||||
dbEdge.h \
|
||||
dbEdgePair.h \
|
||||
dbEdgePairFilters.h \
|
||||
dbEdgePairRelations.h \
|
||||
dbEdgePairs.h \
|
||||
dbEdgeProcessor.h \
|
||||
|
|
|
|||
|
|
@ -346,16 +346,87 @@ EdgePairsDelegate *DeepEdgePairs::add (const EdgePairs &other) const
|
|||
}
|
||||
}
|
||||
|
||||
EdgePairsDelegate *DeepEdgePairs::filter_in_place (const EdgePairFilterBase &filter)
|
||||
EdgePairsDelegate *
|
||||
DeepEdgePairs::filter_in_place (const EdgePairFilterBase &filter)
|
||||
{
|
||||
// TODO: implement
|
||||
return AsIfFlatEdgePairs::filter_in_place (filter);
|
||||
// TODO: implement to be really in-place
|
||||
*this = *apply_filter (filter);
|
||||
return this;
|
||||
}
|
||||
|
||||
EdgePairsDelegate *DeepEdgePairs::filtered (const EdgePairFilterBase &filter) const
|
||||
EdgePairsDelegate *
|
||||
DeepEdgePairs::filtered (const EdgePairFilterBase &filter) const
|
||||
{
|
||||
// TODO: implement
|
||||
return AsIfFlatEdgePairs::filtered (filter);
|
||||
return apply_filter (filter);
|
||||
}
|
||||
|
||||
DeepEdgePairs *
|
||||
DeepEdgePairs::apply_filter (const EdgePairFilterBase &filter) const
|
||||
{
|
||||
const db::DeepLayer &edge_pairs = deep_layer ();
|
||||
|
||||
std::unique_ptr<VariantsCollectorBase> vars;
|
||||
if (filter.vars ()) {
|
||||
|
||||
vars.reset (new db::VariantsCollectorBase (filter.vars ()));
|
||||
|
||||
vars->collect (edge_pairs.layout (), edge_pairs.initial_cell ());
|
||||
|
||||
if (filter.wants_variants ()) {
|
||||
const_cast<db::DeepLayer &> (edge_pairs).separate_variants (*vars);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
db::Layout &layout = const_cast<db::Layout &> (edge_pairs.layout ());
|
||||
std::map<db::cell_index_type, std::map<db::ICplxTrans, db::Shapes> > to_commit;
|
||||
|
||||
std::unique_ptr<db::DeepEdgePairs> res (new db::DeepEdgePairs (edge_pairs.derived ()));
|
||||
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
|
||||
|
||||
const db::Shapes &s = c->shapes (edge_pairs.layer ());
|
||||
|
||||
if (vars.get ()) {
|
||||
|
||||
const std::map<db::ICplxTrans, size_t> &vv = vars->variants (c->cell_index ());
|
||||
for (std::map<db::ICplxTrans, size_t>::const_iterator v = vv.begin (); v != vv.end (); ++v) {
|
||||
|
||||
db::Shapes *st;
|
||||
if (vv.size () == 1) {
|
||||
st = & c->shapes (res->deep_layer ().layer ());
|
||||
} else {
|
||||
st = & to_commit [c->cell_index ()] [v->first];
|
||||
}
|
||||
|
||||
const db::ICplxTrans &tr = v->first;
|
||||
|
||||
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::EdgePairs); ! si.at_end (); ++si) {
|
||||
if (filter.selected (si->edge_pair ().transformed (tr))) {
|
||||
st->insert (*si);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
|
||||
|
||||
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::EdgePairs); ! si.at_end (); ++si) {
|
||||
if (filter.selected (si->edge_pair ())) {
|
||||
st.insert (*si);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! to_commit.empty () && vars.get ()) {
|
||||
res->deep_layer ().commit_shapes (*vars, to_commit);
|
||||
}
|
||||
|
||||
return res.release ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ private:
|
|||
|
||||
void init ();
|
||||
EdgesDelegate *generic_edges (bool first, bool second) const;
|
||||
DeepEdgePairs *apply_filter (const EdgePairFilterBase &filter) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,100 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2021 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "dbCommon.h"
|
||||
|
||||
#include "dbEdgePairFilters.h"
|
||||
#include "dbEdges.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------
|
||||
// EdgeFilterBasedEdgePairFilter implementation
|
||||
|
||||
EdgeFilterBasedEdgePairFilter::EdgeFilterBasedEdgePairFilter (EdgeFilterBase *edge_filter, bool one_must_match)
|
||||
: mp_edge_filter (edge_filter), m_one_must_match (one_must_match)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
EdgeFilterBasedEdgePairFilter::~EdgeFilterBasedEdgePairFilter ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
bool EdgeFilterBasedEdgePairFilter::selected (const db::EdgePair &edge_pair) const
|
||||
{
|
||||
if (m_one_must_match) {
|
||||
return mp_edge_filter->selected (edge_pair.first ()) || mp_edge_filter->selected (edge_pair.second ());
|
||||
} else {
|
||||
return mp_edge_filter->selected (edge_pair.first ()) && mp_edge_filter->selected (edge_pair.second ());
|
||||
}
|
||||
}
|
||||
|
||||
const TransformationReducer *EdgeFilterBasedEdgePairFilter::vars () const
|
||||
{
|
||||
return mp_edge_filter->vars ();
|
||||
}
|
||||
|
||||
bool EdgeFilterBasedEdgePairFilter::wants_variants () const
|
||||
{
|
||||
return mp_edge_filter->wants_variants ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------
|
||||
// EdgePairFilterByDistance implementation
|
||||
|
||||
EdgePairFilterByDistance::EdgePairFilterByDistance (distance_type min_distance, distance_type max_distance, bool inverted)
|
||||
: m_min_distance (min_distance), m_max_distance (max_distance), m_inverted (inverted)
|
||||
{
|
||||
// .. 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);
|
||||
}
|
||||
|
||||
bool sel = (dist >= m_min_distance && dist < m_max_distance);
|
||||
return m_inverted ? !sel : sel;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2021 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HDR_dbEdgePairFilters
|
||||
#define HDR_dbEdgePairFilters
|
||||
|
||||
#include "dbEdgePairs.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
class EdgeFilterBase;
|
||||
|
||||
/**
|
||||
* @brief A base class for edge pair filters based on edge filters
|
||||
*
|
||||
* If "one_must_match" is true, it is sufficient for one edge to be selected.
|
||||
* If it is false, both edges need to be selected to make the edge pair selected.
|
||||
*
|
||||
* NOTE: the edge filter is not owned by the edge pair filter object.
|
||||
*/
|
||||
class DB_PUBLIC EdgeFilterBasedEdgePairFilter
|
||||
: public EdgePairFilterBase
|
||||
{
|
||||
public:
|
||||
EdgeFilterBasedEdgePairFilter (EdgeFilterBase *edge_filter, bool one_must_match);
|
||||
virtual ~EdgeFilterBasedEdgePairFilter ();
|
||||
|
||||
virtual bool selected (const db::EdgePair &edge_pair) const;
|
||||
virtual const TransformationReducer *vars () const;
|
||||
virtual bool wants_variants () const;
|
||||
|
||||
private:
|
||||
EdgeFilterBase *mp_edge_filter;
|
||||
bool m_one_must_match;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Filters edge pairs based on the distance of the edges.
|
||||
*
|
||||
* The distance is measured as the smallest distance between each of the points of the two edges.
|
||||
*/
|
||||
class DB_PUBLIC EdgePairFilterByDistance
|
||||
: public EdgePairFilterBase
|
||||
{
|
||||
public:
|
||||
typedef db::coord_traits<db::Coord>::distance_type distance_type;
|
||||
|
||||
EdgePairFilterByDistance (distance_type min_distance, distance_type max_distance, bool inverted);
|
||||
|
||||
virtual bool selected (const db::EdgePair &edge_pair) const;
|
||||
virtual const TransformationReducer *vars () const { return 0; }
|
||||
virtual bool wants_variants () const { return false; }
|
||||
|
||||
private:
|
||||
distance_type m_min_distance, m_max_distance;
|
||||
bool m_inverted;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -38,6 +38,9 @@
|
|||
namespace db
|
||||
{
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------
|
||||
// EdgePairs implementation
|
||||
|
||||
EdgePairs::EdgePairs ()
|
||||
: mp_delegate (new EmptyEdgePairs ())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -42,17 +42,13 @@ class Edges;
|
|||
class Region;
|
||||
class DeepShapeStore;
|
||||
class TransformationReducer;
|
||||
class EdgeFilterBase;
|
||||
|
||||
/**
|
||||
* @brief An edge pair set iterator
|
||||
*
|
||||
* The iterator delivers the edge pairs of the edge pair set
|
||||
*/
|
||||
/**
|
||||
* @brief An edge set iterator
|
||||
*
|
||||
* The iterator delivers the edges of the edge set
|
||||
*/
|
||||
class DB_PUBLIC EdgePairsIterator
|
||||
: public generic_shape_iterator<db::EdgePair>
|
||||
{
|
||||
|
|
@ -117,7 +113,7 @@ public:
|
|||
EdgePairFilterBase () { }
|
||||
virtual ~EdgePairFilterBase () { }
|
||||
|
||||
virtual bool selected (const db::EdgePair &edge) const = 0;
|
||||
virtual bool selected (const db::EdgePair &edge_pair) const = 0;
|
||||
virtual const TransformationReducer *vars () const = 0;
|
||||
virtual bool wants_variants () const = 0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
#include "dbEdges.h"
|
||||
#include "dbRegion.h"
|
||||
#include "dbDeepEdgePairs.h"
|
||||
#include "dbEdgesUtils.h"
|
||||
#include "dbEdgePairFilters.h"
|
||||
|
||||
namespace gsi
|
||||
{
|
||||
|
|
@ -176,6 +178,74 @@ static size_t id (const db::EdgePairs *ep)
|
|||
return tl::id_of (ep->delegate ());
|
||||
}
|
||||
|
||||
static db::EdgePairs with_distance1 (const db::EdgePairs *r, db::EdgePairs::distance_type length, bool inverse)
|
||||
{
|
||||
db::EdgePairFilterByDistance ef (length, length + 1, inverse);
|
||||
return r->filtered (ef);
|
||||
}
|
||||
|
||||
static db::EdgePairs with_distance2 (const db::EdgePairs *r, const tl::Variant &min, const tl::Variant &max, bool inverse)
|
||||
{
|
||||
db::EdgePairFilterByDistance ef (min.is_nil () ? db::Edges::distance_type (0) : min.to<db::Edges::distance_type> (), max.is_nil () ? std::numeric_limits <db::Edges::distance_type>::max () : max.to<db::Edges::distance_type> (), inverse);
|
||||
return r->filtered (ef);
|
||||
}
|
||||
|
||||
static db::EdgePairs with_length1 (const db::EdgePairs *r, db::EdgePairs::distance_type length, bool inverse)
|
||||
{
|
||||
db::EdgeLengthFilter f (length, length + 1, inverse);
|
||||
db::EdgeFilterBasedEdgePairFilter ef (&f, true /*one must match*/);
|
||||
return r->filtered (ef);
|
||||
}
|
||||
|
||||
static db::EdgePairs with_length2 (const db::EdgePairs *r, const tl::Variant &min, const tl::Variant &max, bool inverse)
|
||||
{
|
||||
db::EdgeLengthFilter f (min.is_nil () ? db::Edges::distance_type (0) : min.to<db::Edges::distance_type> (), max.is_nil () ? std::numeric_limits <db::Edges::distance_type>::max () : max.to<db::Edges::distance_type> (), inverse);
|
||||
db::EdgeFilterBasedEdgePairFilter ef (&f, true /*one must match*/);
|
||||
return r->filtered (ef);
|
||||
}
|
||||
|
||||
static db::EdgePairs with_length_both1 (const db::EdgePairs *r, db::EdgePairs::distance_type length, bool inverse)
|
||||
{
|
||||
db::EdgeLengthFilter f (length, length + 1, inverse);
|
||||
db::EdgeFilterBasedEdgePairFilter ef (&f, false /*both must match*/);
|
||||
return r->filtered (ef);
|
||||
}
|
||||
|
||||
static db::EdgePairs with_length_both2 (const db::EdgePairs *r, const tl::Variant &min, const tl::Variant &max, bool inverse)
|
||||
{
|
||||
db::EdgeLengthFilter f (min.is_nil () ? db::Edges::distance_type (0) : min.to<db::Edges::distance_type> (), max.is_nil () ? std::numeric_limits <db::Edges::distance_type>::max () : max.to<db::Edges::distance_type> (), inverse);
|
||||
db::EdgeFilterBasedEdgePairFilter ef (&f, false /*both must match*/);
|
||||
return r->filtered (ef);
|
||||
}
|
||||
|
||||
static db::EdgePairs with_angle1 (const db::EdgePairs *r, double a, bool inverse)
|
||||
{
|
||||
db::EdgeOrientationFilter f (a, inverse);
|
||||
db::EdgeFilterBasedEdgePairFilter ef (&f, true /*one must match*/);
|
||||
return r->filtered (ef);
|
||||
}
|
||||
|
||||
static db::EdgePairs with_angle2 (const db::EdgePairs *r, double amin, double amax, bool inverse, bool include_amin, bool include_amax)
|
||||
{
|
||||
db::EdgeOrientationFilter f (amin, include_amin, amax, include_amax, inverse);
|
||||
db::EdgeFilterBasedEdgePairFilter ef (&f, true /*one must match*/);
|
||||
return r->filtered (ef);
|
||||
}
|
||||
|
||||
static db::EdgePairs with_angle_both1 (const db::EdgePairs *r, double a, bool inverse)
|
||||
{
|
||||
db::EdgeOrientationFilter f (a, inverse);
|
||||
db::EdgeFilterBasedEdgePairFilter ef (&f, false /*both must match*/);
|
||||
return r->filtered (ef);
|
||||
}
|
||||
|
||||
static db::EdgePairs with_angle_both2 (const db::EdgePairs *r, double amin, double amax, bool inverse, bool include_amin, bool include_amax)
|
||||
{
|
||||
db::EdgeOrientationFilter f (amin, include_amin, amax, include_amax, inverse);
|
||||
db::EdgeFilterBasedEdgePairFilter ef (&f, false /*both must match*/);
|
||||
return r->filtered (ef);
|
||||
}
|
||||
|
||||
extern Class<db::ShapeCollection> decl_dbShapeCollection;
|
||||
|
||||
Class<db::EdgePairs> decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs",
|
||||
|
|
@ -502,6 +572,112 @@ Class<db::EdgePairs> decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs",
|
|||
"The boxes will not be merged, so it is possible to determine overlaps "
|
||||
"of these boxes for example.\n"
|
||||
) +
|
||||
method_ext ("with_length", with_length1, gsi::arg ("length"), gsi::arg ("inverse"),
|
||||
"@brief Filters the edge pairs by length of one of their edges\n"
|
||||
"Filters the edge pairs in the edge pair collection by length of at least one of their edges. If \"inverse\" is false, only "
|
||||
"edge pairs with at least one edge having the given length are returned. If \"inverse\" is true, "
|
||||
"edge pairs not fulfilling this criterion are returned.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.27.1.\n"
|
||||
) +
|
||||
method_ext ("with_length", with_length2, gsi::arg ("min_length"), gsi::arg ("max_length"), gsi::arg ("inverse"),
|
||||
"@brief Filters the edge pairs by length of one of their edges\n"
|
||||
"Filters the edge pairs in the edge pair collection by length of at least one of their edges. If \"inverse\" is false, only "
|
||||
"edge pairs with at least one edge having a length between min_length and max_length (excluding max_length itself) are returned. If \"inverse\" is true, "
|
||||
"edge pairs not fulfilling this criterion are returned.\n"
|
||||
"\n"
|
||||
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.27.1.\n"
|
||||
) +
|
||||
method_ext ("with_length_both", with_length_both1, gsi::arg ("length"), gsi::arg ("inverse"),
|
||||
"@brief Filters the edge pairs by length of both of their edges\n"
|
||||
"Filters the edge pairs in the edge pair collection by length of both of their edges. If \"inverse\" is false, only "
|
||||
"edge pairs where both edges have the given length are returned. If \"inverse\" is true, "
|
||||
"edge pairs not fulfilling this criterion are returned.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.27.1.\n"
|
||||
) +
|
||||
method_ext ("with_length_both", with_length_both2, gsi::arg ("min_length"), gsi::arg ("max_length"), gsi::arg ("inverse"),
|
||||
"@brief Filters the edge pairs by length of both of their edges\n"
|
||||
"Filters the edge pairs in the edge pair collection by length of both of their edges. If \"inverse\" is false, only "
|
||||
"edge pairs with both edges having a length between min_length and max_length (excluding max_length itself) are returned. If \"inverse\" is true, "
|
||||
"edge pairs not fulfilling this criterion are returned.\n"
|
||||
"\n"
|
||||
"If you don't want to specify a lower or upper limit, pass nil to that parameter.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.27.1.\n"
|
||||
) +
|
||||
method_ext ("with_distance", with_distance1, gsi::arg ("distance"), gsi::arg ("inverse"),
|
||||
"@brief Filters the edge pairs by the distance of the edges\n"
|
||||
"Filters the edge pairs in the edge pair collection by distance of the edges. If \"inverse\" is false, only "
|
||||
"edge pairs where both edges have the given distance are returned. If \"inverse\" is true, "
|
||||
"edge pairs not fulfilling this criterion are returned.\n"
|
||||
"\n"
|
||||
"Distance is measured as the shortest distance between any of the points on the edges.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.27.1.\n"
|
||||
) +
|
||||
method_ext ("with_distance", with_distance2, gsi::arg ("min_distance"), gsi::arg ("max_distance"), gsi::arg ("inverse"),
|
||||
"@brief Filters the edge pairs by the distance of the edges\n"
|
||||
"Filters the edge pairs in the edge pair collection by distance of the edges. If \"inverse\" is false, only "
|
||||
"edge pairs where both edges have a distance between min_distance and max_distance (max_distance itself is excluded). If \"inverse\" is true, "
|
||||
"edge pairs not fulfilling this criterion are returned.\n"
|
||||
"\n"
|
||||
"Distance is measured as the shortest distance between any of the points on the edges.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.27.1.\n"
|
||||
) +
|
||||
method_ext ("with_angle", with_angle1, gsi::arg ("angle"), gsi::arg ("inverse"),
|
||||
"@brief Filter the edge pairs by orientation of their edges\n"
|
||||
"Filters the edge pairs in the edge pair collection by orientation. If \"inverse\" is false, only "
|
||||
"edge pairs with at least one edge having the given angle to the x-axis are returned. If \"inverse\" is true, "
|
||||
"edge pairs not fulfilling this criterion are returned.\n"
|
||||
"\n"
|
||||
"This will filter edge pairs with at least one horizontal edge:\n"
|
||||
"\n"
|
||||
"@code\n"
|
||||
"horizontal = edge_pairs.with_orientation(0, false)\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.27.1.\n"
|
||||
) +
|
||||
method_ext ("with_angle", with_angle2, gsi::arg ("min_angle"), gsi::arg ("max_angle"), gsi::arg ("inverse"), gsi::arg ("include_min_angle", true), gsi::arg ("include_max_angle", false),
|
||||
"@brief Filter the edge pairs by orientation of their edges\n"
|
||||
"Filters the edge pairs in the edge pair collection by orientation. If \"inverse\" is false, only "
|
||||
"edge pairs with at least one edge having an angle between min_angle and max_angle are returned. If \"inverse\" is true, "
|
||||
"edge pairs not fulfilling this criterion are returned.\n"
|
||||
"\n"
|
||||
"With \"include_min_angle\" set to true (the default), the minimum angle is included in the criterion while with false, the "
|
||||
"minimum angle itself is not included. Same for \"include_max_angle\" where the default is false, meaning the maximum angle is not included in the range.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.27.1.\n"
|
||||
) +
|
||||
method_ext ("with_angle_both", with_angle_both1, gsi::arg ("angle"), gsi::arg ("inverse"),
|
||||
"@brief Filter the edge pairs by orientation of both of their edges\n"
|
||||
"Filters the edge pairs in the edge pair collection by orientation. If \"inverse\" is false, only "
|
||||
"edge pairs with both edges having the given angle to the x-axis are returned. If \"inverse\" is true, "
|
||||
"edge pairs not fulfilling this criterion are returned.\n"
|
||||
"\n"
|
||||
"This will filter edge pairs with at least one horizontal edge:\n"
|
||||
"\n"
|
||||
"@code\n"
|
||||
"horizontal = edge_pairs.with_orientation(0, false)\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.27.1.\n"
|
||||
) +
|
||||
method_ext ("with_angle_both", with_angle_both2, gsi::arg ("min_angle"), gsi::arg ("max_angle"), gsi::arg ("inverse"), gsi::arg ("include_min_angle", true), gsi::arg ("include_max_angle", false),
|
||||
"@brief Filter the edge pairs by orientation of both of their edges\n"
|
||||
"Filters the edge pairs in the edge pair collection by orientation. If \"inverse\" is false, only "
|
||||
"edge pairs with both edges having an angle between min_angle and max_angle are returned. If \"inverse\" is true, "
|
||||
"edge pairs not fulfilling this criterion are returned.\n"
|
||||
"\n"
|
||||
"With \"include_min_angle\" set to true (the default), the minimum angle is included in the criterion while with false, the "
|
||||
"minimum angle itself is not included. Same for \"include_max_angle\" where the default is false, meaning the maximum angle is not included in the range.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.27.1.\n"
|
||||
) +
|
||||
method_ext ("polygons", &polygons1,
|
||||
"@brief Converts the edge pairs to polygons\n"
|
||||
"This method creates polygons from the edge pairs. Each polygon will be a triangle or quadrangle "
|
||||
|
|
|
|||
|
|
@ -575,10 +575,10 @@ Class<db::Edges> decl_Edges (decl_dbShapeCollection, "db", "Edges",
|
|||
"edges which have the given angle to the x-axis are returned. If \"inverse\" is true, "
|
||||
"edges not having the given angle are returned.\n"
|
||||
"\n"
|
||||
"This will filter horizontal edges:\n"
|
||||
"This will select horizontal edges:\n"
|
||||
"\n"
|
||||
"@code\n"
|
||||
"horizontal = edges.with_orientation(0, true)\n"
|
||||
"horizontal = edges.with_orientation(0, false)\n"
|
||||
"@/code\n"
|
||||
) +
|
||||
method_ext ("with_angle", with_angle2, gsi::arg ("min_angle"), gsi::arg ("max_angle"), gsi::arg ("inverse"), gsi::arg ("include_min_angle", true), gsi::arg ("include_max_angle", false),
|
||||
|
|
|
|||
|
|
@ -64,6 +64,10 @@ module DRC
|
|||
|
||||
end
|
||||
|
||||
def both
|
||||
DRCBothEdges::new
|
||||
end
|
||||
|
||||
def shift(x, y)
|
||||
self._context("shift") do
|
||||
RBA::DCplxTrans::new(RBA::DVector::new(_make_value(x) * self.dbu, _make_value(y) * self.dbu))
|
||||
|
|
@ -1793,6 +1797,7 @@ CODE
|
|||
with_bbox_min
|
||||
with_bbox_width
|
||||
with_length
|
||||
with_distance
|
||||
without_angle
|
||||
without_area
|
||||
without_area_ratio
|
||||
|
|
|
|||
|
|
@ -699,13 +699,19 @@ CODE
|
|||
# @synopsis layer.with_length(min .. max)
|
||||
# @synopsis layer.with_length(value)
|
||||
# @synopsis layer.with_length(min, max)
|
||||
# The method selects edges by their length. The first version selected
|
||||
# @synopsis edge_pairlayer.with_length(min, max [, both])
|
||||
# The method selects edges by their length. The first version selects
|
||||
# edges with a length larger or equal to min and less than max (but not equal).
|
||||
# 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.
|
||||
#
|
||||
# This method is available for edge layers only.
|
||||
# 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.
|
||||
#
|
||||
# This method is available for edge and edge pair layers.
|
||||
|
||||
# %DRC%
|
||||
# @name without_length
|
||||
|
|
@ -713,11 +719,12 @@ CODE
|
|||
# @synopsis layer.without_length(min .. max)
|
||||
# @synopsis layer.without_length(value)
|
||||
# @synopsis layer.without_length(min, max)
|
||||
# @synopsis edge_pairlayer.with_length(min, max [, both])
|
||||
# The method basically is the inverse of \with_length. It selects all edges
|
||||
# of the edge layer which do not have the given length (second form) or are
|
||||
# not inside the given interval (first and third form).
|
||||
#
|
||||
# This method is available for edge layers only.
|
||||
# This method is available for edge and edge pair layers.
|
||||
|
||||
%w(length).each do |f|
|
||||
[true, false].each do |inv|
|
||||
|
|
@ -727,18 +734,96 @@ CODE
|
|||
|
||||
@engine._context("#{mn}") do
|
||||
|
||||
requires_edges
|
||||
requires_edges_or_edge_pairs
|
||||
|
||||
result_class = self.data.class
|
||||
|
||||
f = :with_#{f}
|
||||
args = args.select do |a|
|
||||
if a.is_a?(DRCBothEdges)
|
||||
if !self.data.is_a?(RBA::EdgePairs)
|
||||
raise("'both' keyword only available for edge pair layers")
|
||||
end
|
||||
f = :with_#{f}_both
|
||||
false
|
||||
else
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
if args.size == 1
|
||||
a = args[0]
|
||||
if a.is_a?(Range)
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, RBA::Edges, :with_#{f}, @engine._make_value_with_nil(a.begin), @engine._make_value_with_nil(a.end), #{inv.inspect}))
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, result_class, f, @engine._make_value_with_nil(a.begin), @engine._make_value_with_nil(a.end), #{inv.inspect}))
|
||||
else
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, RBA::Edges, :with_#{f}, @engine._make_value(a), #{inv.inspect}))
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, result_class, f, @engine._make_value(a), #{inv.inspect}))
|
||||
end
|
||||
elsif args.size == 2
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, RBA::Edges, :with_#{f}, @engine._make_value_with_nil(args[0]), @engine._make_value_with_nil(args[1]), #{inv.inspect}))
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, result_class, f, @engine._make_value_with_nil(args[0]), @engine._make_value_with_nil(args[1]), #{inv.inspect}))
|
||||
else
|
||||
raise("Invalid number of arguments (1 or 2 expected)")
|
||||
raise("Invalid number of range arguments (1 or 2 expected)")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
CODE
|
||||
end
|
||||
end
|
||||
|
||||
# %DRC%
|
||||
# @name with_distance
|
||||
# @brief Selects edge pairs by the distance of the edges
|
||||
# @synopsis layer.with_distance(min .. max)
|
||||
# @synopsis layer.with_distance(value)
|
||||
# @synopsis layer.with_distance(min, max)
|
||||
# The method selects edge pairs by the distance of their edges. The first version selects
|
||||
# edge pairs with a distance larger or equal to min and less than max (but not equal).
|
||||
# The second version selects edge pairs with exactly the given distance. 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.
|
||||
#
|
||||
# The distance of the edges is defined by the minimum distance of all points from the
|
||||
# edges involved. For edge pairs generated in geometrical checks this is equivalent
|
||||
# to the actual distance of the original edges.
|
||||
#
|
||||
# This method is available for edge pair layers only.
|
||||
|
||||
# %DRC%
|
||||
# @name without_distance
|
||||
# @brief Selects edge pairs by the distance of the edges
|
||||
# @synopsis layer.without_distance(min .. max)
|
||||
# @synopsis layer.without_distance(value)
|
||||
# @synopsis layer.without_distance(min, max)
|
||||
# The method basically is the inverse of \with_distance. It selects all edge pairs
|
||||
# of the edge pair layer which do not have the given distance (second form) or are
|
||||
# not inside the given interval (first and third form).
|
||||
#
|
||||
# This method is available for edge pair layers only.
|
||||
|
||||
%w(distance).each do |f|
|
||||
[true, false].each do |inv|
|
||||
mn = (inv ? "without" : "with") + "_" + f
|
||||
eval <<"CODE"
|
||||
def #{mn}(*args)
|
||||
|
||||
@engine._context("#{mn}") do
|
||||
|
||||
requires_edge_pairs
|
||||
|
||||
result_class = RBA::EdgePairs
|
||||
|
||||
if args.size == 1
|
||||
a = args[0]
|
||||
if a.is_a?(Range)
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, result_class, :with_#{f}, @engine._make_value_with_nil(a.begin), @engine._make_value_with_nil(a.end), #{inv.inspect}))
|
||||
else
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, result_class, :with_#{f}, @engine._make_value(a), #{inv.inspect}))
|
||||
end
|
||||
elsif args.size == 2
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, result_class, :with_#{f}, @engine._make_value_with_nil(args[0]), @engine._make_value_with_nil(args[1]), #{inv.inspect}))
|
||||
else
|
||||
raise("Invalid number of range arguments (1 or 2 expected)")
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -754,6 +839,7 @@ CODE
|
|||
# @synopsis layer.with_angle(min .. max)
|
||||
# @synopsis layer.with_angle(value)
|
||||
# @synopsis layer.with_angle(min, max)
|
||||
# @synopsis edge_pairlayer.with_angle(min, max [, both])
|
||||
#
|
||||
# When called on an edge layer, the method selects edges by their angle,
|
||||
# measured against the horizontal axis in the mathematical sense.
|
||||
|
|
@ -771,6 +857,11 @@ CODE
|
|||
# given angle or is within the given angle interval. The angle is measured between the edges forming the corner.
|
||||
# For each corner, an edge pair containing the edges forming in the angle is returned.
|
||||
#
|
||||
# When called on an edge pair layer, this method selects edge pairs with one or both edges
|
||||
# meeting the angle criterion. In this case an additional argument is accepted which can be
|
||||
# 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.
|
||||
#
|
||||
# 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:
|
||||
|
|
@ -792,37 +883,52 @@ CODE
|
|||
# @synopsis layer.without_angle(min .. max)
|
||||
# @synopsis layer.without_angle(value)
|
||||
# @synopsis layer.without_angle(min, max)
|
||||
# @synopsis edge_pairlayer.without_angle(min, max [, both])
|
||||
#
|
||||
# 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).
|
||||
|
||||
[true, false].each do |inv|
|
||||
mn = (inv ? "without" : "with") + "_angle"
|
||||
eval <<"CODE"
|
||||
def #{mn}(*args)
|
||||
%w(angle).each do |f|
|
||||
[true, false].each do |inv|
|
||||
mn = (inv ? "without" : "with") + "_" + f
|
||||
eval <<"CODE"
|
||||
def #{mn}(*args)
|
||||
|
||||
@engine._context("#{mn}") do
|
||||
@engine._context("#{mn}") do
|
||||
|
||||
requires_edges_or_region
|
||||
result_class = self.data.is_a?(RBA::Region) ? RBA::EdgePairs : RBA::Edges
|
||||
if args.size == 1
|
||||
a = args[0]
|
||||
if a.is_a?(Range)
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, result_class, :with_angle, a.begin, a.end, #{inv.inspect}))
|
||||
else
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, result_class, :with_angle, a, #{inv.inspect}))
|
||||
f = :with_#{f}
|
||||
args = args.select do |a|
|
||||
if a.is_a?(DRCBothEdges)
|
||||
if !self.data.is_a?(RBA::EdgePairs)
|
||||
raise("'both' keyword only available for edge pair layers")
|
||||
end
|
||||
f = :with_#{f}_both
|
||||
false
|
||||
else
|
||||
true
|
||||
end
|
||||
end
|
||||
elsif args.size == 2
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, result_class, :with_angle, args[0], args[1], #{inv.inspect}))
|
||||
else
|
||||
raise("Invalid number of arguments (1 or 2 expected)")
|
||||
|
||||
result_class = self.data.is_a?(RBA::Edges) ? RBA::Edges : RBA::EdgePairs
|
||||
if args.size == 1
|
||||
a = args[0]
|
||||
if a.is_a?(Range)
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, result_class, f, a.begin, a.end, #{inv.inspect}))
|
||||
else
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, result_class, f, a, #{inv.inspect}))
|
||||
end
|
||||
elsif args.size == 2
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, result_class, f, args[0], args[1], #{inv.inspect}))
|
||||
else
|
||||
raise("Invalid number of range arguments (1 or 2 expected)")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
CODE
|
||||
end
|
||||
end
|
||||
|
||||
# %DRC%
|
||||
|
|
@ -4567,6 +4673,10 @@ END
|
|||
self.data.is_a?(RBA::Edges) || raise("Requires an edge layer")
|
||||
end
|
||||
|
||||
def requires_edges_or_edge_pairs
|
||||
self.data.is_a?(RBA::Edges) || self.data.is_a?(RBA::EdgePairs) || raise("Requires an edge or edge pair layer")
|
||||
end
|
||||
|
||||
def requires_edges_or_region
|
||||
self.data.is_a?(RBA::Edges) || self.data.is_a?(RBA::Region) || raise("Requires an edge or polygon layer")
|
||||
end
|
||||
|
|
|
|||
|
|
@ -16,6 +16,10 @@ module DRC
|
|||
end
|
||||
end
|
||||
|
||||
# A wrapper for the "both edges" flag for EdgePair#with_length or EdgePair#with_angle
|
||||
class DRCBothEdges
|
||||
end
|
||||
|
||||
# A wrapper for the sizing mode value
|
||||
class DRCSizingMode
|
||||
attr_accessor :value
|
||||
|
|
|
|||
|
|
@ -1282,3 +1282,13 @@ TEST(48d_drcWithFragments)
|
|||
{
|
||||
run_test (_this, "48", true);
|
||||
}
|
||||
|
||||
TEST(49_drcWithFragments)
|
||||
{
|
||||
run_test (_this, "49", false);
|
||||
}
|
||||
|
||||
TEST(49d_drcWithFragments)
|
||||
{
|
||||
run_test (_this, "49", true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3158,6 +3158,7 @@ Shielding is enabled by default, but can be switched off with the "transparent"
|
|||
<li><tt>layer.with_angle(min .. max)</tt></li>
|
||||
<li><tt>layer.with_angle(value)</tt></li>
|
||||
<li><tt>layer.with_angle(min, max)</tt></li>
|
||||
<li><tt>edge_pairlayer.with_angle(min, max [, both])</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
When called on an edge layer, the method selects edges by their angle,
|
||||
|
|
@ -3176,6 +3177,11 @@ When called on a polygon layer, this method selects corners which match the
|
|||
given angle or is within the given angle interval. The angle is measured between the edges forming the corner.
|
||||
For each corner, an edge pair containing the edges forming in the angle is returned.
|
||||
</p><p>
|
||||
When called on an edge pair layer, this method selects edge pairs with one or both edges
|
||||
meeting the angle criterion. In this case an additional argument is accepted which can be
|
||||
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>
|
||||
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>
|
||||
|
|
@ -3369,6 +3375,27 @@ low_density = input(1, 0).density(0.0 .. 0.1, tile_size(20.um), tile_origin(0.0,
|
|||
</p><p>
|
||||
The complementary version of "with_density" is <a href="#without_density">without_density</a>.
|
||||
</p>
|
||||
<a name="with_distance"/><h2>"with_distance" - Selects edge pairs by the distance of the edges</h2>
|
||||
<keyword name="with_distance"/>
|
||||
<p>Usage:</p>
|
||||
<ul>
|
||||
<li><tt>layer.with_distance(min .. max)</tt></li>
|
||||
<li><tt>layer.with_distance(value)</tt></li>
|
||||
<li><tt>layer.with_distance(min, max)</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
The method selects edge pairs by the distance of their edges. The first version selects
|
||||
edge pairs with a distance larger or equal to min and less than max (but not equal).
|
||||
The second version selects edge pairs with exactly the given distance. 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>
|
||||
The distance of the edges is defined by the minimum distance of all points from the
|
||||
edges involved. For edge pairs generated in geometrical checks this is equivalent
|
||||
to the actual distance of the original edges.
|
||||
</p><p>
|
||||
This method is available for edge pair layers only.
|
||||
</p>
|
||||
<a name="with_holes"/><h2>"with_holes" - Selects all polygons with the specified number of holes</h2>
|
||||
<keyword name="with_holes"/>
|
||||
<p>Usage:</p>
|
||||
|
|
@ -3388,15 +3415,21 @@ which have the specified number of holes.
|
|||
<li><tt>layer.with_length(min .. max)</tt></li>
|
||||
<li><tt>layer.with_length(value)</tt></li>
|
||||
<li><tt>layer.with_length(min, max)</tt></li>
|
||||
<li><tt>edge_pairlayer.with_length(min, max [, both])</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
The method selects edges by their length. The first version selected
|
||||
The method selects edges by their length. The first version selects
|
||||
edges with a length larger or equal to min and less than max (but not equal).
|
||||
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 layers only.
|
||||
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.
|
||||
</p>
|
||||
<a name="with_perimeter"/><h2>"with_perimeter" - Selects polygons by perimeter</h2>
|
||||
<keyword name="with_perimeter"/>
|
||||
|
|
@ -3441,6 +3474,7 @@ This method is available for polygon layers only.
|
|||
<li><tt>layer.without_angle(min .. max)</tt></li>
|
||||
<li><tt>layer.without_angle(value)</tt></li>
|
||||
<li><tt>layer.without_angle(min, max)</tt></li>
|
||||
<li><tt>edge_pairlayer.without_angle(min, max [, both])</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
The method basically is the inverse of <a href="#with_angle">with_angle</a>. It selects all edges
|
||||
|
|
@ -3546,6 +3580,21 @@ This method is available for polygon layers only.
|
|||
For details about the operations and the operation see <a href="#with_density">with_density</a>. This version will return the
|
||||
tiles where the density is not within the given range.
|
||||
</p>
|
||||
<a name="without_distance"/><h2>"without_distance" - Selects edge pairs by the distance of the edges</h2>
|
||||
<keyword name="without_distance"/>
|
||||
<p>Usage:</p>
|
||||
<ul>
|
||||
<li><tt>layer.without_distance(min .. max)</tt></li>
|
||||
<li><tt>layer.without_distance(value)</tt></li>
|
||||
<li><tt>layer.without_distance(min, max)</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
The method basically is the inverse of <a href="#with_distance">with_distance</a>. It selects all edge pairs
|
||||
of the edge pair layer which do not have the given distance (second form) or are
|
||||
not inside the given interval (first and third form).
|
||||
</p><p>
|
||||
This method is available for edge pair layers only.
|
||||
</p>
|
||||
<a name="without_holes"/><h2>"without_holes" - Selects all polygons with the specified number of holes</h2>
|
||||
<keyword name="without_holes"/>
|
||||
<p>Usage:</p>
|
||||
|
|
@ -3565,13 +3614,14 @@ which do not have the specified number of holes.
|
|||
<li><tt>layer.without_length(min .. max)</tt></li>
|
||||
<li><tt>layer.without_length(value)</tt></li>
|
||||
<li><tt>layer.without_length(min, max)</tt></li>
|
||||
<li><tt>edge_pairlayer.with_length(min, max [, both])</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
The method basically is the inverse of <a href="#with_length">with_length</a>. It selects all edges
|
||||
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 layers only.
|
||||
This method is available for edge and edge pair layers.
|
||||
</p>
|
||||
<a name="without_perimeter"/><h2>"without_perimeter" - Selects polygons by perimeter</h2>
|
||||
<keyword name="without_perimeter"/>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
|
||||
source $drc_test_source
|
||||
target $drc_test_target
|
||||
|
||||
if $drc_test_deep
|
||||
deep
|
||||
end
|
||||
|
||||
ep = input(1, 0).drc(space(projection) < 0.5)
|
||||
|
||||
ep.polygons(0).output(100, 0)
|
||||
|
||||
ep.with_distance(0..0.1).polygons(0).output(110, 0)
|
||||
ep.with_distance(0.25, nil).polygons(0).output(111, 0)
|
||||
ep.without_distance(0..0.1).polygons(0).output(120, 0)
|
||||
ep.without_distance(0.25, nil).polygons(0).output(121, 0)
|
||||
|
||||
ep.with_angle(45.0).polygons(0).output(200, 0)
|
||||
ep.with_angle(0.0).polygons(0).output(201, 0)
|
||||
ep.with_angle(45.0..91.0).polygons(0).output(202, 0)
|
||||
ep.with_angle(45.0, both).polygons(0).output(210, 0)
|
||||
ep.with_angle(0.0, both).polygons(0).output(211, 0)
|
||||
ep.with_angle(45.0..91.0, both).polygons(0).output(212, 0)
|
||||
|
||||
ep.without_angle(45.0).polygons(0).output(220, 0)
|
||||
ep.without_angle(0.0).polygons(0).output(221, 0)
|
||||
ep.without_angle(45.0..91.0).polygons(0).output(222, 0)
|
||||
ep.without_angle(45.0, both).polygons(0).output(230, 0)
|
||||
ep.without_angle(0.0, both).polygons(0).output(231, 0)
|
||||
ep.without_angle(45.0..91.0, both).polygons(0).output(232, 0)
|
||||
|
||||
ep.with_length(0.5).polygons(0).output(300, 0)
|
||||
ep.with_length(0.4..0.51).polygons(0).output(301, 0)
|
||||
ep.with_length(0.5, both).polygons(0).output(310, 0)
|
||||
ep.with_length(0.4..0.51, both).polygons(0).output(311, 0)
|
||||
|
||||
ep.without_length(0.5).polygons(0).output(320, 0)
|
||||
ep.without_length(0.4..0.51).polygons(0).output(321, 0)
|
||||
ep.without_length(0.5, both).polygons(0).output(330, 0)
|
||||
ep.without_length(0.4..0.51, both).polygons(0).output(331, 0)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue