Basic implementation

This commit is contained in:
Matthias Koefferlein 2024-08-04 17:57:50 +02:00
parent 7510728a71
commit c23c4045ba
14 changed files with 1297 additions and 91 deletions

View File

@ -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 \

View File

@ -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>
@ -242,87 +247,305 @@ AsIfFlatEdgePairs::filtered (const EdgePairFilterBase &filter) const
}
RegionDelegate *
AsIfFlatEdgePairs::pull_interacting (const Region &) const
AsIfFlatEdgePairs::pull_interacting (const Region &other) const
{
// @@@
return pull_generic (other);
}
EdgesDelegate *
AsIfFlatEdgePairs::pull_interacting (const Edges &) const
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 *

View File

@ -27,6 +27,7 @@
#include "dbCommon.h"
#include "dbEdgePairsDelegate.h"
#include "dbEdgePairsUtils.h"
namespace db {
@ -101,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;

View File

@ -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,88 +500,190 @@ RegionDelegate *DeepEdgePairs::polygons (db::Coord e) const
return new db::DeepRegion (new_layer);
}
RegionDelegate *
DeepEdgePairs::pull_interacting (const Region &) const
{
// @@@
}
EdgesDelegate *
DeepEdgePairs::pull_interacting (const Edges &) const
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 (const Region &other, size_t min_count, size_t max_count) const
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_not_interacting (const Region &other, size_t min_count, size_t max_count) const
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 ();
}
EdgePairsDelegate *
DeepEdgePairs::selected_interacting (const Edges &other, size_t min_count, size_t max_count) const
{
// @@@
}
min_count = std::max (size_t (1), min_count);
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
EdgePairsDelegate *
DeepEdgePairs::selected_not_interacting (const Edges &other, size_t min_count, size_t max_count) const
{
// @@@
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 (const Region &other, size_t min_count, size_t max_count) const
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 (const Edges &other, size_t min_count, size_t max_count) const
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 ();
}
EdgePairsDelegate *
DeepEdgePairs::selected_outside (const Region &other) const
{
// @@@
}
min_count = std::max (size_t (1), min_count);
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
EdgePairsDelegate *
DeepEdgePairs::selected_not_outside (const Region &other) const
{
// @@@
}
const db::DeepLayer &edge_pairs = deep_layer ();
std::pair<EdgePairsDelegate *, EdgePairsDelegate *>
DeepEdgePairs::selected_outside_pair (const Region &other) const
{
// @@@
}
DeepLayer dl_out (edge_pairs.derived ());
DeepLayer dl_out2 (edge_pairs.derived ());
EdgePairsDelegate *
DeepEdgePairs::selected_inside (const Region &other) const
{
// @@@
}
std::vector<unsigned int> output_layers;
output_layers.reserve (2);
output_layers.push_back (dl_out.layer ());
output_layers.push_back (dl_out2.layer ());
EdgePairsDelegate *
DeepEdgePairs::selected_not_inside (const Region &other) const
{
// @@@
}
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);
std::pair<EdgePairsDelegate *, EdgePairsDelegate *>
DeepEdgePairs::selected_inside_pair (const Region &other) const
{
// @@@
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

View File

@ -83,22 +83,6 @@ 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 &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);
virtual EdgePairsDelegate *add (const EdgePairs &other) const;
@ -120,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);

View File

@ -226,12 +226,12 @@ void EdgePairs::second_edges (Edges &output) const
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)

View File

@ -767,6 +767,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
*

View File

@ -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;

View File

@ -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 ();
@ -254,6 +260,7 @@ protected:
private:
bool m_report_progress;
std::string m_progress_desc;
int m_base_verbosity;
};
}

View File

@ -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"));
}
}

View File

@ -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

View File

@ -0,0 +1,92 @@
/*
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)
{
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)
{
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)
{
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 (a.second (), b);
}
}

View File

@ -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

View File

@ -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)