mirror of https://github.com/KLayout/klayout.git
First implementation of pull* methods
This commit is contained in:
parent
1c16cea421
commit
74880a5198
|
|
@ -27,6 +27,7 @@
|
|||
#include "dbFlatEdges.h"
|
||||
#include "dbEmptyRegion.h"
|
||||
#include "dbEmptyEdgePairs.h"
|
||||
#include "dbEmptyEdges.h"
|
||||
#include "dbRegion.h"
|
||||
#include "dbRegionUtils.h"
|
||||
#include "dbShapeProcessor.h"
|
||||
|
|
@ -337,7 +338,7 @@ AsIfFlatRegion::selected_interacting_generic (const Edges &other, bool inverse)
|
|||
scanner.reserve2 (other.size ());
|
||||
|
||||
std::auto_ptr<FlatRegion> output (new FlatRegion (false));
|
||||
region_to_edge_interaction_filter<Shapes> filter (output->raw_polygons (), inverse);
|
||||
region_to_edge_interaction_filter<Shapes, db::Polygon> filter (output->raw_polygons (), inverse);
|
||||
|
||||
AddressablePolygonDelivery p (begin_merged (), has_valid_merged_polygons ());
|
||||
|
||||
|
|
@ -423,6 +424,92 @@ AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, boo
|
|||
return output.release ();
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
AsIfFlatRegion::pull_generic (const Edges &other) const
|
||||
{
|
||||
if (other.empty ()) {
|
||||
return other.delegate ()->clone ();
|
||||
} else if (empty ()) {
|
||||
return new EmptyEdges ();
|
||||
}
|
||||
|
||||
db::box_scanner2<db::Polygon, size_t, db::Edge, size_t> scanner (report_progress (), progress_desc ());
|
||||
scanner.reserve1 (size ());
|
||||
scanner.reserve2 (other.size ());
|
||||
|
||||
std::auto_ptr<FlatEdges> output (new FlatEdges (false));
|
||||
region_to_edge_interaction_filter<Shapes, db::Edge> filter (output->raw_edges (), false);
|
||||
|
||||
AddressablePolygonDelivery p (begin_merged (), has_valid_merged_polygons ());
|
||||
|
||||
for ( ; ! p.at_end (); ++p) {
|
||||
scanner.insert1 (p.operator-> (), 0);
|
||||
}
|
||||
|
||||
AddressableEdgeDelivery e (other.addressable_edges ());
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
scanner.insert2 (e.operator-> (), 0);
|
||||
}
|
||||
|
||||
scanner.process (filter, 1, db::box_convert<db::Polygon> (), db::box_convert<db::Edge> ());
|
||||
|
||||
return output.release ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
AsIfFlatRegion::pull_generic (const Region &other, int mode, bool touching) const
|
||||
{
|
||||
db::EdgeProcessor ep (report_progress (), progress_desc ());
|
||||
ep.set_base_verbosity (base_verbosity ());
|
||||
|
||||
// shortcut
|
||||
if (empty ()) {
|
||||
return clone ();
|
||||
} else if (other.empty ()) {
|
||||
return new EmptyRegion ();
|
||||
}
|
||||
|
||||
size_t n = 1;
|
||||
for (RegionIterator p = other.begin (); ! p.at_end (); ++p, ++n) {
|
||||
if (p->box ().touches (bbox ())) {
|
||||
ep.insert (*p, n);
|
||||
}
|
||||
}
|
||||
|
||||
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) {
|
||||
if (mode > 0 || p->box ().touches (other.bbox ())) {
|
||||
ep.insert (*p, 0);
|
||||
}
|
||||
}
|
||||
|
||||
db::InteractionDetector id (mode, 0);
|
||||
id.set_include_touching (touching);
|
||||
db::EdgeSink es;
|
||||
ep.process (es, id);
|
||||
id.finish ();
|
||||
|
||||
std::auto_ptr<FlatRegion> output (new FlatRegion (false));
|
||||
|
||||
n = 0;
|
||||
std::set <size_t> selected;
|
||||
for (db::InteractionDetector::iterator i = id.begin (); i != id.end () && i->first == 0; ++i) {
|
||||
++n;
|
||||
selected.insert (i->second);
|
||||
}
|
||||
|
||||
output->reserve (n);
|
||||
|
||||
n = 1;
|
||||
for (RegionIterator p = other.begin (); ! p.at_end (); ++p, ++n) {
|
||||
if (selected.find (n) != selected.end ()) {
|
||||
output->raw_polygons ().insert (*p);
|
||||
}
|
||||
}
|
||||
|
||||
return output.release ();
|
||||
}
|
||||
|
||||
template <class Trans>
|
||||
void
|
||||
AsIfFlatRegion::produce_markers_for_grid_check (const db::Polygon &poly, const Trans &tr, db::Coord gx, db::Coord gy, db::Shapes &shapes)
|
||||
|
|
|
|||
|
|
@ -205,6 +205,26 @@ public:
|
|||
return selected_interacting_generic (other, 0, false, true);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *pull_inside (const Region &other) const
|
||||
{
|
||||
return pull_generic (other, -1, true);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *pull_interacting (const Region &other) const
|
||||
{
|
||||
return pull_generic (other, 0, true);
|
||||
}
|
||||
|
||||
virtual EdgesDelegate *pull_interacting (const Edges &other) const
|
||||
{
|
||||
return pull_generic (other);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *pull_overlapping (const Region &other) const
|
||||
{
|
||||
return pull_generic (other, 0, false);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *in (const Region &other, bool invert) const;
|
||||
|
||||
virtual bool equals (const Region &other) const;
|
||||
|
|
@ -220,6 +240,8 @@ protected:
|
|||
EdgePairsDelegate *run_single_polygon_check (db::edge_relation_type rel, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const;
|
||||
RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse) const;
|
||||
RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse) const;
|
||||
RegionDelegate *pull_generic (const Region &other, int mode, bool touching) const;
|
||||
EdgesDelegate *pull_generic (const Edges &other) const;
|
||||
|
||||
template <class Trans>
|
||||
static void produce_markers_for_grid_check (const db::Polygon &poly, const Trans &tr, db::Coord gx, db::Coord gy, db::Shapes &shapes);
|
||||
|
|
|
|||
|
|
@ -1617,8 +1617,82 @@ private:
|
|||
mutable db::EdgeProcessor m_ep;
|
||||
};
|
||||
|
||||
class PullLocalOperation
|
||||
: public local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef>
|
||||
{
|
||||
public:
|
||||
PullLocalOperation (int mode, bool touching)
|
||||
: m_mode (mode), m_touching (touching)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual void compute_local (db::Layout * /*layout*/, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::unordered_set<db::PolygonRef> &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||
{
|
||||
m_ep.clear ();
|
||||
|
||||
std::set<db::PolygonRef> others;
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.intruder_shape (*j));
|
||||
}
|
||||
}
|
||||
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
const db::PolygonRef &subject = interactions.subject_shape (i->first);
|
||||
for (db::PolygonRef::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end(); ++e) {
|
||||
m_ep.insert (*e, 0);
|
||||
}
|
||||
}
|
||||
|
||||
size_t n = 1;
|
||||
for (std::set<db::PolygonRef>::const_iterator o = others.begin (); o != others.end (); ++o, ++n) {
|
||||
for (db::PolygonRef::polygon_edge_iterator e = o->begin_edge (); ! e.at_end(); ++e) {
|
||||
m_ep.insert (*e, n);
|
||||
}
|
||||
}
|
||||
|
||||
db::InteractionDetector id (m_mode, 0);
|
||||
id.set_include_touching (m_touching);
|
||||
db::EdgeSink es;
|
||||
m_ep.process (es, id);
|
||||
id.finish ();
|
||||
|
||||
n = 0;
|
||||
std::set <size_t> selected;
|
||||
for (db::InteractionDetector::iterator i = id.begin (); i != id.end () && i->first == 0; ++i) {
|
||||
++n;
|
||||
selected.insert (i->second);
|
||||
}
|
||||
|
||||
n = 1;
|
||||
for (std::set<db::PolygonRef>::const_iterator o = others.begin (); o != others.end (); ++o, ++n) {
|
||||
if (selected.find (n) != selected.end ()) {
|
||||
result.insert (*o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual on_empty_intruder_mode on_empty_intruder_hint () const
|
||||
{
|
||||
return Drop;
|
||||
}
|
||||
|
||||
virtual std::string description () const
|
||||
{
|
||||
return tl::to_string (tr ("Pull regions by their geometric relation to first (interacting, inside)"));
|
||||
}
|
||||
|
||||
private:
|
||||
int m_mode;
|
||||
bool m_touching;
|
||||
mutable db::EdgeProcessor m_ep;
|
||||
};
|
||||
|
||||
struct ResultInserter
|
||||
{
|
||||
typedef db::Polygon value_type;
|
||||
|
||||
ResultInserter (db::Layout *layout, std::unordered_set<db::PolygonRef> &result)
|
||||
: mp_layout (layout), mp_result (&result)
|
||||
{
|
||||
|
|
@ -1635,6 +1709,25 @@ private:
|
|||
std::unordered_set<db::PolygonRef> *mp_result;
|
||||
};
|
||||
|
||||
struct EdgeResultInserter
|
||||
{
|
||||
typedef db::Edge value_type;
|
||||
|
||||
EdgeResultInserter (std::unordered_set<db::Edge> &result)
|
||||
: mp_result (&result)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void insert (const db::Edge &e)
|
||||
{
|
||||
(*mp_result).insert (e);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_set<db::Edge> *mp_result;
|
||||
};
|
||||
|
||||
class InteractingWithEdgeLocalOperation
|
||||
: public local_operation<db::PolygonRef, db::Edge, db::PolygonRef>
|
||||
{
|
||||
|
|
@ -1652,7 +1745,7 @@ public:
|
|||
ResultInserter inserter (layout, result);
|
||||
region_to_edge_interaction_filter<ResultInserter> filter (inserter, m_inverse);
|
||||
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::PolygonRef, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::PolygonRef, db::Edge>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
m_scanner.insert2 (& interactions.intruder_shape (*j), 0);
|
||||
}
|
||||
|
|
@ -1688,7 +1781,7 @@ public:
|
|||
|
||||
virtual std::string description () const
|
||||
{
|
||||
return tl::to_string (tr ("Select regions by their geometric relation (interacting, inside, outside ..)"));
|
||||
return tl::to_string (tr ("Select regions by their geometric relation to edges"));
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -1696,6 +1789,55 @@ private:
|
|||
mutable db::box_scanner2<db::Polygon, size_t, db::Edge, size_t> m_scanner;
|
||||
};
|
||||
|
||||
class PullWithEdgeLocalOperation
|
||||
: public local_operation<db::PolygonRef, db::Edge, db::Edge>
|
||||
{
|
||||
public:
|
||||
PullWithEdgeLocalOperation ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual void compute_local (db::Layout *, const shape_interactions<db::PolygonRef, db::Edge> &interactions, std::unordered_set<db::Edge> &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||
{
|
||||
m_scanner.clear ();
|
||||
|
||||
EdgeResultInserter inserter (result);
|
||||
region_to_edge_interaction_filter<EdgeResultInserter> filter (inserter, false);
|
||||
|
||||
for (shape_interactions<db::PolygonRef, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::PolygonRef, db::Edge>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
m_scanner.insert2 (& interactions.intruder_shape (*j), 0);
|
||||
}
|
||||
}
|
||||
|
||||
std::list<db::Polygon> heap;
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
const db::PolygonRef &subject = interactions.subject_shape (i->first);
|
||||
heap.push_back (subject.obj ().transformed (subject.trans ()));
|
||||
|
||||
m_scanner.insert1 (&heap.back (), 0);
|
||||
|
||||
}
|
||||
|
||||
m_scanner.process (filter, 1, db::box_convert<db::Polygon> (), db::box_convert<db::Edge> ());
|
||||
}
|
||||
|
||||
virtual on_empty_intruder_mode on_empty_intruder_hint () const
|
||||
{
|
||||
return Drop;
|
||||
}
|
||||
|
||||
virtual std::string description () const
|
||||
{
|
||||
return tl::to_string (tr ("Select edges from second by their geometric relation to first"));
|
||||
}
|
||||
|
||||
private:
|
||||
mutable db::box_scanner2<db::Polygon, size_t, db::Edge, size_t> m_scanner;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
|
|
@ -1766,4 +1908,60 @@ DeepRegion::selected_interacting_generic (const Edges &other, bool inverse) cons
|
|||
return res;
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
DeepRegion::pull_generic (const Region &other, int mode, bool touching) const
|
||||
{
|
||||
// with these flag set to true, the resulting polygons are broken again.
|
||||
bool split_after = false;
|
||||
|
||||
const db::DeepRegion *other_deep = dynamic_cast<const db::DeepRegion *> (other.delegate ());
|
||||
if (! other_deep) {
|
||||
return db::AsIfFlatRegion::pull_generic (other, mode, touching);
|
||||
}
|
||||
|
||||
ensure_merged_polygons_valid ();
|
||||
|
||||
DeepLayer dl_out (m_deep_layer.derived ());
|
||||
|
||||
db::PullLocalOperation op (mode, touching);
|
||||
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&m_deep_layer.layout ()), const_cast<db::Cell *> (&m_deep_layer.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (m_deep_layer.store ()->threads ());
|
||||
if (split_after) {
|
||||
proc.set_area_ratio (m_deep_layer.store ()->max_area_ratio ());
|
||||
proc.set_max_vertex_count (m_deep_layer.store ()->max_vertex_count ());
|
||||
}
|
||||
|
||||
proc.run (&op, m_merged_polygons.layer (), other_deep->deep_layer ().layer (), dl_out.layer ());
|
||||
|
||||
db::DeepRegion *res = new db::DeepRegion (dl_out);
|
||||
if (! split_after) {
|
||||
res->set_is_merged (true);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
DeepRegion::pull_generic (const Edges &other) const
|
||||
{
|
||||
const db::DeepEdges *other_deep = dynamic_cast<const db::DeepEdges *> (other.delegate ());
|
||||
if (! other_deep) {
|
||||
return db::AsIfFlatRegion::pull_generic (other);
|
||||
}
|
||||
|
||||
ensure_merged_polygons_valid ();
|
||||
|
||||
DeepLayer dl_out (m_deep_layer.derived ());
|
||||
|
||||
db::PullWithEdgeLocalOperation op;
|
||||
|
||||
db::local_processor<db::PolygonRef, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&m_deep_layer.layout ()), const_cast<db::Cell *> (&m_deep_layer.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (m_deep_layer.store ()->threads ());
|
||||
proc.run (&op, m_merged_polygons.layer (), other_deep->deep_layer ().layer (), dl_out.layer ());
|
||||
|
||||
return new db::DeepEdges (dl_out);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -240,6 +240,8 @@ private:
|
|||
EdgePairsDelegate *run_single_polygon_check (db::edge_relation_type rel, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const;
|
||||
RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse) const;
|
||||
RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse) const;
|
||||
RegionDelegate *pull_generic (const Region &other, int mode, bool touching) const;
|
||||
EdgesDelegate *pull_generic (const Edges &other) const;
|
||||
|
||||
const DeepLayer &merged_deep_layer () const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include "dbCommon.h"
|
||||
#include "dbRegionDelegate.h"
|
||||
#include "dbEmptyEdges.h"
|
||||
|
||||
namespace db {
|
||||
|
||||
|
|
@ -106,6 +107,10 @@ public:
|
|||
virtual RegionDelegate *selected_not_interacting (const Edges &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_overlapping (const Region &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_not_overlapping (const Region &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *pull_inside (const Region &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *pull_interacting (const Region &) const { return new EmptyRegion (); }
|
||||
virtual EdgesDelegate *pull_interacting (const Edges &) const { return new EmptyEdges (); }
|
||||
virtual RegionDelegate *pull_overlapping (const Region &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *in (const Region &, bool) const { return new EmptyRegion (); }
|
||||
|
||||
virtual bool has_valid_polygons () const { return true; }
|
||||
|
|
|
|||
|
|
@ -178,6 +178,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
db::Shapes &raw_edges () { return m_edges; }
|
||||
|
||||
protected:
|
||||
virtual void merged_semantics_changed ();
|
||||
virtual Box compute_bbox () const;
|
||||
|
|
@ -187,8 +189,6 @@ protected:
|
|||
private:
|
||||
friend class AsIfFlatEdges;
|
||||
|
||||
db::Shapes &raw_edges () { return m_edges; }
|
||||
|
||||
FlatEdges &operator= (const FlatEdges &other);
|
||||
|
||||
bool m_is_merged;
|
||||
|
|
|
|||
|
|
@ -1355,6 +1355,46 @@ public:
|
|||
return Region (mp_delegate->selected_not_overlapping (other));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all polygons of "other" which are inside polygons of this region
|
||||
*
|
||||
* Merged semantics applies.
|
||||
*/
|
||||
Region pull_inside (const Region &other) const
|
||||
{
|
||||
return Region (mp_delegate->pull_inside (other));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all edges of "other" which are interacting (touching or overlapping with) polygons of this region
|
||||
*
|
||||
* Merged semantics applies.
|
||||
*/
|
||||
Edges pull_interacting (const Edges &other) const
|
||||
{
|
||||
return Edges (mp_delegate->pull_interacting (other));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all polygons of "other" which are interacting (touching or overlapping with) polygons of this region
|
||||
*
|
||||
* Merged semantics applies.
|
||||
*/
|
||||
Region pull_interacting (const Region &other) const
|
||||
{
|
||||
return Region (mp_delegate->pull_interacting (other));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all polygons of "other" which are overlapping with polygons of this region
|
||||
*
|
||||
* Merged semantics applies.
|
||||
*/
|
||||
Region pull_overlapping (const Region &other) const
|
||||
{
|
||||
return Region (mp_delegate->pull_overlapping (other));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the holes
|
||||
*
|
||||
|
|
|
|||
|
|
@ -294,6 +294,10 @@ public:
|
|||
virtual RegionDelegate *selected_not_interacting (const Edges &other) const = 0;
|
||||
virtual RegionDelegate *selected_overlapping (const Region &other) const = 0;
|
||||
virtual RegionDelegate *selected_not_overlapping (const Region &other) const = 0;
|
||||
virtual RegionDelegate *pull_inside (const Region &other) const = 0;
|
||||
virtual RegionDelegate *pull_interacting (const Region &other) const = 0;
|
||||
virtual EdgesDelegate *pull_interacting (const Edges &other) const = 0;
|
||||
virtual RegionDelegate *pull_overlapping (const Region &other) const = 0;
|
||||
virtual RegionDelegate *in (const Region &other, bool invert) const = 0;
|
||||
|
||||
virtual const db::Polygon *nth (size_t n) const = 0;
|
||||
|
|
|
|||
|
|
@ -288,22 +288,47 @@ Poly2PolyCheckBase::enter (const db::Polygon &o1, size_t p1, const db::Polygon &
|
|||
// -------------------------------------------------------------------------------------
|
||||
// RegionToEdgeInteractionFilterBase implementation
|
||||
|
||||
RegionToEdgeInteractionFilterBase::RegionToEdgeInteractionFilterBase (bool inverse)
|
||||
namespace
|
||||
{
|
||||
|
||||
template <class OutputType>
|
||||
struct edge_or_polygon;
|
||||
|
||||
template <>
|
||||
struct edge_or_polygon<db::Polygon>
|
||||
{
|
||||
const db::Polygon *operator() (const db::Polygon *p, const db::Edge *) const { return p; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct edge_or_polygon<db::Edge>
|
||||
{
|
||||
const db::Edge *operator() (const db::Polygon *, const db::Edge *e) const { return e; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <class OutputType>
|
||||
region_to_edge_interaction_filter_base<OutputType>::region_to_edge_interaction_filter_base (bool inverse)
|
||||
: m_inverse (inverse)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
template <class OutputType>
|
||||
void
|
||||
RegionToEdgeInteractionFilterBase::preset (const db::Polygon *poly)
|
||||
region_to_edge_interaction_filter_base<OutputType>::preset (const OutputType *s)
|
||||
{
|
||||
m_seen.insert (poly);
|
||||
m_seen.insert (s);
|
||||
}
|
||||
|
||||
template <class OutputType>
|
||||
void
|
||||
RegionToEdgeInteractionFilterBase::add (const db::Polygon *p, size_t, const db::Edge *e, size_t)
|
||||
region_to_edge_interaction_filter_base<OutputType>::add (const db::Polygon *p, size_t, const db::Edge *e, size_t)
|
||||
{
|
||||
if ((m_seen.find (p) == m_seen.end ()) != m_inverse) {
|
||||
const OutputType *o = edge_or_polygon<OutputType> () (p, e);
|
||||
|
||||
if ((m_seen.find (o) == m_seen.end ()) != m_inverse) {
|
||||
|
||||
// A polygon and an edge interact if the edge is either inside completely
|
||||
// of at least one edge of the polygon intersects with the edge
|
||||
|
|
@ -320,23 +345,28 @@ RegionToEdgeInteractionFilterBase::add (const db::Polygon *p, size_t, const db::
|
|||
|
||||
if (interacts) {
|
||||
if (m_inverse) {
|
||||
m_seen.erase (p);
|
||||
m_seen.erase (o);
|
||||
} else {
|
||||
m_seen.insert (p);
|
||||
put (*p);
|
||||
m_seen.insert (o);
|
||||
put (*o);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template <class OutputType>
|
||||
void
|
||||
RegionToEdgeInteractionFilterBase::fill_output ()
|
||||
region_to_edge_interaction_filter_base<OutputType>::fill_output ()
|
||||
{
|
||||
for (std::set<const db::Polygon *>::const_iterator p = m_seen.begin (); p != m_seen.end (); ++p) {
|
||||
put (**p);
|
||||
for (typename std::set<const OutputType *>::const_iterator s = m_seen.begin (); s != m_seen.end (); ++s) {
|
||||
put (**s);
|
||||
}
|
||||
}
|
||||
|
||||
// explicit instantiations
|
||||
template class region_to_edge_interaction_filter_base<db::Polygon>;
|
||||
template class region_to_edge_interaction_filter_base<db::Edge>;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -481,40 +481,41 @@ public:
|
|||
/**
|
||||
* @brief A helper class for the region to edge interaction functionality
|
||||
*/
|
||||
class DB_PUBLIC RegionToEdgeInteractionFilterBase
|
||||
template <class OutputType>
|
||||
class DB_PUBLIC region_to_edge_interaction_filter_base
|
||||
: public db::box_scanner_receiver2<db::Polygon, size_t, db::Edge, size_t>
|
||||
{
|
||||
public:
|
||||
RegionToEdgeInteractionFilterBase (bool inverse);
|
||||
region_to_edge_interaction_filter_base (bool inverse);
|
||||
|
||||
void preset (const db::Polygon *poly);
|
||||
void preset (const OutputType *s);
|
||||
void add (const db::Polygon *p, size_t, const db::Edge *e, size_t);
|
||||
void fill_output ();
|
||||
|
||||
protected:
|
||||
virtual void put (const db::Polygon &poly) const = 0;
|
||||
virtual void put (const OutputType &s) const = 0;
|
||||
|
||||
private:
|
||||
std::set<const db::Polygon *> m_seen;
|
||||
std::set<const OutputType *> m_seen;
|
||||
bool m_inverse;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A helper class for the region to edge interaction functionality
|
||||
*/
|
||||
template <class OutputContainer>
|
||||
template <class OutputContainer, class OutputType = typename OutputContainer::value_type>
|
||||
class DB_PUBLIC_TEMPLATE region_to_edge_interaction_filter
|
||||
: public RegionToEdgeInteractionFilterBase
|
||||
: public region_to_edge_interaction_filter_base<OutputType>
|
||||
{
|
||||
public:
|
||||
region_to_edge_interaction_filter (OutputContainer &output, bool inverse)
|
||||
: RegionToEdgeInteractionFilterBase (inverse), mp_output (&output)
|
||||
: region_to_edge_interaction_filter_base<OutputType> (inverse), mp_output (&output)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void put (const db::Polygon &poly) const
|
||||
virtual void put (const OutputType &poly) const
|
||||
{
|
||||
mp_output->insert (poly);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1600,6 +1600,49 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("pull_inside", &db::Region::pull_inside, gsi::arg ("other"),
|
||||
"@brief Returns all polygons of \"other\" which are inside polygons of this region\n"
|
||||
"The \"pull_...\" methods are similar to \"selected_...\" but work the opposite way: they "
|
||||
"select shapes from the argument region rather than self. In a deep (hierarchical) context "
|
||||
"the output region will be hierarchically aligned with self, so the \"pull_...\" methods "
|
||||
"provide a way for rehierarchisation.\n"
|
||||
"\n"
|
||||
"@return The region after the polygons have been selected (from other)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.1\n"
|
||||
) +
|
||||
method ("pull_overlapping", &db::Region::pull_overlapping, gsi::arg ("other"),
|
||||
"@brief Returns all polygons of \"other\" which are overlapping polygons of this region\n"
|
||||
"See \\pull_inside for a description of the \"pull_...\" methods.\n"
|
||||
"\n"
|
||||
"@return The region after the polygons have been selected (from other)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.1\n"
|
||||
) +
|
||||
method ("pull_interacting", static_cast<db::Region (db::Region::*) (const db::Region &) const> (&db::Region::pull_interacting), gsi::arg ("other"),
|
||||
"@brief Returns all polygons of \"other\" which are interacting with (overlapping, touching) polygons of this region\n"
|
||||
"See \\pull_inside for a description of the \"pull_...\" methods.\n"
|
||||
"\n"
|
||||
"@return The region after the polygons have been selected (from other)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.1\n"
|
||||
) +
|
||||
method ("pull_interacting", static_cast<db::Edges (db::Region::*) (const db::Edges &) const> (&db::Region::pull_interacting), gsi::arg ("other"),
|
||||
"@brief Returns all edges of \"other\" which are interacting with polygons of this region\n"
|
||||
"See \\pull_inside for a description of the \"pull_...\" methods.\n"
|
||||
"\n"
|
||||
"@return The edge collection after the edges have been selected (from other)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.1\n"
|
||||
) +
|
||||
method ("is_box?", &db::Region::is_box,
|
||||
"@brief Returns true, if the region is a simple box\n"
|
||||
"\n"
|
||||
|
|
|
|||
Loading…
Reference in New Issue