mirror of https://github.com/KLayout/klayout.git
Edge/edge and edge/polygon interaction test ported to hierarchical mode.
This commit is contained in:
parent
7ef0451ca8
commit
c40f147dc7
|
|
@ -195,149 +195,62 @@ AsIfFlatEdges::to_string (size_t nmax) const
|
|||
return os.str ();
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief A helper class for the edge to region interaction functionality which acts as an edge pair receiver
|
||||
*
|
||||
* Note: This special scanner uses pointers to two different objects: edges and polygons.
|
||||
* It uses odd value pointers to indicate pointers to polygons and even value pointers to indicate
|
||||
* pointers to edges.
|
||||
*
|
||||
* There is a special box converter which is able to sort that out as well.
|
||||
*/
|
||||
template <class OutputContainer>
|
||||
class edge_to_region_interaction_filter
|
||||
: public db::box_scanner_receiver<char, size_t>
|
||||
{
|
||||
public:
|
||||
edge_to_region_interaction_filter (OutputContainer &output)
|
||||
: mp_output (&output)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void add (const char *o1, size_t p1, const char *o2, size_t p2)
|
||||
{
|
||||
const db::Edge *e = 0;
|
||||
const db::Polygon *p = 0;
|
||||
|
||||
// Note: edges have property 0 and have even-valued pointers.
|
||||
// Polygons have property 1 and odd-valued pointers.
|
||||
if (p1 == 0 && p2 == 1) {
|
||||
e = reinterpret_cast<const db::Edge *> (o1);
|
||||
p = reinterpret_cast<const db::Polygon *> (o2 - 1);
|
||||
} else if (p1 == 1 && p2 == 0) {
|
||||
e = reinterpret_cast<const db::Edge *> (o2);
|
||||
p = reinterpret_cast<const db::Polygon *> (o1 - 1);
|
||||
}
|
||||
|
||||
if (e && p && m_seen.find (e) == m_seen.end ()) {
|
||||
if (db::interact (*p, *e)) {
|
||||
m_seen.insert (e);
|
||||
mp_output->insert (*e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
OutputContainer *mp_output;
|
||||
std::set<const db::Edge *> m_seen;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A special box converter that splits the pointers into polygon and edge pointers
|
||||
*/
|
||||
struct EdgeOrRegionBoxConverter
|
||||
{
|
||||
typedef db::Box box_type;
|
||||
|
||||
db::Box operator() (const char &c) const
|
||||
{
|
||||
// Note: edges have property 0 and have even-valued pointers.
|
||||
// Polygons have property 1 and odd-valued pointers.
|
||||
const char *cp = &c;
|
||||
if ((size_t (cp) & 1) == 1) {
|
||||
// it's a polygon
|
||||
return (reinterpret_cast<const db::Polygon *> (cp - 1))->box ();
|
||||
} else {
|
||||
// it's an edge
|
||||
const db::Edge *e = reinterpret_cast<const db::Edge *> (cp);
|
||||
return db::Box (e->p1 (), e->p2 ());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
AsIfFlatEdges::selected_interacting (const Region &other) const
|
||||
AsIfFlatEdges::selected_interacting_generic (const Region &other, bool inverse) const
|
||||
{
|
||||
// shortcuts
|
||||
if (other.empty () || empty ()) {
|
||||
return new EmptyEdges ();
|
||||
}
|
||||
|
||||
db::box_scanner<char, size_t> scanner (report_progress (), progress_desc ());
|
||||
scanner.reserve (size () + other.size ());
|
||||
db::box_scanner2<db::Edge, size_t, db::Polygon, size_t> scanner (report_progress (), progress_desc ());
|
||||
|
||||
AddressableEdgeDelivery e (begin_merged (), has_valid_merged_edges ());
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
scanner.insert ((char *) e.operator-> (), 0);
|
||||
scanner.insert1 (e.operator-> (), 0);
|
||||
}
|
||||
|
||||
AddressablePolygonDelivery p = other.addressable_polygons ();
|
||||
|
||||
for ( ; ! p.at_end (); ++p) {
|
||||
scanner.insert ((char *) p.operator-> () + 1, 1);
|
||||
scanner.insert2 (p.operator-> (), 1);
|
||||
}
|
||||
|
||||
std::auto_ptr<FlatEdges> output (new FlatEdges (true));
|
||||
edge_to_region_interaction_filter<FlatEdges> filter (*output);
|
||||
EdgeOrRegionBoxConverter bc;
|
||||
scanner.process (filter, 1, bc);
|
||||
|
||||
if (! inverse) {
|
||||
|
||||
edge_to_region_interaction_filter<FlatEdges> filter (*output);
|
||||
scanner.process (filter, 1, db::box_convert<db::Edge> (), db::box_convert<db::Polygon> ());
|
||||
|
||||
} else {
|
||||
|
||||
std::set<db::Edge> interacting;
|
||||
edge_to_region_interaction_filter<std::set<db::Edge> > filter (interacting);
|
||||
scanner.process (filter, 1, db::box_convert<db::Edge> (), db::box_convert<db::Polygon> ());
|
||||
|
||||
for (EdgesIterator o (begin_merged ()); ! o.at_end (); ++o) {
|
||||
if (interacting.find (*o) == interacting.end ()) {
|
||||
output->insert (*o);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return output.release ();
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
AsIfFlatEdges::selected_interacting (const Region &other) const
|
||||
{
|
||||
return selected_interacting_generic (other, false);
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
AsIfFlatEdges::selected_not_interacting (const Region &other) const
|
||||
{
|
||||
// shortcuts
|
||||
if (other.empty () || empty ()) {
|
||||
return clone ();
|
||||
}
|
||||
|
||||
db::box_scanner<char, size_t> scanner (report_progress (), progress_desc ());
|
||||
scanner.reserve (size () + other.size ());
|
||||
|
||||
AddressableEdgeDelivery e (begin_merged (), has_valid_merged_edges ());
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
scanner.insert ((char *) e.operator-> (), 0);
|
||||
}
|
||||
|
||||
AddressablePolygonDelivery p = other.addressable_polygons ();
|
||||
|
||||
for ( ; ! p.at_end (); ++p) {
|
||||
scanner.insert ((char *) p.operator-> () + 1, 1);
|
||||
}
|
||||
|
||||
std::set<db::Edge> interacting;
|
||||
edge_to_region_interaction_filter<std::set<db::Edge> > filter (interacting);
|
||||
EdgeOrRegionBoxConverter bc;
|
||||
scanner.process (filter, 1, bc);
|
||||
|
||||
std::auto_ptr<FlatEdges> output (new FlatEdges (true));
|
||||
for (EdgesIterator o (begin_merged ()); ! o.at_end (); ++o) {
|
||||
if (interacting.find (*o) == interacting.end ()) {
|
||||
output->insert (*o);
|
||||
}
|
||||
}
|
||||
|
||||
return output.release ();
|
||||
return selected_interacting_generic (other, true);
|
||||
}
|
||||
|
||||
namespace
|
||||
|
|
@ -483,99 +396,57 @@ AsIfFlatEdges::centers (length_type length, double fraction) const
|
|||
return segments (0, length, fraction);
|
||||
}
|
||||
|
||||
namespace
|
||||
EdgesDelegate *
|
||||
AsIfFlatEdges::selected_interacting_generic (const Edges &edges, bool inverse) const
|
||||
{
|
||||
db::box_scanner<db::Edge, size_t> scanner (report_progress (), progress_desc ());
|
||||
|
||||
/**
|
||||
* @brief A helper class for the edge interaction functionality which acts as an edge pair receiver
|
||||
*/
|
||||
template <class OutputContainer>
|
||||
class edge_interaction_filter
|
||||
: public db::box_scanner_receiver<db::Edge, size_t>
|
||||
{
|
||||
public:
|
||||
edge_interaction_filter (OutputContainer &output)
|
||||
: mp_output (&output)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
AddressableEdgeDelivery e (begin_merged (), has_valid_merged_edges ());
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
scanner.insert (e.operator-> (), 0);
|
||||
}
|
||||
|
||||
void add (const db::Edge *o1, size_t p1, const db::Edge *o2, size_t p2)
|
||||
{
|
||||
// Select the edges which intersect
|
||||
if (p1 != p2) {
|
||||
const db::Edge *o = p1 > p2 ? o2 : o1;
|
||||
const db::Edge *oo = p1 > p2 ? o1 : o2;
|
||||
if (o->intersect (*oo)) {
|
||||
if (m_seen.insert (o).second) {
|
||||
mp_output->insert (*o);
|
||||
}
|
||||
|
||||
AddressableEdgeDelivery ee = edges.addressable_edges ();
|
||||
|
||||
for ( ; ! ee.at_end (); ++ee) {
|
||||
scanner.insert (ee.operator-> (), 1);
|
||||
}
|
||||
|
||||
std::auto_ptr<FlatEdges> output (new FlatEdges (true));
|
||||
|
||||
if (! inverse) {
|
||||
|
||||
edge_interaction_filter<FlatEdges> filter (*output);
|
||||
scanner.process (filter, 1, db::box_convert<db::Edge> ());
|
||||
|
||||
} else {
|
||||
|
||||
std::set<db::Edge> interacting;
|
||||
edge_interaction_filter<std::set<db::Edge> > filter (interacting);
|
||||
scanner.process (filter, 1, db::box_convert<db::Edge> ());
|
||||
|
||||
for (EdgesIterator o (begin_merged ()); ! o.at_end (); ++o) {
|
||||
if (interacting.find (*o) == interacting.end ()) {
|
||||
output->insert (*o);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
OutputContainer *mp_output;
|
||||
std::set<const db::Edge *> m_seen;
|
||||
};
|
||||
|
||||
return output.release ();
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
AsIfFlatEdges::selected_interacting (const Edges &other) const
|
||||
{
|
||||
db::box_scanner<db::Edge, size_t> scanner (report_progress (), progress_desc ());
|
||||
scanner.reserve (size () + other.size ());
|
||||
|
||||
AddressableEdgeDelivery e (begin_merged (), has_valid_merged_edges ());
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
scanner.insert (e.operator-> (), 0);
|
||||
}
|
||||
|
||||
AddressableEdgeDelivery ee = other.addressable_edges ();
|
||||
|
||||
for ( ; ! ee.at_end (); ++ee) {
|
||||
scanner.insert (ee.operator-> (), 1);
|
||||
}
|
||||
|
||||
std::auto_ptr<FlatEdges> output (new FlatEdges (true));
|
||||
edge_interaction_filter<FlatEdges> filter (*output);
|
||||
scanner.process (filter, 1, db::box_convert<db::Edge> ());
|
||||
|
||||
return output.release ();
|
||||
return selected_interacting_generic (other, false);
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
AsIfFlatEdges::selected_not_interacting (const Edges &other) const
|
||||
{
|
||||
db::box_scanner<db::Edge, size_t> scanner (report_progress (), progress_desc ());
|
||||
scanner.reserve (size () + other.size ());
|
||||
|
||||
AddressableEdgeDelivery e (begin_merged (), has_valid_merged_edges ());
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
scanner.insert (e.operator-> (), 0);
|
||||
}
|
||||
|
||||
AddressableEdgeDelivery ee = other.addressable_edges ();
|
||||
|
||||
for ( ; ! ee.at_end (); ++ee) {
|
||||
scanner.insert (ee.operator-> (), 1);
|
||||
}
|
||||
|
||||
std::set<db::Edge> interacting;
|
||||
edge_interaction_filter<std::set<db::Edge> > filter (interacting);
|
||||
scanner.process (filter, 1, db::box_convert<db::Edge> ());
|
||||
|
||||
std::auto_ptr<FlatEdges> output (new FlatEdges (true));
|
||||
for (EdgesIterator o (begin_merged ()); ! o.at_end (); ++o) {
|
||||
if (interacting.find (*o) == interacting.end ()) {
|
||||
output->insert (*o);
|
||||
}
|
||||
}
|
||||
|
||||
return output.release ();
|
||||
return selected_interacting_generic (other, true);
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
#include "dbCommon.h"
|
||||
#include "dbBoxScanner.h"
|
||||
#include "dbEdgesDelegate.h"
|
||||
#include "dbBoxScanner.h"
|
||||
#include "dbPolygonTools.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
|
@ -35,6 +37,74 @@ namespace db {
|
|||
|
||||
class PolygonSink;
|
||||
|
||||
/**
|
||||
* @brief A helper class for the edge interaction functionality which acts as an edge pair receiver
|
||||
*/
|
||||
template <class OutputContainer>
|
||||
class edge_interaction_filter
|
||||
: public db::box_scanner_receiver<db::Edge, size_t>
|
||||
{
|
||||
public:
|
||||
edge_interaction_filter (OutputContainer &output)
|
||||
: mp_output (&output)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void add (const db::Edge *o1, size_t p1, const db::Edge *o2, size_t p2)
|
||||
{
|
||||
// Select the edges which intersect
|
||||
if (p1 != p2) {
|
||||
const db::Edge *o = p1 > p2 ? o2 : o1;
|
||||
const db::Edge *oo = p1 > p2 ? o1 : o2;
|
||||
if (o->intersect (*oo)) {
|
||||
if (m_seen.insert (o).second) {
|
||||
mp_output->insert (*o);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
OutputContainer *mp_output;
|
||||
std::set<const db::Edge *> m_seen;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A helper class for the edge to region interaction functionality which acts as an edge pair receiver
|
||||
*
|
||||
* Note: This special scanner uses pointers to two different objects: edges and polygons.
|
||||
* It uses odd value pointers to indicate pointers to polygons and even value pointers to indicate
|
||||
* pointers to edges.
|
||||
*
|
||||
* There is a special box converter which is able to sort that out as well.
|
||||
*/
|
||||
template <class OutputContainer>
|
||||
class edge_to_region_interaction_filter
|
||||
: public db::box_scanner_receiver2<db::Edge, size_t, db::Polygon, size_t>
|
||||
{
|
||||
public:
|
||||
edge_to_region_interaction_filter (OutputContainer &output)
|
||||
: mp_output (&output)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void add (const db::Edge *e, size_t, const db::Polygon *p, size_t)
|
||||
{
|
||||
if (m_seen.find (e) == m_seen.end ()) {
|
||||
if (db::interact (*p, *e)) {
|
||||
m_seen.insert (e);
|
||||
mp_output->insert (*e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
OutputContainer *mp_output;
|
||||
std::set<const db::Edge *> m_seen;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A helper class to turn joined edge sequences into polygons
|
||||
*
|
||||
|
|
@ -186,6 +256,8 @@ protected:
|
|||
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;
|
||||
static db::Polygon extended_edge (const db::Edge &edge, coord_type ext_b, coord_type ext_e, coord_type ext_o, coord_type ext_i);
|
||||
static db::Edge compute_partial (const db::Edge &edge, int mode, length_type length, double fraction);
|
||||
virtual EdgesDelegate *selected_interacting_generic (const Edges &edges, bool inverse) const;
|
||||
virtual EdgesDelegate *selected_interacting_generic (const Region ®ion, bool inverse) const;
|
||||
|
||||
private:
|
||||
AsIfFlatEdges &operator= (const AsIfFlatEdges &other);
|
||||
|
|
|
|||
|
|
@ -956,33 +956,221 @@ EdgesDelegate *DeepEdges::centers (length_type length, double fraction) const
|
|||
return segments (0, length, fraction);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class Edge2EdgeInteractingLocalOperation
|
||||
: public local_operation<db::Edge, db::Edge, db::Edge>
|
||||
{
|
||||
public:
|
||||
Edge2EdgeInteractingLocalOperation (bool inverse)
|
||||
: m_inverse (inverse)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual void compute_local (db::Layout * /*layout*/, const shape_interactions<db::Edge, db::Edge> &interactions, std::unordered_set<db::Edge> &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||
{
|
||||
db::box_scanner<db::Edge, size_t> scanner;
|
||||
|
||||
std::set<db::Edge> others;
|
||||
for (shape_interactions<db::Edge, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::Edge, db::Edge>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.intruder_shape (*j));
|
||||
}
|
||||
}
|
||||
|
||||
for (shape_interactions<db::Edge, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
const db::Edge &subject = interactions.subject_shape (i->first);
|
||||
scanner.insert (&subject, 0);
|
||||
}
|
||||
|
||||
for (std::set<db::Edge>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||
scanner.insert (o.operator-> (), 1);
|
||||
}
|
||||
|
||||
if (m_inverse) {
|
||||
|
||||
std::unordered_set<db::Edge> interacting;
|
||||
edge_interaction_filter<std::unordered_set<db::Edge> > filter (interacting);
|
||||
scanner.process (filter, 1, db::box_convert<db::Edge> ());
|
||||
|
||||
for (shape_interactions<db::Edge, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
const db::Edge &subject = interactions.subject_shape (i->first);
|
||||
if (interacting.find (subject) == interacting.end ()) {
|
||||
result.insert (subject);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
edge_interaction_filter<std::unordered_set<db::Edge> > filter (result);
|
||||
scanner.process (filter, 1, db::box_convert<db::Edge> ());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
virtual on_empty_intruder_mode on_empty_intruder_hint () const
|
||||
{
|
||||
if (m_inverse) {
|
||||
return Copy;
|
||||
} else {
|
||||
return Drop;
|
||||
}
|
||||
}
|
||||
|
||||
virtual std::string description () const
|
||||
{
|
||||
return tl::to_string (tr ("Select interacting edges"));
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_inverse;
|
||||
};
|
||||
|
||||
class Edge2PolygonInteractingLocalOperation
|
||||
: public local_operation<db::Edge, db::PolygonRef, db::Edge>
|
||||
{
|
||||
public:
|
||||
Edge2PolygonInteractingLocalOperation (bool inverse)
|
||||
: m_inverse (inverse)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual void compute_local (db::Layout * /*layout*/, const shape_interactions<db::Edge, db::PolygonRef> &interactions, std::unordered_set<db::Edge> &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||
{
|
||||
db::box_scanner2<db::Edge, size_t, db::Polygon, size_t> scanner;
|
||||
|
||||
std::set<db::PolygonRef> others;
|
||||
for (shape_interactions<db::Edge, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::Edge, db::PolygonRef>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.intruder_shape (*j));
|
||||
}
|
||||
}
|
||||
|
||||
for (shape_interactions<db::Edge, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
const db::Edge &subject = interactions.subject_shape (i->first);
|
||||
scanner.insert1 (&subject, 0);
|
||||
}
|
||||
|
||||
std::list<db::Polygon> heap;
|
||||
for (std::set<db::PolygonRef>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||
heap.push_back (o->obj ().transformed (o->trans ()));
|
||||
scanner.insert2 (& heap.back (), 1);
|
||||
}
|
||||
|
||||
if (m_inverse) {
|
||||
|
||||
std::unordered_set<db::Edge> interacting;
|
||||
edge_to_region_interaction_filter<std::unordered_set<db::Edge> > filter (interacting);
|
||||
scanner.process (filter, 1, db::box_convert<db::Edge> (), db::box_convert<db::Polygon> ());
|
||||
|
||||
for (shape_interactions<db::Edge, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
const db::Edge &subject = interactions.subject_shape (i->first);
|
||||
if (interacting.find (subject) == interacting.end ()) {
|
||||
result.insert (subject);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
edge_to_region_interaction_filter<std::unordered_set<db::Edge> > filter (result);
|
||||
scanner.process (filter, 1, db::box_convert<db::Edge> (), db::box_convert<db::Polygon> ());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
virtual on_empty_intruder_mode on_empty_intruder_hint () const
|
||||
{
|
||||
if (m_inverse) {
|
||||
return Copy;
|
||||
} else {
|
||||
return Drop;
|
||||
}
|
||||
}
|
||||
|
||||
virtual std::string description () const
|
||||
{
|
||||
return tl::to_string (tr ("Select interacting edges"));
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_inverse;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
DeepEdges::selected_interacting_generic (const Region &other, bool inverse) const
|
||||
{
|
||||
const db::DeepRegion *other_deep = dynamic_cast<const db::DeepRegion *> (other.delegate ());
|
||||
if (! other_deep) {
|
||||
return db::AsIfFlatEdges::selected_interacting_generic (other, inverse);
|
||||
}
|
||||
|
||||
ensure_merged_edges_valid ();
|
||||
|
||||
DeepLayer dl_out (m_deep_layer.derived ());
|
||||
|
||||
db::Edge2PolygonInteractingLocalOperation op (inverse);
|
||||
|
||||
db::local_processor<db::Edge, db::PolygonRef, db::Edge> proc (const_cast<db::Layout *> (&m_deep_layer.layout ()), const_cast<db::Cell *> (&m_deep_layer.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (m_deep_layer.store ()->threads ());
|
||||
|
||||
proc.run (&op, m_merged_edges.layer (), other_deep->deep_layer ().layer (), dl_out.layer ());
|
||||
|
||||
return new db::DeepEdges (dl_out);
|
||||
}
|
||||
|
||||
EdgesDelegate *
|
||||
DeepEdges::selected_interacting_generic (const Edges &other, bool inverse) const
|
||||
{
|
||||
const db::DeepEdges *other_deep = dynamic_cast<const db::DeepEdges *> (other.delegate ());
|
||||
if (! other_deep) {
|
||||
return db::AsIfFlatEdges::selected_interacting_generic (other, inverse);
|
||||
}
|
||||
|
||||
ensure_merged_edges_valid ();
|
||||
|
||||
DeepLayer dl_out (m_deep_layer.derived ());
|
||||
|
||||
db::Edge2EdgeInteractingLocalOperation op (inverse);
|
||||
|
||||
db::local_processor<db::Edge, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&m_deep_layer.layout ()), const_cast<db::Cell *> (&m_deep_layer.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (m_deep_layer.store ()->threads ());
|
||||
|
||||
proc.run (&op, m_merged_edges.layer (), other_deep->deep_layer ().layer (), dl_out.layer ());
|
||||
|
||||
return new db::DeepEdges (dl_out);
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::selected_interacting (const Edges &other) const
|
||||
{
|
||||
// TODO: implement
|
||||
return AsIfFlatEdges::selected_interacting (other);
|
||||
return selected_interacting_generic (other, false);
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::selected_not_interacting (const Edges &other) const
|
||||
{
|
||||
// TODO: implement
|
||||
return AsIfFlatEdges::selected_not_interacting (other);
|
||||
return selected_interacting_generic (other, true);
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::selected_interacting (const Region &other) const
|
||||
{
|
||||
// TODO: implement
|
||||
return AsIfFlatEdges::selected_interacting (other);
|
||||
return selected_interacting_generic (other, false);
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::selected_not_interacting (const Region &other) const
|
||||
{
|
||||
// TODO: implement
|
||||
return AsIfFlatEdges::selected_not_interacting (other);
|
||||
return selected_interacting_generic (other, true);
|
||||
}
|
||||
|
||||
EdgesDelegate *DeepEdges::in (const Edges &other, bool invert) const
|
||||
{
|
||||
// TODO: implement
|
||||
// TODO: is there a cheaper way?
|
||||
return AsIfFlatEdges::in (other, invert);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -174,6 +174,8 @@ private:
|
|||
DeepLayer edge_region_op (const DeepRegion *other, bool outside, bool include_borders) const;
|
||||
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 *segments (int mode, length_type length, double fraction) const;
|
||||
EdgesDelegate *selected_interacting_generic (const Edges &edges, bool invert) const;
|
||||
EdgesDelegate *selected_interacting_generic (const Region ®ion, bool invert) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -342,3 +342,47 @@ TEST(7_Partial)
|
|||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_edges_au7.gds");
|
||||
}
|
||||
|
||||
TEST(8_SelectInteracting)
|
||||
{
|
||||
db::Layout ly;
|
||||
{
|
||||
std::string fn (tl::testsrc ());
|
||||
fn += "/testdata/algo/deep_region_l1.gds";
|
||||
tl::InputStream stream (fn);
|
||||
db::Reader reader (stream);
|
||||
reader.read (ly);
|
||||
}
|
||||
|
||||
db::cell_index_type top_cell_index = *ly.begin_top_down ();
|
||||
db::Cell &top_cell = ly.cell (top_cell_index);
|
||||
|
||||
db::DeepShapeStore dss;
|
||||
|
||||
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
|
||||
unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0));
|
||||
|
||||
db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss);
|
||||
db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss);
|
||||
db::Edges e2 = r2.edges ();
|
||||
db::Edges e3 = r3.edges ();
|
||||
|
||||
db::Layout target;
|
||||
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (2, 0)), r2);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (3, 0)), r3);
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), e2.selected_interacting (e3));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), e2.selected_not_interacting (e3));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), e3.selected_interacting (e2));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), e3.selected_not_interacting (e2));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), e2.selected_interacting (r3));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), e2.selected_not_interacting (r3));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (22, 0)), e3.selected_interacting (r2));
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (23, 0)), e3.selected_not_interacting (r2));
|
||||
|
||||
CHECKPOINT();
|
||||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_edges_au8.gds");
|
||||
}
|
||||
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Reference in New Issue