mirror of https://github.com/KLayout/klayout.git
First steps towards differential interaction functions
This commit is contained in:
parent
aad393d7c9
commit
8c6b231ae6
|
|
@ -378,28 +378,77 @@ AsIfFlatRegion::processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &f
|
|||
return new_edge_pairs.release ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
AsIfFlatRegion::selected_interacting_generic (const Edges &other, bool inverse, size_t min_count, size_t max_count) const
|
||||
namespace {
|
||||
|
||||
class OutputPairHolder
|
||||
{
|
||||
public:
|
||||
OutputPairHolder (InteractingOutputMode output_mode, bool merged_semantics)
|
||||
{
|
||||
if (output_mode == None) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (output_mode == Positive || output_mode == Negative || output_mode == PositiveAndNegative) {
|
||||
m_positive.reset (new FlatRegion (merged_semantics));
|
||||
m_results.push_back (& m_positive->raw_polygons ());
|
||||
} else {
|
||||
m_results.push_back ((db::Shapes *) 0);
|
||||
}
|
||||
|
||||
if (output_mode == PositiveAndNegative) {
|
||||
m_negative.reset (new FlatRegion (merged_semantics));
|
||||
m_results.push_back (& m_negative->raw_polygons ());
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<RegionDelegate *, RegionDelegate *> region_pair ()
|
||||
{
|
||||
return std::make_pair (m_positive.release (), m_negative.release ());
|
||||
}
|
||||
|
||||
const std::vector<db::Shapes *> &results () { return m_results; }
|
||||
|
||||
private:
|
||||
std::unique_ptr<FlatRegion> m_positive, m_negative;
|
||||
std::vector<db::Shapes *> m_results;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
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 ());
|
||||
|
||||
if (output_mode == None) {
|
||||
return oph.region_pair ();
|
||||
}
|
||||
|
||||
min_count = std::max (size_t (1), min_count);
|
||||
|
||||
if (max_count < min_count || other.empty ()) {
|
||||
if (! inverse) {
|
||||
return new EmptyRegion ();
|
||||
// shortcut
|
||||
if (empty ()) {
|
||||
if (output_mode == Positive || output_mode == Negative) {
|
||||
return std::make_pair (const_cast <AsIfFlatRegion *> (this), (RegionDelegate *) 0);
|
||||
} else {
|
||||
return clone ();
|
||||
return std::make_pair (const_cast <AsIfFlatRegion *> (this), const_cast <AsIfFlatRegion *> (this));
|
||||
}
|
||||
} else if (max_count < min_count || other.empty ()) {
|
||||
if (output_mode == Positive) {
|
||||
return std::make_pair (new EmptyRegion (), (RegionDelegate *) 0);
|
||||
} else if (output_mode == Negative) {
|
||||
return std::make_pair (const_cast <AsIfFlatRegion *> (this), (RegionDelegate *) 0);
|
||||
} else {
|
||||
return std::make_pair (new EmptyRegion (), const_cast <AsIfFlatRegion *> (this));
|
||||
}
|
||||
} else if (empty ()) {
|
||||
return clone ();
|
||||
}
|
||||
|
||||
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
|
||||
|
||||
#if defined(USE_LOCAL_PROCESSOR)
|
||||
|
||||
db::RegionIterator polygons (begin_merged ());
|
||||
|
||||
db::interacting_with_edge_local_operation<db::Polygon, db::Edge, db::Polygon> op (inverse, min_count, max_count, true);
|
||||
db::interacting_with_edge_local_operation<db::Polygon, db::Edge, db::Polygon> op (output_mode, min_count, max_count, true);
|
||||
|
||||
db::local_processor<db::Polygon, db::Edge, db::Polygon> proc;
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
|
|
@ -413,71 +462,42 @@ AsIfFlatRegion::selected_interacting_generic (const Edges &other, bool inverse,
|
|||
std::vector<db::Shapes *> results;
|
||||
results.push_back (&output->raw_polygons ());
|
||||
|
||||
proc.run_flat (polygons, others, std::vector<bool> (), &op, results);
|
||||
proc.run_flat (polygons, others, std::vector<bool> (), &op, oph.results ());
|
||||
|
||||
return output.release ();
|
||||
|
||||
#else
|
||||
std::unordered_map<const db::Polygon *, size_t, std::ptr_hash_from_value<db::Polygon> > counted_results;
|
||||
ResultCountingInserter inserter (counted_results);
|
||||
|
||||
db::box_scanner2<db::Polygon, size_t, db::Edge, size_t> scanner (report_progress (), progress_desc ());
|
||||
scanner.reserve1 (count ());
|
||||
scanner.reserve2 (other.count ());
|
||||
|
||||
std::unique_ptr<FlatRegion> output (new FlatRegion (false));
|
||||
region_to_edge_interaction_filter<db::Polygon, db::Edge, ResultCountingInserter> filter (inserter, false, counting /*get all in counting mode*/);
|
||||
|
||||
AddressablePolygonDelivery p (begin_merged ());
|
||||
|
||||
for ( ; ! p.at_end (); ++p) {
|
||||
scanner.insert1 (p.operator-> (), 0);
|
||||
if (inverse) {
|
||||
inserter.init (p.operator-> ());
|
||||
}
|
||||
}
|
||||
|
||||
AddressableEdgeDelivery e (counting ? other.addressable_merged_edges () : other.addressable_edges ());
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
scanner.insert2 (e.operator-> (), 0);
|
||||
}
|
||||
|
||||
scanner.process (filter, 1, db::box_convert<db::Polygon> (), db::box_convert<db::Edge> ());
|
||||
|
||||
// select hits based on their count
|
||||
|
||||
for (std::unordered_map<const db::Polygon *, size_t, std::ptr_hash_from_value<db::Polygon> >::const_iterator r = counted_results.begin (); r != counted_results.end (); ++r) {
|
||||
bool hit = r->second >= min_count && r->second <= max_count;
|
||||
if (hit != inverse) {
|
||||
output->insert (*r->first);
|
||||
}
|
||||
}
|
||||
|
||||
return output.release ();
|
||||
#endif
|
||||
return oph.region_pair ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
AsIfFlatRegion::selected_interacting_generic (const Texts &other, bool inverse, size_t min_count, size_t max_count) const
|
||||
std::pair<RegionDelegate *, RegionDelegate *>
|
||||
AsIfFlatRegion::selected_interacting_generic (const Texts &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const
|
||||
{
|
||||
min_count = std::max (size_t (1), min_count);
|
||||
OutputPairHolder oph (output_mode, merged_semantics ());
|
||||
|
||||
if (max_count < min_count || other.empty ()) {
|
||||
if (! inverse) {
|
||||
return new EmptyRegion ();
|
||||
} else {
|
||||
return clone ();
|
||||
}
|
||||
} else if (empty ()) {
|
||||
return clone ();
|
||||
if (output_mode == None) {
|
||||
return oph.region_pair ();
|
||||
}
|
||||
|
||||
#if defined(USE_LOCAL_PROCESSOR)
|
||||
min_count = std::max (size_t (1), min_count);
|
||||
|
||||
// shortcut
|
||||
if (empty ()) {
|
||||
if (output_mode == Positive || output_mode == Negative) {
|
||||
return std::make_pair (const_cast <AsIfFlatRegion *> (this), (RegionDelegate *) 0);
|
||||
} else {
|
||||
return std::make_pair (const_cast <AsIfFlatRegion *> (this), const_cast <AsIfFlatRegion *> (this));
|
||||
}
|
||||
} else if (max_count < min_count || other.empty ()) {
|
||||
if (output_mode == Positive) {
|
||||
return std::make_pair (new EmptyRegion (), (RegionDelegate *) 0);
|
||||
} else if (output_mode == Negative) {
|
||||
return std::make_pair (const_cast <AsIfFlatRegion *> (this), (RegionDelegate *) 0);
|
||||
} else {
|
||||
return std::make_pair (new EmptyRegion (), const_cast <AsIfFlatRegion *> (this));
|
||||
}
|
||||
}
|
||||
|
||||
db::RegionIterator polygons (begin_merged ());
|
||||
|
||||
db::interacting_with_text_local_operation<db::Polygon, db::Text, db::Polygon> op (inverse, min_count, max_count);
|
||||
db::interacting_with_text_local_operation<db::Polygon, db::Text, db::Polygon> op (output_mode, min_count, max_count);
|
||||
|
||||
db::local_processor<db::Polygon, db::Text, db::Polygon> proc;
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
|
|
@ -487,84 +507,58 @@ AsIfFlatRegion::selected_interacting_generic (const Texts &other, bool inverse,
|
|||
std::vector<generic_shape_iterator<db::Text> > others;
|
||||
others.push_back (other.begin ());
|
||||
|
||||
std::unique_ptr<FlatRegion> output (new FlatRegion (merged_semantics ()));
|
||||
std::vector<db::Shapes *> results;
|
||||
results.push_back (&output->raw_polygons ());
|
||||
proc.run_flat (polygons, others, std::vector<bool> (), &op, oph.results ());
|
||||
|
||||
proc.run_flat (polygons, others, std::vector<bool> (), &op, results);
|
||||
|
||||
return output.release ();
|
||||
|
||||
#else
|
||||
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
|
||||
|
||||
std::unordered_map<const db::Polygon *, size_t, std::ptr_hash_from_value<db::Polygon> > counted_results;
|
||||
ResultCountingInserter inserter (counted_results);
|
||||
|
||||
db::box_scanner2<db::Polygon, size_t, db::Text, size_t> scanner (report_progress (), progress_desc ());
|
||||
scanner.reserve1 (count ());
|
||||
scanner.reserve2 (other.count ());
|
||||
|
||||
region_to_text_interaction_filter<db::Polygon, db::Text, ResultCountingInserter> filter (inserter, false, counting /*get all in counting mode*/);
|
||||
|
||||
AddressablePolygonDelivery p (begin_merged ());
|
||||
|
||||
for ( ; ! p.at_end (); ++p) {
|
||||
scanner.insert1 (p.operator-> (), 0);
|
||||
if (inverse) {
|
||||
inserter.init (p.operator-> ());
|
||||
}
|
||||
}
|
||||
|
||||
AddressableTextDelivery e (other.addressable_texts ());
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
scanner.insert2 (e.operator-> (), 0);
|
||||
}
|
||||
|
||||
scanner.process (filter, 1, db::box_convert<db::Polygon> (), db::box_convert<db::Text> ());
|
||||
|
||||
// select hits based on their count
|
||||
|
||||
std::unique_ptr<FlatRegion> output (new FlatRegion (true));
|
||||
|
||||
for (std::unordered_map<const db::Polygon *, size_t, std::ptr_hash_from_value<db::Polygon> >::const_iterator r = counted_results.begin (); r != counted_results.end (); ++r) {
|
||||
bool hit = r->second >= min_count && r->second <= max_count;
|
||||
if (hit != inverse) {
|
||||
output->insert (*r->first);
|
||||
}
|
||||
}
|
||||
|
||||
return output.release ();
|
||||
#endif
|
||||
return oph.region_pair ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse, size_t min_count, size_t max_count) const
|
||||
|
||||
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 ());
|
||||
|
||||
if (output_mode == None) {
|
||||
return oph.region_pair ();
|
||||
}
|
||||
|
||||
min_count = std::max (size_t (1), min_count);
|
||||
|
||||
// shortcut
|
||||
if (empty ()) {
|
||||
return clone ();
|
||||
if (output_mode == Positive || output_mode == Negative) {
|
||||
return std::make_pair (const_cast <AsIfFlatRegion *> (this), (RegionDelegate *) 0);
|
||||
} else {
|
||||
return std::make_pair (const_cast <AsIfFlatRegion *> (this), const_cast <AsIfFlatRegion *> (this));
|
||||
}
|
||||
} else if (max_count < min_count || other.empty ()) {
|
||||
// clear, if b is empty and
|
||||
// * mode is inside, enclosing or interacting and inverse is false ("inside" or "interacting")
|
||||
// * mode is outside and inverse is true ("not outside")
|
||||
if ((mode <= 0) != inverse) {
|
||||
return new EmptyRegion ();
|
||||
if ((mode <= 0)) {
|
||||
if (output_mode == Positive) {
|
||||
return std::make_pair (new EmptyRegion (), (RegionDelegate *) 0);
|
||||
} else if (output_mode == Negative) {
|
||||
return std::make_pair (const_cast <AsIfFlatRegion *> (this), (RegionDelegate *) 0);
|
||||
} else {
|
||||
return std::make_pair (new EmptyRegion (), const_cast <AsIfFlatRegion *> (this));
|
||||
}
|
||||
} else {
|
||||
return clone ();
|
||||
if (output_mode == Positive) {
|
||||
return std::make_pair (const_cast <AsIfFlatRegion *> (this), (RegionDelegate *) 0);
|
||||
} else if (output_mode == Negative) {
|
||||
return std::make_pair (new EmptyRegion (), (RegionDelegate *) 0);
|
||||
} else {
|
||||
return std::make_pair (const_cast <AsIfFlatRegion *> (this), new EmptyRegion ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(USE_LOCAL_PROCESSOR)
|
||||
|
||||
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
|
||||
|
||||
db::RegionIterator polygons (begin_merged ());
|
||||
|
||||
db::interacting_local_operation<db::Polygon, db::Polygon, db::Polygon> op (mode, touching, inverse, min_count, max_count, true);
|
||||
db::interacting_local_operation<db::Polygon, db::Polygon, db::Polygon> op (mode, touching, output_mode, min_count, max_count, true);
|
||||
|
||||
db::local_processor<db::Polygon, db::Polygon, db::Polygon> proc;
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
|
|
@ -574,121 +568,9 @@ AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, boo
|
|||
std::vector<generic_shape_iterator<db::Polygon> > others;
|
||||
others.push_back ((mode < 0 || counting) ? other.begin_merged () : other.begin ());
|
||||
|
||||
std::unique_ptr<FlatRegion> output (new FlatRegion (merged_semantics ()));
|
||||
std::vector<db::Shapes *> results;
|
||||
results.push_back (&output->raw_polygons ());
|
||||
proc.run_flat (polygons, others, std::vector<bool> (), &op, oph.results ());
|
||||
|
||||
proc.run_flat (polygons, others, std::vector<bool> (), &op, results);
|
||||
|
||||
return output.release ();
|
||||
|
||||
#else
|
||||
db::EdgeProcessor ep (report_progress (), progress_desc ());
|
||||
ep.set_base_verbosity (base_verbosity ());
|
||||
|
||||
size_t n = 0;
|
||||
size_t nstart = 0;
|
||||
|
||||
if (mode < -1) {
|
||||
|
||||
// in enclosing mode self must be primary and other the secondary. For other
|
||||
// modes it's the other way round
|
||||
|
||||
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p, ++n) {
|
||||
if (mode > 0 || p->box ().touches (other.bbox ())) {
|
||||
ep.insert (*p, n);
|
||||
}
|
||||
}
|
||||
|
||||
nstart = n;
|
||||
|
||||
}
|
||||
|
||||
if (min_count == size_t (1) && max_count == std::numeric_limits<size_t>::max ()) {
|
||||
|
||||
if (mode < 0) {
|
||||
|
||||
// NOTE: on "inside" or "enclosing", the other region must be merged
|
||||
for (RegionIterator p = other.begin_merged (); ! p.at_end (); ++p) {
|
||||
if (p->box ().touches (bbox ())) {
|
||||
ep.insert (*p, n);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
for (RegionIterator p = other.begin (); ! p.at_end (); ++p) {
|
||||
if (p->box ().touches (bbox ())) {
|
||||
ep.insert (*p, n);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
++n;
|
||||
|
||||
} else {
|
||||
|
||||
// with counting we need to separate the other polygons by different properties
|
||||
|
||||
// cannot only have min_count/max_count in outside mode
|
||||
tl_assert (mode <= 0);
|
||||
|
||||
for (RegionIterator p = other.begin_merged (); ! p.at_end (); ++p) {
|
||||
if (p->box ().touches (bbox ())) {
|
||||
ep.insert (*p, n);
|
||||
}
|
||||
++n;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (mode >= -1) {
|
||||
|
||||
nstart = n;
|
||||
|
||||
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p, ++n) {
|
||||
if (mode > 0 || p->box ().touches (other.bbox ())) {
|
||||
ep.insert (*p, n);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// there should be at least one element to look at for primary
|
||||
tl_assert (nstart > 0);
|
||||
|
||||
db::InteractionDetector id (mode, nstart - 1);
|
||||
id.set_include_touching (touching);
|
||||
db::EdgeSink es;
|
||||
ep.process (es, id);
|
||||
id.finish ();
|
||||
|
||||
std::unique_ptr<FlatRegion> output (new FlatRegion (false));
|
||||
|
||||
std::map <size_t, size_t> interaction_counts;
|
||||
for (db::InteractionDetector::iterator i = id.begin (); i != id.end () ; ++i) {
|
||||
if (i->first < nstart && i->second >= nstart) {
|
||||
interaction_counts [mode < -1 ? i->first : i->second] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
output->reserve (n);
|
||||
|
||||
n = (mode < -1 ? 0 : nstart);
|
||||
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p, ++n) {
|
||||
size_t count = 0;
|
||||
std::map <size_t, size_t>::const_iterator c = interaction_counts.find (n);
|
||||
if (c != interaction_counts.end ()) {
|
||||
count = c->second;
|
||||
}
|
||||
if ((count >= min_count && count <= max_count) != inverse) {
|
||||
output->insert (*p);
|
||||
}
|
||||
}
|
||||
|
||||
return output.release ();
|
||||
#endif
|
||||
return oph.region_pair ();
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
|
|
|
|||
|
|
@ -139,72 +139,107 @@ public:
|
|||
|
||||
virtual RegionDelegate *selected_outside (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, 1, false, false);
|
||||
return selected_interacting_generic (other, 1, false, Positive, size_t (0), std::numeric_limits<size_t>::max ()).first;
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_not_outside (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, 1, false, true);
|
||||
return selected_interacting_generic (other, 1, false, Negative, size_t (0), std::numeric_limits<size_t>::max ()).first;
|
||||
}
|
||||
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_outside_pair (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, 1, false, PositiveAndNegative, size_t (0), std::numeric_limits<size_t>::max ());
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_inside (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, -1, true, false);
|
||||
return selected_interacting_generic (other, -1, true, Positive, size_t (0), std::numeric_limits<size_t>::max ()).first;
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_not_inside (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, -1, true, true);
|
||||
return selected_interacting_generic (other, -1, true, Negative, size_t (0), std::numeric_limits<size_t>::max ()).first;
|
||||
}
|
||||
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_inside_pair (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, -1, true, PositiveAndNegative, size_t (0), std::numeric_limits<size_t>::max ());
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_enclosing (const Region &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, -2, false, false, min_count, max_count);
|
||||
return selected_interacting_generic (other, -2, false, Positive, min_count, max_count).first;
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_not_enclosing (const Region &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, -2, false, true, min_count, max_count);
|
||||
return selected_interacting_generic (other, -2, false, Negative, min_count, max_count).first;
|
||||
}
|
||||
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_enclosing_pair (const Region &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, -2, false, PositiveAndNegative, min_count, max_count);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_interacting (const Region &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, 0, true, false, min_count, max_count);
|
||||
return selected_interacting_generic (other, 0, true, Positive, min_count, max_count).first;
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_not_interacting (const Region &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, 0, true, true, min_count, max_count);
|
||||
return selected_interacting_generic (other, 0, true, Negative, min_count, max_count).first;
|
||||
}
|
||||
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_pair (const Region &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, 0, true, PositiveAndNegative, min_count, max_count);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_interacting (const Edges &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, false, min_count, max_count);
|
||||
return selected_interacting_generic (other, Positive, min_count, max_count).first;
|
||||
}
|
||||
|
||||
virtual RegionDelegate *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);
|
||||
return selected_interacting_generic (other, Negative, min_count, max_count).first;
|
||||
}
|
||||
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_pair (const Edges &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, PositiveAndNegative, min_count, max_count);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_interacting (const Texts &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, false, min_count, max_count);
|
||||
return selected_interacting_generic (other, Positive, min_count, max_count).first;
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_not_interacting (const Texts &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, true, min_count, max_count);
|
||||
return selected_interacting_generic (other, Negative, min_count, max_count).first;
|
||||
}
|
||||
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_pair (const Texts &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, PositiveAndNegative, min_count, max_count);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_overlapping (const Region &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, 0, false, false, min_count, max_count);
|
||||
return selected_interacting_generic (other, 0, false, Positive, min_count, max_count).first;
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_not_overlapping (const Region &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, 0, false, true, min_count, max_count);
|
||||
return selected_interacting_generic (other, 0, false, Negative, min_count, max_count).first;
|
||||
}
|
||||
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_overlapping_pair (const Region &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, 0, false, PositiveAndNegative, min_count, max_count);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *pull_inside (const Region &other) const
|
||||
|
|
@ -245,9 +280,9 @@ protected:
|
|||
|
||||
virtual EdgePairsDelegate *run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, const RegionCheckOptions &options) const;
|
||||
virtual EdgePairsDelegate *run_single_polygon_check (db::edge_relation_type rel, db::Coord d, const RegionCheckOptions &options) const;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Texts &other, bool inverse, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_generic (const Region &other, int mode, bool touching, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_generic (const Edges &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_generic (const Texts &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const;
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -1060,13 +1060,13 @@ template void CompoundRegionLogicalCaseSelectOperationNode::implement_compute_lo
|
|||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
CompoundRegionInteractOperationNode::CompoundRegionInteractOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b, int mode, bool touching, bool inverse, size_t min_count, size_t max_count)
|
||||
: compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon> (&m_op, a, b), m_op (mode, touching, inverse, min_count, max_count, b->is_merged ())
|
||||
: compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon> (&m_op, a, b), m_op (mode, touching, inverse ? Negative : Positive, min_count, max_count, b->is_merged ())
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
CompoundRegionInteractOperationNode::CompoundRegionInteractOperationNode (db::Region *a, db::Region *b, int mode, bool touching, bool inverse, size_t min_count, size_t max_count)
|
||||
: compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon> (&m_op, a, b), m_op (mode, touching, inverse, min_count, max_count, b->is_merged ())
|
||||
: compound_region_generic_operation_node<db::Polygon, db::Polygon, db::Polygon> (&m_op, a, b), m_op (mode, touching, inverse ? Negative : Positive, min_count, max_count, b->is_merged ())
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -1080,7 +1080,7 @@ CompoundRegionInteractOperationNode::generated_description () const
|
|||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
CompoundRegionInteractWithEdgeOperationNode::CompoundRegionInteractWithEdgeOperationNode (CompoundRegionOperationNode *a, CompoundRegionOperationNode *b, bool inverse, size_t min_count, size_t max_count)
|
||||
: compound_region_generic_operation_node<db::Polygon, db::Edge, db::Polygon> (&m_op, a, b), m_op (inverse, min_count, max_count, b->is_merged ())
|
||||
: compound_region_generic_operation_node<db::Polygon, db::Edge, db::Polygon> (&m_op, a, b), m_op (inverse ? Negative : Positive, min_count, max_count, b->is_merged ())
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
|
|||
|
|
@ -753,7 +753,8 @@ public:
|
|||
virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<db::PolygonRef, db::PolygonRef> & /*interactions*/, std::vector<std::unordered_set<db::EdgePair> > & /*results*/, size_t /*max_vertex_count*/, double /*area_ratio*/) const { }
|
||||
|
||||
private:
|
||||
db::interacting_local_operation<db::Polygon, db::Polygon, db::Polygon> m_op;
|
||||
typedef db::interacting_local_operation<db::Polygon, db::Polygon, db::Polygon> op_type;
|
||||
op_type m_op;
|
||||
};
|
||||
|
||||
class DB_PUBLIC CompoundRegionInteractWithEdgeOperationNode
|
||||
|
|
|
|||
|
|
@ -1519,9 +1519,67 @@ DeepRegion::run_single_polygon_check (db::edge_relation_type rel, db::Coord d, c
|
|||
return res.release ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
DeepRegion::selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse, size_t min_count, size_t max_count) const
|
||||
namespace
|
||||
{
|
||||
|
||||
class InteractingResultHolder
|
||||
{
|
||||
public:
|
||||
InteractingResultHolder (InteractingOutputMode output_mode, bool is_merged, const db::DeepLayer &polygons)
|
||||
: m_output_mode (output_mode), m_is_merged (is_merged)
|
||||
{
|
||||
if (m_output_mode == Positive || m_output_mode == Negative) {
|
||||
m_dl1 = db::DeepLayer (polygons.derived ());
|
||||
} else if (m_output_mode == PositiveAndNegative) {
|
||||
m_dl1 = db::DeepLayer (polygons.derived ());
|
||||
m_dl2 = db::DeepLayer (polygons.derived ());
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<unsigned int> layers () const
|
||||
{
|
||||
std::vector<unsigned int> l;
|
||||
if (m_output_mode == Positive || m_output_mode == Negative) {
|
||||
l.push_back (m_dl1.layer ());
|
||||
} else if (m_output_mode == PositiveAndNegative) {
|
||||
l.push_back (m_dl1.layer ());
|
||||
l.push_back (m_dl2.layer ());
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
std::pair<RegionDelegate *, RegionDelegate *> result_pair ()
|
||||
{
|
||||
if (m_output_mode == Positive || m_output_mode == Negative) {
|
||||
db::DeepRegion *res = new db::DeepRegion (m_dl1);
|
||||
res->set_is_merged (m_is_merged);
|
||||
return std::pair<RegionDelegate *, RegionDelegate *> (res, 0);
|
||||
} else if (m_output_mode == PositiveAndNegative) {
|
||||
db::DeepRegion *res1 = new db::DeepRegion (m_dl1);
|
||||
res1->set_is_merged (m_is_merged);
|
||||
db::DeepRegion *res2 = new db::DeepRegion (m_dl2);
|
||||
res2->set_is_merged (m_is_merged);
|
||||
return std::pair<RegionDelegate *, RegionDelegate *> (res1, res2);
|
||||
} else {
|
||||
return std::pair<RegionDelegate *, RegionDelegate *> (0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
InteractingOutputMode m_output_mode;
|
||||
bool m_is_merged;
|
||||
DeepLayer m_dl1, m_dl2;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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.
|
||||
|
|
@ -1539,9 +1597,7 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
|
|||
// 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 ();
|
||||
|
||||
DeepLayer dl_out (polygons.derived ());
|
||||
|
||||
db::InteractingLocalOperation op (mode, touching, inverse, min_count, max_count, true);
|
||||
db::InteractingLocalOperation op (mode, touching, output_mode, min_count, max_count, true);
|
||||
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell (), polygons.breakout_cells (), other_polygons.breakout_cells ());
|
||||
proc.set_description (progress_desc ());
|
||||
|
|
@ -1553,17 +1609,16 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
|
|||
proc.set_max_vertex_count (polygons.store ()->max_vertex_count ());
|
||||
}
|
||||
|
||||
proc.run (&op, polygons.layer (), other_polygons.layer (), dl_out.layer ());
|
||||
bool result_is_merged = (! split_after && ((mode < 0 && other.merged_semantics ()) || other.is_merged ()) && (merged_semantics () || is_merged ()));
|
||||
InteractingResultHolder orh (output_mode, result_is_merged, polygons);
|
||||
|
||||
db::DeepRegion *res = new db::DeepRegion (dl_out);
|
||||
if (! split_after && ((mode < 0 && other.merged_semantics ()) || other.is_merged ()) && (merged_semantics () || is_merged ())) {
|
||||
res->set_is_merged (true);
|
||||
}
|
||||
return res;
|
||||
proc.run (&op, polygons.layer (), other_polygons.layer (), orh.layers ());
|
||||
|
||||
return orh.result_pair ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
DeepRegion::selected_interacting_generic (const Edges &other, bool inverse, size_t min_count, size_t max_count) const
|
||||
std::pair<RegionDelegate *, RegionDelegate *>
|
||||
DeepRegion::selected_interacting_generic (const Edges &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const
|
||||
{
|
||||
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
|
||||
|
||||
|
|
@ -1580,9 +1635,7 @@ DeepRegion::selected_interacting_generic (const Edges &other, bool inverse, size
|
|||
|
||||
const db::DeepLayer &polygons = merged_deep_layer ();
|
||||
|
||||
DeepLayer dl_out (polygons.derived ());
|
||||
|
||||
db::InteractingWithEdgeLocalOperation op (inverse, min_count, max_count, true);
|
||||
db::InteractingWithEdgeLocalOperation op (output_mode, min_count, max_count, true);
|
||||
|
||||
db::local_processor<db::PolygonRef, db::Edge, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), polygons.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
|
||||
proc.set_description (progress_desc ());
|
||||
|
|
@ -1594,13 +1647,12 @@ DeepRegion::selected_interacting_generic (const Edges &other, bool inverse, size
|
|||
proc.set_max_vertex_count (polygons.store ()->max_vertex_count ());
|
||||
}
|
||||
|
||||
proc.run (&op, polygons.layer (), counting ? other_deep->merged_deep_layer ().layer () : other_deep->deep_layer ().layer (), dl_out.layer ());
|
||||
bool result_is_merged = (! split_after && other.is_merged () && (merged_semantics () || is_merged ()));
|
||||
InteractingResultHolder orh (output_mode, result_is_merged, polygons);
|
||||
|
||||
db::DeepRegion *res = new db::DeepRegion (dl_out);
|
||||
if (! split_after) {
|
||||
res->set_is_merged (other.is_merged () && (merged_semantics () || is_merged ()));
|
||||
}
|
||||
return res;
|
||||
proc.run (&op, polygons.layer (), counting ? other_deep->merged_deep_layer ().layer () : other_deep->deep_layer ().layer (), orh.layers ());
|
||||
|
||||
return orh.result_pair ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
|
|
@ -1706,8 +1758,9 @@ DeepRegion::pull_generic (const Texts &other) const
|
|||
return res;
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
DeepRegion::selected_interacting_generic (const Texts &other, bool inverse, size_t min_count, size_t max_count) const
|
||||
|
||||
std::pair<RegionDelegate *, RegionDelegate *>
|
||||
DeepRegion::selected_interacting_generic (const Texts &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const
|
||||
{
|
||||
// with these flag set to true, the resulting polygons are broken again.
|
||||
bool split_after = false;
|
||||
|
|
@ -1722,9 +1775,7 @@ DeepRegion::selected_interacting_generic (const Texts &other, bool inverse, size
|
|||
|
||||
const db::DeepLayer &polygons = merged_deep_layer ();
|
||||
|
||||
DeepLayer dl_out (polygons.derived ());
|
||||
|
||||
db::InteractingWithTextLocalOperation op (inverse, min_count, max_count);
|
||||
db::InteractingWithTextLocalOperation op (output_mode, min_count, max_count);
|
||||
|
||||
db::local_processor<db::PolygonRef, db::TextRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), polygons.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
|
||||
proc.set_description (progress_desc ());
|
||||
|
|
@ -1736,13 +1787,12 @@ DeepRegion::selected_interacting_generic (const Texts &other, bool inverse, size
|
|||
proc.set_max_vertex_count (polygons.store ()->max_vertex_count ());
|
||||
}
|
||||
|
||||
proc.run (&op, polygons.layer (), other_deep->deep_layer ().layer (), dl_out.layer ());
|
||||
bool result_is_merged = (! split_after && (merged_semantics () || is_merged ()));
|
||||
InteractingResultHolder orh (output_mode, result_is_merged, polygons);
|
||||
|
||||
db::DeepRegion *res = new db::DeepRegion (dl_out);
|
||||
if (! split_after) {
|
||||
res->set_is_merged (merged_semantics () || is_merged ());
|
||||
}
|
||||
return res;
|
||||
proc.run (&op, polygons.layer (), other_deep->deep_layer ().layer (), orh.layers ());
|
||||
|
||||
return orh.result_pair ();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -140,9 +140,9 @@ protected:
|
|||
|
||||
virtual EdgePairsDelegate *run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, const RegionCheckOptions &options) const;
|
||||
virtual EdgePairsDelegate *run_single_polygon_check (db::edge_relation_type rel, db::Coord d, const RegionCheckOptions &options) const;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse, size_t min_count, size_t max_count) const;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse, size_t min_count, size_t max_count) const;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Texts &other, bool inverse, size_t min_count, size_t max_count) const;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_generic (const Region &other, int mode, bool touching, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_generic (const Edges &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_generic (const Texts &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const;
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -108,18 +108,25 @@ public:
|
|||
|
||||
virtual RegionDelegate *selected_outside (const Region &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_not_outside (const Region &) const { return new EmptyRegion (); }
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_outside_pair (const Region &) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
|
||||
virtual RegionDelegate *selected_inside (const Region &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_not_inside (const Region &) const { return new EmptyRegion (); }
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_inside_pair (const Region &) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
|
||||
virtual RegionDelegate *selected_enclosing (const Region &, size_t, size_t) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_not_enclosing (const Region &, size_t, size_t) const { return new EmptyRegion (); }
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_enclosing_pair (const Region &, size_t, size_t) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
|
||||
virtual RegionDelegate *selected_interacting (const Region &, size_t, size_t) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_not_interacting (const Region &, size_t, size_t) const { return new EmptyRegion (); }
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_pair (const Region &, size_t, size_t) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
|
||||
virtual RegionDelegate *selected_interacting (const Edges &, size_t, size_t) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_not_interacting (const Edges &, size_t, size_t) const { return new EmptyRegion (); }
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_pair (const Edges &, size_t, size_t) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
|
||||
virtual RegionDelegate *selected_interacting (const Texts &, size_t, size_t) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_not_interacting (const Texts &, size_t, size_t) const { return new EmptyRegion (); }
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_pair (const Texts &, size_t, size_t) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
|
||||
virtual RegionDelegate *selected_overlapping (const Region &, size_t, size_t) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_not_overlapping (const Region &, size_t, size_t) const { return new EmptyRegion (); }
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_overlapping_pair (const Region &, size_t, size_t) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); }
|
||||
virtual RegionDelegate *pull_inside (const Region &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *pull_interacting (const Region &) const { return new EmptyRegion (); }
|
||||
virtual EdgesDelegate *pull_interacting (const Edges &) const { return new EmptyEdges (); }
|
||||
|
|
|
|||
|
|
@ -1280,6 +1280,14 @@ void local_processor<TS, TI, TR>::run (local_operation<TS, TI, TR> *op, unsigned
|
|||
run (op, subject_layer, il, ol);
|
||||
}
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
void local_processor<TS, TI, TR>::run (local_operation<TS, TI, TR> *op, unsigned int subject_layer, unsigned int intruder_layer, const std::vector<unsigned int> &output_layers)
|
||||
{
|
||||
std::vector<unsigned int> ol, il;
|
||||
il.push_back (intruder_layer);
|
||||
run (op, subject_layer, il, output_layers);
|
||||
}
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
void local_processor<TS, TI, TR>::run (local_operation<TS, TI, TR> *op, unsigned int subject_layer, const std::vector<unsigned int> &intruder_layers, unsigned int output_layer)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -419,6 +419,7 @@ public:
|
|||
local_processor (db::Layout *layout = 0, db::Cell *top = 0, const std::set<db::cell_index_type> *breakout_cells = 0);
|
||||
local_processor (db::Layout *subject_layout, db::Cell *subject_top, const db::Layout *intruder_layout, const db::Cell *intruder_cell, const std::set<db::cell_index_type> *subject_breakout_cells = 0, const std::set<db::cell_index_type> *intruder_breakout_cells = 0);
|
||||
void run (local_operation<TS, TI, TR> *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layers);
|
||||
void run (local_operation<TS, TI, TR> *op, unsigned int subject_layer, unsigned int intruder_layer, const std::vector<unsigned int> &output_layers);
|
||||
void run (local_operation<TS, TI, TR> *op, unsigned int subject_layer, const std::vector<unsigned int> &intruder_layers, const std::vector<unsigned int> &output_layers);
|
||||
void run (local_operation<TS, TI, TR> *op, unsigned int subject_layer, const std::vector<unsigned int> &intruder_layers, unsigned int output_layer);
|
||||
void compute_contexts (local_processor_contexts<TS, TI, TR> &contexts, const local_operation<TS, TI, TR> *op, unsigned int subject_layer, const std::vector<unsigned int> &intruder_layers) const;
|
||||
|
|
|
|||
|
|
@ -54,6 +54,11 @@ enum OnEmptyIntruderHint {
|
|||
*/
|
||||
Copy,
|
||||
|
||||
/**
|
||||
* @brief Copy the subject shape to the second result
|
||||
*/
|
||||
CopyToSecond,
|
||||
|
||||
/**
|
||||
* @brief Drop the subject shape
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -281,18 +281,25 @@ public:
|
|||
|
||||
virtual RegionDelegate *selected_outside (const Region &other) const = 0;
|
||||
virtual RegionDelegate *selected_not_outside (const Region &other) const = 0;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_outside_pair (const Region &other) const = 0;
|
||||
virtual RegionDelegate *selected_inside (const Region &other) const = 0;
|
||||
virtual RegionDelegate *selected_not_inside (const Region &other) const = 0;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_inside_pair (const Region &other) const = 0;
|
||||
virtual RegionDelegate *selected_enclosing (const Region &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual RegionDelegate *selected_not_enclosing (const Region &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_enclosing_pair (const Region &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual RegionDelegate *selected_interacting (const Region &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual RegionDelegate *selected_not_interacting (const Region &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_pair (const Region &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual RegionDelegate *selected_interacting (const Edges &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual RegionDelegate *selected_not_interacting (const Edges &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_pair (const Edges &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual RegionDelegate *selected_interacting (const Texts &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual RegionDelegate *selected_not_interacting (const Texts &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_interacting_pair (const Texts &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual RegionDelegate *selected_overlapping (const Region &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual RegionDelegate *selected_not_overlapping (const Region &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual std::pair<RegionDelegate *, RegionDelegate *> selected_overlapping_pair (const Region &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual RegionDelegate *pull_inside (const Region &other) const = 0;
|
||||
virtual RegionDelegate *pull_interacting (const Region &other) const = 0;
|
||||
virtual EdgesDelegate *pull_interacting (const Edges &other) const = 0;
|
||||
|
|
|
|||
|
|
@ -537,8 +537,8 @@ private:
|
|||
}
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
interacting_local_operation<TS, TI, TR>::interacting_local_operation (int mode, bool touching, bool inverse, size_t min_count, size_t max_count, bool other_is_merged)
|
||||
: m_mode (mode), m_touching (touching), m_inverse (inverse), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count), m_other_is_merged (other_is_merged)
|
||||
interacting_local_operation<TS, TI, TR>::interacting_local_operation (int mode, bool touching, InteractingOutputMode output_mode, size_t min_count, size_t max_count, bool other_is_merged)
|
||||
: m_mode (mode), m_touching (touching), m_output_mode (output_mode), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count), m_other_is_merged (other_is_merged)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -552,8 +552,13 @@ db::Coord interacting_local_operation<TS, TI, TR>::dist () const
|
|||
template <class TS, class TI, class TR>
|
||||
void interacting_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
|
||||
{
|
||||
tl_assert (results.size () == 1);
|
||||
std::unordered_set<TR> &result = results.front ();
|
||||
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);
|
||||
}
|
||||
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
|
|
@ -652,9 +657,21 @@ void interacting_local_operation<TS, TI, TR>::do_compute_local (db::Layout * /*l
|
|||
if (c != interaction_counts.end ()) {
|
||||
count = c->second;
|
||||
}
|
||||
if ((count >= m_min_count && count <= m_max_count) != m_inverse) {
|
||||
const TS &subject = interactions.subject_shape (i->first);
|
||||
result.insert (subject);
|
||||
bool good = (count >= m_min_count && count <= m_max_count);
|
||||
if (good) {
|
||||
if (m_output_mode == Positive || m_output_mode == PositiveAndNegative) {
|
||||
const TS &subject = interactions.subject_shape (i->first);
|
||||
results [0].insert (subject);
|
||||
}
|
||||
} else {
|
||||
if (m_output_mode == Negative) {
|
||||
const TS &subject = interactions.subject_shape (i->first);
|
||||
// Yes, it's "positive_result" as this is the first one.
|
||||
results [0].insert (subject);
|
||||
} else if (m_output_mode == PositiveAndNegative) {
|
||||
const TS &subject = interactions.subject_shape (i->first);
|
||||
results [1].insert (subject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -663,11 +680,22 @@ template <class TS, class TI, class TR>
|
|||
OnEmptyIntruderHint
|
||||
interacting_local_operation<TS, TI, TR>::on_empty_intruder_hint () const
|
||||
{
|
||||
if ((m_mode <= 0) != m_inverse) {
|
||||
return OnEmptyIntruderHint::Drop;
|
||||
if ((m_mode <= 0)) {
|
||||
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::Copy;
|
||||
if (m_output_mode == Positive || m_output_mode == PositiveAndNegative) {
|
||||
return OnEmptyIntruderHint::Copy;
|
||||
} else if (m_output_mode == Negative) {
|
||||
return OnEmptyIntruderHint::Drop;
|
||||
}
|
||||
}
|
||||
return OnEmptyIntruderHint::Ignore;
|
||||
}
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
|
|
@ -761,8 +789,8 @@ template class DB_PUBLIC pull_local_operation<db::Polygon, db::Polygon, db::Poly
|
|||
// ---------------------------------------------------------------------------------------------------------------
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
interacting_with_edge_local_operation<TS, TI, TR>::interacting_with_edge_local_operation (bool inverse, size_t min_count, size_t max_count, bool other_is_merged)
|
||||
: m_inverse (inverse), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count), m_other_is_merged (other_is_merged)
|
||||
interacting_with_edge_local_operation<TS, TI, TR>::interacting_with_edge_local_operation (InteractingOutputMode output_mode, size_t min_count, size_t max_count, bool other_is_merged)
|
||||
: m_output_mode (output_mode), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count), m_other_is_merged (other_is_merged)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -777,6 +805,14 @@ db::Coord interacting_with_edge_local_operation<TS, TI, TR>::dist () const
|
|||
template <class TS, class TI, class TR>
|
||||
void interacting_with_edge_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::unordered_map<TR, size_t> counted_results;
|
||||
bool counting = !(m_min_count == 1 && m_max_count == std::numeric_limits<size_t>::max ());
|
||||
|
||||
|
|
@ -829,7 +865,7 @@ void interacting_with_edge_local_operation<TS, TI, TR>::do_compute_local (db::La
|
|||
const TR *addressable = push_polygon_to_heap (layout, subject, heap);
|
||||
|
||||
scanner.insert1 (addressable, 0);
|
||||
if (m_inverse) {
|
||||
if (m_output_mode == Negative || m_output_mode == PositiveAndNegative) {
|
||||
inserter.init (*addressable);
|
||||
}
|
||||
|
||||
|
|
@ -839,13 +875,18 @@ void interacting_with_edge_local_operation<TS, TI, TR>::do_compute_local (db::La
|
|||
|
||||
// select hits based on their count
|
||||
|
||||
tl_assert (results.size () == 1);
|
||||
std::unordered_set<TR> &result = results.front ();
|
||||
|
||||
for (typename std::unordered_map<TR, size_t>::const_iterator r = counted_results.begin (); r != counted_results.end (); ++r) {
|
||||
bool hit = r->second >= m_min_count && r->second <= m_max_count;
|
||||
if (hit != m_inverse) {
|
||||
result.insert (r->first);
|
||||
if (hit) {
|
||||
if (m_output_mode == Positive || m_output_mode == PositiveAndNegative) {
|
||||
results [0].insert (r->first);
|
||||
}
|
||||
} else {
|
||||
if (m_output_mode == Negative) {
|
||||
results [0].insert (r->first);
|
||||
} else if (m_output_mode == PositiveAndNegative) {
|
||||
results [1].insert (r->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -853,10 +894,14 @@ void interacting_with_edge_local_operation<TS, TI, TR>::do_compute_local (db::La
|
|||
template <class TS, class TI, class TR>
|
||||
OnEmptyIntruderHint interacting_with_edge_local_operation<TS, TI, TR>::on_empty_intruder_hint () const
|
||||
{
|
||||
if (!m_inverse) {
|
||||
if (m_output_mode == Positive) {
|
||||
return OnEmptyIntruderHint::Drop;
|
||||
} else {
|
||||
} else if (m_output_mode == Negative) {
|
||||
return OnEmptyIntruderHint::Copy;
|
||||
} else if (m_output_mode == PositiveAndNegative) {
|
||||
return OnEmptyIntruderHint::CopyToSecond;
|
||||
} else {
|
||||
return OnEmptyIntruderHint::Ignore;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1000,8 +1045,8 @@ template class DB_PUBLIC pull_with_text_local_operation<db::Polygon, db::Text, d
|
|||
// ---------------------------------------------------------------------------------------------------------------
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
interacting_with_text_local_operation<TS, TI, TR>::interacting_with_text_local_operation (bool inverse, size_t min_count, size_t max_count)
|
||||
: m_inverse (inverse), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count)
|
||||
interacting_with_text_local_operation<TS, TI, TR>::interacting_with_text_local_operation (InteractingOutputMode output_mode, size_t min_count, size_t max_count)
|
||||
: m_output_mode (output_mode), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -1017,6 +1062,14 @@ db::Coord interacting_with_text_local_operation<TS, TI, TR>::dist () const
|
|||
template <class TS, class TI, class TR>
|
||||
void interacting_with_text_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::unordered_map<TR, size_t> counted_results;
|
||||
bool counting = !(m_min_count == 1 && m_max_count == std::numeric_limits<size_t>::max ());
|
||||
|
||||
|
|
@ -1042,7 +1095,7 @@ void interacting_with_text_local_operation<TS, TI, TR>::do_compute_local (db::La
|
|||
const TR *addressable = push_polygon_to_heap (layout, interactions.subject_shape (i->first), heap);
|
||||
|
||||
scanner.insert1 (addressable, 0);
|
||||
if (m_inverse) {
|
||||
if (m_output_mode == Negative || m_output_mode == PositiveAndNegative) {
|
||||
inserter.init (*addressable);
|
||||
}
|
||||
|
||||
|
|
@ -1052,13 +1105,19 @@ void interacting_with_text_local_operation<TS, TI, TR>::do_compute_local (db::La
|
|||
|
||||
// select hits based on their count
|
||||
|
||||
tl_assert (results.size () == 1);
|
||||
std::unordered_set<TR> &result = results.front ();
|
||||
|
||||
for (typename std::unordered_map<TR, size_t>::const_iterator r = counted_results.begin (); r != counted_results.end (); ++r) {
|
||||
bool hit = r->second >= m_min_count && r->second <= m_max_count;
|
||||
if (hit != m_inverse) {
|
||||
result.insert (r->first);
|
||||
if (hit) {
|
||||
if (m_output_mode == Positive || m_output_mode == PositiveAndNegative) {
|
||||
results [0].insert (r->first);
|
||||
}
|
||||
} else {
|
||||
if (m_output_mode == Negative) {
|
||||
// Yes. It's "positive"! This is the first output.
|
||||
results [0].insert (r->first);
|
||||
} else if (m_output_mode == PositiveAndNegative) {
|
||||
results [1].insert (r->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1066,10 +1125,14 @@ void interacting_with_text_local_operation<TS, TI, TR>::do_compute_local (db::La
|
|||
template <class TS, class TI, class TR>
|
||||
OnEmptyIntruderHint interacting_with_text_local_operation<TS, TI, TR>::on_empty_intruder_hint () const
|
||||
{
|
||||
if (!m_inverse) {
|
||||
if (m_output_mode == Positive) {
|
||||
return OnEmptyIntruderHint::Drop;
|
||||
} else {
|
||||
} else if (m_output_mode == Negative) {
|
||||
return OnEmptyIntruderHint::Copy;
|
||||
} else if (m_output_mode == PositiveAndNegative) {
|
||||
return OnEmptyIntruderHint::CopyToSecond;
|
||||
} else {
|
||||
return OnEmptyIntruderHint::Ignore;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -222,12 +222,16 @@ private:
|
|||
|
||||
typedef check_local_operation<db::PolygonRef, db::PolygonRef> CheckLocalOperation;
|
||||
|
||||
enum InteractingOutputMode {
|
||||
None = 0, Positive = 1, Negative = 2, PositiveAndNegative = 3
|
||||
};
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
class interacting_local_operation
|
||||
: public local_operation<TS, TI, TR>
|
||||
{
|
||||
public:
|
||||
interacting_local_operation (int mode, bool touching, bool inverse, size_t min_count, size_t max_count, bool other_is_merged);
|
||||
interacting_local_operation (int mode, bool touching, InteractingOutputMode output_mode, size_t min_count, size_t max_count, bool other_is_merged);
|
||||
|
||||
virtual db::Coord dist () const;
|
||||
virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const;
|
||||
|
|
@ -237,7 +241,7 @@ public:
|
|||
private:
|
||||
int m_mode;
|
||||
bool m_touching;
|
||||
bool m_inverse;
|
||||
InteractingOutputMode m_output_mode;
|
||||
size_t m_min_count, m_max_count;
|
||||
bool m_other_is_merged;
|
||||
};
|
||||
|
|
@ -268,7 +272,7 @@ class interacting_with_edge_local_operation
|
|||
: public local_operation<TS, TI, TR>
|
||||
{
|
||||
public:
|
||||
interacting_with_edge_local_operation (bool inverse, size_t min_count, size_t max_count, bool other_is_merged);
|
||||
interacting_with_edge_local_operation (InteractingOutputMode output_mode, size_t min_count, size_t max_count, bool other_is_merged);
|
||||
|
||||
virtual db::Coord dist () const;
|
||||
virtual void do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const;
|
||||
|
|
@ -276,7 +280,7 @@ public:
|
|||
virtual std::string description () const;
|
||||
|
||||
private:
|
||||
bool m_inverse;
|
||||
InteractingOutputMode m_output_mode;
|
||||
size_t m_min_count, m_max_count;
|
||||
bool m_other_is_merged;
|
||||
};
|
||||
|
|
@ -303,7 +307,7 @@ class interacting_with_text_local_operation
|
|||
: public local_operation<TS, TI, TR>
|
||||
{
|
||||
public:
|
||||
interacting_with_text_local_operation (bool inverse, size_t min_count, size_t max_count);
|
||||
interacting_with_text_local_operation (InteractingOutputMode output_mode, size_t min_count, size_t max_count);
|
||||
|
||||
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;
|
||||
|
|
@ -311,7 +315,7 @@ public:
|
|||
virtual std::string description () const;
|
||||
|
||||
private:
|
||||
bool m_inverse;
|
||||
InteractingOutputMode m_output_mode;
|
||||
size_t m_min_count, m_max_count;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue