mirror of https://github.com/KLayout/klayout.git
Further refactoring: provide adressable polygons.
This commit is contained in:
parent
9c92a9c72e
commit
885a440089
|
|
@ -724,8 +724,11 @@ Edges::select_interacting (const Region &other)
|
|||
scanner.insert ((char *) &*e, 0);
|
||||
}
|
||||
|
||||
for (Region::const_iterator p = other.begin (); ! p.at_end (); ++p) {
|
||||
scanner.insert ((char *) &*p + 1, 1);
|
||||
AddressablePolygonDelivery p = other.addressable_polygons ();
|
||||
|
||||
for ( ; ! p.at_end (); ++p) {
|
||||
// NOTE: dirty hack - we can take the address of the polygon because we used ensure_flat_polygons.
|
||||
scanner.insert ((char *) p.operator-> () + 1, 1);
|
||||
}
|
||||
|
||||
Edges output;
|
||||
|
|
@ -753,8 +756,10 @@ Edges::select_not_interacting (const Region &other)
|
|||
scanner.insert ((char *) &*e, 0);
|
||||
}
|
||||
|
||||
for (Region::const_iterator p = other.begin (); ! p.at_end (); ++p) {
|
||||
scanner.insert ((char *) &*p + 1, 1);
|
||||
AddressablePolygonDelivery p = other.addressable_polygons ();
|
||||
for ( ; ! p.at_end (); ++p) {
|
||||
// NOTE: dirty hack - we can take the address of the polygon because we used ensure_flat_polygons.
|
||||
scanner.insert ((char *) p.operator-> () + 1, 1);
|
||||
}
|
||||
|
||||
std::set<db::Edge> interacting;
|
||||
|
|
|
|||
|
|
@ -559,8 +559,10 @@ AsIfFlatRegion::selected_interacting_generic (const Edges &other, bool inverse)
|
|||
db::box_scanner<char, size_t> scanner (report_progress (), progress_desc ());
|
||||
scanner.reserve (size () + other.size ());
|
||||
|
||||
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) {
|
||||
scanner.insert ((char *) &*p + 1, 1);
|
||||
AddressablePolygonDelivery p (begin_merged (), has_valid_merged_polygons ());
|
||||
|
||||
for ( ; ! p.at_end (); ++p) {
|
||||
scanner.insert ((char *) p.operator-> () + 1, 1);
|
||||
}
|
||||
|
||||
other.ensure_valid_merged_edges ();
|
||||
|
|
@ -1019,23 +1021,28 @@ public:
|
|||
}
|
||||
|
||||
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_scanner.reserve (o.vertices ());
|
||||
|
||||
m_edges.clear ();
|
||||
m_edges.reserve (o->vertices ());
|
||||
m_edges.reserve (o.vertices ());
|
||||
|
||||
for (db::Polygon::polygon_edge_iterator e = o->begin_edge (); ! e.at_end (); ++e) {
|
||||
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 ());
|
||||
tl_assert (m_edges.size () == o.vertices ());
|
||||
|
||||
m_scanner.process (*mp_output, mp_output->distance (), db::box_convert<db::Edge> ());
|
||||
|
||||
|
|
@ -1043,26 +1050,31 @@ public:
|
|||
}
|
||||
|
||||
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_scanner.reserve (o1.vertices () + o2.vertices ());
|
||||
|
||||
m_edges.clear ();
|
||||
m_edges.reserve (o1->vertices () + o2->vertices ());
|
||||
m_edges.reserve (o1.vertices () + o2.vertices ());
|
||||
|
||||
for (db::Polygon::polygon_edge_iterator e = o1->begin_edge (); ! e.at_end (); ++e) {
|
||||
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) {
|
||||
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 ());
|
||||
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).
|
||||
|
|
@ -1092,18 +1104,26 @@ AsIfFlatRegion::run_check (db::edge_relation_type rel, bool different_polygons,
|
|||
db::box_scanner<db::Polygon, size_t> scanner (report_progress (), progress_desc ());
|
||||
scanner.reserve (size () + (other ? other->size () : 0));
|
||||
|
||||
AddressablePolygonDelivery p (begin_merged (), has_valid_merged_polygons ());
|
||||
|
||||
size_t n = 0;
|
||||
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) {
|
||||
scanner.insert (&*p, n);
|
||||
for ( ; ! p.at_end (); ++p) {
|
||||
scanner.insert (p.operator-> (), n);
|
||||
n += 2;
|
||||
}
|
||||
|
||||
AddressablePolygonDelivery po;
|
||||
|
||||
if (other) {
|
||||
|
||||
po = other->addressable_merged_polygons ();
|
||||
|
||||
n = 1;
|
||||
for (RegionIterator p (other->begin_merged ()); ! p.at_end (); ++p) {
|
||||
scanner.insert (&*p, n);
|
||||
for ( ; ! po.at_end (); ++po) {
|
||||
scanner.insert (po.operator-> (), n);
|
||||
n += 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
EdgeRelationFilter check (rel, d, metrics);
|
||||
|
|
@ -1138,11 +1158,13 @@ AsIfFlatRegion::run_single_polygon_check (db::edge_relation_type rel, db::Coord
|
|||
Poly2PolyCheck poly_check (edge_check);
|
||||
|
||||
do {
|
||||
|
||||
size_t n = 0;
|
||||
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) {
|
||||
poly_check.finish (&*p, n);
|
||||
poly_check.enter (*p, n);
|
||||
n += 2;
|
||||
}
|
||||
|
||||
} while (edge_check.prepare_next_pass ());
|
||||
|
||||
return result;
|
||||
|
|
@ -1966,6 +1988,11 @@ bool FlatRegion::has_valid_polygons () const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool FlatRegion::has_valid_merged_polygons () const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const db::RecursiveShapeIterator *FlatRegion::iter () const
|
||||
{
|
||||
return 0;
|
||||
|
|
@ -2205,6 +2232,12 @@ OriginalLayerRegion::has_valid_polygons () const
|
|||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
OriginalLayerRegion::has_valid_merged_polygons () const
|
||||
{
|
||||
return merged_semantics () && ! m_is_merged;
|
||||
}
|
||||
|
||||
const db::RecursiveShapeIterator *
|
||||
OriginalLayerRegion::iter () const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@
|
|||
#include "tlString.h"
|
||||
#include "gsiObject.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
namespace db {
|
||||
|
||||
class EdgeFilterBase;
|
||||
|
|
@ -526,6 +528,7 @@ public:
|
|||
|
||||
virtual const db::Polygon *nth (size_t n) const = 0;
|
||||
virtual bool has_valid_polygons () const = 0;
|
||||
virtual bool has_valid_merged_polygons () const = 0;
|
||||
|
||||
virtual const db::RecursiveShapeIterator *iter () const = 0;
|
||||
|
||||
|
|
@ -636,6 +639,7 @@ public:
|
|||
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; }
|
||||
virtual const db::Polygon *nth (size_t) const { tl_assert (false); }
|
||||
|
||||
virtual const db::RecursiveShapeIterator *iter () const { return 0; }
|
||||
|
|
@ -883,6 +887,7 @@ public:
|
|||
|
||||
virtual const db::Polygon *nth (size_t n) const;
|
||||
virtual bool has_valid_polygons () const;
|
||||
virtual bool has_valid_merged_polygons () const;
|
||||
|
||||
virtual const db::RecursiveShapeIterator *iter () const;
|
||||
|
||||
|
|
@ -980,6 +985,7 @@ public:
|
|||
|
||||
virtual const db::Polygon *nth (size_t n) const;
|
||||
virtual bool has_valid_polygons () const;
|
||||
virtual bool has_valid_merged_polygons () const;
|
||||
|
||||
virtual const db::RecursiveShapeIterator *iter () const;
|
||||
|
||||
|
|
@ -999,6 +1005,61 @@ private:
|
|||
void ensure_merged_polygons_valid () const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A helper class allowing delivery of addressable polygons
|
||||
*
|
||||
* In some applications (i.e. box scanner), polygons need to be taken
|
||||
* by address. The region cannot always deliver adressable polygons.
|
||||
* This class help providing this ability by keeping a temporary copy
|
||||
* if required.
|
||||
*/
|
||||
|
||||
class DB_PUBLIC AddressablePolygonDelivery
|
||||
{
|
||||
public:
|
||||
AddressablePolygonDelivery ()
|
||||
: m_iter (), m_valid (false)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
AddressablePolygonDelivery (const RegionIterator &iter, bool valid)
|
||||
: m_iter (iter), m_valid (valid)
|
||||
{
|
||||
if (! m_valid && ! m_iter.at_end ()) {
|
||||
m_heap.push_back (*m_iter);
|
||||
}
|
||||
}
|
||||
|
||||
bool at_end () const
|
||||
{
|
||||
return m_iter.at_end ();
|
||||
}
|
||||
|
||||
AddressablePolygonDelivery &operator++ ()
|
||||
{
|
||||
++m_iter;
|
||||
if (! m_valid && ! m_iter.at_end ()) {
|
||||
m_heap.push_back (*m_iter);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
const db::Polygon *operator-> () const
|
||||
{
|
||||
if (m_valid) {
|
||||
return m_iter.operator-> ();
|
||||
} else {
|
||||
return &m_heap.back ();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
RegionIterator m_iter;
|
||||
bool m_valid;
|
||||
std::list<db::Polygon> m_heap;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A region
|
||||
*
|
||||
|
|
@ -2161,12 +2222,47 @@ public:
|
|||
|
||||
/**
|
||||
* @brief Returns true, if the region has valid polygons stored within itself
|
||||
*
|
||||
* If the region has valid polygons, it is permissable to use the polygon's addresses
|
||||
* from the iterator. Furthermore, the random access operator nth() is available.
|
||||
*/
|
||||
bool has_valid_polygons () const
|
||||
{
|
||||
return mp_delegate->has_valid_polygons ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns an addressable delivery for polygons
|
||||
*
|
||||
* This object allows accessing the polygons by address, even if they
|
||||
* are not delivered from a container. The magic is a heap object
|
||||
* inside the delivery object. Hence, the deliver object must persist
|
||||
* as long as the addresses are required.
|
||||
*/
|
||||
AddressablePolygonDelivery addressable_polygons () const
|
||||
{
|
||||
return AddressablePolygonDelivery (begin (), has_valid_polygons ());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true, if the region has valid merged polygons stored within itself
|
||||
*
|
||||
* If the region has valid merged polygons, it is permissable to use the polygon's addresses
|
||||
* from the merged polygon iterator. Furthermore, the random access operator nth() is available.
|
||||
*/
|
||||
bool has_valid_merged_polygons () const
|
||||
{
|
||||
return mp_delegate->has_valid_merged_polygons ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns an addressable delivery for merged polygons
|
||||
*/
|
||||
AddressablePolygonDelivery addressable_merged_polygons () const
|
||||
{
|
||||
return AddressablePolygonDelivery (begin_merged (), has_valid_merged_polygons ());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the internal iterator
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue