From 318a462cb429990996f2f42f6659cddd389c124a Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 27 Aug 2022 21:31:40 +0200 Subject: [PATCH] WIP: first code pieces --- src/db/db/dbAsIfFlatEdges.cc | 273 +++++++++++++++++++--- src/db/db/dbAsIfFlatEdges.h | 57 ++++- src/db/db/dbDeepEdges.cc | 64 +++-- src/db/db/dbDeepEdges.h | 13 +- src/db/db/dbEdgeBoolean.h | 65 +++++- src/db/db/dbEdgeProcessor.cc | 38 +-- src/db/db/dbEdgeProcessor.h | 56 ++++- src/db/db/dbEdges.h | 236 +++++++++++++++++++ src/db/db/dbEdgesDelegate.h | 20 +- src/db/db/dbEdgesUtils.cc | 2 +- src/db/db/dbEdgesUtils.h | 21 +- src/db/db/dbEmptyEdges.h | 21 +- src/db/db/dbLocalOperation.cc | 2 +- src/db/db/dbShapeProcessor.h | 25 +- src/db/unit_tests/dbEdgeProcessorTests.cc | 4 +- 15 files changed, 790 insertions(+), 107 deletions(-) diff --git a/src/db/db/dbAsIfFlatEdges.cc b/src/db/db/dbAsIfFlatEdges.cc index 8aa9d1fae..bee4e3709 100644 --- a/src/db/db/dbAsIfFlatEdges.cc +++ b/src/db/db/dbAsIfFlatEdges.cc @@ -95,11 +95,11 @@ AsIfFlatEdges::to_string (size_t nmax) const } EdgesDelegate * -AsIfFlatEdges::selected_interacting_generic (const Region &other, bool inverse) const +AsIfFlatEdges::selected_interacting_generic (const Region &other, EdgeInteractionMode mode, bool inverse) const { // shortcuts if (other.empty () || empty ()) { - return new EmptyEdges (); + return ((mode == EdgesOutside) == inverse) ? new EmptyEdges () : clone (); } db::box_scanner2 scanner (report_progress (), progress_desc ()); @@ -120,17 +120,17 @@ AsIfFlatEdges::selected_interacting_generic (const Region &other, bool inverse) if (! inverse) { - edge_to_region_interaction_filter filter (*output); + edge_to_region_interaction_filter filter (output.get (), mode); scanner.process (filter, 1, db::box_convert (), db::box_convert ()); } else { - std::set interacting; - edge_to_region_interaction_filter > filter (interacting); + std::set result; + edge_to_region_interaction_filter > filter (&result, mode); scanner.process (filter, 1, db::box_convert (), db::box_convert ()); for (EdgesIterator o (begin_merged ()); ! o.at_end (); ++o) { - if (interacting.find (*o) == interacting.end ()) { + if (result.find (*o) == result.end ()) { output->insert (*o); } } @@ -141,8 +141,13 @@ AsIfFlatEdges::selected_interacting_generic (const Region &other, bool inverse) } EdgesDelegate * -AsIfFlatEdges::selected_interacting_generic (const Edges &edges, bool inverse) const +AsIfFlatEdges::selected_interacting_generic (const Edges &edges, EdgeInteractionMode mode, bool inverse) const { + // shortcuts + if (edges.empty () || empty ()) { + return ((mode == EdgesOutside) == inverse) ? new EmptyEdges () : clone (); + } + db::box_scanner scanner (report_progress (), progress_desc ()); AddressableEdgeDelivery e (begin_merged (), has_valid_merged_edges ()); @@ -161,17 +166,17 @@ AsIfFlatEdges::selected_interacting_generic (const Edges &edges, bool inverse) c if (! inverse) { - edge_interaction_filter filter (*output); + edge_interaction_filter filter (*output, mode); scanner.process (filter, 1, db::box_convert ()); } else { - std::set interacting; - edge_interaction_filter > filter (interacting); + std::set result; + edge_interaction_filter > filter (result, mode); scanner.process (filter, 1, db::box_convert ()); for (EdgesIterator o (begin_merged ()); ! o.at_end (); ++o) { - if (interacting.find (*o) == interacting.end ()) { + if (result.find (*o) == result.end ()) { output->insert (*o); } } @@ -181,6 +186,95 @@ AsIfFlatEdges::selected_interacting_generic (const Edges &edges, bool inverse) c return output.release (); } +std::pair +AsIfFlatEdges::selected_interacting_pair_generic (const Region ®ion, EdgeInteractionMode mode) const +{ + // shortcuts + if (region.empty () || empty ()) { + if (mode != EdgesOutside) { + return std::make_pair (new EmptyEdges (), clone ()); + } else { + return std::make_pair (clone (), new EmptyEdges ()); + } + } + + db::box_scanner2 scanner (report_progress (), progress_desc ()); + + AddressableEdgeDelivery e (begin_merged (), has_valid_merged_edges ()); + + for ( ; ! e.at_end (); ++e) { + scanner.insert1 (e.operator-> (), 0); + } + + AddressablePolygonDelivery p = region.addressable_polygons (); + + for ( ; ! p.at_end (); ++p) { + scanner.insert2 (p.operator-> (), 1); + } + + std::unique_ptr output (new FlatEdges (true)); + std::unique_ptr output2 (new FlatEdges (true)); + + std::set result; + edge_to_region_interaction_filter > filter (&result, mode); + scanner.process (filter, 1, db::box_convert (), db::box_convert ()); + + for (EdgesIterator o (begin_merged ()); ! o.at_end (); ++o) { + if (result.find (*o) == result.end ()) { + output->insert (*o); + } else { + output2->insert (*o); + } + } + + return std::make_pair (output.release (), output2.release ()); +} + +std::pair +AsIfFlatEdges::selected_interacting_pair_generic (const Edges &other, EdgeInteractionMode mode) const +{ + // shortcuts + if (other.empty () || empty ()) { + if (mode != EdgesOutside) { + return std::make_pair (new EmptyEdges (), clone ()); + } else { + return std::make_pair (clone (), new EmptyEdges ()); + } + } + + db::box_scanner scanner (report_progress (), progress_desc ()); + + AddressableEdgeDelivery e (begin_merged (), has_valid_merged_edges ()); + + for ( ; ! e.at_end (); ++e) { + scanner.insert (e.operator-> (), 0); + } + + AddressableEdgeDelivery ee = other.addressable_edges (); + + for ( ; ! ee.at_end (); ++ee) { + scanner.insert (ee.operator-> (), 1); + } + + std::unique_ptr output (new FlatEdges (true)); + std::unique_ptr output2 (new FlatEdges (true)); + + std::set results; + edge_interaction_filter > filter (results, mode); + scanner.process (filter, 1, db::box_convert ()); + + for (EdgesIterator o (begin_merged ()); ! o.at_end (); ++o) { + if (results.find (*o) == results.end ()) { + output->insert (*o); + } else { + output2->insert (*o); + } + } + + return std::make_pair (output.release (), output2.release ()); +} + + EdgesDelegate * AsIfFlatEdges::pull_generic (const Edges &edges) const { @@ -199,7 +293,7 @@ AsIfFlatEdges::pull_generic (const Edges &edges) const } std::unique_ptr output (new FlatEdges (true)); - edge_interaction_filter filter (*output); + edge_interaction_filter filter (*output, EdgesInteract); scanner.process (filter, 1, db::box_convert ()); return output.release (); @@ -229,7 +323,7 @@ AsIfFlatEdges::pull_generic (const Region &other) const std::unique_ptr output (new FlatRegion (true)); - edge_to_region_interaction_filter filter (*output); + edge_to_region_interaction_filter filter (output.get (), EdgesInteract); scanner.process (filter, 1, db::box_convert (), db::box_convert ()); return output.release (); @@ -250,27 +344,112 @@ AsIfFlatEdges::pull_interacting (const Region &other) const EdgesDelegate * AsIfFlatEdges::selected_interacting (const Edges &other) const { - return selected_interacting_generic (other, false); + return selected_interacting_generic (other, EdgesInteract, false); } EdgesDelegate * AsIfFlatEdges::selected_not_interacting (const Edges &other) const { - return selected_interacting_generic (other, true); + return selected_interacting_generic (other, EdgesInteract, true); } EdgesDelegate * AsIfFlatEdges::selected_interacting (const Region &other) const { - return selected_interacting_generic (other, false); + return selected_interacting_generic (other, EdgesInteract, false); } EdgesDelegate * AsIfFlatEdges::selected_not_interacting (const Region &other) const { - return selected_interacting_generic (other, true); + return selected_interacting_generic (other, EdgesInteract, true); } +std::pair +AsIfFlatEdges::selected_interacting_pair (const Region &other) const +{ + return selected_interacting_pair_generic (other, EdgesInteract); +} + +std::pair +AsIfFlatEdges::selected_interacting_pair (const Edges &other) const +{ + return selected_interacting_pair_generic (other, EdgesInteract); +} + +EdgesDelegate * +AsIfFlatEdges::selected_outside (const Region &other) const +{ + return selected_interacting_generic (other, EdgesOutside, false); +} + +EdgesDelegate * +AsIfFlatEdges::selected_not_outside (const Region &other) const +{ + return selected_interacting_generic (other, EdgesOutside, true); +} + +std::pair +AsIfFlatEdges::selected_outside_pair (const Region &other) const +{ + return selected_interacting_pair_generic (other, EdgesOutside); +} + +EdgesDelegate * +AsIfFlatEdges::selected_inside (const Region &other) const +{ + return selected_interacting_generic (other, EdgesInside, false); +} + +EdgesDelegate * +AsIfFlatEdges::selected_not_inside (const Region &other) const +{ + return selected_interacting_generic (other, EdgesInside, true); +} + +std::pair +AsIfFlatEdges::selected_inside_pair (const Region &other) const +{ + return selected_interacting_pair_generic (other, EdgesInside); +} + +EdgesDelegate * +AsIfFlatEdges::selected_outside (const Edges &other) const +{ + return selected_interacting_generic (other, EdgesOutside, false); +} + +EdgesDelegate * +AsIfFlatEdges::selected_not_outside (const Edges &other) const +{ + return selected_interacting_generic (other, EdgesOutside, true); +} + +std::pair +AsIfFlatEdges::selected_outside_pair (const Edges &other) const +{ + return selected_interacting_pair_generic (other, EdgesOutside); +} + +EdgesDelegate * +AsIfFlatEdges::selected_inside (const Edges &other) const +{ + return selected_interacting_generic (other, EdgesInside, false); +} + +EdgesDelegate * +AsIfFlatEdges::selected_not_inside (const Edges &other) const +{ + return selected_interacting_generic (other, EdgesInside, true); +} + +std::pair +AsIfFlatEdges::selected_inside_pair (const Edges &other) const +{ + return selected_interacting_pair_generic (other, EdgesInside); +} + + namespace { @@ -584,18 +763,50 @@ AsIfFlatEdges::boolean (const Edges *other, EdgeBoolOp op) const return output.release (); } -EdgesDelegate * -AsIfFlatEdges::edge_region_op (const Region &other, bool outside, bool include_borders) const +std::pair +AsIfFlatEdges::boolean_andnot (const Edges *other) const +{ + std::unique_ptr output (new FlatEdges (true)); + std::unique_ptr output2 (new FlatEdges (true)); + EdgeBooleanClusterCollectorToShapes cluster_collector (&output->raw_edges (), EdgeAndNot, &output2->raw_edges ()); + + db::box_scanner scanner (report_progress (), progress_desc ()); + scanner.reserve (count () + (other ? other->count () : 0)); + + AddressableEdgeDelivery e (begin (), has_valid_edges ()); + + for ( ; ! e.at_end (); ++e) { + if (! e->is_degenerate ()) { + scanner.insert (e.operator-> (), 0); + } + } + + AddressableEdgeDelivery ee; + + if (other) { + ee = other->addressable_edges (); + for ( ; ! ee.at_end (); ++ee) { + if (! ee->is_degenerate ()) { + scanner.insert (ee.operator-> (), 1); + } + } + } + + scanner.process (cluster_collector, 1, db::box_convert ()); + + return std::make_pair (output.release (), output2.release ()); +} + +std::pair +AsIfFlatEdges::edge_region_op (const Region &other, db::EdgePolygonOp::mode_t mode, bool include_borders) const { // shortcuts - if (other.empty ()) { - if (! outside) { - return new EmptyEdges (); + if (other.empty () || empty ()) { + if (mode != db::EdgePolygonOp::Outside) { + return std::make_pair (new EmptyEdges (), clone ()); } else { - return clone (); + return std::make_pair (clone (), new EmptyEdges ()); } - } else if (empty ()) { - return new EmptyEdges (); } db::EdgeProcessor ep (report_progress (), progress_desc ()); @@ -610,12 +821,18 @@ AsIfFlatEdges::edge_region_op (const Region &other, bool outside, bool include_b ep.insert (*e, 1); } + std::unique_ptr output_second; + std::unique_ptr cc_second; + if (mode == db::EdgePolygonOp::Both) { + cc_second.reset (new db::EdgeShapeGenerator (output_second->raw_edges (), true /*clear*/, 2 /*second tag*/)); + } + std::unique_ptr output (new FlatEdges (false)); - db::EdgeShapeGenerator cc (output->raw_edges (), true /*clear*/); - db::EdgePolygonOp op (outside, include_borders); + db::EdgeShapeGenerator cc (output->raw_edges (), true /*clear*/, 1 /*tag*/, cc_second.get ()); + db::EdgePolygonOp op (mode, include_borders); ep.process (cc, op); - return output.release (); + return std::make_pair (output.release (), output_second.release ()); } EdgesDelegate * diff --git a/src/db/db/dbAsIfFlatEdges.h b/src/db/db/dbAsIfFlatEdges.h index 98e93d35d..785b0a677 100644 --- a/src/db/db/dbAsIfFlatEdges.h +++ b/src/db/db/dbAsIfFlatEdges.h @@ -28,6 +28,8 @@ #include "dbBoxScanner.h" #include "dbEdgesDelegate.h" #include "dbEdgeBoolean.h" +#include "dbEdgeProcessor.h" +#include "dbEdgesUtils.h" #include "dbBoxScanner.h" #include "dbPolygonTools.h" @@ -115,19 +117,29 @@ public: return boolean (&other, EdgeAnd); } - virtual EdgesDelegate *and_with (const Region &other) const - { - return edge_region_op (other, false /*inside*/, true /*include borders*/); - } - virtual EdgesDelegate *not_with (const Edges &other) const { return boolean (&other, EdgeNot); } + virtual std::pair andnot_with (const Edges &other) const + { + return boolean_andnot (&other); + } + + virtual EdgesDelegate *and_with (const Region &other) const + { + return edge_region_op (other, db::EdgePolygonOp::Inside, true /*include borders*/).first; + } + virtual EdgesDelegate *not_with (const Region &other) const { - return edge_region_op (other, true /*outside*/, true /*include borders*/); + return edge_region_op (other, db::EdgePolygonOp::Outside, true /*include borders*/).first; + } + + virtual std::pair andnot_with (const Region &other) const + { + return edge_region_op (other, db::EdgePolygonOp::Both, true /*include borders*/); } virtual EdgesDelegate *xor_with (const Edges &other) const @@ -154,12 +166,17 @@ public: virtual EdgesDelegate *inside_part (const Region &other) const { - return edge_region_op (other, false /*inside*/, false /*don't include borders*/); + return edge_region_op (other, db::EdgePolygonOp::Inside, false /*don't include borders*/).first; } virtual EdgesDelegate *outside_part (const Region &other) const { - return edge_region_op (other, true /*outside*/, false /*don't include borders*/); + return edge_region_op (other, db::EdgePolygonOp::Outside, false /*don't include borders*/).first; + } + + virtual std::pair inside_outside_part_pair (const Region &other) const + { + return edge_region_op (other, db::EdgePolygonOp::Both, false /*don't include borders*/); } virtual RegionDelegate *extended (coord_type ext_b, coord_type ext_e, coord_type ext_o, coord_type ext_i, bool join) const; @@ -170,6 +187,21 @@ public: virtual EdgesDelegate *selected_not_interacting (const Edges &) const; virtual EdgesDelegate *selected_interacting (const Region &) const; virtual EdgesDelegate *selected_not_interacting (const Region &) const; + virtual std::pair selected_interacting_pair (const Region &other) const; + virtual std::pair selected_interacting_pair (const Edges &other) const; + + virtual EdgesDelegate *selected_outside (const Edges &other) const; + virtual EdgesDelegate *selected_not_outside (const Edges &other) const; + virtual std::pair selected_outside_pair (const Edges &other) const; + virtual EdgesDelegate *selected_inside (const Edges &other) const; + virtual EdgesDelegate *selected_not_inside (const Edges &other) const; + virtual std::pair selected_inside_pair (const Edges &other) const; + virtual EdgesDelegate *selected_outside (const Region &other) const; + virtual EdgesDelegate *selected_not_outside (const Region &other) const; + virtual std::pair selected_outside_pair (const Region &other) const; + virtual EdgesDelegate *selected_inside (const Region &other) const; + virtual EdgesDelegate *selected_not_inside (const Region &other) const; + virtual std::pair selected_inside_pair (const Region &other) const; virtual EdgesDelegate *in (const Edges &, bool) const; @@ -184,8 +216,10 @@ protected: EdgePairsDelegate *run_check (db::edge_relation_type rel, const Edges *other, db::Coord d, const EdgesCheckOptions &options) const; virtual EdgesDelegate *pull_generic (const Edges &edges) const; virtual RegionDelegate *pull_generic (const Region ®ion) const; - virtual EdgesDelegate *selected_interacting_generic (const Edges &edges, bool inverse) const; - virtual EdgesDelegate *selected_interacting_generic (const Region ®ion, bool inverse) const; + virtual EdgesDelegate *selected_interacting_generic (const Edges &edges, EdgeInteractionMode mode, bool inverse) const; + virtual std::pair selected_interacting_pair_generic (const Edges &edges, EdgeInteractionMode mode) const; + virtual EdgesDelegate *selected_interacting_generic (const Region ®ion, EdgeInteractionMode mode, bool inverse) const; + virtual std::pair selected_interacting_pair_generic (const Region ®ion, EdgeInteractionMode mode) const; AsIfFlatEdges &operator= (const AsIfFlatEdges &other); AsIfFlatEdges (const AsIfFlatEdges &other); @@ -195,7 +229,8 @@ private: virtual db::Box compute_bbox () const; EdgesDelegate *boolean (const Edges *other, EdgeBoolOp op) const; - EdgesDelegate *edge_region_op (const Region &other, bool outside, bool include_borders) const; + std::pair boolean_andnot (const Edges *other) const; + std::pair edge_region_op(const Region &other, db::EdgePolygonOp::mode_t mode, bool include_borders) const; }; } diff --git a/src/db/db/dbDeepEdges.cc b/src/db/db/dbDeepEdges.cc index b45c93f56..afd4b747f 100644 --- a/src/db/db/dbDeepEdges.cc +++ b/src/db/db/dbDeepEdges.cc @@ -930,6 +930,20 @@ EdgesDelegate *DeepEdges::not_with (const Region &other) const } } +std::pair +DeepEdges::andnot_with (const Edges &) const +{ + // @@@ + return std::pair(); +} + +std::pair +DeepEdges::andnot_with (const Region &) const +{ + // @@@ + return std::pair(); +} + EdgesDelegate *DeepEdges::xor_with (const Edges &other) const { const DeepEdges *other_deep = dynamic_cast (other.delegate ()); @@ -1057,6 +1071,12 @@ EdgesDelegate *DeepEdges::outside_part (const Region &other) const } } +std::pair DeepEdges::inside_outside_part_pair (const Region &) const +{ + // @@@ + return std::pair(); +} + RegionDelegate *DeepEdges::extended (coord_type ext_b, coord_type ext_e, coord_type ext_o, coord_type ext_i, bool join) const { const db::DeepLayer &edges = merged_deep_layer (); @@ -1157,8 +1177,8 @@ class Edge2EdgeInteractingLocalOperation : public local_operation { public: - Edge2EdgeInteractingLocalOperation (bool inverse) - : m_inverse (inverse) + Edge2EdgeInteractingLocalOperation (EdgeInteractionMode mode, bool inverse) + : m_mode (mode), m_inverse (inverse) { // .. nothing yet .. } @@ -1195,7 +1215,7 @@ public: if (m_inverse) { std::unordered_set interacting; - edge_interaction_filter > filter (interacting); + edge_interaction_filter > filter (interacting, m_mode); scanner.process (filter, 1, db::box_convert ()); for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { @@ -1207,7 +1227,7 @@ public: } else { - edge_interaction_filter > filter (result); + edge_interaction_filter > filter (result, m_mode); scanner.process (filter, 1, db::box_convert ()); } @@ -1229,6 +1249,7 @@ public: } private: + EdgeInteractionMode m_mode; bool m_inverse; }; @@ -1270,7 +1291,7 @@ public: scanner.insert (o.operator-> (), 0); } - edge_interaction_filter > filter (result); + edge_interaction_filter > filter (result, EdgesInteract); scanner.process (filter, 1, db::box_convert ()); } @@ -1290,8 +1311,8 @@ class Edge2PolygonInteractingLocalOperation : public local_operation { public: - Edge2PolygonInteractingLocalOperation (bool inverse) - : m_inverse (inverse) + Edge2PolygonInteractingLocalOperation (EdgeInteractionMode mode, bool inverse) + : m_mode (mode), m_inverse (inverse) { // .. nothing yet .. } @@ -1330,7 +1351,7 @@ public: if (m_inverse) { std::unordered_set interacting; - edge_to_region_interaction_filter > filter (interacting); + edge_to_region_interaction_filter > filter (&interacting, m_mode); scanner.process (filter, 1, db::box_convert (), db::box_convert ()); for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { @@ -1342,7 +1363,7 @@ public: } else { - edge_to_region_interaction_filter > filter (result); + edge_to_region_interaction_filter > filter (&result, m_mode); scanner.process (filter, 1, db::box_convert (), db::box_convert ()); } @@ -1363,6 +1384,7 @@ public: } private: + EdgeInteractionMode m_mode; bool m_inverse; }; @@ -1427,7 +1449,7 @@ public: } ResultInserter inserter (layout, result); - edge_to_region_interaction_filter filter (inserter); + edge_to_region_interaction_filter filter (&inserter, EdgesInteract); scanner.process (filter, 1, db::box_convert (), db::box_convert ()); } @@ -1445,7 +1467,7 @@ public: } EdgesDelegate * -DeepEdges::selected_interacting_generic (const Region &other, bool inverse) const +DeepEdges::selected_interacting_generic (const Region &other, EdgeInteractionMode mode, bool inverse) const { std::unique_ptr dr_holder; const db::DeepRegion *other_deep = dynamic_cast (other.delegate ()); @@ -1459,7 +1481,7 @@ DeepEdges::selected_interacting_generic (const Region &other, bool inverse) cons DeepLayer dl_out (edges.derived ()); - db::Edge2PolygonInteractingLocalOperation op (inverse); + db::Edge2PolygonInteractingLocalOperation op (mode, inverse); db::local_processor proc (const_cast (&edges.layout ()), const_cast (&edges.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ()); proc.set_base_verbosity (base_verbosity ()); @@ -1471,7 +1493,7 @@ DeepEdges::selected_interacting_generic (const Region &other, bool inverse) cons } EdgesDelegate * -DeepEdges::selected_interacting_generic (const Edges &other, bool inverse) const +DeepEdges::selected_interacting_generic (const Edges &other, EdgeInteractionMode mode, bool inverse) const { std::unique_ptr dr_holder; const db::DeepEdges *other_deep = dynamic_cast (other.delegate ()); @@ -1485,7 +1507,7 @@ DeepEdges::selected_interacting_generic (const Edges &other, bool inverse) const DeepLayer dl_out (edges.derived ()); - db::Edge2EdgeInteractingLocalOperation op (inverse); + db::Edge2EdgeInteractingLocalOperation op (mode, inverse); db::local_processor proc (const_cast (&edges.layout ()), const_cast (&edges.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ()); proc.set_base_verbosity (base_verbosity ()); @@ -1496,6 +1518,20 @@ DeepEdges::selected_interacting_generic (const Edges &other, bool inverse) const return new db::DeepEdges (dl_out); } +std::pair +DeepEdges::selected_interacting_pair_generic (const Edges &edges, EdgeInteractionMode mode) const +{ + // @@@ + return std::pair(); +} + +std::pair +DeepEdges::selected_interacting_pair_generic (const Region ®ion, EdgeInteractionMode mode) const +{ + // @@@ + return std::pair(); +} + RegionDelegate *DeepEdges::pull_generic (const Region &other) const { std::unique_ptr dr_holder; diff --git a/src/db/db/dbDeepEdges.h b/src/db/db/dbDeepEdges.h index f00913540..a39eb4a60 100644 --- a/src/db/db/dbDeepEdges.h +++ b/src/db/db/dbDeepEdges.h @@ -133,10 +133,12 @@ public: virtual EdgesDelegate *merged () const; virtual EdgesDelegate *and_with (const Edges &other) const; - virtual EdgesDelegate *and_with (const Region &other) const; - virtual EdgesDelegate *not_with (const Edges &other) const; + virtual std::pair andnot_with (const Edges &) const; + + virtual EdgesDelegate *and_with (const Region &other) const; virtual EdgesDelegate *not_with (const Region &other) const; + virtual std::pair andnot_with (const Region &) const; virtual EdgesDelegate *xor_with (const Edges &other) const; @@ -149,6 +151,7 @@ public: virtual EdgesDelegate *inside_part (const Region &other) const; virtual EdgesDelegate *outside_part (const Region &other) const; + virtual std::pair inside_outside_part_pair (const Region &) const; virtual RegionDelegate *extended (coord_type ext_b, coord_type ext_e, coord_type ext_o, coord_type ext_i, bool join) const; @@ -183,8 +186,10 @@ private: EdgePairsDelegate *run_check (db::edge_relation_type rel, const Edges *other, db::Coord d, const db::EdgesCheckOptions &options) const; virtual EdgesDelegate *pull_generic (const Edges &edges) const; virtual RegionDelegate *pull_generic (const Region ®ion) const; - virtual EdgesDelegate *selected_interacting_generic (const Edges &edges, bool invert) const; - virtual EdgesDelegate *selected_interacting_generic (const Region ®ion, bool invert) const; + virtual EdgesDelegate *selected_interacting_generic (const Edges &edges, EdgeInteractionMode mode, bool inverse) const; + virtual std::pair selected_interacting_pair_generic (const Edges &edges, EdgeInteractionMode mode) const; + virtual EdgesDelegate *selected_interacting_generic (const Region ®ion, EdgeInteractionMode mode, bool inverse) const; + virtual std::pair selected_interacting_pair_generic (const Region ®ion, EdgeInteractionMode mode) const; DeepEdges *apply_filter (const EdgeFilterBase &filter) const; template OutputContainer *processed_impl (const edge_processor &filter) const; diff --git a/src/db/db/dbEdgeBoolean.h b/src/db/db/dbEdgeBoolean.h index 1e258104d..d09c20b29 100644 --- a/src/db/db/dbEdgeBoolean.h +++ b/src/db/db/dbEdgeBoolean.h @@ -36,7 +36,7 @@ namespace db /** * @brief A common definition for the boolean operations available on edges */ -enum EdgeBoolOp { EdgeOr, EdgeNot, EdgeXor, EdgeAnd, EdgeIntersections }; +enum EdgeBoolOp { EdgeOr, EdgeNot, EdgeXor, EdgeAnd, EdgeIntersections, EdgeAndNot /*not always supported*/ }; struct OrJoinOp { @@ -87,7 +87,13 @@ struct EdgeBooleanCluster typedef db::Edge::coord_type coord_type; EdgeBooleanCluster (OutputContainer *output, EdgeBoolOp op) - : mp_output (output), m_op (op) + : mp_output (output), mp_output2 (0), m_op (op) + { + // .. nothing yet .. + } + + EdgeBooleanCluster (OutputContainer *output, OutputContainer *output2, EdgeBoolOp op) + : mp_output (output), mp_output2 (output2), m_op (op) { // .. nothing yet .. } @@ -99,11 +105,13 @@ struct EdgeBooleanCluster // shortcut for single edge if (begin () + 1 == end ()) { if (begin ()->second == 0) { - if (m_op != EdgeAnd) { + if (m_op == EdgeAndNot) { + mp_output2->insert (*(begin ()->first)); + } else if (m_op != EdgeAnd) { mp_output->insert (*(begin ()->first)); } } else { - if (m_op != EdgeAnd && m_op != EdgeNot) { + if (m_op != EdgeAnd && m_op != EdgeNot && m_op != EdgeAndNot) { mp_output->insert (*(begin ()->first)); } } @@ -174,19 +182,34 @@ struct EdgeBooleanCluster if (b.begin () == b.end ()) { // optimize for empty b - if (m_op != EdgeAnd) { + OutputContainer *oc = 0; + if (m_op == EdgeAndNot) { + oc = mp_output; + } else if (m_op != EdgeAnd) { + oc = mp_output; + } + + if (oc) { for (tl::interval_map::const_iterator ib = b.begin (); ib != b.end (); ++ib) { if (ib->second > 0) { - mp_output->insert (db::Edge (p1 + db::Vector (d * (ib->first.first * n)), p1 + db::Vector (d * (ib->first.second * n)))); + oc->insert (db::Edge (p1 + db::Vector (d * (ib->first.first * n)), p1 + db::Vector (d * (ib->first.second * n)))); } else if (ib->second < 0) { - mp_output->insert (db::Edge (p1 + db::Vector (d * (ib->first.second * n)), p1 + db::Vector (d * (ib->first.first * n)))); + oc->insert (db::Edge (p1 + db::Vector (d * (ib->first.second * n)), p1 + db::Vector (d * (ib->first.first * n)))); } } } } else { - if (m_op == EdgeAnd) { + tl::interval_map q2; + + if (m_op == EdgeAnd || m_op == EdgeAndNot) { + if (m_op == EdgeAndNot) { + q2 = q; + for (tl::interval_map::const_iterator ib = b.begin (); ib != b.end (); ++ib) { + q2.add (ib->first.first, ib->first.second, ib->second, not_jop); + } + } for (tl::interval_map::const_iterator ib = b.begin (); ib != b.end (); ++ib) { q.add (ib->first.first, ib->first.second, ib->second, and_jop); } @@ -208,12 +231,20 @@ struct EdgeBooleanCluster } } + for (tl::interval_map::const_iterator iq = q2.begin (); iq != q2.end (); ++iq) { + if (iq->second > 0) { + mp_output2->insert (db::Edge (p1 + db::Vector (d * (iq->first.first * n)), p1 + db::Vector (d * (iq->first.second * n)))); + } else if (iq->second < 0) { + mp_output2->insert (db::Edge (p1 + db::Vector (d * (iq->first.second * n)), p1 + db::Vector (d * (iq->first.first * n)))); + } + } + } } private: - OutputContainer *mp_output; + OutputContainer *mp_output, *mp_output2; db::EdgeBoolOp m_op; }; @@ -221,8 +252,8 @@ template struct EdgeBooleanClusterCollector : public db::cluster_collector > { - EdgeBooleanClusterCollector (OutputContainer *output, EdgeBoolOp op) - : db::cluster_collector > (EdgeBooleanCluster (output, op == EdgeIntersections ? EdgeAnd : op), op != EdgeAnd && op != EdgeIntersections /*report single*/), + EdgeBooleanClusterCollector (OutputContainer *output, EdgeBoolOp op, OutputContainer *output2 = 0) + : db::cluster_collector > (EdgeBooleanCluster (output, output2, op == EdgeIntersections ? EdgeAnd : op), op != EdgeAnd && op != EdgeIntersections /*report single*/), mp_output (output), mp_intersections (op == EdgeIntersections ? output : 0) { // .. nothing yet .. @@ -377,6 +408,12 @@ public: typedef Iterator const_iterator; + ShapesToOutputContainerAdaptor () + : mp_shapes (0) + { + // .. nothing yet .. + } + ShapesToOutputContainerAdaptor (db::Shapes &shapes) : mp_shapes (&shapes) { @@ -413,8 +450,14 @@ struct DB_PUBLIC EdgeBooleanClusterCollectorToShapes { } + EdgeBooleanClusterCollectorToShapes (db::Shapes *output, EdgeBoolOp op, db::Shapes *output2) + : EdgeBooleanClusterCollector (&m_adaptor, op, &m_adaptor2), m_adaptor (*output), m_adaptor2 (*output2) + { + } + private: ShapesToOutputContainerAdaptor m_adaptor; + ShapesToOutputContainerAdaptor m_adaptor2; }; } diff --git a/src/db/db/dbEdgeProcessor.cc b/src/db/db/dbEdgeProcessor.cc index e5d75c16e..1a8115b65 100644 --- a/src/db/db/dbEdgeProcessor.cc +++ b/src/db/db/dbEdgeProcessor.cc @@ -560,8 +560,8 @@ private: // ------------------------------------------------------------------------------- // EdgePolygonOp implementation -EdgePolygonOp::EdgePolygonOp (bool outside, bool include_touching, int polygon_mode) - : m_outside (outside), m_include_touching (include_touching), +EdgePolygonOp::EdgePolygonOp (EdgePolygonOp::mode_t mode, bool include_touching, int polygon_mode) + : m_mode (mode), m_include_touching (include_touching), m_function (polygon_mode), m_wcp_n (0), m_wcp_s (0) { @@ -572,27 +572,30 @@ void EdgePolygonOp::reset () m_wcp_n = m_wcp_s = 0; } -bool EdgePolygonOp::select_edge (bool horizontal, property_type p) +int EdgePolygonOp::select_edge (bool horizontal, property_type p) { if (p == 0) { + return 0; + } - return false; + bool inside; - } else if (horizontal) { - - bool res; + if (horizontal) { if (m_include_touching) { - res = (m_function (m_wcp_n) || m_function (m_wcp_s)); + inside = (m_function (m_wcp_n) || m_function (m_wcp_s)); } else { - res = (m_function (m_wcp_n) && m_function (m_wcp_s)); + inside = (m_function (m_wcp_n) && m_function (m_wcp_s)); } - - return m_outside ? !res : res; - } else { + inside = m_function (m_wcp_n); + } - return m_outside ? !m_function (m_wcp_n) : m_function (m_wcp_n); - + if (m_mode == Inside) { + return inside ? 1 : 0; + } else if (m_mode == Outside) { + return inside ? 0 : 1; + } else { + return inside ? 1 : 2; } } @@ -1705,10 +1708,11 @@ public: void select_edge (const WorkEdge &e) { - if (mp_op->select_edge (e.dy () == 0, e.prop)) { - mp_es->put (e); + int tag = mp_op->select_edge (e.dy () == 0, e.prop); + if (tag > 0) { + mp_es->put (e, (unsigned int) tag); #ifdef DEBUG_EDGE_PROCESSOR - printf ("put(%s)\n", e.to_string().c_str()); + printf ("put(%s, %d)\n", e.to_string().c_str(), tag); #endif } } diff --git a/src/db/db/dbEdgeProcessor.h b/src/db/db/dbEdgeProcessor.h index be7916479..870466046 100644 --- a/src/db/db/dbEdgeProcessor.h +++ b/src/db/db/dbEdgeProcessor.h @@ -87,6 +87,15 @@ public: */ virtual void put (const db::Edge &) { } + /** + * @brief Deliver a tagged edge + * + * This method delivers an edge that ends or starts at the current scanline. + * This version includes a tag which is generated when using "select_edge". + * A tag is a value > 0 returned by "select_edge". + */ + virtual void put (const db::Edge &, int /*tag*/) { } + /** * @brief Deliver an edge that crosses the scanline * @@ -130,15 +139,15 @@ public: /** * @brief Constructor connecting this receiver to an external edge vector */ - EdgeContainer (std::vector &edges, bool clear = false) - : EdgeSink (), mp_edges (&edges), m_clear (clear) + EdgeContainer (std::vector &edges, bool clear = false, int tag = 0, EdgeContainer *chained = 0) + : EdgeSink (), mp_edges (&edges), m_clear (clear), m_tag (tag), mp_chained (chained) { } /** * @brief Constructor using an internal edge vector */ - EdgeContainer () - : EdgeSink (), mp_edges (&m_edges), m_clear (false) + EdgeContainer (int tag = 0, EdgeContainer *chained = 0) + : EdgeSink (), mp_edges (&m_edges), m_clear (false), m_tag (tag), mp_chained (chained) { } /** @@ -167,6 +176,9 @@ public: // The single-shot scheme is a easy way to overcome problems with multiple start/flush brackets (i.e. on size filter) m_clear = false; } + if (mp_chained) { + mp_chained->start (); + } } /** @@ -175,12 +187,30 @@ public: virtual void put (const db::Edge &e) { mp_edges->push_back (e); + if (mp_chained) { + mp_chained->put (e); + } + } + + /** + * @brief Implementation of the EdgeSink interface + */ + virtual void put (const db::Edge &e, int tag) + { + if (m_tag == 0 || tag == m_tag) { + mp_edges->push_back (e); + } + if (mp_chained) { + mp_chained->put (e, tag); + } } private: std::vector m_edges; std::vector *mp_edges; bool m_clear; + int m_tag; + EdgeContainer *mp_chained; }; /** @@ -204,7 +234,7 @@ public: virtual void reset () { } virtual void reserve (size_t /*n*/) { } virtual int edge (bool /*north*/, bool /*enter*/, property_type /*p*/) { return 0; } - virtual bool select_edge (bool /*horizontal*/, property_type /*p*/) { return false; } + virtual int select_edge (bool /*horizontal*/, property_type /*p*/) { return 0; } virtual int compare_ns () const { return 0; } virtual bool is_reset () const { return false; } virtual bool prefer_touch () const { return false; } @@ -491,6 +521,15 @@ class DB_PUBLIC EdgePolygonOp : public db::EdgeEvaluatorBase { public: + /** + * @brief The operation mode + */ + enum mode_t { + Inside = 0, // Selects inside edges + Outside = 1, // Selects outside edges + Both = 2 // Selects both (inside -> tag #1, outside -> tag #2) + }; + /** * @brief Constructor * @@ -498,17 +537,18 @@ public: * @param include_touching If true, edges on the polygon's border will be considered "inside" of polygons * @param polygon_mode Determines how the polygon edges on property 0 are interpreted (see merge operators) */ - EdgePolygonOp (bool outside = false, bool include_touching = true, int polygon_mode = -1); + EdgePolygonOp (mode_t mode = Inside, bool include_touching = true, int polygon_mode = -1); virtual void reset (); - virtual bool select_edge (bool horizontal, property_type p); + virtual int select_edge (bool horizontal, property_type p); virtual int edge (bool north, bool enter, property_type p); virtual bool is_reset () const; virtual bool prefer_touch () const; virtual bool selects_edges () const; private: - bool m_outside, m_include_touching; + mode_t m_mode; + bool m_include_touching; db::ParametrizedInsideFunc m_function; int m_wcp_n, m_wcp_s; }; diff --git a/src/db/db/dbEdges.h b/src/db/db/dbEdges.h index 77bc25801..828649714 100644 --- a/src/db/db/dbEdges.h +++ b/src/db/db/dbEdges.h @@ -1037,6 +1037,242 @@ public: return Edges (mp_delegate->selected_not_interacting (other)); } + /** + * @brief Selects all edges of this edge collection which are completely outside polygons from the region + * + * Merged semantics applies. + */ + Edges &select_outside (const Region &other) + { + set_delegate (mp_delegate->selected_outside (other)); + return *this; + } + + /** + * @brief Selects all edges of this edge collection which are not completely outside polygons from the region + * + * Merged semantics applies. + */ + Edges &select_not_outside (const Region &other) + { + set_delegate (mp_delegate->selected_not_outside (other)); + return *this; + } + + /** + * @brief Returns all edges of this edge collection which are completely outside polygons from the region + * + * This method is an out-of-place version of select_outside. + * + * Merged semantics applies. + */ + Edges selected_outside (const Region &other) const + { + return Edges (mp_delegate->selected_outside (other)); + } + + /** + * @brief Returns all edges of this edge collection which are not completely outside polygons from the region + * + * This method is an out-of-place version of select_not_outside. + * + * Merged semantics applies. + */ + Edges selected_not_outside (const Region &other) const + { + return Edges (mp_delegate->selected_not_outside (other)); + } + + /** + * @brief Returns all edges of this which are completely outside polygons from the region and the opposite ones at the same time + * + * This method is equivalent to calling selected_outside and selected_not_outside, but faster. + * + * Merged semantics applies. + */ + std::pair selected_outside_differential (const Region &other) const + { + std::pair p = mp_delegate->selected_outside_pair (other); + return std::pair (Edges (p.first), Edges (p.second)); + } + + /** + * @brief Selects all edges of this edge collection which are completely inside polygons from the region + * + * Merged semantics applies. + */ + Edges &select_inside (const Region &other) + { + set_delegate (mp_delegate->selected_inside (other)); + return *this; + } + + /** + * @brief Selects all edges of this edge collection which are not completely inside polygons from the region + * + * Merged semantics applies. + */ + Edges &select_not_inside (const Region &other) + { + set_delegate (mp_delegate->selected_not_inside (other)); + return *this; + } + + /** + * @brief Returns all edges of this which are completely inside polygons from the region + * + * This method is an out-of-place version of select_inside. + * + * Merged semantics applies. + */ + Edges selected_inside (const Region &other) const + { + return Edges (mp_delegate->selected_inside (other)); + } + + /** + * @brief Returns all edges of this which are not completely inside polygons from the region + * + * This method is an out-of-place version of select_not_inside. + * + * Merged semantics applies. + */ + Edges selected_not_inside (const Region &other) const + { + return Edges (mp_delegate->selected_not_inside (other)); + } + + /** + * @brief Returns all edges of this which are completely inside polygons from the region and the opposite ones at the same time + * + * This method is equivalent to calling selected_inside and selected_not_inside, but faster. + * + * Merged semantics applies. + */ + std::pair selected_inside_differential (const Region &other) const + { + std::pair p = mp_delegate->selected_inside_pair (other); + return std::pair (Edges (p.first), Edges (p.second)); + } + + /** + * @brief Selects all edges of this edge collection which are completely outside edges from the other edge collection + * + * Merged semantics applies. + */ + Edges &select_outside (const Edges &other) + { + set_delegate (mp_delegate->selected_outside (other)); + return *this; + } + + /** + * @brief Selects all edges of this edge collection which are not completely outside edges from the other edge collection + * + * Merged semantics applies. + */ + Edges &select_not_outside (const Edges &other) + { + set_delegate (mp_delegate->selected_not_outside (other)); + return *this; + } + + /** + * @brief Returns all edges of this edge collection which are completely outside edges from the other edge collection + * + * This method is an out-of-place version of select_outside. + * + * Merged semantics applies. + */ + Edges selected_outside (const Edges &other) const + { + return Edges (mp_delegate->selected_outside (other)); + } + + /** + * @brief Returns all edges of this edge collection which are not completely outside edges from the other edge collection + * + * This method is an out-of-place version of select_not_outside. + * + * Merged semantics applies. + */ + Edges selected_not_outside (const Edges &other) const + { + return Edges (mp_delegate->selected_not_outside (other)); + } + + /** + * @brief Returns all edges of this which are completely outside edges from the other edge collection and the opposite ones at the same time + * + * This method is equivalent to calling selected_outside and selected_not_outside, but faster. + * + * Merged semantics applies. + */ + std::pair selected_outside_differential (const Edges &other) const + { + std::pair p = mp_delegate->selected_outside_pair (other); + return std::pair (Edges (p.first), Edges (p.second)); + } + + /** + * @brief Selects all edges of this edge collection which are completely inside edges from the other edge collection + * + * Merged semantics applies. + */ + Edges &select_inside (const Edges &other) + { + set_delegate (mp_delegate->selected_inside (other)); + return *this; + } + + /** + * @brief Selects all edges of this edge collection which are not completely inside edges from the other edge collection + * + * Merged semantics applies. + */ + Edges &select_not_inside (const Edges &other) + { + set_delegate (mp_delegate->selected_not_inside (other)); + return *this; + } + + /** + * @brief Returns all edges of this which are completely inside edgess from the other edge collection + * + * This method is an out-of-place version of select_inside. + * + * Merged semantics applies. + */ + Edges selected_inside (const Edges &other) const + { + return Edges (mp_delegate->selected_inside (other)); + } + + /** + * @brief Returns all edges of this which are not completely inside edges from the other edge collection + * + * This method is an out-of-place version of select_not_inside. + * + * Merged semantics applies. + */ + Edges selected_not_inside (const Edges &other) const + { + return Edges (mp_delegate->selected_not_inside (other)); + } + + /** + * @brief Returns all edges of this which are completely inside edges from the other edge collection and the opposite ones at the same time + * + * This method is equivalent to calling selected_inside and selected_not_inside, but faster. + * + * Merged semantics applies. + */ + std::pair selected_inside_differential (const Edges &other) const + { + std::pair p = mp_delegate->selected_inside_pair (other); + return std::pair (Edges (p.first), Edges (p.second)); + } + /** * @brief Selects all edges of this edge set which overlap or touch with edges from the other edge set * diff --git a/src/db/db/dbEdgesDelegate.h b/src/db/db/dbEdgesDelegate.h index d33084df5..59a595f4b 100644 --- a/src/db/db/dbEdgesDelegate.h +++ b/src/db/db/dbEdgesDelegate.h @@ -294,9 +294,11 @@ public: virtual EdgesDelegate *merged () const = 0; virtual EdgesDelegate *and_with (const Edges &other) const = 0; - virtual EdgesDelegate *and_with (const Region &other) const = 0; virtual EdgesDelegate *not_with (const Edges &other) const = 0; + virtual std::pair andnot_with (const Edges &) const = 0; + virtual EdgesDelegate *and_with (const Region &other) const = 0; virtual EdgesDelegate *not_with (const Region &other) const = 0; + virtual std::pair andnot_with (const Region &) const = 0; virtual EdgesDelegate *xor_with (const Edges &other) const = 0; virtual EdgesDelegate *or_with (const Edges &other) const = 0; virtual EdgesDelegate *add_in_place (const Edges &other) = 0; @@ -307,12 +309,28 @@ public: virtual EdgesDelegate *inside_part (const Region &other) const = 0; virtual EdgesDelegate *outside_part (const Region &other) const = 0; + virtual std::pair inside_outside_part_pair (const Region &other) const = 0; virtual RegionDelegate *pull_interacting (const Region &) const = 0; virtual EdgesDelegate *pull_interacting (const Edges &) const = 0; virtual EdgesDelegate *selected_interacting (const Region &other) const = 0; virtual EdgesDelegate *selected_not_interacting (const Region &other) const = 0; virtual EdgesDelegate *selected_interacting (const Edges &other) const = 0; virtual EdgesDelegate *selected_not_interacting (const Edges &other) const = 0; + virtual std::pair selected_interacting_pair (const Region &other) const = 0; + virtual std::pair selected_interacting_pair (const Edges &other) const = 0; + + virtual EdgesDelegate *selected_outside (const Region &other) const = 0; + virtual EdgesDelegate *selected_not_outside (const Region &other) const = 0; + virtual std::pair selected_outside_pair (const Region &other) const = 0; + virtual EdgesDelegate *selected_inside (const Region &other) const = 0; + virtual EdgesDelegate *selected_not_inside (const Region &other) const = 0; + virtual std::pair selected_inside_pair (const Region &other) const = 0; + virtual EdgesDelegate *selected_outside (const Edges &other) const = 0; + virtual EdgesDelegate *selected_not_outside (const Edges &other) const = 0; + virtual std::pair selected_outside_pair (const Edges &other) const = 0; + virtual EdgesDelegate *selected_inside (const Edges &other) const = 0; + virtual EdgesDelegate *selected_not_inside (const Edges &other) const = 0; + virtual std::pair selected_inside_pair (const Edges &other) const = 0; virtual EdgesDelegate *in (const Edges &other, bool invert) const = 0; diff --git a/src/db/db/dbEdgesUtils.cc b/src/db/db/dbEdgesUtils.cc index add511f2e..8210a988e 100644 --- a/src/db/db/dbEdgesUtils.cc +++ b/src/db/db/dbEdgesUtils.cc @@ -177,7 +177,7 @@ extended_edge (const db::Edge &edge, db::Coord ext_b, db::Coord ext_e, db::Coord // ------------------------------------------------------------------------------------------------------------- // EdgeSegmentSelector processor -EdgeSegmentSelector::EdgeSegmentSelector (int mode, db::Edges::length_type length, double fraction) +EdgeSegmentSelector::EdgeSegmentSelector (int mode, Edge::distance_type length, double fraction) : m_mode (mode), m_length (length), m_fraction (fraction) { } diff --git a/src/db/db/dbEdgesUtils.h b/src/db/db/dbEdgesUtils.h index 666581358..96b1a7ac5 100644 --- a/src/db/db/dbEdgesUtils.h +++ b/src/db/db/dbEdgesUtils.h @@ -34,6 +34,11 @@ namespace db { +/** + * @brief The operation mode for the interaction filters + */ +enum EdgeInteractionMode { EdgesInteract, EdgesInside, EdgesOutside }; + class PolygonSink; /** @@ -249,8 +254,8 @@ class edge_interaction_filter : public db::box_scanner_receiver { public: - edge_interaction_filter (OutputContainer &output) - : mp_output (&output) + edge_interaction_filter (OutputContainer &output, EdgeInteractionMode mode) + : mp_output (&output), m_mode (mode) { // .. nothing yet .. } @@ -261,6 +266,7 @@ public: if (p1 != p2) { const db::Edge *o = p1 > p2 ? o2 : o1; const db::Edge *oo = p1 > p2 ? o1 : o2; + // @@@ if (o->intersect (*oo)) { if (m_seen.insert (o).second) { mp_output->insert (*o); @@ -272,6 +278,7 @@ public: private: OutputContainer *mp_output; std::set m_seen; + EdgeInteractionMode m_mode; }; /** @@ -288,8 +295,8 @@ class edge_to_region_interaction_filter : public db::box_scanner_receiver2 { public: - edge_to_region_interaction_filter (OutputContainer &output) - : mp_output (&output) + edge_to_region_interaction_filter (OutputContainer *output, EdgeInteractionMode mode) + : mp_output (output), m_mode (mode) { // .. nothing yet .. } @@ -300,6 +307,7 @@ public: tl::select (ep, e, p); if (m_seen.find (ep) == m_seen.end ()) { + // @@@ if (db::interact (*p, *e)) { m_seen.insert (ep); mp_output->insert (*ep); @@ -310,6 +318,7 @@ public: private: OutputContainer *mp_output; std::set m_seen; + EdgeInteractionMode m_mode; }; /** @@ -407,7 +416,7 @@ class DB_PUBLIC EdgeSegmentSelector : public EdgeProcessorBase { public: - EdgeSegmentSelector (int mode, db::Edges::length_type length, double fraction); + EdgeSegmentSelector (int mode, Edge::distance_type length, double fraction); ~EdgeSegmentSelector (); virtual void process (const db::Edge &edge, std::vector &res) const; @@ -420,7 +429,7 @@ public: private: int m_mode; - db::Edges::length_type m_length; + db::Edge::distance_type m_length; double m_fraction; db::MagnificationReducer m_vars; }; diff --git a/src/db/db/dbEmptyEdges.h b/src/db/db/dbEmptyEdges.h index a58f5d374..569eada56 100644 --- a/src/db/db/dbEmptyEdges.h +++ b/src/db/db/dbEmptyEdges.h @@ -75,9 +75,11 @@ public: virtual EdgesDelegate *merged () const { return new EmptyEdges (); } virtual EdgesDelegate *and_with (const Edges &) const { return new EmptyEdges (); } - virtual EdgesDelegate *and_with (const Region &) const { return new EmptyEdges (); } virtual EdgesDelegate *not_with (const Edges &) const { return new EmptyEdges (); } + virtual std::pair andnot_with (const Edges &) const { return std::make_pair (new EmptyEdges (), new EmptyEdges ()); } + virtual EdgesDelegate *and_with (const Region &) const { return new EmptyEdges (); } virtual EdgesDelegate *not_with (const Region &) const { return new EmptyEdges (); } + virtual std::pair andnot_with (const Region &) const { return std::make_pair (new EmptyEdges (), new EmptyEdges ()); } virtual EdgesDelegate *xor_with (const Edges &other) const; virtual EdgesDelegate *or_with (const Edges &other) const; virtual EdgesDelegate *add_in_place (const Edges &other); @@ -88,12 +90,29 @@ public: virtual EdgesDelegate *inside_part (const Region &) const { return new EmptyEdges (); } virtual EdgesDelegate *outside_part (const Region &) const { return new EmptyEdges (); } + virtual std::pair inside_outside_part_pair (const Region &) const { return std::make_pair (new EmptyEdges (), new EmptyEdges ()); } + virtual RegionDelegate *pull_interacting (const Region &) const; virtual EdgesDelegate *pull_interacting (const Edges &) const { return new EmptyEdges (); } virtual EdgesDelegate *selected_interacting (const Edges &) const { return new EmptyEdges (); } virtual EdgesDelegate *selected_not_interacting (const Edges &) const { return new EmptyEdges (); } virtual EdgesDelegate *selected_interacting (const Region &) const { return new EmptyEdges (); } virtual EdgesDelegate *selected_not_interacting (const Region &) const { return new EmptyEdges (); } + virtual std::pair selected_interacting_pair (const Region &) const { return std::make_pair (new EmptyEdges (), new EmptyEdges ()); } + virtual std::pair selected_interacting_pair (const Edges &) const { return std::make_pair (new EmptyEdges (), new EmptyEdges ()); } + + virtual EdgesDelegate *selected_outside (const Region &) const { return new EmptyEdges (); } + virtual EdgesDelegate *selected_not_outside (const Region &) const { return new EmptyEdges (); } + virtual std::pair selected_outside_pair (const Region &) const { return std::make_pair (new EmptyEdges (), new EmptyEdges ()); } + virtual EdgesDelegate *selected_inside (const Region &) const { return new EmptyEdges (); } + virtual EdgesDelegate *selected_not_inside (const Region &) const { return new EmptyEdges (); } + virtual std::pair selected_inside_pair (const Region &) const { return std::make_pair (new EmptyEdges (), new EmptyEdges ()); } + virtual EdgesDelegate *selected_outside (const Edges &) const { return new EmptyEdges (); } + virtual EdgesDelegate *selected_not_outside (const Edges &) const { return new EmptyEdges (); } + virtual std::pair selected_outside_pair (const Edges &) const { return std::make_pair (new EmptyEdges (), new EmptyEdges ()); } + virtual EdgesDelegate *selected_inside (const Edges &) const { return new EmptyEdges (); } + virtual EdgesDelegate *selected_not_inside (const Edges &) const { return new EmptyEdges (); } + virtual std::pair selected_inside_pair (const Edges &) const { return std::make_pair (new EmptyEdges (), new EmptyEdges ()); } virtual EdgesDelegate *in (const Edges &, bool) const { return new EmptyEdges (); } diff --git a/src/db/db/dbLocalOperation.cc b/src/db/db/dbLocalOperation.cc index 4c5f8d392..f7b9b8651 100644 --- a/src/db/db/dbLocalOperation.cc +++ b/src/db/db/dbLocalOperation.cc @@ -475,7 +475,7 @@ EdgeToPolygonLocalOperation::do_compute_local (db::Layout * /*layout*/, const sh } db::EdgeToEdgeSetGenerator cc (result); - db::EdgePolygonOp op (m_outside, m_include_borders); + db::EdgePolygonOp op (m_outside ? db::EdgePolygonOp::Outside : db::EdgePolygonOp::Inside, m_include_borders); ep.process (cc, op); } diff --git a/src/db/db/dbShapeProcessor.h b/src/db/db/dbShapeProcessor.h index 8030054e4..eac1b9ed0 100644 --- a/src/db/db/dbShapeProcessor.h +++ b/src/db/db/dbShapeProcessor.h @@ -105,8 +105,8 @@ public: * * @param clear_shapes If true, the shapes container is cleared on the start event. */ - EdgeShapeGenerator (db::Shapes &shapes, bool clear_shapes = false) - : EdgeSink (), mp_shapes (&shapes), m_clear_shapes (clear_shapes) + EdgeShapeGenerator (db::Shapes &shapes, bool clear_shapes = false, int tag = 0, EdgeShapeGenerator *chained = 0) + : EdgeSink (), mp_shapes (&shapes), m_clear_shapes (clear_shapes), m_tag (tag), mp_chained (chained) { } /** @@ -115,6 +115,22 @@ public: virtual void put (const db::Edge &edge) { mp_shapes->insert (edge); + if (mp_chained) { + mp_chained->put (edge); + } + } + + /** + * @brief Implementation of the EdgeSink interface + */ + virtual void put (const db::Edge &edge, int tag) + { + if (m_tag == 0 || m_tag == tag) { + mp_shapes->insert (edge); + } + if (mp_chained) { + mp_chained->put (edge, tag); + } } /** @@ -127,11 +143,16 @@ public: // The single-shot scheme is a easy way to overcome problems with multiple start/flush brackets (i.e. on size filter) m_clear_shapes = false; } + if (mp_chained) { + mp_chained->start (); + } } private: db::Shapes *mp_shapes; bool m_clear_shapes; + int m_tag; + EdgeShapeGenerator *mp_chained; }; /** diff --git a/src/db/unit_tests/dbEdgeProcessorTests.cc b/src/db/unit_tests/dbEdgeProcessorTests.cc index 8847cc6fd..b7230a86d 100644 --- a/src/db/unit_tests/dbEdgeProcessorTests.cc +++ b/src/db/unit_tests/dbEdgeProcessorTests.cc @@ -2051,7 +2051,7 @@ TEST(32) std::vector out; db::EdgeContainer ec (out); - db::EdgePolygonOp op (false, false /*not including touch*/); + db::EdgePolygonOp op (db::EdgePolygonOp::Inside, false /*not including touch*/); ep.process (ec, op); @@ -2114,7 +2114,7 @@ TEST(33) std::vector out; db::EdgeContainer ec (out); - db::EdgePolygonOp op (true, true /*including touch*/); + db::EdgePolygonOp op (db::EdgePolygonOp::Outside, true /*including touch*/); ep.process (ec, op);