Refactoring of the polygon processing in Region

This commit is contained in:
Matthias Koefferlein 2019-02-19 22:11:55 +01:00
parent 90c1d212a4
commit 496b695ef0
15 changed files with 900 additions and 654 deletions

View File

@ -26,6 +26,7 @@
#include "dbFlatEdgePairs.h"
#include "dbEmptyRegion.h"
#include "dbRegion.h"
#include "dbRegionUtils.h"
#include "dbShapeProcessor.h"
#include "dbBoxConvert.h"
#include "dbBoxScanner.h"
@ -92,60 +93,6 @@ AsIfFlatRegion::edges (const EdgeFilterBase *filter) const
return edges;
}
RegionDelegate *
AsIfFlatRegion::hulls () const
{
std::auto_ptr<FlatRegion> new_region (new FlatRegion (false));
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) {
db::Polygon h;
h.assign_hull (p->begin_hull (), p->end_hull ());
new_region->insert (h);
}
return new_region.release ();
}
RegionDelegate *
AsIfFlatRegion::holes () const
{
std::auto_ptr<FlatRegion> new_region (new FlatRegion (false));
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) {
for (size_t i = 0; i < p->holes (); ++i) {
db::Polygon h;
h.assign_hull (p->begin_hole ((unsigned int) i), p->end_hole ((unsigned int) i));
new_region->insert (h);
}
}
return new_region.release ();
}
RegionDelegate *
AsIfFlatRegion::rounded_corners (double rinner, double router, unsigned int n) const
{
std::auto_ptr<FlatRegion> new_region (new FlatRegion (false));
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) {
new_region->insert (db::compute_rounded (*p, rinner, router, n));
}
return new_region.release ();
}
RegionDelegate *
AsIfFlatRegion::smoothed (coord_type d) const
{
std::auto_ptr<FlatRegion> new_region (new FlatRegion (false));
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) {
new_region->insert (db::smooth (*p, d));
}
return new_region.release ();
}
RegionDelegate *
AsIfFlatRegion::in (const Region &other, bool invert) const
{
@ -301,6 +248,25 @@ AsIfFlatRegion::filtered (const PolygonFilterBase &filter) const
return new_region.release ();
}
RegionDelegate *
AsIfFlatRegion::processed (const PolygonProcessorBase &filter) const
{
std::auto_ptr<FlatRegion> new_region (new FlatRegion ());
std::vector<db::Polygon> poly_res;
for (RegionIterator p (filter.requires_raw_input () ? begin () : begin_merged ()); ! p.at_end (); ++p) {
poly_res.clear ();
filter.process (*p, poly_res);
for (std::vector<db::Polygon>::const_iterator pr = poly_res.begin (); pr != poly_res.end (); ++pr) {
new_region->insert (*pr);
}
}
return new_region.release ();
}
RegionDelegate *
AsIfFlatRegion::selected_interacting_generic (const Edges &other, bool inverse) const
{
@ -593,41 +559,6 @@ AsIfFlatRegion::snapped (db::Coord gx, db::Coord gy)
return new_region.release ();
}
/**
* @brief A helper class to implement the strange polygon detector
*/
struct DB_PUBLIC StrangePolygonInsideFunc
{
inline bool operator() (int wc) const
{
return wc < 0 || wc > 1;
}
};
void
AsIfFlatRegion::produce_shape_for_strange_polygon (const db::Polygon &poly, db::Shapes &shapes)
{
EdgeProcessor ep;
ep.insert (poly);
StrangePolygonInsideFunc inside;
db::GenericMerge<StrangePolygonInsideFunc> op (inside);
db::ShapeGenerator pc (shapes, false);
db::PolygonGenerator pg (pc, false, false);
ep.process (pg, op);
}
RegionDelegate *
AsIfFlatRegion::strange_polygon_check () const
{
std::auto_ptr<FlatRegion> new_region (new FlatRegion (merged_semantics ()));
for (RegionIterator p (begin ()); ! p.at_end (); ++p) {
produce_shape_for_strange_polygon (*p, new_region->raw_polygons ());
}
return new_region.release ();
}
EdgePairs
AsIfFlatRegion::run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) const
{

View File

@ -36,329 +36,6 @@
namespace db {
/**
* @brief A helper class for the DRC functionality which acts as an edge pair receiver
*/
template <class Output>
class edge2edge_check
: public db::box_scanner_receiver<db::Edge, size_t>
{
public:
edge2edge_check (const EdgeRelationFilter &check, Output &output, bool different_polygons, bool requires_different_layers)
: mp_check (&check), mp_output (&output), m_requires_different_layers (requires_different_layers), m_different_polygons (different_polygons),
m_pass (0)
{
m_distance = check.distance ();
}
bool prepare_next_pass ()
{
++m_pass;
if (m_pass == 1) {
if (! m_ep.empty ()) {
m_ep_discarded.resize (m_ep.size (), false);
return true;
}
} else if (m_pass == 2) {
std::vector<bool>::const_iterator d = m_ep_discarded.begin ();
std::vector<db::EdgePair>::const_iterator ep = m_ep.begin ();
while (ep != m_ep.end ()) {
tl_assert (d != m_ep_discarded.end ());
if (! *d) {
mp_output->insert (*ep);
}
++d;
++ep;
}
}
return false;
}
void add (const db::Edge *o1, size_t p1, const db::Edge *o2, size_t p2)
{
if (m_pass == 0) {
// Overlap or inside checks require input from different layers
if ((! m_different_polygons || p1 != p2) && (! m_requires_different_layers || ((p1 ^ p2) & 1) != 0)) {
// ensure that the first check argument is of layer 1 and the second of
// layer 2 (unless both are of the same layer)
int l1 = int (p1 & size_t (1));
int l2 = int (p2 & size_t (1));
db::EdgePair ep;
if (mp_check->check (l1 <= l2 ? *o1 : *o2, l1 <= l2 ? *o2 : *o1, &ep)) {
// found a violation: store inside the local buffer for now. In the second
// pass we will eliminate those which are shielded completely.
size_t n = m_ep.size ();
m_ep.push_back (ep);
m_e2ep.insert (std::make_pair (std::make_pair (*o1, p1), n));
m_e2ep.insert (std::make_pair (std::make_pair (*o2, p2), n));
}
}
} else {
// a simple (complete) shielding implementation which is based on the
// assumption that shielding is relevant as soon as a foreign edge cuts through
// both of the edge pair's connecting edges.
// TODO: this implementation does not take into account the nature of the
// EdgePair - because of "whole_edge" it may not reflect the part actually
// violating the distance.
std::vector<size_t> n1, n2;
for (unsigned int p = 0; p < 2; ++p) {
std::pair<db::Edge, size_t> k (*o1, p1);
for (std::multimap<std::pair<db::Edge, size_t>, size_t>::const_iterator i = m_e2ep.find (k); i != m_e2ep.end () && i->first == k; ++i) {
n1.push_back (i->second);
}
std::sort (n1.begin (), n1.end ());
std::swap (o1, o2);
std::swap (p1, p2);
n1.swap (n2);
}
for (unsigned int p = 0; p < 2; ++p) {
std::vector<size_t> nn;
std::set_difference (n1.begin (), n1.end (), n2.begin (), n2.end (), std::back_inserter (nn));
for (std::vector<size_t>::const_iterator i = nn.begin (); i != nn.end (); ++i) {
if (! m_ep_discarded [*i]) {
db::EdgePair ep = m_ep [*i].normalized ();
if (db::Edge (ep.first ().p1 (), ep.second ().p2 ()).intersect (*o2) &&
db::Edge (ep.second ().p1 (), ep.first ().p2 ()).intersect (*o2)) {
m_ep_discarded [*i] = true;
}
}
}
std::swap (o1, o2);
std::swap (p1, p2);
n1.swap (n2);
}
}
}
/**
* @brief Gets a value indicating whether the check requires different layers
*/
bool requires_different_layers () const
{
return m_requires_different_layers;
}
/**
* @brief Sets a value indicating whether the check requires different layers
*/
void set_requires_different_layers (bool f)
{
m_requires_different_layers = f;
}
/**
* @brief Gets a value indicating whether the check requires different layers
*/
bool different_polygons () const
{
return m_different_polygons;
}
/**
* @brief Sets a value indicating whether the check requires different layers
*/
void set_different_polygons (bool f)
{
m_different_polygons = f;
}
/**
* @brief Gets the distance value
*/
EdgeRelationFilter::distance_type distance () const
{
return m_distance;
}
private:
const EdgeRelationFilter *mp_check;
Output *mp_output;
bool m_requires_different_layers;
bool m_different_polygons;
EdgeRelationFilter::distance_type m_distance;
std::vector<db::EdgePair> m_ep;
std::multimap<std::pair<db::Edge, size_t>, size_t> m_e2ep;
std::vector<bool> m_ep_discarded;
unsigned int m_pass;
};
/**
* @brief A helper class for the DRC functionality which acts as an edge pair receiver
*/
template <class Output>
class poly2poly_check
: public db::box_scanner_receiver<db::Polygon, size_t>
{
public:
poly2poly_check (edge2edge_check<Output> &output)
: mp_output (&output)
{
// .. nothing yet ..
}
void finish (const db::Polygon *o, size_t p)
{
enter (*o, p);
}
void enter (const db::Polygon &o, size_t p)
{
if (! mp_output->requires_different_layers () && ! mp_output->different_polygons ()) {
// finally we check the polygons vs. itself for checks involving intra-polygon interactions
m_scanner.clear ();
m_scanner.reserve (o.vertices ());
m_edges.clear ();
m_edges.reserve (o.vertices ());
for (db::Polygon::polygon_edge_iterator e = o.begin_edge (); ! e.at_end (); ++e) {
m_edges.push_back (*e);
m_scanner.insert (& m_edges.back (), p);
}
tl_assert (m_edges.size () == o.vertices ());
m_scanner.process (*mp_output, mp_output->distance (), db::box_convert<db::Edge> ());
}
}
void add (const db::Polygon *o1, size_t p1, const db::Polygon *o2, size_t p2)
{
enter (*o1, p1, *o2, p2);
}
void enter (const db::Polygon &o1, size_t p1, const db::Polygon &o2, size_t p2)
{
if ((! mp_output->different_polygons () || p1 != p2) && (! mp_output->requires_different_layers () || ((p1 ^ p2) & 1) != 0)) {
m_scanner.clear ();
m_scanner.reserve (o1.vertices () + o2.vertices ());
m_edges.clear ();
m_edges.reserve (o1.vertices () + o2.vertices ());
for (db::Polygon::polygon_edge_iterator e = o1.begin_edge (); ! e.at_end (); ++e) {
m_edges.push_back (*e);
m_scanner.insert (& m_edges.back (), p1);
}
for (db::Polygon::polygon_edge_iterator e = o2.begin_edge (); ! e.at_end (); ++e) {
m_edges.push_back (*e);
m_scanner.insert (& m_edges.back (), p2);
}
tl_assert (m_edges.size () == o1.vertices () + o2.vertices ());
// temporarily disable intra-polygon check in that step .. we do that later in finish()
// if required (#650).
bool no_intra = mp_output->different_polygons ();
mp_output->set_different_polygons (true);
m_scanner.process (*mp_output, mp_output->distance (), db::box_convert<db::Edge> ());
mp_output->set_different_polygons (no_intra);
}
}
private:
db::box_scanner<db::Edge, size_t> m_scanner;
edge2edge_check<Output> *mp_output;
std::vector<db::Edge> m_edges;
};
/**
* @brief A helper class for the region to edge interaction functionality
*/
template <class OutputContainer>
class DB_PUBLIC region_to_edge_interaction_filter
: public db::box_scanner_receiver2<db::Polygon, size_t, db::Edge, size_t>
{
public:
region_to_edge_interaction_filter (OutputContainer &output, bool inverse)
: mp_output (&output), m_inverse (inverse)
{
// .. nothing yet ..
}
void preset (const db::Polygon *poly)
{
m_seen.insert (poly);
}
void add (const db::Polygon *p, size_t, const db::Edge *e, size_t)
{
if ((m_seen.find (p) == 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
bool interacts = false;
if (p->box ().contains (e->p1 ()) && db::inside_poly (p->begin_edge (), e->p1 ()) >= 0) {
interacts = true;
} else {
for (db::Polygon::polygon_edge_iterator pe = p->begin_edge (); ! pe.at_end () && ! interacts; ++pe) {
if ((*pe).intersect (*e)) {
interacts = true;
}
}
}
if (interacts) {
if (m_inverse) {
m_seen.erase (p);
} else {
m_seen.insert (p);
mp_output->insert (*p);
}
}
}
}
void fill_output ()
{
for (std::set<const db::Polygon *>::const_iterator p = m_seen.begin (); p != m_seen.end (); ++p) {
mp_output->insert (**p);
}
}
private:
OutputContainer *mp_output;
std::set<const db::Polygon *> m_seen;
bool m_inverse;
};
/**
* @brief Provides default flat implementations
*/
@ -430,6 +107,13 @@ public:
virtual Edges edges (const EdgeFilterBase *) const;
virtual RegionDelegate *process_in_place (const PolygonProcessorBase &filter)
{
return processed (filter);
}
virtual RegionDelegate *processed (const PolygonProcessorBase &filter) const;
virtual RegionDelegate *filter_in_place (const PolygonFilterBase &filter)
{
return filtered (filter);
@ -454,8 +138,6 @@ public:
virtual RegionDelegate *merged (bool min_coherence, unsigned int min_wc) const;
virtual RegionDelegate *strange_polygon_check () const;
virtual RegionDelegate *sized (coord_type d, unsigned int mode) const;
virtual RegionDelegate *sized (coord_type dx, coord_type dy, unsigned int mode) const;
@ -521,11 +203,7 @@ public:
return selected_interacting_generic (other, 0, false, true);
}
virtual RegionDelegate *holes () const;
virtual RegionDelegate *hulls () const;
virtual RegionDelegate *in (const Region &other, bool invert) const;
virtual RegionDelegate *rounded_corners (double rinner, double router, unsigned int n) const;
virtual RegionDelegate *smoothed (coord_type d) const;
virtual bool equals (const Region &other) const;
virtual bool less (const Region &other) const;
@ -541,7 +219,6 @@ protected:
RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse) const;
RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse) const;
static void produce_shape_for_strange_polygon (const db::Polygon &poly, db::Shapes &shapes);
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);
template <class Trans>

View File

@ -25,6 +25,7 @@
#include "dbDeepShapeStore.h"
#include "dbEmptyRegion.h"
#include "dbRegion.h"
#include "dbRegionUtils.h"
#include "dbDeepEdges.h"
#include "dbDeepEdgePairs.h"
#include "dbShapeProcessor.h"
@ -902,6 +903,83 @@ DeepRegion::edges (const EdgeFilterBase *filter) const
return db::Edges (res.release ());
}
RegionDelegate *
DeepRegion::process_in_place (const PolygonProcessorBase &filter)
{
// TODO: implement to be really in-place
return processed (filter);
}
RegionDelegate *
DeepRegion::processed (const PolygonProcessorBase &filter) const
{
ensure_merged_polygons_valid ();
std::auto_ptr<VariantsCollectorBase> vars;
if (filter.vars ()) {
vars.reset (new db::VariantsCollectorBase (filter.vars ()));
vars->collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ());
// NOTE: m_merged_polygons is mutable, so why is the const_cast needed?
const_cast<db::DeepLayer &> (m_merged_polygons).separate_variants (*vars);
}
db::Layout &layout = m_merged_polygons.layout ();
std::vector<db::Polygon> poly_res;
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.derived ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
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 db::Shapes &s = c->shapes (filter.requires_raw_input () ? m_deep_layer.layer () : m_merged_polygons.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
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) {
st.insert (p->transformed (trinv));
}
}
} else {
const db::Shapes &s = c->shapes (filter.requires_raw_input () ? m_deep_layer.layer () : m_merged_polygons.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
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) {
st.insert (*p);
}
}
}
}
if (filter.result_is_merged ()) {
res->set_is_merged (true);
}
return res.release ();
}
RegionDelegate *
DeepRegion::filter_in_place (const PolygonFilterBase &filter)
{
@ -1043,12 +1121,6 @@ DeepRegion::merged (bool min_coherence, unsigned int min_wc) const
return res;
}
RegionDelegate *
DeepRegion::strange_polygon_check () const
{
throw tl::Exception (tl::to_string (tr ("A strange polygon check does not make sense on a processed region - polygons are already normalized")));
}
RegionDelegate *
DeepRegion::sized (coord_type d, unsigned int mode) const
{
@ -1173,72 +1245,6 @@ DeepRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const
return res.release ();
}
RegionDelegate *
DeepRegion::holes () const
{
ensure_merged_polygons_valid ();
db::Layout &layout = m_merged_polygons.layout ();
std::vector<db::Point> pts;
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.derived ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const db::Shapes &s = c->shapes (m_merged_polygons.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
db::PolygonRefToShapesGenerator pr (&layout, &st);
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
for (size_t i = 0; i < si->holes (); ++i) {
db::Polygon h;
pts.clear ();
for (db::Shape::point_iterator p = si->begin_hole ((unsigned int) i); p != si->end_hole ((unsigned int) i); ++p) {
pts.push_back (*p);
}
h.assign_hull (pts.begin (), pts.end ());
pr.put (h);
}
}
}
res->set_is_merged (true);
return res.release ();
}
RegionDelegate *
DeepRegion::hulls () const
{
ensure_merged_polygons_valid ();
db::Layout &layout = m_merged_polygons.layout ();
std::vector<db::Point> pts;
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.derived ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const db::Shapes &s = c->shapes (m_merged_polygons.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
db::PolygonRefToShapesGenerator pr (&layout, &st);
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
db::Polygon h;
pts.clear ();
for (db::Shape::point_iterator p = si->begin_hull (); p != si->end_hull (); ++p) {
pts.push_back (*p);
}
h.assign_hull (pts.begin (), pts.end ());
pr.put (h);
}
}
res->set_is_merged (true);
return res.release ();
}
RegionDelegate *
DeepRegion::in (const Region &other, bool invert) const
{
@ -1246,79 +1252,6 @@ DeepRegion::in (const Region &other, bool invert) const
return db::AsIfFlatRegion::in (other, invert);
}
RegionDelegate *
DeepRegion::rounded_corners (double rinner, double router, unsigned int n) const
{
ensure_merged_polygons_valid ();
db::cell_variants_collector<db::MagnificationReducer> vars;
vars.collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ());
// NOTE: m_merged_polygons is mutable, so why is the const_cast needed?
const_cast<db::DeepLayer &> (m_merged_polygons).separate_variants (vars);
db::Layout &layout = m_merged_polygons.layout ();
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.derived ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const std::map<db::ICplxTrans, size_t> &v = vars.variants (c->cell_index ());
tl_assert (v.size () == size_t (1));
double mag = v.begin ()->first.mag ();
db::Coord rinner_with_mag = db::coord_traits<db::Coord>::rounded (rinner / mag);
db::Coord router_with_mag = db::coord_traits<db::Coord>::rounded (router / mag);
const db::Shapes &s = c->shapes (m_merged_polygons.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
db::PolygonRefToShapesGenerator pr (&layout, &st);
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
db::Polygon poly;
si->polygon (poly);
pr.put (db::compute_rounded (poly, rinner_with_mag, router_with_mag, n));
}
}
return res.release ();
}
RegionDelegate *
DeepRegion::smoothed (coord_type d) const
{
ensure_merged_polygons_valid ();
db::cell_variants_collector<db::MagnificationReducer> vars;
vars.collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ());
// NOTE: m_merged_polygons is mutable, so why is the const_cast needed?
const_cast<db::DeepLayer &> (m_merged_polygons).separate_variants (vars);
db::Layout &layout = m_merged_polygons.layout ();
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.derived ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const std::map<db::ICplxTrans, size_t> &v = vars.variants (c->cell_index ());
tl_assert (v.size () == size_t (1));
double mag = v.begin ()->first.mag ();
db::Coord d_with_mag = db::coord_traits<db::Coord>::rounded (d / mag);
const db::Shapes &s = c->shapes (m_merged_polygons.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
db::PolygonRefToShapesGenerator pr (&layout, &st);
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
db::Polygon poly;
si->polygon (poly);
pr.put (db::smooth (poly, d_with_mag));
}
}
return res.release ();
}
namespace
{

View File

@ -138,6 +138,8 @@ public:
virtual Edges edges (const EdgeFilterBase *) const;
virtual RegionDelegate *process_in_place (const PolygonProcessorBase &filter);
virtual RegionDelegate *processed (const PolygonProcessorBase &filter) const;
virtual RegionDelegate *filter_in_place (const PolygonFilterBase &filter);
virtual RegionDelegate *filtered (const PolygonFilterBase &filter) const;
@ -147,8 +149,6 @@ public:
virtual RegionDelegate *merged () const;
virtual RegionDelegate *merged (bool min_coherence, unsigned int min_wc) const;
virtual RegionDelegate *strange_polygon_check () const;
virtual RegionDelegate *sized (coord_type d, unsigned int mode) const;
virtual RegionDelegate *sized (coord_type dx, coord_type dy, unsigned int mode) const;
@ -202,11 +202,7 @@ public:
return selected_interacting_generic (other, 0, false, true);
}
virtual RegionDelegate *holes () const;
virtual RegionDelegate *hulls () const;
virtual RegionDelegate *in (const Region &other, bool invert) const;
virtual RegionDelegate *rounded_corners (double rinner, double router, unsigned int n) const;
virtual RegionDelegate *smoothed (coord_type d) const;
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;

View File

@ -41,6 +41,7 @@ class EmptyEdgePairs;
class Edges;
class Region;
class DeepShapeStore;
class TransformationReducer;
/**
* @brief An edge pair set iterator
@ -213,6 +214,7 @@ public:
virtual ~EdgePairFilterBase () { }
virtual bool selected (const db::EdgePair &edge) const = 0;
virtual const TransformationReducer *vars () const = 0;
};
/**

View File

@ -73,11 +73,11 @@ public:
virtual RegionDelegate *snapped_in_place (db::Coord, db::Coord) { return this; }
virtual RegionDelegate *snapped (db::Coord, db::Coord) { return new EmptyRegion (); }
virtual RegionDelegate *strange_polygon_check () const { return new EmptyRegion (); }
virtual Edges edges (const EdgeFilterBase *) const { return db::Edges (); }
virtual RegionDelegate *filter_in_place (const PolygonFilterBase &) { return this; }
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 RegionDelegate *merged_in_place () { return this; }
virtual RegionDelegate *merged_in_place (bool, unsigned int) { return this; }
@ -104,12 +104,7 @@ 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 *holes () const { return new EmptyRegion (); }
virtual RegionDelegate *hulls () const { return new EmptyRegion (); }
virtual RegionDelegate *in (const Region &, bool) const { return new EmptyRegion (); }
virtual RegionDelegate *rounded_corners (double, double, unsigned int) const { return new EmptyRegion (); }
virtual RegionDelegate *smoothed (coord_type) const { return new EmptyRegion (); }
virtual bool has_valid_polygons () const { return true; }
virtual bool has_valid_merged_polygons () const { return true; }

View File

@ -205,6 +205,34 @@ RegionDelegate *FlatRegion::filter_in_place (const PolygonFilterBase &filter)
return this;
}
RegionDelegate *FlatRegion::process_in_place (const PolygonProcessorBase &filter)
{
std::vector<db::Polygon> poly_res;
polygon_iterator_type pw = m_polygons.get_layer<db::Polygon, db::unstable_layer_tag> ().begin ();
for (RegionIterator p (filter.requires_raw_input () ? begin () : begin_merged ()); ! p.at_end (); ++p) {
poly_res.clear ();
filter.process (*p, poly_res);
for (std::vector<db::Polygon>::const_iterator pr = poly_res.begin (); pr != poly_res.end (); ++pr) {
if (pw == m_polygons.get_layer<db::Polygon, db::unstable_layer_tag> ().end ()) {
m_polygons.get_layer<db::Polygon, db::unstable_layer_tag> ().insert (*pr);
pw = m_polygons.get_layer<db::Polygon, db::unstable_layer_tag> ().end ();
} else {
m_polygons.get_layer<db::Polygon, db::unstable_layer_tag> ().replace (pw++, *pr);
}
}
}
m_polygons.get_layer<db::Polygon, db::unstable_layer_tag> ().erase (pw, m_polygons.get_layer<db::Polygon, db::unstable_layer_tag> ().end ());
m_merged_polygons.clear ();
m_is_merged = filter.result_is_merged () && merged_semantics ();
return this;
}
RegionDelegate *FlatRegion::merged_in_place ()
{
if (! m_is_merged) {

View File

@ -119,6 +119,7 @@ public:
return db::AsIfFlatRegion::merged (min_coherence, min_wc);
}
virtual RegionDelegate *process_in_place (const PolygonProcessorBase &filter);
virtual RegionDelegate *filter_in_place (const PolygonFilterBase &filter);
virtual RegionDelegate *add_in_place (const Region &other);

View File

@ -26,10 +26,144 @@
#include "dbEmptyRegion.h"
#include "dbFlatRegion.h"
#include "dbDeepRegion.h"
#include "dbPolygonTools.h"
namespace db
{
namespace
{
// -------------------------------------------------------------------------------------------------------------
// Strange polygon processor
/**
* @brief A helper class to implement the strange polygon detector
*/
struct DB_PUBLIC StrangePolygonInsideFunc
{
inline bool operator() (int wc) const
{
return wc < 0 || wc > 1;
}
};
class StrangePolygonCheckProcessor
: public PolygonProcessorBase
{
public:
StrangePolygonCheckProcessor () { }
virtual void process (const db::Polygon &poly, std::vector<db::Polygon> &res) const
{
EdgeProcessor ep;
ep.insert (poly);
StrangePolygonInsideFunc inside;
db::GenericMerge<StrangePolygonInsideFunc> op (inside);
db::PolygonContainer pc (res, false);
db::PolygonGenerator pg (pc, false, false);
ep.process (pg, op);
}
virtual const TransformationReducer *vars () const { return 0; }
virtual bool result_is_merged () const { return false; }
virtual bool requires_raw_input () const { return true; }
};
// -------------------------------------------------------------------------------------------------------------
// Smoothing processor
class SmoothingProcessor
: public PolygonProcessorBase
{
public:
SmoothingProcessor (db::Coord d) : m_d (d) { }
virtual void process (const db::Polygon &poly, std::vector<db::Polygon> &res) const
{
res.push_back (db::smooth (poly, m_d));
}
virtual const TransformationReducer *vars () const { return &m_vars; }
virtual bool result_is_merged () const { return false; }
virtual bool requires_raw_input () const { return false; }
private:
db::Coord m_d;
db::MagnificationReducer m_vars;
};
// -------------------------------------------------------------------------------------------------------------
// Rounded corners processor
class RoundedCornersProcessor
: public PolygonProcessorBase
{
public:
RoundedCornersProcessor (double rinner, double router, unsigned int n)
: m_rinner (rinner), m_router (router), m_n (n)
{ }
virtual void process (const db::Polygon &poly, std::vector<db::Polygon> &res) const
{
res.push_back (db::compute_rounded (poly, m_rinner, m_router, m_n));
}
virtual const TransformationReducer *vars () const { return &m_vars; }
virtual bool result_is_merged () const { return true; } // we believe so ...
virtual bool requires_raw_input () const { return false; }
private:
double m_rinner, m_router;
unsigned int m_n;
db::MagnificationReducer m_vars;
};
// -------------------------------------------------------------------------------------------------------------
// Holes decomposition processor
class HolesExtractionProcessor
: public PolygonProcessorBase
{
public:
HolesExtractionProcessor () { }
virtual void process (const db::Polygon &poly, std::vector<db::Polygon> &res) const
{
for (size_t i = 0; i < poly.holes (); ++i) {
res.push_back (db::Polygon ());
res.back ().assign_hull (poly.begin_hole ((unsigned int) i), poly.end_hole ((unsigned int) i));
}
}
virtual const TransformationReducer *vars () const { return 0; }
virtual bool result_is_merged () const { return true; } // we believe so ...
virtual bool requires_raw_input () const { return false; }
};
// -------------------------------------------------------------------------------------------------------------
// Hull extraction processor
class HullExtractionProcessor
: public PolygonProcessorBase
{
public:
HullExtractionProcessor () { }
virtual void process (const db::Polygon &poly, std::vector<db::Polygon> &res) const
{
res.push_back (db::Polygon ());
res.back ().assign_hull (poly.begin_hull (), poly.end_hull ());
}
virtual const TransformationReducer *vars () const { return 0; }
virtual bool result_is_merged () const { return true; } // we believe so ...
virtual bool requires_raw_input () const { return false; }
};
}
// -------------------------------------------------------------------------------------------------------------
// Region implementation
@ -174,6 +308,86 @@ Region::flat_region ()
return region;
}
Region &
Region::size (coord_type d, unsigned int mode)
{
set_delegate (mp_delegate->sized (d, mode));
return *this;
}
Region &
Region::size (coord_type dx, coord_type dy, unsigned int mode)
{
set_delegate (mp_delegate->sized (dx, dy, mode));
return *this;
}
Region
Region::sized (coord_type d, unsigned int mode) const
{
return Region (mp_delegate->sized (d, mode));
}
Region
Region::sized (coord_type dx, coord_type dy, unsigned int mode) const
{
return Region (mp_delegate->sized (dx, dy, mode));
}
void
Region::round_corners (double rinner, double router, unsigned int n)
{
process (RoundedCornersProcessor (rinner, router, n));
}
Region
Region::rounded_corners (double rinner, double router, unsigned int n) const
{
return processed (RoundedCornersProcessor (rinner, router, n));
}
void
Region::smooth (coord_type d)
{
process (SmoothingProcessor (d));
}
Region
Region::smoothed (coord_type d) const
{
return processed (SmoothingProcessor (d));
}
void
Region::snap (db::Coord gx, db::Coord gy)
{
set_delegate (mp_delegate->snapped_in_place (gx, gy));
}
Region
Region::snapped (db::Coord gx, db::Coord gy) const
{
return Region (mp_delegate->snapped (gx, gy));
}
Region
Region::strange_polygon_check () const
{
return Region (processed (StrangePolygonCheckProcessor ()));
}
Region
Region::holes () const
{
return Region (processed (HolesExtractionProcessor ()));
}
Region
Region::hulls () const
{
return Region (processed (HullExtractionProcessor ()));
}
}
namespace tl

View File

@ -42,19 +42,6 @@ class EmptyRegion;
class DeepShapeStore;
class TransformationReducer;
/**
* @brief A base class for polygon filters
*/
class DB_PUBLIC PolygonFilterBase
{
public:
PolygonFilterBase () { }
virtual ~PolygonFilterBase () { }
virtual bool selected (const db::Polygon &polygon) const = 0;
virtual const TransformationReducer *vars () const = 0;
};
/**
* @brief A region iterator
*
@ -640,6 +627,39 @@ public:
return Region (mp_delegate->filtered (filter));
}
/**
* @brief Processes the (merged) polygons
*
* This method will keep all polygons for which the processing filter returns true.
* The processing filter can apply modifications too. These modifications will be
* kept in the output region.
*
* Merged semantics applies. In merged semantics, the filter will run over
* all merged polygons.
*/
Region &process (const PolygonProcessorBase &filter)
{
set_delegate (mp_delegate->process_in_place (filter));
return *this;
}
/**
* @brief Returns the processed polygons
*
* This method will keep all polygons for which the processing filter returns true.
* The processing filter can apply modifications too. These modifications will be
* kept in the output region.
*
* Merged semantics applies. In merged semantics, the filter will run over
* all merged polygons.
*
* This method will return a new region with the modified and filtered polygons.
*/
Region processed (const PolygonProcessorBase &filter) const
{
return Region (mp_delegate->processed (filter));
}
/**
* @brief Applies a width check and returns EdgePairs which correspond to violation markers
*
@ -844,18 +864,12 @@ public:
* Snaps the vertices of the polygons to the specified grid.
* different grids can be specified int x and y direction.
*/
void snap (db::Coord gx, db::Coord gy)
{
set_delegate (mp_delegate->snapped_in_place (gx, gy));
}
void snap (db::Coord gx, db::Coord gy);
/**
* @brief Returns the snapped region
*/
Region snapped (db::Coord gx, db::Coord gy) const
{
return Region (mp_delegate->snapped (gx, gy));
}
Region snapped (db::Coord gx, db::Coord gy) const;
/**
* @brief Performs a check for "strange" polygons
@ -865,10 +879,7 @@ public:
*
* Naturally this method will ignore the merged_semantics setting.
*/
Region strange_polygon_check () const
{
return Region (mp_delegate->strange_polygon_check ());
}
Region strange_polygon_check () const;
/**
* @brief Swap with the other region
@ -948,11 +959,7 @@ public:
* @param mode The sizing mode (see EdgeProcessor) for a description of the sizing mode which controls the miter distance.
* @return A reference to self
*/
Region &size (coord_type d, unsigned int mode = 2)
{
set_delegate (mp_delegate->sized (d, mode));
return *this;
}
Region &size (coord_type d, unsigned int mode = 2);
/**
* @brief Anisotropic sizing
@ -966,11 +973,7 @@ public:
* @param dy The vertical sizing
* @param mode The sizing mode (see EdgeProcessor) for a description of the sizing mode which controls the miter distance.
*/
Region &size (coord_type dx, coord_type dy, unsigned int mode = 2)
{
set_delegate (mp_delegate->sized (dx, dy, mode));
return *this;
}
Region &size (coord_type dx, coord_type dy, unsigned int mode = 2);
/**
* @brief Returns the sized region
@ -980,10 +983,7 @@ public:
*
* Merged semantics applies.
*/
Region sized (coord_type d, unsigned int mode = 2) const
{
return Region (mp_delegate->sized (d, mode));
}
Region sized (coord_type d, unsigned int mode = 2) const;
/**
* @brief Returns the sized region
@ -993,10 +993,7 @@ public:
*
* Merged semantics applies.
*/
Region sized (coord_type dx, coord_type dy, unsigned int mode = 2) const
{
return Region (mp_delegate->sized (dx, dy, mode));
}
Region sized (coord_type dx, coord_type dy, unsigned int mode = 2) const;
/**
* @brief Boolean AND operator
@ -1333,10 +1330,7 @@ public:
*
* Merged semantics applies.
*/
Region holes () const
{
return Region (mp_delegate->holes ());
}
Region holes () const;
/**
* @brief Returns the hulls
@ -1346,10 +1340,7 @@ public:
*
* Merged semantics applies.
*/
Region hulls () const
{
return Region (mp_delegate->hulls ());
}
Region hulls () const;
/**
* @brief Returns all polygons which are in the other region
@ -1374,36 +1365,24 @@ public:
* @param router The outer radius in DBU units
* @param n The number of points to use per circle
*/
void round_corners (double rinner, double router, unsigned int n)
{
set_delegate (mp_delegate->rounded_corners (rinner, router, n));
}
void round_corners (double rinner, double router, unsigned int n);
/**
* @brief Returns a new region with rounded corners (out of place)
*/
Region rounded_corners (double rinner, double router, unsigned int n) const
{
return Region (mp_delegate->rounded_corners (rinner, router, n));
}
Region rounded_corners (double rinner, double router, unsigned int n) const;
/**
* @brief Smoothes the region (in-place)
*/
void smooth (coord_type d)
{
set_delegate (mp_delegate->smoothed (d));
}
void smooth (coord_type d);
/**
* @brief Returns the smoothed region
*
* @param d The smoothing accuracy
*/
Region smoothed (coord_type d) const
{
return Region (mp_delegate->smoothed (d));
}
Region smoothed (coord_type d) const;
/**
* @brief Returns the nth polygon

View File

@ -37,7 +37,34 @@ namespace db {
class RecursiveShapeIterator;
class EdgeFilterBase;
class PolygonFilterBase;
/**
* @brief A base class for polygon filters
*/
class DB_PUBLIC PolygonFilterBase
{
public:
PolygonFilterBase () { }
virtual ~PolygonFilterBase () { }
virtual bool selected (const db::Polygon &polygon) const = 0;
virtual const TransformationReducer *vars () const = 0;
};
/**
* @brief A base class for polygon processors
*/
class DB_PUBLIC PolygonProcessorBase
{
public:
PolygonProcessorBase () { }
virtual ~PolygonProcessorBase () { }
virtual void process (const db::Polygon &polygon, std::vector<db::Polygon> &res) const = 0;
virtual const TransformationReducer *vars () const = 0;
virtual bool result_is_merged () const = 0;
virtual bool requires_raw_input () const = 0;
};
/**
* @brief The region iterator delegate
@ -141,14 +168,14 @@ public:
virtual Edges edges (const EdgeFilterBase *filter) const = 0;
virtual RegionDelegate *filter_in_place (const PolygonFilterBase &filter) = 0;
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 RegionDelegate *merged_in_place () = 0;
virtual RegionDelegate *merged_in_place (bool min_coherence, unsigned int min_wc) = 0;
virtual RegionDelegate *merged () const = 0;
virtual RegionDelegate *merged (bool min_coherence, unsigned int min_wc) const = 0;
virtual RegionDelegate *strange_polygon_check () const = 0;
virtual RegionDelegate *sized (coord_type d, unsigned int mode) const = 0;
virtual RegionDelegate *sized (coord_type dx, coord_type dy, unsigned int mode) const = 0;
@ -169,12 +196,7 @@ 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 *holes () const = 0;
virtual RegionDelegate *hulls () const = 0;
virtual RegionDelegate *in (const Region &other, bool invert) const = 0;
virtual RegionDelegate *rounded_corners (double rinner, double router, unsigned int n) const = 0;
virtual RegionDelegate *smoothed (coord_type d) const = 0;
virtual const db::Polygon *nth (size_t n) const = 0;
virtual bool has_valid_polygons () const = 0;

View File

@ -23,9 +23,306 @@
#include "dbRegionUtils.h"
namespace db {
namespace db
{
// .. nothing yet ..
// -------------------------------------------------------------------------------------
// Edge2EdgeCheckBase implementation
Edge2EdgeCheckBase::Edge2EdgeCheckBase (const EdgeRelationFilter &check, bool different_polygons, bool requires_different_layers)
: mp_check (&check), m_requires_different_layers (requires_different_layers), m_different_polygons (different_polygons),
m_pass (0)
{
m_distance = check.distance ();
}
bool
Edge2EdgeCheckBase::prepare_next_pass ()
{
++m_pass;
if (m_pass == 1) {
if (! m_ep.empty ()) {
m_ep_discarded.resize (m_ep.size (), false);
return true;
}
} else if (m_pass == 2) {
std::vector<bool>::const_iterator d = m_ep_discarded.begin ();
std::vector<db::EdgePair>::const_iterator ep = m_ep.begin ();
while (ep != m_ep.end ()) {
tl_assert (d != m_ep_discarded.end ());
if (! *d) {
put (*ep);
}
++d;
++ep;
}
}
return false;
}
void
Edge2EdgeCheckBase::add (const db::Edge *o1, size_t p1, const db::Edge *o2, size_t p2)
{
if (m_pass == 0) {
// Overlap or inside checks require input from different layers
if ((! m_different_polygons || p1 != p2) && (! m_requires_different_layers || ((p1 ^ p2) & 1) != 0)) {
// ensure that the first check argument is of layer 1 and the second of
// layer 2 (unless both are of the same layer)
int l1 = int (p1 & size_t (1));
int l2 = int (p2 & size_t (1));
db::EdgePair ep;
if (mp_check->check (l1 <= l2 ? *o1 : *o2, l1 <= l2 ? *o2 : *o1, &ep)) {
// found a violation: store inside the local buffer for now. In the second
// pass we will eliminate those which are shielded completely.
size_t n = m_ep.size ();
m_ep.push_back (ep);
m_e2ep.insert (std::make_pair (std::make_pair (*o1, p1), n));
m_e2ep.insert (std::make_pair (std::make_pair (*o2, p2), n));
}
}
} else {
// a simple (complete) shielding implementation which is based on the
// assumption that shielding is relevant as soon as a foreign edge cuts through
// both of the edge pair's connecting edges.
// TODO: this implementation does not take into account the nature of the
// EdgePair - because of "whole_edge" it may not reflect the part actually
// violating the distance.
std::vector<size_t> n1, n2;
for (unsigned int p = 0; p < 2; ++p) {
std::pair<db::Edge, size_t> k (*o1, p1);
for (std::multimap<std::pair<db::Edge, size_t>, size_t>::const_iterator i = m_e2ep.find (k); i != m_e2ep.end () && i->first == k; ++i) {
n1.push_back (i->second);
}
std::sort (n1.begin (), n1.end ());
std::swap (o1, o2);
std::swap (p1, p2);
n1.swap (n2);
}
for (unsigned int p = 0; p < 2; ++p) {
std::vector<size_t> nn;
std::set_difference (n1.begin (), n1.end (), n2.begin (), n2.end (), std::back_inserter (nn));
for (std::vector<size_t>::const_iterator i = nn.begin (); i != nn.end (); ++i) {
if (! m_ep_discarded [*i]) {
db::EdgePair ep = m_ep [*i].normalized ();
if (db::Edge (ep.first ().p1 (), ep.second ().p2 ()).intersect (*o2) &&
db::Edge (ep.second ().p1 (), ep.first ().p2 ()).intersect (*o2)) {
m_ep_discarded [*i] = true;
}
}
}
std::swap (o1, o2);
std::swap (p1, p2);
n1.swap (n2);
}
}
}
/**
* @brief Gets a value indicating whether the check requires different layers
*/
bool
Edge2EdgeCheckBase::requires_different_layers () const
{
return m_requires_different_layers;
}
/**
* @brief Sets a value indicating whether the check requires different layers
*/
void
Edge2EdgeCheckBase::set_requires_different_layers (bool f)
{
m_requires_different_layers = f;
}
/**
* @brief Gets a value indicating whether the check requires different layers
*/
bool
Edge2EdgeCheckBase::different_polygons () const
{
return m_different_polygons;
}
/**
* @brief Sets a value indicating whether the check requires different layers
*/
void
Edge2EdgeCheckBase::set_different_polygons (bool f)
{
m_different_polygons = f;
}
/**
* @brief Gets the distance value
*/
EdgeRelationFilter::distance_type
Edge2EdgeCheckBase::distance () const
{
return m_distance;
}
// -------------------------------------------------------------------------------------
// Poly2PolyCheckBase implementation
Poly2PolyCheckBase::Poly2PolyCheckBase (Edge2EdgeCheckBase &output)
: mp_output (& output)
{
// .. nothing yet ..
}
void
Poly2PolyCheckBase::finish (const db::Polygon *o, size_t p)
{
enter (*o, p);
}
void
Poly2PolyCheckBase::enter (const db::Polygon &o, size_t p)
{
if (! mp_output->requires_different_layers () && ! mp_output->different_polygons ()) {
// finally we check the polygons vs. itself for checks involving intra-polygon interactions
m_scanner.clear ();
m_scanner.reserve (o.vertices ());
m_edges.clear ();
m_edges.reserve (o.vertices ());
for (db::Polygon::polygon_edge_iterator e = o.begin_edge (); ! e.at_end (); ++e) {
m_edges.push_back (*e);
m_scanner.insert (& m_edges.back (), p);
}
tl_assert (m_edges.size () == o.vertices ());
m_scanner.process (*mp_output, mp_output->distance (), db::box_convert<db::Edge> ());
}
}
void
Poly2PolyCheckBase::add (const db::Polygon *o1, size_t p1, const db::Polygon *o2, size_t p2)
{
enter (*o1, p1, *o2, p2);
}
void
Poly2PolyCheckBase::enter (const db::Polygon &o1, size_t p1, const db::Polygon &o2, size_t p2)
{
if ((! mp_output->different_polygons () || p1 != p2) && (! mp_output->requires_different_layers () || ((p1 ^ p2) & 1) != 0)) {
m_scanner.clear ();
m_scanner.reserve (o1.vertices () + o2.vertices ());
m_edges.clear ();
m_edges.reserve (o1.vertices () + o2.vertices ());
for (db::Polygon::polygon_edge_iterator e = o1.begin_edge (); ! e.at_end (); ++e) {
m_edges.push_back (*e);
m_scanner.insert (& m_edges.back (), p1);
}
for (db::Polygon::polygon_edge_iterator e = o2.begin_edge (); ! e.at_end (); ++e) {
m_edges.push_back (*e);
m_scanner.insert (& m_edges.back (), p2);
}
tl_assert (m_edges.size () == o1.vertices () + o2.vertices ());
// temporarily disable intra-polygon check in that step .. we do that later in finish()
// if required (#650).
bool no_intra = mp_output->different_polygons ();
mp_output->set_different_polygons (true);
m_scanner.process (*mp_output, mp_output->distance (), db::box_convert<db::Edge> ());
mp_output->set_different_polygons (no_intra);
}
}
// -------------------------------------------------------------------------------------
// RegionToEdgeInteractionFilterBase implementation
RegionToEdgeInteractionFilterBase::RegionToEdgeInteractionFilterBase (bool inverse)
: m_inverse (inverse)
{
// .. nothing yet ..
}
void
RegionToEdgeInteractionFilterBase::preset (const db::Polygon *poly)
{
m_seen.insert (poly);
}
void
RegionToEdgeInteractionFilterBase::add (const db::Polygon *p, size_t, const db::Edge *e, size_t)
{
if ((m_seen.find (p) == 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
bool interacts = false;
if (p->box ().contains (e->p1 ()) && db::inside_poly (p->begin_edge (), e->p1 ()) >= 0) {
interacts = true;
} else {
for (db::Polygon::polygon_edge_iterator pe = p->begin_edge (); ! pe.at_end () && ! interacts; ++pe) {
if ((*pe).intersect (*e)) {
interacts = true;
}
}
}
if (interacts) {
if (m_inverse) {
m_seen.erase (p);
} else {
m_seen.insert (p);
put (*p);
}
}
}
}
void
RegionToEdgeInteractionFilterBase::fill_output ()
{
for (std::set<const db::Polygon *>::const_iterator p = m_seen.begin (); p != m_seen.end (); ++p) {
put (**p);
}
}
}

View File

@ -27,6 +27,7 @@
#include "dbCommon.h"
#include "dbRegion.h"
#include "dbCellVariants.h"
#include "dbBoxScanner.h"
namespace db {
@ -310,6 +311,168 @@ private:
db::MagnificationAndOrientationReducer m_anisotropic_vars;
};
/**
* @brief A helper class for the DRC functionality which acts as an edge pair receiver
*/
class Edge2EdgeCheckBase
: public db::box_scanner_receiver<db::Edge, size_t>
{
public:
Edge2EdgeCheckBase (const EdgeRelationFilter &check, bool different_polygons, bool requires_different_layers);
/**
* @brief Call this to initiate a new pass until the return value is false
*/
bool prepare_next_pass ();
/**
* @brief Reimplementation of the box_scanner_receiver interface
*/
void add (const db::Edge *o1, size_t p1, const db::Edge *o2, size_t p2);
/**
* @brief Gets a value indicating whether the check requires different layers
*/
bool requires_different_layers () const;
/**
* @brief Sets a value indicating whether the check requires different layers
*/
void set_requires_different_layers (bool f);
/**
* @brief Gets a value indicating whether the check requires different layers
*/
bool different_polygons () const;
/**
* @brief Sets a value indicating whether the check requires different layers
*/
void set_different_polygons (bool f);
/**
* @brief Gets the distance value
*/
EdgeRelationFilter::distance_type distance () const;
protected:
virtual void put (const db::EdgePair &edge) const = 0;
private:
const EdgeRelationFilter *mp_check;
bool m_requires_different_layers;
bool m_different_polygons;
EdgeRelationFilter::distance_type m_distance;
std::vector<db::EdgePair> m_ep;
std::multimap<std::pair<db::Edge, size_t>, size_t> m_e2ep;
std::vector<bool> m_ep_discarded;
unsigned int m_pass;
};
/**
* @brief A helper class for the DRC functionality which acts as an edge pair receiver
*/
template <class Output>
class edge2edge_check
: public Edge2EdgeCheckBase
{
public:
edge2edge_check (const EdgeRelationFilter &check, Output &output, bool different_polygons, bool requires_different_layers)
: Edge2EdgeCheckBase (check, different_polygons, requires_different_layers), mp_output (&output)
{
// .. nothing yet ..
}
protected:
void put (const db::EdgePair &edge) const
{
mp_output->insert (edge);
}
private:
Output *mp_output;
};
/**
* @brief A helper class for the DRC functionality which acts as an edge pair receiver
*/
class Poly2PolyCheckBase
: public db::box_scanner_receiver<db::Polygon, size_t>
{
public:
Poly2PolyCheckBase (Edge2EdgeCheckBase &output);
void finish (const db::Polygon *o, size_t p);
void enter (const db::Polygon &o, size_t p);
void add (const db::Polygon *o1, size_t p1, const db::Polygon *o2, size_t p2);
void enter (const db::Polygon &o1, size_t p1, const db::Polygon &o2, size_t p2);
private:
db::Edge2EdgeCheckBase *mp_output;
db::box_scanner<db::Edge, size_t> m_scanner;
std::vector<db::Edge> m_edges;
};
/**
* @brief A helper class for the DRC functionality which acts as an edge pair receiver
*/
template <class Output>
class poly2poly_check
: public Poly2PolyCheckBase
{
public:
poly2poly_check (edge2edge_check<Output> &output)
: Poly2PolyCheckBase (output)
{
// .. nothing yet ..
}
};
/**
* @brief A helper class for the region to edge interaction functionality
*/
class DB_PUBLIC RegionToEdgeInteractionFilterBase
: public db::box_scanner_receiver2<db::Polygon, size_t, db::Edge, size_t>
{
public:
RegionToEdgeInteractionFilterBase (bool inverse);
void preset (const db::Polygon *poly);
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;
private:
std::set<const db::Polygon *> m_seen;
bool m_inverse;
};
/**
* @brief A helper class for the region to edge interaction functionality
*/
template <class OutputContainer>
class DB_PUBLIC region_to_edge_interaction_filter
: public RegionToEdgeInteractionFilterBase
{
public:
region_to_edge_interaction_filter (OutputContainer &output, bool inverse)
: RegionToEdgeInteractionFilterBase (inverse), mp_output (&output)
{
// .. nothing yet ..
}
protected:
virtual void put (const db::Polygon &poly) const
{
mp_output->insert (poly);
}
private:
OutputContainer *mp_output;
};
} // namespace db
#endif

View File

@ -112,6 +112,14 @@ struct EPTestFilter
{
return ep.first ().double_length () < 50;
}
const db::TransformationReducer *vars () const
{
return &m_vars;
}
private:
db::MagnificationReducer m_vars;
};
TEST(3)

Binary file not shown.