Refactoring: generalization of filter/processor for edges, region

This commit is contained in:
Matthias Koefferlein 2019-02-20 09:45:38 +01:00
parent 0f2d0605a9
commit 124c4eb61c
21 changed files with 615 additions and 72 deletions

View File

@ -23,6 +23,8 @@
#include "dbAsIfFlatEdges.h"
#include "dbFlatEdges.h"
#include "dbFlatEdgePairs.h"
#include "dbFlatRegion.h"
#include "dbEmptyEdges.h"
#include "dbEdges.h"
#include "dbEdgesUtils.h"
@ -362,6 +364,50 @@ AsIfFlatEdges::processed (const EdgeProcessorBase &filter) const
return edges.release ();
}
EdgePairsDelegate *
AsIfFlatEdges::processed_to_edge_pairs (const EdgeToEdgePairProcessorBase &filter) const
{
std::auto_ptr<FlatEdgePairs> edge_pairs (new FlatEdgePairs ());
if (filter.result_must_not_be_merged ()) {
edge_pairs->set_merged_semantics (false);
}
std::vector<db::EdgePair> res_edge_pairs;
for (EdgesIterator e (filter.requires_raw_input () ? begin () : begin_merged ()); ! e.at_end (); ++e) {
res_edge_pairs.clear ();
filter.process (*e, res_edge_pairs);
for (std::vector<db::EdgePair>::const_iterator epr = res_edge_pairs.begin (); epr != res_edge_pairs.end (); ++epr) {
edge_pairs->insert (*epr);
}
}
return edge_pairs.release ();
}
RegionDelegate *
AsIfFlatEdges::processed_to_polygons (const EdgeToPolygonProcessorBase &filter) const
{
std::auto_ptr<FlatRegion> region (new FlatRegion ());
if (filter.result_must_not_be_merged ()) {
region->set_merged_semantics (false);
}
std::vector<db::Polygon> res_polygons;
for (EdgesIterator e (filter.requires_raw_input () ? begin () : begin_merged ()); ! e.at_end (); ++e) {
res_polygons.clear ();
filter.process (*e, res_polygons);
for (std::vector<db::Polygon>::const_iterator pr = res_polygons.begin (); pr != res_polygons.end (); ++pr) {
region->insert (*pr);
}
}
return region.release ();
}
EdgesDelegate *
AsIfFlatEdges::filtered (const EdgeFilterBase &filter) const
{

View File

@ -88,6 +88,8 @@ public:
}
virtual EdgesDelegate *processed (const EdgeProcessorBase &filter) const;
virtual EdgePairsDelegate *processed_to_edge_pairs (const EdgeToEdgePairProcessorBase &) const;
virtual RegionDelegate *processed_to_polygons (const EdgeToPolygonProcessorBase &) const;
virtual EdgesDelegate *filter_in_place (const EdgeFilterBase &filter)
{

View File

@ -24,6 +24,7 @@
#include "dbAsIfFlatRegion.h"
#include "dbFlatRegion.h"
#include "dbFlatEdgePairs.h"
#include "dbFlatEdges.h"
#include "dbEmptyRegion.h"
#include "dbRegion.h"
#include "dbRegionUtils.h"
@ -252,6 +253,10 @@ RegionDelegate *
AsIfFlatRegion::processed (const PolygonProcessorBase &filter) const
{
std::auto_ptr<FlatRegion> new_region (new FlatRegion ());
if (filter.result_must_not_be_merged ()) {
new_region->set_merged_semantics (false);
}
std::vector<db::Polygon> poly_res;
for (RegionIterator p (filter.requires_raw_input () ? begin () : begin_merged ()); ! p.at_end (); ++p) {
@ -267,6 +272,52 @@ AsIfFlatRegion::processed (const PolygonProcessorBase &filter) const
return new_region.release ();
}
EdgesDelegate *
AsIfFlatRegion::processed_to_edges (const PolygonToEdgeProcessorBase &filter) const
{
std::auto_ptr<FlatEdges> new_edges (new FlatEdges ());
if (filter.result_must_not_be_merged ()) {
new_edges->set_merged_semantics (false);
}
std::vector<db::Edge> edge_res;
for (RegionIterator p (filter.requires_raw_input () ? begin () : begin_merged ()); ! p.at_end (); ++p) {
edge_res.clear ();
filter.process (*p, edge_res);
for (std::vector<db::Edge>::const_iterator er = edge_res.begin (); er != edge_res.end (); ++er) {
new_edges->insert (*er);
}
}
return new_edges.release ();
}
EdgePairsDelegate *
AsIfFlatRegion::processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &filter) const
{
std::auto_ptr<FlatEdgePairs> new_edge_pairs (new FlatEdgePairs ());
if (filter.result_must_not_be_merged ()) {
new_edge_pairs->set_merged_semantics (false);
}
std::vector<db::EdgePair> edge_pair_res;
for (RegionIterator p (filter.requires_raw_input () ? begin () : begin_merged ()); ! p.at_end (); ++p) {
edge_pair_res.clear ();
filter.process (*p, edge_pair_res);
for (std::vector<db::EdgePair>::const_iterator epr = edge_pair_res.begin (); epr != edge_pair_res.end (); ++epr) {
new_edge_pairs->insert (*epr);
}
}
return new_edge_pairs.release ();
}
RegionDelegate *
AsIfFlatRegion::selected_interacting_generic (const Edges &other, bool inverse) const
{

View File

@ -113,6 +113,8 @@ public:
}
virtual RegionDelegate *processed (const PolygonProcessorBase &filter) const;
virtual EdgesDelegate *processed_to_edges (const PolygonToEdgeProcessorBase &filter) const;
virtual EdgePairsDelegate *processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &filter) const;
virtual RegionDelegate *filter_in_place (const PolygonFilterBase &filter)
{

View File

@ -483,59 +483,136 @@ EdgesDelegate *DeepEdges::process_in_place (const EdgeProcessorBase &filter)
return processed (filter);
}
EdgesDelegate *DeepEdges::processed (const EdgeProcessorBase &filter) const
EdgesDelegate *
DeepEdges::processed (const EdgeProcessorBase &filter) const
{
return processed_impl<db::Edge, db::DeepEdges> (filter);
}
EdgePairsDelegate *
DeepEdges::processed_to_edge_pairs (const EdgeToEdgePairProcessorBase &filter) const
{
return processed_impl<db::EdgePair, db::DeepEdgePairs> (filter);
}
RegionDelegate *
DeepEdges::processed_to_polygons (const EdgeToPolygonProcessorBase &filter) const
{
return processed_impl<db::Polygon, db::DeepRegion> (filter);
}
namespace
{
template <class Result> struct delivery;
template <>
struct delivery<db::Polygon>
{
delivery (db::Layout *layout, db::Shapes *shapes)
: mp_layout (layout), mp_shapes (shapes)
{ }
void put (const db::Polygon &result)
{
tl::MutexLocker locker (&mp_layout->lock ());
mp_shapes->insert (db::PolygonRef (result, mp_layout->shape_repository ()));
}
private:
db::Layout *mp_layout;
db::Shapes *mp_shapes;
};
template <class Result>
struct delivery
{
delivery (db::Layout *, db::Shapes *shapes)
: mp_shapes (shapes)
{ }
void put (const Result &result)
{
mp_shapes->insert (result);
}
private:
db::Shapes *mp_shapes;
};
}
template <class Result, class OutputContainer>
OutputContainer *
DeepEdges::processed_impl (const edge_processor<Result> &filter) const
{
if (! filter.requires_raw_input ()) {
ensure_merged_edges_valid ();
}
std::auto_ptr<VariantsCollectorBase> vars;
if (filter.vars ()) {
vars.reset (new db::VariantsCollectorBase (filter.vars ()));
vars->collect (m_deep_layer.layout (), m_deep_layer.initial_cell ());
// NOTE: m_merged_polygons is mutable, so why is the const_cast needed?
const_cast<db::DeepLayer &> (m_deep_layer).separate_variants (*vars);
if (filter.wants_variants ()) {
const_cast<db::DeepLayer &> (m_deep_layer).separate_variants (*vars);
}
}
db::Layout &layout = const_cast<db::Layout &> (m_deep_layer.layout ());
std::vector<db::Edge> res_edges;
std::auto_ptr<db::DeepEdges> res (new db::DeepEdges (m_deep_layer.derived ()));
std::vector<Result> heap;
std::map<db::cell_index_type, std::map<db::ICplxTrans, db::Shapes> > to_commit;
std::auto_ptr<OutputContainer> res (new OutputContainer (m_deep_layer.derived ()));
if (filter.result_must_not_be_merged ()) {
res->set_merged_semantics (false);
}
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const db::Shapes &s = c->shapes (filter.requires_raw_input () ? m_deep_layer.layer () : m_merged_edges.layer ());
if (vars.get ()) {
const std::map<db::ICplxTrans, size_t> &v = vars->variants (c->cell_index ());
tl_assert (v.size () == size_t (1));
const db::ICplxTrans &tr = v.begin ()->first;
db::ICplxTrans trinv = tr.inverted ();
const std::map<db::ICplxTrans, size_t> &vv = vars->variants (c->cell_index ());
for (std::map<db::ICplxTrans, size_t>::const_iterator v = vv.begin (); v != vv.end (); ++v) {
const db::Shapes &s = c->shapes (filter.requires_raw_input () ? m_deep_layer.layer () : m_merged_edges.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) {
res_edges.clear ();
filter.process (si->edge ().transformed (tr), res_edges);
for (std::vector<db::Edge>::const_iterator er = res_edges.begin (); er != res_edges.end (); ++er) {
st.insert (er->transformed (trinv));
db::Shapes *st;
if (vv.size () == 1) {
st = & c->shapes (res->deep_layer ().layer ());
} else {
st = & to_commit [c->cell_index ()] [v->first];
}
delivery<Result> delivery (&layout, st);
const db::ICplxTrans &tr = v->first;
db::ICplxTrans trinv = tr.inverted ();
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) {
heap.clear ();
filter.process (si->edge ().transformed (tr), heap);
for (typename std::vector<Result>::const_iterator i = heap.begin (); i != heap.end (); ++i) {
delivery.put (i->transformed (trinv));
}
}
}
} else {
const db::Shapes &s = c->shapes (filter.requires_raw_input () ? m_deep_layer.layer () : m_merged_edges.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
delivery<Result> delivery (&layout, &st);
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) {
res_edges.clear ();
filter.process (si->edge (), res_edges);
for (std::vector<db::Edge>::const_iterator er = res_edges.begin (); er != res_edges.end (); ++er) {
st.insert (*er);
filter.process (si->edge (), heap);
for (typename std::vector<Result>::const_iterator i = heap.begin (); i != heap.end (); ++i) {
delivery.put (*i);
}
}
@ -543,66 +620,80 @@ EdgesDelegate *DeepEdges::processed (const EdgeProcessorBase &filter) const
}
if (! to_commit.empty () && vars.get ()) {
res->deep_layer ().commit_shapes (*vars, to_commit);
}
if (filter.result_is_merged ()) {
res->set_is_merged (true);
}
return res.release ();
}
EdgesDelegate *DeepEdges::filter_in_place (const EdgeFilterBase &filter)
EdgesDelegate *
DeepEdges::filter_in_place (const EdgeFilterBase &filter)
{
// TODO: implement to be really in-place
return filtered (filter);
}
EdgesDelegate *DeepEdges::filtered (const EdgeFilterBase &filter) const
EdgesDelegate *
DeepEdges::filtered (const EdgeFilterBase &filter) const
{
ensure_merged_edges_valid ();
if (! filter.requires_raw_input ()) {
ensure_merged_edges_valid ();
}
std::auto_ptr<VariantsCollectorBase> vars;
if (filter.vars ()) {
vars.reset (new db::VariantsCollectorBase (filter.vars ()));
vars->collect (m_merged_edges.layout (), m_merged_edges.initial_cell ());
vars->collect (m_deep_layer.layout (), m_deep_layer.initial_cell ());
// NOTE: m_merged_polygons is mutable, so why is the const_cast needed?
const_cast<db::DeepLayer &> (m_merged_edges).separate_variants (*vars);
if (filter.wants_variants ()) {
const_cast<db::DeepLayer &> (m_deep_layer).separate_variants (*vars);
}
}
db::Layout &layout = m_merged_edges.layout ();
db::Layout &layout = const_cast<db::Layout &> (m_deep_layer.layout ());
std::map<db::cell_index_type, std::map<db::ICplxTrans, db::Shapes> > to_commit;
std::auto_ptr<db::DeepEdges> res (new db::DeepEdges (m_merged_edges.derived ()));
std::auto_ptr<db::DeepEdges> res (new db::DeepEdges (m_deep_layer.derived ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const db::Shapes &s = c->shapes (filter.requires_raw_input () ? m_deep_layer.layer () : m_merged_edges.layer ());
if (vars.get ()) {
const std::map<db::ICplxTrans, size_t> &v = vars->variants (c->cell_index ());
tl_assert (v.size () == size_t (1));
const db::ICplxTrans &tr = v.begin ()->first;
const std::map<db::ICplxTrans, size_t> &vv = vars->variants (c->cell_index ());
for (std::map<db::ICplxTrans, size_t>::const_iterator v = vv.begin (); v != vv.end (); ++v) {
const db::Shapes &s = c->shapes (m_merged_edges.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) {
db::Edge edge = si->edge ();
if (filter.selected (edge.transformed (tr))) {
st.insert (edge);
db::Shapes *st;
if (vv.size () == 1) {
st = & c->shapes (res->deep_layer ().layer ());
} else {
st = & to_commit [c->cell_index ()] [v->first];
}
const db::ICplxTrans &tr = v->first;
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) {
if (filter.selected (si->edge ().transformed (tr))) {
st->insert (*si);
}
}
}
} else {
const db::Shapes &s = c->shapes (m_merged_edges.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) {
db::Edge edge = si->edge ();
if (filter.selected (edge)) {
st.insert (edge);
if (filter.selected (si->edge ())) {
st.insert (*si);
}
}
@ -610,7 +701,13 @@ EdgesDelegate *DeepEdges::filtered (const EdgeFilterBase &filter) const
}
res->set_is_merged (true);
if (! to_commit.empty () && vars.get ()) {
res->deep_layer ().commit_shapes (*vars, to_commit);
}
if (! filter.requires_raw_input ()) {
res->set_is_merged (true);
}
return res.release ();
}

View File

@ -112,6 +112,8 @@ public:
virtual EdgesDelegate *filtered (const EdgeFilterBase &) const;
virtual EdgesDelegate *process_in_place (const EdgeProcessorBase &);
virtual EdgesDelegate *processed (const EdgeProcessorBase &) const;
virtual EdgePairsDelegate *processed_to_edge_pairs (const EdgeToEdgePairProcessorBase &filter) const;
virtual RegionDelegate *processed_to_polygons (const EdgeToPolygonProcessorBase &filter) const;
virtual EdgesDelegate *merged_in_place ();
virtual EdgesDelegate *merged () const;
@ -174,6 +176,7 @@ private:
EdgePairs run_check (db::edge_relation_type rel, const Edges *other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const;
EdgesDelegate *selected_interacting_generic (const Edges &edges, bool invert) const;
EdgesDelegate *selected_interacting_generic (const Region &region, bool invert) const;
template <class Result, class OutputContainer> OutputContainer *processed_impl (const edge_processor<Result> &filter) const;
};
}

View File

@ -912,8 +912,68 @@ DeepRegion::process_in_place (const PolygonProcessorBase &filter)
return processed (filter);
}
EdgesDelegate *
DeepRegion::processed_to_edges (const PolygonToEdgeProcessorBase &filter) const
{
return processed_impl<db::Edge, db::DeepEdges> (filter);
}
EdgePairsDelegate *
DeepRegion::processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &filter) const
{
return processed_impl<db::EdgePair, db::DeepEdgePairs> (filter);
}
RegionDelegate *
DeepRegion::processed (const PolygonProcessorBase &filter) const
{
return processed_impl<db::Polygon, db::DeepRegion> (filter);
}
namespace
{
template <class Result> struct delivery;
template <>
struct delivery<db::Polygon>
{
delivery (db::Layout *layout, db::Shapes *shapes)
: mp_layout (layout), mp_shapes (shapes)
{ }
void put (const db::Polygon &result)
{
tl::MutexLocker locker (&mp_layout->lock ());
mp_shapes->insert (db::PolygonRef (result, mp_layout->shape_repository ()));
}
private:
db::Layout *mp_layout;
db::Shapes *mp_shapes;
};
template <class Result>
struct delivery
{
delivery (db::Layout *, db::Shapes *shapes)
: mp_shapes (shapes)
{ }
void put (const Result &result)
{
mp_shapes->insert (result);
}
private:
db::Shapes *mp_shapes;
};
}
template <class Result, class OutputContainer>
OutputContainer *
DeepRegion::processed_impl (const polygon_processor<Result> &filter) const
{
if (! filter.requires_raw_input ()) {
ensure_merged_polygons_valid ();
@ -934,10 +994,14 @@ DeepRegion::processed (const PolygonProcessorBase &filter) const
db::Layout &layout = const_cast<db::Layout &> (m_deep_layer.layout ());
std::vector<db::Polygon> poly_res;
std::vector<Result> heap;
std::map<db::cell_index_type, std::map<db::ICplxTrans, db::Shapes> > to_commit;
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_deep_layer.derived ()));
std::auto_ptr<OutputContainer> res (new OutputContainer (m_deep_layer.derived ()));
if (filter.result_must_not_be_merged ()) {
res->set_merged_semantics (false);
}
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const db::Shapes &s = c->shapes (filter.requires_raw_input () ? m_deep_layer.layer () : m_merged_polygons.layer ());
@ -954,7 +1018,7 @@ DeepRegion::processed (const PolygonProcessorBase &filter) const
st = & to_commit [c->cell_index ()] [v->first];
}
db::PolygonRefToShapesGenerator pr (&layout, st);
delivery<Result> delivery (&layout, st);
const db::ICplxTrans &tr = v->first;
db::ICplxTrans trinv = tr.inverted ();
@ -963,10 +1027,10 @@ DeepRegion::processed (const PolygonProcessorBase &filter) const
db::Polygon poly;
si->polygon (poly);
poly.transform (tr);
poly_res.clear ();
filter.process (poly, poly_res);
for (std::vector<db::Polygon>::const_iterator p = poly_res.begin (); p != poly_res.end (); ++p) {
pr.put (p->transformed (trinv));
heap.clear ();
filter.process (poly, heap);
for (typename std::vector<Result>::const_iterator i = heap.begin (); i != heap.end (); ++i) {
delivery.put (i->transformed (trinv));
}
}
@ -975,15 +1039,15 @@ DeepRegion::processed (const PolygonProcessorBase &filter) const
} else {
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
db::PolygonRefToShapesGenerator pr (&layout, &st);
delivery<Result> delivery (&layout, &st);
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
db::Polygon poly;
si->polygon (poly);
poly_res.clear ();
filter.process (poly, poly_res);
for (std::vector<db::Polygon>::const_iterator p = poly_res.begin (); p != poly_res.end (); ++p) {
pr.put (*p);
heap.clear ();
filter.process (poly, heap);
for (typename std::vector<Result>::const_iterator i = heap.begin (); i != heap.end (); ++i) {
delivery.put (*i);
}
}
@ -1022,7 +1086,6 @@ DeepRegion::filtered (const PolygonFilterBase &filter) const
vars->collect (m_deep_layer.layout (), m_deep_layer.initial_cell ());
// NOTE: m_merged_polygons is mutable, so why is the const_cast needed?
if (filter.wants_variants ()) {
const_cast<db::DeepLayer &> (m_deep_layer).separate_variants (*vars);
}

View File

@ -140,6 +140,8 @@ public:
virtual RegionDelegate *process_in_place (const PolygonProcessorBase &filter);
virtual RegionDelegate *processed (const PolygonProcessorBase &filter) const;
virtual EdgesDelegate *processed_to_edges (const PolygonToEdgeProcessorBase &filter) const;
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;
@ -221,6 +223,8 @@ protected:
void set_is_merged (bool f);
private:
friend class DeepEdges;
DeepRegion &operator= (const DeepRegion &other);
DeepLayer m_deep_layer;
@ -240,6 +244,8 @@ private:
{
return m_merged_polygons;
}
template <class Result, class OutputContainer> OutputContainer *processed_impl (const polygon_processor<Result> &filter) const;
};
}

View File

@ -78,6 +78,12 @@ public:
void enable_progress (const std::string &progress_desc);
void disable_progress ();
// dummy features to harmonize the interface of region, edges and edge pair delegates
void set_merged_semantics (bool) { }
bool merged_semantics () const { return false; }
void set_is_merged (bool) { }
bool is_merged () const { return false; }
virtual std::string to_string (size_t nmax) const = 0;
virtual EdgePairsIteratorDelegate *begin () const = 0;

View File

@ -70,6 +70,7 @@ public:
virtual bool result_is_merged () const { return false; }
virtual bool requires_raw_input () const { return false; }
virtual bool result_must_not_be_merged () const { return m_length <= 0; }
virtual bool wants_variants () const { return true; }
private:
int m_mode;
@ -185,6 +186,11 @@ Edges::reserve (size_t n)
flat_edges ()->reserve (n);
}
void Edges::processed (Region &output, const EdgeToPolygonProcessorBase &filter) const
{
output.set_delegate (mp_delegate->processed_to_polygons (filter));
}
void Edges::extended (Region &output, coord_type ext_b, coord_type ext_e, coord_type ext_o, coord_type ext_i, bool join) const
{
output.set_delegate (mp_delegate->extended (ext_b, ext_e, ext_o, ext_i, join));

View File

@ -623,6 +623,31 @@ public:
return Edges (mp_delegate->processed (filter));
}
/**
* @brief Processes the edges into polygons
*
* This method will run the processor over all edges and return a region
* with the outputs of the processor.
*
* Merged semantics applies. In merged semantics, the filter will run over
* all merged edges.
*/
void processed (Region &output, const EdgeToPolygonProcessorBase &filter) const;
/**
* @brief Processes the edges into edge pairs
*
* This method will run the processor over all edges and return an edge pair collection
* with the outputs of the processor.
*
* Merged semantics applies. In merged semantics, the filter will run over
* all merged edges.
*/
EdgePairs processed (const EdgeToEdgePairProcessorBase &filter) const
{
return EdgePairs (mp_delegate->processed_to_edge_pairs (filter));
}
/**
* @brief Applies a width check and returns EdgePairs which correspond to violation markers
*

View File

@ -40,27 +40,118 @@ namespace db {
class DB_PUBLIC EdgeFilterBase
{
public:
/**
* @brief Constructor
*/
EdgeFilterBase () { }
virtual ~EdgeFilterBase () { }
/**
* @brief Filters the edge
* If this method returns true, the polygon is kept. Otherwise it's discarded.
*/
virtual bool selected (const db::Edge &edge) const = 0;
/**
* @brief Returns the transformation reducer for building cell variants
* This method may return 0. In this case, not cell variants are built.
*/
virtual const TransformationReducer *vars () const = 0;
/**
* @brief Returns true, if the filter wants raw (not merged) input
*/
virtual bool requires_raw_input () const = 0;
/**
* @brief Returns true, if the filter wants to build variants
* If not true, the filter accepts shape propagation as variant resolution.
*/
virtual bool wants_variants () const = 0;
};
/**
* @brief A base class for polygon processors
* @brief A template base class for edge processors
*
* A polygon processor can turn a edge into something else.
*/
class DB_PUBLIC EdgeProcessorBase
template <class Result>
class DB_PUBLIC edge_processor
{
public:
EdgeProcessorBase () { }
virtual ~EdgeProcessorBase () { }
/**
* @brief Constructor
*/
edge_processor () { }
virtual void process (const db::Edge &polygon, std::vector<db::Edge> &res) const = 0;
/**
* @brief Destructor
*/
virtual ~edge_processor () { }
/**
* @brief Performs the actual processing
* This method will take the input edge from "edge" and puts the results into "res".
* "res" can be empty - in this case, the edge will be skipped.
*/
virtual void process (const db::Edge &edge, std::vector<Result> &res) const = 0;
/**
* @brief Returns the transformation reducer for building cell variants
* This method may return 0. In this case, not cell variants are built.
*/
virtual const TransformationReducer *vars () const = 0;
/**
* @brief Returns true, if the result of this operation can be regarded "merged" always.
*/
virtual bool result_is_merged () const = 0;
virtual bool requires_raw_input () const = 0;
/**
* @brief Returns true, if the result of this operation must not be merged.
* This feature can be used, if the result represents "degenerated" objects such
* as point-like edges. These must not be merged. Otherwise they disappear.
*/
virtual bool result_must_not_be_merged () const = 0;
/**
* @brief Returns true, if the processor wants raw (not merged) input
*/
virtual bool requires_raw_input () const = 0;
/**
* @brief Returns true, if the processor wants to build variants
* If not true, the processor accepts shape propagation as variant resolution.
*/
virtual bool wants_variants () const = 0;
};
/**
* @brief A edge processor base class
*/
class DB_PUBLIC EdgeProcessorBase
: public edge_processor<db::Edge>
{
// .. nothing yet ..
};
/**
* @brief An edge-to-polygon processor base class
*/
class DB_PUBLIC EdgeToPolygonProcessorBase
: public edge_processor<db::Polygon>
{
// .. nothing yet ..
};
/**
* @brief An edge-to-edge pair processor base class
*/
class DB_PUBLIC EdgeToEdgePairProcessorBase
: public edge_processor<db::EdgePair>
{
// .. nothing yet ..
};
/**
@ -70,6 +161,7 @@ enum EdgeBoolOp { EdgeOr, EdgeNot, EdgeXor, EdgeAnd };
class RecursiveShapeIterator;
class EdgeFilterBase;
class EdgePairsDelegate;
class RegionDelegate;
/**
@ -159,6 +251,8 @@ public:
virtual EdgesDelegate *filtered (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;
virtual RegionDelegate *processed_to_polygons (const EdgeToPolygonProcessorBase &filter) const = 0;
virtual EdgesDelegate *merged_in_place () = 0;
virtual EdgesDelegate *merged () const = 0;

View File

@ -80,6 +80,22 @@ struct DB_PUBLIC EdgeLengthFilter
return &m_vars;
}
/**
* @brief Requires merged input
*/
virtual bool requires_raw_input () const
{
return false;
}
/**
* @brief Wants to build variants
*/
virtual bool wants_variants () const
{
return true;
}
private:
length_type m_lmin, m_lmax;
bool m_inverse;
@ -161,6 +177,22 @@ struct DB_PUBLIC EdgeOrientationFilter
return &m_vars;
}
/**
* @brief Requires merged input
*/
virtual bool requires_raw_input () const
{
return false;
}
/**
* @brief Wants to build variants
*/
virtual bool wants_variants () const
{
return true;
}
private:
db::DVector m_emin, m_emax;
bool m_inverse;

View File

@ -22,6 +22,7 @@
#include "dbEmptyEdges.h"
#include "dbEmptyEdgePairs.h"
#include "dbEmptyRegion.h"
#include "dbEdges.h"
@ -59,6 +60,18 @@ EmptyEdges::extended (coord_type, coord_type, coord_type, coord_type, bool) cons
return new EmptyRegion ();
}
EdgePairsDelegate *
EmptyEdges::processed_to_edge_pairs (const EdgeToEdgePairProcessorBase &) const
{
return new EmptyEdgePairs ();
}
RegionDelegate *
EmptyEdges::processed_to_polygons (const EdgeToPolygonProcessorBase &) const
{
return new EmptyRegion ();
}
EdgesDelegate *
EmptyEdges::add_in_place (const Edges &other)
{

View File

@ -67,6 +67,8 @@ public:
virtual EdgesDelegate *filtered (const EdgeFilterBase &) const { return 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;
virtual RegionDelegate *processed_to_polygons (const EdgeToPolygonProcessorBase &) const;
virtual EdgesDelegate *merged_in_place () { return this; }
virtual EdgesDelegate *merged () const { return new EmptyEdges (); }

View File

@ -22,6 +22,8 @@
#include "dbEmptyRegion.h"
#include "dbEmptyEdges.h"
#include "dbEmptyEdgePairs.h"
#include "dbRegion.h"
namespace db
@ -82,6 +84,18 @@ EmptyRegion::or_with (const Region &other) const
}
}
EdgesDelegate *
EmptyRegion::processed_to_edges (const PolygonToEdgeProcessorBase &) const
{
return new EmptyEdges ();
}
EdgePairsDelegate *
EmptyRegion::processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &) const
{
return new EmptyEdgePairs ();
}
bool
EmptyRegion::equals (const Region &other) const
{

View File

@ -78,6 +78,8 @@ public:
virtual RegionDelegate *filtered (const PolygonFilterBase &) const { return 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;
virtual EdgePairsDelegate *processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &) const;
virtual RegionDelegate *merged_in_place () { return this; }
virtual RegionDelegate *merged_in_place (bool, unsigned int) { return this; }

View File

@ -230,6 +230,10 @@ RegionDelegate *FlatRegion::process_in_place (const PolygonProcessorBase &filter
m_merged_polygons.clear ();
m_is_merged = filter.result_is_merged () && merged_semantics ();
if (filter.result_must_not_be_merged ()) {
set_merged_semantics (false);
}
return this;
}

View File

@ -70,6 +70,7 @@ public:
virtual bool result_is_merged () const { return false; }
virtual bool requires_raw_input () const { return true; }
virtual bool wants_variants () const { return true; }
virtual bool result_must_not_be_merged () const { return false; }
};
// -------------------------------------------------------------------------------------------------------------
@ -90,6 +91,7 @@ public:
virtual bool result_is_merged () const { return false; }
virtual bool requires_raw_input () const { return false; }
virtual bool wants_variants () const { return true; }
virtual bool result_must_not_be_merged () const { return false; }
private:
db::Coord m_d;
@ -116,6 +118,7 @@ public:
virtual bool result_is_merged () const { return true; } // we believe so ...
virtual bool requires_raw_input () const { return false; }
virtual bool wants_variants () const { return true; }
virtual bool result_must_not_be_merged () const { return false; }
private:
double m_rinner, m_router;
@ -144,6 +147,7 @@ public:
virtual bool result_is_merged () const { return true; } // we believe so ...
virtual bool requires_raw_input () const { return false; }
virtual bool wants_variants () const { return true; }
virtual bool result_must_not_be_merged () const { return false; }
};
// -------------------------------------------------------------------------------------------------------------
@ -165,6 +169,7 @@ public:
virtual bool result_is_merged () const { return true; } // we believe so ...
virtual bool requires_raw_input () const { return false; }
virtual bool wants_variants () const { return true; }
virtual bool result_must_not_be_merged () const { return false; }
};
}

View File

@ -660,6 +660,32 @@ public:
return Region (mp_delegate->processed (filter));
}
/**
* @brief Processes the polygons into edges
*
* This method applies a processor returning edges for the polygons.
*
* Merged semantics applies. In merged semantics, the filter will run over
* all merged polygons.
*/
Edges processed (const PolygonToEdgeProcessorBase &filter) const
{
return Edges (mp_delegate->processed_to_edges (filter));
}
/**
* @brief Processes the polygons into edge pairs
*
* This method applies a processor returning edge pairs for the polygons.
*
* Merged semantics applies. In merged semantics, the filter will run over
* all merged polygons.
*/
EdgePairs processed (const PolygonToEdgePairProcessorBase &filter) const
{
return EdgePairs (mp_delegate->processed_to_edge_pairs (filter));
}
/**
* @brief Applies a width check and returns EdgePairs which correspond to violation markers
*

View File

@ -37,6 +37,8 @@ namespace db {
class RecursiveShapeIterator;
class EdgeFilterBase;
class EdgesDelegate;
class EdgePairsDelegate;
/**
* @brief A base class for polygon filters
@ -76,24 +78,30 @@ public:
};
/**
* @brief A base class for polygon processors
* @brief A template base class for polygon processors
*
* A polygon processor can turn a polygon into something else.
*/
class DB_PUBLIC PolygonProcessorBase
template <class Result>
class DB_PUBLIC polygon_processor
{
public:
/**
* @brief Constructor
*/
PolygonProcessorBase () { }
polygon_processor () { }
virtual ~PolygonProcessorBase () { }
/**
* @brief Destructor
*/
virtual ~polygon_processor () { }
/**
* @brief Performs the actual processing
* This method will take the input polygon from "polygon" and puts the results into "res".
* "res" can be empty - in this case, the polygon will be skipped.
*/
virtual void process (const db::Polygon &polygon, std::vector<db::Polygon> &res) const = 0;
virtual void process (const db::Polygon &polygon, std::vector<Result> &res) const = 0;
/**
* @brief Returns the transformation reducer for building cell variants
@ -106,6 +114,13 @@ public:
*/
virtual bool result_is_merged () const = 0;
/**
* @brief Returns true, if the result of this operation must not be merged.
* This feature can be used, if the result represents "degenerated" objects such
* as point-like edges. These must not be merged. Otherwise they disappear.
*/
virtual bool result_must_not_be_merged () const = 0;
/**
* @brief Returns true, if the processor wants raw (not merged) input
*/
@ -118,6 +133,33 @@ public:
virtual bool wants_variants () const = 0;
};
/**
* @brief A polygon-to-polygon processor base class
*/
class DB_PUBLIC PolygonProcessorBase
: public polygon_processor<db::Polygon>
{
// .. nothing yet ..
};
/**
* @brief A polygon-to-edge processor base class
*/
class DB_PUBLIC PolygonToEdgeProcessorBase
: public polygon_processor<db::Edge>
{
// .. nothing yet ..
};
/**
* @brief A polygon-to-edge pair processor base class
*/
class DB_PUBLIC PolygonToEdgePairProcessorBase
: public polygon_processor<db::EdgePair>
{
// .. nothing yet ..
};
/**
* @brief The region iterator delegate
*/
@ -222,6 +264,8 @@ public:
virtual RegionDelegate *filtered (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;
virtual EdgePairsDelegate *processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &filter) const = 0;
virtual RegionDelegate *merged_in_place () = 0;
virtual RegionDelegate *merged_in_place (bool min_coherence, unsigned int min_wc) = 0;