Further refactoring: provide adressable polygons.

This commit is contained in:
Matthias Koefferlein 2018-11-07 02:44:15 +01:00
parent 9c92a9c72e
commit 885a440089
3 changed files with 154 additions and 20 deletions

View File

@ -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;

View File

@ -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
{

View File

@ -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
*