mirror of https://github.com/KLayout/klayout.git
WIP: documentation, local merging of polygon for interact, covering ..
This commit is contained in:
parent
aefc3153fe
commit
ae29c75326
|
|
@ -399,7 +399,7 @@ AsIfFlatRegion::selected_interacting_generic (const Edges &other, bool inverse,
|
|||
|
||||
db::RegionIterator polygons (begin_merged ());
|
||||
|
||||
db::interacting_with_edge_local_operation<db::Polygon, db::Edge, db::Polygon> op (inverse, min_count, max_count);
|
||||
db::interacting_with_edge_local_operation<db::Polygon, db::Edge, db::Polygon> op (inverse, min_count, max_count, true);
|
||||
|
||||
db::local_processor<db::Polygon, db::Edge, db::Polygon> proc;
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
|
|
@ -560,7 +560,7 @@ AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, boo
|
|||
|
||||
db::RegionIterator polygons (begin_merged ());
|
||||
|
||||
db::interacting_local_operation<db::Polygon, db::Polygon, db::Polygon> op (mode, touching, inverse, min_count, max_count);
|
||||
db::interacting_local_operation<db::Polygon, db::Polygon, db::Polygon> op (mode, touching, inverse, min_count, max_count, true);
|
||||
|
||||
db::local_processor<db::Polygon, db::Polygon, db::Polygon> proc;
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
|
|
|
|||
|
|
@ -61,6 +61,21 @@ CompoundRegionOperationNode::generated_description () const
|
|||
return std::string ();
|
||||
}
|
||||
|
||||
bool
|
||||
CompoundRegionOperationNode::is_merged () const
|
||||
{
|
||||
std::vector<db::Region *> iv = inputs ();
|
||||
// NOTE: the primary is supposed to be merged always (except in raw mode)
|
||||
return iv.size () == 1 && (is_subject_regionptr (iv.front ()) || iv.front ()->is_merged ());
|
||||
}
|
||||
|
||||
bool
|
||||
CompoundRegionOperationNode::has_external_inputs () const
|
||||
{
|
||||
std::vector<db::Region *> iv = inputs ();
|
||||
return iv.size () == 1 && ! is_subject_regionptr (iv.front ());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
static void translate (db::Layout *layout, const std::vector<std::unordered_set<db::Polygon> > &in, std::vector<std::unordered_set<db::PolygonRef> > &out)
|
||||
|
|
@ -1052,6 +1067,75 @@ template void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_lo
|
|||
template void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_local<db::Polygon, db::EdgePair> (db::Layout *, const shape_interactions<db::Polygon, db::Polygon> &, std::vector<std::unordered_set<db::EdgePair> > &, size_t, double) const;
|
||||
template void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_local<db::PolygonRef, db::EdgePair> (db::Layout *, const shape_interactions<db::PolygonRef, db::PolygonRef> &, std::vector<std::unordered_set<db::EdgePair> > &, size_t, double) const;
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
CompoundRegionInteractOperationNode::CompoundRegionInteractOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b, int mode, bool touching, bool inverse, size_t min_count, size_t max_count)
|
||||
: compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon> (&m_op, a, b), m_op (mode, touching, inverse, min_count, max_count, b->is_merged ())
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
CompoundRegionInteractOperationNode::CompoundRegionInteractOperationNode (db::Region *a, db::Region *b, int mode, bool touching, bool inverse, size_t min_count, size_t max_count)
|
||||
: compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon> (&m_op, a, b), m_op (mode, touching, inverse, min_count, max_count, b->is_merged ())
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
std::string
|
||||
CompoundRegionInteractOperationNode::generated_description () const
|
||||
{
|
||||
return std::string ("interact") + compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon>::generated_description ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
CompoundRegionInteractWithEdgeOperationNode::CompoundRegionInteractWithEdgeOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b, bool inverse, size_t min_count, size_t max_count)
|
||||
: compound_region_generic_operation_node<db::Polygon, db::Edge, db::Polygon> (&m_op, a, b), m_op (inverse, min_count, max_count, b->is_merged ())
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
std::string
|
||||
CompoundRegionInteractWithEdgeOperationNode::generated_description () const
|
||||
{
|
||||
return std::string ("interact") + compound_region_generic_operation_node<db::Polygon, db::Edge, db::Polygon>::generated_description ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
CompoundRegionPullOperationNode::CompoundRegionPullOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b, int mode, bool touching)
|
||||
: compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon> (&m_op, a, b), m_op (mode, touching)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
CompoundRegionPullOperationNode::CompoundRegionPullOperationNode (db::Region *a, db::Region *b, int mode, bool touching)
|
||||
: compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon> (&m_op, a, b), m_op (mode, touching)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
std::string
|
||||
CompoundRegionPullOperationNode::generated_description () const
|
||||
{
|
||||
return std::string ("pull") + compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon>::generated_description ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
CompoundRegionPullWithEdgeOperationNode::CompoundRegionPullWithEdgeOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b)
|
||||
: compound_region_generic_operation_node<db::Polygon, db::Edge, db::Edge> (&m_op, a, b), m_op ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
std::string
|
||||
CompoundRegionPullWithEdgeOperationNode::generated_description () const
|
||||
{
|
||||
return std::string ("pull") + compound_region_generic_operation_node<db::Polygon, db::Edge, db::Edge>::generated_description ();
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
CompoundRegionJoinOperationNode::CompoundRegionJoinOperationNode (const std::vector<CompoundRegionOperationNode *> &inputs)
|
||||
|
|
@ -1514,17 +1598,8 @@ CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (CompoundRegi
|
|||
CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (CompoundRegionOperationNode * /*input*/, CompoundRegionOperationNode *other, db::edge_relation_type rel, bool different_polygons, db::Coord d, const db::RegionCheckOptions &options)
|
||||
: CompoundRegionMultiInputOperationNode (other), m_check (rel, d, options.metrics), m_different_polygons (different_polygons), m_options (options)
|
||||
{
|
||||
m_has_other = false;
|
||||
std::vector<db::Region *> other_inputs = other->inputs ();
|
||||
if (other_inputs.size () > 1) {
|
||||
m_has_other = true;
|
||||
m_is_other_merged = false; // or do we know better?
|
||||
} else if (other_inputs.size () == 1) {
|
||||
if (! is_subject_regionptr (other_inputs.front ())) {
|
||||
m_has_other = true;
|
||||
m_is_other_merged = other_inputs.front ()->is_merged ();
|
||||
}
|
||||
}
|
||||
m_has_other = other->has_external_inputs ();
|
||||
m_is_other_merged = other->is_merged ();
|
||||
|
||||
set_description ("check");
|
||||
|
||||
|
|
|
|||
|
|
@ -104,6 +104,18 @@ public:
|
|||
*/
|
||||
void set_description (const std::string &d);
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether the result is definitely merged
|
||||
* The default implementation is based on a heuristic analysis of the inputs.
|
||||
*/
|
||||
virtual bool is_merged () const;
|
||||
|
||||
/**
|
||||
* @brief Returns a value indicating whether this node provides external inputs
|
||||
* A node has external inputs if it has inputs and does not refer to the primary alone.
|
||||
*/
|
||||
virtual bool has_external_inputs () const;
|
||||
|
||||
/**
|
||||
* @brief Returns a value giving a hint how to handle the case of empty intruders
|
||||
*/
|
||||
|
|
@ -676,22 +688,10 @@ class DB_PUBLIC CompoundRegionInteractOperationNode
|
|||
: public compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon>
|
||||
{
|
||||
public:
|
||||
CompoundRegionInteractOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b, int mode, bool touching, bool inverse, size_t min_count = 0, size_t max_count = std::numeric_limits<size_t>::max ())
|
||||
: compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon> (&m_op, a, b), m_op (mode, touching, inverse, min_count, max_count)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
CompoundRegionInteractOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b, int mode, bool touching, bool inverse, size_t min_count = 0, size_t max_count = std::numeric_limits<size_t>::max ());
|
||||
CompoundRegionInteractOperationNode (db::Region *a, db::Region *b, int mode, bool touching, bool inverse, size_t min_count = 0, size_t max_count = std::numeric_limits<size_t>::max ());
|
||||
|
||||
CompoundRegionInteractOperationNode (db::Region *a, db::Region *b, int mode, bool touching, bool inverse, size_t min_count = 0, size_t max_count = std::numeric_limits<size_t>::max ())
|
||||
: compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon> (&m_op, a, b), m_op (mode, touching, inverse, min_count, max_count)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
std::string generated_description () const
|
||||
{
|
||||
return std::string ("interact") + compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon>::generated_description ();
|
||||
}
|
||||
std::string generated_description () const;
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::Polygon, db::Polygon> &interactions, std::vector<std::unordered_set<db::Polygon> > &results, size_t max_vertex_count, double area_ratio) const
|
||||
{
|
||||
|
|
@ -711,16 +711,9 @@ class DB_PUBLIC CompoundRegionInteractWithEdgeOperationNode
|
|||
: public compound_region_generic_operation_node<db::Polygon, db::Edge, db::Polygon>
|
||||
{
|
||||
public:
|
||||
CompoundRegionInteractWithEdgeOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b, bool inverse, size_t min_count = 0, size_t max_count = std::numeric_limits<size_t>::max ())
|
||||
: compound_region_generic_operation_node<db::Polygon, db::Edge, db::Polygon> (&m_op, a, b), m_op (inverse, min_count, max_count)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
CompoundRegionInteractWithEdgeOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b, bool inverse, size_t min_count = 0, size_t max_count = std::numeric_limits<size_t>::max ());
|
||||
|
||||
std::string generated_description () const
|
||||
{
|
||||
return std::string ("interact") + compound_region_generic_operation_node<db::Polygon, db::Edge, db::Polygon>::generated_description ();
|
||||
}
|
||||
std::string generated_description () const;
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::Polygon, db::Polygon> &interactions, std::vector<std::unordered_set<db::Polygon> > &results, size_t max_vertex_count, double area_ratio) const
|
||||
{
|
||||
|
|
@ -740,22 +733,10 @@ class DB_PUBLIC CompoundRegionPullOperationNode
|
|||
: public compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon>
|
||||
{
|
||||
public:
|
||||
CompoundRegionPullOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b, int mode, bool touching)
|
||||
: compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon> (&m_op, a, b), m_op (mode, touching)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
CompoundRegionPullOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b, int mode, bool touching);
|
||||
CompoundRegionPullOperationNode (db::Region *a, db::Region *b, int mode, bool touching);
|
||||
|
||||
CompoundRegionPullOperationNode (db::Region *a, db::Region *b, int mode, bool touching)
|
||||
: compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon> (&m_op, a, b), m_op (mode, touching)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
std::string generated_description () const
|
||||
{
|
||||
return std::string ("pull") + compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon>::generated_description ();
|
||||
}
|
||||
std::string generated_description () const;
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::Polygon, db::Polygon> &interactions, std::vector<std::unordered_set<db::Polygon> > &results, size_t max_vertex_count, double area_ratio) const
|
||||
{
|
||||
|
|
@ -775,16 +756,9 @@ class DB_PUBLIC CompoundRegionPullWithEdgeOperationNode
|
|||
: public compound_region_generic_operation_node<db::Polygon, db::Edge, db::Edge>
|
||||
{
|
||||
public:
|
||||
CompoundRegionPullWithEdgeOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b)
|
||||
: compound_region_generic_operation_node<db::Polygon, db::Edge, db::Edge> (&m_op, a, b), m_op ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
CompoundRegionPullWithEdgeOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b);
|
||||
|
||||
std::string generated_description () const
|
||||
{
|
||||
return std::string ("pull") + compound_region_generic_operation_node<db::Polygon, db::Edge, db::Edge>::generated_description ();
|
||||
}
|
||||
std::string generated_description () const;
|
||||
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<db::Polygon, db::Polygon> &interactions, std::vector<std::unordered_set<db::Edge> > &results, size_t max_vertex_count, double area_ratio) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1534,7 +1534,7 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
|
|||
|
||||
DeepLayer dl_out (polygons.derived ());
|
||||
|
||||
db::InteractingLocalOperation op (mode, touching, inverse, min_count, max_count);
|
||||
db::InteractingLocalOperation op (mode, touching, inverse, min_count, max_count, true);
|
||||
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell (), polygons.breakout_cells (), other_polygons.breakout_cells ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
|
|
@ -1573,7 +1573,7 @@ DeepRegion::selected_interacting_generic (const Edges &other, bool inverse, size
|
|||
|
||||
DeepLayer dl_out (polygons.derived ());
|
||||
|
||||
db::InteractingWithEdgeLocalOperation op (inverse, min_count, max_count);
|
||||
db::InteractingWithEdgeLocalOperation op (inverse, min_count, max_count, true);
|
||||
|
||||
db::local_processor<db::PolygonRef, db::Edge, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), polygons.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
|
|
|
|||
|
|
@ -233,6 +233,9 @@ check_local_operation<TS, TI>::do_compute_local (db::Layout *layout, const shape
|
|||
|
||||
} else if (! m_other_is_merged && (ids.size () > 1 || ! interactions.intruder_shape (*ids.begin ()).second.is_box ())) {
|
||||
|
||||
// NOTE: this local merge is not necessarily giving the same results than a global merge before running
|
||||
// the processor. Reason: the search range is limited, hence not all necessary components may have been
|
||||
// captured.
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
ep.clear ();
|
||||
|
|
@ -536,9 +539,31 @@ template class DB_PUBLIC check_local_operation<db::Polygon, db::Polygon>;
|
|||
|
||||
// ---------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace {
|
||||
|
||||
class PolygonToEdgeProcessor
|
||||
: public db::PolygonSink
|
||||
{
|
||||
public:
|
||||
PolygonToEdgeProcessor (db::EdgeProcessor *target, size_t *id)
|
||||
: mp_target (target), mp_id (id)
|
||||
{ }
|
||||
|
||||
virtual void put (const db::Polygon &poly)
|
||||
{
|
||||
mp_target->insert (poly, (*mp_id)++);
|
||||
}
|
||||
|
||||
private:
|
||||
db::EdgeProcessor *mp_target;
|
||||
size_t *mp_id;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
interacting_local_operation<TS, TI, TR>::interacting_local_operation (int mode, bool touching, bool inverse, size_t min_count, size_t max_count)
|
||||
: m_mode (mode), m_touching (touching), m_inverse (inverse), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count)
|
||||
interacting_local_operation<TS, TI, TR>::interacting_local_operation (int mode, bool touching, bool inverse, size_t min_count, size_t max_count, bool other_is_merged)
|
||||
: m_mode (mode), m_touching (touching), m_inverse (inverse), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count), m_other_is_merged (other_is_merged)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -588,6 +613,24 @@ void interacting_local_operation<TS, TI, TR>::do_compute_local (db::Layout * /*l
|
|||
}
|
||||
n++;
|
||||
|
||||
} else if (! m_other_is_merged && ! (m_min_count == size_t (1) && m_max_count == std::numeric_limits<size_t>::max ())) {
|
||||
|
||||
// in counted mode we need to merge the shapes because they might overlap
|
||||
db::EdgeProcessor ep_merge;
|
||||
|
||||
size_t i = 0;
|
||||
for (typename std::set<TI>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||
for (typename TI::polygon_edge_iterator e = o->begin_edge (); ! e.at_end (); ++e) {
|
||||
ep_merge.insert (*e, i);
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
PolygonToEdgeProcessor ps (&ep, &n);
|
||||
db::PolygonGenerator pg (ps, false /*don't resolve holes*/, false);
|
||||
db::SimpleMerge op (1 /*wc>0*/);
|
||||
ep_merge.process (pg, op);
|
||||
|
||||
} else {
|
||||
|
||||
for (typename std::set<TI>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||
|
|
@ -743,8 +786,8 @@ template class DB_PUBLIC pull_local_operation<db::Polygon, db::Polygon, db::Poly
|
|||
// ---------------------------------------------------------------------------------------------------------------
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
interacting_with_edge_local_operation<TS, TI, TR>::interacting_with_edge_local_operation (bool inverse, size_t min_count, size_t max_count)
|
||||
: m_inverse (inverse), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count)
|
||||
interacting_with_edge_local_operation<TS, TI, TR>::interacting_with_edge_local_operation (bool inverse, size_t min_count, size_t max_count, bool other_is_merged)
|
||||
: m_inverse (inverse), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count), m_other_is_merged (other_is_merged)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -774,8 +817,33 @@ void interacting_with_edge_local_operation<TS, TI, TR>::do_compute_local (db::La
|
|||
}
|
||||
}
|
||||
|
||||
for (std::set<unsigned int>::const_iterator j = intruder_ids.begin (); j != intruder_ids.end (); ++j) {
|
||||
scanner.insert2 (& interactions.intruder_shape (*j).second, 0);
|
||||
// locally merge the intruder edges if required
|
||||
std::unordered_set<TI> merged_heap;
|
||||
if (! m_other_is_merged && counting) {
|
||||
|
||||
EdgeBooleanClusterCollector<std::unordered_set<TI> > cluster_collector (&merged_heap, EdgeOr);
|
||||
|
||||
db::box_scanner<TI, size_t> merge_scanner;
|
||||
|
||||
for (std::set<unsigned int>::const_iterator j = intruder_ids.begin (); j != intruder_ids.end (); ++j) {
|
||||
const TI *e = &interactions.intruder_shape (*j).second;
|
||||
if (! e->is_degenerate ()) {
|
||||
merge_scanner.insert (e, 0);
|
||||
}
|
||||
}
|
||||
|
||||
merge_scanner.process (cluster_collector, 1, db::box_convert<db::Edge> ());
|
||||
|
||||
for (typename std::unordered_set<TI>::const_iterator e = merged_heap.begin (); e != merged_heap.end (); ++e) {
|
||||
scanner.insert2 (e.operator-> (), 0);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
for (std::set<unsigned int>::const_iterator j = intruder_ids.begin (); j != intruder_ids.end (); ++j) {
|
||||
scanner.insert2 (& interactions.intruder_shape (*j).second, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::list<TR> heap;
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ class interacting_local_operation
|
|||
: public local_operation<TS, TI, TR>
|
||||
{
|
||||
public:
|
||||
interacting_local_operation (int mode, bool touching, bool inverse, size_t min_count, size_t max_count);
|
||||
interacting_local_operation (int mode, bool touching, bool inverse, size_t min_count, size_t max_count, bool other_is_merged);
|
||||
|
||||
virtual db::Coord dist () const;
|
||||
virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const;
|
||||
|
|
@ -236,6 +236,7 @@ private:
|
|||
bool m_touching;
|
||||
bool m_inverse;
|
||||
size_t m_min_count, m_max_count;
|
||||
bool m_other_is_merged;
|
||||
};
|
||||
|
||||
typedef interacting_local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef> InteractingLocalOperation;
|
||||
|
|
@ -264,7 +265,7 @@ class interacting_with_edge_local_operation
|
|||
: public local_operation<TS, TI, TR>
|
||||
{
|
||||
public:
|
||||
interacting_with_edge_local_operation (bool inverse, size_t min_count, size_t max_count);
|
||||
interacting_with_edge_local_operation (bool inverse, size_t min_count, size_t max_count, bool other_is_merged);
|
||||
|
||||
virtual db::Coord dist () const;
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const;
|
||||
|
|
@ -274,6 +275,7 @@ public:
|
|||
private:
|
||||
bool m_inverse;
|
||||
size_t m_min_count, m_max_count;
|
||||
bool m_other_is_merged;
|
||||
};
|
||||
|
||||
typedef interacting_with_edge_local_operation<db::PolygonRef, db::Edge, db::PolygonRef> InteractingWithEdgeLocalOperation;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,52 @@ module DRC
|
|||
# @code
|
||||
# out = in.drc((width < 2.0).polygons)
|
||||
# @/code
|
||||
#
|
||||
# The following global functions are relevant for the DRC expressions:
|
||||
#
|
||||
# @ul
|
||||
# @li \global#angle @/li
|
||||
# @li \global#area @/li
|
||||
# @li \global#bbox_height @/li
|
||||
# @li \global#bbox_max @/li
|
||||
# @li \global#bbox_min @/li
|
||||
# @li \global#bbox_width @/li
|
||||
# @li \global#case @/li
|
||||
# @li \global#corners @/li
|
||||
# @li \global#covering @/li
|
||||
# @li \global#enc @/li
|
||||
# @li \global#enclosing @/li
|
||||
# @li \global#extent_refs @/li
|
||||
# @li \global#extents @/li
|
||||
# @li \global#foreign @/li
|
||||
# @li \global#holes @/li
|
||||
# @li \global#hulls @/li
|
||||
# @li \global#if_all @/li
|
||||
# @li \global#if_any @/li
|
||||
# @li \global#if_none @/li
|
||||
# @li \global#inside @/li
|
||||
# @li \global#interacting @/li
|
||||
# @li \global#iso @/li
|
||||
# @li \global#length @/li
|
||||
# @li \global#middle @/li
|
||||
# @li \global#notch @/li
|
||||
# @li \global#odd_polygons @/li
|
||||
# @li \global#outside @/li
|
||||
# @li \global#overlap @/li
|
||||
# @li \global#overlapping @/li
|
||||
# @li \global#perimeter @/li
|
||||
# @li \global#primary @/li
|
||||
# @li \global#rectangles @/li
|
||||
# @li \global#rectilinear @/li
|
||||
# @li \global#rounded_corners @/li
|
||||
# @li \global#secondary @/li
|
||||
# @li \global#separation @/li
|
||||
# @li \global#sep @/li
|
||||
# @li \global#sized @/li
|
||||
# @li \global#smoothed @/li
|
||||
# @li \global#space @/li
|
||||
# @li \global#width @/li
|
||||
# @/ul
|
||||
#
|
||||
# The following documentation will list the methods available for DRC expression objects.
|
||||
|
||||
|
|
@ -939,6 +985,34 @@ CODE
|
|||
end
|
||||
end
|
||||
|
||||
%w(covering overlapping interacting).each do |f|
|
||||
eval <<"CODE"
|
||||
def #{f}(other)
|
||||
@engine._context("#{f}") do
|
||||
other = @engine._make_node(other)
|
||||
if ! other.is_a?(DRCOpNode)
|
||||
raise("Argument " + other.to_s + " to #{f} must be a DRC expression")
|
||||
end
|
||||
DRCOpNodeInteractingWithCount::new(@engine, self, other, :#{f})
|
||||
end
|
||||
end
|
||||
CODE
|
||||
end
|
||||
|
||||
%w(inside outside).each do |f|
|
||||
eval <<"CODE"
|
||||
def #{f}(other)
|
||||
@engine._context("#{f}") do
|
||||
other = @engine._make_node(other)
|
||||
if ! other.is_a?(DRCOpNode)
|
||||
raise("Argument " + other.to_s + " to #{f} must be a DRC expression")
|
||||
end
|
||||
DRCOpNodeInteracting::new(@engine, self, other, :#{f})
|
||||
end
|
||||
end
|
||||
CODE
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class DRCOpNodeLogicalBool < DRCOpNode
|
||||
|
|
@ -1410,7 +1484,7 @@ class DRCOpNodeInteractingWithCount < DRCOpNodeWithCompare
|
|||
args = [ self.a.create_node(cache), self.b.create_node(cache), self.inverse ]
|
||||
args << (self.gt ? self.gt + 1 : (self.ge ? self.ge : 0))
|
||||
if self.lt || self.le
|
||||
args << (self.lt ? self.lt : self.le + 1)
|
||||
args << (self.lt ? self.lt - 1 : self.le)
|
||||
end
|
||||
factory = { :covering => :new_enclosing,
|
||||
:overlapping => :new_overlapping,
|
||||
|
|
|
|||
|
|
@ -52,18 +52,143 @@ module DRC
|
|||
# using measurement operations like "area" on secondary polygons.
|
||||
#
|
||||
# Here is an example for a generic DRC operation which performs a width
|
||||
# check for less than 0.5.um on the primary shapes.
|
||||
# check for less than 0.5.um on the primary shapes. It uses the \global#width operator:
|
||||
#
|
||||
# @code
|
||||
# out = in.drc(width < 0.5.um)
|
||||
# @/code
|
||||
#
|
||||
# Another example computes a boolean AND between two layers before selecting
|
||||
# the result polygons with an area larger than 1 square micrometer:
|
||||
# Other single or double-bounded conditions are available too, for example:
|
||||
#
|
||||
# @code
|
||||
# other = ... another layer ..
|
||||
# out = in.drc((primary & other).area > 1.0)
|
||||
# out = in.drc(width <= 0.5.um)
|
||||
# out = in.drc(width > 0.5.um)
|
||||
# out = in.drc(width == 0.5.um)
|
||||
# out = in.drc(width != 0.5.um)
|
||||
# out = in.drc(0.2.um < width < 0.5.um)
|
||||
# @/code
|
||||
#
|
||||
# To specify the second input for a two-layer check, specify the second input
|
||||
# with the check function. Here a two-layer separation check is used (\global#separation):
|
||||
#
|
||||
# @code
|
||||
# l1 = input(1, 0)
|
||||
# l2 = input(2, 0)
|
||||
# out = l1.drc(separation(l2) < 0.5.um)
|
||||
# @/code
|
||||
#
|
||||
# The second input of this check function can be a computed expression. In this
|
||||
# case the local loop will first evaluate the expression for the second input and
|
||||
# then use it inside the check.
|
||||
#
|
||||
# Options for the checks are also specified inside the brackets. For example,
|
||||
# to specify a projection metrics for width use:
|
||||
#
|
||||
# @code
|
||||
# out = in.drc(width(projection) < 0.5.um)
|
||||
# @/code
|
||||
#
|
||||
# The "drc" function supports filter operators. These select input or derived polygons
|
||||
# based on their properties. These filters are:
|
||||
#
|
||||
# @ul
|
||||
# @li "\global#area": select polygons based on their area @/li
|
||||
# @li "\global#perimeter": select polygons based on their perimeter @/li
|
||||
# @li "\global#bbox_min", "\global#bbox_max", "\global#bbox_width", "\global#bbox_height": select polygons based on their bounding box properties @/li
|
||||
# @/ul
|
||||
#
|
||||
# For example, to select polygons with an area larger than one square micrometer, use:
|
||||
#
|
||||
# @code
|
||||
# out = in.drc(area > 1.0)
|
||||
# @/code
|
||||
#
|
||||
# For the condition, use the usual numerical bounds like:
|
||||
#
|
||||
# @code
|
||||
# out = in.drc(area == 1.0)
|
||||
# out = in.drc(area <= 1.0)
|
||||
# out = in.drc(0.2 < area < 1.0)
|
||||
# @/code
|
||||
#
|
||||
# The result of the area operation is the input polygon if the area condition is met.
|
||||
#
|
||||
# In the same fashion, "perimeter" applies to the perimeter of the polygon.
|
||||
# "bbox_min" etc. will evaluate a particular dimensions of the polygon's bounding box and
|
||||
# use the respective dimension for filtering the polygon.
|
||||
#
|
||||
# Note that it's basically possible to use the polygon filters on any kind of input.
|
||||
# In fact, plain "area" for example is a shortcut for "\global#primary.area" indicating that
|
||||
# the area of primary shapes are supposed to be computed.
|
||||
# However, any input other than the primary is not necessarily complete or it may
|
||||
# consist of multiple polygons. Hence the computed values may be too big or too small.
|
||||
# It's recommended therefore to use the measurement functions on primary polygons
|
||||
# only.
|
||||
#
|
||||
# The "drc" feature also supports some predicates. "predicates" are boolean values
|
||||
# indicating a certain condition. A predicate filter works in a way that it only
|
||||
# passes the polygons
|
||||
# The predicates available currently are:
|
||||
#
|
||||
# @ul
|
||||
# @li "\global#rectangles": Filters rectangles @/li
|
||||
# @li "\global#rectilinear": Filters rectilinear ("Manhattan") polygons @/li
|
||||
# @/ul
|
||||
#
|
||||
# For the same reason as explained above, it's recommended to use these predicates
|
||||
# standalone, so they act on primary shapes. It's possible to use the predicates
|
||||
# on computed shapes or secondary input, but that may not render the desired results.
|
||||
#
|
||||
# The "!" operator will evaluate the expression behind it and return the
|
||||
# current primary shape if the input is empty and return an empty polygon set
|
||||
# if not. Hence the following filter will deliver all polygons which are
|
||||
# not rectangles:
|
||||
#
|
||||
# @code
|
||||
# out = in.drc(! rectangles)
|
||||
# @/code
|
||||
#
|
||||
# The logical "if_any" or "if_all" statements allow connecting multiple
|
||||
# conditions and evaluate to "true" (means: a non-empty shape set) if either
|
||||
# on input is a non-empty shape set ("if_any") or if all inputs are non-empty
|
||||
# ("if_all"). For example, this will select all polygons which are rectangles
|
||||
# and whose area is larger than 20 quare micrometers:
|
||||
#
|
||||
# @code
|
||||
# out = in.drc(if_all(rectangles, area > 20.0))
|
||||
# @/code
|
||||
#
|
||||
# In fact, "if_all" renders the result of the last expression, provided all
|
||||
# previous ones are non-empty. So this operation will render rectangles
|
||||
# sized by 100 nm and skip all other types of polygons:
|
||||
#
|
||||
# @code
|
||||
# out = in.drc(if_all(rectangles, sized(100.nm)))
|
||||
# @/code
|
||||
#
|
||||
# Contrary to this, the "if_any" operation will render the first non-empty
|
||||
# expression result and skip the following ones. So this example will
|
||||
# size all rectangles by 100 nm and leave all other types of polygons
|
||||
# untouched:
|
||||
#
|
||||
# @code
|
||||
# out = in.drc(if_any(rectangles.sized(100.nm), primary))
|
||||
# @/code
|
||||
#
|
||||
#
|
||||
# The "drc" operations feature polygon manipulations where the input is
|
||||
# either the primary polygon or derived shapes.
|
||||
# Manipulations include sizing ("\global#sized"), corner rounding ("\global#rounded_corners"), smoothing ("\global#smoothed")
|
||||
# and boolean operations.
|
||||
#
|
||||
# This example computes a boolean AND between two layers before selecting
|
||||
# the result polygons with an area larger than 1 square micrometer. Note that
|
||||
# "primary" is a placeholder for the primary shape:
|
||||
#
|
||||
# @code
|
||||
# l1 = input(1, 0)
|
||||
# l2 = input(2, 0)
|
||||
# out = l1.drc((primary & l2).area > 1.0)
|
||||
# @/code
|
||||
#
|
||||
# This example demonstrates how the "drc" operation can improve performance: as the
|
||||
|
|
@ -71,7 +196,64 @@ module DRC
|
|||
# less shapes need to be stored hence reducing the memory overhead and CPU time required
|
||||
# to manage these shapes.
|
||||
#
|
||||
# For more details about the expression see the \DRC# class documentation.
|
||||
# Note that the precise form of the example above is
|
||||
#
|
||||
# @code
|
||||
# out = l1.drc((primary & secondary(l2)).area > 1.0)
|
||||
# @/code
|
||||
#
|
||||
# The "\global#secondar" operator indicates that "l2" is to be used as secondary input to the "drc" function. Only
|
||||
# in this form, the operators of the boolean AND can be reversed:
|
||||
#
|
||||
# @code
|
||||
# out = l1.drc((secondary(l2) & primary).area > 1.0)
|
||||
# @/code
|
||||
#
|
||||
# The expression inside the "drc" function is a Ruby object and can be
|
||||
# stored in variables. If you need the same expression multiple times, it can be
|
||||
# more efficient to use the same Ruby object. In this example, the same expression
|
||||
# is used two times. Hence it's computed two times:
|
||||
#
|
||||
# @code
|
||||
# out = l1.drc(((primary & l2).area == 1.0) + ((primary & l2).area == 2.0))
|
||||
# @/code
|
||||
#
|
||||
# A more efficient version is:
|
||||
#
|
||||
# @code
|
||||
# overlap_area = (primary & l2).area
|
||||
# out = l1.drc((overlap_area == 1.0) + (overlap_area == 2.0))
|
||||
# @/code
|
||||
#
|
||||
# Note that the first line prepares the operation, but does not execute the area computation
|
||||
# or the boolean operation. But when the "drc" function executes the operation it will
|
||||
# only compute the area once as it is represented by the same Ruby object.
|
||||
#
|
||||
#
|
||||
# The "drc" functionality also offers support for edge pairs and edges. Edge pairs
|
||||
# are the results of check operations and can be turned into polygons using the
|
||||
# "polygons" method:
|
||||
#
|
||||
# @code
|
||||
# drc = in.drc((width < 0.5.um).polygons)
|
||||
# @/code
|
||||
#
|
||||
# Similarly, polygons can be converted into edges:
|
||||
#
|
||||
# @code
|
||||
# drc = in.drc(primary.edges)
|
||||
# @/code
|
||||
#
|
||||
# The "drc" framework supports edge vs. edge and edge vs. polygon booleans, edge
|
||||
# filters (\global#length, \global#angle), edge vs. polygon interactions (\global#interacting, \global#overlapping),
|
||||
# edge sampling (\global#start_segments, \global#centers, \global#end_segments) and edge to polygon
|
||||
# conversions (\global#extended, \global#extended_in, \global#extended_out). Edge pairs
|
||||
# can be converted into polygons and edges and separated into first and second edges (\global#first_edges,
|
||||
# \global#second_edges).
|
||||
#
|
||||
#
|
||||
# The bottom line is: DRC expressions are quite rich and there is a lot more to be said and written.
|
||||
# More formal details about the bits and pieces can be found in the \DRC# class documentation.
|
||||
|
||||
def drc(op)
|
||||
@engine._context("drc") do
|
||||
|
|
@ -564,12 +746,8 @@ CODE
|
|||
# @name covering
|
||||
# @brief Selects shapes entirely covering other shapes
|
||||
# @synopsis covering(other) (in conditions)
|
||||
# @synopsis covering(layer, other [, options ])
|
||||
#
|
||||
# This function can be used with a layer argument in which case it
|
||||
# is equivalent to "layer.covering" (see \Layer#covering).
|
||||
#
|
||||
# Without a layer argument, this method represents the selector of primary shapes
|
||||
# This method represents the selector of primary shapes
|
||||
# which entirely cover shapes from the other layer. This version can be put into
|
||||
# a condition indicating how many shapes of the other layer need to be covered.
|
||||
# Use this variant within \DRC# expressions (also see \Layer#drc).
|
||||
|
|
@ -593,32 +771,40 @@ CODE
|
|||
# @name interacting
|
||||
# @brief Selects shapes interacting with other shapes
|
||||
# @synopsis interacting(other) (in conditions)
|
||||
# @synopsis interacting(layer, other [, options ])
|
||||
#
|
||||
# See \covering for a description of the use cases for this function.
|
||||
# When using "interacting", shapes are selected when the interact (overlap, touch)
|
||||
# shapes from the other layer.
|
||||
#
|
||||
# When using this method with a count, the operation may not render
|
||||
# the correct results if the other input is not merged. By nature of the
|
||||
# generic DRC feature, only those shapes that interact with the primary shape
|
||||
# will be selected. If the other input is split into multiple polygons,
|
||||
# not all components may be captured and the computed interaction count
|
||||
# may be incorrect.
|
||||
|
||||
# %DRC%
|
||||
# @name overlapping
|
||||
# @brief Selects shapes overlapping with other shapes
|
||||
# @synopsis overlapping(other) (in conditions)
|
||||
# @synopsis overlapping(layer, other [, options ])
|
||||
#
|
||||
# See \covering for a description of the use cases for this function.
|
||||
# When using "overlapping", shapes are selected when the overlap
|
||||
# shapes from the other layer.
|
||||
#
|
||||
# When using this method with a count, the operation may not render
|
||||
# the correct results if the other input is not merged. By nature of the
|
||||
# generic DRC feature, only those shapes that interact with the primary shape
|
||||
# will be selected. If the other input is split into multiple polygons,
|
||||
# not all components may be captured and the computed interaction count
|
||||
# may be incorrect.
|
||||
|
||||
# %DRC%
|
||||
# @name inside
|
||||
# @brief Selects shapes entirely inside other shapes
|
||||
# @synopsis inside(other)
|
||||
# @synopsis inside(layer, other)
|
||||
#
|
||||
# This function can be used with a layer argument in which case it
|
||||
# is equivalent to "layer.inside" (see \Layer#inside).
|
||||
#
|
||||
# Without a layer argument, this method represents the selector of primary shapes
|
||||
# This method represents the selector of primary shapes
|
||||
# which are entirely inside shapes from the other layer.
|
||||
# Use this variant within \DRC# expressions (also see \Layer#drc).
|
||||
|
||||
|
|
@ -626,12 +812,8 @@ CODE
|
|||
# @name outside
|
||||
# @brief Selects shapes entirely outside other shapes
|
||||
# @synopsis outside(other)
|
||||
# @synopsis outside(layer, other)
|
||||
#
|
||||
# This function can be used with a layer argument in which case it
|
||||
# is equivalent to "layer.outside" (see \Layer#outside).
|
||||
#
|
||||
# Without a layer argument, this method represents the selector of primary shapes
|
||||
# This method represents the selector of primary shapes
|
||||
# which are entirely outside shapes from the other layer.
|
||||
# Use this variant within \DRC# expressions (also see \Layer#drc).
|
||||
|
||||
|
|
@ -642,9 +824,8 @@ CODE
|
|||
outside
|
||||
overlapping
|
||||
).each do |f|
|
||||
# NOTE: these methods are fallback for the respective global ones which route to DRCLayer or here.
|
||||
eval <<"CODE"
|
||||
def _cop_#{f}(other)
|
||||
def #{f}(other)
|
||||
primary.#{f}(other)
|
||||
end
|
||||
CODE
|
||||
|
|
@ -674,6 +855,7 @@ CODE
|
|||
# out = in.drc(enclosing(other) > 0.2.um)
|
||||
# out = in.drc(enclosing(other) >= 0.2.um)
|
||||
# out = in.drc(enclosing(other) == 0.2.um)
|
||||
# out = in.drc(enclosing(other) != 0.2.um)
|
||||
# out = in.drc(0.1.um <= enclosing(other) < 0.2.um)
|
||||
# @/code
|
||||
#
|
||||
|
|
@ -728,6 +910,7 @@ CODE
|
|||
# out = in.drc(width > 0.2.um)
|
||||
# out = in.drc(width >= 0.2.um)
|
||||
# out = in.drc(width == 0.2.um)
|
||||
# out = in.drc(width != 0.2.um)
|
||||
# out = in.drc(0.1.um <= width < 0.2.um)
|
||||
# @/code
|
||||
#
|
||||
|
|
|
|||
|
|
@ -1579,7 +1579,6 @@ CODE
|
|||
bbox
|
||||
centers
|
||||
corners
|
||||
covering
|
||||
end_segments
|
||||
extended
|
||||
extended_in
|
||||
|
|
@ -1591,9 +1590,7 @@ CODE
|
|||
holes
|
||||
hulls
|
||||
in
|
||||
inside
|
||||
inside_part
|
||||
interacting
|
||||
intersections
|
||||
iso
|
||||
isolated
|
||||
|
|
@ -1619,9 +1616,7 @@ CODE
|
|||
ongrid
|
||||
or
|
||||
output
|
||||
outside
|
||||
outside_part
|
||||
overlapping
|
||||
perimeter
|
||||
pull_inside
|
||||
pull_interacting
|
||||
|
|
|
|||
|
|
@ -188,3 +188,13 @@ TEST(12d)
|
|||
{
|
||||
run_test (_this, "12", true);
|
||||
}
|
||||
|
||||
TEST(13)
|
||||
{
|
||||
run_test (_this, "13", false);
|
||||
}
|
||||
|
||||
TEST(13d)
|
||||
{
|
||||
run_test (_this, "13", true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,52 @@ renders edge pairs. To obtain polygons from these edge pairs, use the "polygons"
|
|||
out = in.drc((width < 2.0).polygons)
|
||||
</pre>
|
||||
</p><p>
|
||||
The following global functions are relevant for the DRC expressions:
|
||||
</p><p>
|
||||
<ul>
|
||||
<li><a href="/about/drc_ref_global.xml#case">global#case</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#secondary">global#secondary</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#primary">global#primary</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#foreign">global#foreign</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#if_all">global#if_all</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#if_any">global#if_any</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#if_none">global#if_none</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#bbox_height">global#bbox_height</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#bbox_width">global#bbox_width</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#bbox_max">global#bbox_max</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#bbox_min">global#bbox_min</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#area">global#area</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#hulls">global#hulls</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#holes">global#holes</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#odd_polygons">global#odd_polygons</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#perimeter">global#perimeter</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#rectangles">global#rectangles</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#rectilinear">global#rectilinear</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#length">global#length</a> (in condition) </li>
|
||||
<li><a href="/about/drc_ref_global.xml#angle">global#angle</a> (in condition) </li>
|
||||
<li><a href="/about/drc_ref_global.xml#corners">global#corners</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#extent_refs">global#extent_refs</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#extents">global#extents</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#middle">global#middle</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#rounded_corners">global#rounded_corners</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#sized">global#sized</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#smoothed">global#smoothed</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#covering">global#covering</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#interacting">global#interacting</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#overlapping">global#overlapping</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#inside">global#inside</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#outside">global#outside</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#enclosing">global#enclosing</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#separation">global#separation</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#overlap">global#overlap</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#width">global#width</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#space">global#space</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#notch">global#notch</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#iso">global#iso</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#sep">global#sep</a> </li>
|
||||
<li><a href="/about/drc_ref_global.xml#enc">global#enc</a> </li>
|
||||
</ul>
|
||||
</p><p>
|
||||
The following documentation will list the methods available for DRC expression objects.
|
||||
</p>
|
||||
<h2-index/>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
|
||||
source $drc_test_source
|
||||
target $drc_test_target
|
||||
|
||||
if $drc_test_deep
|
||||
deep
|
||||
end
|
||||
|
||||
l1 = input(1, 0)
|
||||
l2 = input(2, 0)
|
||||
l3 = input(3, 0)
|
||||
|
||||
l1.output(1, 0)
|
||||
l2.output(2, 0)
|
||||
l3.output(3, 0)
|
||||
|
||||
l2.drc(covering(l1)).output(100, 0)
|
||||
l2.drc(! covering(l1)).output(101, 0)
|
||||
|
||||
l1.drc(interacting(l2)).output(110, 0)
|
||||
l1.drc(! interacting(l2)).output(111, 0)
|
||||
l1.drc(interacting(l2) >= 2).output(112, 0)
|
||||
l1.drc(interacting(l2) < 2).output(113, 0)
|
||||
|
||||
l1.drc(overlapping(l2)).output(120, 0)
|
||||
l1.drc(! overlapping(l2)).output(121, 0)
|
||||
l1.drc(overlapping(l2) >= 2).output(122, 0)
|
||||
l1.drc(overlapping(l2) < 2).output(123, 0)
|
||||
|
||||
l1.drc(outside(l2)).output(130, 0)
|
||||
l1.drc(! outside(l2)).output(131, 0)
|
||||
|
||||
l1.drc(inside(l2)).output(140, 0)
|
||||
l1.drc(! inside(l2)).output(141, 0)
|
||||
|
||||
l2e = secondary(l2).edges
|
||||
l1e = primary.edges
|
||||
|
||||
# Secondary edges are supported, but as secondaries are not merged
|
||||
# internally, the result is not well defined for unmerged secondary:
|
||||
|
||||
l1.drc(interacting(l2e)).output(200, 0)
|
||||
l1.drc(! interacting(l2e)).output(201, 0)
|
||||
l1.drc(interacting(l2e) >= 4).output(202, 0)
|
||||
l1.drc(interacting(l2e) < 4).output(203, 0)
|
||||
|
||||
# TODO: edge-to-polygon interactions and edge-to-edge interactions not supported yet
|
||||
|
||||
# l1.drc(l1e.interacting(l2)).output(210, 0)
|
||||
# l1.drc(! l1e.interacting(l2)).output(211, 0)
|
||||
# l1.drc(l1e.interacting(l2) >= 2).output(212, 0)
|
||||
# l1.drc(l1e.interacting(l2) < 2).output(213, 0)
|
||||
|
||||
# l1.drc(l1e.interacting(l2e)).output(210, 0)
|
||||
# l1.drc(! l1e.interacting(l2e)).output(211, 0)
|
||||
# l1.drc(l1e.interacting(l2e) >= 2).output(212, 0)
|
||||
# l1.drc(l1e.interacting(l2e) < 2).output(213, 0)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue