Merge pull request #1197 from KLayout/wip

Wip
This commit is contained in:
Matthias Köfferlein 2022-12-02 01:29:25 +01:00 committed by GitHub
commit b3968c31e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 964 additions and 145 deletions

View File

@ -560,6 +560,25 @@ else
fi
echo " Installation target: $BIN"
echo " Build directory: $BUILD"
echo ""
echo " Build flags:"
echo " HAVE_RUBY=$HAVE_RUBY"
echo " HAVE_PYTHON=$HAVE_PYTHON"
echo " HAVE_QTBINDINGS=$HAVE_QTBINDINGS"
echo " HAVE_QT=$HAVE_QT"
echo " HAVE_QT_UITOOLS=$HAVE_QT_UITOOLS"
echo " HAVE_QT_NETWORK=$HAVE_QT_NETWORK"
echo " HAVE_QT_SQL=$HAVE_QT_SQL"
echo " HAVE_QT_SVG=$HAVE_QT_SVG"
echo " HAVE_QT_PRINTSUPPORT=$HAVE_QT_PRINTSUPPORT"
echo " HAVE_QT_MULTIMEDIA=$HAVE_QT_MULTIMEDIA"
echo " HAVE_QT_DESIGNER=$HAVE_QT_DESIGNER"
echo " HAVE_QT_XML=$HAVE_QT_XML"
echo " HAVE_64BIT_COORD=$HAVE_64BIT_COORD"
echo " HAVE_CURL=$HAVE_CURL"
echo " HAVE_PNG=$HAVE_PNG"
echo " HAVE_EXPAT=$HAVE_EXPAT"
echo " RPATH=$RPATH"
mkdir -p $BUILD
@ -674,6 +693,7 @@ if [ $BUILD_EXPERT = 1 ]; then
QMAKE_CXXFLAGS="$CXXFLAGS"
QMAKE_CXXFLAGS_RELEASE=
QMAKE_CXXFLAGS_DEBUG=
QMAKE_LIBS="$LIBS"
QMAKE_LFLAGS="$LDFLAGS"
QMAKE_LFLAGS_RELEASE=
QMAKE_LFLAGS_DEBUG=

View File

@ -514,6 +514,12 @@ AsIfFlatEdges::extended (coord_type ext_b, coord_type ext_e, coord_type ext_o, c
EdgesDelegate *
AsIfFlatEdges::in (const Edges &other, bool invert) const
{
if (other.empty ()) {
return invert ? clone () : new EmptyEdges ();
} else if (empty ()) {
return new EmptyEdges ();
}
std::set <db::Edge> op;
for (EdgesIterator o (other.begin_merged ()); ! o.at_end (); ++o) {
op.insert (*o);
@ -530,6 +536,34 @@ AsIfFlatEdges::in (const Edges &other, bool invert) const
return new_region.release ();
}
std::pair<EdgesDelegate *, EdgesDelegate *>
AsIfFlatEdges::in_and_out (const Edges &other) const
{
if (other.empty ()) {
return std::make_pair (new EmptyEdges (), clone ());
} else if (empty ()) {
return std::make_pair (new EmptyEdges (), new EmptyEdges ());
}
std::set <db::Edge> op;
for (EdgesIterator o (other.begin_merged ()); ! o.at_end (); ++o) {
op.insert (*o);
}
std::unique_ptr<FlatEdges> in (new FlatEdges (false));
std::unique_ptr<FlatEdges> out (new FlatEdges (false));
for (EdgesIterator o (begin_merged ()); ! o.at_end (); ++o) {
if (op.find (*o) != op.end ()) {
in->insert (*o);
} else {
out->insert (*o);
}
}
return std::make_pair (in.release (), out.release ());
}
size_t
AsIfFlatEdges::count () const
{

View File

@ -204,6 +204,7 @@ public:
virtual std::pair<EdgesDelegate *, EdgesDelegate *> selected_inside_pair (const Region &other) const;
virtual EdgesDelegate *in (const Edges &, bool) const;
virtual std::pair<EdgesDelegate *, EdgesDelegate *> in_and_out (const Edges &) const;
virtual bool equals (const Edges &other) const;
virtual bool less (const Edges &other) const;

View File

@ -148,25 +148,6 @@ AsIfFlatRegion::edges (const EdgeFilterBase *filter) const
return result.release ();
}
RegionDelegate *
AsIfFlatRegion::in (const Region &other, bool invert) const
{
std::set <db::Polygon> op;
for (RegionIterator o (other.begin_merged ()); ! o.at_end (); ++o) {
op.insert (*o);
}
std::unique_ptr<FlatRegion> new_region (new FlatRegion (false));
for (RegionIterator o (begin_merged ()); ! o.at_end (); ++o) {
if ((op.find (*o) == op.end ()) == invert) {
new_region->insert (*o);
}
}
return new_region.release ();
}
bool
AsIfFlatRegion::is_box () const
{
@ -401,7 +382,7 @@ private:
}
std::pair<RegionDelegate *, RegionDelegate *>
AsIfFlatRegion::selected_interacting_generic (const Edges &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const
AsIfFlatRegion::in_and_out_generic (const Region &other, InteractingOutputMode output_mode) const
{
OutputPairHolder oph (output_mode, merged_semantics ());
@ -409,6 +390,56 @@ AsIfFlatRegion::selected_interacting_generic (const Edges &other, InteractingOut
return oph.region_pair ();
}
// shortcut
if (empty ()) {
if (output_mode == Positive || output_mode == Negative) {
return std::make_pair (clone (), (RegionDelegate *) 0);
} else {
return std::make_pair (clone (), clone ());
}
} else if (other.empty ()) {
if (output_mode == Positive) {
return std::make_pair (new EmptyRegion (), (RegionDelegate *) 0);
} else if (output_mode == Negative) {
return std::make_pair (clone (), (RegionDelegate *) 0);
} else {
return std::make_pair (new EmptyRegion (), clone ());
}
}
std::set <db::Polygon> op;
for (RegionIterator o (other.begin_merged ()); ! o.at_end (); ++o) {
op.insert (*o);
}
std::unique_ptr<FlatRegion> new_region (new FlatRegion (false));
for (RegionIterator o (begin_merged ()); ! o.at_end (); ++o) {
if (op.find (*o) != op.end ()) {
if (output_mode == Positive || output_mode == PositiveAndNegative) {
oph.results () [0]->insert (*o);
}
} else {
if (output_mode == Negative) {
oph.results () [0]->insert (*o);
} else if (output_mode == PositiveAndNegative) {
oph.results () [1]->insert (*o);
}
}
}
return oph.region_pair ();
}
std::pair<RegionDelegate *, RegionDelegate *>
AsIfFlatRegion::selected_interacting_generic (const Edges &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const
{
OutputPairHolder oph (output_mode, merged_semantics () || is_merged ());
if (output_mode == None) {
return oph.region_pair ();
}
min_count = std::max (size_t (1), min_count);
// shortcut
@ -454,7 +485,7 @@ AsIfFlatRegion::selected_interacting_generic (const Edges &other, InteractingOut
std::pair<RegionDelegate *, RegionDelegate *>
AsIfFlatRegion::selected_interacting_generic (const Texts &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const
{
OutputPairHolder oph (output_mode, merged_semantics ());
OutputPairHolder oph (output_mode, merged_semantics () || is_merged ());
if (output_mode == None) {
return oph.region_pair ();
@ -500,7 +531,7 @@ AsIfFlatRegion::selected_interacting_generic (const Texts &other, InteractingOut
std::pair<RegionDelegate *, RegionDelegate *>
AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, bool touching, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const
{
OutputPairHolder oph (output_mode, merged_semantics ());
OutputPairHolder oph (output_mode, merged_semantics () || is_merged ());
if (output_mode == None) {
return oph.region_pair ();
@ -580,7 +611,7 @@ AsIfFlatRegion::pull_generic (const Edges &other) const
std::vector<generic_shape_iterator<db::Edge> > others;
others.push_back (other.begin_merged ());
std::unique_ptr<FlatEdges> output (new FlatEdges (merged_semantics ()));
std::unique_ptr<FlatEdges> output (new FlatEdges (other.merged_semantics () || other.is_merged ()));
std::vector<db::Shapes *> results;
results.push_back (&output->raw_edges ());
@ -689,7 +720,7 @@ AsIfFlatRegion::pull_generic (const Region &other, int mode, bool touching) cons
std::vector<generic_shape_iterator<db::Polygon> > others;
others.push_back (other.begin_merged ());
std::unique_ptr<FlatRegion> output (new FlatRegion (merged_semantics ()));
std::unique_ptr<FlatRegion> output (new FlatRegion (other.merged_semantics () || other.is_merged ()));
std::vector<db::Shapes *> results;
results.push_back (&output->raw_polygons ());

View File

@ -265,7 +265,15 @@ public:
return pull_generic (other, 0, false);
}
virtual RegionDelegate *in (const Region &other, bool invert) const;
virtual RegionDelegate *in (const Region &other, bool invert) const
{
return in_and_out_generic (other, invert ? Negative : Positive).first;
}
virtual std::pair<RegionDelegate *, RegionDelegate *> in_and_out (const Region &other) const
{
return in_and_out_generic (other, PositiveAndNegative);
}
virtual bool equals (const Region &other) const;
virtual bool less (const Region &other) const;
@ -284,6 +292,7 @@ protected:
virtual RegionDelegate *pull_generic (const Region &other, int mode, bool touching) const;
virtual EdgesDelegate *pull_generic (const Edges &other) const;
virtual TextsDelegate *pull_generic (const Texts &other) const;
virtual std::pair<RegionDelegate *, RegionDelegate *> in_and_out_generic (const Region &other, InteractingOutputMode output_mode) const;
template <class Trans>
static void produce_markers_for_grid_check (const db::Polygon &poly, const Trans &tr, db::Coord gx, db::Coord gy, db::Shapes &shapes);

View File

@ -34,6 +34,7 @@
#include "dbLayoutUtils.h"
#include "dbLocalOperation.h"
#include "dbLocalOperationUtils.h"
#include "dbRegionLocalOperations.h" // for db::ContainedEdgesLocalOperation
#include "dbHierProcessor.h"
#include "dbEmptyEdges.h"
@ -1741,8 +1742,62 @@ EdgesDelegate *DeepEdges::pull_generic (const Edges &other) const
EdgesDelegate *DeepEdges::in (const Edges &other, bool invert) const
{
// TODO: is there a cheaper way?
return AsIfFlatEdges::in (other, invert);
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 edge collection isn't deep, turn into a top-level only deep edge collection 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 &edges = merged_deep_layer ();
DeepLayer dl_out (edges.derived ());
std::vector<unsigned int> output_layers;
output_layers.reserve (1);
output_layers.push_back (dl_out.layer ());
db::ContainedEdgesLocalOperation op (invert ? Negative : Positive);
db::local_processor<db::Edge, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&edges.layout ()), const_cast<db::Cell *> (&edges.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (edges.store ()->threads ());
proc.run (&op, edges.layer (), other_deep->merged_deep_layer ().layer (), output_layers);
return new db::DeepEdges (dl_out);
}
std::pair<EdgesDelegate *, EdgesDelegate *> DeepEdges::in_and_out (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 edge collection isn't deep, turn into a top-level only deep edge collection 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 &edges = merged_deep_layer ();
DeepLayer dl_out (edges.derived ());
DeepLayer dl_out2 (edges.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::ContainedEdgesLocalOperation op (PositiveAndNegative);
db::local_processor<db::Edge, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&edges.layout ()), const_cast<db::Cell *> (&edges.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (edges.store ()->threads ());
proc.run (&op, edges.layer (), other_deep->merged_deep_layer ().layer (), output_layers);
return std::make_pair (new db::DeepEdges (dl_out), new db::DeepEdges (dl_out2));
}
namespace

View File

@ -156,6 +156,7 @@ public:
virtual RegionDelegate *extended (coord_type ext_b, coord_type ext_e, coord_type ext_o, coord_type ext_i, bool join) const;
virtual EdgesDelegate *in (const Edges &, bool) const;
virtual std::pair<EdgesDelegate *, EdgesDelegate *> in_and_out (const Edges &) const;
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;

View File

@ -555,6 +555,12 @@ DeepRegion::merged_deep_layer () const
}
}
bool
DeepRegion::merged_polygons_available () const
{
return m_is_merged || m_merged_polygons_valid;
}
void
DeepRegion::ensure_merged_polygons_valid () const
{
@ -850,6 +856,10 @@ DeepRegion::is_box () const
size_t
DeepRegion::count () const
{
if (empty ()) {
return 0;
}
size_t n = 0;
const db::Layout &layout = deep_layer ().layout ();
@ -864,6 +874,10 @@ DeepRegion::count () const
size_t
DeepRegion::hier_count () const
{
if (empty ()) {
return 0;
}
size_t n = 0;
const db::Layout &layout = deep_layer ().layout ();
@ -877,6 +891,10 @@ DeepRegion::hier_count () const
DeepRegion::area_type
DeepRegion::area (const db::Box &box) const
{
if (empty ()) {
return 0;
}
if (box.empty ()) {
const db::DeepLayer &polygons = merged_deep_layer ();
@ -910,6 +928,10 @@ DeepRegion::area (const db::Box &box) const
DeepRegion::perimeter_type
DeepRegion::perimeter (const db::Box &box) const
{
if (empty ()) {
return 0;
}
if (box.empty ()) {
const db::DeepLayer &polygons = merged_deep_layer ();
@ -955,6 +977,10 @@ DeepRegion::to_string (size_t nmax) const
EdgePairsDelegate *
DeepRegion::grid_check (db::Coord gx, db::Coord gy) const
{
if (empty ()) {
return new EmptyEdgePairs ();
}
if (gx < 0 || gy < 0) {
throw tl::Exception (tl::to_string (tr ("Grid check requires a positive grid value")));
}
@ -1013,6 +1039,10 @@ DeepRegion::grid_check (db::Coord gx, db::Coord gy) const
EdgePairsDelegate *
DeepRegion::angle_check (double min, double max, bool inverse) const
{
if (empty ()) {
return new DeepEdgePairs (deep_layer ().derived ());
}
const db::DeepLayer &polygons = merged_deep_layer ();
db::Layout &layout = const_cast<db::Layout &> (polygons.layout ());
@ -1037,6 +1067,10 @@ DeepRegion::angle_check (double min, double max, bool inverse) const
RegionDelegate *
DeepRegion::snapped (db::Coord gx, db::Coord gy)
{
if (empty ()) {
return clone ();
}
if (gx < 0 || gy < 0) {
throw tl::Exception (tl::to_string (tr ("Snapping requires a positive grid value")));
}
@ -1047,7 +1081,7 @@ DeepRegion::snapped (db::Coord gx, db::Coord gy)
}
if (! gx) {
return this;
return clone ();
}
const db::DeepLayer &polygons = merged_deep_layer ();
@ -1169,7 +1203,11 @@ public:
EdgesDelegate *
DeepRegion::edges (const EdgeFilterBase *filter) const
{
if (! filter && merged_semantics ()) {
if (empty ()) {
return new db::DeepEdges (deep_layer ().derived ());
}
if (! filter && merged_semantics () && ! merged_polygons_available ()) {
// Hierarchical edge detector - no pre-merge required
@ -1251,6 +1289,10 @@ DeepRegion::edges (const EdgeFilterBase *filter) const
RegionDelegate *
DeepRegion::process_in_place (const PolygonProcessorBase &filter)
{
if (empty ()) {
return this;
}
// TODO: implement to be really in-place
return processed (filter);
}
@ -1258,24 +1300,40 @@ DeepRegion::process_in_place (const PolygonProcessorBase &filter)
EdgesDelegate *
DeepRegion::processed_to_edges (const PolygonToEdgeProcessorBase &filter) const
{
if (empty ()) {
return new db::DeepEdges (deep_layer ().derived ());
}
return shape_collection_processed_impl<db::Polygon, db::Edge, db::DeepEdges> (filter.requires_raw_input () ? deep_layer () : merged_deep_layer (), filter);
}
EdgePairsDelegate *
DeepRegion::processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &filter) const
{
if (empty ()) {
return new db::DeepEdgePairs (deep_layer ().derived ());
}
return shape_collection_processed_impl<db::Polygon, db::EdgePair, db::DeepEdgePairs> (filter.requires_raw_input () ? deep_layer () : merged_deep_layer (), filter);
}
RegionDelegate *
DeepRegion::processed (const PolygonProcessorBase &filter) const
{
if (empty ()) {
return clone ();
}
return shape_collection_processed_impl<db::Polygon, db::Polygon, db::DeepRegion> (filter.requires_raw_input () ? deep_layer () : merged_deep_layer (), filter);
}
RegionDelegate *
DeepRegion::filter_in_place (const PolygonFilterBase &filter)
{
if (empty ()) {
return this;
}
// TODO: implement to be really in-place
*this = *apply_filter (filter);
return this;
@ -1284,6 +1342,10 @@ DeepRegion::filter_in_place (const PolygonFilterBase &filter)
RegionDelegate *
DeepRegion::filtered (const PolygonFilterBase &filter) const
{
if (empty ()) {
return clone ();
}
return apply_filter (filter);
}
@ -1366,6 +1428,10 @@ DeepRegion::apply_filter (const PolygonFilterBase &filter) const
RegionDelegate *
DeepRegion::merged_in_place ()
{
if (empty ()) {
return this;
}
ensure_merged_polygons_valid ();
// NOTE: this makes both layers share the same resource
@ -1378,12 +1444,17 @@ DeepRegion::merged_in_place ()
RegionDelegate *
DeepRegion::merged_in_place (bool min_coherence, unsigned int min_wc)
{
// TODO: implement to be really in-place
return merged (min_coherence, min_wc);
}
RegionDelegate *
DeepRegion::merged () const
{
if (empty ()) {
return clone ();
}
ensure_merged_polygons_valid ();
db::Layout &layout = const_cast<db::Layout &> (m_merged_polygons.layout ());
@ -1402,6 +1473,10 @@ DeepRegion::merged () const
RegionDelegate *
DeepRegion::merged (bool min_coherence, unsigned int min_wc) const
{
if (empty ()) {
return clone ();
}
tl::SelfTimer timer (tl::verbosity () > base_verbosity (), "Ensure merged polygons");
db::Layout &layout = const_cast<db::Layout &> (deep_layer ().layout ());
@ -1550,13 +1625,6 @@ DeepRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const
return res.release ();
}
RegionDelegate *
DeepRegion::in (const Region &other, bool invert) const
{
// TODO: this can be optimized maybe ...
return db::AsIfFlatRegion::in (other, invert);
}
template <class TR, class Output>
static
Output *region_cop_impl (DeepRegion *region, db::CompoundRegionOperationNode &node)
@ -1643,6 +1711,12 @@ DeepRegion::cop_to_edges (db::CompoundRegionOperationNode &node)
EdgePairsDelegate *
DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, const RegionCheckOptions &options) const
{
if (empty ()) {
return new db::DeepEdgePairs (deep_layer ().derived ());
} else if (other && ! is_subject_regionptr (other) && other->empty () && ! options.negative) {
return new db::DeepEdgePairs (deep_layer ().derived ());
}
const db::DeepRegion *other_deep = 0;
unsigned int other_layer = 0;
bool other_is_merged = true;
@ -1706,6 +1780,10 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons
EdgePairsDelegate *
DeepRegion::run_single_polygon_check (db::edge_relation_type rel, db::Coord d, const RegionCheckOptions &options) const
{
if (empty ()) {
return new db::DeepEdgePairs (deep_layer ().derived ());
}
const db::DeepLayer &polygons = merged_deep_layer ();
EdgeRelationFilter check (rel, d, options.metrics);
@ -1796,11 +1874,82 @@ private:
}
std::pair<RegionDelegate *, RegionDelegate *>
DeepRegion::in_and_out_generic (const Region &other, InteractingOutputMode output_mode) const
{
if (output_mode == None) {
return std::pair<RegionDelegate *, RegionDelegate *> ((RegionDelegate *) 0, (RegionDelegate *) 0);
} else if (empty ()) {
if (output_mode == PositiveAndNegative) {
return std::make_pair (clone (), clone ());
} else {
return std::make_pair (clone (), (RegionDelegate *) 0);
}
} else if (other.empty ()) {
if (output_mode == PositiveAndNegative) {
return std::make_pair (new DeepRegion (deep_layer ().derived ()), clone ());
} else if (output_mode == Negative) {
return std::make_pair (clone (), (RegionDelegate *) 0);
} else {
return std::make_pair (new DeepRegion (deep_layer ().derived ()), (RegionDelegate *) 0);
}
}
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 &polygons = merged_deep_layer ();
const db::DeepLayer &other_polygons = other_deep->merged_deep_layer ();
db::ContainedLocalOperation op (output_mode);
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell (), polygons.breakout_cells (), other_polygons.breakout_cells ());
proc.set_description (progress_desc ());
proc.set_report_progress (report_progress ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (polygons.store ()->threads ());
InteractingResultHolder orh (output_mode, merged_semantics (), polygons);
proc.run (&op, polygons.layer (), other_polygons.layer (), orh.layers ());
return orh.result_pair ();
}
std::pair<RegionDelegate *, RegionDelegate *>
DeepRegion::selected_interacting_generic (const Region &other, int mode, bool touching, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const
{
if (output_mode == None) {
return std::pair<RegionDelegate *, RegionDelegate *> (0, 0);
return std::pair<RegionDelegate *, RegionDelegate *> ((RegionDelegate *) 0, (RegionDelegate *) 0);
} else if (empty ()) {
if (output_mode == PositiveAndNegative) {
return std::make_pair (clone (), clone ());
} else {
return std::make_pair (clone (), (RegionDelegate *) 0);
}
} else if (other.empty ()) {
if (mode > 0 /*outside*/) {
if (output_mode == PositiveAndNegative) {
return std::make_pair (clone (), new DeepRegion (deep_layer ().derived ()));
} else if (output_mode == Negative) {
return std::make_pair (new DeepRegion (deep_layer ().derived ()), (RegionDelegate *) 0);
} else {
return std::make_pair (clone (), (RegionDelegate *) 0);
}
} else {
if (output_mode == PositiveAndNegative) {
return std::make_pair (new DeepRegion (deep_layer ().derived ()), clone ());
} else if (output_mode == Negative) {
return std::make_pair (clone (), (RegionDelegate *) 0);
} else {
return std::make_pair (new DeepRegion (deep_layer ().derived ()), (RegionDelegate *) 0);
}
}
}
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
@ -1818,7 +1967,8 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
const db::DeepLayer &polygons = merged_deep_layer ();
// NOTE: on "inside" or with counting, the other polygons must be merged
const db::DeepLayer &other_polygons = (mode < 0 || counting) ? other_deep->merged_deep_layer () : other_deep->deep_layer ();
bool other_needs_merged = (mode < 0 || counting);
const db::DeepLayer &other_polygons = other_needs_merged ? other_deep->merged_deep_layer () : other_deep->deep_layer ();
db::InteractingLocalOperation op (mode, touching, output_mode, min_count, max_count, true);
@ -1832,7 +1982,7 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
proc.set_max_vertex_count (polygons.store ()->max_vertex_count ());
}
bool result_is_merged = (! split_after && ((mode < 0 && other.merged_semantics ()) || other.is_merged ()) && (merged_semantics () || is_merged ()));
bool result_is_merged = (! split_after && (merged_semantics () || is_merged ()));
InteractingResultHolder orh (output_mode, result_is_merged, polygons);
proc.run (&op, polygons.layer (), other_polygons.layer (), orh.layers ());
@ -1843,6 +1993,24 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
std::pair<RegionDelegate *, RegionDelegate *>
DeepRegion::selected_interacting_generic (const Edges &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const
{
if (output_mode == None) {
return std::pair<RegionDelegate *, RegionDelegate *> ((RegionDelegate *) 0, (RegionDelegate *) 0);
} else if (empty ()) {
if (output_mode == PositiveAndNegative) {
return std::make_pair (clone (), clone ());
} else {
return std::make_pair (clone (), (RegionDelegate *) 0);
}
} else if (other.empty ()) {
if (output_mode == PositiveAndNegative) {
return std::make_pair (new DeepRegion (deep_layer ().derived ()), clone ());
} else if (output_mode == Negative) {
return std::make_pair (clone (), (RegionDelegate *) 0);
} else {
return std::make_pair (new DeepRegion (deep_layer ().derived ()), (RegionDelegate *) 0);
}
}
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
// with these flag set to true, the resulting polygons are broken again.
@ -1870,7 +2038,7 @@ DeepRegion::selected_interacting_generic (const Edges &other, InteractingOutputM
proc.set_max_vertex_count (polygons.store ()->max_vertex_count ());
}
bool result_is_merged = (! split_after && other.is_merged () && (merged_semantics () || is_merged ()));
bool result_is_merged = (! split_after && (merged_semantics () || is_merged ()));
InteractingResultHolder orh (output_mode, result_is_merged, polygons);
proc.run (&op, polygons.layer (), counting ? other_deep->merged_deep_layer ().layer () : other_deep->deep_layer ().layer (), orh.layers ());
@ -1881,6 +2049,12 @@ DeepRegion::selected_interacting_generic (const Edges &other, InteractingOutputM
RegionDelegate *
DeepRegion::pull_generic (const Region &other, int mode, bool touching) const
{
if (empty ()) {
return clone ();
} else if (other.empty ()) {
return new DeepRegion (deep_layer ().derived ());
}
// with these flag set to true, the resulting polygons are broken again.
bool split_after = false;
@ -1913,15 +2087,17 @@ DeepRegion::pull_generic (const Region &other, int mode, bool touching) const
proc.run (&op, polygons.layer (), other_polygons.layer (), dl_out.layer ());
db::DeepRegion *res = new db::DeepRegion (dl_out);
if (! split_after && ((mode < 0 && merged_semantics ()) || is_merged ()) && (other.merged_semantics () || other.is_merged ())) {
res->set_is_merged (true);
}
res->set_is_merged (! split_after && (other.merged_semantics () || other.is_merged ()));
return res;
}
EdgesDelegate *
DeepRegion::pull_generic (const Edges &other) const
{
if (empty () || other.empty ()) {
return new DeepEdges (deep_layer ().derived ());
}
std::unique_ptr<db::DeepEdges> dr_holder;
const db::DeepEdges *other_deep = dynamic_cast<const db::DeepEdges *> (other.delegate ());
if (! other_deep) {
@ -1953,6 +2129,10 @@ DeepRegion::pull_generic (const Edges &other) const
TextsDelegate *
DeepRegion::pull_generic (const Texts &other) const
{
if (empty () || other.empty ()) {
return new DeepTexts (deep_layer ().derived ());
}
std::unique_ptr<db::DeepTexts> dr_holder;
const db::DeepTexts *other_deep = dynamic_cast<const db::DeepTexts *> (other.delegate ());
if (! other_deep) {
@ -1976,15 +2156,31 @@ DeepRegion::pull_generic (const Texts &other) const
proc.set_threads (polygons.store ()->threads ());
proc.run (&op, polygons.layer (), other_texts.layer (), dl_out.layer ());
db::DeepTexts *res = new db::DeepTexts (dl_out);
res->set_is_merged (is_merged ());
return res;
return new db::DeepTexts (dl_out);
}
std::pair<RegionDelegate *, RegionDelegate *>
DeepRegion::selected_interacting_generic (const Texts &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const
{
if (output_mode == None) {
return std::pair<RegionDelegate *, RegionDelegate *> ((RegionDelegate *) 0, (RegionDelegate *) 0);
} else if (empty ()) {
if (output_mode == PositiveAndNegative) {
return std::make_pair (clone (), clone ());
} else {
return std::make_pair (clone (), (RegionDelegate *) 0);
}
} else if (other.empty ()) {
if (output_mode == PositiveAndNegative) {
return std::make_pair (new DeepRegion (deep_layer ().derived ()), clone ());
} else if (output_mode == Negative) {
return std::make_pair (clone (), (RegionDelegate *) 0);
} else {
return std::make_pair (new DeepRegion (deep_layer ().derived ()), (RegionDelegate *) 0);
}
}
// with these flag set to true, the resulting polygons are broken again.
bool split_after = false;

View File

@ -133,8 +133,6 @@ public:
virtual RegionDelegate *sized (coord_type d, unsigned int mode) const;
virtual RegionDelegate *sized (coord_type dx, coord_type dy, unsigned int mode) const;
virtual RegionDelegate *in (const Region &other, bool invert) const;
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
virtual DeepShapeCollectionDelegateBase *deep ()
@ -144,6 +142,7 @@ public:
void set_is_merged (bool f);
bool merged_polygons_available () const;
const DeepLayer &merged_deep_layer () const;
protected:
@ -158,6 +157,7 @@ protected:
virtual RegionDelegate *pull_generic (const Region &other, int mode, bool touching) const;
virtual EdgesDelegate *pull_generic (const Edges &other) const;
virtual TextsDelegate *pull_generic (const Texts &other) const;
virtual std::pair<RegionDelegate *, RegionDelegate *> in_and_out_generic (const Region &other, InteractingOutputMode output_mode) const;
private:
friend class DeepEdges;

View File

@ -1390,6 +1390,19 @@ public:
return Edges (mp_delegate->in (other, invert));
}
/**
* @brief Returns all edges which are in the other edge set and which are not.
*
* This method is equivalent to calling in with invert = false and true, but more efficient.
*
* Merged semantics applies.
*/
std::pair<Edges, Edges> in_and_out (const Edges &other) const
{
std::pair<db::EdgesDelegate *, db::EdgesDelegate *> p = mp_delegate->in_and_out (other);
return std::pair<Edges, Edges> (Edges (p.first), Edges (p.second));
}
/**
* @brief Returns the nth edge
*

View File

@ -333,6 +333,7 @@ public:
virtual std::pair<EdgesDelegate *, EdgesDelegate *> selected_inside_pair (const Edges &other) const = 0;
virtual EdgesDelegate *in (const Edges &other, bool invert) const = 0;
virtual std::pair<EdgesDelegate *, EdgesDelegate *> in_and_out (const Edges &) const = 0;
virtual const db::Edge *nth (size_t n) const = 0;
virtual bool has_valid_edges () const = 0;

View File

@ -115,6 +115,7 @@ public:
virtual std::pair<EdgesDelegate *, EdgesDelegate *> selected_inside_pair (const Edges &) const { return std::make_pair (new EmptyEdges (), new EmptyEdges ()); }
virtual EdgesDelegate *in (const Edges &, bool) const { return new EmptyEdges (); }
virtual std::pair<EdgesDelegate *, EdgesDelegate *> in_and_out (const Edges &) const { return std::make_pair (new EmptyEdges (), new EmptyEdges ()); }
virtual const db::Edge *nth (size_t) const { tl_assert (false); }
virtual bool has_valid_edges () const { return true; }

View File

@ -133,6 +133,7 @@ public:
virtual TextsDelegate *pull_interacting (const Texts &) const { return new EmptyTexts (); }
virtual RegionDelegate *pull_overlapping (const Region &) const { return new EmptyRegion (); }
virtual RegionDelegate *in (const Region &, bool) const { return new EmptyRegion (); }
virtual std::pair<RegionDelegate *, RegionDelegate *> in_and_out (const Region &) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
virtual bool has_valid_polygons () const { return true; }
virtual bool has_valid_merged_polygons () const { return true; }

View File

@ -1602,6 +1602,19 @@ public:
return Region (mp_delegate->in (other, invert));
}
/**
* @brief Returns all polygons which are in the other region plus the ones which are not
*
* This method is similar to calling in with inverse = false and true, but more efficient.
*
* Merged semantics applies.
*/
std::pair<Region, Region> in_and_out (const Region &other) const
{
std::pair<db::RegionDelegate *, db::RegionDelegate *> p = mp_delegate->in_and_out (other);
return std::pair<Region, Region> (Region (p.first), Region (p.second));
}
/**
* @brief Round corners (in-place)
*

View File

@ -308,6 +308,7 @@ public:
virtual RegionDelegate *pull_overlapping (const Region &other) const = 0;
virtual TextsDelegate *pull_interacting (const Texts &other) const = 0;
virtual RegionDelegate *in (const Region &other, bool invert) const = 0;
virtual std::pair<RegionDelegate *, RegionDelegate *> in_and_out (const Region &other) const = 0;
virtual const db::Polygon *nth (size_t n) const = 0;
virtual bool has_valid_polygons () const = 0;

View File

@ -915,6 +915,81 @@ template class DB_PUBLIC interacting_local_operation<db::Polygon, db::Polygon, d
// ---------------------------------------------------------------------------------------------------------------
template <class TS, class TI, class TR>
contained_local_operation<TS, TI, TR>::contained_local_operation (InteractingOutputMode output_mode)
: m_output_mode (output_mode)
{
// .. nothing yet ..
}
template <class TS, class TI, class TR>
db::Coord contained_local_operation<TS, TI, TR>::dist () const
{
return 1; // touching included for degenerated polygons and edges
}
template <class TS, class TI, class TR>
void contained_local_operation<TS, TI, TR>::do_compute_local (db::Layout * /*layout*/, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
{
if (m_output_mode == None) {
return;
} else if (m_output_mode == Positive || m_output_mode == Negative) {
tl_assert (results.size () == 1);
} else {
tl_assert (results.size () == 2);
}
std::set<TI> others;
for (typename shape_interactions<TS, TI>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
for (typename shape_interactions<TS, TI>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
others.insert (interactions.intruder_shape (*j).second);
}
}
for (typename shape_interactions<TS, TI>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
const TS &subject = interactions.subject_shape (i->first);
if (others.find (subject) != others.end ()) {
if (m_output_mode == Positive || m_output_mode == PositiveAndNegative) {
results [0].insert (subject);
}
} else {
if (m_output_mode == Negative) {
results [0].insert (subject);
} else if (m_output_mode == PositiveAndNegative) {
results [1].insert (subject);
}
}
}
}
template <class TS, class TI, class TR>
OnEmptyIntruderHint
contained_local_operation<TS, TI, TR>::on_empty_intruder_hint () const
{
if (m_output_mode == Positive) {
return OnEmptyIntruderHint::Drop;
} else if (m_output_mode == Negative) {
return OnEmptyIntruderHint::Copy;
} else if (m_output_mode == PositiveAndNegative) {
return OnEmptyIntruderHint::CopyToSecond;
} else {
return OnEmptyIntruderHint::Ignore;
}
}
template <class TS, class TI, class TR>
std::string contained_local_operation<TS, TI, TR>::description () const
{
return tl::to_string (tr ("Select polygons contained in other region"));
}
// explicit instantiations
template class DB_PUBLIC contained_local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC contained_local_operation<db::Polygon, db::Polygon, db::Polygon>;
template class DB_PUBLIC contained_local_operation<db::Edge, db::Edge, db::Edge>;
// ---------------------------------------------------------------------------------------------------------------
template <class TS, class TI, class TR>
pull_local_operation<TS, TI, TR>::pull_local_operation (int mode, bool touching)
: m_mode (mode), m_touching (touching)

View File

@ -351,6 +351,26 @@ public:
typedef pull_with_text_local_operation<db::PolygonRef, db::TextRef, db::TextRef> PullWithTextLocalOperation;
template <class TS, class TI, class TR>
class contained_local_operation
: public local_operation<TS, TI, TR>
{
public:
contained_local_operation (InteractingOutputMode output_mode);
virtual db::Coord dist () const;
virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const;
virtual OnEmptyIntruderHint on_empty_intruder_hint () const;
virtual std::string description () const;
private:
InteractingOutputMode m_output_mode;
};
typedef contained_local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef> ContainedLocalOperation;
// the implementation is type-agnostic and can be used for edges too
typedef contained_local_operation<db::Edge, db::Edge, db::Edge> ContainedEdgesLocalOperation;
} // namespace db
#endif

View File

@ -35,7 +35,16 @@
namespace gsi
{
static db::Edges *new_v ()
static inline std::vector<db::Edges> as_2edges_vector (const std::pair<db::Edges, db::Edges> &rp)
{
std::vector<db::Edges> res;
res.reserve (2);
res.push_back (db::Edges (const_cast<db::Edges &> (rp.first).take_delegate ()));
res.push_back (db::Edges (const_cast<db::Edges &> (rp.second).take_delegate ()));
return res;
}
static db::Edges *new_v ()
{
return new db::Edges ();
}
@ -166,6 +175,11 @@ static db::Edges not_in (const db::Edges *r, const db::Edges &other)
return r->in (other, true);
}
static std::vector<db::Edges> in_and_out (const db::Edges *r, const db::Edges &other)
{
return as_2edges_vector (r->in_and_out (other));
}
static db::Edges &move_p (db::Edges *r, const db::Vector &p)
{
r->transform (db::Disp (p));
@ -377,15 +391,6 @@ static size_t id (const db::Edges *e)
return tl::id_of (e->delegate ());
}
static inline std::vector<db::Edges> as_2edges_vector (const std::pair<db::Edges, db::Edges> &rp)
{
std::vector<db::Edges> res;
res.reserve (2);
res.push_back (db::Edges (const_cast<db::Edges &> (rp.first).take_delegate ()));
res.push_back (db::Edges (const_cast<db::Edges &> (rp.second).take_delegate ()));
return res;
}
static std::vector<db::Edges> andnot_with_edges (const db::Edges *r, const db::Edges &other)
{
return as_2edges_vector (r->andnot (other));
@ -1633,16 +1638,24 @@ Class<db::Edges> decl_Edges (decl_dbShapeCollection, "db", "Edges",
"\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
) +
method_ext ("members_of|#in", &in, gsi::arg ("other"),
method_ext ("members_of|in", &in, gsi::arg ("other"),
"@brief Returns all edges which are members of the other edge collection\n"
"This method returns all edges in self which can be found in the other edge collection as well with exactly the same "
"geometry."
) +
method_ext ("not_members_of|#not_in", &not_in, gsi::arg ("other"),
method_ext ("not_members_of|not_in", &not_in, gsi::arg ("other"),
"@brief Returns all edges which are not members of the other edge collection\n"
"This method returns all edges in self which can not be found in the other edge collection with exactly the same "
"geometry."
) +
method_ext ("in_and_out", &in_and_out, gsi::arg ("other"),
"@brief Returns all polygons which are members and not members of the other region\n"
"This method is equivalent to calling \\members_of and \\not_members_of, but delivers both results at the same time and "
"is more efficient than two separate calls. "
"The first element returned is the \\members_of part, the second is the \\not_members_of part.\n"
"\n"
"This method has been introduced in version 0.28.\n"
) +
method_ext ("is_deep?", &is_deep,
"@brief Returns true if the edge collection is a deep (hierarchical) one\n"
"\n"

View File

@ -44,6 +44,15 @@
namespace gsi
{
static inline std::vector<db::Region> as_2region_vector (const std::pair<db::Region, db::Region> &rp)
{
std::vector<db::Region> res;
res.reserve (2);
res.push_back (db::Region (const_cast<db::Region &> (rp.first).take_delegate ()));
res.push_back (db::Region (const_cast<db::Region &> (rp.second).take_delegate ()));
return res;
}
static db::Region *new_v ()
{
return new db::Region ();
@ -430,6 +439,11 @@ static db::Region not_in (const db::Region *r, const db::Region &other)
return r->in (other, true);
}
static std::vector<db::Region> in_and_out (const db::Region *r, const db::Region &other)
{
return as_2region_vector (r->in_and_out (other));
}
static db::Region rectangles (const db::Region *r)
{
db::RectangleFilter f (false, false);
@ -605,15 +619,6 @@ static db::EdgePairs separation2 (const db::Region *r, const db::Region &other,
);
}
static inline std::vector<db::Region> as_2region_vector (const std::pair<db::Region, db::Region> &rp)
{
std::vector<db::Region> res;
res.reserve (2);
res.push_back (db::Region (const_cast<db::Region &> (rp.first).take_delegate ()));
res.push_back (db::Region (const_cast<db::Region &> (rp.second).take_delegate ()));
return res;
}
static std::vector<db::Region> andnot (const db::Region *r, const db::Region &other)
{
return as_2region_vector (r->andnot (other));
@ -2186,16 +2191,24 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"are taken from a hole-less representation (i.e. GDS2 file). Use explicit merge (\\merge method) "
"in order to merge the polygons and detect holes.\n"
) +
method_ext ("members_of|#in", &in, gsi::arg ("other"),
method_ext ("members_of|in", &in, gsi::arg ("other"),
"@brief Returns all polygons which are members of the other region\n"
"This method returns all polygons in self which can be found in the other region as well with exactly the same "
"geometry."
) +
method_ext ("not_members_of|#not_in", &not_in, gsi::arg ("other"),
method_ext ("not_members_of|not_in", &not_in, gsi::arg ("other"),
"@brief Returns all polygons which are not members of the other region\n"
"This method returns all polygons in self which can not be found in the other region with exactly the same "
"geometry."
) +
method_ext ("in_and_out", &in_and_out, gsi::arg ("other"),
"@brief Returns all polygons which are members and not members of the other region\n"
"This method is equivalent to calling \\members_of and \\not_members_of, but delivers both results at the same time and "
"is more efficient than two separate calls. "
"The first element returned is the \\members_of part, the second is the \\not_members_of part.\n"
"\n"
"This method has been introduced in version 0.28.\n"
) +
method_ext ("rectangles", &rectangles,
"@brief Returns all polygons which are rectangles\n"
"This method returns all polygons in self which are rectangles."

View File

@ -1182,3 +1182,113 @@ TEST(19_AndNotWithEdges)
EXPECT_EQ (db::compare (eflat.andnot (ee).second, "(1500,2000;1500,2100);(1100,0;1100,1000);(0,0;0,1000);(100,0;100,3000);(1800,2500;1800,3500);(-1500,0;-1500,1000);(1700,1500;1600,2500)"), true);
}
TEST(20_in)
{
db::Layout ly;
{
std::string fn (tl::testdata ());
fn += "/algo/deep_region_l31.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::cell_index_type top_cell_index = *ly.begin_top_down ();
db::Cell &top_cell = ly.cell (top_cell_index);
db::DeepShapeStore dss;
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0)); // empty
db::Edges e1 = db::Edges ((db::Region (db::RecursiveShapeIterator (ly, top_cell, l1), dss)).edges ());
db::Edges e2 = db::Edges ((db::Region (db::RecursiveShapeIterator (ly, top_cell, l2), dss)).edges ());
db::Edges e3 = db::Edges ((db::Region (db::RecursiveShapeIterator (ly, top_cell, l3), dss)).edges ());
db::Edges e1r = e1;
e1r.set_merged_semantics (false);
db::Edges e2r = e2;
e2r.set_merged_semantics (false);
db::Layout target;
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (1, 0)), e1);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (2, 0)), e2);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), e2.in (e1));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), e2.in (e1, true));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), e2.in (e3));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), e2.in (e3, true));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (14, 0)), e3.in (e1));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (15, 0)), e3.in (e1, true));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), e2r.in (e1));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), e2r.in (e1, true));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (30, 0)), e2.in (e1r));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (31, 0)), e2.in (e1r, true));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (40, 0)), e2r.in (e1r));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (41, 0)), e2r.in (e1r, true));
CHECKPOINT();
db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_edges_au20.gds");
}
TEST(20_in_and_out)
{
db::Layout ly;
{
std::string fn (tl::testdata ());
fn += "/algo/deep_region_l31.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::cell_index_type top_cell_index = *ly.begin_top_down ();
db::Cell &top_cell = ly.cell (top_cell_index);
db::DeepShapeStore dss;
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0)); // empty
db::Edges e1 = db::Edges ((db::Region (db::RecursiveShapeIterator (ly, top_cell, l1), dss)).edges ());
db::Edges e2 = db::Edges ((db::Region (db::RecursiveShapeIterator (ly, top_cell, l2), dss)).edges ());
db::Edges e3 = db::Edges ((db::Region (db::RecursiveShapeIterator (ly, top_cell, l3), dss)).edges ());
db::Edges e1r = e1;
e1r.set_merged_semantics (false);
db::Edges e2r = e2;
e2r.set_merged_semantics (false);
db::Layout target;
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (1, 0)), e1);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (2, 0)), e2);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), e2.in_and_out (e1).first);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), e2.in_and_out (e1).second);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), e2.in_and_out (e3).first);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), e2.in_and_out (e3).second);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (14, 0)), e3.in_and_out (e1).first);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (15, 0)), e3.in_and_out (e1).second);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), e2r.in_and_out (e1).first);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), e2r.in_and_out (e1).second);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (30, 0)), e2.in_and_out (e1r).first);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (31, 0)), e2.in_and_out (e1r).second);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (40, 0)), e2r.in_and_out (e1r).first);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (41, 0)), e2r.in_and_out (e1r).second);
CHECKPOINT();
db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_edges_au20.gds");
}

View File

@ -880,8 +880,6 @@ TEST(14_Interacting)
db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss);
db::Region r6 (db::RecursiveShapeIterator (ly, top_cell, l6), dss);
db::Region r1f (db::RecursiveShapeIterator (ly, top_cell, l1));
db::Region r2f (db::RecursiveShapeIterator (ly, top_cell, l2));
db::Region r6f (db::RecursiveShapeIterator (ly, top_cell, l6));
db::Region r1r = r1;
r1r.set_merged_semantics (false);
db::Region r2r = r2;
@ -889,6 +887,11 @@ TEST(14_Interacting)
db::Region r6r = r6;
r6r.set_merged_semantics (false);
db::Edges r1e = r1.edges ();
db::Edges r1ef = r1f.edges ();
db::Edges r1er = r1r.edges ();
r1er.set_merged_semantics (false);
{
db::Layout target;
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
@ -947,22 +950,18 @@ TEST(14_Interacting)
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (66, 0)), r6r.selected_overlapping (r1r));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (67, 0)), r6r.selected_not_overlapping (r1r));
EXPECT_EQ (r2.selected_interacting (r1).is_merged (), false);
EXPECT_EQ (r2.selected_interacting (r1.merged ()).is_merged (), true);
EXPECT_EQ (r2.selected_inside (r1).is_merged (), true);
EXPECT_EQ (r2.selected_interacting (r1).is_merged (), true);
EXPECT_EQ (r2r.selected_interacting (r1).is_merged (), false);
EXPECT_EQ (r2.selected_interacting (r1r).is_merged (), false);
EXPECT_EQ (r2r.selected_interacting (r1r).is_merged (), false);
EXPECT_EQ (r2r.selected_interacting (r1.merged ()).is_merged (), false);
EXPECT_EQ (r2.selected_interacting (r1r).is_merged (), true);
EXPECT_EQ (r2.selected_inside (r1).is_merged (), true);
EXPECT_EQ (r2r.selected_inside (r1).is_merged (), false);
EXPECT_EQ (r2.selected_inside (r1).is_merged (), true);
CHECKPOINT();
db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_region_au14a.gds");
}
db::Edges r1e = r1.edges ();
db::Edges r1ef = r1f.edges ();
db::Edges r1er = r1r.edges ();
r1er.set_merged_semantics (false);
{
db::Layout target;
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
@ -976,8 +975,8 @@ TEST(14_Interacting)
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (32, 0)), r6r.selected_interacting (r1er));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (33, 0)), r6r.selected_not_interacting (r1er));
EXPECT_EQ (r6.selected_interacting (r1e).is_merged (), false);
EXPECT_EQ (r6.selected_interacting (r1er).is_merged (), false);
EXPECT_EQ (r6.selected_interacting (r1e).is_merged (), true);
EXPECT_EQ (r6.selected_interacting (r1er).is_merged (), true);
EXPECT_EQ (r6r.selected_interacting (r1e).is_merged (), false);
EXPECT_EQ (r6r.selected_interacting (r1er).is_merged (), false);
@ -1470,6 +1469,16 @@ TEST(25_Pull)
db::Region r6r = r6;
r6r.set_merged_semantics (false);
db::Edges r1e = r1.edges ();
db::Edges r1ef = r1f.edges ();
db::Edges r1er = r1r.edges ();
r1er.set_merged_semantics (false);
db::Edges r6e = r6.edges ();
db::Edges r6ef = r6f.edges ();
db::Edges r6er = r6r.edges ();
r6er.set_merged_semantics (false);
{
db::Layout target;
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
@ -1499,8 +1508,8 @@ TEST(25_Pull)
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (62, 0)), r2r.pull_overlapping (r6r));
EXPECT_EQ (r2.pull_inside (r6).is_merged (), true);
EXPECT_EQ (r2.pull_interacting (r6).is_merged (), false);
EXPECT_EQ (r2r.pull_interacting (r6).is_merged (), false);
EXPECT_EQ (r2.pull_interacting (r6).is_merged (), true);
EXPECT_EQ (r2r.pull_interacting (r6).is_merged (), true);
EXPECT_EQ (r2.pull_interacting (r6r).is_merged (), false);
EXPECT_EQ (r2r.pull_interacting (r6r).is_merged (), false);
@ -1508,16 +1517,6 @@ TEST(25_Pull)
db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_region_au25a.gds");
}
db::Edges r1e = r1.edges ();
db::Edges r1ef = r1f.edges ();
db::Edges r1er = r1r.edges ();
r1er.set_merged_semantics (false);
db::Edges r6e = r6.edges ();
db::Edges r6ef = r6f.edges ();
db::Edges r6er = r6r.edges ();
r6er.set_merged_semantics (false);
{
db::Layout target;
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
@ -1800,7 +1799,7 @@ TEST(30a_interact_with_count_region)
EXPECT_EQ (r.selected_interacting (rr2, 2, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_interacting (rr2, 4, 5).to_string (), "");
EXPECT_EQ (r.selected_not_interacting (empty).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_not_interacting (empty).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_not_interacting (rr).to_string (), "");
EXPECT_EQ (r.selected_not_interacting (rr, 0, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_not_interacting (rr, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
@ -1891,7 +1890,7 @@ TEST(30b_interact_with_count_edge)
EXPECT_EQ (r.selected_interacting (rr2, 2, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_interacting (rr2, 4, 5).to_string (), "");
EXPECT_EQ (r.selected_not_interacting (empty).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_not_interacting (empty).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_not_interacting (rr).to_string (), "");
EXPECT_EQ (r.selected_not_interacting (rr, 0, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_not_interacting (rr, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
@ -1981,7 +1980,7 @@ TEST(30c_interact_with_count_text)
EXPECT_EQ (r.selected_interacting (rr2, 2, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_interacting (rr2, 4, 5).to_string (), "");
EXPECT_EQ (r.selected_not_interacting (empty).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_not_interacting (empty).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_not_interacting (rr).to_string (), "");
EXPECT_EQ (r.selected_not_interacting (rr, 0, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
EXPECT_EQ (r.selected_not_interacting (rr, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
@ -2018,6 +2017,115 @@ TEST(30c_interact_with_count_text)
EXPECT_EQ (r.selected_not_interacting (rr, 3, 4).to_string (), "(0,0;0,200;100,200;100,0)");
}
TEST(31_in)
{
db::Layout ly;
{
std::string fn (tl::testdata ());
fn += "/algo/deep_region_l31.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::cell_index_type top_cell_index = *ly.begin_top_down ();
db::Cell &top_cell = ly.cell (top_cell_index);
db::DeepShapeStore dss;
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0)); // empty
db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1), dss);
db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss);
db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss);
db::Region r1r = r1;
r1r.set_merged_semantics (false);
db::Region r2r = r2;
r2r.set_merged_semantics (false);
db::Layout target;
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (1, 0)), r1);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (2, 0)), r2);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r2.in (r1));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r2.in (r1, true));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r2.in (r3, false));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), r2.in (r3, true));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (14, 0)), r3.in (r1, false));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (15, 0)), r3.in (r1, true));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r2r.in (r1));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), r2r.in (r1, true));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (30, 0)), r2.in (r1r));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (31, 0)), r2.in (r1r, true));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (40, 0)), r2r.in (r1r));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (41, 0)), r2r.in (r1r, true));
CHECKPOINT();
db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_region_au31.gds");
}
TEST(31_in_and_out)
{
db::Layout ly;
{
std::string fn (tl::testdata ());
fn += "/algo/deep_region_l31.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::cell_index_type top_cell_index = *ly.begin_top_down ();
db::Cell &top_cell = ly.cell (top_cell_index);
db::DeepShapeStore dss;
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0)); // empty
db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1), dss);
db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss);
db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss);
db::Region r1r = r1;
r1r.set_merged_semantics (false);
db::Region r2r = r2;
r2r.set_merged_semantics (false);
db::Layout target;
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (1, 0)), r1);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (2, 0)), r2);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r2.in_and_out (r1).first);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r2.in_and_out (r1).second);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r2.in_and_out (r3).first);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), r2.in_and_out (r3).second);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (14, 0)), r3.in_and_out (r1).first);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (15, 0)), r3.in_and_out (r1).second);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r2r.in_and_out (r1).first);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), r2r.in_and_out (r1).second);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (30, 0)), r2.in_and_out (r1r).first);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (31, 0)), r2.in_and_out (r1r).second);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (40, 0)), r2r.in_and_out (r1r).first);
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (41, 0)), r2r.in_and_out (r1r).second);
CHECKPOINT();
db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_region_au31.gds");
}
TEST(100_Integration)
{
db::Layout ly;

View File

@ -1121,6 +1121,42 @@ TEST(27)
EXPECT_EQ (db::compare (e.selected_outside_differential (ee).second, "(1100,-1000;1100,2000);(1200,-1000;1200,0);(1300,-800;1300,-200);(1400,1000;1400,1100);(1500,1000;1500,2100);(1600,-800;1600,-200);(1900,1000;1900,2000)"), true);
}
// Edges::in and Edges:in_and_out
TEST(28)
{
db::Edges e;
e.insert (db::Edge (0, 0, 0, 1000));
e.insert (db::Edge (0, 1000, 0, 2000));
e.insert (db::Edge (100, 0, 100, 1000));
db::Edges ee;
ee.insert (db::Edge (0, 0, 0, 2000));
ee.insert (db::Edge (100, 1000, 0, 2000));
ee.insert (db::Edge (100, 0, 100, 1000));
EXPECT_EQ (db::compare (e.in (db::Edges ()), ""), true);
EXPECT_EQ (db::compare (e.in (db::Edges (), true), "(0,0;0,1000);(0,1000;0,2000);(100,0;100,1000)"), true);
EXPECT_EQ (db::compare (e.in_and_out (db::Edges ()).first, ""), true);
EXPECT_EQ (db::compare (e.in_and_out (db::Edges ()).second, "(0,0;0,1000);(0,1000;0,2000);(100,0;100,1000)"), true);
EXPECT_EQ (db::compare (db::Edges ().in (ee), ""), true);
EXPECT_EQ (db::compare (db::Edges ().in (ee, true), ""), true);
EXPECT_EQ (db::compare (db::Edges ().in_and_out (ee).first, ""), true);
EXPECT_EQ (db::compare (db::Edges ().in_and_out (ee).second, ""), true);
EXPECT_EQ (db::compare (e.in (ee), "(0,0;0,2000);(100,0;100,1000)"), true);
EXPECT_EQ (db::compare (e.in (ee, true), ""), true);
EXPECT_EQ (db::compare (e.in_and_out (ee).first, "(0,0;0,2000);(100,0;100,1000)"), true);
EXPECT_EQ (db::compare (e.in_and_out (ee).second, ""), true);
EXPECT_EQ (db::compare (ee.in (e, true), "(100,1000;0,2000)"), true);
EXPECT_EQ (db::compare (ee.in_and_out (e).second, "(100,1000;0,2000)"), true);
e.set_merged_semantics (false);
ee.set_merged_semantics (false);
EXPECT_EQ (db::compare (e.in (ee), "(100,0;100,1000)"), true);
EXPECT_EQ (db::compare (e.in (ee, true), "(0,0;0,1000);(0,1000;0,2000)"), true);
EXPECT_EQ (db::compare (ee.in (e, true), "(0,0;0,2000);(100,1000;0,2000)"), true);
}
// GitHub issue #72 (Edges/Region NOT issue)
TEST(100)
{

View File

@ -1095,15 +1095,25 @@ TEST(19)
r2.insert (db::Box (db::Point (0, 0), db::Point (20, 30)));
EXPECT_EQ (r1.in (r2, false).to_string (), "(0,0;0,30;20,30;20,0)");
EXPECT_EQ (r1.in_and_out (r2).first.to_string (), "(0,0;0,30;20,30;20,0)");
EXPECT_EQ (r1.in (r2, true).to_string (), "");
EXPECT_EQ (r1.in (r1, false).to_string (), "(0,0;0,30;20,30;20,0)");
EXPECT_EQ (r1.in (r1, true).to_string (), "");
EXPECT_EQ (r1.in_and_out (r2).second.to_string (), "");
EXPECT_EQ (r2.in (r1, true).to_string (), "");
r1.set_merged_semantics (false);
r2.set_merged_semantics (false);
EXPECT_EQ (db::compare (r1.in (r2, false), "(0,0;0,20;20,20;20,0);(0,0;0,30;20,30;20,0)"), true);
EXPECT_EQ (db::compare (r1.in_and_out (r2).first, "(0,0;0,20;20,20;20,0);(0,0;0,30;20,30;20,0)"), true);
EXPECT_EQ (r1.in (r2, true).to_string (), "(0,0;0,20;10,20;10,0)");
EXPECT_EQ (r1.in_and_out (r2).second.to_string (), "(0,0;0,20;10,20;10,0)");
EXPECT_EQ (r2.in (r1, true).to_string (), "(0,0;0,10;20,10;20,0)");
EXPECT_EQ (r1.in (db::Region (), false).to_string (), "");
EXPECT_EQ (db::compare (r1.in (db::Region (), true), "(0,0;0,20;10,20;10,0);(0,0;0,20;20,20;20,0);(0,0;0,30;20,30;20,0)"), true);
EXPECT_EQ (db::Region ().in (r1, false).to_string (), "");
EXPECT_EQ (db::Region ().in (r1, true).to_string (), "");
}
TEST(20)

View File

@ -1342,6 +1342,44 @@ The following image shows the effect of the "in" method (input1: red, input2: bl
</tr>
</table>
</p>
<a name="in_and_out"/><h2>"in_and_out" - Selects shapes or regions of self which are and which are not contained in the other layer</h2>
<keyword name="in_and_out"/>
<p>Usage:</p>
<ul>
<li><tt>(in, not_in) = layer.in_and_out(other)</tt></li>
</ul>
<p>
This method is equivalent to calling <a href="#in">in</a> and <a href="#not_in">not_in</a>, but more
efficient as it delivers both results in a single call.
</p><p>
This method is available for polygon, text and edge layers. Edges 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.
</p><p>
The following image shows the effect of the "interacting" method (input1: red, input2: blue):
</p><p>
<table>
<tr>
<td><img src="/images/drc_interacting.png"/></td>
</tr>
</table>
</p><p>
If a single count is given, shapes from self are selected only if they do interact at least with the given
number of (different) shapes from the other layer. If a min and max count is given, shapes from
self are selected only if they interact with min_count or more, but a maximum of max_count different shapes
from the other layer. Two polygons overlapping or touching at two locations are counted as single interactions.
</p><p>
<table>
<tr>
<td><img src="/images/drc_interacting2.png"/></td>
<td><img src="/images/drc_interacting3.png"/></td>
</tr>
<tr>
<td><img src="/images/drc_interacting4.png"/></td>
<td><img src="/images/drc_interacting5.png"/></td>
</tr>
</table>
</p>
<a name="insert"/><h2>"insert" - Inserts one or many objects into the layer</h2>
<keyword name="insert"/>
<p>Usage:</p>
@ -1448,50 +1486,6 @@ method computing both inside and outside part in a single call.
</tr>
</table>
</p>
<a name="interacting"/><h2>"interacting" - Selects shapes or regions of self which touch or overlap shapes from the other region</h2>
<keyword name="interacting"/>
<p>Usage:</p>
<ul>
<li><tt>layer.interacting(other)</tt></li>
<li><tt>layer.interacting(other, min_count)</tt></li>
<li><tt>layer.interacting(other, min_count, max_count)</tt></li>
<li><tt>layer.interacting(other, min_count .. max_count)</tt></li>
</ul>
<p>
This method selects all shapes or regions from self which touch or overlap shapes from the other
region. Unless self is in raw mode (see <a href="#raw">raw</a>), coherent regions are selected from self,
otherwise individual shapes are selected.
It returns a new layer containing the selected shapes. A version which modifies self
is <a href="#select_interacting">select_interacting</a>.
</p><p>
This method is available for polygon, text and edge layers. Edges 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.
</p><p>
The following image shows the effect of the "interacting" method (input1: red, input2: blue):
</p><p>
<table>
<tr>
<td><img src="/images/drc_interacting.png"/></td>
</tr>
</table>
</p><p>
If a single count is given, shapes from self are selected only if they do interact at least with the given
number of (different) shapes from the other layer. If a min and max count is given, shapes from
self are selected only if they interact with min_count or more, but a maximum of max_count different shapes
from the other layer. Two polygons overlapping or touching at two locations are counted as single interactions.
</p><p>
<table>
<tr>
<td><img src="/images/drc_interacting2.png"/></td>
<td><img src="/images/drc_interacting3.png"/></td>
</tr>
<tr>
<td><img src="/images/drc_interacting4.png"/></td>
<td><img src="/images/drc_interacting5.png"/></td>
</tr>
</table>
</p>
<a name="intersections"/><h2>"intersections" - Returns the intersection points of intersecting edge segments for two edge collections</h2>
<keyword name="intersections"/>
<p>Usage:</p>

View File

@ -2442,6 +2442,13 @@ CODE
# @/tr
# @/table
# %DRC%
# @name in_and_out
# @brief Selects shapes or regions of self which are and which are not contained in the other layer
# @synopsis (in, not_in) = layer.in_and_out(other)
# This method is equivalent to calling \in and \not_in, but more
# efficient as it delivers both results in a single call.
# %DRC%
# @name interacting
# @brief Selects shapes or regions of self which touch or overlap shapes from the other region
@ -2844,6 +2851,24 @@ CODE
CODE
end
%w(in_and_out).each do |f|
eval <<"CODE"
def #{f}(other, *args)
@engine._context("#{f}") do
requires_same_type(other)
requires_edges_or_region
res = @engine._tcmd_a2(self.data, 0, self.data.class, self.data.class, :#{f}, other.data)
[ DRCLayer::new(@engine, res[0]), DRCLayer::new(@engine, res[1]) ]
end
end
CODE
end
%w(split_interacting).each do |f|
eval <<"CODE"
def #{f}(other, *args)

View File

@ -1376,3 +1376,13 @@ TEST(57d_issue_1190)
{
run_test (_this, "57", true);
}
TEST(58_in_and_out)
{
run_test (_this, "58", false);
}
TEST(58d_in_and_out)
{
run_test (_this, "58", true);
}

View File

@ -422,7 +422,8 @@ void MacroCollection::scan ()
}
}
std::vector<std::string> dirs = tl::dir_entries (p, false /*with_files*/, true /*with_dirs*/, true /*without_dotfiles*/);
// NOTE: we add files to capture symlinks to directories
std::vector<std::string> dirs = tl::dir_entries (p, true /*with_files*/, true /*with_dirs*/, true /*without_dotfiles*/);
for (auto f = dirs.begin (); f != dirs.end (); ++f) {
std::string fp = tl::combine_path (p, *f);

BIN
testdata/algo/deep_edges_au20.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/deep_region_au31.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/deep_region_l31.gds vendored Normal file

Binary file not shown.

27
testdata/drc/drcSimpleTests_58.drc vendored Normal file
View File

@ -0,0 +1,27 @@
source $drc_test_source
target $drc_test_target
if $drc_test_deep
deep
end
l1 = input(1, 0)
l2 = input(2, 0)
l1.output(1, 0)
l2.output(2, 0)
l1e = l1.edges
l2e = l2.edges
l2.in(l1).output(10, 0)
l2.not_in(l1).output(11, 0)
l2.in_and_out(l1).first.output(12, 0)
l2.in_and_out(l1).last.output(13, 0)
l2e.in(l1e).output(20, 0)
l2e.not_in(l1e).output(21, 0)
l2e.in_and_out(l1e).first.output(22, 0)
l2e.in_and_out(l1e).last.output(23, 0)

BIN
testdata/drc/drcSimpleTests_58.gds vendored Normal file

Binary file not shown.

BIN
testdata/drc/drcSimpleTests_au58.gds vendored Normal file

Binary file not shown.

BIN
testdata/drc/drcSimpleTests_au58d.gds vendored Normal file

Binary file not shown.

Binary file not shown.