First steps towards differential interaction functions

This commit is contained in:
Matthias Koefferlein 2021-02-28 23:22:44 +01:00
parent aad393d7c9
commit 8c6b231ae6
13 changed files with 394 additions and 331 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -54,6 +54,11 @@ enum OnEmptyIntruderHint {
*/
Copy,
/**
* @brief Copy the subject shape to the second result
*/
CopyToSecond,
/**
* @brief Drop the subject shape
*/

View File

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

View File

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

View File

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