mirror of https://github.com/KLayout/klayout.git
Merge pull request #1821 from KLayout/feature/issue-1816
Feature/issue 1816
This commit is contained in:
commit
bccc421f3d
|
|
@ -27,6 +27,8 @@ SOURCES = \
|
|||
dbEdgePairFilters.cc \
|
||||
dbEdgePairRelations.cc \
|
||||
dbEdgePairs.cc \
|
||||
dbEdgePairsLocalOperations.cc \
|
||||
dbEdgePairsUtils.cc \
|
||||
dbEdgeProcessor.cc \
|
||||
dbEdges.cc \
|
||||
dbEdgesLocalOperations.cc \
|
||||
|
|
@ -250,6 +252,8 @@ HEADERS = \
|
|||
dbEdgePairFilters.h \
|
||||
dbEdgePairRelations.h \
|
||||
dbEdgePairs.h \
|
||||
dbEdgePairsLocalOperations.h \
|
||||
dbEdgePairsUtils.h \
|
||||
dbEdgeProcessor.h \
|
||||
dbEdges.h \
|
||||
dbEdgesLocalOperations.h \
|
||||
|
|
|
|||
|
|
@ -26,8 +26,13 @@
|
|||
#include "dbFlatRegion.h"
|
||||
#include "dbFlatEdges.h"
|
||||
#include "dbEmptyEdgePairs.h"
|
||||
#include "dbEmptyEdges.h"
|
||||
#include "dbEmptyRegion.h"
|
||||
#include "dbEdgePairs.h"
|
||||
#include "dbEdgePairsLocalOperations.h"
|
||||
#include "dbBoxConvert.h"
|
||||
#include "dbRegion.h"
|
||||
#include "dbHierProcessor.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
|
|
@ -241,6 +246,308 @@ AsIfFlatEdgePairs::filtered (const EdgePairFilterBase &filter) const
|
|||
return new_edge_pairs.release ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
AsIfFlatEdgePairs::pull_interacting (const Region &other) const
|
||||
{
|
||||
return pull_generic (other);
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
AsIfFlatEdgePairs::pull_interacting (const Edges &other) const
|
||||
{
|
||||
return pull_generic (other);
|
||||
}
|
||||
|
||||
EdgePairsDelegate *
|
||||
AsIfFlatEdgePairs::selected_interacting (const Region &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, EdgePairsInteract, false, min_count, max_count);
|
||||
}
|
||||
|
||||
EdgePairsDelegate *
|
||||
AsIfFlatEdgePairs::selected_not_interacting (const Region &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, EdgePairsInteract, true, min_count, max_count);
|
||||
}
|
||||
|
||||
EdgePairsDelegate *
|
||||
AsIfFlatEdgePairs::selected_interacting (const Edges &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, false, min_count, max_count);
|
||||
}
|
||||
|
||||
EdgePairsDelegate *
|
||||
AsIfFlatEdgePairs::selected_not_interacting (const Edges &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, true, min_count, max_count);
|
||||
}
|
||||
|
||||
std::pair<EdgePairsDelegate *, EdgePairsDelegate *>
|
||||
AsIfFlatEdgePairs::selected_interacting_pair (const Region &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_pair_generic (other, EdgePairsInteract, min_count, max_count);
|
||||
}
|
||||
|
||||
std::pair<EdgePairsDelegate *, EdgePairsDelegate *>
|
||||
AsIfFlatEdgePairs::selected_interacting_pair (const Edges &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_pair_generic (other, min_count, max_count);
|
||||
}
|
||||
|
||||
EdgePairsDelegate *
|
||||
AsIfFlatEdgePairs::selected_outside (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, EdgePairsOutside, false, size_t (1), std::numeric_limits<size_t>::max ());
|
||||
}
|
||||
|
||||
EdgePairsDelegate *
|
||||
AsIfFlatEdgePairs::selected_not_outside (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, EdgePairsOutside, true, size_t (1), std::numeric_limits<size_t>::max ());
|
||||
}
|
||||
|
||||
std::pair<EdgePairsDelegate *, EdgePairsDelegate *>
|
||||
AsIfFlatEdgePairs::selected_outside_pair (const Region &other) const
|
||||
{
|
||||
return selected_interacting_pair_generic (other, EdgePairsOutside, size_t (1), std::numeric_limits<size_t>::max ());
|
||||
}
|
||||
|
||||
EdgePairsDelegate *
|
||||
AsIfFlatEdgePairs::selected_inside (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, EdgePairsInside, false, size_t (1), std::numeric_limits<size_t>::max ());
|
||||
}
|
||||
|
||||
EdgePairsDelegate *
|
||||
AsIfFlatEdgePairs::selected_not_inside (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, EdgePairsInside, true, size_t (1), std::numeric_limits<size_t>::max ());
|
||||
}
|
||||
|
||||
std::pair<EdgePairsDelegate *, EdgePairsDelegate *>
|
||||
AsIfFlatEdgePairs::selected_inside_pair (const Region &other) const
|
||||
{
|
||||
return selected_interacting_pair_generic (other, EdgePairsInside, size_t (1), std::numeric_limits<size_t>::max ());
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class OutputPairHolder
|
||||
{
|
||||
public:
|
||||
OutputPairHolder (int inverse, bool merged_semantics)
|
||||
{
|
||||
m_e1.reset (new FlatEdgePairs (merged_semantics));
|
||||
m_results.push_back (& m_e1->raw_edge_pairs ());
|
||||
|
||||
if (inverse == 0) {
|
||||
m_e2.reset (new FlatEdgePairs (merged_semantics));
|
||||
m_results.push_back (& m_e2->raw_edge_pairs ());
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<EdgePairsDelegate *, EdgePairsDelegate *> region_pair ()
|
||||
{
|
||||
return std::make_pair (m_e1.release (), m_e2.release ());
|
||||
}
|
||||
|
||||
const std::vector<db::Shapes *> &results () { return m_results; }
|
||||
|
||||
private:
|
||||
std::unique_ptr<FlatEdgePairs> m_e1, m_e2;
|
||||
std::vector<db::Shapes *> m_results;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
AsIfFlatEdgePairs::pull_generic (const Edges &other) const
|
||||
{
|
||||
// shortcuts
|
||||
if (other.empty () || empty ()) {
|
||||
return new EmptyEdges ();
|
||||
}
|
||||
|
||||
db::box_scanner2<db::EdgePair, size_t, db::Edge, size_t> scanner (report_progress (), progress_desc ());
|
||||
|
||||
AddressableEdgePairDelivery e (begin ());
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
scanner.insert1 (e.operator-> (), 0);
|
||||
}
|
||||
|
||||
AddressableEdgeDelivery p = other.addressable_merged_edges ();
|
||||
|
||||
for ( ; ! p.at_end (); ++p) {
|
||||
scanner.insert2 (p.operator-> (), 1);
|
||||
}
|
||||
|
||||
std::unique_ptr<FlatEdges> output (new FlatEdges (true));
|
||||
|
||||
edge_pair_to_edge_interaction_filter<FlatEdges> filter (output.get (), size_t (1), std::numeric_limits<size_t>::max ());
|
||||
scanner.process (filter, 1, db::box_convert<db::EdgePair> (), db::box_convert<db::Edge> ());
|
||||
|
||||
return output.release ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
AsIfFlatEdgePairs::pull_generic (const Region &other) const
|
||||
{
|
||||
// shortcuts
|
||||
if (other.empty () || empty ()) {
|
||||
return new EmptyRegion ();
|
||||
}
|
||||
|
||||
db::box_scanner2<db::EdgePair, size_t, db::Polygon, size_t> scanner (report_progress (), progress_desc ());
|
||||
|
||||
AddressableEdgePairDelivery e (begin ());
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
scanner.insert1 (e.operator-> (), 0);
|
||||
}
|
||||
|
||||
AddressablePolygonDelivery p = other.addressable_merged_polygons ();
|
||||
|
||||
for ( ; ! p.at_end (); ++p) {
|
||||
scanner.insert2 (p.operator-> (), 1);
|
||||
}
|
||||
|
||||
std::unique_ptr<FlatRegion> output (new FlatRegion (true));
|
||||
|
||||
edge_pair_to_polygon_interaction_filter<FlatRegion> filter (output.get (), EdgePairsInteract, size_t (1), std::numeric_limits<size_t>::max ());
|
||||
scanner.process (filter, 1, db::box_convert<db::EdgePair> (), db::box_convert<db::Polygon> ());
|
||||
|
||||
return output.release ();
|
||||
}
|
||||
|
||||
EdgePairsDelegate *
|
||||
AsIfFlatEdgePairs::selected_interacting_generic (const Edges &other, bool inverse, size_t min_count, size_t max_count) const
|
||||
{
|
||||
min_count = std::max (size_t (1), min_count);
|
||||
|
||||
// shortcuts
|
||||
if (max_count < min_count || other.empty () || empty ()) {
|
||||
return inverse ? clone () : new EmptyEdgePairs ();
|
||||
}
|
||||
|
||||
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
|
||||
OutputPairHolder oph (inverse ? 1 : -1, merged_semantics () || is_merged ());
|
||||
|
||||
db::EdgePairsIterator edges (begin ());
|
||||
|
||||
db::EdgePair2EdgeInteractingLocalOperation op (inverse ? db::EdgePair2EdgeInteractingLocalOperation::Inverse : db::EdgePair2EdgeInteractingLocalOperation::Normal, min_count, max_count);
|
||||
|
||||
db::local_processor<db::EdgePair, db::Edge, db::EdgePair> proc;
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
|
||||
std::vector<generic_shape_iterator<db::Edge> > others;
|
||||
// NOTE: with counting the other edge collection needs to be merged
|
||||
others.push_back (counting ? other.begin_merged () : other.begin ());
|
||||
|
||||
proc.run_flat (edges, others, std::vector<bool> (), &op, oph.results ());
|
||||
|
||||
return oph.region_pair ().first;
|
||||
}
|
||||
|
||||
EdgePairsDelegate *
|
||||
AsIfFlatEdgePairs::selected_interacting_generic (const Region &other, EdgePairInteractionMode mode, bool inverse, size_t min_count, size_t max_count) const
|
||||
{
|
||||
min_count = std::max (size_t (1), min_count);
|
||||
|
||||
// shortcuts
|
||||
if (max_count < min_count || other.empty () || empty ()) {
|
||||
return ((mode == EdgePairsOutside) == inverse) ? new EmptyEdgePairs () : clone ();
|
||||
}
|
||||
|
||||
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
|
||||
OutputPairHolder oph (inverse ? 1 : -1, merged_semantics () || is_merged ());
|
||||
|
||||
db::EdgePairsIterator edges (begin ());
|
||||
|
||||
db::edge_pair_to_polygon_interacting_local_operation<db::Polygon> op (mode, inverse ? db::edge_pair_to_polygon_interacting_local_operation<db::Polygon>::Inverse : db::edge_pair_to_polygon_interacting_local_operation<db::Polygon>::Normal, min_count, max_count);
|
||||
|
||||
db::local_processor<db::EdgePair, db::Polygon, db::EdgePair> proc;
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
|
||||
std::vector<generic_shape_iterator<db::Polygon> > others;
|
||||
// NOTE: with counting the other region needs to be merged
|
||||
others.push_back (counting || mode != EdgePairsInteract ? other.begin_merged () : other.begin ());
|
||||
|
||||
proc.run_flat (edges, others, std::vector<bool> (), &op, oph.results ());
|
||||
|
||||
return oph.region_pair ().first;
|
||||
}
|
||||
|
||||
std::pair<EdgePairsDelegate *, EdgePairsDelegate *>
|
||||
AsIfFlatEdgePairs::selected_interacting_pair_generic (const Edges &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
min_count = std::max (size_t (1), min_count);
|
||||
|
||||
// shortcuts
|
||||
if (max_count < min_count || other.empty () || empty ()) {
|
||||
return std::make_pair (new EmptyEdgePairs (), clone ());
|
||||
}
|
||||
|
||||
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
|
||||
OutputPairHolder oph (0, merged_semantics () || is_merged ());
|
||||
|
||||
db::EdgePairsIterator edges (begin ());
|
||||
|
||||
db::EdgePair2EdgeInteractingLocalOperation op (db::EdgePair2EdgeInteractingLocalOperation::Both, min_count, max_count);
|
||||
|
||||
db::local_processor<db::EdgePair, db::Edge, db::EdgePair> proc;
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
|
||||
std::vector<generic_shape_iterator<db::Edge> > others;
|
||||
// NOTE: with counting the other region needs to be merged
|
||||
others.push_back (counting ? other.begin_merged () : other.begin ());
|
||||
|
||||
proc.run_flat (edges, others, std::vector<bool> (), &op, oph.results ());
|
||||
|
||||
return oph.region_pair ();
|
||||
}
|
||||
|
||||
std::pair<EdgePairsDelegate *, EdgePairsDelegate *>
|
||||
AsIfFlatEdgePairs::selected_interacting_pair_generic (const Region &other, EdgePairInteractionMode mode, size_t min_count, size_t max_count) const
|
||||
{
|
||||
min_count = std::max (size_t (1), min_count);
|
||||
|
||||
// shortcuts
|
||||
if (max_count < min_count || other.empty () || empty ()) {
|
||||
if (mode != EdgePairsOutside) {
|
||||
return std::make_pair (new EmptyEdgePairs (), clone ());
|
||||
} else {
|
||||
return std::make_pair (clone (), new EmptyEdgePairs ());
|
||||
}
|
||||
}
|
||||
|
||||
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
|
||||
OutputPairHolder oph (0, merged_semantics () || is_merged ());
|
||||
|
||||
db::EdgePairsIterator edges (begin ());
|
||||
|
||||
db::edge_pair_to_polygon_interacting_local_operation<db::Polygon> op (mode, db::edge_pair_to_polygon_interacting_local_operation<db::Polygon>::Both, min_count, max_count);
|
||||
|
||||
db::local_processor<db::EdgePair, db::Polygon, db::EdgePair> proc;
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_description (progress_desc ());
|
||||
proc.set_report_progress (report_progress ());
|
||||
|
||||
std::vector<generic_shape_iterator<db::Polygon> > others;
|
||||
// NOTE: with counting the other region needs to be merged
|
||||
others.push_back (counting || mode != EdgePairsInteract ? other.begin_merged () : other.begin ());
|
||||
|
||||
proc.run_flat (edges, others, std::vector<bool> (), &op, oph.results ());
|
||||
|
||||
return oph.region_pair ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
AsIfFlatEdgePairs::polygons (db::Coord e) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "dbCommon.h"
|
||||
|
||||
#include "dbEdgePairsDelegate.h"
|
||||
#include "dbEdgePairsUtils.h"
|
||||
|
||||
namespace db {
|
||||
|
||||
|
|
@ -62,6 +63,22 @@ public:
|
|||
virtual RegionDelegate *processed_to_polygons (const EdgePairToPolygonProcessorBase &proc) const;
|
||||
virtual EdgesDelegate *processed_to_edges (const EdgePairToEdgeProcessorBase &proc) const;
|
||||
|
||||
virtual RegionDelegate *pull_interacting (const Region &) const;
|
||||
virtual EdgesDelegate *pull_interacting (const Edges &) const;
|
||||
virtual EdgePairsDelegate *selected_interacting (const Region &other, size_t min_count, size_t max_count) const;
|
||||
virtual EdgePairsDelegate *selected_not_interacting (const Region &other, size_t min_count, size_t max_count) const;
|
||||
virtual EdgePairsDelegate *selected_interacting (const Edges &other, size_t min_count, size_t max_count) const;
|
||||
virtual EdgePairsDelegate *selected_not_interacting (const Edges &other, size_t min_count, size_t max_count) const;
|
||||
virtual std::pair<EdgePairsDelegate *, EdgePairsDelegate *> selected_interacting_pair (const Region &other, size_t min_count, size_t max_count) const;
|
||||
virtual std::pair<EdgePairsDelegate *, EdgePairsDelegate *> selected_interacting_pair (const Edges &other, size_t min_count, size_t max_count) const;
|
||||
|
||||
virtual EdgePairsDelegate *selected_outside (const Region &other) const;
|
||||
virtual EdgePairsDelegate *selected_not_outside (const Region &other) const;
|
||||
virtual std::pair<EdgePairsDelegate *, EdgePairsDelegate *> selected_outside_pair (const Region &other) const;
|
||||
virtual EdgePairsDelegate *selected_inside (const Region &other) const;
|
||||
virtual EdgePairsDelegate *selected_not_inside (const Region &other) const;
|
||||
virtual std::pair<EdgePairsDelegate *, EdgePairsDelegate *> selected_inside_pair (const Region &other) const;
|
||||
|
||||
virtual EdgePairsDelegate *add_in_place (const EdgePairs &other)
|
||||
{
|
||||
return add (other);
|
||||
|
|
@ -85,6 +102,12 @@ public:
|
|||
protected:
|
||||
void update_bbox (const db::Box &box);
|
||||
void invalidate_bbox ();
|
||||
virtual EdgesDelegate *pull_generic (const Edges &other) const;
|
||||
virtual RegionDelegate *pull_generic (const Region &other) const;
|
||||
virtual EdgePairsDelegate *selected_interacting_generic (const Edges &other, bool inverse, size_t min_count, size_t max_count) const;
|
||||
virtual std::pair<EdgePairsDelegate *, EdgePairsDelegate *> selected_interacting_pair_generic (const Edges &other, size_t min_count, size_t max_count) const;
|
||||
virtual EdgePairsDelegate *selected_interacting_generic (const Region &other, EdgePairInteractionMode mode, bool inverse, size_t min_count, size_t max_count) const;
|
||||
virtual std::pair<EdgePairsDelegate *, EdgePairsDelegate *> selected_interacting_pair_generic (const Region &other, EdgePairInteractionMode mode, size_t min_count, size_t max_count) const;
|
||||
|
||||
private:
|
||||
friend class DeepEdgePairs;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@
|
|||
#include "dbDeepRegion.h"
|
||||
#include "dbCellMapping.h"
|
||||
#include "dbLayoutUtils.h"
|
||||
#include "dbEdgePairsLocalOperations.h"
|
||||
#include "dbHierProcessor.h"
|
||||
#include "dbRegion.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
|
|
@ -497,6 +500,192 @@ RegionDelegate *DeepEdgePairs::polygons (db::Coord e) const
|
|||
return new db::DeepRegion (new_layer);
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
DeepEdgePairs::pull_generic (const Edges &other) const
|
||||
{
|
||||
std::unique_ptr<db::DeepEdges> dr_holder;
|
||||
const db::DeepEdges *other_deep = dynamic_cast<const db::DeepEdges *> (other.delegate ());
|
||||
if (! other_deep) {
|
||||
// if the other region isn't deep, turn into a top-level only deep region to facilitate re-hierarchization
|
||||
dr_holder.reset (new db::DeepEdges (other, const_cast<db::DeepShapeStore &> (*deep_layer ().store ())));
|
||||
other_deep = dr_holder.get ();
|
||||
}
|
||||
|
||||
const db::DeepLayer &edge_pairs = deep_layer ();
|
||||
const db::DeepLayer &other_edges = other_deep->merged_deep_layer ();
|
||||
|
||||
DeepLayer dl_out (other_edges.derived ());
|
||||
|
||||
db::EdgePair2EdgePullLocalOperation op;
|
||||
|
||||
db::local_processor<db::EdgePair, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&edge_pairs.layout ()), const_cast<db::Cell *> (&edge_pairs.initial_cell ()), &other_edges.layout (), &other_edges.initial_cell (), edge_pairs.breakout_cells (), other_edges.breakout_cells ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (edge_pairs.store ()->threads ());
|
||||
|
||||
proc.run (&op, edge_pairs.layer (), other_edges.layer (), dl_out.layer ());
|
||||
|
||||
return new db::DeepEdges (dl_out);
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
DeepEdgePairs::pull_generic (const Region &other) const
|
||||
{
|
||||
std::unique_ptr<db::DeepRegion> dr_holder;
|
||||
const db::DeepRegion *other_deep = dynamic_cast<const db::DeepRegion *> (other.delegate ());
|
||||
if (! other_deep) {
|
||||
// if the other region isn't deep, turn into a top-level only deep region to facilitate re-hierarchization
|
||||
dr_holder.reset (new db::DeepRegion (other, const_cast<db::DeepShapeStore &> (*deep_layer ().store ())));
|
||||
other_deep = dr_holder.get ();
|
||||
}
|
||||
|
||||
const db::DeepLayer &edge_pairs = deep_layer ();
|
||||
const db::DeepLayer &other_polygons = other_deep->merged_deep_layer ();
|
||||
|
||||
DeepLayer dl_out (other_polygons.derived ());
|
||||
|
||||
db::EdgePair2PolygonPullLocalOperation op;
|
||||
|
||||
db::local_processor<db::EdgePair, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&edge_pairs.layout ()), const_cast<db::Cell *> (&edge_pairs.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell (), edge_pairs.breakout_cells (), other_polygons.breakout_cells ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (edge_pairs.store ()->threads ());
|
||||
|
||||
proc.run (&op, edge_pairs.layer (), other_polygons.layer (), dl_out.layer ());
|
||||
|
||||
return new db::DeepRegion (dl_out);
|
||||
}
|
||||
|
||||
EdgePairsDelegate *
|
||||
DeepEdgePairs::selected_interacting_generic (const Edges &other, bool inverse, size_t min_count, size_t max_count) const
|
||||
{
|
||||
std::unique_ptr<db::DeepEdges> dr_holder;
|
||||
const db::DeepEdges *other_deep = dynamic_cast<const db::DeepEdges *> (other.delegate ());
|
||||
if (! other_deep) {
|
||||
// if the other region isn't deep, turn into a top-level only deep region to facilitate re-hierarchization
|
||||
dr_holder.reset (new db::DeepEdges (other, const_cast<db::DeepShapeStore &> (*deep_layer ().store ())));
|
||||
other_deep = dr_holder.get ();
|
||||
}
|
||||
|
||||
min_count = std::max (size_t (1), min_count);
|
||||
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
|
||||
|
||||
const db::DeepLayer &edge_pairs = deep_layer ();
|
||||
|
||||
DeepLayer dl_out (edge_pairs.derived ());
|
||||
|
||||
db::EdgePair2EdgeInteractingLocalOperation op (inverse ? db::EdgePair2EdgeInteractingLocalOperation::Inverse : db::EdgePair2EdgeInteractingLocalOperation::Normal, min_count, max_count);
|
||||
|
||||
db::local_processor<db::EdgePair, db::Edge, db::EdgePair> proc (const_cast<db::Layout *> (&edge_pairs.layout ()), const_cast<db::Cell *> (&edge_pairs.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), edge_pairs.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (edge_pairs.store ()->threads ());
|
||||
|
||||
// NOTE: with counting the other region needs to be merged
|
||||
proc.run (&op, edge_pairs.layer (), (counting ? other_deep->merged_deep_layer () : other_deep->deep_layer ()).layer (), dl_out.layer ());
|
||||
|
||||
return new db::DeepEdgePairs (dl_out);
|
||||
}
|
||||
|
||||
EdgePairsDelegate *
|
||||
DeepEdgePairs::selected_interacting_generic (const Region &other, EdgePairInteractionMode mode, bool inverse, size_t min_count, size_t max_count) const
|
||||
{
|
||||
std::unique_ptr<db::DeepRegion> dr_holder;
|
||||
const db::DeepRegion *other_deep = dynamic_cast<const db::DeepRegion *> (other.delegate ());
|
||||
if (! other_deep) {
|
||||
// if the other region isn't deep, turn into a top-level only deep region to facilitate re-hierarchization
|
||||
dr_holder.reset (new db::DeepRegion (other, const_cast<db::DeepShapeStore &> (*deep_layer ().store ())));
|
||||
other_deep = dr_holder.get ();
|
||||
}
|
||||
|
||||
min_count = std::max (size_t (1), min_count);
|
||||
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
|
||||
|
||||
const db::DeepLayer &edge_pairs = deep_layer ();
|
||||
|
||||
DeepLayer dl_out (edge_pairs.derived ());
|
||||
|
||||
db::edge_pair_to_polygon_interacting_local_operation<db::PolygonRef> op (mode, inverse ? db::edge_pair_to_polygon_interacting_local_operation<db::PolygonRef>::Inverse : db::edge_pair_to_polygon_interacting_local_operation<db::PolygonRef>::Normal, min_count, max_count);
|
||||
|
||||
db::local_processor<db::EdgePair, db::PolygonRef, db::EdgePair> proc (const_cast<db::Layout *> (&edge_pairs.layout ()), const_cast<db::Cell *> (&edge_pairs.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), edge_pairs.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (edge_pairs.store ()->threads ());
|
||||
|
||||
// NOTE: with counting the other region needs to be merged
|
||||
proc.run (&op, edge_pairs.layer (), (counting || mode != EdgePairsInteract ? other_deep->merged_deep_layer () : other_deep->deep_layer ()).layer (), dl_out.layer ());
|
||||
|
||||
return new db::DeepEdgePairs (dl_out);
|
||||
}
|
||||
|
||||
std::pair<EdgePairsDelegate *, EdgePairsDelegate *>
|
||||
DeepEdgePairs::selected_interacting_pair_generic (const Edges &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
std::unique_ptr<db::DeepEdges> dr_holder;
|
||||
const db::DeepEdges *other_deep = dynamic_cast<const db::DeepEdges *> (other.delegate ());
|
||||
if (! other_deep) {
|
||||
// if the other region isn't deep, turn into a top-level only deep region to facilitate re-hierarchization
|
||||
dr_holder.reset (new db::DeepEdges (other, const_cast<db::DeepShapeStore &> (*deep_layer ().store ())));
|
||||
other_deep = dr_holder.get ();
|
||||
}
|
||||
|
||||
min_count = std::max (size_t (1), min_count);
|
||||
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
|
||||
|
||||
const db::DeepLayer &edge_pairs = deep_layer ();
|
||||
|
||||
DeepLayer dl_out (edge_pairs.derived ());
|
||||
DeepLayer dl_out2 (edge_pairs.derived ());
|
||||
|
||||
std::vector<unsigned int> output_layers;
|
||||
output_layers.reserve (2);
|
||||
output_layers.push_back (dl_out.layer ());
|
||||
output_layers.push_back (dl_out2.layer ());
|
||||
|
||||
db::EdgePair2EdgeInteractingLocalOperation op (db::EdgePair2EdgeInteractingLocalOperation::Both, min_count, max_count);
|
||||
|
||||
db::local_processor<db::EdgePair, db::Edge, db::EdgePair> proc (const_cast<db::Layout *> (&edge_pairs.layout ()), const_cast<db::Cell *> (&edge_pairs.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), edge_pairs.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (edge_pairs.store ()->threads ());
|
||||
|
||||
// NOTE: with counting the other region needs to be merged
|
||||
proc.run (&op, edge_pairs.layer (), (counting ? other_deep->merged_deep_layer () : other_deep->deep_layer ()).layer (), output_layers);
|
||||
|
||||
return std::make_pair (new db::DeepEdgePairs (dl_out), new db::DeepEdgePairs (dl_out2));
|
||||
}
|
||||
|
||||
std::pair<EdgePairsDelegate *, EdgePairsDelegate *>
|
||||
DeepEdgePairs::selected_interacting_pair_generic (const Region &other, EdgePairInteractionMode mode, size_t min_count, size_t max_count) const
|
||||
{
|
||||
std::unique_ptr<db::DeepRegion> dr_holder;
|
||||
const db::DeepRegion *other_deep = dynamic_cast<const db::DeepRegion *> (other.delegate ());
|
||||
if (! other_deep) {
|
||||
// if the other region isn't deep, turn into a top-level only deep region to facilitate re-hierarchization
|
||||
dr_holder.reset (new db::DeepRegion (other, const_cast<db::DeepShapeStore &> (*deep_layer ().store ())));
|
||||
other_deep = dr_holder.get ();
|
||||
}
|
||||
|
||||
min_count = std::max (size_t (1), min_count);
|
||||
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
|
||||
|
||||
const db::DeepLayer &edge_pairs = deep_layer ();
|
||||
|
||||
DeepLayer dl_out (edge_pairs.derived ());
|
||||
DeepLayer dl_out2 (edge_pairs.derived ());
|
||||
|
||||
std::vector<unsigned int> output_layers;
|
||||
output_layers.reserve (2);
|
||||
output_layers.push_back (dl_out.layer ());
|
||||
output_layers.push_back (dl_out2.layer ());
|
||||
|
||||
db::edge_pair_to_polygon_interacting_local_operation<db::PolygonRef> op (mode, db::edge_pair_to_polygon_interacting_local_operation<db::PolygonRef>::Both, min_count, max_count);
|
||||
|
||||
db::local_processor<db::EdgePair, db::PolygonRef, db::EdgePair> proc (const_cast<db::Layout *> (&edge_pairs.layout ()), const_cast<db::Cell *> (&edge_pairs.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), edge_pairs.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (edge_pairs.store ()->threads ());
|
||||
|
||||
// NOTE: with counting the other region needs to be merged
|
||||
proc.run (&op, edge_pairs.layer (), (counting || mode != EdgePairsInteract ? other_deep->merged_deep_layer () : other_deep->deep_layer ()).layer (), output_layers);
|
||||
|
||||
return std::make_pair (new db::DeepEdgePairs (dl_out), new db::DeepEdgePairs (dl_out2));
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdgePairs::generic_edges (bool first, bool second) const
|
||||
{
|
||||
db::DeepLayer new_layer = deep_layer ().derived ();
|
||||
|
|
|
|||
|
|
@ -104,6 +104,14 @@ public:
|
|||
return this;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual EdgesDelegate *pull_generic (const Edges &other) const;
|
||||
virtual RegionDelegate *pull_generic (const Region &other) const;
|
||||
virtual EdgePairsDelegate *selected_interacting_generic (const Edges &other, bool inverse, size_t min_count, size_t max_count) const;
|
||||
virtual std::pair<EdgePairsDelegate *, EdgePairsDelegate *> selected_interacting_pair_generic (const Edges &other, size_t min_count, size_t max_count) const;
|
||||
virtual EdgePairsDelegate *selected_interacting_generic (const Region &other, EdgePairInteractionMode mode, bool inverse, size_t min_count, size_t max_count) const;
|
||||
virtual std::pair<EdgePairsDelegate *, EdgePairsDelegate *> selected_interacting_pair_generic (const Region &other, EdgePairInteractionMode mode, size_t min_count, size_t max_count) const;
|
||||
|
||||
private:
|
||||
DeepEdgePairs &operator= (const DeepEdgePairs &other);
|
||||
|
||||
|
|
|
|||
|
|
@ -224,6 +224,16 @@ void EdgePairs::second_edges (Edges &output) const
|
|||
output.set_delegate (mp_delegate->second_edges ());
|
||||
}
|
||||
|
||||
void EdgePairs::pull_interacting (Region &output, const Region &other) const
|
||||
{
|
||||
output = Region (mp_delegate->pull_interacting (other));
|
||||
}
|
||||
|
||||
void EdgePairs::pull_interacting (Edges &output, const Edges &other) const
|
||||
{
|
||||
output = Edges (mp_delegate->pull_interacting (other));
|
||||
}
|
||||
|
||||
void EdgePairs::set_delegate (EdgePairsDelegate *delegate)
|
||||
{
|
||||
if (delegate != mp_delegate) {
|
||||
|
|
|
|||
|
|
@ -217,6 +217,16 @@ public:
|
|||
return mp_delegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Takes the underlying delegate object
|
||||
*/
|
||||
EdgePairsDelegate *take_delegate ()
|
||||
{
|
||||
EdgePairsDelegate *delegate = mp_delegate;
|
||||
mp_delegate = 0;
|
||||
return delegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Iterator of the edge pair set
|
||||
*
|
||||
|
|
@ -370,6 +380,214 @@ public:
|
|||
*/
|
||||
void processed (Edges &output, const EdgePairToEdgeProcessorBase &proc) const;
|
||||
|
||||
/**
|
||||
* @brief Selects all polygons of the region set which overlap or touch edges from this edge pair set
|
||||
*
|
||||
* Merged semantics applies for the other region. Merged polygons will be selected from the other region
|
||||
* if merged semantics is enabled.
|
||||
*/
|
||||
void pull_interacting (Region &output, const Region &other) const;
|
||||
|
||||
/**
|
||||
* @brief Selects all edges of the other edge set which overlap or touch edges from this edge pair set
|
||||
*
|
||||
* Merged semantics applies. If merged semantics is chosen, the connected edge parts will be
|
||||
* selected as a whole from other.
|
||||
*/
|
||||
void pull_interacting (Edges &output, const Edges &other) const;
|
||||
|
||||
/**
|
||||
* @brief Selects all edge pairs of this set which overlap or touch with polygons from the region
|
||||
*/
|
||||
EdgePairs &select_interacting (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ())
|
||||
{
|
||||
set_delegate (mp_delegate->selected_interacting (other, min_count, max_count));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all edge pairs of this set which overlap or touch with polygons from the region
|
||||
*
|
||||
* This method is an out-of-place version of select_interacting.
|
||||
*/
|
||||
EdgePairs selected_interacting (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const
|
||||
{
|
||||
return EdgePairs (mp_delegate->selected_interacting (other, min_count, max_count));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Selects all edge pairs of this set which do not overlap or touch with polygons from the region
|
||||
*/
|
||||
EdgePairs &select_not_interacting (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ())
|
||||
{
|
||||
set_delegate (mp_delegate->selected_not_interacting (other, min_count, max_count));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all edge pairs of this set which do not overlap or touch with polygons from the region
|
||||
*
|
||||
* This method is an out-of-place version of select_not_interacting.
|
||||
*/
|
||||
EdgePairs selected_not_interacting (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const
|
||||
{
|
||||
return EdgePairs (mp_delegate->selected_not_interacting (other, min_count, max_count));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all edge pairs of this set which do not overlap or touch with polygons from the region together with the ones that do not
|
||||
*/
|
||||
std::pair<EdgePairs, EdgePairs> selected_interacting_differential (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const
|
||||
{
|
||||
std::pair<db::EdgePairsDelegate *, db::EdgePairsDelegate *> p = mp_delegate->selected_interacting_pair (other, min_count, max_count);
|
||||
return std::pair<EdgePairs, EdgePairs> (EdgePairs (p.first), EdgePairs (p.second));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Selects all edge pairs of this collection which are completely outside polygons from the region
|
||||
*/
|
||||
EdgePairs &select_outside (const Region &other)
|
||||
{
|
||||
set_delegate (mp_delegate->selected_outside (other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Selects all edge pairs of this collection which are not completely outside polygons from the region
|
||||
*/
|
||||
EdgePairs &select_not_outside (const Region &other)
|
||||
{
|
||||
set_delegate (mp_delegate->selected_not_outside (other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all edge pairs of this collection which are completely outside polygons from the region
|
||||
*
|
||||
* This method is an out-of-place version of select_outside.
|
||||
*/
|
||||
EdgePairs selected_outside (const Region &other) const
|
||||
{
|
||||
return EdgePairs (mp_delegate->selected_outside (other));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all edge pairs of this collection which are not completely outside polygons from the region
|
||||
*
|
||||
* This method is an out-of-place version of select_not_outside.
|
||||
*/
|
||||
EdgePairs selected_not_outside (const Region &other) const
|
||||
{
|
||||
return EdgePairs (mp_delegate->selected_not_outside (other));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all edge pairs of this which are completely outside polygons from the region and the opposite ones at the same time
|
||||
*
|
||||
* This method is equivalent to calling selected_outside and selected_not_outside, but faster.
|
||||
*/
|
||||
std::pair<EdgePairs, EdgePairs> selected_outside_differential (const Region &other) const
|
||||
{
|
||||
std::pair<db::EdgePairsDelegate *, db::EdgePairsDelegate *> p = mp_delegate->selected_outside_pair (other);
|
||||
return std::pair<EdgePairs, EdgePairs> (EdgePairs (p.first), EdgePairs (p.second));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Selects all edge pairs of this collection which are completely inside polygons from the region
|
||||
*/
|
||||
EdgePairs &select_inside (const Region &other)
|
||||
{
|
||||
set_delegate (mp_delegate->selected_inside (other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Selects all edge pairs of this collection which are not completely inside polygons from the region
|
||||
*/
|
||||
EdgePairs &select_not_inside (const Region &other)
|
||||
{
|
||||
set_delegate (mp_delegate->selected_not_inside (other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all edge pairs of this which are completely inside polygons from the region
|
||||
*
|
||||
* This method is an out-of-place version of select_inside.
|
||||
*/
|
||||
EdgePairs selected_inside (const Region &other) const
|
||||
{
|
||||
return EdgePairs (mp_delegate->selected_inside (other));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all edge pairs of this which are not completely inside polygons from the region
|
||||
*
|
||||
* This method is an out-of-place version of select_not_inside.
|
||||
*/
|
||||
EdgePairs selected_not_inside (const Region &other) const
|
||||
{
|
||||
return EdgePairs (mp_delegate->selected_not_inside (other));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all edge pairs of this which are completely inside polygons from the region and the opposite ones at the same time
|
||||
*
|
||||
* This method is equivalent to calling selected_inside and selected_not_inside, but faster.
|
||||
*/
|
||||
std::pair<EdgePairs, EdgePairs> selected_inside_differential (const Region &other) const
|
||||
{
|
||||
std::pair<db::EdgePairsDelegate *, db::EdgePairsDelegate *> p = mp_delegate->selected_inside_pair (other);
|
||||
return std::pair<EdgePairs, EdgePairs> (EdgePairs (p.first), EdgePairs (p.second));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Selects all edge pairs of this edge pairs set which overlap or touch with edges from the edge set
|
||||
*/
|
||||
EdgePairs &select_interacting (const Edges &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ())
|
||||
{
|
||||
set_delegate (mp_delegate->selected_interacting (other, min_count, max_count));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all edge pairs of this edge pairs set which overlap or touch with edges from the edge set
|
||||
*
|
||||
* This method is an out-of-place version of select_interacting.
|
||||
*/
|
||||
EdgePairs selected_interacting (const Edges &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const
|
||||
{
|
||||
return EdgePairs (mp_delegate->selected_interacting (other, min_count, max_count));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all edge pairs of this edge set which do not overlap or touch with edges from the other edge set together with the ones that do not
|
||||
*/
|
||||
std::pair<EdgePairs, EdgePairs> selected_interacting_differential (const Edges &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const
|
||||
{
|
||||
std::pair<db::EdgePairsDelegate *, db::EdgePairsDelegate *> p = mp_delegate->selected_interacting_pair (other, min_count, max_count);
|
||||
return std::pair<EdgePairs, EdgePairs> (EdgePairs (p.first), EdgePairs (p.second));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Selects all edge pairs of this edge pairs set which do not overlap or touch with edges from the edge set
|
||||
*/
|
||||
EdgePairs &select_not_interacting (const Edges &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ())
|
||||
{
|
||||
set_delegate (mp_delegate->selected_not_interacting (other, min_count, max_count));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all edge pairs of this edge pairs set which do not overlap or touch with edges from the edge set
|
||||
*
|
||||
* This method is an out-of-place version of select_not_interacting.
|
||||
*/
|
||||
EdgePairs selected_not_interacting (const Edges &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const
|
||||
{
|
||||
return EdgePairs (mp_delegate->selected_not_interacting (other, min_count, max_count));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transforms the edge pair set
|
||||
*/
|
||||
|
|
@ -559,6 +777,26 @@ public:
|
|||
*/
|
||||
void second_edges (Edges &output) const;
|
||||
|
||||
/**
|
||||
* @brief Sets the base verbosity
|
||||
*
|
||||
* Setting this value will make timing measurements appear at least at
|
||||
* the given verbosity level and more detailed timing at the given level
|
||||
* plus 10. The default level is 30.
|
||||
*/
|
||||
void set_base_verbosity (int vb)
|
||||
{
|
||||
mp_delegate->set_base_verbosity (vb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the base verbosity
|
||||
*/
|
||||
unsigned int base_verbosity () const
|
||||
{
|
||||
return mp_delegate->base_verbosity ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable progress reporting
|
||||
*
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ namespace db
|
|||
|
||||
EdgePairsDelegate::EdgePairsDelegate ()
|
||||
{
|
||||
m_base_verbosity = 30;
|
||||
m_report_progress = false;
|
||||
}
|
||||
|
||||
|
|
@ -43,6 +44,7 @@ EdgePairsDelegate &
|
|||
EdgePairsDelegate::operator= (const EdgePairsDelegate &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
m_base_verbosity = other.m_base_verbosity;
|
||||
m_report_progress = other.m_report_progress;
|
||||
}
|
||||
return *this;
|
||||
|
|
@ -53,6 +55,11 @@ EdgePairsDelegate::~EdgePairsDelegate ()
|
|||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void EdgePairsDelegate::set_base_verbosity (int vb)
|
||||
{
|
||||
m_base_verbosity = vb;
|
||||
}
|
||||
|
||||
void EdgePairsDelegate::enable_progress (const std::string &progress_desc)
|
||||
{
|
||||
m_report_progress = true;
|
||||
|
|
|
|||
|
|
@ -173,6 +173,12 @@ public:
|
|||
return this;
|
||||
}
|
||||
|
||||
void set_base_verbosity (int vb);
|
||||
int base_verbosity () const
|
||||
{
|
||||
return m_base_verbosity;
|
||||
}
|
||||
|
||||
void enable_progress (const std::string &progress_desc);
|
||||
void disable_progress ();
|
||||
|
||||
|
|
@ -200,6 +206,22 @@ public:
|
|||
virtual RegionDelegate *processed_to_polygons (const EdgePairToPolygonProcessorBase &proc) const = 0;
|
||||
virtual EdgesDelegate *processed_to_edges (const EdgePairToEdgeProcessorBase &proc) const = 0;
|
||||
|
||||
virtual RegionDelegate *pull_interacting (const Region &) const = 0;
|
||||
virtual EdgesDelegate *pull_interacting (const Edges &) const = 0;
|
||||
virtual EdgePairsDelegate *selected_interacting (const Region &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual EdgePairsDelegate *selected_not_interacting (const Region &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual EdgePairsDelegate *selected_interacting (const Edges &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual EdgePairsDelegate *selected_not_interacting (const Edges &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual std::pair<EdgePairsDelegate *, EdgePairsDelegate *> selected_interacting_pair (const Region &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual std::pair<EdgePairsDelegate *, EdgePairsDelegate *> selected_interacting_pair (const Edges &other, size_t min_count, size_t max_count) const = 0;
|
||||
|
||||
virtual EdgePairsDelegate *selected_outside (const Region &other) const = 0;
|
||||
virtual EdgePairsDelegate *selected_not_outside (const Region &other) const = 0;
|
||||
virtual std::pair<EdgePairsDelegate *, EdgePairsDelegate *> selected_outside_pair (const Region &other) const = 0;
|
||||
virtual EdgePairsDelegate *selected_inside (const Region &other) const = 0;
|
||||
virtual EdgePairsDelegate *selected_not_inside (const Region &other) const = 0;
|
||||
virtual std::pair<EdgePairsDelegate *, EdgePairsDelegate *> selected_inside_pair (const Region &other) const = 0;
|
||||
|
||||
virtual RegionDelegate *polygons (db::Coord e) const = 0;
|
||||
virtual EdgesDelegate *edges () const = 0;
|
||||
virtual EdgesDelegate *first_edges () const = 0;
|
||||
|
|
@ -238,6 +260,7 @@ protected:
|
|||
private:
|
||||
bool m_report_progress;
|
||||
std::string m_progress_desc;
|
||||
int m_base_verbosity;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,377 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2024 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 "dbEdgePairsLocalOperations.h"
|
||||
#include "dbHierProcessor.h"
|
||||
#include "dbLocalOperationUtils.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// EdgePair2EdgeInteractingLocalOperation implementation
|
||||
|
||||
EdgePair2EdgeInteractingLocalOperation::EdgePair2EdgeInteractingLocalOperation (output_mode_t output_mode, size_t min_count, size_t max_count)
|
||||
: m_output_mode (output_mode), m_min_count (min_count), m_max_count (max_count)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
db::Coord EdgePair2EdgeInteractingLocalOperation::dist () const
|
||||
{
|
||||
// touching is sufficient
|
||||
return 1;
|
||||
}
|
||||
|
||||
void EdgePair2EdgeInteractingLocalOperation::do_compute_local (db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions<db::EdgePair, db::Edge> &interactions, std::vector<std::unordered_set<db::EdgePair> > &results, const db::LocalProcessorBase * /*proc*/) const
|
||||
{
|
||||
tl_assert (results.size () == size_t (m_output_mode == Both ? 2 : 1));
|
||||
|
||||
std::unordered_set<db::EdgePair> &result = results.front ();
|
||||
|
||||
std::unordered_set<db::EdgePair> *result2 = 0;
|
||||
if (m_output_mode == Both) {
|
||||
result2 = &results[1];
|
||||
}
|
||||
|
||||
db::box_scanner2<db::EdgePair, size_t, db::Edge, size_t> scanner;
|
||||
|
||||
std::set<db::Edge> others;
|
||||
for (typename shape_interactions<db::EdgePair, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (typename shape_interactions<db::EdgePair, db::Edge>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.intruder_shape (*j).second);
|
||||
}
|
||||
}
|
||||
|
||||
for (typename shape_interactions<db::EdgePair, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
const db::EdgePair &subject = interactions.subject_shape (i->first);
|
||||
scanner.insert1 (&subject, 0);
|
||||
}
|
||||
|
||||
for (typename std::set<db::Edge>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||
scanner.insert2 (o.operator-> (), 1);
|
||||
}
|
||||
|
||||
if (m_output_mode == Inverse || m_output_mode == Both) {
|
||||
|
||||
std::unordered_set<db::EdgePair> interacting;
|
||||
edge_pair_to_edge_interaction_filter<std::unordered_set<db::EdgePair> > filter (&interacting, m_min_count, m_max_count);
|
||||
scanner.process (filter, 1, db::box_convert<db::EdgePair> (), db::box_convert<db::Edge> ());
|
||||
|
||||
for (typename shape_interactions<db::EdgePair, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
const db::EdgePair &subject = interactions.subject_shape (i->first);
|
||||
|
||||
if (interacting.find (subject) == interacting.end ()) {
|
||||
if (m_output_mode != Both) {
|
||||
result.insert (subject);
|
||||
} else {
|
||||
result2->insert (subject);
|
||||
}
|
||||
} else if (m_output_mode == Both) {
|
||||
result.insert (subject);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
edge_pair_to_edge_interaction_filter<std::unordered_set<db::EdgePair> > filter (&result, m_min_count, m_max_count);
|
||||
scanner.process (filter, 1, db::box_convert<db::EdgePair> (), db::box_convert<db::Edge> ());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
OnEmptyIntruderHint EdgePair2EdgeInteractingLocalOperation::on_empty_intruder_hint () const
|
||||
{
|
||||
return m_output_mode == Both ? CopyToSecond : (m_output_mode == Inverse ? Copy : Drop);
|
||||
}
|
||||
|
||||
std::string EdgePair2EdgeInteractingLocalOperation::description () const
|
||||
{
|
||||
return tl::to_string (tr ("Select edge pairs interacting edges"));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// Edge2EdgePullLocalOperation implementation
|
||||
|
||||
EdgePair2EdgePullLocalOperation::EdgePair2EdgePullLocalOperation ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
db::Coord EdgePair2EdgePullLocalOperation::dist () const
|
||||
{
|
||||
// touching is sufficient
|
||||
return 1;
|
||||
}
|
||||
|
||||
void EdgePair2EdgePullLocalOperation::do_compute_local (db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions<db::EdgePair, db::Edge> &interactions, std::vector<std::unordered_set<db::Edge> > &results, const db::LocalProcessorBase * /*proc*/) const
|
||||
{
|
||||
tl_assert (results.size () == 1);
|
||||
std::unordered_set<db::Edge> &result = results.front ();
|
||||
|
||||
db::box_scanner2<db::EdgePair, size_t, db::Edge, size_t> scanner;
|
||||
|
||||
std::set<db::Edge> others;
|
||||
for (shape_interactions<db::EdgePair, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::EdgePair, db::Edge>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.intruder_shape (*j).second);
|
||||
}
|
||||
}
|
||||
|
||||
for (shape_interactions<db::EdgePair, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
const db::EdgePair &subject = interactions.subject_shape (i->first);
|
||||
scanner.insert1 (&subject, 1);
|
||||
}
|
||||
|
||||
for (std::set<db::Edge>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||
scanner.insert2 (o.operator-> (), 0);
|
||||
}
|
||||
|
||||
edge_pair_to_edge_interaction_filter<std::unordered_set<db::Edge> > filter (&result, size_t (1), std::numeric_limits<size_t>::max ());
|
||||
scanner.process (filter, 1, db::box_convert<db::EdgePair> (), db::box_convert<db::Edge> ());
|
||||
}
|
||||
|
||||
OnEmptyIntruderHint EdgePair2EdgePullLocalOperation::on_empty_intruder_hint () const
|
||||
{
|
||||
return Drop;
|
||||
}
|
||||
|
||||
std::string EdgePair2EdgePullLocalOperation::description () const
|
||||
{
|
||||
return tl::to_string (tr ("Select interacting edges from other"));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// edge_to_polygon_interacting_local_operation implementation
|
||||
|
||||
template <class TI>
|
||||
edge_pair_to_polygon_interacting_local_operation<TI>::edge_pair_to_polygon_interacting_local_operation (EdgePairInteractionMode mode, output_mode_t output_mode, size_t min_count, size_t max_count)
|
||||
: m_mode (mode), m_output_mode (output_mode), m_min_count (min_count), m_max_count (max_count)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
template <class TI>
|
||||
db::Coord edge_pair_to_polygon_interacting_local_operation<TI>::dist () const
|
||||
{
|
||||
// touching is sufficient
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const db::Polygon *deref (const db::Polygon &poly, std::list<db::Polygon> &)
|
||||
{
|
||||
return &poly;
|
||||
}
|
||||
|
||||
static const db::Polygon *deref (const db::PolygonRef &pref, std::list<db::Polygon> &heap)
|
||||
{
|
||||
heap.push_back (pref.obj ().transformed (pref.trans ()));
|
||||
return & heap.back ();
|
||||
}
|
||||
|
||||
template <class TI>
|
||||
void edge_pair_to_polygon_interacting_local_operation<TI>::do_compute_local (db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions<db::EdgePair, TI> &interactions, std::vector<std::unordered_set<db::EdgePair> > &results, const db::LocalProcessorBase * /*proc*/) const
|
||||
{
|
||||
tl_assert (results.size () == size_t (m_output_mode == Both ? 2 : 1));
|
||||
|
||||
std::unordered_set<db::EdgePair> &result = results.front ();
|
||||
|
||||
std::unordered_set<db::EdgePair> *result2 = 0;
|
||||
if (m_output_mode == Both) {
|
||||
result2 = &results[1];
|
||||
}
|
||||
|
||||
db::box_scanner2<db::EdgePair, size_t, db::Polygon, size_t> scanner;
|
||||
|
||||
std::set<TI> others;
|
||||
for (typename shape_interactions<db::EdgePair, TI>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (typename shape_interactions<db::EdgePair, TI>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.intruder_shape (*j).second);
|
||||
}
|
||||
}
|
||||
|
||||
for (typename shape_interactions<db::EdgePair, TI>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
const db::EdgePair &subject = interactions.subject_shape (i->first);
|
||||
scanner.insert1 (&subject, 0);
|
||||
}
|
||||
|
||||
std::list<db::Polygon> heap;
|
||||
for (typename std::set<TI>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||
scanner.insert2 (deref (*o, heap), 1);
|
||||
}
|
||||
|
||||
if (m_output_mode == Inverse || m_output_mode == Both) {
|
||||
|
||||
std::unordered_set<db::EdgePair> interacting;
|
||||
edge_pair_to_polygon_interaction_filter<std::unordered_set<db::EdgePair> > filter (&interacting, m_mode, m_min_count, m_max_count);
|
||||
scanner.process (filter, 1, db::box_convert<db::EdgePair> (), db::box_convert<db::Polygon> ());
|
||||
|
||||
for (typename shape_interactions<db::EdgePair, TI>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
const db::EdgePair &subject = interactions.subject_shape (i->first);
|
||||
|
||||
if (interacting.find (subject) == interacting.end ()) {
|
||||
if (m_output_mode != Both) {
|
||||
result.insert (subject);
|
||||
} else {
|
||||
result2->insert (subject);
|
||||
}
|
||||
} else if (m_output_mode == Both) {
|
||||
result.insert (subject);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
edge_pair_to_polygon_interaction_filter<std::unordered_set<db::EdgePair> > filter (&result, m_mode, m_min_count, m_max_count);
|
||||
scanner.process (filter, 1, db::box_convert<db::EdgePair> (), db::box_convert<db::Polygon> ());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template <class TI>
|
||||
OnEmptyIntruderHint edge_pair_to_polygon_interacting_local_operation<TI>::on_empty_intruder_hint () const
|
||||
{
|
||||
if (m_mode == EdgePairsOutside) {
|
||||
return m_output_mode == Both ? Copy : (m_output_mode == Inverse ? Drop : Copy);
|
||||
} else {
|
||||
return m_output_mode == Both ? CopyToSecond : (m_output_mode == Inverse ? Copy : Drop);
|
||||
}
|
||||
}
|
||||
|
||||
template <class TI>
|
||||
std::string edge_pair_to_polygon_interacting_local_operation<TI>::description () const
|
||||
{
|
||||
if (m_mode == EdgePairsInteract) {
|
||||
if (m_output_mode == Inverse) {
|
||||
return tl::to_string (tr ("Select non-interacting edge pairs"));
|
||||
} else if (m_output_mode == Normal) {
|
||||
return tl::to_string (tr ("Select interacting edge pairs"));
|
||||
} else {
|
||||
return tl::to_string (tr ("Select interacting and non-interacting edge pairs"));
|
||||
}
|
||||
} else if (m_mode == EdgePairsInside) {
|
||||
if (m_output_mode == Inverse) {
|
||||
return tl::to_string (tr ("Select non-inside edge pairs"));
|
||||
} else if (m_output_mode == Normal) {
|
||||
return tl::to_string (tr ("Select inside edge pairs"));
|
||||
} else {
|
||||
return tl::to_string (tr ("Select inside and non-inside edge pairs"));
|
||||
}
|
||||
} else if (m_mode == EdgePairsOutside) {
|
||||
if (m_output_mode == Inverse) {
|
||||
return tl::to_string (tr ("Select non-outside edge pairs"));
|
||||
} else if (m_output_mode == Normal) {
|
||||
return tl::to_string (tr ("Select outside edge pairs"));
|
||||
} else {
|
||||
return tl::to_string (tr ("Select outside and non-outside edge pairs"));
|
||||
}
|
||||
}
|
||||
return std::string ();
|
||||
}
|
||||
|
||||
template class edge_pair_to_polygon_interacting_local_operation<db::Polygon>;
|
||||
template class edge_pair_to_polygon_interacting_local_operation<db::PolygonRef>;
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// EdgePair2PolygonPullLocalOperation implementation
|
||||
|
||||
namespace {
|
||||
|
||||
struct ResultInserter
|
||||
{
|
||||
typedef db::Polygon value_type;
|
||||
|
||||
ResultInserter (db::Layout *layout, std::unordered_set<db::PolygonRef> &result)
|
||||
: mp_layout (layout), mp_result (&result)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void insert (const db::Polygon &p)
|
||||
{
|
||||
(*mp_result).insert (db::PolygonRef (p, mp_layout->shape_repository ()));
|
||||
}
|
||||
|
||||
private:
|
||||
db::Layout *mp_layout;
|
||||
std::unordered_set<db::PolygonRef> *mp_result;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
EdgePair2PolygonPullLocalOperation::EdgePair2PolygonPullLocalOperation ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
db::Coord EdgePair2PolygonPullLocalOperation::dist () const
|
||||
{
|
||||
// touching is sufficient
|
||||
return 1;
|
||||
}
|
||||
|
||||
void EdgePair2PolygonPullLocalOperation::do_compute_local (db::Layout *layout, db::Cell * /*cell*/, const shape_interactions<db::EdgePair, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &results, const db::LocalProcessorBase * /*proc*/) const
|
||||
{
|
||||
tl_assert (results.size () == 1);
|
||||
std::unordered_set<db::PolygonRef> &result = results.front ();
|
||||
|
||||
db::box_scanner2<db::EdgePair, size_t, db::Polygon, size_t> scanner;
|
||||
|
||||
std::set<db::PolygonRef> others;
|
||||
for (shape_interactions<db::EdgePair, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::EdgePair, db::PolygonRef>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.intruder_shape (*j).second);
|
||||
}
|
||||
}
|
||||
|
||||
for (shape_interactions<db::EdgePair, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
const db::EdgePair &subject = interactions.subject_shape (i->first);
|
||||
scanner.insert1 (&subject, 1);
|
||||
}
|
||||
|
||||
std::list<db::Polygon> heap;
|
||||
for (std::set<db::PolygonRef>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||
heap.push_back (o->obj ().transformed (o->trans ()));
|
||||
scanner.insert2 (& heap.back (), 0);
|
||||
}
|
||||
|
||||
ResultInserter inserter (layout, result);
|
||||
edge_pair_to_polygon_interaction_filter<ResultInserter> filter (&inserter, EdgePairsInteract, size_t (1), std::numeric_limits<size_t>::max ());
|
||||
scanner.process (filter, 1, db::box_convert<db::EdgePair> (), db::box_convert<db::Polygon> ());
|
||||
}
|
||||
|
||||
OnEmptyIntruderHint EdgePair2PolygonPullLocalOperation::on_empty_intruder_hint () const
|
||||
{
|
||||
return Drop;
|
||||
}
|
||||
|
||||
std::string EdgePair2PolygonPullLocalOperation::description () const
|
||||
{
|
||||
return tl::to_string (tr ("Select interacting polygons"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2024 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_dbEdgePairsLocalOperation
|
||||
#define HDR_dbEdgePairsLocalOperation
|
||||
|
||||
#include "dbCommon.h"
|
||||
|
||||
#include "dbLayout.h"
|
||||
#include "dbLocalOperation.h"
|
||||
#include "dbEdgePairsUtils.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Implements edge pair-to-edge interactions
|
||||
*/
|
||||
class DB_PUBLIC EdgePair2EdgeInteractingLocalOperation
|
||||
: public local_operation<db::EdgePair, db::Edge, db::EdgePair>
|
||||
{
|
||||
public:
|
||||
enum output_mode_t { Normal, Inverse, Both };
|
||||
|
||||
EdgePair2EdgeInteractingLocalOperation (output_mode_t output_mode, size_t min_count, size_t max_count);
|
||||
|
||||
virtual db::Coord dist () const;
|
||||
virtual void do_compute_local (db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions<db::EdgePair, db::Edge> &interactions, std::vector<std::unordered_set<db::EdgePair> > &results, const db::LocalProcessorBase * /*proc*/) const;
|
||||
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
|
||||
virtual std::string description () const;
|
||||
|
||||
private:
|
||||
output_mode_t m_output_mode;
|
||||
size_t m_min_count, m_max_count;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Implements edge pair-to-edge interactions (pull mode)
|
||||
*/
|
||||
class DB_PUBLIC EdgePair2EdgePullLocalOperation
|
||||
: public local_operation<db::EdgePair, db::Edge, db::Edge>
|
||||
{
|
||||
public:
|
||||
EdgePair2EdgePullLocalOperation ();
|
||||
|
||||
virtual db::Coord dist () const;
|
||||
virtual void do_compute_local (db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions<db::EdgePair, db::Edge> &interactions, std::vector<std::unordered_set<db::Edge> > &results, const db::LocalProcessorBase * /*proc*/) const;
|
||||
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
|
||||
virtual std::string description () const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Implements edge-to-polygon interactions
|
||||
*/
|
||||
template<class TI>
|
||||
class DB_PUBLIC edge_pair_to_polygon_interacting_local_operation
|
||||
: public local_operation<db::EdgePair, TI, db::EdgePair>
|
||||
{
|
||||
public:
|
||||
enum output_mode_t { Normal, Inverse, Both };
|
||||
|
||||
edge_pair_to_polygon_interacting_local_operation (EdgePairInteractionMode mode, output_mode_t output_mode, size_t min_count, size_t max_count);
|
||||
|
||||
virtual db::Coord dist () const;
|
||||
virtual void do_compute_local (db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions<db::EdgePair, TI> &interactions, std::vector<std::unordered_set<db::EdgePair> > &results, const db::LocalProcessorBase * /*proc*/) const;
|
||||
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
|
||||
virtual std::string description () const;
|
||||
|
||||
private:
|
||||
EdgePairInteractionMode m_mode;
|
||||
output_mode_t m_output_mode;
|
||||
size_t m_min_count, m_max_count;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Implements edge-to-polygon interactions (pull mode)
|
||||
*/
|
||||
class DB_PUBLIC EdgePair2PolygonPullLocalOperation
|
||||
: public local_operation<db::EdgePair, db::PolygonRef, db::PolygonRef>
|
||||
{
|
||||
public:
|
||||
EdgePair2PolygonPullLocalOperation ();
|
||||
|
||||
virtual db::Coord dist () const;
|
||||
virtual void do_compute_local (db::Layout *layout, db::Cell * /*cell*/, const shape_interactions<db::EdgePair, db::PolygonRef> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &results, const db::LocalProcessorBase * /*proc*/) const;
|
||||
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
|
||||
virtual std::string description () const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2024 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 "dbEdgePairsUtils.h"
|
||||
#include "dbEdgesUtils.h"
|
||||
#include "dbEdgeProcessor.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
static void insert_into_ep (const db::EdgePair &ep, db::EdgeProcessor &proc, size_t prop_id)
|
||||
{
|
||||
proc.insert (db::Edge (ep.first ().p1 (), ep.first ().p2 ()), prop_id);
|
||||
proc.insert (db::Edge (ep.first ().p2 (), ep.second ().p1 ()), prop_id);
|
||||
proc.insert (db::Edge (ep.second ().p1 (), ep.second ().p2 ()), prop_id);
|
||||
proc.insert (db::Edge (ep.second ().p2 (), ep.first ().p1 ()), prop_id);
|
||||
}
|
||||
|
||||
// NOTE: these predicates are based on the "polygon" interpretation of edge pairs.
|
||||
// Edge pairs are considered connected and filled.
|
||||
// This is different from the interpretation of edge pairs as two edges.
|
||||
|
||||
bool edge_pair_interacts (const db::EdgePair &a, const db::Polygon &b)
|
||||
{
|
||||
// fall back to edge-only checks for degenerate edge pairs
|
||||
if (a.area () == 0) {
|
||||
return edge_interacts (a.first (), b) || edge_interacts (db::Edge (a.first ().p2 (), a.second ().p1 ()), b) ||
|
||||
edge_interacts (a.second (), b) || edge_interacts (db::Edge (a.second ().p2 (), a.first ().p1 ()), b);
|
||||
}
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
insert_into_ep (a, ep, 1);
|
||||
ep.insert (b, 0);
|
||||
|
||||
db::InteractionDetector id (0, 0);
|
||||
id.set_include_touching (true);
|
||||
db::EdgeSink es;
|
||||
ep.process (es, id);
|
||||
id.finish ();
|
||||
|
||||
return id.begin () != id.end ();
|
||||
}
|
||||
|
||||
bool edge_pair_is_inside (const db::EdgePair &a, const db::Polygon &b)
|
||||
{
|
||||
// fall back to edge-only checks for degenerate edge pairs
|
||||
if (a.area () == 0) {
|
||||
return edge_is_inside (a.first (), b) && edge_is_inside (db::Edge (a.first ().p2 (), a.second ().p1 ()), b) &&
|
||||
edge_is_inside (a.second (), b) && edge_is_inside (db::Edge (a.second ().p2 (), a.first ().p1 ()), b);
|
||||
}
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
insert_into_ep (a, ep, 1);
|
||||
ep.insert (b, 0);
|
||||
|
||||
db::InteractionDetector id (-1, 0);
|
||||
id.set_include_touching (true);
|
||||
db::EdgeSink es;
|
||||
ep.process (es, id);
|
||||
id.finish ();
|
||||
|
||||
return id.begin () != id.end ();
|
||||
}
|
||||
|
||||
bool edge_pair_is_outside (const db::EdgePair &a, const db::Polygon &b)
|
||||
{
|
||||
// fall back to edge-only checks for degenerate edge pairs
|
||||
if (a.area () == 0) {
|
||||
return edge_is_outside (a.first (), b) && edge_is_outside (db::Edge (a.first ().p2 (), a.second ().p1 ()), b) &&
|
||||
edge_is_outside (a.second (), b) && edge_is_outside (db::Edge (a.second ().p2 (), a.first ().p1 ()), b);
|
||||
}
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
insert_into_ep (a, ep, 1);
|
||||
ep.insert (b, 0);
|
||||
|
||||
db::InteractionDetector id (1, 0);
|
||||
id.set_include_touching (false);
|
||||
db::EdgeSink es;
|
||||
ep.process (es, id);
|
||||
id.finish ();
|
||||
|
||||
return id.begin () != id.end ();
|
||||
}
|
||||
|
||||
bool edge_pair_interacts (const db::EdgePair &a, const db::Edge &b)
|
||||
{
|
||||
return edge_interacts (a.first (), b) || edge_interacts (db::Edge (a.first ().p2 (), a.second ().p1 ()), b) ||
|
||||
edge_interacts (a.second (), b) || edge_interacts (db::Edge (a.second ().p2 (), a.first ().p1 ()), b);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,261 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2024 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_dbEdgePairsUtils
|
||||
#define HDR_dbEdgePairsUtils
|
||||
|
||||
#include "dbCommon.h"
|
||||
#include "dbHash.h"
|
||||
#include "dbEdgePairs.h"
|
||||
#include "dbBoxScanner.h"
|
||||
#include "tlSelect.h"
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
namespace db {
|
||||
|
||||
/**
|
||||
* @brief The operation mode for the interaction filters
|
||||
*/
|
||||
enum EdgePairInteractionMode { EdgePairsInteract, EdgePairsInside, EdgePairsOutside };
|
||||
|
||||
/**
|
||||
* @brief A predicate defining edge pair a interacts with polygon b
|
||||
*/
|
||||
DB_PUBLIC bool edge_pair_interacts (const db::EdgePair &a, const db::Polygon &b);
|
||||
|
||||
/**
|
||||
* @brief A predicate defining edge pair a is "inside" polygon b
|
||||
*/
|
||||
DB_PUBLIC bool edge_pair_is_inside (const db::EdgePair &a, const db::Polygon &b);
|
||||
|
||||
/**
|
||||
* @brief A predicate defining edge pair a is "outside" polygon b
|
||||
*/
|
||||
DB_PUBLIC bool edge_pair_is_outside (const db::EdgePair &a, const db::Polygon &b);
|
||||
|
||||
/**
|
||||
* @brief A helper class for the edge pair to region interaction functionality which acts as an edge pair receiver
|
||||
*
|
||||
* Note: This special scanner uses pointers to two different objects: edge pairs and polygons.
|
||||
* It uses odd value pointers to indicate pointers to polygons and even value pointers to indicate
|
||||
* pointers to edge pairs.
|
||||
*
|
||||
* There is a special box converter which is able to sort that out as well.
|
||||
*/
|
||||
template <class OutputContainer, class OutputType = typename OutputContainer::value_type>
|
||||
class edge_pair_to_polygon_interaction_filter
|
||||
: public db::box_scanner_receiver2<db::EdgePair, size_t, db::Polygon, size_t>
|
||||
{
|
||||
public:
|
||||
edge_pair_to_polygon_interaction_filter (OutputContainer *output, EdgePairInteractionMode mode, size_t min_count, size_t max_count)
|
||||
: mp_output (output), m_mode (mode), m_min_count (min_count), m_max_count (max_count)
|
||||
{
|
||||
// NOTE: "counting" does not really make much sense in Outside mode ...
|
||||
m_counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
|
||||
tl_assert (!m_counting || mode != EdgePairsOutside);
|
||||
}
|
||||
|
||||
void finish (const OutputType *o)
|
||||
{
|
||||
if (m_counting) {
|
||||
|
||||
size_t count = 0;
|
||||
auto i = m_counts.find (o);
|
||||
if (i != m_counts.end ()) {
|
||||
count = i->second;
|
||||
}
|
||||
|
||||
bool match = (count >= m_min_count && count <= m_max_count);
|
||||
if (match == (m_mode != EdgePairsOutside)) {
|
||||
mp_output->insert (*o);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (m_mode == EdgePairsOutside && m_seen.find (o) == m_seen.end ()) {
|
||||
mp_output->insert (*o);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void finish1 (const db::EdgePair *o, size_t /*p*/)
|
||||
{
|
||||
const OutputType *ep = 0;
|
||||
tl::select (ep, o, (const db::Polygon *) 0);
|
||||
if (ep) {
|
||||
finish (ep);
|
||||
}
|
||||
}
|
||||
|
||||
void finish2 (const db::Polygon *o, size_t /*p*/)
|
||||
{
|
||||
const OutputType *ep = 0;
|
||||
tl::select (ep, (const db::EdgePair *) 0, o);
|
||||
if (ep) {
|
||||
finish (ep);
|
||||
}
|
||||
}
|
||||
|
||||
void add (const db::EdgePair *e, size_t, const db::Polygon *p, size_t)
|
||||
{
|
||||
const OutputType *ep = 0;
|
||||
tl::select (ep, e, p);
|
||||
|
||||
if (m_counting) {
|
||||
|
||||
if ((m_mode == EdgePairsInteract && db::edge_pair_interacts (*e, *p)) ||
|
||||
(m_mode == EdgePairsInside && db::edge_pair_is_inside (*e, *p)) ||
|
||||
(m_mode == EdgePairsOutside && ! db::edge_pair_is_outside (*e, *p))) {
|
||||
|
||||
// we report the result on "finish" here.
|
||||
m_counts[ep] += 1;
|
||||
|
||||
}
|
||||
|
||||
} else if (m_seen.find (ep) == m_seen.end ()) {
|
||||
|
||||
if ((m_mode == EdgePairsInteract && db::edge_pair_interacts (*e, *p)) ||
|
||||
(m_mode == EdgePairsInside && db::edge_pair_is_inside (*e, *p))) {
|
||||
|
||||
m_seen.insert (ep);
|
||||
mp_output->insert (*ep);
|
||||
|
||||
} else if (m_mode == EdgePairsOutside && ! db::edge_pair_is_outside (*e, *p)) {
|
||||
|
||||
// In this case we need to collect edges which are outside always - we report those on "finished".
|
||||
m_seen.insert (ep);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
OutputContainer *mp_output;
|
||||
std::map<const OutputType *, size_t> m_counts;
|
||||
std::set<const OutputType *> m_seen;
|
||||
EdgePairInteractionMode m_mode;
|
||||
size_t m_min_count, m_max_count;
|
||||
bool m_counting;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A predicate defining edge pair a interacts with edge b
|
||||
*/
|
||||
DB_PUBLIC bool edge_pair_interacts (const db::EdgePair &a, const db::Edge &b);
|
||||
|
||||
/**
|
||||
* @brief A helper class for the edge pair to region interaction functionality which acts as an edge pair receiver
|
||||
*
|
||||
* Note: This special scanner uses pointers to two different objects: edge pairs and polygons.
|
||||
* It uses odd value pointers to indicate pointers to polygons and even value pointers to indicate
|
||||
* pointers to edge pairs.
|
||||
*
|
||||
* There is a special box converter which is able to sort that out as well.
|
||||
*/
|
||||
template <class OutputContainer, class OutputType = typename OutputContainer::value_type>
|
||||
class edge_pair_to_edge_interaction_filter
|
||||
: public db::box_scanner_receiver2<db::EdgePair, size_t, db::Edge, size_t>
|
||||
{
|
||||
public:
|
||||
edge_pair_to_edge_interaction_filter (OutputContainer *output, size_t min_count, size_t max_count)
|
||||
: mp_output (output), m_min_count (min_count), m_max_count (max_count)
|
||||
{
|
||||
m_counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
|
||||
}
|
||||
|
||||
void finish (const OutputType *o)
|
||||
{
|
||||
if (m_counting) {
|
||||
|
||||
size_t count = 0;
|
||||
auto i = m_counts.find (o);
|
||||
if (i != m_counts.end ()) {
|
||||
count = i->second;
|
||||
}
|
||||
|
||||
bool match = (count >= m_min_count && count <= m_max_count);
|
||||
if (match) {
|
||||
mp_output->insert (*o);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void finish1 (const db::EdgePair *o, size_t /*p*/)
|
||||
{
|
||||
const OutputType *ep = 0;
|
||||
tl::select (ep, o, (const db::Edge *) 0);
|
||||
if (ep) {
|
||||
finish (ep);
|
||||
}
|
||||
}
|
||||
|
||||
void finish2 (const db::Edge *o, size_t /*p*/)
|
||||
{
|
||||
const OutputType *ep = 0;
|
||||
tl::select (ep, (const db::EdgePair *) 0, o);
|
||||
if (ep) {
|
||||
finish (ep);
|
||||
}
|
||||
}
|
||||
|
||||
void add (const db::EdgePair *e, size_t, const db::Edge *p, size_t)
|
||||
{
|
||||
const OutputType *ep = 0;
|
||||
tl::select (ep, e, p);
|
||||
|
||||
if (m_counting) {
|
||||
|
||||
if (db::edge_pair_interacts (*e, *p)) {
|
||||
|
||||
// we report the result on "finish" here.
|
||||
m_counts[ep] += 1;
|
||||
|
||||
}
|
||||
|
||||
} else if (m_seen.find (ep) == m_seen.end ()) {
|
||||
|
||||
if (db::edge_pair_interacts (*e, *p)) {
|
||||
|
||||
m_seen.insert (ep);
|
||||
mp_output->insert (*ep);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
OutputContainer *mp_output;
|
||||
std::map<const OutputType *, size_t> m_counts;
|
||||
std::set<const OutputType *> m_seen;
|
||||
EdgePairInteractionMode m_mode;
|
||||
size_t m_min_count, m_max_count;
|
||||
bool m_counting;
|
||||
};
|
||||
|
||||
} // namespace db
|
||||
|
||||
#endif
|
||||
|
|
@ -344,7 +344,7 @@ std::string Edge2EdgePullLocalOperation::description () const
|
|||
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// Edge2EdgePullLocalOperation implementation
|
||||
// edge_to_polygon_interacting_local_operation implementation
|
||||
|
||||
template <class TI>
|
||||
edge_to_polygon_interacting_local_operation<TI>::edge_to_polygon_interacting_local_operation (EdgeInteractionMode mode, output_mode_t output_mode, size_t min_count, size_t max_count)
|
||||
|
|
|
|||
|
|
@ -65,6 +65,18 @@ EmptyEdgePairs::processed_to_edges (const EdgePairToEdgeProcessorBase &) const
|
|||
return new EmptyEdges ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
EmptyEdgePairs::pull_interacting (const Region &) const
|
||||
{
|
||||
return new EmptyRegion ();
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
EmptyEdgePairs::pull_interacting (const Edges &) const
|
||||
{
|
||||
return new EmptyEdges ();
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
EmptyEdgePairs::edges () const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -61,6 +61,22 @@ public:
|
|||
virtual RegionDelegate *processed_to_polygons (const EdgePairToPolygonProcessorBase &filter) const;
|
||||
virtual EdgesDelegate *processed_to_edges (const EdgePairToEdgeProcessorBase &filter) const;
|
||||
|
||||
virtual RegionDelegate *pull_interacting (const Region &) const;
|
||||
virtual EdgesDelegate *pull_interacting (const Edges &) const;
|
||||
virtual EdgePairsDelegate *selected_interacting (const Region &, size_t, size_t) const { return new EmptyEdgePairs (); }
|
||||
virtual EdgePairsDelegate *selected_not_interacting (const Region &, size_t, size_t) const { return new EmptyEdgePairs (); }
|
||||
virtual EdgePairsDelegate *selected_interacting (const Edges &, size_t, size_t) const { return new EmptyEdgePairs (); }
|
||||
virtual EdgePairsDelegate *selected_not_interacting (const Edges &, size_t, size_t) const { return new EmptyEdgePairs (); }
|
||||
virtual std::pair<EdgePairsDelegate *, EdgePairsDelegate *> selected_interacting_pair (const Region &, size_t, size_t) const { return std::make_pair (new EmptyEdgePairs (), new EmptyEdgePairs ()); }
|
||||
virtual std::pair<EdgePairsDelegate *, EdgePairsDelegate *> selected_interacting_pair (const Edges &, size_t, size_t) const { return std::make_pair (new EmptyEdgePairs (), new EmptyEdgePairs ()); }
|
||||
|
||||
virtual EdgePairsDelegate *selected_outside (const Region &) const { return new EmptyEdgePairs (); }
|
||||
virtual EdgePairsDelegate *selected_not_outside (const Region &) const { return new EmptyEdgePairs (); }
|
||||
virtual std::pair<EdgePairsDelegate *, EdgePairsDelegate *> selected_outside_pair (const Region &) const { return std::make_pair (new EmptyEdgePairs (), new EmptyEdgePairs ()); }
|
||||
virtual EdgePairsDelegate *selected_inside (const Region &) const { return new EmptyEdgePairs (); }
|
||||
virtual EdgePairsDelegate *selected_not_inside (const Region &) const { return new EmptyEdgePairs (); }
|
||||
virtual std::pair<EdgePairsDelegate *, EdgePairsDelegate *> selected_inside_pair (const Region &) const { return std::make_pair (new EmptyEdgePairs (), new EmptyEdgePairs ()); }
|
||||
|
||||
virtual RegionDelegate *polygons (db::Coord e) const;
|
||||
virtual EdgesDelegate *edges () const;
|
||||
virtual EdgesDelegate *first_edges () const;
|
||||
|
|
|
|||
|
|
@ -2558,6 +2558,12 @@ template class DB_PUBLIC local_processor_cell_context<db::Polygon, db::Polygon,
|
|||
template class DB_PUBLIC local_processor_cell_context<db::Edge, db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::Edge, db::Polygon, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::Edge, db::Edge, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::EdgePair, db::Polygon, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::EdgePair, db::PolygonRef, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::EdgePair, db::Edge, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::EdgePair, db::Polygon, db::Polygon>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::EdgePair, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor_cell_context<db::EdgePair, db::Edge, db::Edge>;
|
||||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::Polygon, db::Polygon, db::Polygon>;
|
||||
|
|
@ -2581,6 +2587,12 @@ template class DB_PUBLIC local_processor_cell_contexts<db::Edge, db::PolygonRef,
|
|||
template class DB_PUBLIC local_processor_cell_contexts<db::Edge, db::Polygon, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::Edge, db::Edge, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::Edge, db::Edge, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::EdgePair, db::Polygon, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::EdgePair, db::PolygonRef, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::EdgePair, db::Edge, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::EdgePair, db::Polygon, db::Polygon>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::EdgePair, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor_cell_contexts<db::EdgePair, db::Edge, db::Edge>;
|
||||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC shape_interactions<db::Polygon, db::Polygon>;
|
||||
|
|
@ -2598,6 +2610,9 @@ template class DB_PUBLIC shape_interactions<db::Edge, db::PolygonRef>;
|
|||
template class DB_PUBLIC shape_interactions<db::Edge, db::Polygon>;
|
||||
template class DB_PUBLIC shape_interactions<db::TextRef, db::TextRef>;
|
||||
template class DB_PUBLIC shape_interactions<db::TextRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC shape_interactions<db::EdgePair, db::Polygon>;
|
||||
template class DB_PUBLIC shape_interactions<db::EdgePair, db::PolygonRef>;
|
||||
template class DB_PUBLIC shape_interactions<db::EdgePair, db::Edge>;
|
||||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::Polygon, db::Polygon, db::Polygon>;
|
||||
|
|
@ -2629,6 +2644,12 @@ template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::
|
|||
template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::Polygon, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::Edge, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::Edge, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::EdgePair, db::Polygon, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::EdgePair, db::PolygonRef, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::EdgePair, db::Edge, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::EdgePair, db::Polygon, db::Polygon>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::EdgePair, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor_context_computation_task<db::EdgePair, db::Edge, db::Edge>;
|
||||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::Polygon, db::Polygon, db::Polygon>;
|
||||
|
|
@ -2652,6 +2673,12 @@ template class DB_PUBLIC local_processor_result_computation_task<db::Edge, db::E
|
|||
template class DB_PUBLIC local_processor_result_computation_task<db::Edge, db::PolygonRef, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::Edge, db::Polygon, db::Edge>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::Edge, db::Edge, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::EdgePair, db::Polygon, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::EdgePair, db::PolygonRef, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::EdgePair, db::Edge, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::EdgePair, db::Polygon, db::Polygon>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::EdgePair, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor_result_computation_task<db::EdgePair, db::Edge, db::Edge>;
|
||||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC local_processor<db::Polygon, db::Polygon, db::Polygon>;
|
||||
|
|
@ -2683,6 +2710,12 @@ template class DB_PUBLIC local_processor<db::Edge, db::PolygonRef, db::PolygonRe
|
|||
template class DB_PUBLIC local_processor<db::Edge, db::Edge, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor<db::TextRef, db::PolygonRef, db::TextRef>;
|
||||
template class DB_PUBLIC local_processor<db::TextRef, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor<db::EdgePair, db::Polygon, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor<db::EdgePair, db::PolygonRef, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor<db::EdgePair, db::Edge, db::EdgePair>;
|
||||
template class DB_PUBLIC local_processor<db::EdgePair, db::Polygon, db::Polygon>;
|
||||
template class DB_PUBLIC local_processor<db::EdgePair, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_processor<db::EdgePair, db::Edge, db::Edge>;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -106,6 +106,12 @@ template class DB_PUBLIC local_operation<db::Edge, db::PolygonRef, db::PolygonRe
|
|||
template class DB_PUBLIC local_operation<db::Edge, db::Edge, db::EdgePair>;
|
||||
template class DB_PUBLIC local_operation<db::TextRef, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_operation<db::TextRef, db::PolygonRef, db::TextRef>;
|
||||
template class DB_PUBLIC local_operation<db::EdgePair, db::Polygon, db::EdgePair>;
|
||||
template class DB_PUBLIC local_operation<db::EdgePair, db::PolygonRef, db::EdgePair>;
|
||||
template class DB_PUBLIC local_operation<db::EdgePair, db::Edge, db::EdgePair>;
|
||||
template class DB_PUBLIC local_operation<db::EdgePair, db::Polygon, db::Polygon>;
|
||||
template class DB_PUBLIC local_operation<db::EdgePair, db::PolygonRef, db::PolygonRef>;
|
||||
template class DB_PUBLIC local_operation<db::EdgePair, db::Edge, db::Edge>;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -211,6 +211,15 @@ Class<shape_processor_impl<db::EdgePairToEdgeProcessorBase> > decl_EdgePairToEdg
|
|||
// ---------------------------------------------------------------------------------
|
||||
// EdgePairs binding
|
||||
|
||||
static inline std::vector<db::EdgePairs> as_2edge_pairs_vector (const std::pair<db::EdgePairs, db::EdgePairs> &rp)
|
||||
{
|
||||
std::vector<db::EdgePairs> res;
|
||||
res.reserve (2);
|
||||
res.push_back (db::EdgePairs (const_cast<db::EdgePairs &> (rp.first).take_delegate ()));
|
||||
res.push_back (db::EdgePairs (const_cast<db::EdgePairs &> (rp.second).take_delegate ()));
|
||||
return res;
|
||||
}
|
||||
|
||||
static db::EdgePairs *new_v ()
|
||||
{
|
||||
return new db::EdgePairs ();
|
||||
|
|
@ -287,6 +296,40 @@ static db::EdgePairs moved_xy (const db::EdgePairs *r, db::Coord x, db::Coord y)
|
|||
return r->transformed (db::Disp (db::Vector (x, y)));
|
||||
}
|
||||
|
||||
static db::Region pull_interacting_polygons (const db::EdgePairs *r, const db::Region &other)
|
||||
{
|
||||
db::Region out;
|
||||
r->pull_interacting (out, other);
|
||||
return out;
|
||||
}
|
||||
|
||||
static db::Edges pull_interacting_edges (const db::EdgePairs *r, const db::Edges &other)
|
||||
{
|
||||
db::Edges out;
|
||||
r->pull_interacting (out, other);
|
||||
return out;
|
||||
}
|
||||
|
||||
static std::vector<db::EdgePairs> split_inside_with_region (const db::EdgePairs *r, const db::Region &other)
|
||||
{
|
||||
return as_2edge_pairs_vector (r->selected_inside_differential (other));
|
||||
}
|
||||
|
||||
static std::vector<db::EdgePairs> split_outside_with_region (const db::EdgePairs *r, const db::Region &other)
|
||||
{
|
||||
return as_2edge_pairs_vector (r->selected_outside_differential (other));
|
||||
}
|
||||
|
||||
static std::vector<db::EdgePairs> split_interacting_with_edges (const db::EdgePairs *r, const db::Edges &other, size_t min_count, size_t max_count)
|
||||
{
|
||||
return as_2edge_pairs_vector (r->selected_interacting_differential (other, min_count, max_count));
|
||||
}
|
||||
|
||||
static std::vector<db::EdgePairs> split_interacting_with_region (const db::EdgePairs *r, const db::Region &other, size_t min_count, size_t max_count)
|
||||
{
|
||||
return as_2edge_pairs_vector (r->selected_interacting_differential (other, min_count, max_count));
|
||||
}
|
||||
|
||||
static db::Region polygons1 (const db::EdgePairs *e)
|
||||
{
|
||||
db::Region r;
|
||||
|
|
@ -1158,6 +1201,247 @@ Class<db::EdgePairs> decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs",
|
|||
"enlargement it is possible to give edge pairs an area which otherwise would not have one (coincident edges, "
|
||||
"two point-like edges)."
|
||||
) +
|
||||
method ("interacting", (db::EdgePairs (db::EdgePairs::*) (const db::Edges &, size_t, size_t) const) &db::EdgePairs::selected_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Returns the edge pairs from this edge pair collection which overlap or touch edges from the other edge collection\n"
|
||||
"\n"
|
||||
"@return A new edge pair collection containing the edge pairs overlapping or touching edges from the other edge collection\n"
|
||||
"\n"
|
||||
"'min_count' and 'max_count' impose a constraint on the number of times an edge pair of this collection "
|
||||
"has to interact with (different) edges of the other collection to make the edge pair selected. An edge pair is "
|
||||
"not selected by this method if the number of edges interacting with an edge pair of this collection is between min_count and max_count "
|
||||
"(including max_count).\n"
|
||||
"\n"
|
||||
"Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to "
|
||||
"the edge pair, hence participates in the check.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.29.6\n"
|
||||
) +
|
||||
method ("not_interacting", (db::EdgePairs (db::EdgePairs::*) (const db::Edges &, size_t, size_t) const) &db::EdgePairs::selected_not_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Returns the edge pairs from this edge pair collection which do not overlap or touch edges from the other edge collection\n"
|
||||
"\n"
|
||||
"@return A new edge pair collection containing the edge pairs not overlapping or touching edges from the other edge collection\n"
|
||||
"\n"
|
||||
"'min_count' and 'max_count' impose a constraint on the number of times an edge pair of this collection "
|
||||
"has to interact with (different) edges of the other collection to make the edge pair selected. An edge pair is "
|
||||
"not selected by this method if the number of edges interacting with an edge pair of this collection is between min_count and max_count "
|
||||
"(including max_count).\n"
|
||||
"\n"
|
||||
"Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to "
|
||||
"the edge pair, hence participates in the check.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.29.6\n"
|
||||
) +
|
||||
method ("select_interacting", (db::EdgePairs &(db::EdgePairs::*) (const db::Edges &, size_t, size_t)) &db::EdgePairs::select_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Selects the edge pairs from this edge pair collection which overlap or touch edges from the other edge collection\n"
|
||||
"\n"
|
||||
"@return The edge pair collection after the edge pairs have been selected (self)\n"
|
||||
"\n"
|
||||
"This is the in-place version of \\interacting - i.e. self is modified rather than a new collection is returned.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.29.6\n"
|
||||
) +
|
||||
method ("select_not_interacting", (db::EdgePairs &(db::EdgePairs::*) (const db::Edges &, size_t, size_t)) &db::EdgePairs::select_not_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Selects the edge pairs from this edge pair collection which do not overlap or touch edges from the other edge collection\n"
|
||||
"\n"
|
||||
"@return The edge pair collection after the edge pairs have been selected (self)\n"
|
||||
"\n"
|
||||
"This is the in-place version of \\not_interacting - i.e. self is modified rather than a new collection is returned.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.29.6\n"
|
||||
) +
|
||||
method_ext ("split_interacting", &split_interacting_with_edges, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Selects the edge pairs from this edge pair collection which do and do not interact with edges from the other collection\n"
|
||||
"\n"
|
||||
"@return A two-element list of edge pair collections (first: interacting, second: non-interacting)\n"
|
||||
"\n"
|
||||
"This method provides a faster way to compute both interacting and non-interacting edges compared to using separate methods. "
|
||||
"It has been introduced in version 0.29.6.\n"
|
||||
) +
|
||||
method ("interacting", (db::EdgePairs (db::EdgePairs::*) (const db::Region &, size_t, size_t) const) &db::EdgePairs::selected_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Returns the edge pairs from this edge pair collection which overlap or touch polygons from the region\n"
|
||||
"\n"
|
||||
"@return A new edge pair collection containing the edge pairs overlapping or touching polygons from the region\n"
|
||||
"\n"
|
||||
"'min_count' and 'max_count' impose a constraint on the number of times an edge pair of this collection "
|
||||
"has to interact with (different) polygons of the other region to make the edge pair selected. An edge pair is "
|
||||
"not selected by this method if the number of polygons interacting with an edge pair of this collection is between min_count and max_count "
|
||||
"(including max_count).\n"
|
||||
"\n"
|
||||
"Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to "
|
||||
"the edge pair, hence participates in the check.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.29.6\n"
|
||||
) +
|
||||
method ("not_interacting", (db::EdgePairs (db::EdgePairs::*) (const db::Region &, size_t, size_t) const) &db::EdgePairs::selected_not_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Returns the edge pairs from this edge pair collection which do not overlap or touch polygons from the region\n"
|
||||
"\n"
|
||||
"@return A new edge pair collection containing the edge pairs not overlapping or touching polygons from the region\n"
|
||||
"\n"
|
||||
"'min_count' and 'max_count' impose a constraint on the number of times an edge pair of this collection "
|
||||
"has to interact with (different) polygons of the other region to make the edge pair selected. An edge pair is "
|
||||
"not selected by this method if the number of polygons interacting with an edge pair of this collection is between min_count and max_count "
|
||||
"(including max_count).\n"
|
||||
"\n"
|
||||
"Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to "
|
||||
"the edge pair, hence participates in the check.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.29.6\n"
|
||||
) +
|
||||
method ("select_interacting", (db::EdgePairs &(db::EdgePairs::*) (const db::Region &, size_t, size_t)) &db::EdgePairs::select_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Selects the edge pairs from this edge pair collection which overlap or touch polygons from the region\n"
|
||||
"\n"
|
||||
"@return The edge pair collection after the edge pairs have been selected (self)\n"
|
||||
"\n"
|
||||
"This is the in-place version of \\interacting - i.e. self is modified rather than a new collection is returned.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.29.6\n"
|
||||
) +
|
||||
method ("select_not_interacting", (db::EdgePairs &(db::EdgePairs::*) (const db::Region &, size_t, size_t)) &db::EdgePairs::select_not_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Selects the edge pairs from this edge pair collection which do not overlap or touch polygons from the region\n"
|
||||
"\n"
|
||||
"@return The edge pair collection after the edge pairs have been selected (self)\n"
|
||||
"\n"
|
||||
"This is the in-place version of \\not_interacting - i.e. self is modified rather than a new collection is returned.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.29.6\n"
|
||||
) +
|
||||
method_ext ("split_interacting", &split_interacting_with_region, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Selects the edge pairs from this edge pair collection which do and do not interact with polygons from the other region\n"
|
||||
"\n"
|
||||
"@return A two-element list of edge pair collections (first: interacting, second: non-interacting)\n"
|
||||
"\n"
|
||||
"This method provides a faster way to compute both interacting and non-interacting edges compared to using separate methods. "
|
||||
"It has been introduced in version 0.29.6.\n"
|
||||
) +
|
||||
method ("inside", (db::EdgePairs (db::EdgePairs::*) (const db::Region &) const) &db::EdgePairs::selected_inside, gsi::arg ("other"),
|
||||
"@brief Returns the edge pairs from this edge pair collection which are inside (completely covered by) polygons from the region\n"
|
||||
"\n"
|
||||
"@return A new edge pair collection containing the edge pairs completely inside polygons from the region\n"
|
||||
"\n"
|
||||
"Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to "
|
||||
"the edge pair, hence participates in the check.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.29.6\n"
|
||||
) +
|
||||
method ("not_inside", (db::EdgePairs (db::EdgePairs::*) (const db::Region &) const) &db::EdgePairs::selected_not_inside, gsi::arg ("other"),
|
||||
"@brief Returns the edge pairs from this edge pair collection which are not inside (not completely covered by) polygons from the region\n"
|
||||
"\n"
|
||||
"@return A new edge pair collection containing the edge pairs not completely inside polygons from the region\n"
|
||||
"\n"
|
||||
"Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to "
|
||||
"the edge pair, hence participates in the check.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.29.6\n"
|
||||
) +
|
||||
method ("select_inside", (db::EdgePairs &(db::EdgePairs::*) (const db::Region &)) &db::EdgePairs::select_inside, gsi::arg ("other"),
|
||||
"@brief Selects the edge pairs from this edge pair collection which are inside (completely covered by) polygons from the region\n"
|
||||
"\n"
|
||||
"@return The edge pair collection after the edge pairs have been selected (self)\n"
|
||||
"\n"
|
||||
"Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to "
|
||||
"the edge pair, hence participates in the check.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.29.6\n"
|
||||
) +
|
||||
method ("select_not_inside", (db::EdgePairs &(db::EdgePairs::*) (const db::Region &)) &db::EdgePairs::select_not_inside, gsi::arg ("other"),
|
||||
"@brief Selects the edge pairs from this edge pair collection which are not inside (completely covered by) polygons from the region\n"
|
||||
"\n"
|
||||
"@return The edge pair collection after the edge pairs have been selected (self)\n"
|
||||
"\n"
|
||||
"Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to "
|
||||
"the edge pair, hence participates in the check.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.29.6\n"
|
||||
) +
|
||||
method_ext ("split_inside", &split_inside_with_region, gsi::arg ("other"),
|
||||
"@brief Selects the edge pairs from this edge pair collection which are and are not inside (completely covered by) polygons from the other region\n"
|
||||
"\n"
|
||||
"@return A two-element list of edge pair collections (first: inside, second: non-inside)\n"
|
||||
"\n"
|
||||
"This method provides a faster way to compute both inside and non-inside edge pairs compared to using separate methods. "
|
||||
"It has been introduced in version 0.29.6."
|
||||
) +
|
||||
method ("outside", (db::EdgePairs (db::EdgePairs::*) (const db::Region &) const) &db::EdgePairs::selected_outside, gsi::arg ("other"),
|
||||
"@brief Returns the edge pairs from this edge pair collection which are outside (not overlapped by) polygons from the other region\n"
|
||||
"\n"
|
||||
"@return A new edge pair collection containing the the selected edges\n"
|
||||
"\n"
|
||||
"Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to "
|
||||
"the edge pair, hence participates in the check.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.29.6\n"
|
||||
) +
|
||||
method ("not_outside", (db::EdgePairs (db::EdgePairs::*) (const db::Region &) const) &db::EdgePairs::selected_not_outside, gsi::arg ("other"),
|
||||
"@brief Returns the edge pairs from this edge pair collection which are not outside (partially overlapped by) polygons from the other region\n"
|
||||
"\n"
|
||||
"@return A new edge pair collection containing the the selected edges\n"
|
||||
"\n"
|
||||
"Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to "
|
||||
"the edge pair, hence participates in the check.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.29.6\n"
|
||||
) +
|
||||
method ("select_outside", (db::EdgePairs &(db::EdgePairs::*) (const db::Region &)) &db::EdgePairs::select_outside, gsi::arg ("other"),
|
||||
"@brief Selects the edge pairs from this edge pair collection which are outside (not overlapped by) polygons from the other region\n"
|
||||
"\n"
|
||||
"@return The edge pair collection after the edges have been selected (self)\n"
|
||||
"\n"
|
||||
"Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to "
|
||||
"the edge pair, hence participates in the check.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.29.6\n"
|
||||
) +
|
||||
method ("select_not_outside", (db::EdgePairs &(db::EdgePairs::*) (const db::Region &)) &db::EdgePairs::select_not_outside, gsi::arg ("other"),
|
||||
"@brief Selects the edge pairs from this edge pair collection which are not outside (partially overlapped by) polygons from the other region\n"
|
||||
"\n"
|
||||
"@return The edge pair collection after the edges have been selected (self)\n"
|
||||
"\n"
|
||||
"Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to "
|
||||
"the edge pair, hence participates in the check.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.29.6\n"
|
||||
) +
|
||||
method_ext ("split_outside", &split_outside_with_region, gsi::arg ("other"),
|
||||
"@brief Selects the edge pairs from this edge pair collection which are and are not outside (not overlapped by) polygons from the other region\n"
|
||||
"\n"
|
||||
"@return A two-element list of edge pair collections (first: outside, second: non-outside)\n"
|
||||
"\n"
|
||||
"This method provides a faster way to compute both outside and non-outside edges compared to using separate methods. "
|
||||
"\n"
|
||||
"This method has been introduced in version 0.29.6\n"
|
||||
) +
|
||||
method_ext ("pull_interacting", &pull_interacting_edges, gsi::arg ("other"),
|
||||
"@brief Returns all edges of \"other\" which are interacting with (overlapping, touching) edge pairs of this set\n"
|
||||
"The \"pull_...\" methods are similar to \"select_...\" but work the opposite way: they "
|
||||
"select shapes from the argument region rather than self. In a deep (hierarchical) context "
|
||||
"the output region will be hierarchically aligned with self, so the \"pull_...\" methods "
|
||||
"provide a way for re-hierarchization.\n"
|
||||
"\n"
|
||||
"Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to "
|
||||
"the edge pair, hence participates in the check.\n"
|
||||
"\n"
|
||||
"@return The edge collection after the edges have been selected (from other)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.29.6\n"
|
||||
) +
|
||||
method_ext ("pull_interacting", &pull_interacting_polygons, gsi::arg ("other"),
|
||||
"@brief Returns all polygons of \"other\" which are interacting with (overlapping, touching) edge pairs of this set\n"
|
||||
"The \"pull_...\" methods are similar to \"select_...\" but work the opposite way: they "
|
||||
"select shapes from the argument region rather than self. In a deep (hierarchical) context "
|
||||
"the output region will be hierarchically aligned with self, so the \"pull_...\" methods "
|
||||
"provide a way for re-hierarchization.\n"
|
||||
"\n"
|
||||
"Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to "
|
||||
"the edge pair, hence participates in the check.\n"
|
||||
"\n"
|
||||
"@return The region after the polygons have been selected (from other)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.29.6\n"
|
||||
) +
|
||||
method ("clear", &db::EdgePairs::clear,
|
||||
"@brief Clears the edge pair collection\n"
|
||||
) +
|
||||
|
|
|
|||
|
|
@ -1366,14 +1366,14 @@ Class<db::Edges> decl_Edges (decl_dbShapeCollection, "db", "Edges",
|
|||
method ("inside", (db::Edges (db::Edges::*) (const db::Edges &) const) &db::Edges::selected_inside, gsi::arg ("other"),
|
||||
"@brief Returns the edges of this edge collection which are inside (completely covered by) edges from the other edge collection\n"
|
||||
"\n"
|
||||
"@return A new edge collection containing the edges overlapping or touching edges from the other edge collection\n"
|
||||
"@return A new edge collection containing the the selected edges\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28."
|
||||
) +
|
||||
method ("not_inside", (db::Edges (db::Edges::*) (const db::Edges &) const) &db::Edges::selected_not_inside, gsi::arg ("other"),
|
||||
"@brief Returns the edges of this edge collection which are not inside (completely covered by) edges from the other edge collection\n"
|
||||
"\n"
|
||||
"@return A new edge collection containing the edges not overlapping or touching edges from the other edge collection\n"
|
||||
"@return A new edge collection containing the the selected edges\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28."
|
||||
) +
|
||||
|
|
@ -1402,14 +1402,14 @@ Class<db::Edges> decl_Edges (decl_dbShapeCollection, "db", "Edges",
|
|||
method ("inside", (db::Edges (db::Edges::*) (const db::Region &) const) &db::Edges::selected_inside, gsi::arg ("other"),
|
||||
"@brief Returns the edges from this edge collection which are inside (completely covered by) polygons from the region\n"
|
||||
"\n"
|
||||
"@return A new edge collection containing the edges overlapping or touching polygons from the region\n"
|
||||
"@return A new edge collection containing the the selected edges\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28."
|
||||
) +
|
||||
method ("not_inside", (db::Edges (db::Edges::*) (const db::Region &) const) &db::Edges::selected_not_inside, gsi::arg ("other"),
|
||||
"@brief Returns the edges from this edge collection which are not inside (completely covered by) polygons from the region\n"
|
||||
"\n"
|
||||
"@return A new edge collection containing the edges not overlapping or touching polygons from the region\n"
|
||||
"@return A new edge collection containing the the selected edges\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28."
|
||||
) +
|
||||
|
|
@ -1436,35 +1436,35 @@ Class<db::Edges> decl_Edges (decl_dbShapeCollection, "db", "Edges",
|
|||
"It has been introduced in version 0.28."
|
||||
) +
|
||||
method ("outside", (db::Edges (db::Edges::*) (const db::Edges &) const) &db::Edges::selected_outside, gsi::arg ("other"),
|
||||
"@brief Returns the edges of this edge collection which are outside (completely covered by) edges from the other edge collection\n"
|
||||
"@brief Returns the edges of this edge collection which are outside (not overlapped by) edges from the other edge collection\n"
|
||||
"\n"
|
||||
"@return A new edge collection containing the edges overlapping or touching edges from the other edge collection\n"
|
||||
"@return A new edge collection containing the the selected edges\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28."
|
||||
) +
|
||||
method ("not_outside", (db::Edges (db::Edges::*) (const db::Edges &) const) &db::Edges::selected_not_outside, gsi::arg ("other"),
|
||||
"@brief Returns the edges of this edge collection which are not outside (completely covered by) edges from the other edge collection\n"
|
||||
"@brief Returns the edges of this edge collection which are not outside (partially overlapped by) edges from the other edge collection\n"
|
||||
"\n"
|
||||
"@return A new edge collection containing the edges not overlapping or touching edges from the other edge collection\n"
|
||||
"@return A new edge collection containing the the selected edges\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28."
|
||||
) +
|
||||
method ("select_outside", (db::Edges &(db::Edges::*) (const db::Edges &)) &db::Edges::select_outside, gsi::arg ("other"),
|
||||
"@brief Selects the edges from this edge collection which are outside (completely covered by) edges from the other edge collection\n"
|
||||
"@brief Selects the edges from this edge collection which are outside (not overlapped by) edges from the other edge collection\n"
|
||||
"\n"
|
||||
"@return The edge collection after the edges have been selected (self)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28."
|
||||
) +
|
||||
method ("select_not_outside", (db::Edges &(db::Edges::*) (const db::Edges &)) &db::Edges::select_not_outside, gsi::arg ("other"),
|
||||
"@brief Selects the edges from this edge collection which are not outside (completely covered by) edges from the other edge collection\n"
|
||||
"@brief Selects the edges from this edge collection which are not outside (partially overlapped by) edges from the other edge collection\n"
|
||||
"\n"
|
||||
"@return The edge collection after the edges have been selected (self)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28."
|
||||
) +
|
||||
method_ext ("split_outside", &split_outside_with_edges, gsi::arg ("other"),
|
||||
"@brief Selects the edges from this edge collection which are and are not outside (completely covered by) edges from the other collection\n"
|
||||
"@brief Selects the edges from this edge collection which are and are not outside (not overlapped by) edges from the other collection\n"
|
||||
"\n"
|
||||
"@return A two-element list of edge collections (first: outside, second: non-outside)\n"
|
||||
"\n"
|
||||
|
|
@ -1472,35 +1472,35 @@ Class<db::Edges> decl_Edges (decl_dbShapeCollection, "db", "Edges",
|
|||
"It has been introduced in version 0.28."
|
||||
) +
|
||||
method ("outside", (db::Edges (db::Edges::*) (const db::Region &) const) &db::Edges::selected_outside, gsi::arg ("other"),
|
||||
"@brief Returns the edges from this edge collection which are outside (completely covered by) polygons from the region\n"
|
||||
"@brief Returns the edges from this edge collection which are outside (not overlapped by) polygons from the region\n"
|
||||
"\n"
|
||||
"@return A new edge collection containing the edges overlapping or touching polygons from the region\n"
|
||||
"@return A new edge collection containing the the selected edges\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28."
|
||||
) +
|
||||
method ("not_outside", (db::Edges (db::Edges::*) (const db::Region &) const) &db::Edges::selected_not_outside, gsi::arg ("other"),
|
||||
"@brief Returns the edges from this edge collection which are not outside (completely covered by) polygons from the region\n"
|
||||
"@brief Returns the edges from this edge collection which are not outside (partially overlapped by) polygons from the region\n"
|
||||
"\n"
|
||||
"@return A new edge collection containing the edges not overlapping or touching polygons from the region\n"
|
||||
"@return A new edge collection containing the the selected edges\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28."
|
||||
) +
|
||||
method ("select_outside", (db::Edges &(db::Edges::*) (const db::Region &)) &db::Edges::select_outside, gsi::arg ("other"),
|
||||
"@brief Selects the edges from this edge collection which are outside (completely covered by) polygons from the region\n"
|
||||
"@brief Selects the edges from this edge collection which are outside (not overlapped by) polygons from the region\n"
|
||||
"\n"
|
||||
"@return The edge collection after the edges have been selected (self)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28."
|
||||
) +
|
||||
method ("select_not_outside", (db::Edges &(db::Edges::*) (const db::Region &)) &db::Edges::select_not_outside, gsi::arg ("other"),
|
||||
"@brief Selects the edges from this edge collection which are not outside (completely covered by) polygons from the region\n"
|
||||
"@brief Selects the edges from this edge collection which are not outside (partially overlapped by) polygons from the region\n"
|
||||
"\n"
|
||||
"@return The edge collection after the edges have been selected (self)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28."
|
||||
) +
|
||||
method_ext ("split_outside", &split_outside_with_region, gsi::arg ("other"),
|
||||
"@brief Selects the edges from this edge collection which are and are not outside (completely covered by) polygons from the other region\n"
|
||||
"@brief Selects the edges from this edge collection which are and are not outside (not overlapped by) polygons from the other region\n"
|
||||
"\n"
|
||||
"@return A two-element list of edge collections (first: outside, second: non-outside)\n"
|
||||
"\n"
|
||||
|
|
|
|||
|
|
@ -2283,13 +2283,17 @@ CODE
|
|||
|
||||
# %DRC%
|
||||
# @name inside
|
||||
# @brief Selects edges or polygons of self which are inside edges or polygons from the other layer
|
||||
# @brief Selects edges, edge pairs or polygons of self which are inside edges or polygons from the other layer
|
||||
# @synopsis layer.inside(other)
|
||||
#
|
||||
# If layer is a polygon layer, the other layer needs to be a polygon layer too.
|
||||
# In this case, this method selects all polygons which are completely inside
|
||||
# polygons from the other layer.
|
||||
#
|
||||
# If layer is an edge pair layer, the other layer needs to be a polygon layer.
|
||||
# In this case, this method selects all edge pairs which are completely inside
|
||||
# polygons from the other layer.
|
||||
#
|
||||
# If layer is an edge layer, the other layer can be polygon or edge layer. In the
|
||||
# first case, all edges completely inside the polygons from the other layer are
|
||||
# selected. If the other layer is an edge layer, all edges completely contained
|
||||
|
|
@ -2329,10 +2333,10 @@ CODE
|
|||
|
||||
# %DRC%
|
||||
# @name not_inside
|
||||
# @brief Selects edges or polygons of self which are not inside edges or polygons from the other layer
|
||||
# @brief Selects edges, edge pairs or polygons of self which are not inside edges or polygons from the other layer
|
||||
# @synopsis layer.not_inside(other)
|
||||
#
|
||||
# This method computes the inverse of \inside - i.e. edges or polygons from the layer
|
||||
# This method computes the inverse of \inside - i.e. edge, edge pairs or polygons from the layer
|
||||
# not being inside polygons or edges from the other layer.
|
||||
#
|
||||
# This method returns a new layer containing the selected shapes. A version which modifies self
|
||||
|
|
@ -2370,7 +2374,7 @@ CODE
|
|||
# @brief Returns the results of \inside and \not_inside at the same time
|
||||
# @synopsis (a, b) = layer.split_inside(other)
|
||||
#
|
||||
# This method returns the polygons or edges inside of polygons or edges from the other layer in
|
||||
# This method returns the polygons, edge pairs or edges inside of polygons or edges from the other layer in
|
||||
# one layer and all others in a second layer. This method is equivalent to calling
|
||||
# \inside and \not_inside, but is faster than doing this in separate steps:
|
||||
#
|
||||
|
|
@ -2380,7 +2384,7 @@ CODE
|
|||
|
||||
# %DRC%
|
||||
# @name select_inside
|
||||
# @brief Selects edges or polygons of self which are inside edges or polygons from the other layer
|
||||
# @brief Selects edges, edge pairs or polygons of self which are inside edges or polygons from the other layer
|
||||
# @synopsis layer.select_inside(other)
|
||||
#
|
||||
# This method is the in-place version of \inside - i.e. it modifies the layer instead
|
||||
|
|
@ -2388,7 +2392,7 @@ CODE
|
|||
|
||||
# %DRC%
|
||||
# @name select_not_inside
|
||||
# @brief Selects edges or polygons of self which are not inside edges or polygons from the other layer
|
||||
# @brief Selects edges, edge pairs or polygons of self which are not inside edges or polygons from the other layer
|
||||
# @synopsis layer.select_not_inside(other)
|
||||
#
|
||||
# This method is the in-place version of \inside - i.e. it modifies the layer instead
|
||||
|
|
@ -2396,13 +2400,17 @@ CODE
|
|||
|
||||
# %DRC%
|
||||
# @name outside
|
||||
# @brief Selects edges or polygons of self which are outside edges or polygons from the other layer
|
||||
# @brief Selects edges, edge pairs or polygons of self which are outside edges or polygons from the other layer
|
||||
# @synopsis layer.outside(other)
|
||||
#
|
||||
# If layer is a polygon layer, the other layer needs to be a polygon layer too.
|
||||
# In this case, this method selects all polygons which are entirely outside
|
||||
# polygons from the other layer.
|
||||
#
|
||||
# If layer is an edge pair layer, the other layer needs to be a polygon layer.
|
||||
# In this case, this method selects all edge pairs which are entirely outside
|
||||
# polygons from the other layer.
|
||||
#
|
||||
# If layer is an edge layer, the other layer can be polygon or edge layer. In the
|
||||
# first case, all edges entirely outside the polygons from the other layer are
|
||||
# selected. If the other layer is an edge layer, all edges entirely outside
|
||||
|
|
@ -2442,10 +2450,10 @@ CODE
|
|||
|
||||
# %DRC%
|
||||
# @name not_outside
|
||||
# @brief Selects edges or polygons of self which are not outside edges or polygons from the other layer
|
||||
# @brief Selects edges, edge pairs or polygons of self which are not outside edges or polygons from the other layer
|
||||
# @synopsis layer.not_outside(other)
|
||||
#
|
||||
# This method computes the inverse of \outside - i.e. edges or polygons from the layer
|
||||
# This method computes the inverse of \outside - i.e. edges, edge pairs or polygons from the layer
|
||||
# not being outside polygons or edges from the other layer.
|
||||
#
|
||||
# This method returns a new layer containing the selected shapes. A version which modifies self
|
||||
|
|
@ -2483,7 +2491,7 @@ CODE
|
|||
# @brief Returns the results of \outside and \not_outside at the same time
|
||||
# @synopsis (a, b) = layer.split_outside(other)
|
||||
#
|
||||
# This method returns the polygons or edges outside of polygons or edges from the other layer in
|
||||
# This method returns the polygons, edge pairs or edges outside of polygons or edges from the other layer in
|
||||
# one layer and all others in a second layer. This method is equivalent to calling
|
||||
# \outside and \not_outside, but is faster than doing this in separate steps:
|
||||
#
|
||||
|
|
@ -2493,7 +2501,7 @@ CODE
|
|||
|
||||
# %DRC%
|
||||
# @name select_outside
|
||||
# @brief Selects edges or polygons of self which are outside edges or polygons from the other layer
|
||||
# @brief Selects edges, edge pairs or polygons of self which are outside edges or polygons from the other layer
|
||||
# @synopsis layer.select_outside(other)
|
||||
#
|
||||
# This method is the in-place version of \outside - i.e. it modifies the layer instead
|
||||
|
|
@ -2501,7 +2509,7 @@ CODE
|
|||
|
||||
# %DRC%
|
||||
# @name select_not_outside
|
||||
# @brief Selects edges or polygons of self which are not outside edges or polygons from the other layer
|
||||
# @brief Selects edges, edge pairs or polygons of self which are not outside edges or polygons from the other layer
|
||||
# @synopsis layer.select_not_outside(other)
|
||||
#
|
||||
# This method is the in-place version of \outside - i.e. it modifies the layer instead
|
||||
|
|
@ -2571,7 +2579,7 @@ CODE
|
|||
# It returns a new layer containing the selected shapes. A version which modifies self
|
||||
# is \select_interacting.
|
||||
#
|
||||
# This method is available for polygon, text and edge layers. Edges can be selected
|
||||
# This method is available for polygon, text, edge and edge pair layers. Edges and edge pairs can be selected
|
||||
# with respect to other edges or polygons. Texts can be selected with respect to
|
||||
# polygons. Polygons can be selected with respect to edges, texts and other polygons.
|
||||
#
|
||||
|
|
@ -2612,7 +2620,7 @@ CODE
|
|||
# It returns a new layer containing the selected shapes. A version which modifies self
|
||||
# is \select_not_interacting.
|
||||
#
|
||||
# This method is available for polygon, text and edge layers. Edges can be selected
|
||||
# This method is available for polygon, text, edge and edge pair layers. Edges and edge pairs can be selected
|
||||
# with respect to other edges or polygons. Texts can be selected with respect to
|
||||
# polygons. Polygons can be selected with respect to edges, texts and other polygons.
|
||||
#
|
||||
|
|
@ -2668,7 +2676,7 @@ CODE
|
|||
# It modifies self to contain the selected shapes. A version which does not modify self
|
||||
# is \interacting.
|
||||
#
|
||||
# This method is available for polygon, text and edge layers. Edges can be selected
|
||||
# This method is available for polygon, text, edge and edge pair layers. Edges and edge pairs can be selected
|
||||
# with respect to other edges or polygons. Texts can be selected with respect to
|
||||
# polygons. Polygons can be selected with respect to edges, texts and other polygons.
|
||||
#
|
||||
|
|
@ -2690,7 +2698,7 @@ CODE
|
|||
# It modifies self to contain the selected shapes. A version which does not modify self
|
||||
# is \not_interacting.
|
||||
#
|
||||
# This method is available for polygon, text and edge layers. Edges can be selected
|
||||
# This method is available for polygon, text, edge and edge pair layers. Edges or edge pairs can be selected
|
||||
# with respect to other edges or polygons. Texts can be selected with respect to
|
||||
# polygons. Polygons can be selected with respect to edges, texts and other polygons.
|
||||
#
|
||||
|
|
@ -2772,7 +2780,7 @@ CODE
|
|||
#
|
||||
# This method will neither modify self nor other.
|
||||
#
|
||||
# This method is available for polygon, edge and text layers, similar to interacting.
|
||||
# This method is available for polygon, edge, edge pair and text layers, similar to interacting.
|
||||
|
||||
# %DRC%
|
||||
# @name pull_overlapping
|
||||
|
|
@ -2813,13 +2821,14 @@ CODE
|
|||
requires_region
|
||||
other.requires_region
|
||||
else
|
||||
requires_edges_texts_or_region
|
||||
if self.data.is_a?(RBA::Text)
|
||||
if self.data.is_a?(RBA::Texts)
|
||||
other.requires_region
|
||||
elsif self.data.is_a?(RBA::Region)
|
||||
other.requires_edges_texts_or_region
|
||||
else
|
||||
elsif self.data.is_a?(RBA::Edges) || self.data.is_a?(RBA::EdgePairs)
|
||||
other.requires_edges_or_region
|
||||
else
|
||||
raise("Invalid data type of primary layer")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -2837,11 +2846,13 @@ CODE
|
|||
|
||||
@engine._context("#{f}") do
|
||||
|
||||
requires_edges_or_region
|
||||
check_is_layer(other)
|
||||
if self.data.is_a?(RBA::Edges)
|
||||
other.requires_edges_or_region
|
||||
else
|
||||
elsif self.data.is_a?(RBA::Region) || self.data.is_a?(RBA::EdgePairs)
|
||||
other.requires_region
|
||||
else
|
||||
raise("Invalid data type of primary layer")
|
||||
end
|
||||
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data))
|
||||
|
|
@ -2913,12 +2924,14 @@ CODE
|
|||
@engine._context("#{f}") do
|
||||
|
||||
check_is_layer(other)
|
||||
if self.data.is_a?(RBA::Text)
|
||||
if self.data.is_a?(RBA::Texts)
|
||||
other.requires_region
|
||||
elsif self.data.is_a?(RBA::Region)
|
||||
other.requires_edges_texts_or_region
|
||||
else
|
||||
elsif self.data.is_a?(RBA::Edges) || self.data.is_a?(RBA::EdgePairs)
|
||||
other.requires_edges_or_region
|
||||
else
|
||||
raise("Invalid data type of primary layer")
|
||||
end
|
||||
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data, *minmax_count(*args)))
|
||||
|
|
@ -2938,13 +2951,14 @@ CODE
|
|||
@engine._context("#{f}") do
|
||||
|
||||
check_is_layer(other)
|
||||
requires_edges_texts_or_region
|
||||
if self.data.is_a?(RBA::Text)
|
||||
if self.data.is_a?(RBA::Texts)
|
||||
other.requires_region
|
||||
elsif self.data.is_a?(RBA::Region)
|
||||
other.requires_edges_texts_or_region
|
||||
else
|
||||
elsif self.data.is_a?(RBA::Edges) || self.data.is_a?(RBA::EdgePairs)
|
||||
other.requires_edges_or_region
|
||||
else
|
||||
raise("Invalid data type of primary layer")
|
||||
end
|
||||
|
||||
if @engine.is_tiled?
|
||||
|
|
@ -2985,11 +2999,13 @@ CODE
|
|||
@engine._context("#{f}") do
|
||||
|
||||
check_is_layer(other)
|
||||
requires_edges_or_region
|
||||
if self.data.is_a?(RBA::Edges)
|
||||
other.requires_edges_or_region
|
||||
elsif self.data.is_a?(RBA::Region)
|
||||
if self.data.is_a?(RBA::Region)
|
||||
other.requires_edges_texts_or_region
|
||||
elsif self.data.is_a?(RBA::Edges) || self.data.is_a?(RBA::EdgePairs)
|
||||
other.requires_edges_or_region
|
||||
else
|
||||
# Note: there is no "split" for Texts yet.
|
||||
raise("Invalid data type of primary layer")
|
||||
end
|
||||
|
||||
res = @engine._tcmd_a2(self.data, 0, self.data.class, self.data.class, :#{f}, other.data, *minmax_count(*args))
|
||||
|
|
@ -3088,11 +3104,13 @@ CODE
|
|||
|
||||
@engine._context("#{f}") do
|
||||
|
||||
requires_edges_or_region
|
||||
check_is_layer(other)
|
||||
if self.data.is_a?(RBA::Edges)
|
||||
other.requires_edges_or_region
|
||||
else
|
||||
elsif self.data.is_a?(RBA::Region) || self.data.is_a?(RBA::EdgePairs)
|
||||
other.requires_region
|
||||
else
|
||||
raise("Invalid data type of primary layer")
|
||||
end
|
||||
|
||||
if @engine.is_tiled?
|
||||
|
|
@ -3115,11 +3133,12 @@ CODE
|
|||
@engine._context("#{f}") do
|
||||
|
||||
check_is_layer(other)
|
||||
requires_edges_or_region
|
||||
if self.data.is_a?(RBA::Edges)
|
||||
other.requires_edges_or_region
|
||||
elsif self.data.is_a?(RBA::Region)
|
||||
elsif self.data.is_a?(RBA::Region) || self.data.is_a?(RBA::EdgePairs)
|
||||
other.requires_region
|
||||
else
|
||||
raise("Invalid data type of primary layer")
|
||||
end
|
||||
|
||||
res = @engine._tcmd_a2(self.data, 0, self.data.class, self.data.class, :#{f}, other.data, *minmax_count(*args))
|
||||
|
|
|
|||
|
|
@ -1963,3 +1963,13 @@ TEST(130d_size_inside_outside)
|
|||
{
|
||||
run_test (_this, "130", true);
|
||||
}
|
||||
|
||||
TEST(131_edge_pair_interactions)
|
||||
{
|
||||
run_test (_this, "131", false);
|
||||
}
|
||||
|
||||
TEST(131d_edge_pair_interactions)
|
||||
{
|
||||
run_test (_this, "131", true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,146 @@
|
|||
|
||||
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)
|
||||
l4 = input(4, 0)
|
||||
l5 = input(5, 0)
|
||||
l6 = input(6, 0)
|
||||
|
||||
l1.output(1, 0)
|
||||
l2.output(2, 0)
|
||||
l3.output(3, 0)
|
||||
l4.output(4, 0)
|
||||
l5.output(5, 0)
|
||||
l6.output(6, 0)
|
||||
|
||||
eps = l1.sep(l2, 200.nm)
|
||||
|
||||
eps.output(10, 0)
|
||||
|
||||
l = 100
|
||||
eps.interacting(l3).output(l + 0, 0)
|
||||
eps.interacting(l4).output(l + 1, 0)
|
||||
eps.interacting(l5).output(l + 2, 0)
|
||||
eps.interacting(l6).output(l + 3, 0)
|
||||
|
||||
l = 110
|
||||
eps.interacting(l3, 1..1).output(l + 0, 0)
|
||||
eps.interacting(l4, 1..1).output(l + 1, 0)
|
||||
eps.interacting(l5, 1..1).output(l + 2, 0)
|
||||
eps.interacting(l6, 1..1).output(l + 3, 0)
|
||||
|
||||
l = 120
|
||||
eps.interacting(l3, 2).output(l + 0, 0)
|
||||
eps.interacting(l4, 2).output(l + 1, 0)
|
||||
eps.interacting(l5, 2).output(l + 2, 0)
|
||||
eps.interacting(l6, 2).output(l + 3, 0)
|
||||
|
||||
l = 130
|
||||
eps.not_interacting(l3).output(l + 0, 0)
|
||||
eps.not_interacting(l4).output(l + 1, 0)
|
||||
eps.not_interacting(l5).output(l + 2, 0)
|
||||
eps.not_interacting(l6).output(l + 3, 0)
|
||||
|
||||
l = 140
|
||||
eps.interacting(l3.edges).output(l + 0, 0)
|
||||
eps.interacting(l4.edges).output(l + 1, 0)
|
||||
eps.interacting(l5.edges).output(l + 2, 0)
|
||||
eps.interacting(l6.edges).output(l + 3, 0)
|
||||
|
||||
l = 150
|
||||
eps.interacting(l3.edges, 1 .. 1).output(l + 0, 0)
|
||||
eps.interacting(l4.edges, 1 .. 1).output(l + 1, 0)
|
||||
eps.interacting(l5.edges, 1 .. 1).output(l + 2, 0)
|
||||
eps.interacting(l6.edges, 1 .. 1).output(l + 3, 0)
|
||||
|
||||
l = 160
|
||||
eps.interacting(l3.edges, 2).output(l + 0, 0)
|
||||
eps.interacting(l4.edges, 2).output(l + 1, 0)
|
||||
eps.interacting(l5.edges, 2).output(l + 2, 0)
|
||||
eps.interacting(l6.edges, 2).output(l + 3, 0)
|
||||
|
||||
l = 170
|
||||
eps.not_interacting(l3.edges).output(l + 0, 0)
|
||||
eps.not_interacting(l4.edges).output(l + 1, 0)
|
||||
eps.not_interacting(l5.edges).output(l + 2, 0)
|
||||
eps.not_interacting(l6.edges).output(l + 3, 0)
|
||||
|
||||
l = 180
|
||||
eps.split_interacting(l3, 1..1)[0].output(l + 0, 0)
|
||||
eps.split_interacting(l4, 1..1)[0].output(l + 1, 0)
|
||||
eps.split_interacting(l5, 1..1)[0].output(l + 2, 0)
|
||||
eps.split_interacting(l6, 1..1)[0].output(l + 3, 0)
|
||||
|
||||
l = 190
|
||||
eps.split_interacting(l3, 1..1)[1].output(l + 0, 0)
|
||||
eps.split_interacting(l4, 1..1)[1].output(l + 1, 0)
|
||||
eps.split_interacting(l5, 1..1)[1].output(l + 2, 0)
|
||||
eps.split_interacting(l6, 1..1)[1].output(l + 3, 0)
|
||||
|
||||
l = 200
|
||||
eps.split_interacting(l3.edges, 1..1)[0].output(l + 0, 0)
|
||||
eps.split_interacting(l4.edges, 1..1)[0].output(l + 1, 0)
|
||||
eps.split_interacting(l5.edges, 1..1)[0].output(l + 2, 0)
|
||||
eps.split_interacting(l6.edges, 1..1)[0].output(l + 3, 0)
|
||||
|
||||
l = 210
|
||||
eps.split_interacting(l3.edges, 1..1)[1].output(l + 0, 0)
|
||||
eps.split_interacting(l4.edges, 1..1)[1].output(l + 1, 0)
|
||||
eps.split_interacting(l5.edges, 1..1)[1].output(l + 2, 0)
|
||||
eps.split_interacting(l6.edges, 1..1)[1].output(l + 3, 0)
|
||||
|
||||
l = 300
|
||||
eps.inside(l3).output(l + 0, 0)
|
||||
eps.inside(l4).output(l + 1, 0)
|
||||
eps.inside(l5).output(l + 2, 0)
|
||||
eps.inside(l6).output(l + 3, 0)
|
||||
|
||||
l = 310
|
||||
eps.not_inside(l3).output(l + 0, 0)
|
||||
eps.not_inside(l4).output(l + 1, 0)
|
||||
eps.not_inside(l5).output(l + 2, 0)
|
||||
eps.not_inside(l6).output(l + 3, 0)
|
||||
|
||||
l = 320
|
||||
eps.split_inside(l3)[0].output(l + 0, 0)
|
||||
eps.split_inside(l4)[0].output(l + 1, 0)
|
||||
eps.split_inside(l5)[0].output(l + 2, 0)
|
||||
eps.split_inside(l6)[0].output(l + 3, 0)
|
||||
|
||||
l = 330
|
||||
eps.split_inside(l3)[1].output(l + 0, 0)
|
||||
eps.split_inside(l4)[1].output(l + 1, 0)
|
||||
eps.split_inside(l5)[1].output(l + 2, 0)
|
||||
eps.split_inside(l6)[1].output(l + 3, 0)
|
||||
|
||||
l = 400
|
||||
eps.outside(l3).output(l + 0, 0)
|
||||
eps.outside(l4).output(l + 1, 0)
|
||||
eps.outside(l5).output(l + 2, 0)
|
||||
eps.outside(l6).output(l + 3, 0)
|
||||
|
||||
l = 410
|
||||
eps.not_outside(l3).output(l + 0, 0)
|
||||
eps.not_outside(l4).output(l + 1, 0)
|
||||
eps.not_outside(l5).output(l + 2, 0)
|
||||
eps.not_outside(l6).output(l + 3, 0)
|
||||
|
||||
l = 420
|
||||
eps.split_outside(l3)[0].output(l + 0, 0)
|
||||
eps.split_outside(l4)[0].output(l + 1, 0)
|
||||
eps.split_outside(l5)[0].output(l + 2, 0)
|
||||
eps.split_outside(l6)[0].output(l + 3, 0)
|
||||
|
||||
l = 430
|
||||
eps.split_outside(l3)[1].output(l + 0, 0)
|
||||
eps.split_outside(l4)[1].output(l + 1, 0)
|
||||
eps.split_outside(l5)[1].output(l + 2, 0)
|
||||
eps.split_outside(l6)[1].output(l + 3, 0)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -480,6 +480,100 @@ class DBEdgePairs_TestClass < TestBase
|
|||
|
||||
end
|
||||
|
||||
# Interactions
|
||||
def test_interactions
|
||||
|
||||
edge_pairs = RBA::EdgePairs::new
|
||||
edge_pairs.insert(RBA::EdgePair::new(RBA::Edge::new(0, 0, 100, 100), RBA::Edge::new(200, 300, 200, 500)))
|
||||
edge_pairs.insert(RBA::EdgePair::new(RBA::Edge::new(0, 1000, 100, 1000), RBA::Edge::new(100, 1000, 0, 1000)))
|
||||
|
||||
e = RBA::Edges::new
|
||||
e.insert(RBA::Edge::new(0, 200, 200, 200))
|
||||
|
||||
assert_equal(edge_pairs.interacting(e).to_s, "(0,0;100,100)/(200,300;200,500)")
|
||||
assert_equal(edge_pairs.interacting(e, 1, 1).to_s, "(0,0;100,100)/(200,300;200,500)")
|
||||
assert_equal(edge_pairs.interacting(e, 2, 2).to_s, "")
|
||||
assert_equal(edge_pairs.not_interacting(e).to_s, "(0,1000;100,1000)/(100,1000;0,1000)")
|
||||
assert_equal(edge_pairs.not_interacting(e, 2, 2).to_s, "(0,0;100,100)/(200,300;200,500);(0,1000;100,1000)/(100,1000;0,1000)")
|
||||
ep = edge_pairs.dup
|
||||
ep.select_interacting(e)
|
||||
assert_equal(ep.to_s, "(0,0;100,100)/(200,300;200,500)")
|
||||
ep = edge_pairs.dup
|
||||
ep.select_interacting(e, 1, 1)
|
||||
assert_equal(ep.to_s, "(0,0;100,100)/(200,300;200,500)")
|
||||
ep = edge_pairs.dup
|
||||
ep.select_interacting(e, 2, 2)
|
||||
assert_equal(ep.to_s, "")
|
||||
ep = edge_pairs.dup
|
||||
ep.select_not_interacting(e)
|
||||
assert_equal(ep.to_s, "(0,1000;100,1000)/(100,1000;0,1000)")
|
||||
ep = edge_pairs.dup
|
||||
ep.select_not_interacting(e, 2, 2)
|
||||
assert_equal(ep.to_s, "(0,0;100,100)/(200,300;200,500);(0,1000;100,1000)/(100,1000;0,1000)")
|
||||
assert_equal(edge_pairs.split_interacting(e)[0].to_s, "(0,0;100,100)/(200,300;200,500)")
|
||||
assert_equal(edge_pairs.split_interacting(e)[1].to_s, "(0,1000;100,1000)/(100,1000;0,1000)")
|
||||
assert_equal(edge_pairs.split_interacting(e, 1, 1)[0].to_s, "(0,0;100,100)/(200,300;200,500)")
|
||||
assert_equal(edge_pairs.split_interacting(e, 1, 1)[1].to_s, "(0,1000;100,1000)/(100,1000;0,1000)")
|
||||
assert_equal(edge_pairs.split_interacting(e, 2, 2)[0].to_s, "")
|
||||
assert_equal(edge_pairs.split_interacting(e, 2, 2)[1].to_s, "(0,0;100,100)/(200,300;200,500);(0,1000;100,1000)/(100,1000;0,1000)")
|
||||
|
||||
r = RBA::Region::new
|
||||
r.insert(RBA::Box::new(0, 190, 200, 210))
|
||||
|
||||
assert_equal(edge_pairs.interacting(r).to_s, "(0,0;100,100)/(200,300;200,500)")
|
||||
assert_equal(edge_pairs.interacting(r, 1, 1).to_s, "(0,0;100,100)/(200,300;200,500)")
|
||||
assert_equal(edge_pairs.interacting(r, 2, 2).to_s, "")
|
||||
assert_equal(edge_pairs.not_interacting(r).to_s, "(0,1000;100,1000)/(100,1000;0,1000)")
|
||||
assert_equal(edge_pairs.not_interacting(r, 2, 2).to_s, "(0,0;100,100)/(200,300;200,500);(0,1000;100,1000)/(100,1000;0,1000)")
|
||||
ep = edge_pairs.dup
|
||||
ep.select_interacting(r)
|
||||
assert_equal(ep.to_s, "(0,0;100,100)/(200,300;200,500)")
|
||||
ep = edge_pairs.dup
|
||||
ep.select_interacting(r, 1, 1)
|
||||
assert_equal(ep.to_s, "(0,0;100,100)/(200,300;200,500)")
|
||||
ep = edge_pairs.dup
|
||||
ep.select_interacting(r, 2, 2)
|
||||
assert_equal(ep.to_s, "")
|
||||
ep = edge_pairs.dup
|
||||
ep.select_not_interacting(r)
|
||||
assert_equal(ep.to_s, "(0,1000;100,1000)/(100,1000;0,1000)")
|
||||
ep = edge_pairs.dup
|
||||
ep.select_not_interacting(r, 2, 2)
|
||||
assert_equal(ep.to_s, "(0,0;100,100)/(200,300;200,500);(0,1000;100,1000)/(100,1000;0,1000)")
|
||||
assert_equal(edge_pairs.split_interacting(r)[0].to_s, "(0,0;100,100)/(200,300;200,500)")
|
||||
assert_equal(edge_pairs.split_interacting(r)[1].to_s, "(0,1000;100,1000)/(100,1000;0,1000)")
|
||||
assert_equal(edge_pairs.split_interacting(r, 1, 1)[0].to_s, "(0,0;100,100)/(200,300;200,500)")
|
||||
assert_equal(edge_pairs.split_interacting(r, 1, 1)[1].to_s, "(0,1000;100,1000)/(100,1000;0,1000)")
|
||||
assert_equal(edge_pairs.split_interacting(r, 2, 2)[0].to_s, "")
|
||||
assert_equal(edge_pairs.split_interacting(r, 2, 2)[1].to_s, "(0,0;100,100)/(200,300;200,500);(0,1000;100,1000)/(100,1000;0,1000)")
|
||||
|
||||
r = RBA::Region::new
|
||||
r.insert(RBA::Box::new(0, 0, 200, 500))
|
||||
|
||||
assert_equal(edge_pairs.inside(r).to_s, "(0,0;100,100)/(200,300;200,500)")
|
||||
assert_equal(edge_pairs.not_inside(r).to_s, "(0,1000;100,1000)/(100,1000;0,1000)")
|
||||
ep = edge_pairs.dup
|
||||
ep.select_inside(r)
|
||||
assert_equal(ep.to_s, "(0,0;100,100)/(200,300;200,500)")
|
||||
ep = edge_pairs.dup
|
||||
ep.select_not_inside(r)
|
||||
assert_equal(ep.to_s, "(0,1000;100,1000)/(100,1000;0,1000)")
|
||||
assert_equal(edge_pairs.split_inside(r)[0].to_s, "(0,0;100,100)/(200,300;200,500)")
|
||||
assert_equal(edge_pairs.split_inside(r)[1].to_s, "(0,1000;100,1000)/(100,1000;0,1000)")
|
||||
|
||||
assert_equal(edge_pairs.outside(r).to_s, "(0,1000;100,1000)/(100,1000;0,1000)")
|
||||
assert_equal(edge_pairs.not_outside(r).to_s, "(0,0;100,100)/(200,300;200,500)")
|
||||
ep = edge_pairs.dup
|
||||
ep.select_outside(r)
|
||||
assert_equal(ep.to_s, "(0,1000;100,1000)/(100,1000;0,1000)")
|
||||
ep = edge_pairs.dup
|
||||
ep.select_not_outside(r)
|
||||
assert_equal(ep.to_s, "(0,0;100,100)/(200,300;200,500)")
|
||||
assert_equal(edge_pairs.split_outside(r)[0].to_s, "(0,1000;100,1000)/(100,1000;0,1000)")
|
||||
assert_equal(edge_pairs.split_outside(r)[1].to_s, "(0,0;100,100)/(200,300;200,500)")
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue