diff --git a/src/db/db/dbAsIfFlatEdgePairs.cc b/src/db/db/dbAsIfFlatEdgePairs.cc index fc087ffa8..5a28a1ae9 100644 --- a/src/db/db/dbAsIfFlatEdgePairs.cc +++ b/src/db/db/dbAsIfFlatEdgePairs.cc @@ -226,6 +226,16 @@ AsIfFlatEdgePairs::processed_to_edges (const EdgePairToEdgeProcessorBase &filter return edges.release (); } +static void +insert_ep (FlatEdgePairs *dest, const db::EdgePair &ep, db::properties_id_type prop_id) +{ + if (prop_id != 0) { + dest->insert (db::EdgePairWithProperties (ep, prop_id)); + } else { + dest->insert (ep); + } +} + EdgePairsDelegate * AsIfFlatEdgePairs::filtered (const EdgePairFilterBase &filter) const { @@ -234,18 +244,28 @@ AsIfFlatEdgePairs::filtered (const EdgePairFilterBase &filter) const for (EdgePairsIterator p (begin ()); ! p.at_end (); ++p) { if (filter.selected (*p)) { - db::properties_id_type prop_id = pm (p.prop_id ()); - if (prop_id != 0) { - new_edge_pairs->insert (db::EdgePairWithProperties (*p, prop_id)); - } else { - new_edge_pairs->insert (*p); - } + insert_ep (new_edge_pairs.get (), *p, pm (p.prop_id ())); } } return new_edge_pairs.release (); } +std::pair +AsIfFlatEdgePairs::filtered_pair (const EdgePairFilterBase &filter) const +{ + std::unique_ptr new_edge_pairs_true (new FlatEdgePairs ()); + std::unique_ptr new_edge_pairs_false (new FlatEdgePairs ()); + db::PropertyMapper pm (new_edge_pairs_true->properties_repository (), properties_repository ()); + + for (EdgePairsIterator p (begin ()); ! p.at_end (); ++p) { + FlatEdgePairs *dest = filter.selected (*p) ? new_edge_pairs_true.get () : new_edge_pairs_false.get (); + insert_ep (dest, *p, pm (p.prop_id ())); + } + + return std::make_pair (new_edge_pairs_true.release (), new_edge_pairs_false.release ()); +} + RegionDelegate * AsIfFlatEdgePairs::pull_interacting (const Region &other) const { diff --git a/src/db/db/dbAsIfFlatEdgePairs.h b/src/db/db/dbAsIfFlatEdgePairs.h index 9a251dccb..c437fb79f 100644 --- a/src/db/db/dbAsIfFlatEdgePairs.h +++ b/src/db/db/dbAsIfFlatEdgePairs.h @@ -53,6 +53,7 @@ public: } virtual EdgePairsDelegate *filtered (const EdgePairFilterBase &) const; + virtual std::pair filtered_pair (const EdgePairFilterBase &filter) const; virtual EdgePairsDelegate *process_in_place (const EdgePairProcessorBase &proc) { diff --git a/src/db/db/dbAsIfFlatEdges.cc b/src/db/db/dbAsIfFlatEdges.cc index f9f3beb30..cc3fdeee8 100644 --- a/src/db/db/dbAsIfFlatEdges.cc +++ b/src/db/db/dbAsIfFlatEdges.cc @@ -717,6 +717,23 @@ AsIfFlatEdges::filtered (const EdgeFilterBase &filter) const return new_region.release (); } +std::pair +AsIfFlatEdges::filtered_pair (const EdgeFilterBase &filter) const +{ + std::unique_ptr new_region_true (new FlatEdges ()); + std::unique_ptr new_region_false (new FlatEdges ()); + + for (EdgesIterator p (begin_merged ()); ! p.at_end (); ++p) { + if (filter.selected (*p)) { + new_region_true->insert (*p); + } else { + new_region_false->insert (*p); + } + } + + return std::make_pair (new_region_true.release (), new_region_false.release ()); +} + EdgePairsDelegate * AsIfFlatEdges::run_check (db::edge_relation_type rel, const Edges *other, db::Coord d, const db::EdgesCheckOptions &options) const { diff --git a/src/db/db/dbAsIfFlatEdges.h b/src/db/db/dbAsIfFlatEdges.h index a0bb035ab..a1113e074 100644 --- a/src/db/db/dbAsIfFlatEdges.h +++ b/src/db/db/dbAsIfFlatEdges.h @@ -101,6 +101,7 @@ public: } virtual EdgesDelegate *filtered (const EdgeFilterBase &) const; + virtual std::pair filtered_pair (const EdgeFilterBase &filter) const; virtual EdgesDelegate *merged_in_place () { diff --git a/src/db/db/dbAsIfFlatRegion.cc b/src/db/db/dbAsIfFlatRegion.cc index 38f52cba2..b4d14617b 100644 --- a/src/db/db/dbAsIfFlatRegion.cc +++ b/src/db/db/dbAsIfFlatRegion.cc @@ -414,6 +414,25 @@ AsIfFlatRegion::filtered (const PolygonFilterBase &filter) const return new_region.release (); } +std::pair +AsIfFlatRegion::filtered_pair (const PolygonFilterBase &filter) const +{ + std::unique_ptr new_region_true (new FlatRegion ()); + std::unique_ptr new_region_false (new FlatRegion ()); + + for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) { + if (filter.selected (*p)) { + new_region_true->insert (*p); + } else { + new_region_true->insert (*p); + } + } + + new_region_true->set_is_merged (true); + new_region_false->set_is_merged (true); + return std::make_pair (new_region_true.release (), new_region_false.release ()); +} + RegionDelegate * AsIfFlatRegion::processed (const PolygonProcessorBase &filter) const { diff --git a/src/db/db/dbAsIfFlatRegion.h b/src/db/db/dbAsIfFlatRegion.h index b34b58299..51b182443 100644 --- a/src/db/db/dbAsIfFlatRegion.h +++ b/src/db/db/dbAsIfFlatRegion.h @@ -101,6 +101,7 @@ public: } virtual RegionDelegate *filtered (const PolygonFilterBase &filter) const; + virtual std::pair filtered_pair (const PolygonFilterBase &filter) const; virtual RegionDelegate *merged_in_place () { diff --git a/src/db/db/dbAsIfFlatTexts.cc b/src/db/db/dbAsIfFlatTexts.cc index c5498fd64..6576d0d5e 100644 --- a/src/db/db/dbAsIfFlatTexts.cc +++ b/src/db/db/dbAsIfFlatTexts.cc @@ -164,6 +164,23 @@ AsIfFlatTexts::filtered (const TextFilterBase &filter) const return new_texts.release (); } +std::pair +AsIfFlatTexts::filtered_pair (const TextFilterBase &filter) const +{ + std::unique_ptr new_texts_true (new FlatTexts ()); + std::unique_ptr new_texts_false (new FlatTexts ()); + + for (TextsIterator p (begin ()); ! p.at_end (); ++p) { + if (filter.selected (*p)) { + new_texts_true->insert (*p); + } else { + new_texts_false->insert (*p); + } + } + + return std::make_pair (new_texts_true.release (), new_texts_false.release ()); +} + TextsDelegate * AsIfFlatTexts::processed (const TextProcessorBase &filter) const { diff --git a/src/db/db/dbAsIfFlatTexts.h b/src/db/db/dbAsIfFlatTexts.h index 62046626b..79591cf33 100644 --- a/src/db/db/dbAsIfFlatTexts.h +++ b/src/db/db/dbAsIfFlatTexts.h @@ -54,6 +54,7 @@ public: } virtual TextsDelegate *filtered (const TextFilterBase &) const; + virtual std::pair filtered_pair (const TextFilterBase &filter) const; virtual TextsDelegate *process_in_place (const TextProcessorBase &proc) { diff --git a/src/db/db/dbDeepEdgePairs.cc b/src/db/db/dbDeepEdgePairs.cc index cf4f06923..444bc4743 100644 --- a/src/db/db/dbDeepEdgePairs.cc +++ b/src/db/db/dbDeepEdgePairs.cc @@ -375,18 +375,24 @@ EdgePairsDelegate * DeepEdgePairs::filter_in_place (const EdgePairFilterBase &filter) { // TODO: implement to be really in-place - *this = *apply_filter (filter); + *this = *apply_filter (filter, true, false).first; return this; } EdgePairsDelegate * DeepEdgePairs::filtered (const EdgePairFilterBase &filter) const { - return apply_filter (filter); + return apply_filter (filter, true, false).first; } -DeepEdgePairs * -DeepEdgePairs::apply_filter (const EdgePairFilterBase &filter) const +std::pair +DeepEdgePairs::filtered_pair (const EdgePairFilterBase &filter) const +{ + return apply_filter (filter, true, true); +} + +std::pair +DeepEdgePairs::apply_filter (const EdgePairFilterBase &filter, bool with_true, bool with_false) const { const db::DeepLayer &edge_pairs = deep_layer (); db::Layout &layout = const_cast (edge_pairs.layout ()); @@ -404,9 +410,10 @@ DeepEdgePairs::apply_filter (const EdgePairFilterBase &filter) const } - std::map > to_commit; + std::map > to_commit_true, to_commit_false; - std::unique_ptr res (new db::DeepEdgePairs (edge_pairs.derived ())); + std::unique_ptr res_true (with_true ? new db::DeepEdgePairs (edge_pairs.derived ()) : 0); + std::unique_ptr res_false (with_false ? new db::DeepEdgePairs (edge_pairs.derived ()) : 0); for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { const db::Shapes &s = c->shapes (edge_pairs.layer ()); @@ -416,18 +423,34 @@ DeepEdgePairs::apply_filter (const EdgePairFilterBase &filter) const const std::set &vv = vars->variants (c->cell_index ()); for (auto v = vv.begin (); v != vv.end (); ++v) { - db::Shapes *st; + db::Shapes *st_true = 0, *st_false = 0; if (vv.size () == 1) { - st = & c->shapes (res->deep_layer ().layer ()); + if (with_true) { + st_true = & c->shapes (res_true->deep_layer ().layer ()); + } + if (with_false) { + st_false = & c->shapes (res_false->deep_layer ().layer ()); + } } else { - st = & to_commit [c->cell_index ()] [*v]; + if (with_true) { + st_true = & to_commit_true [c->cell_index ()] [*v]; + } + if (with_false) { + st_false = & to_commit_false [c->cell_index ()] [*v]; + } } const db::ICplxTrans &tr = *v; for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::EdgePairs); ! si.at_end (); ++si) { if (filter.selected (si->edge_pair ().transformed (tr))) { - st->insert (*si); + if (st_true) { + st_true->insert (*si); + } + } else { + if (st_false) { + st_false->insert (*si); + } } } @@ -435,11 +458,18 @@ DeepEdgePairs::apply_filter (const EdgePairFilterBase &filter) const } else { - db::Shapes &st = c->shapes (res->deep_layer ().layer ()); + db::Shapes *st_true = with_true ? &c->shapes (res_true->deep_layer ().layer ()) : 0; + db::Shapes *st_false = with_false ? &c->shapes (res_false->deep_layer ().layer ()) : 0; for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::EdgePairs); ! si.at_end (); ++si) { if (filter.selected (si->edge_pair ())) { - st.insert (*si); + if (with_true) { + st_true->insert (*si); + } + } else { + if (with_false) { + st_false->insert (*si); + } } } @@ -447,11 +477,16 @@ DeepEdgePairs::apply_filter (const EdgePairFilterBase &filter) const } - if (! to_commit.empty () && vars.get ()) { - vars->commit_shapes (res->deep_layer ().layer (), to_commit); + if (! to_commit_true.empty () && vars.get ()) { + tl_assert (res_true.get () != 0); + vars->commit_shapes (res_true->deep_layer ().layer (), to_commit_true); + } + if (! to_commit_false.empty () && vars.get ()) { + tl_assert (res_false.get () != 0); + vars->commit_shapes (res_false->deep_layer ().layer (), to_commit_false); } - return res.release (); + return std::make_pair (res_true.release (), res_false.release ()); } EdgePairsDelegate *DeepEdgePairs::process_in_place (const EdgePairProcessorBase &filter) diff --git a/src/db/db/dbDeepEdgePairs.h b/src/db/db/dbDeepEdgePairs.h index 89a659cbf..8537d77c8 100644 --- a/src/db/db/dbDeepEdgePairs.h +++ b/src/db/db/dbDeepEdgePairs.h @@ -78,6 +78,7 @@ public: virtual EdgePairsDelegate *filter_in_place (const EdgePairFilterBase &filter); virtual EdgePairsDelegate *filtered (const EdgePairFilterBase &) const; + virtual std::pair filtered_pair (const EdgePairFilterBase &filter) const; virtual EdgePairsDelegate *process_in_place (const EdgePairProcessorBase &); virtual EdgePairsDelegate *processed (const EdgePairProcessorBase &) const; virtual RegionDelegate *processed_to_polygons (const EdgePairToPolygonProcessorBase &filter) const; @@ -117,7 +118,7 @@ private: void init (); EdgesDelegate *generic_edges (bool first, bool second) const; - DeepEdgePairs *apply_filter (const EdgePairFilterBase &filter) const; + std::pair apply_filter (const EdgePairFilterBase &filter, bool with_true, bool with_false) const; }; } diff --git a/src/db/db/dbDeepEdges.cc b/src/db/db/dbDeepEdges.cc index 8f1872b76..c2e86caaa 100644 --- a/src/db/db/dbDeepEdges.cc +++ b/src/db/db/dbDeepEdges.cc @@ -809,18 +809,24 @@ EdgesDelegate * DeepEdges::filter_in_place (const EdgeFilterBase &filter) { // TODO: implement to be really in-place - *this = *apply_filter (filter); + *this = *apply_filter (filter, true, false).first; return this; } EdgesDelegate * DeepEdges::filtered (const EdgeFilterBase &filter) const { - return apply_filter (filter); + return apply_filter (filter, true, false).first; } -DeepEdges * -DeepEdges::apply_filter (const EdgeFilterBase &filter) const +std::pair +DeepEdges::filtered_pair (const EdgeFilterBase &filter) const +{ + return apply_filter (filter, true, true); +} + +std::pair +DeepEdges::apply_filter (const EdgeFilterBase &filter, bool with_true, bool with_false) const { const db::DeepLayer &edges = filter.requires_raw_input () ? deep_layer () : merged_deep_layer (); db::Layout &layout = const_cast (edges.layout ()); @@ -838,9 +844,10 @@ DeepEdges::apply_filter (const EdgeFilterBase &filter) const } - std::map > to_commit; + std::map > to_commit_true, to_commit_false; - std::unique_ptr res (new db::DeepEdges (edges.derived ())); + std::unique_ptr res_true (with_true ? new db::DeepEdges (edges.derived ()) : 0); + std::unique_ptr res_false (with_false ? new db::DeepEdges (edges.derived ()) : 0); for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { const db::Shapes &s = c->shapes (edges.layer ()); @@ -850,16 +857,34 @@ DeepEdges::apply_filter (const EdgeFilterBase &filter) const const std::set &vv = vars->variants (c->cell_index ()); for (auto v = vv.begin (); v != vv.end (); ++v) { - db::Shapes *st; + db::Shapes *st_true = 0, *st_false = 0; if (vv.size () == 1) { - st = & c->shapes (res->deep_layer ().layer ()); + if (with_true) { + st_true = & c->shapes (res_true->deep_layer ().layer ()); + } + if (with_false) { + st_false = & c->shapes (res_false->deep_layer ().layer ()); + } } else { - st = & to_commit [c->cell_index ()] [*v]; + if (with_true) { + st_true = & to_commit_true [c->cell_index ()] [*v]; + } + if (with_false) { + st_false = & to_commit_false [c->cell_index ()] [*v]; + } } + const db::ICplxTrans &tr = *v; + for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) { - if (filter.selected (si->edge ().transformed (*v))) { - st->insert (*si); + if (filter.selected (si->edge ().transformed (tr))) { + if (st_true) { + st_true->insert (*si); + } + } else { + if (st_false) { + st_false->insert (*si); + } } } @@ -867,11 +892,18 @@ DeepEdges::apply_filter (const EdgeFilterBase &filter) const } else { - db::Shapes &st = c->shapes (res->deep_layer ().layer ()); + db::Shapes *st_true = with_true ? &c->shapes (res_true->deep_layer ().layer ()) : 0; + db::Shapes *st_false = with_false ? &c->shapes (res_false->deep_layer ().layer ()) : 0; for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) { if (filter.selected (si->edge ())) { - st.insert (*si); + if (with_true) { + st_true->insert (*si); + } + } else { + if (with_false) { + st_false->insert (*si); + } } } @@ -879,14 +911,25 @@ DeepEdges::apply_filter (const EdgeFilterBase &filter) const } - if (! to_commit.empty () && vars.get ()) { - vars->commit_shapes (res->deep_layer ().layer (), to_commit); + if (! to_commit_true.empty () && vars.get ()) { + tl_assert (res_true.get () != 0); + vars->commit_shapes (res_true->deep_layer ().layer (), to_commit_true); + } + if (! to_commit_false.empty () && vars.get ()) { + tl_assert (res_false.get () != 0); + vars->commit_shapes (res_false->deep_layer ().layer (), to_commit_false); } if (! filter.requires_raw_input ()) { - res->set_is_merged (true); + if (res_true.get ()) { + res_true->set_is_merged (true); + } + if (res_false.get ()) { + res_false->set_is_merged (true); + } } - return res.release (); + + return std::make_pair (res_true.release (), res_false.release ()); } EdgesDelegate *DeepEdges::merged_in_place () diff --git a/src/db/db/dbDeepEdges.h b/src/db/db/dbDeepEdges.h index da104c0ec..3a1262732 100644 --- a/src/db/db/dbDeepEdges.h +++ b/src/db/db/dbDeepEdges.h @@ -127,6 +127,7 @@ public: virtual EdgesDelegate *filter_in_place (const EdgeFilterBase &filter); virtual EdgesDelegate *filtered (const EdgeFilterBase &) const; + virtual std::pair filtered_pair (const EdgeFilterBase &filter) const; virtual EdgesDelegate *process_in_place (const EdgeProcessorBase &); virtual EdgesDelegate *processed (const EdgeProcessorBase &) const; virtual EdgePairsDelegate *processed_to_edge_pairs (const EdgeToEdgePairProcessorBase &filter) const; @@ -199,7 +200,7 @@ private: virtual std::pair selected_interacting_pair_generic (const Region ®ion, EdgeInteractionMode mode, size_t min_count, size_t max_count) const; EdgesDelegate *selected_interacting_generic_impl (const DeepRegion *other_deep, EdgeInteractionMode mode, bool inverse, size_t min_count, size_t max_count) const; std::pair selected_interacting_pair_generic_impl (const DeepRegion *other_deep, EdgeInteractionMode mode, size_t min_count, size_t max_count) const; - DeepEdges *apply_filter (const EdgeFilterBase &filter) const; + std::pair apply_filter (const EdgeFilterBase &filter, bool with_true, bool with_false) const; template OutputContainer *processed_impl (const edge_processor &filter) const; }; diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index 03e278d26..9dac1d01e 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -1599,7 +1599,7 @@ DeepRegion::filter_in_place (const PolygonFilterBase &filter) } // TODO: implement to be really in-place - *this = *apply_filter (filter); + *this = *apply_filter (filter, true, false).first; return this; } @@ -1610,11 +1610,17 @@ DeepRegion::filtered (const PolygonFilterBase &filter) const return clone (); } - return apply_filter (filter); + return apply_filter (filter, true, false).first; } -DeepRegion * -DeepRegion::apply_filter (const PolygonFilterBase &filter) const +std::pair +DeepRegion::filtered_pair (const PolygonFilterBase &filter) const +{ + return apply_filter (filter, true, true); +} + +std::pair +DeepRegion::apply_filter (const PolygonFilterBase &filter, bool with_true, bool with_false) const { const db::DeepLayer &polygons = filter.requires_raw_input () ? deep_layer () : merged_deep_layer (); db::Layout &layout = const_cast (polygons.layout ()); @@ -1632,9 +1638,10 @@ DeepRegion::apply_filter (const PolygonFilterBase &filter) const } - std::map > to_commit; + std::map > to_commit_true, to_commit_false; - std::unique_ptr res (new db::DeepRegion (polygons.derived ())); + std::unique_ptr res_true (with_true ? new db::DeepRegion (polygons.derived ()) : 0); + std::unique_ptr res_false (with_false ? new db::DeepRegion (polygons.derived ()) : 0); for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { const db::Shapes &s = c->shapes (polygons.layer ()); @@ -1644,18 +1651,36 @@ DeepRegion::apply_filter (const PolygonFilterBase &filter) const const std::set &vv = vars->variants (c->cell_index ()); for (auto v = vv.begin (); v != vv.end (); ++v) { - db::Shapes *st; + db::Shapes *st_true = 0, *st_false = 0; if (vv.size () == 1) { - st = & c->shapes (res->deep_layer ().layer ()); + if (with_true) { + st_true = & c->shapes (res_true->deep_layer ().layer ()); + } + if (with_false) { + st_false = & c->shapes (res_false->deep_layer ().layer ()); + } } else { - st = & to_commit [c->cell_index ()] [*v]; + if (with_true) { + st_true = & to_commit_true [c->cell_index ()] [*v]; + } + if (with_false) { + st_false = & to_commit_false [c->cell_index ()] [*v]; + } } + const db::ICplxTrans &tr = *v; + for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) { db::Polygon poly; si->polygon (poly); - if (filter.selected (poly.transformed (*v))) { - st->insert (*si); + if (filter.selected (poly.transformed (tr))) { + if (st_true) { + st_true->insert (*si); + } + } else { + if (st_false) { + st_false->insert (*si); + } } } @@ -1663,13 +1688,20 @@ DeepRegion::apply_filter (const PolygonFilterBase &filter) const } else { - db::Shapes &st = c->shapes (res->deep_layer ().layer ()); + db::Shapes *st_true = with_true ? &c->shapes (res_true->deep_layer ().layer ()) : 0; + db::Shapes *st_false = with_false ? &c->shapes (res_false->deep_layer ().layer ()) : 0; for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) { db::Polygon poly; si->polygon (poly); if (filter.selected (poly)) { - st.insert (*si); + if (with_true) { + st_true->insert (*si); + } + } else { + if (with_false) { + st_false->insert (*si); + } } } @@ -1677,14 +1709,25 @@ DeepRegion::apply_filter (const PolygonFilterBase &filter) const } - if (! to_commit.empty () && vars.get ()) { - vars->commit_shapes (res->deep_layer ().layer (), to_commit); + if (! to_commit_true.empty () && vars.get ()) { + tl_assert (res_true.get () != 0); + vars->commit_shapes (res_true->deep_layer ().layer (), to_commit_true); + } + if (! to_commit_false.empty () && vars.get ()) { + tl_assert (res_false.get () != 0); + vars->commit_shapes (res_false->deep_layer ().layer (), to_commit_false); } if (! filter.requires_raw_input ()) { - res->set_is_merged (true); + if (res_true.get ()) { + res_true->set_is_merged (true); + } + if (res_false.get ()) { + res_false->set_is_merged (true); + } } - return res.release (); + + return std::make_pair (res_true.release (), res_false.release ()); } RegionDelegate * diff --git a/src/db/db/dbDeepRegion.h b/src/db/db/dbDeepRegion.h index 6860fc472..b162168a4 100644 --- a/src/db/db/dbDeepRegion.h +++ b/src/db/db/dbDeepRegion.h @@ -127,6 +127,7 @@ public: virtual EdgePairsDelegate *processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &filter) const; virtual RegionDelegate *filter_in_place (const PolygonFilterBase &filter); virtual RegionDelegate *filtered (const PolygonFilterBase &filter) const; + virtual std::pair filtered_pair (const PolygonFilterBase &filter) const; virtual RegionDelegate *merged_in_place (); virtual RegionDelegate *merged_in_place (bool min_coherence, unsigned int min_wc); @@ -183,8 +184,7 @@ private: DeepLayer not_with_impl (const DeepRegion *other, PropertyConstraint property_constraint) const; DeepLayer and_with_impl (const DeepRegion *other, PropertyConstraint property_constraint) const; std::pair and_and_not_with (const DeepRegion *other, PropertyConstraint property_constraint) const; - DeepRegion *apply_filter (const PolygonFilterBase &filter) const; - + std::pair apply_filter (const PolygonFilterBase &filter, bool with_true, bool with_false) const; template void configure_proc (Proc &proc) const { diff --git a/src/db/db/dbDeepTexts.cc b/src/db/db/dbDeepTexts.cc index 3d9df8ca4..8933f79c5 100644 --- a/src/db/db/dbDeepTexts.cc +++ b/src/db/db/dbDeepTexts.cc @@ -395,16 +395,23 @@ TextsDelegate *DeepTexts::add (const Texts &other) const TextsDelegate *DeepTexts::filter_in_place (const TextFilterBase &filter) { // TODO: implement as really in place - *this = *apply_filter (filter); + *this = *apply_filter (filter, true, false).first; return this; } TextsDelegate *DeepTexts::filtered (const TextFilterBase &filter) const { - return apply_filter (filter); + return apply_filter (filter, true, false).first; } -DeepTexts *DeepTexts::apply_filter (const TextFilterBase &filter) const +std::pair +DeepTexts::filtered_pair (const TextFilterBase &filter) const +{ + return apply_filter (filter, true, true); +} + +std::pair +DeepTexts::apply_filter (const TextFilterBase &filter, bool with_true, bool with_false) const { const db::DeepLayer &texts = deep_layer (); db::Layout &layout = const_cast (texts.layout ()); @@ -422,9 +429,10 @@ DeepTexts *DeepTexts::apply_filter (const TextFilterBase &filter) const } - std::map > to_commit; + std::map > to_commit_true, to_commit_false; - std::unique_ptr res (new db::DeepTexts (texts.derived ())); + std::unique_ptr res_true (with_true ? new db::DeepTexts (texts.derived ()) : 0); + std::unique_ptr res_false (with_false ? new db::DeepTexts (texts.derived ()) : 0); for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { const db::Shapes &s = c->shapes (texts.layer ()); @@ -434,18 +442,36 @@ DeepTexts *DeepTexts::apply_filter (const TextFilterBase &filter) const const std::set &vv = vars->variants (c->cell_index ()); for (auto v = vv.begin (); v != vv.end (); ++v) { - db::Shapes *st; + db::Shapes *st_true = 0, *st_false = 0; if (vv.size () == 1) { - st = & c->shapes (res->deep_layer ().layer ()); + if (with_true) { + st_true = & c->shapes (res_true->deep_layer ().layer ()); + } + if (with_false) { + st_false = & c->shapes (res_false->deep_layer ().layer ()); + } } else { - st = & to_commit [c->cell_index ()] [*v]; + if (with_true) { + st_true = & to_commit_true [c->cell_index ()] [*v]; + } + if (with_false) { + st_false = & to_commit_false [c->cell_index ()] [*v]; + } } + const db::ICplxTrans &tr = *v; + for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Texts); ! si.at_end (); ++si) { db::Text text; si->text (text); - if (filter.selected (text.transformed (*v))) { - st->insert (*si); + if (filter.selected (text.transformed (tr))) { + if (st_true) { + st_true->insert (*si); + } + } else { + if (st_false) { + st_false->insert (*si); + } } } @@ -453,13 +479,20 @@ DeepTexts *DeepTexts::apply_filter (const TextFilterBase &filter) const } else { - db::Shapes &st = c->shapes (res->deep_layer ().layer ()); + db::Shapes *st_true = with_true ? &c->shapes (res_true->deep_layer ().layer ()) : 0; + db::Shapes *st_false = with_false ? &c->shapes (res_false->deep_layer ().layer ()) : 0; for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Texts); ! si.at_end (); ++si) { db::Text text; si->text (text); if (filter.selected (text)) { - st.insert (*si); + if (with_true) { + st_true->insert (*si); + } + } else { + if (with_false) { + st_false->insert (*si); + } } } @@ -467,11 +500,16 @@ DeepTexts *DeepTexts::apply_filter (const TextFilterBase &filter) const } - if (! to_commit.empty () && vars.get ()) { - vars->commit_shapes (res->deep_layer ().layer (), to_commit); + if (! to_commit_true.empty () && vars.get ()) { + tl_assert (res_true.get () != 0); + vars->commit_shapes (res_true->deep_layer ().layer (), to_commit_true); + } + if (! to_commit_false.empty () && vars.get ()) { + tl_assert (res_false.get () != 0); + vars->commit_shapes (res_false->deep_layer ().layer (), to_commit_false); } - return res.release (); + return std::make_pair (res_true.release (), res_false.release ()); } TextsDelegate *DeepTexts::process_in_place (const TextProcessorBase &filter) diff --git a/src/db/db/dbDeepTexts.h b/src/db/db/dbDeepTexts.h index 95d0d13e1..7c8e125ff 100644 --- a/src/db/db/dbDeepTexts.h +++ b/src/db/db/dbDeepTexts.h @@ -79,6 +79,7 @@ public: virtual TextsDelegate *filter_in_place (const TextFilterBase &filter); virtual TextsDelegate *filtered (const TextFilterBase &) const; + virtual std::pair filtered_pair (const TextFilterBase &filter) const; virtual TextsDelegate *process_in_place (const TextProcessorBase &); virtual TextsDelegate *processed (const TextProcessorBase &) const; @@ -107,7 +108,7 @@ private: DeepTexts &operator= (const DeepTexts &other); void init (); - DeepTexts *apply_filter (const TextFilterBase &filter) const; + std::pair apply_filter (const TextFilterBase &filter, bool with_true, bool with_false) const; virtual TextsDelegate *selected_interacting_generic (const Region &other, bool inverse) const; virtual RegionDelegate *pull_generic (const Region &other) const; diff --git a/src/db/db/dbEdgePairs.h b/src/db/db/dbEdgePairs.h index b1b451a58..36b8960f8 100644 --- a/src/db/db/dbEdgePairs.h +++ b/src/db/db/dbEdgePairs.h @@ -346,6 +346,18 @@ public: return EdgePairs (mp_delegate->filtered (filter)); } + /** + * @brief Returns the filtered edge pairs and the others + * + * This method will return a new edge pair collection with only those edge pairs which + * conform to the filter criterion and another for those which don't. + */ + std::pair split_filter (const EdgePairFilterBase &filter) const + { + std::pair p = mp_delegate->filtered_pair (filter); + return std::pair (EdgePairs (p.first), EdgePairs (p.second)); + } + /** * @brief Processes the edge pairs in-place * diff --git a/src/db/db/dbEdgePairsDelegate.h b/src/db/db/dbEdgePairsDelegate.h index eeb05ec19..419c61409 100644 --- a/src/db/db/dbEdgePairsDelegate.h +++ b/src/db/db/dbEdgePairsDelegate.h @@ -201,6 +201,7 @@ public: virtual EdgePairsDelegate *filter_in_place (const EdgePairFilterBase &filter) = 0; virtual EdgePairsDelegate *filtered (const EdgePairFilterBase &filter) const = 0; + virtual std::pair filtered_pair (const EdgePairFilterBase &filter) const = 0; virtual EdgePairsDelegate *process_in_place (const EdgePairProcessorBase &proc) = 0; virtual EdgePairsDelegate *processed (const EdgePairProcessorBase &proc) const = 0; virtual RegionDelegate *processed_to_polygons (const EdgePairToPolygonProcessorBase &proc) const = 0; diff --git a/src/db/db/dbEdges.h b/src/db/db/dbEdges.h index 649ded1c3..bb57ada29 100644 --- a/src/db/db/dbEdges.h +++ b/src/db/db/dbEdges.h @@ -468,6 +468,18 @@ public: return Edges (mp_delegate->filtered (filter)); } + /** + * @brief Returns the filtered edges and the others + * + * This method will return a new edge collection with only those edges which + * conform to the filter criterion and another for those which don't. + */ + std::pair split_filter (const EdgeFilterBase &filter) const + { + std::pair p = mp_delegate->filtered_pair (filter); + return std::pair (Edges (p.first), Edges (p.second)); + } + /** * @brief Processes the (merged) edges * diff --git a/src/db/db/dbEdgesDelegate.h b/src/db/db/dbEdgesDelegate.h index caeab6524..c0b971044 100644 --- a/src/db/db/dbEdgesDelegate.h +++ b/src/db/db/dbEdgesDelegate.h @@ -228,6 +228,7 @@ public: virtual EdgesDelegate *filter_in_place (const EdgeFilterBase &filter) = 0; virtual EdgesDelegate *filtered (const EdgeFilterBase &filter) const = 0; + virtual std::pair filtered_pair (const EdgeFilterBase &filter) const = 0; virtual EdgesDelegate *process_in_place (const EdgeProcessorBase &filter) = 0; virtual EdgesDelegate *processed (const EdgeProcessorBase &filter) const = 0; virtual EdgePairsDelegate *processed_to_edge_pairs (const EdgeToEdgePairProcessorBase &filter) const = 0; diff --git a/src/db/db/dbEmptyEdgePairs.h b/src/db/db/dbEmptyEdgePairs.h index f1f6b981a..6f01ddd92 100644 --- a/src/db/db/dbEmptyEdgePairs.h +++ b/src/db/db/dbEmptyEdgePairs.h @@ -56,6 +56,7 @@ public: virtual EdgePairsDelegate *filter_in_place (const EdgePairFilterBase &) { return this; } virtual EdgePairsDelegate *filtered (const EdgePairFilterBase &) const { return new EmptyEdgePairs (); } + virtual std::pair filtered_pair (const EdgePairFilterBase &) const { return std::make_pair (new EmptyEdgePairs (), new EmptyEdgePairs ()); } virtual EdgePairsDelegate *process_in_place (const EdgePairProcessorBase &) { return this; } virtual EdgePairsDelegate *processed (const EdgePairProcessorBase &) const { return new EmptyEdgePairs (); } virtual RegionDelegate *processed_to_polygons (const EdgePairToPolygonProcessorBase &filter) const; diff --git a/src/db/db/dbEmptyEdges.h b/src/db/db/dbEmptyEdges.h index 4514ea80d..13dfd39d3 100644 --- a/src/db/db/dbEmptyEdges.h +++ b/src/db/db/dbEmptyEdges.h @@ -66,6 +66,7 @@ public: virtual EdgesDelegate *filter_in_place (const EdgeFilterBase &) { return this; } virtual EdgesDelegate *filtered (const EdgeFilterBase &) const { return new EmptyEdges (); } + virtual std::pair filtered_pair (const EdgeFilterBase &) const { return std::make_pair (new EmptyEdges (), new EmptyEdges ()); } virtual EdgesDelegate *process_in_place (const EdgeProcessorBase &) { return this; } virtual EdgesDelegate *processed (const EdgeProcessorBase &) const { return new EmptyEdges (); } virtual EdgePairsDelegate *processed_to_edge_pairs (const EdgeToEdgePairProcessorBase &) const; diff --git a/src/db/db/dbEmptyRegion.h b/src/db/db/dbEmptyRegion.h index 46dc1397a..1016b6080 100644 --- a/src/db/db/dbEmptyRegion.h +++ b/src/db/db/dbEmptyRegion.h @@ -85,6 +85,7 @@ public: virtual EdgesDelegate *edges (const EdgeFilterBase *, const PolygonToEdgeProcessorBase *) const; virtual RegionDelegate *filter_in_place (const PolygonFilterBase &) { return this; } virtual RegionDelegate *filtered (const PolygonFilterBase &) const { return new EmptyRegion (); } + virtual std::pair filtered_pair (const PolygonFilterBase &) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); } virtual RegionDelegate *process_in_place (const PolygonProcessorBase &) { return this; } virtual RegionDelegate *processed (const PolygonProcessorBase &) const { return new EmptyRegion (); } virtual EdgesDelegate *processed_to_edges (const PolygonToEdgeProcessorBase &) const; diff --git a/src/db/db/dbEmptyTexts.h b/src/db/db/dbEmptyTexts.h index ecc3f313a..934bf62c9 100644 --- a/src/db/db/dbEmptyTexts.h +++ b/src/db/db/dbEmptyTexts.h @@ -56,6 +56,7 @@ public: virtual TextsDelegate *filter_in_place (const TextFilterBase &) { return this; } virtual TextsDelegate *filtered (const TextFilterBase &) const { return new EmptyTexts (); } + virtual std::pair filtered_pair (const TextFilterBase &) const { return std::make_pair (new EmptyTexts (), new EmptyTexts ()); } virtual TextsDelegate *process_in_place (const TextProcessorBase &) { return this; } virtual TextsDelegate *processed (const TextProcessorBase &) const { return new EmptyTexts (); } diff --git a/src/db/db/dbRegion.h b/src/db/db/dbRegion.h index 26a908fe7..893931949 100644 --- a/src/db/db/dbRegion.h +++ b/src/db/db/dbRegion.h @@ -572,6 +572,18 @@ public: return Region (mp_delegate->filtered (filter)); } + /** + * @brief Returns the filtered polygons and the others + * + * This method will return a new region with only those polygons which + * conform to the filter criterion and another for those which don't. + */ + std::pair split_filter (const PolygonFilterBase &filter) const + { + std::pair p = mp_delegate->filtered_pair (filter); + return std::pair (Region (p.first), Region (p.second)); + } + /** * @brief Processes the (merged) polygons * diff --git a/src/db/db/dbRegionDelegate.h b/src/db/db/dbRegionDelegate.h index 70acd8810..0920cb0e9 100644 --- a/src/db/db/dbRegionDelegate.h +++ b/src/db/db/dbRegionDelegate.h @@ -214,6 +214,7 @@ public: virtual EdgesDelegate *edges (const EdgeFilterBase *filter, const db::PolygonToEdgeProcessorBase *proc) const = 0; virtual RegionDelegate *filter_in_place (const PolygonFilterBase &filter) = 0; virtual RegionDelegate *filtered (const PolygonFilterBase &filter) const = 0; + virtual std::pair filtered_pair (const PolygonFilterBase &filter) const = 0; virtual RegionDelegate *process_in_place (const PolygonProcessorBase &filter) = 0; virtual RegionDelegate *processed (const PolygonProcessorBase &filter) const = 0; virtual EdgesDelegate *processed_to_edges (const PolygonToEdgeProcessorBase &filter) const = 0; diff --git a/src/db/db/dbTexts.h b/src/db/db/dbTexts.h index 86b2a7e24..03594f1fd 100644 --- a/src/db/db/dbTexts.h +++ b/src/db/db/dbTexts.h @@ -213,6 +213,16 @@ public: return mp_delegate; } + /** + * @brief Takes the underlying delegate object + */ + TextsDelegate *take_delegate () + { + TextsDelegate *delegate = mp_delegate; + mp_delegate = 0; + return delegate; + } + /** * @brief Iterator of the text set * @@ -323,6 +333,18 @@ public: return Texts (mp_delegate->filtered (filter)); } + /** + * @brief Returns the filtered texts and the others + * + * This method will return a new text collection with only those texts which + * conform to the filter criterion and another for those which don't. + */ + std::pair split_filter (const TextFilterBase &filter) const + { + std::pair p = mp_delegate->filtered_pair (filter); + return std::pair (Texts (p.first), Texts (p.second)); + } + /** * @brief Processes the edge pairs in-place * diff --git a/src/db/db/dbTextsDelegate.h b/src/db/db/dbTextsDelegate.h index c22e6be67..ea6ca62f1 100644 --- a/src/db/db/dbTextsDelegate.h +++ b/src/db/db/dbTextsDelegate.h @@ -95,6 +95,7 @@ public: virtual TextsDelegate *filter_in_place (const TextFilterBase &filter) = 0; virtual TextsDelegate *filtered (const TextFilterBase &filter) const = 0; + virtual std::pair filtered_pair (const TextFilterBase &filter) const = 0; virtual TextsDelegate *process_in_place (const TextProcessorBase &proc) = 0; virtual TextsDelegate *processed (const TextProcessorBase &proc) const = 0; virtual RegionDelegate *processed_to_polygons (const TextToPolygonProcessorBase &proc) const = 0; diff --git a/src/db/db/gsiDeclDbEdgePairs.cc b/src/db/db/gsiDeclDbEdgePairs.cc index 99f289880..e17e89c48 100644 --- a/src/db/db/gsiDeclDbEdgePairs.cc +++ b/src/db/db/gsiDeclDbEdgePairs.cc @@ -409,6 +409,11 @@ static void filter (db::EdgePairs *r, const EdgePairFilterImpl *f) r->filter (*f); } +static std::vector split_filter (const db::EdgePairs *r, const EdgePairFilterImpl *f) +{ + return as_2edge_pairs_vector (r->split_filter (*f)); +} + static db::EdgePairs processed_epep (const db::EdgePairs *r, const shape_processor_impl *f) { return r->processed (*f); @@ -439,12 +444,24 @@ static db::EdgePairs with_distance1 (const db::EdgePairs *r, db::EdgePairs::dist return r->filtered (ef); } +static std::vector split_with_distance1 (const db::EdgePairs *r, db::EdgePairs::distance_type length) +{ + db::EdgePairFilterByDistance ef (length, length + 1, false); + return as_2edge_pairs_vector (r->split_filter (ef)); +} + static db::EdgePairs with_distance2 (const db::EdgePairs *r, const tl::Variant &min, const tl::Variant &max, bool inverse) { db::EdgePairFilterByDistance ef (min.is_nil () ? db::Edges::distance_type (0) : min.to (), max.is_nil () ? std::numeric_limits ::max () : max.to (), inverse); return r->filtered (ef); } +static std::vector split_with_distance2 (const db::EdgePairs *r, const tl::Variant &min, const tl::Variant &max) +{ + db::EdgePairFilterByDistance ef (min.is_nil () ? db::Edges::distance_type (0) : min.to (), max.is_nil () ? std::numeric_limits ::max () : max.to (), false); + return as_2edge_pairs_vector (r->split_filter (ef)); +} + static db::EdgePairs with_length1 (const db::EdgePairs *r, db::EdgePairs::distance_type length, bool inverse) { db::EdgeLengthFilter f (length, length + 1, inverse); @@ -452,6 +469,13 @@ static db::EdgePairs with_length1 (const db::EdgePairs *r, db::EdgePairs::distan return r->filtered (ef); } +static std::vector split_with_length1 (const db::EdgePairs *r, db::EdgePairs::distance_type length) +{ + db::EdgeLengthFilter f (length, length + 1, false); + db::EdgeFilterBasedEdgePairFilter ef (&f, true /*one must match*/); + return as_2edge_pairs_vector (r->split_filter (ef)); +} + static db::EdgePairs with_length2 (const db::EdgePairs *r, const tl::Variant &min, const tl::Variant &max, bool inverse) { db::EdgeLengthFilter f (min.is_nil () ? db::Edges::distance_type (0) : min.to (), max.is_nil () ? std::numeric_limits ::max () : max.to (), inverse); @@ -459,6 +483,13 @@ static db::EdgePairs with_length2 (const db::EdgePairs *r, const tl::Variant &mi return r->filtered (ef); } +static std::vector split_with_length2 (const db::EdgePairs *r, const tl::Variant &min, const tl::Variant &max) +{ + db::EdgeLengthFilter f (min.is_nil () ? db::Edges::distance_type (0) : min.to (), max.is_nil () ? std::numeric_limits ::max () : max.to (), false); + db::EdgeFilterBasedEdgePairFilter ef (&f, true /*one must match*/); + return as_2edge_pairs_vector (r->split_filter (ef)); +} + static db::EdgePairs with_length_both1 (const db::EdgePairs *r, db::EdgePairs::distance_type length, bool inverse) { db::EdgeLengthFilter f (length, length + 1, inverse); @@ -466,6 +497,13 @@ static db::EdgePairs with_length_both1 (const db::EdgePairs *r, db::EdgePairs::d return r->filtered (ef); } +static std::vector split_with_length_both1 (const db::EdgePairs *r, db::EdgePairs::distance_type length) +{ + db::EdgeLengthFilter f (length, length + 1, false); + db::EdgeFilterBasedEdgePairFilter ef (&f, false /*both must match*/); + return as_2edge_pairs_vector (r->split_filter (ef)); +} + static db::EdgePairs with_length_both2 (const db::EdgePairs *r, const tl::Variant &min, const tl::Variant &max, bool inverse) { db::EdgeLengthFilter f (min.is_nil () ? db::Edges::distance_type (0) : min.to (), max.is_nil () ? std::numeric_limits ::max () : max.to (), inverse); @@ -473,6 +511,13 @@ static db::EdgePairs with_length_both2 (const db::EdgePairs *r, const tl::Varian return r->filtered (ef); } +static std::vector split_with_length_both2 (const db::EdgePairs *r, const tl::Variant &min, const tl::Variant &max) +{ + db::EdgeLengthFilter f (min.is_nil () ? db::Edges::distance_type (0) : min.to (), max.is_nil () ? std::numeric_limits ::max () : max.to (), false); + db::EdgeFilterBasedEdgePairFilter ef (&f, false /*both must match*/); + return as_2edge_pairs_vector (r->split_filter (ef)); +} + static db::EdgePairs with_angle1 (const db::EdgePairs *r, double a, bool inverse) { db::EdgeOrientationFilter f (a, inverse, false); @@ -480,6 +525,13 @@ static db::EdgePairs with_angle1 (const db::EdgePairs *r, double a, bool inverse return r->filtered (ef); } +static std::vector split_with_angle1 (const db::EdgePairs *r, double a) +{ + db::EdgeOrientationFilter f (a, false, false); + db::EdgeFilterBasedEdgePairFilter ef (&f, true /*one must match*/); + return as_2edge_pairs_vector (r->split_filter (ef)); +} + static db::EdgePairs with_angle2 (const db::EdgePairs *r, double amin, double amax, bool inverse, bool include_amin, bool include_amax) { db::EdgeOrientationFilter f (amin, include_amin, amax, include_amax, inverse, false); @@ -487,6 +539,13 @@ static db::EdgePairs with_angle2 (const db::EdgePairs *r, double amin, double am return r->filtered (ef); } +static std::vector split_with_angle2 (const db::EdgePairs *r, double amin, double amax, bool include_amin, bool include_amax) +{ + db::EdgeOrientationFilter f (amin, include_amin, amax, include_amax, false, false); + db::EdgeFilterBasedEdgePairFilter ef (&f, true /*one must match*/); + return as_2edge_pairs_vector (r->split_filter (ef)); +} + static db::EdgePairs with_abs_angle1 (const db::EdgePairs *r, double a, bool inverse) { db::EdgeOrientationFilter f (a, inverse, true); @@ -494,6 +553,13 @@ static db::EdgePairs with_abs_angle1 (const db::EdgePairs *r, double a, bool inv return r->filtered (ef); } +static std::vector split_with_abs_angle1 (const db::EdgePairs *r, double a) +{ + db::EdgeOrientationFilter f (a, false, true); + db::EdgeFilterBasedEdgePairFilter ef (&f, true /*one must match*/); + return as_2edge_pairs_vector (r->split_filter (ef)); +} + static db::EdgePairs with_abs_angle2 (const db::EdgePairs *r, double amin, double amax, bool inverse, bool include_amin, bool include_amax) { db::EdgeOrientationFilter f (amin, include_amin, amax, include_amax, inverse, true); @@ -501,6 +567,13 @@ static db::EdgePairs with_abs_angle2 (const db::EdgePairs *r, double amin, doubl return r->filtered (ef); } +static std::vector split_with_abs_angle2 (const db::EdgePairs *r, double amin, double amax, bool include_amin, bool include_amax) +{ + db::EdgeOrientationFilter f (amin, include_amin, amax, include_amax, false, true); + db::EdgeFilterBasedEdgePairFilter ef (&f, true /*one must match*/); + return as_2edge_pairs_vector (r->split_filter (ef)); +} + static db::EdgePairs with_angle3 (const db::EdgePairs *r, db::SpecialEdgeOrientationFilter::FilterType type, bool inverse) { db::SpecialEdgeOrientationFilter f (type, inverse); @@ -508,6 +581,13 @@ static db::EdgePairs with_angle3 (const db::EdgePairs *r, db::SpecialEdgeOrienta return r->filtered (ef); } +static std::vector split_with_angle3 (const db::EdgePairs *r, db::SpecialEdgeOrientationFilter::FilterType type) +{ + db::SpecialEdgeOrientationFilter f (type, false); + db::EdgeFilterBasedEdgePairFilter ef (&f, true /*one must match*/); + return as_2edge_pairs_vector (r->split_filter (ef)); +} + static db::EdgePairs with_angle_both1 (const db::EdgePairs *r, double a, bool inverse) { db::EdgeOrientationFilter f (a, inverse, false); @@ -515,6 +595,13 @@ static db::EdgePairs with_angle_both1 (const db::EdgePairs *r, double a, bool in return r->filtered (ef); } +static std::vector split_with_angle_both1 (const db::EdgePairs *r, double a) +{ + db::EdgeOrientationFilter f (a, false, false); + db::EdgeFilterBasedEdgePairFilter ef (&f, false /*both must match*/); + return as_2edge_pairs_vector (r->split_filter (ef)); +} + static db::EdgePairs with_angle_both2 (const db::EdgePairs *r, double amin, double amax, bool inverse, bool include_amin, bool include_amax) { db::EdgeOrientationFilter f (amin, include_amin, amax, include_amax, inverse, false); @@ -522,6 +609,13 @@ static db::EdgePairs with_angle_both2 (const db::EdgePairs *r, double amin, doub return r->filtered (ef); } +static std::vector split_with_angle_both2 (const db::EdgePairs *r, double amin, double amax, bool include_amin, bool include_amax) +{ + db::EdgeOrientationFilter f (amin, include_amin, amax, include_amax, false, false); + db::EdgeFilterBasedEdgePairFilter ef (&f, false /*both must match*/); + return as_2edge_pairs_vector (r->split_filter (ef)); +} + static db::EdgePairs with_abs_angle_both1 (const db::EdgePairs *r, double a, bool inverse) { db::EdgeOrientationFilter f (a, inverse, true); @@ -529,6 +623,13 @@ static db::EdgePairs with_abs_angle_both1 (const db::EdgePairs *r, double a, boo return r->filtered (ef); } +static std::vector split_with_abs_angle_both1 (const db::EdgePairs *r, double a) +{ + db::EdgeOrientationFilter f (a, false, true); + db::EdgeFilterBasedEdgePairFilter ef (&f, false /*both must match*/); + return as_2edge_pairs_vector (r->split_filter (ef)); +} + static db::EdgePairs with_abs_angle_both2 (const db::EdgePairs *r, double amin, double amax, bool inverse, bool include_amin, bool include_amax) { db::EdgeOrientationFilter f (amin, include_amin, amax, include_amax, inverse, true); @@ -536,6 +637,13 @@ static db::EdgePairs with_abs_angle_both2 (const db::EdgePairs *r, double amin, return r->filtered (ef); } +static std::vector split_with_abs_angle_both2 (const db::EdgePairs *r, double amin, double amax, bool include_amin, bool include_amax) +{ + db::EdgeOrientationFilter f (amin, include_amin, amax, include_amax, false, true); + db::EdgeFilterBasedEdgePairFilter ef (&f, false /*both must match*/); + return as_2edge_pairs_vector (r->split_filter (ef)); +} + static db::EdgePairs with_angle_both3 (const db::EdgePairs *r, db::SpecialEdgeOrientationFilter::FilterType type, bool inverse) { db::SpecialEdgeOrientationFilter f (type, inverse); @@ -543,30 +651,61 @@ static db::EdgePairs with_angle_both3 (const db::EdgePairs *r, db::SpecialEdgeOr return r->filtered (ef); } +static std::vector split_with_angle_both3 (const db::EdgePairs *r, db::SpecialEdgeOrientationFilter::FilterType type) +{ + db::SpecialEdgeOrientationFilter f (type, false); + db::EdgeFilterBasedEdgePairFilter ef (&f, false /*both must match*/); + return as_2edge_pairs_vector (r->split_filter (ef)); +} + static db::EdgePairs with_internal_angle1 (const db::EdgePairs *r, double a, bool inverse) { db::InternalAngleEdgePairFilter f (a, inverse); return r->filtered (f); } +static std::vector split_with_internal_angle1 (const db::EdgePairs *r, double a) +{ + db::InternalAngleEdgePairFilter f (a, false); + return as_2edge_pairs_vector (r->split_filter (f)); +} + static db::EdgePairs with_internal_angle2 (const db::EdgePairs *r, double amin, double amax, bool inverse, bool include_amin, bool include_amax) { db::InternalAngleEdgePairFilter f (amin, include_amin, amax, include_amax, inverse); return r->filtered (f); } +static std::vector split_with_internal_angle2 (const db::EdgePairs *r, double amin, double amax, bool include_amin, bool include_amax) +{ + db::InternalAngleEdgePairFilter f (amin, include_amin, amax, include_amax, false); + return as_2edge_pairs_vector (r->split_filter (f)); +} + static db::EdgePairs with_area1 (const db::EdgePairs *r, db::EdgePair::area_type a, bool inverse) { db::EdgePairFilterByArea f (a, a + 1, inverse); return r->filtered (f); } +static std::vector split_with_area1 (const db::EdgePairs *r, db::EdgePair::area_type a) +{ + db::EdgePairFilterByArea f (a, a + 1, false); + return as_2edge_pairs_vector (r->split_filter (f)); +} + static db::EdgePairs with_area2 (const db::EdgePairs *r, db::EdgePair::area_type amin, db::EdgePair::area_type amax, bool inverse) { db::EdgePairFilterByArea f (amin, amax, inverse); return r->filtered (f); } +static std::vector split_with_area2 (const db::EdgePairs *r, db::EdgePair::area_type amin, db::EdgePair::area_type amax) +{ + db::EdgePairFilterByArea f (amin, amax, false); + return as_2edge_pairs_vector (r->split_filter (f)); +} + extern Class decl_dbShapeCollection; Class decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs", @@ -911,12 +1050,18 @@ Class decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs", "\n" "This method has been introduced in version 0.29.\n" ) + - method_ext ("filtered", &filtered, gsi::arg ("filtered"), + method_ext ("filtered", &filtered, gsi::arg ("filter"), "@brief Applies a generic filter and returns a filtered copy\n" "See \\EdgePairFilter for a description of this feature.\n" "\n" "This method has been introduced in version 0.29.\n" ) + + method_ext ("split_filter", &split_filter, gsi::arg ("filter"), + "@brief Applies a generic filter and returns a copy with all matching shapes and one with the non-matching ones\n" + "See \\EdgePairFilter for a description of this feature.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + method_ext ("process", &process_epep, gsi::arg ("process"), "@brief Applies a generic edge pair processor in place (replacing the edge pairs from the EdgePairs collection)\n" "See \\EdgePairProcessor for a description of this feature.\n" @@ -959,6 +1104,18 @@ Class decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs", "\n" "This method has been added in version 0.27.1.\n" ) + + method_ext ("split_with_length", split_with_length1, gsi::arg ("length"), + "@brief Like \\with_length, but returning two edge pair collections\n" + "The first edge pair collection will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + + method_ext ("split_with_length", split_with_length2, gsi::arg ("min_length"), gsi::arg ("max_length"), + "@brief Like \\with_length, but returning two edge pair collections\n" + "The first edge pair collection will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + method_ext ("with_length_both", with_length_both1, gsi::arg ("length"), gsi::arg ("inverse"), "@brief Filters the edge pairs by length of both of their edges\n" "Filters the edge pairs in the edge pair collection by length of both of their edges. If \"inverse\" is false, only " @@ -977,6 +1134,18 @@ Class decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs", "\n" "This method has been added in version 0.27.1.\n" ) + + method_ext ("split_with_length_both", split_with_length_both1, gsi::arg ("length"), + "@brief Like \\with_length_both, but returning two edge pair collections\n" + "The first edge pair collection will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + + method_ext ("split_with_length_both", split_with_length_both2, gsi::arg ("min_length"), gsi::arg ("max_length"), + "@brief Like \\with_length_both, but returning two edge pair collections\n" + "The first edge pair collection will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + method_ext ("with_distance", with_distance1, gsi::arg ("distance"), gsi::arg ("inverse"), "@brief Filters the edge pairs by the distance of the edges\n" "Filters the edge pairs in the edge pair collection by distance of the edges. If \"inverse\" is false, only " @@ -997,6 +1166,18 @@ Class decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs", "\n" "This method has been added in version 0.27.1.\n" ) + + method_ext ("split_with_distance", split_with_distance1, gsi::arg ("distance"), + "@brief Like \\with_distance, but returning two edge pair collections\n" + "The first edge pair collection will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + + method_ext ("split_with_distance", split_with_distance2, gsi::arg ("min_distance"), gsi::arg ("max_distance"), + "@brief Like \\with_distance, but returning two edge pair collections\n" + "The first edge pair collection will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + method_ext ("with_angle", with_angle1, gsi::arg ("angle"), gsi::arg ("inverse"), "@brief Filter the edge pairs by orientation of their edges\n" "Filters the edge pairs in the edge pair collection by orientation. If \"inverse\" is false, only " @@ -1038,22 +1219,6 @@ Class decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs", "\n" "This method has been added in version 0.27.1.\n" ) + - method_ext ("with_abs_angle", with_abs_angle1, gsi::arg ("angle"), gsi::arg ("inverse"), - "@brief Filter the edge pairs by orientation of their edges\n" - "\n" - "This method behaves like \\with_angle, but angles are always positive - i.e. there is no " - "differentiation between edges sloping 'down' vs. edges sloping 'up.\n" - "\n" - "This method has been added in version 0.29.1.\n" - ) + - method_ext ("with_abs_angle", with_abs_angle2, gsi::arg ("min_angle"), gsi::arg ("max_angle"), gsi::arg ("inverse"), gsi::arg ("include_min_angle", true), gsi::arg ("include_max_angle", false), - "@brief Filter the edge pairs by orientation of their edges\n" - "\n" - "This method behaves like \\with_angle, but angles are always positive - i.e. there is no " - "differentiation between edges sloping 'down' vs. edges sloping 'up.\n" - "\n" - "This method has been added in version 0.29.1.\n" - ) + method_ext ("with_angle", with_angle3, gsi::arg ("type"), gsi::arg ("inverse"), "@brief Filter the edge pairs by orientation of their edges\n" "Filters the edge pairs in the edge pair collection by orientation. If \"inverse\" is false, only " @@ -1073,6 +1238,52 @@ Class decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs", "\n" "This method has been added in version 0.28.\n" ) + + method_ext ("split_with_angle", split_with_angle1, gsi::arg ("angle"), + "@brief Like \\with_angle, but returning two edge pair collections\n" + "The first edge pair collection will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + + method_ext ("split_with_angle", split_with_angle2, gsi::arg ("min_angle"), gsi::arg ("max_angle"), gsi::arg ("include_min_angle", true), gsi::arg ("include_max_angle", false), + "@brief Like \\with_angle, but returning two edge pair collections\n" + "The first edge pair collection will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + + method_ext ("split_with_angle", split_with_angle3, gsi::arg ("type"), + "@brief Like \\with_angle, but returning two edge pair collections\n" + "The first edge pair collection will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + + method_ext ("with_abs_angle", with_abs_angle1, gsi::arg ("angle"), gsi::arg ("inverse"), + "@brief Filter the edge pairs by orientation of their edges\n" + "\n" + "This method behaves like \\with_angle, but angles are always positive - i.e. there is no " + "differentiation between edges sloping 'down' vs. edges sloping 'up.\n" + "\n" + "This method has been added in version 0.29.1.\n" + ) + + method_ext ("with_abs_angle", with_abs_angle2, gsi::arg ("min_angle"), gsi::arg ("max_angle"), gsi::arg ("inverse"), gsi::arg ("include_min_angle", true), gsi::arg ("include_max_angle", false), + "@brief Filter the edge pairs by orientation of their edges\n" + "\n" + "This method behaves like \\with_angle, but angles are always positive - i.e. there is no " + "differentiation between edges sloping 'down' vs. edges sloping 'up.\n" + "\n" + "This method has been added in version 0.29.1.\n" + ) + + method_ext ("split_with_abs_angle", split_with_abs_angle1, gsi::arg ("angle"), + "@brief Like \\with_abs_angle, but returning two edge pair collections\n" + "The first edge pair collection will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + + method_ext ("split_with_abs_angle", split_with_abs_angle2, gsi::arg ("min_angle"), gsi::arg ("max_angle"), gsi::arg ("include_min_angle", true), gsi::arg ("include_max_angle", false), + "@brief Like \\with_abs_angle, but returning two edge pair collections\n" + "The first edge pair collection will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + method_ext ("with_angle_both", with_angle_both1, gsi::arg ("angle"), gsi::arg ("inverse"), "@brief Filter the edge pairs by orientation of both of their edges\n" "Filters the edge pairs in the edge pair collection by orientation. If \"inverse\" is false, only " @@ -1114,21 +1325,6 @@ Class decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs", "\n" "This method has been added in version 0.27.1.\n" ) + - method_ext ("with_abs_angle_both", with_abs_angle_both1, gsi::arg ("angle"), gsi::arg ("inverse"), - "@brief Filter the edge pairs by orientation of both of their edges\n" - "\n" - "This method behaves like \\with_angle_both, but angles are always positive - i.e. there is no " - "differentiation between edges sloping 'down' vs. edges sloping 'up.\n" - "\n" - "This method has been added in version 0.29.1.\n" - ) + - method_ext ("with_abs_angle_both", with_abs_angle_both2, gsi::arg ("min_angle"), gsi::arg ("max_angle"), gsi::arg ("inverse"), gsi::arg ("include_min_angle", true), gsi::arg ("include_max_angle", false), - "\n" - "This method behaves like \\with_angle_both, but angles are always positive - i.e. there is no " - "differentiation between edges sloping 'down' vs. edges sloping 'up.\n" - "\n" - "This method has been added in version 0.29.1.\n" - ) + method_ext ("with_angle_both", with_angle_both3, gsi::arg ("type"), gsi::arg ("inverse"), "@brief Filter the edge pairs by orientation of their edges\n" "Filters the edge pairs in the edge pair collection by orientation. If \"inverse\" is false, only " @@ -1148,6 +1344,51 @@ Class decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs", "\n" "This method has been added in version 0.28.\n" ) + + method_ext ("split_with_angle_both", split_with_angle_both1, gsi::arg ("angle"), + "@brief Like \\with_angle_both, but returning two edge pair collections\n" + "The first edge pair collection will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + + method_ext ("split_with_angle_both", split_with_angle_both2, gsi::arg ("min_angle"), gsi::arg ("max_angle"), gsi::arg ("include_min_angle", true), gsi::arg ("include_max_angle", false), + "@brief Like \\with_angle_both, but returning two edge pair collections\n" + "The first edge pair collection will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + + method_ext ("split_with_angle_both", split_with_angle_both3, gsi::arg ("type"), + "@brief Like \\with_angle_both, but returning two edge pair collections\n" + "The first edge pair collection will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + + method_ext ("with_abs_angle_both", with_abs_angle_both1, gsi::arg ("angle"), gsi::arg ("inverse"), + "@brief Filter the edge pairs by orientation of both of their edges\n" + "\n" + "This method behaves like \\with_angle_both, but angles are always positive - i.e. there is no " + "differentiation between edges sloping 'down' vs. edges sloping 'up.\n" + "\n" + "This method has been added in version 0.29.1.\n" + ) + + method_ext ("with_abs_angle_both", with_abs_angle_both2, gsi::arg ("min_angle"), gsi::arg ("max_angle"), gsi::arg ("inverse"), gsi::arg ("include_min_angle", true), gsi::arg ("include_max_angle", false), + "\n" + "This method behaves like \\with_angle_both, but angles are always positive - i.e. there is no " + "differentiation between edges sloping 'down' vs. edges sloping 'up.\n" + "\n" + "This method has been added in version 0.29.1.\n" + ) + + method_ext ("split_with_abs_angle_both", split_with_abs_angle_both1, gsi::arg ("angle"), + "@brief Like \\with_abs_angle_both, but returning two edge pair collections\n" + "The first edge pair collection will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + + method_ext ("split_with_abs_angle_both", split_with_abs_angle_both2, gsi::arg ("min_angle"), gsi::arg ("max_angle"), gsi::arg ("include_min_angle", true), gsi::arg ("include_max_angle", false), + "@brief Like \\with_abs_angle_both, but returning two edge pair collections\n" + "The first edge pair collection will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + method_ext ("with_area", with_area1, gsi::arg ("area"), gsi::arg ("inverse"), "@brief Filters the edge pairs by the enclosed area\n" "Filters the edge pairs in the edge pair collection by enclosed area. If \"inverse\" is false, only " @@ -1164,6 +1405,18 @@ Class decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs", "\n" "This method has been added in version 0.27.2.\n" ) + + method_ext ("split_with_area", split_with_area1, gsi::arg ("area"), + "@brief Like \\with_area, but returning two edge pair collections\n" + "The first edge pair collection will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + + method_ext ("split_with_area", split_with_area2, gsi::arg ("min_area"), gsi::arg ("max_area"), + "@brief Like \\with_area, but returning two edge pair collections\n" + "The first edge pair collection will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + method_ext ("with_internal_angle", with_internal_angle1, gsi::arg ("angle"), gsi::arg ("inverse"), "@brief Filters the edge pairs by the angle between their edges\n" "Filters the edge pairs in the edge pair collection by the angle between their edges. If \"inverse\" is false, only " @@ -1187,6 +1440,18 @@ Class decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs", "\n" "This method has been added in version 0.27.2.\n" ) + + method_ext ("split_with_internal_angle", split_with_internal_angle1, gsi::arg ("angle"), + "@brief Like \\with_internal_angle, but returning two edge pair collections\n" + "The first edge pair collection will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + + method_ext ("split_with_internal_angle", split_with_internal_angle2, gsi::arg ("min_angle"), gsi::arg ("max_angle"), gsi::arg ("include_min_angle", true), gsi::arg ("include_max_angle", false), + "@brief Like \\with_internal_angle, but returning two edge pair collections\n" + "The first edge pair collection will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + method_ext ("polygons", &polygons1, "@brief Converts the edge pairs to polygons\n" "This method creates polygons from the edge pairs. Each polygon will be a triangle or quadrangle " diff --git a/src/db/db/gsiDeclDbEdges.cc b/src/db/db/gsiDeclDbEdges.cc index 76181040e..51722c2f9 100644 --- a/src/db/db/gsiDeclDbEdges.cc +++ b/src/db/db/gsiDeclDbEdges.cc @@ -399,6 +399,11 @@ static db::Edges filtered (const db::Edges *r, const EdgeFilterImpl *f) return r->filtered (*f); } +static std::vector split_filter (const db::Edges *r, const EdgeFilterImpl *f) +{ + return as_2edges_vector (r->split_filter (*f)); +} + static void filter (db::Edges *r, const EdgeFilterImpl *f) { r->filter (*f); @@ -432,42 +437,84 @@ static db::Edges with_length1 (const db::Edges *r, db::Edges::distance_type leng return r->filtered (f); } +static std::vector split_with_length1 (const db::Edges *r, db::Edges::distance_type length) +{ + db::EdgeLengthFilter f (length, length + 1, false); + return as_2edges_vector (r->split_filter (f)); +} + static db::Edges with_length2 (const db::Edges *r, const tl::Variant &min, const tl::Variant &max, bool inverse) { db::EdgeLengthFilter f (min.is_nil () ? db::Edges::distance_type (0) : min.to (), max.is_nil () ? std::numeric_limits ::max () : max.to (), inverse); return r->filtered (f); } +static std::vector split_with_length2 (const db::Edges *r, const tl::Variant &min, const tl::Variant &max) +{ + db::EdgeLengthFilter f (min.is_nil () ? db::Edges::distance_type (0) : min.to (), max.is_nil () ? std::numeric_limits ::max () : max.to (), false); + return as_2edges_vector (r->split_filter (f)); +} + static db::Edges with_angle1 (const db::Edges *r, double a, bool inverse) { db::EdgeOrientationFilter f (a, inverse, false); return r->filtered (f); } +static std::vector split_with_angle1 (const db::Edges *r, double a) +{ + db::EdgeOrientationFilter f (a, false, false); + return as_2edges_vector (r->split_filter (f)); +} + static db::Edges with_angle2 (const db::Edges *r, double amin, double amax, bool inverse, bool include_amin, bool include_amax) { db::EdgeOrientationFilter f (amin, include_amin, amax, include_amax, inverse, false); return r->filtered (f); } +static std::vector split_with_angle2 (const db::Edges *r, double amin, double amax, bool include_amin, bool include_amax) +{ + db::EdgeOrientationFilter f (amin, include_amin, amax, include_amax, false, false); + return as_2edges_vector (r->split_filter (f)); +} + static db::Edges with_abs_angle1 (const db::Edges *r, double a, bool inverse) { db::EdgeOrientationFilter f (a, inverse, true); return r->filtered (f); } +static std::vector split_with_abs_angle1 (const db::Edges *r, double a) +{ + db::EdgeOrientationFilter f (a, false, true); + return as_2edges_vector (r->split_filter (f)); +} + static db::Edges with_abs_angle2 (const db::Edges *r, double amin, double amax, bool inverse, bool include_amin, bool include_amax) { db::EdgeOrientationFilter f (amin, include_amin, amax, include_amax, inverse, true); return r->filtered (f); } +static std::vector split_with_abs_angle2 (const db::Edges *r, double amin, double amax, bool include_amin, bool include_amax) +{ + db::EdgeOrientationFilter f (amin, include_amin, amax, include_amax, false, true); + return as_2edges_vector (r->split_filter (f)); +} + static db::Edges with_angle3 (const db::Edges *r, db::SpecialEdgeOrientationFilter::FilterType type, bool inverse) { db::SpecialEdgeOrientationFilter f (type, inverse); return r->filtered (f); } +static std::vector split_with_angle3 (const db::Edges *r, db::SpecialEdgeOrientationFilter::FilterType type) +{ + db::SpecialEdgeOrientationFilter f (type, false); + return as_2edges_vector (r->split_filter (f)); +} + static db::EdgePairs width2 (const db::Edges *r, db::Edges::coord_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, db::zero_distance_mode zd_mode) { return r->width_check (d, db::EdgesCheckOptions (whole_edges, @@ -867,12 +914,18 @@ Class decl_Edges (decl_dbShapeCollection, "db", "Edges", "\n" "This method has been introduced in version 0.29.\n" ) + - method_ext ("filtered", &filtered, gsi::arg ("filtered"), + method_ext ("filtered", &filtered, gsi::arg ("filter"), "@brief Applies a generic filter and returns a filtered copy\n" "See \\EdgeFilter for a description of this feature.\n" "\n" "This method has been introduced in version 0.29.\n" ) + + method_ext ("split_filter", &split_filter, gsi::arg ("filter"), + "@brief Applies a generic filter and returns a copy with all matching shapes and one with the non-matching ones\n" + "See \\EdgeFilter for a description of this feature.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + method_ext ("process", &process_ee, gsi::arg ("process"), "@brief Applies a generic edge processor in place (replacing the edges from the Edges collection)\n" "See \\EdgeProcessor for a description of this feature.\n" @@ -913,6 +966,18 @@ Class decl_Edges (decl_dbShapeCollection, "db", "Edges", "\n" "If you don't want to specify a lower or upper limit, pass nil to that parameter.\n" ) + + method_ext ("split_with_length", split_with_length1, gsi::arg ("length"), + "@brief Like \\with_length, but returning two edge collections\n" + "The first edge collection will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + + method_ext ("split_with_length", split_with_length2, gsi::arg ("min_length"), gsi::arg ("max_length"), + "@brief Like \\with_length, but returning two edge collections\n" + "The first edge collection will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + method_ext ("with_angle", with_angle1, gsi::arg ("angle"), gsi::arg ("inverse"), "@brief Filters the edges by orientation\n" "Filters the edges in the edge collection by orientation. If \"inverse\" is false, only " @@ -937,6 +1002,35 @@ Class decl_Edges (decl_dbShapeCollection, "db", "Edges", "\n" "The two \"include..\" arguments have been added in version 0.27.\n" ) + + method_ext ("with_angle", with_angle3, gsi::arg ("type"), gsi::arg ("inverse"), + "@brief Filters the edges by orientation type\n" + "Filters the edges in the edge collection by orientation. If \"inverse\" is false, only " + "edges which have an angle of the given type are returned. If \"inverse\" is true, " + "edges which do not conform to this criterion are returned.\n" + "\n" + "This version allows specifying an edge type instead of an angle. Edge types include multiple distinct orientations " + "and are specified using one of the \\OrthoEdges, \\DiagonalEdges or \\OrthoDiagonalEdges types.\n" + "\n" + "This method has been added in version 0.28.\n" + ) + + method_ext ("split_with_angle", split_with_angle1, gsi::arg ("angle"), + "@brief Like \\with_angle, but returning two edge collections\n" + "The first edge collection will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + + method_ext ("split_with_angle", split_with_angle2, gsi::arg ("min_angle"), gsi::arg ("max_angle"), gsi::arg ("include_min_angle", true), gsi::arg ("include_max_angle", false), + "@brief Like \\with_angle, but returning two edge collections\n" + "The first edge collection will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + + method_ext ("split_with_angle", split_with_angle3, gsi::arg ("type"), + "@brief Like \\with_angle, but returning two edge collections\n" + "The first edge collection will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + method_ext ("with_abs_angle", with_abs_angle1, gsi::arg ("angle"), gsi::arg ("inverse"), "@brief Filter the edges by orientation\n" "\n" @@ -953,16 +1047,17 @@ Class decl_Edges (decl_dbShapeCollection, "db", "Edges", "\n" "This method has been added in version 0.29.1.\n" ) + - method_ext ("with_angle", with_angle3, gsi::arg ("type"), gsi::arg ("inverse"), - "@brief Filters the edges by orientation type\n" - "Filters the edges in the edge collection by orientation. If \"inverse\" is false, only " - "edges which have an angle of the given type are returned. If \"inverse\" is true, " - "edges which do not conform to this criterion are returned.\n" + method_ext ("split_with_abs_angle", split_with_abs_angle1, gsi::arg ("angle"), + "@brief Like \\with_abs_angle, but returning two edge collections\n" + "The first edge collection will contain all matching shapes, the other the non-matching ones.\n" "\n" - "This version allows specifying an edge type instead of an angle. Edge types include multiple distinct orientations " - "and are specified using one of the \\OrthoEdges, \\DiagonalEdges or \\OrthoDiagonalEdges types.\n" + "This method has been introduced in version 0.29.12.\n" + ) + + method_ext ("split_with_abs_angle", split_with_abs_angle2, gsi::arg ("min_angle"), gsi::arg ("max_angle"), gsi::arg ("include_min_angle", true), gsi::arg ("include_max_angle", false), + "@brief Like \\with_abs_angle, but returning two edge collections\n" + "The first edge collection will contain all matching shapes, the other the non-matching ones.\n" "\n" - "This method has been added in version 0.28.\n" + "This method has been introduced in version 0.29.12.\n" ) + method ("insert", (void (db::Edges::*)(const db::Edge &)) &db::Edges::insert, gsi::arg ("edge"), "@brief Inserts an edge\n" diff --git a/src/db/db/gsiDeclDbRegion.cc b/src/db/db/gsiDeclDbRegion.cc index 9294f23d4..0775c78ec 100644 --- a/src/db/db/gsiDeclDbRegion.cc +++ b/src/db/db/gsiDeclDbRegion.cc @@ -513,6 +513,11 @@ static db::Region filtered (const db::Region *r, const PolygonFilterImpl *f) return r->filtered (*f); } +static std::vector split_filter (const db::Region *r, const PolygonFilterImpl *f) +{ + return as_2region_vector (r->split_filter (*f)); +} + static void filter (db::Region *r, const PolygonFilterImpl *f) { r->filter (*f); @@ -544,84 +549,240 @@ static db::Region with_perimeter1 (const db::Region *r, db::Region::perimeter_ty return r->filtered (f); } +static std::vector split_with_perimeter1 (const db::Region *r, db::Region::perimeter_type perimeter) +{ + db::RegionPerimeterFilter f (perimeter, perimeter + 1, false); + return as_2region_vector (r->split_filter (f)); +} + static db::Region with_perimeter2 (const db::Region *r, const tl::Variant &min, const tl::Variant &max, bool inverse) { db::RegionPerimeterFilter f (min.is_nil () ? db::Region::perimeter_type (0) : min.to (), max.is_nil () ? std::numeric_limits ::max () : max.to (), inverse); return r->filtered (f); } +static std::vector split_with_perimeter2 (const db::Region *r, const tl::Variant &min, const tl::Variant &max) +{ + db::RegionPerimeterFilter f (min.is_nil () ? db::Region::perimeter_type (0) : min.to (), max.is_nil () ? std::numeric_limits ::max () : max.to (), false); + return as_2region_vector (r->split_filter (f)); +} + static db::Region with_area1 (const db::Region *r, db::Region::area_type area, bool inverse) { db::RegionAreaFilter f (area, area + 1, inverse); return r->filtered (f); } +static std::vector split_with_area1 (const db::Region *r, db::Region::area_type area) +{ + db::RegionAreaFilter f (area, area + 1, false); + return as_2region_vector (r->split_filter (f)); +} + static db::Region with_area2 (const db::Region *r, const tl::Variant &min, const tl::Variant &max, bool inverse) { db::RegionAreaFilter f (min.is_nil () ? db::Region::area_type (0) : min.to (), max.is_nil () ? std::numeric_limits ::max () : max.to (), inverse); return r->filtered (f); } +static std::vector split_with_area2 (const db::Region *r, const tl::Variant &min, const tl::Variant &max) +{ + db::RegionAreaFilter f (min.is_nil () ? db::Region::area_type (0) : min.to (), max.is_nil () ? std::numeric_limits ::max () : max.to (), false); + return as_2region_vector (r->split_filter (f)); +} + static db::Region with_holes1 (const db::Region *r, size_t n, bool inverse) { db::HoleCountFilter f (n, n + 1, inverse); return r->filtered (f); } +static std::vector split_with_holes1 (const db::Region *r, size_t n) +{ + db::HoleCountFilter f (n, n + 1, false); + return as_2region_vector (r->split_filter (f)); +} + static db::Region with_holes2 (const db::Region *r, const tl::Variant &min, const tl::Variant &max, bool inverse) { db::HoleCountFilter f (min.is_nil () ? size_t (0) : min.to (), max.is_nil () ? std::numeric_limits ::max () : max.to (), inverse); return r->filtered (f); } +static std::vector split_with_holes2 (const db::Region *r, const tl::Variant &min, const tl::Variant &max) +{ + db::HoleCountFilter f (min.is_nil () ? size_t (0) : min.to (), max.is_nil () ? std::numeric_limits ::max () : max.to (), false); + return as_2region_vector (r->split_filter (f)); +} + static db::Region with_bbox_width1 (const db::Region *r, db::Region::distance_type bbox_width, bool inverse) { db::RegionBBoxFilter f (bbox_width, bbox_width + 1, inverse, db::RegionBBoxFilter::BoxWidth); return r->filtered (f); } +static std::vector split_with_bbox_width1 (const db::Region *r, db::Region::distance_type bbox_width) +{ + db::RegionBBoxFilter f (bbox_width, bbox_width + 1, false, db::RegionBBoxFilter::BoxWidth); + return as_2region_vector (r->split_filter (f)); +} + static db::Region with_bbox_width2 (const db::Region *r, const tl::Variant &min, const tl::Variant &max, bool inverse) { db::RegionBBoxFilter f (min.is_nil () ? db::Region::distance_type (0) : min.to (), max.is_nil () ? std::numeric_limits ::max () : max.to (), inverse, db::RegionBBoxFilter::BoxWidth); return r->filtered (f); } +static std::vector split_with_bbox_width2 (const db::Region *r, const tl::Variant &min, const tl::Variant &max) +{ + db::RegionBBoxFilter f (min.is_nil () ? db::Region::distance_type (0) : min.to (), max.is_nil () ? std::numeric_limits ::max () : max.to (), false, db::RegionBBoxFilter::BoxWidth); + return as_2region_vector (r->split_filter (f)); +} + static db::Region with_bbox_height1 (const db::Region *r, db::Region::distance_type bbox_height, bool inverse) { db::RegionBBoxFilter f (bbox_height, bbox_height + 1, inverse, db::RegionBBoxFilter::BoxHeight); return r->filtered (f); } +static std::vector split_with_bbox_height1 (const db::Region *r, db::Region::distance_type bbox_height) +{ + db::RegionBBoxFilter f (bbox_height, bbox_height + 1, false, db::RegionBBoxFilter::BoxHeight); + return as_2region_vector (r->split_filter (f)); +} + static db::Region with_bbox_height2 (const db::Region *r, const tl::Variant &min, const tl::Variant &max, bool inverse) { db::RegionBBoxFilter f (min.is_nil () ? db::Region::distance_type (0) : min.to (), max.is_nil () ? std::numeric_limits ::max () : max.to (), inverse, db::RegionBBoxFilter::BoxHeight); return r->filtered (f); } +static std::vector split_with_bbox_height2 (const db::Region *r, const tl::Variant &min, const tl::Variant &max) +{ + db::RegionBBoxFilter f (min.is_nil () ? db::Region::distance_type (0) : min.to (), max.is_nil () ? std::numeric_limits ::max () : max.to (), false, db::RegionBBoxFilter::BoxHeight); + return as_2region_vector (r->split_filter (f)); +} + static db::Region with_bbox_min1 (const db::Region *r, db::Region::distance_type bbox_min, bool inverse) { db::RegionBBoxFilter f (bbox_min, bbox_min + 1, inverse, db::RegionBBoxFilter::BoxMinDim); return r->filtered (f); } +static std::vector split_with_bbox_min1 (const db::Region *r, db::Region::distance_type bbox_min) +{ + db::RegionBBoxFilter f (bbox_min, bbox_min + 1, false, db::RegionBBoxFilter::BoxMinDim); + return as_2region_vector (r->split_filter (f)); +} + static db::Region with_bbox_min2 (const db::Region *r, const tl::Variant &min, const tl::Variant &max, bool inverse) { db::RegionBBoxFilter f (min.is_nil () ? db::Region::distance_type (0) : min.to (), max.is_nil () ? std::numeric_limits ::max () : max.to (), inverse, db::RegionBBoxFilter::BoxMinDim); return r->filtered (f); } +static std::vector split_with_bbox_min2 (const db::Region *r, const tl::Variant &min, const tl::Variant &max) +{ + db::RegionBBoxFilter f (min.is_nil () ? db::Region::distance_type (0) : min.to (), max.is_nil () ? std::numeric_limits ::max () : max.to (), false, db::RegionBBoxFilter::BoxMinDim); + return as_2region_vector (r->split_filter (f)); +} + static db::Region with_bbox_max1 (const db::Region *r, db::Region::distance_type bbox_max, bool inverse) { db::RegionBBoxFilter f (bbox_max, bbox_max + 1, inverse, db::RegionBBoxFilter::BoxMaxDim); return r->filtered (f); } +static std::vector split_with_bbox_max1 (const db::Region *r, db::Region::distance_type bbox_max) +{ + db::RegionBBoxFilter f (bbox_max, bbox_max + 1, false, db::RegionBBoxFilter::BoxMaxDim); + return as_2region_vector (r->split_filter (f)); +} + static db::Region with_bbox_max2 (const db::Region *r, const tl::Variant &min, const tl::Variant &max, bool inverse) { db::RegionBBoxFilter f (min.is_nil () ? db::Region::distance_type (0) : min.to (), max.is_nil () ? std::numeric_limits ::max () : max.to (), inverse, db::RegionBBoxFilter::BoxMaxDim); return r->filtered (f); } +static std::vector split_with_bbox_max2 (const db::Region *r, const tl::Variant &min, const tl::Variant &max) +{ + db::RegionBBoxFilter f (min.is_nil () ? db::Region::distance_type (0) : min.to (), max.is_nil () ? std::numeric_limits ::max () : max.to (), false, db::RegionBBoxFilter::BoxMaxDim); + return as_2region_vector (r->split_filter (f)); +} + +static db::Region with_bbox_aspect_ratio1 (const db::Region *r, double v, bool inverse) +{ + db::RegionRatioFilter f (v, true, v, true, inverse, db::RegionRatioFilter::AspectRatio); + return r->filtered (f); +} + +static std::vector split_with_bbox_aspect_ratio1 (const db::Region *r, double v) +{ + db::RegionRatioFilter f (v, true, v, true, false, db::RegionRatioFilter::AspectRatio); + return as_2region_vector (r->split_filter (f)); +} + +static db::Region with_bbox_aspect_ratio2 (const db::Region *r, const tl::Variant &min, const tl::Variant &max, bool inverse, bool min_included, bool max_included) +{ + db::RegionRatioFilter f (min.is_nil () ? 0.0 : min.to (), min_included, max.is_nil () ? std::numeric_limits ::max () : max.to (), max_included, inverse, db::RegionRatioFilter::AspectRatio); + return r->filtered (f); +} + +static std::vector split_with_bbox_aspect_ratio2 (const db::Region *r, const tl::Variant &min, const tl::Variant &max, bool min_included, bool max_included) +{ + db::RegionRatioFilter f (min.is_nil () ? 0.0 : min.to (), min_included, max.is_nil () ? std::numeric_limits ::max () : max.to (), max_included, false, db::RegionRatioFilter::AspectRatio); + return as_2region_vector (r->split_filter (f)); +} + +static db::Region with_area_ratio1 (const db::Region *r, double v, bool inverse) +{ + db::RegionRatioFilter f (v, true, v, true, inverse, db::RegionRatioFilter::AreaRatio); + return r->filtered (f); +} + +static std::vector split_with_area_ratio1 (const db::Region *r, double v) +{ + db::RegionRatioFilter f (v, true, v, true, false, db::RegionRatioFilter::AreaRatio); + return as_2region_vector (r->split_filter (f)); +} + +static db::Region with_area_ratio2 (const db::Region *r, const tl::Variant &min, const tl::Variant &max, bool inverse, bool min_included, bool max_included) +{ + db::RegionRatioFilter f (min.is_nil () ? 0.0 : min.to (), min_included, max.is_nil () ? std::numeric_limits ::max () : max.to (), max_included, inverse, db::RegionRatioFilter::AreaRatio); + return r->filtered (f); +} + +static std::vector split_with_area_ratio2 (const db::Region *r, const tl::Variant &min, const tl::Variant &max, bool min_included, bool max_included) +{ + db::RegionRatioFilter f (min.is_nil () ? 0.0 : min.to (), min_included, max.is_nil () ? std::numeric_limits ::max () : max.to (), max_included, false, db::RegionRatioFilter::AreaRatio); + return as_2region_vector (r->split_filter (f)); +} + +static db::Region with_relative_height1 (const db::Region *r, double v, bool inverse) +{ + db::RegionRatioFilter f (v, true, v, true, inverse, db::RegionRatioFilter::RelativeHeight); + return r->filtered (f); +} + +static std::vector split_with_relative_height1 (const db::Region *r, double v) +{ + db::RegionRatioFilter f (v, true, v, true, false, db::RegionRatioFilter::RelativeHeight); + return as_2region_vector (r->split_filter (f)); +} + +static db::Region with_relative_height2 (const db::Region *r, const tl::Variant &min, const tl::Variant &max, bool inverse, bool min_included, bool max_included) +{ + db::RegionRatioFilter f (min.is_nil () ? 0.0 : min.to (), min_included, max.is_nil () ? std::numeric_limits ::max () : max.to (), max_included, inverse, db::RegionRatioFilter::RelativeHeight); + return r->filtered (f); +} + +static std::vector split_with_relative_height2 (const db::Region *r, const tl::Variant &min, const tl::Variant &max, bool min_included, bool max_included) +{ + db::RegionRatioFilter f (min.is_nil () ? 0.0 : min.to (), min_included, max.is_nil () ? std::numeric_limits ::max () : max.to (), max_included, false, db::RegionRatioFilter::RelativeHeight); + return as_2region_vector (r->split_filter (f)); +} + static db::EdgePairs angle_check1 (const db::Region *r, double angle, bool inverse) { return r->angle_check (angle, angle + 1e-4, inverse); @@ -632,42 +793,6 @@ static db::EdgePairs angle_check2 (const db::Region *r, double amin, double amax return r->angle_check (amin, amax, inverse); } -static db::Region with_bbox_aspect_ratio1 (const db::Region *r, double v, bool inverse) -{ - db::RegionRatioFilter f (v, true, v, true, inverse, db::RegionRatioFilter::AspectRatio); - return r->filtered (f); -} - -static db::Region with_bbox_aspect_ratio2 (const db::Region *r, const tl::Variant &min, const tl::Variant &max, bool inverse, bool min_included, bool max_included) -{ - db::RegionRatioFilter f (min.is_nil () ? 0.0 : min.to (), min_included, max.is_nil () ? std::numeric_limits ::max () : max.to (), max_included, inverse, db::RegionRatioFilter::AspectRatio); - return r->filtered (f); -} - -static db::Region with_area_ratio1 (const db::Region *r, double v, bool inverse) -{ - db::RegionRatioFilter f (v, true, v, true, inverse, db::RegionRatioFilter::AreaRatio); - return r->filtered (f); -} - -static db::Region with_area_ratio2 (const db::Region *r, const tl::Variant &min, const tl::Variant &max, bool inverse, bool min_included, bool max_included) -{ - db::RegionRatioFilter f (min.is_nil () ? 0.0 : min.to (), min_included, max.is_nil () ? std::numeric_limits ::max () : max.to (), max_included, inverse, db::RegionRatioFilter::AreaRatio); - return r->filtered (f); -} - -static db::Region with_relative_height1 (const db::Region *r, double v, bool inverse) -{ - db::RegionRatioFilter f (v, true, v, true, inverse, db::RegionRatioFilter::RelativeHeight); - return r->filtered (f); -} - -static db::Region with_relative_height2 (const db::Region *r, const tl::Variant &min, const tl::Variant &max, bool inverse, bool min_included, bool max_included) -{ - db::RegionRatioFilter f (min.is_nil () ? 0.0 : min.to (), min_included, max.is_nil () ? std::numeric_limits ::max () : max.to (), max_included, inverse, db::RegionRatioFilter::RelativeHeight); - return r->filtered (f); -} - static db::Region in (const db::Region *r, const db::Region &other) { return r->in (other, false); @@ -695,6 +820,12 @@ static db::Region non_rectangles (const db::Region *r) return r->filtered (f); } +static std::vector split_rectangles (const db::Region *r) +{ + db::RectangleFilter f (false, false); + return as_2region_vector (r->split_filter (f)); +} + static db::Region squares (const db::Region *r) { db::RectangleFilter f (true, false); @@ -707,6 +838,12 @@ static db::Region non_squares (const db::Region *r) return r->filtered (f); } +static std::vector split_squares (const db::Region *r) +{ + db::RectangleFilter f (true, false); + return as_2region_vector (r->split_filter (f)); +} + static db::Region rectilinear (const db::Region *r) { db::RectilinearFilter f (false); @@ -719,6 +856,12 @@ static db::Region non_rectilinear (const db::Region *r) return r->filtered (f); } +static std::vector split_rectilinear (const db::Region *r) +{ + db::RectilinearFilter f (false); + return as_2region_vector (r->split_filter (f)); +} + static void break_polygons (db::Region *r, size_t max_vertex_count, double max_area_ratio) { r->process (db::PolygonBreaker (max_vertex_count, max_area_ratio)); @@ -1416,6 +1559,18 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + + method_ext ("split_with_perimeter", split_with_perimeter1, gsi::arg ("perimeter"), + "@brief Like \\with_perimeter, but returning two regions\n" + "The first region will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + + method_ext ("split_with_perimeter", split_with_perimeter2, gsi::arg ("min_perimeter"), gsi::arg ("max_perimeter"), + "@brief Like \\with_perimeter, but returning two regions\n" + "The first region will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + method_ext ("with_area", with_area1, gsi::arg ("area"), gsi::arg ("inverse"), "@brief Filter the polygons by area\n" "Filters the polygons of the region by area. If \"inverse\" is false, only " @@ -1436,6 +1591,18 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + + method_ext ("split_with_area", split_with_area1, gsi::arg ("area"), + "@brief Like \\with_area, but returning two regions\n" + "The first region will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + + method_ext ("split_with_area", split_with_area2, gsi::arg ("min_area"), gsi::arg ("max_area"), + "@brief Like \\with_area, but returning two regions\n" + "The first region will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + method_ext ("with_holes", with_holes1, gsi::arg ("nholes"), gsi::arg ("inverse"), "@brief Filters the polygons by their number of holes\n" "Filters the polygons of the region by number of holes. If \"inverse\" is false, only " @@ -1446,7 +1613,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "This method has been introduced in version 0.27.\n" ) + - method_ext ("with_holes", with_holes2, gsi::arg ("min_bholes"), gsi::arg ("max_nholes"), gsi::arg ("inverse"), + method_ext ("with_holes", with_holes2, gsi::arg ("min_nholes"), gsi::arg ("max_nholes"), gsi::arg ("inverse"), "@brief Filter the polygons by their number of holes\n" "Filters the polygons of the region by number of holes. If \"inverse\" is false, only " "polygons which have a hole count larger or equal to \"min_nholes\" and less than \"max_nholes\" are " @@ -1460,6 +1627,18 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "This method has been introduced in version 0.27.\n" ) + + method_ext ("split_with_holes", split_with_holes1, gsi::arg ("nholes"), + "@brief Like \\with_holes, but returning two regions\n" + "The first region will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + + method_ext ("split_with_holes", split_with_holes2, gsi::arg ("min_nholes"), gsi::arg ("max_nholes"), + "@brief Like \\with_holes, but returning two regions\n" + "The first region will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + method_ext ("with_bbox_width", with_bbox_width1, gsi::arg ("width"), gsi::arg ("inverse"), "@brief Filter the polygons by bounding box width\n" "Filters the polygons of the region by the width of their bounding box. If \"inverse\" is false, only " @@ -1478,6 +1657,18 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + + method_ext ("split_with_bbox_width", split_with_bbox_width1, gsi::arg ("width"), + "@brief Like \\with_bbox_width, but returning two regions\n" + "The first region will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + + method_ext ("split_with_bbox_width", split_with_bbox_width2, gsi::arg ("min_width"), gsi::arg ("max_width"), + "@brief Like \\with_bbox_width, but returning two regions\n" + "The first region will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + method_ext ("with_bbox_height", with_bbox_height1, gsi::arg ("height"), gsi::arg ("inverse"), "@brief Filter the polygons by bounding box height\n" "Filters the polygons of the region by the height of their bounding box. If \"inverse\" is false, only " @@ -1496,6 +1687,18 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + + method_ext ("split_with_bbox_height", split_with_bbox_height1, gsi::arg ("height"), + "@brief Like \\with_bbox_height, but returning two regions\n" + "The first region will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + + method_ext ("split_with_bbox_height", split_with_bbox_height2, gsi::arg ("min_height"), gsi::arg ("max_height"), + "@brief Like \\with_bbox_height, but returning two regions\n" + "The first region will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + method_ext ("with_bbox_min", with_bbox_min1, gsi::arg ("dim"), gsi::arg ("inverse"), "@brief Filter the polygons by bounding box width or height, whichever is smaller\n" "Filters the polygons inside the region by the minimum dimension of their bounding box. " @@ -1516,6 +1719,18 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + + method_ext ("split_with_bbox_min", split_with_bbox_min1, gsi::arg ("dim"), + "@brief Like \\with_bbox_min, but returning two regions\n" + "The first region will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + + method_ext ("split_with_bbox_min", split_with_bbox_min2, gsi::arg ("min_dim"), gsi::arg ("max_dim"), + "@brief Like \\with_bbox_min, but returning two regions\n" + "The first region will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + method_ext ("with_bbox_max", with_bbox_max1, gsi::arg ("dim"), gsi::arg ("inverse"), "@brief Filter the polygons by bounding box width or height, whichever is larger\n" "Filters the polygons of the region by the maximum dimension of their bounding box. " @@ -1536,6 +1751,18 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + + method_ext ("split_with_bbox_max", split_with_bbox_max1, gsi::arg ("dim"), + "@brief Like \\with_bbox_max, but returning two regions\n" + "The first region will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + + method_ext ("split_with_bbox_max", split_with_bbox_max2, gsi::arg ("min_dim"), gsi::arg ("max_dim"), + "@brief Like \\with_bbox_max, but returning two regions\n" + "The first region will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + method_ext ("with_bbox_aspect_ratio", with_bbox_aspect_ratio1, gsi::arg ("ratio"), gsi::arg ("inverse"), "@brief Filters the polygons by the aspect ratio of their bounding boxes\n" "Filters the polygons of the region by the aspect ratio of their bounding boxes. " @@ -1565,6 +1792,18 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "This method has been introduced in version 0.27.\n" ) + + method_ext ("split_with_bbox_aspect_ratio", split_with_bbox_aspect_ratio1, gsi::arg ("ratio"), + "@brief Like \\with_bbox_aspect_ratio, but returning two regions\n" + "The first region will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + + method_ext ("split_with_bbox_aspect_ratio", split_with_bbox_aspect_ratio2, gsi::arg ("min_ratio"), gsi::arg ("max_ratio"), gsi::arg ("min_included", true), gsi::arg ("max_included", true), + "@brief Like \\with_bbox_aspect_ratio, but returning two regions\n" + "The first region will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + method_ext ("with_area_ratio", with_area_ratio1, gsi::arg ("ratio"), gsi::arg ("inverse"), "@brief Filters the polygons by the bounding box area to polygon area ratio\n" "The area ratio is defined by the ratio of bounding box area to polygon area. It's a measure " @@ -1594,6 +1833,18 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "This method has been introduced in version 0.27.\n" ) + + method_ext ("split_with_area_ratio", split_with_area_ratio1, gsi::arg ("ratio"), + "@brief Like \\with_area_ratio, but returning two regions\n" + "The first region will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + + method_ext ("split_with_area_ratio", split_with_area_ratio2, gsi::arg ("min_ratio"), gsi::arg ("max_ratio"), gsi::arg ("min_included", true), gsi::arg ("max_included", true), + "@brief Like \\with_area_ratio, but returning two regions\n" + "The first region will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + method_ext ("with_relative_height", with_relative_height1, gsi::arg ("ratio"), gsi::arg ("inverse"), "@brief Filters the polygons by the ratio of height to width\n" "This method filters the polygons of the region by the ratio of height vs. width of their bounding boxes. " @@ -1625,6 +1876,18 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "This method has been introduced in version 0.27.\n" ) + + method_ext ("split_with_relative_height", split_with_relative_height1, gsi::arg ("ratio"), + "@brief Like \\with_relative_height, but returning two regions\n" + "The first region will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + + method_ext ("split_with_relative_height", split_with_relative_height2, gsi::arg ("min_ratio"), gsi::arg ("max_ratio"), gsi::arg ("min_included", true), gsi::arg ("max_included", true), + "@brief Like \\with_relative_height, but returning two regions\n" + "The first region will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + method ("strange_polygon_check", &db::Region::strange_polygon_check, "@brief Returns a region containing those parts of polygons which are \"strange\"\n" "Strange parts of polygons are self-overlapping parts or non-orientable parts (i.e. in the \"8\" configuration).\n" @@ -2849,12 +3112,18 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "This method has been introduced in version 0.29.\n" ) + - method_ext ("filtered", &filtered, gsi::arg ("filtered"), + method_ext ("filtered", &filtered, gsi::arg ("filter"), "@brief Applies a generic filter and returns a filtered copy\n" "See \\PolygonFilter for a description of this feature.\n" "\n" "This method has been introduced in version 0.29.\n" ) + + method_ext ("split_filter", &split_filter, gsi::arg ("filter"), + "@brief Applies a generic filter and returns a copy with all matching shapes and one with the non-matching ones\n" + "See \\PolygonFilter for a description of this feature.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + method_ext ("process", &process_pp, gsi::arg ("process"), "@brief Applies a generic polygon processor in place (replacing the polygons from the Region)\n" "See \\PolygonProcessor for a description of this feature.\n" @@ -2889,6 +3158,12 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "This method returns all polygons in self which are not rectangles." "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + + method_ext ("split_rectangles", &split_rectangles, + "@brief Combined results of \\rectangles and \\non_rectangles\n" + "This method returns a list with two Regions, the first is the result of \\rectangles, the second the result of \\non_rectangles. " + "Using this method is faster when you need both.\n\n" + "This method has been introduced in version 0.29.12.\n" + ) + method_ext ("squares", &squares, "@brief Returns all polygons which are squares\n" "This method returns all polygons in self which are squares." @@ -2903,6 +3178,12 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "This method has been introduced in version 0.27.\n" ) + + method_ext ("split_squares", &split_squares, + "@brief Combined results of \\squares and \\non_squares\n" + "This method returns a list with two Regions, the first is the result of \\squares, the second the result of \\non_squares. " + "Using this method is faster when you need both.\n\n" + "This method has been introduced in version 0.29.12.\n" + ) + method_ext ("rectilinear", &rectilinear, "@brief Returns all polygons which are rectilinear\n" "This method returns all polygons in self which are rectilinear." @@ -2913,6 +3194,12 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "This method returns all polygons in self which are not rectilinear." "Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n" ) + + method_ext ("split_rectilinear", &split_rectilinear, + "@brief Combined results of \\rectilinear and \\non_rectilinear\n" + "This method returns a list with two Regions, the first is the result of \\rectilinear, the second the result of \\non_rectilinear. " + "Using this method is faster when you need both.\n\n" + "This method has been introduced in version 0.29.12.\n" + ) + method_ext ("break_polygons|#break", &break_polygons, gsi::arg ("max_vertex_count"), gsi::arg ("max_area_ratio", 0.0), "@brief Breaks the polygons of the region into smaller ones\n" "\n" diff --git a/src/db/db/gsiDeclDbTexts.cc b/src/db/db/gsiDeclDbTexts.cc index 241e734c4..227a754c3 100644 --- a/src/db/db/gsiDeclDbTexts.cc +++ b/src/db/db/gsiDeclDbTexts.cc @@ -187,6 +187,15 @@ Class > decl_TextToPolygonP // --------------------------------------------------------------------------------- // Texts binding +static inline std::vector as_2texts_vector (const std::pair &rp) +{ + std::vector res; + res.reserve (2); + res.push_back (db::Texts (const_cast (rp.first).take_delegate ())); + res.push_back (db::Texts (const_cast (rp.second).take_delegate ())); + return res; +} + static db::Texts *new_v () { return new db::Texts (); @@ -316,6 +325,11 @@ static void filter (db::Texts *r, const TextFilterImpl *f) r->filter (*f); } +static std::vector split_filter (const db::Texts *r, const TextFilterImpl *f) +{ + return as_2texts_vector (r->split_filter (*f)); +} + static db::Texts processed_tt (const db::Texts *r, const shape_processor_impl *f) { return r->processed (*f); @@ -339,12 +353,24 @@ static db::Texts with_text (const db::Texts *r, const std::string &text, bool in return r->filtered (f); } +static std::vector split_with_text (const db::Texts *r, const std::string &text) +{ + db::TextStringFilter f (text, false); + return as_2texts_vector (r->split_filter (f)); +} + static db::Texts with_match (const db::Texts *r, const std::string &pattern, bool inverse) { db::TextPatternFilter f (pattern, inverse); return r->filtered (f); } +static std::vector split_with_match (const db::Texts *r, const std::string &pattern) +{ + db::TextPatternFilter f (pattern, false); + return as_2texts_vector (r->split_filter (f)); +} + static db::Region pull_interacting (const db::Texts *r, const db::Region &other) { db::Region out; @@ -600,6 +626,12 @@ Class decl_Texts (decl_dbShapeCollection, "db", "Texts", "\n" "This method has been introduced in version 0.29.\n" ) + + method_ext ("split_filter", &split_filter, gsi::arg ("filter"), + "@brief Applies a generic filter and returns a copy with all matching shapes and one with the non-matching ones\n" + "See \\TextFilter for a description of this feature.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + method_ext ("process", &process_tt, gsi::arg ("process"), "@brief Applies a generic text processor in place (replacing the texts from the text collection)\n" "See \\TextProcessor for a description of this feature.\n" @@ -623,12 +655,24 @@ Class decl_Texts (decl_dbShapeCollection, "db", "Texts", "If \"inverse\" is false, this method returns the texts with the given string.\n" "If \"inverse\" is true, this method returns the texts not having the given string.\n" ) + + method_ext ("split_with_text", split_with_text, gsi::arg ("text"), + "@brief Like \\with_text, but returning two text collections\n" + "The first text collection will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + method_ext ("with_match", with_match, gsi::arg ("pattern"), gsi::arg ("inverse"), "@brief Filter the text by glob pattern\n" "\"pattern\" is a glob-style pattern (e.g. \"A*\" will select all texts starting with a capital \"A\").\n" "If \"inverse\" is false, this method returns the texts matching the pattern.\n" "If \"inverse\" is true, this method returns the texts not matching the pattern.\n" ) + + method_ext ("split_with_match", split_with_match, gsi::arg ("pattern"), + "@brief Like \\with_match, but returning two text collections\n" + "The first text collection will contain all matching shapes, the other the non-matching ones.\n" + "\n" + "This method has been introduced in version 0.29.12.\n" + ) + method ("interacting|&", (db::Texts (db::Texts::*) (const db::Region &) const) &db::Texts::selected_interacting, gsi::arg ("other"), "@brief Returns the texts from this text collection which are inside or on the edge of polygons from the given region\n" "\n"