mirror of https://github.com/KLayout/klayout.git
First steps towards hiearchical DRC - needs testing.
This commit is contained in:
parent
6e35e80963
commit
5a994fef6d
|
|
@ -701,11 +701,12 @@ namespace
|
|||
*
|
||||
* If will perform a edge by edge check using the provided EdgeRelationFilter
|
||||
*/
|
||||
class Edge2EdgeCheck
|
||||
template <class Output>
|
||||
class edge2edge_check_for_edges
|
||||
: public db::box_scanner_receiver<db::Edge, size_t>
|
||||
{
|
||||
public:
|
||||
Edge2EdgeCheck (const EdgeRelationFilter &check, EdgePairs &output, bool requires_different_layers)
|
||||
edge2edge_check_for_edges (const EdgeRelationFilter &check, Output &output, bool requires_different_layers)
|
||||
: mp_check (&check), mp_output (&output)
|
||||
{
|
||||
m_requires_different_layers = requires_different_layers;
|
||||
|
|
@ -731,7 +732,7 @@ public:
|
|||
|
||||
private:
|
||||
const EdgeRelationFilter *mp_check;
|
||||
EdgePairs *mp_output;
|
||||
Output *mp_output;
|
||||
bool m_requires_different_layers;
|
||||
};
|
||||
|
||||
|
|
@ -771,7 +772,7 @@ AsIfFlatEdges::run_check (db::edge_relation_type rel, const Edges *other, db::Co
|
|||
check.set_min_projection (min_projection);
|
||||
check.set_max_projection (max_projection);
|
||||
|
||||
Edge2EdgeCheck edge_check (check, result, other != 0);
|
||||
edge2edge_check_for_edges<db::EdgePairs> edge_check (check, result, other != 0);
|
||||
scanner.process (edge_check, d, db::box_convert<db::Edge> ());
|
||||
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -595,271 +595,6 @@ AsIfFlatRegion::strange_polygon_check () const
|
|||
return new_region.release ();
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* @brief A helper class for the DRC functionality which acts as an edge pair receiver
|
||||
*/
|
||||
class Edge2EdgeCheck
|
||||
: public db::box_scanner_receiver<db::Edge, size_t>
|
||||
{
|
||||
public:
|
||||
Edge2EdgeCheck (const EdgeRelationFilter &check, EdgePairs &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;
|
||||
EdgePairs *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
|
||||
*/
|
||||
class Poly2PolyCheck
|
||||
: public db::box_scanner_receiver<db::Polygon, size_t>
|
||||
{
|
||||
public:
|
||||
Poly2PolyCheck (Edge2EdgeCheck &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;
|
||||
Edge2EdgeCheck *mp_output;
|
||||
std::vector<db::Edge> m_edges;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
|
|
@ -897,8 +632,8 @@ AsIfFlatRegion::run_check (db::edge_relation_type rel, bool different_polygons,
|
|||
check.set_min_projection (min_projection);
|
||||
check.set_max_projection (max_projection);
|
||||
|
||||
Edge2EdgeCheck edge_check (check, result, different_polygons, other != 0);
|
||||
Poly2PolyCheck poly_check (edge_check);
|
||||
edge2edge_check<db::EdgePairs> edge_check (check, result, different_polygons, other != 0);
|
||||
poly2poly_check<db::EdgePairs> poly_check (edge_check);
|
||||
|
||||
do {
|
||||
scanner.process (poly_check, d, db::box_convert<db::Polygon> ());
|
||||
|
|
@ -918,8 +653,8 @@ AsIfFlatRegion::run_single_polygon_check (db::edge_relation_type rel, db::Coord
|
|||
check.set_min_projection (min_projection);
|
||||
check.set_max_projection (max_projection);
|
||||
|
||||
Edge2EdgeCheck edge_check (check, result, false, false);
|
||||
Poly2PolyCheck poly_check (edge_check);
|
||||
edge2edge_check<db::EdgePairs> edge_check (check, result, false, false);
|
||||
poly2poly_check<db::EdgePairs> poly_check (edge_check);
|
||||
|
||||
do {
|
||||
|
||||
|
|
|
|||
|
|
@ -30,11 +30,274 @@
|
|||
#include "dbPolygon.h"
|
||||
#include "dbEdge.h"
|
||||
#include "dbBoxScanner.h"
|
||||
#include "dbEdgePairRelations.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include "dbEmptyRegion.h"
|
||||
#include "dbRegion.h"
|
||||
#include "dbDeepEdges.h"
|
||||
#include "dbDeepEdgePairs.h"
|
||||
#include "dbShapeProcessor.h"
|
||||
#include "dbFlatRegion.h"
|
||||
#include "dbHierProcessor.h"
|
||||
|
|
@ -1233,18 +1234,142 @@ DeepRegion::smoothed (coord_type d) const
|
|||
return res.release ();
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class CheckLocalOperation
|
||||
: public local_operation<db::PolygonRef, db::PolygonRef, db::EdgePair>
|
||||
{
|
||||
public:
|
||||
CheckLocalOperation (const EdgeRelationFilter &check, bool different_polygons)
|
||||
: m_check (check), m_different_polygons (different_polygons)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual void compute_local (db::Layout * /*layout*/, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::unordered_set<db::EdgePair> &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||
{
|
||||
edge2edge_check<std::unordered_set<db::EdgePair> > edge_check (m_check, result, false, false);
|
||||
poly2poly_check<std::unordered_set<db::EdgePair> > poly_check (edge_check);
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
size_t n = 0;
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i, ++n) {
|
||||
const db::PolygonRef &subject = interactions.subject_shape (i->first);
|
||||
db::Polygon poly = subject.obj ().transformed (subject.trans ());
|
||||
poly_check.enter (poly, n);
|
||||
n += 2;
|
||||
}
|
||||
|
||||
n = 1;
|
||||
for (std::set<db::PolygonRef>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||
db::Polygon poly = o->obj ().transformed (o->trans ());
|
||||
poly_check.enter (poly, n);
|
||||
n += 2;
|
||||
}
|
||||
|
||||
db::box_scanner<db::Polygon, size_t> scanner;
|
||||
|
||||
do {
|
||||
scanner.process (poly_check, m_check.distance (), db::box_convert<db::Polygon> ());
|
||||
} while (edge_check.prepare_next_pass ());
|
||||
}
|
||||
|
||||
virtual db::Coord dist () const
|
||||
{
|
||||
// TODO: will the distance be sufficient? Or should be take somewhat more?
|
||||
return m_check.distance ();
|
||||
}
|
||||
|
||||
virtual on_empty_intruder_mode on_empty_intruder_hint () const
|
||||
{
|
||||
return m_different_polygons ? Drop : Ignore;
|
||||
}
|
||||
|
||||
virtual std::string description () const
|
||||
{
|
||||
return tl::to_string (tr ("Generic DRC check"));
|
||||
}
|
||||
|
||||
private:
|
||||
EdgeRelationFilter m_check;
|
||||
bool m_different_polygons;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
EdgePairs
|
||||
DeepRegion::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
|
||||
{
|
||||
// TODO: implement hierarchically
|
||||
return db::AsIfFlatRegion::run_check (rel, different_polygons, other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection);
|
||||
const db::DeepRegion *other_deep = dynamic_cast<const db::DeepRegion *> (other->delegate ());
|
||||
if (! other_deep) {
|
||||
return db::AsIfFlatRegion::run_check (rel, different_polygons, other, d, whole_edges, metrics, ignore_angle, min_projection, max_projection);
|
||||
}
|
||||
|
||||
ensure_merged_polygons_valid ();
|
||||
|
||||
EdgeRelationFilter check (rel, d, metrics);
|
||||
check.set_whole_edges (whole_edges);
|
||||
check.set_ignore_angle (ignore_angle);
|
||||
check.set_min_projection (min_projection);
|
||||
check.set_max_projection (max_projection);
|
||||
|
||||
DeepLayer dl_out (m_deep_layer.derived ());
|
||||
std::auto_ptr<db::DeepEdgePairs> res (new db::DeepEdgePairs (m_merged_polygons.derived ()));
|
||||
|
||||
db::CheckLocalOperation op (check, different_polygons);
|
||||
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef, db::EdgePair> 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 db::EdgePairs (res.release ());
|
||||
}
|
||||
|
||||
EdgePairs
|
||||
DeepRegion::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
|
||||
{
|
||||
// TODO: implement hierarchically
|
||||
return db::AsIfFlatRegion::run_single_polygon_check (rel, d, whole_edges, metrics, ignore_angle, min_projection, max_projection);
|
||||
ensure_merged_polygons_valid ();
|
||||
|
||||
EdgeRelationFilter check (rel, d, metrics);
|
||||
check.set_whole_edges (whole_edges);
|
||||
check.set_ignore_angle (ignore_angle);
|
||||
check.set_min_projection (min_projection);
|
||||
check.set_max_projection (max_projection);
|
||||
|
||||
db::Layout &layout = m_merged_polygons.layout ();
|
||||
|
||||
std::auto_ptr<db::DeepEdgePairs> res (new db::DeepEdgePairs (m_merged_polygons.derived ()));
|
||||
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
|
||||
|
||||
const db::Shapes &shapes = c->shapes (m_merged_polygons.layer ());
|
||||
db::Shapes &result = c->shapes (res->deep_layer ().layer ());
|
||||
|
||||
for (db::Shapes::shape_iterator s = shapes.begin (db::ShapeIterator::Polygons); ! s.at_end (); ++s) {
|
||||
|
||||
edge2edge_check<db::Shapes> edge_check (check, result, false, false);
|
||||
poly2poly_check<db::Shapes> poly_check (edge_check);
|
||||
|
||||
db::Polygon poly;
|
||||
s->polygon (poly);
|
||||
|
||||
do {
|
||||
poly_check.enter (poly, 0);
|
||||
} while (edge_check.prepare_next_pass ());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return db::EdgePairs (res.release ());
|
||||
}
|
||||
|
||||
namespace
|
||||
|
|
|
|||
Loading…
Reference in New Issue