klayout/src/db/dbEdgeProcessor.h

970 lines
33 KiB
C
Raw Normal View History

/*
KLayout Layout Viewer
Copyright (C) 2006-2016 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef HDR_dbEdgeProcessor
#define HDR_dbEdgeProcessor
#include "dbCommon.h"
#include "dbTypes.h"
#include "dbEdge.h"
#include "dbPolygon.h"
#include <vector>
#include <set>
namespace db
{
struct WorkEdge;
struct CutPoints;
class EdgeSink;
/**
* @brief A destination for a (sorted) set of edges
*
* This receiver can be used as destination for the edge processor.
* It will receive edge events in the scanline order, this is bottom to
* top and left to right. Edges will be non-intersecting.
*
* This is the base class for such edge receivers.
*/
class DB_PUBLIC EdgeSink
{
public:
/**
* @brief Constructor
*/
EdgeSink () { }
/**
* @brief Destructor
*/
virtual ~EdgeSink () { };
/**
* @brief Start event
*
* This method is called shortly before the first edge is delivered.
* Specifically, all edges are already cached before this method is called.
* Thus, inside an implementation of this method, the original source can be
* discarded.
*/
virtual void start () { }
/**
* @brief End event
*
* This method is called after the last edge has been delivered.
*/
virtual void flush () { }
/**
* @brief Deliver an edge
*
* This method delivers an edge that ends or starts at the current scanline.
*/
virtual void put (const db::Edge &) { }
/**
* @brief Deliver an edge that crosses the scanline
*
* This method is called to deliver an edge that is not starting or ending at the
* current scanline.
* Another delivery of a set of crossing edges may happen through the skip_n
* method which delivers a set of (unspecified) edges which are guaranteed to form
* a closed sequence, that is one which is starting and ending at a wrap count of 0.
*/
virtual void crossing_edge (const db::Edge &) { }
/**
* @brief Deliver an edge set forming a closed sequence
*
* See description of "crossing_egde" for details.
*/
virtual void skip_n (size_t /*n*/) { }
/**
* @brief Signal the start of a scanline at the given y coordinate
*/
virtual void begin_scanline (db::Coord /*y*/) { }
/**
* @brief Signal the end of a scanline at the given y coordinate
*/
virtual void end_scanline (db::Coord /*y*/) { }
};
/**
* @brief A edge container that can be used as a receiver for edges
*
* This class reimplements the EdgeSink interface.
* This receiver simply collects the edges in a container (a vector of edges)
* which is either kept internally or supplied from the outside.
*/
class DB_PUBLIC EdgeContainer
: public EdgeSink
{
public:
/**
* @brief Constructor connecting this receiver to an external edge vector
*/
EdgeContainer (std::vector<db::Edge> &edges, bool clear = false)
: EdgeSink (), mp_edges (&edges), m_clear (clear)
{ }
/**
* @brief Constructor using an internal edge vector
*/
EdgeContainer ()
: EdgeSink (), mp_edges (&m_edges), m_clear (false)
{ }
/**
* @brief Get the edges collected so far (const version)
*/
const std::vector<db::Edge> &edges () const
{
return *mp_edges;
}
/**
* @brief Get the edges collected so far (non-const version)
*/
std::vector<db::Edge> &edges ()
{
return *mp_edges;
}
/**
* @brief Implementation of the EdgeSink interface
*/
virtual void start ()
{
if (m_clear) {
mp_edges->clear ();
// The single-shot scheme is a easy way to overcome problems with multiple start/flush brackets (i.e. on size filter)
m_clear = false;
}
}
/**
* @brief Implementation of the EdgeSink interface
*/
virtual void put (const db::Edge &e)
{
mp_edges->push_back (e);
}
private:
std::vector<db::Edge> m_edges;
std::vector<db::Edge> *mp_edges;
bool m_clear;
};
/**
* @brief The edge set operator base class
*
* This class is an internal class that specifies how the output is formed from
* a set of intersecting-free input edges.
* Basically, this object receives events for the edges along the scan line.
* At the beginning of the scan line, the "reset" method is called to bring the
* evaluator into a defined state. Each edge has an integer property that can be
* used to distinguish edges from different polygons or layers.
*/
class DB_PUBLIC EdgeEvaluatorBase
{
public:
typedef size_t property_type;
EdgeEvaluatorBase () { }
virtual ~EdgeEvaluatorBase () { }
virtual void reset () { }
virtual void reserve (size_t /*n*/) { }
virtual int edge (bool /*north*/, bool /*enter*/, property_type /*p*/) { return 0; }
virtual bool select_edge (bool /*horizontal*/, property_type /*p*/) { return false; }
virtual int compare_ns () const { return 0; }
virtual bool is_reset () const { return false; }
virtual bool prefer_touch () const { return false; }
virtual bool selects_edges () const { return false; }
};
/**
* @brief An intersection detector
*
* This edge evaluator will not produce output edges but rather record the
* property pairs of polygons intersecting. Only intersections (overlaps)
* are recorded. Touching contacts are not recorded.
*
* It will build a set of property pairs, where the lower property value
* is the first one of the pairs.
*/
class DB_PUBLIC InteractionDetector
: public EdgeEvaluatorBase
{
public:
typedef std::set<std::pair<property_type, property_type> > interactions_type;
typedef interactions_type::const_iterator iterator;
/**
* @brief Constructor
*
* The mode parameter selects the interaction check mode.
* 0 is "overlapping".
* -1 will select all polygons inside polygons from the other layer.
* +1 will select all polygons outside polygons from the other layer.
*
* In mode -1 and +1, finish () needs to be called before the interactions
* can be used. In mode -1 and +1, the interactions delivered will contain
* interactions of the reference property vs. the property of the respective
* input polygons (property != reference property). In mode +1 these are
* pseudo-interactions, because "outside" by definition means non-interacting.
*
* Mode -1 (inside) and +1 (outside) requires a single property value for the containing region.
* This property value must be specified in the container_id parameter.
* For correct operation, the container_id must be the lowest property ID and
* the interacting edges must have higher property id's.
* The reported interactions will be (container_id,polygon_id) even for outside mode.
*/
InteractionDetector (int mode = 0, property_type container_id = 0);
/**
* @brief Sets the "touching" flag
*
* If this flag is set, the interaction will include "touching" interactions in mode 0, i.e.
* touching shapes will be counted as interacting.
*/
void set_include_touching (bool f)
{
m_include_touching = f;
}
/**
* @brief Gets the "touching" flag
*/
bool include_touching () const
{
return m_include_touching;
}
/**
* @brief Finish the collection
*
* This method must be called in mode -1 and +1 in order to finish the collection.
*/
void finish ();
/**
* @brief Iterator delivering the interactions (begin iterator)
*
* The iterator delivers pairs of property values. The lower value will be the first one of the pair.
*/
iterator begin () const
{
return m_interactions.begin ();
}
/**
* @brief Iterator delivering the interactions (end iterator)
*/
iterator end () const
{
return m_interactions.end ();
}
virtual void reset ();
virtual void reserve (size_t n);
virtual int edge (bool north, bool enter, property_type p);
virtual int compare_ns () const;
virtual bool is_reset () const { return m_inside.empty (); }
virtual bool prefer_touch () const { return m_mode == 0 && m_include_touching; }
private:
int m_mode;
bool m_include_touching;
property_type m_container_id;
std::vector <int> m_wcv_n, m_wcv_s;
std::set <property_type> m_inside;
std::set<std::pair<property_type, property_type> > m_interactions;
std::set<property_type> m_non_interactions;
};
/**
* @brief A generic inside operator
*
* This incarnation of the evaluator class implements an "inside" function
* based on a generic operator.
*/
template <class F>
class DB_PUBLIC GenericMerge
: public EdgeEvaluatorBase
{
public:
/**
* @brief Constructor
*/
GenericMerge (const F &function)
: m_wc_n (0), m_wc_s (0), m_function (function)
{ }
virtual void reset ()
{
m_wc_n = m_wc_s = 0;
}
virtual void reserve (size_t /*n*/)
{
// .. nothing yet ..
}
virtual int edge (bool north, bool enter, property_type /*p*/)
{
int *wc = north ? &m_wc_n : &m_wc_s;
bool t0 = m_function (*wc);
if (enter) {
++*wc;
} else {
--*wc;
}
bool t1 = m_function (*wc);
if (t1 && ! t0) {
return 1;
} else if (! t1 && t0) {
return -1;
} else {
return 0;
}
}
virtual int compare_ns () const
{
if (m_function (m_wc_s) && ! m_function (m_wc_n)) {
return -1;
} else if (! m_function (m_wc_s) && m_function (m_wc_n)) {
return 1;
} else {
return 0;
}
}
virtual bool is_reset () const
{
return (m_wc_n == 0 && m_wc_s == 0);
}
private:
int m_wc_n, m_wc_s;
F m_function;
};
/**
* @brief A helper class to implement the SimpleMerge operator
*/
struct ParametrizedInsideFunc
{
ParametrizedInsideFunc (int mode)
: m_mode (mode)
{
// .. nothing yet ..
}
inline bool operator() (int wc) const
{
if (m_mode > 0) {
return wc >= m_mode;
} else if (m_mode < 0) {
return wc <= m_mode || -wc <= m_mode;
} else {
return (wc < 0 ? ((-wc) % 2) : (wc % 2)) != 0;
}
}
public:
int m_mode;
};
/**
* @brief Simple merge operator
*
* This incarnation of the evaluator class implements a simple
* merge criterion for a set of edges. A result is generated if the wrap count (wc)
* of the edge set satisfies a condition given by "mode". Specifically:
* mode == 0: even-odd rule (wc = ... -3, -1, 1, 3, ...)
* mode == 1: wc >= 1
* mode == -1: wc >= 1 || wc <= -1
* mode == n: wc >= n
* mode == -n: wc >= n || wc <= -n
*/
class DB_PUBLIC SimpleMerge
: public GenericMerge<ParametrizedInsideFunc>
{
public:
/**
* @brief Constructor
*/
SimpleMerge (int mode = -1)
: GenericMerge<ParametrizedInsideFunc> (ParametrizedInsideFunc (mode))
{ }
};
/**
* @brief Boolean operations
*
* This incarnation of the evaluator class implements a boolean operation
* (AND, A NOT B, B NOT A, XOR, OR). The mode can be specified in the constructor.
* It relies on the properties being set in a certain way: bit 0 codes the layer (0 for A, 1 for B)
* while the other bits are used to distinguish the polygons. For each polygon, a non-zero
* wrap count rule is applied before the boolean operation's output is formed.
*/
class DB_PUBLIC BooleanOp
: public EdgeEvaluatorBase
{
public:
enum BoolOp {
And = 1, ANotB = 2, BNotA = 3, Xor = 4, Or = 5
};
/**
* @brief Constructor
*
* @param mode The boolean operation that this object represents
*/
BooleanOp (BoolOp mode);
virtual void reset ();
virtual void reserve (size_t n);
virtual int edge (bool north, bool enter, property_type p);
virtual int compare_ns () const;
virtual bool is_reset () const { return m_zeroes == m_wcv_n.size () + m_wcv_s.size (); }
protected:
template <class InsideFunc> bool result (int wca, int wcb, const InsideFunc &inside_a, const InsideFunc &inside_b) const;
template <class InsideFunc> int edge_impl (bool north, bool enter, property_type p, const InsideFunc &inside_a, const InsideFunc &inside_b);
template <class InsideFunc> int compare_ns_impl (const InsideFunc &inside_a, const InsideFunc &inside_b) const;
private:
int m_wc_na, m_wc_nb, m_wc_sa, m_wc_sb;
std::vector <int> m_wcv_n, m_wcv_s;
BoolOp m_mode;
size_t m_zeroes;
};
/**
* @brief Edge vs. Polygon intersection
*
* This operator detects edges inside or outside polygons.
* The polygon edges must be given with property 0, the other edges
* with properties 1 and higher.
*
* The operator will deliver edges inside polygons or outside polygons.
* It can be configured to include edges on the border of the polygons
* as being considered "inside the polygon".
*/
class DB_PUBLIC EdgePolygonOp
: public db::EdgeEvaluatorBase
{
public:
/**
* @brief Constructor
*
* @param outside If true, the operator will deliver edges outside the polygon
* @param include_touching If true, edges on the polygon's border will be considered "inside" of polygons
* @param polygon_mode Determines how the polygon edges on property 0 are interpreted (see merge operators)
*/
EdgePolygonOp (bool outside = false, bool include_touching = true, int polygon_mode = -1);
virtual void reset ();
virtual bool select_edge (bool horizontal, property_type p);
virtual int edge (bool north, bool enter, property_type p);
virtual bool is_reset () const;
virtual bool prefer_touch () const;
virtual bool selects_edges () const;
private:
bool m_outside, m_include_touching;
db::ParametrizedInsideFunc m_function;
int m_wcp_n, m_wcp_s;
};
/**
* @brief Boolean operations
*
* This class implements a boolean operation similar to BooleanOp, but
* in addition it allows to specify the merge mode for the two inputs.
* See "SimpleMergeOp" for the definition of the merge modes.
* This operator is especially useful to implement boolean operations
* with sized polygons which required a >0 interpretation.
*/
class DB_PUBLIC BooleanOp2
: public BooleanOp
{
public:
/**
* @brief Constructor
*
* @param mode The boolean operation that this object represents
*/
BooleanOp2 (BoolOp mode, int wc_mode_a, int wc_mode_b);
virtual int edge (bool north, bool enter, property_type p);
virtual int compare_ns () const;
private:
int m_wc_mode_a, m_wc_mode_b;
};
/**
* @brief Merge operation
*
* This incarnation of the evaluator class implements a merge operation
* which allows to distinguish polygons (through edge properties) and
* allows to specify a overlap value. Default is 0 which means that the
* merge is equivalent to producing all polygins. A overlap value of 1 means
* that at least two polygons must overlap to produce a result.
*/
class DB_PUBLIC MergeOp
: public EdgeEvaluatorBase
{
public:
/**
* @brief Constructor
*
* @param min_overlap See class description
*/
MergeOp (unsigned int min_overlap = 0);
virtual void reset ();
virtual void reserve (size_t n);
virtual int edge (bool north, bool enter, property_type p);
virtual int compare_ns () const;
virtual bool is_reset () const { return m_zeroes == m_wcv_n.size () + m_wcv_s.size (); }
private:
int m_wc_n, m_wc_s;
std::vector <int> m_wcv_n, m_wcv_s;
unsigned int m_min_wc;
size_t m_zeroes;
};
/**
* @brief The basic edge processor
*
* An edge processor takes a set of edges, processes them by removing intersections and
* applying a custom operator for computing the output edge sets which then are delivered
* to an EdgeSink receiver object.
*/
class DB_PUBLIC EdgeProcessor
{
public:
typedef size_t property_type;
/**
* @brief Default constructor
*
* @param report_progress If true, a tl::Progress object will be created to report any progress (warning: this will impose a performance penalty)
* @param progress_text The description text of the progress object
*/
EdgeProcessor (bool report_progress = false, const std::string &progress_desc = std::string ());
/**
* @brief Destructor
*/
~EdgeProcessor ();
/**
* @brief Enable progress reporting
*
* @param progress_text The description text of the progress object
*/
void enable_progress (const std::string &progress_desc = std::string ());
/**
* @brief Disable progress reporting
*/
void disable_progress ();
/**
* @brief Reserve space for at least n edges
*/
void reserve (size_t n);
/**
* @brief Insert an edge
*/
void insert (const db::Edge &e, property_type p = 0);
/**
* @brief Insert an polygon
*/
void insert (const db::Polygon &q, property_type p = 0);
/**
* @brief Insert a sequence of edges
*
* This method does not reserve for the number of elements required. This must
* be done explicitly for performance benefits.
*/
template <class Iter>
void insert_sequence (Iter from, Iter to, property_type p = 0)
{
for (Iter i = from; i != to; ++i) {
insert (*i, p);
}
}
/**
* @brief Insert a sequence of edges (iterator with at_end semantics)
*
* This method does not reserve for the number of elements required. This must
* be done explicitly for performance benefits.
*/
template <class Iter>
void insert_sequence (Iter i, property_type p = 0)
{
for ( ; !i.at_end (); ++i) {
insert (*i, p);
}
}
/**
* @brief Clear all edges stored currently in this processor
*/
void clear ();
/**
* @brief Process the edges stored currently
*/
void process (db::EdgeSink &es, EdgeEvaluatorBase &op);
/**
* @brief Merge the given polygons in a simple "non-zero wrapcount" fashion
*
* The wrapcount is computed over all polygons, i.e. overlapping polygons may "cancel" if they
* have different orientation (since a polygon is oriented by construction that is not easy to achieve).
* The other merge operation provided for this purpose is "merge" which normalizes each polygon individually before
* merging them. "simple_merge" is somewhat faster and consumes less memory.
*
* The result is presented as a set of edges forming closed contours. Hulls are oriented clockwise while
* holes are oriented counter-clockwise.
*
* This is a convenience method that bundles filling of the edges, processing with
* a SimpleMerge operator and puts the result into an output vector.
*
* @param in The input polygons
* @param out The output edges
* @param mode The merge mode (see SimpleMerge constructor)
*/
void simple_merge (const std::vector<db::Polygon> &in, std::vector <db::Edge> &out, int mode = -1);
/**
* @brief Merge the given polygons in a simple "non-zero wrapcount" fashion into polygons
*
* The wrapcount is computed over all polygons, i.e. overlapping polygons may "cancel" if they
* have different orientation (since a polygon is oriented by construction that is not easy to achieve).
* The other merge operation provided for this purpose is "merge" which normalizes each polygon individually before
* merging them. "simple_merge" is somewhat faster and consumes less memory.
*
* This method produces polygons and allows to fine-tune the parameters for that purpose.
*
* This is a convenience method that bundles filling of the edges, processing with
* a SimpleMerge operator and puts the result into an output vector.
*
* @param in The input polygons
* @param out The output polygons
* @param resolve_holes true, if holes should be resolved into the hull
* @param min_coherence true, if touching corners should be resolved into less connected contours
* @param mode The merge mode (see SimpleMerge constructor)
*/
void simple_merge (const std::vector<db::Polygon> &in, std::vector <db::Polygon> &out, bool resolve_holes = true, bool min_coherence = true, int mode = -1);
/**
* @brief Merge the given edges in a simple "non-zero wrapcount" fashion
*
* The egdes provided must form valid closed contours. Contours oriented differently "cancel" each other.
* Overlapping contours are merged when the orientation is the same.
*
* The result is presented as a set of edges forming closed contours. Hulls are oriented clockwise while
* holes are oriented counter-clockwise.
*
* This is a convenience method that bundles filling of the edges, processing with
* a SimpleMerge operator and puts the result into an output vector.
*
* @param in The input edges
* @param out The output edges
* @param mode The merge mode (see SimpleMerge constructor)
*/
void simple_merge (const std::vector<db::Edge> &in, std::vector <db::Edge> &out, int mode = -1);
/**
* @brief Merge the given edges in a simple "non-zero wrapcount" fashion into polygons
*
* The egdes provided must form valid closed contours. Contours oriented differently "cancel" each other.
* Overlapping contours are merged when the orientation is the same.
*
* This method produces polygons and allows to fine-tune the parameters for that purpose.
*
* This is a convenience method that bundles filling of the edges, processing with
* a SimpleMerge operator and puts the result into an output vector.
*
* @param in The input edges
* @param out The output polygons
* @param resolve_holes true, if holes should be resolved into the hull
* @param min_coherence true, if touching corners should be resolved into less connected contours
* @param mode The merge mode (see SimpleMerge constructor)
*/
void simple_merge (const std::vector<db::Edge> &in, std::vector <db::Polygon> &out, bool resolve_holes = true, bool min_coherence = true, int mode = -1);
/**
* @brief Merge the given polygons
*
* In contrast to "simple_merge", this merge implementation considers each polygon individually before merging them.
* Thus self-overlaps are effectively removed before the output is computed and holes are correctly merged with the
* hull. In addition, this method allows to select areas with a higher wrap count which allows to compute overlaps
* of polygons on the same layer. Because this method merges the polygons before the overlap is computed, self-overlapping
* polygons do not contribute to higher wrap count areas.
*
* The result is presented as a set of edges forming closed contours. Hulls are oriented clockwise while
* holes are oriented counter-clockwise.
*
* This is a convenience method that bundles filling of the edges, processing with
* a Merge operator and puts the result into an output vector.
*
* @param in The input polygons
* @param out The output edges
* @param min_wc The minimum wrap count for output (0: all polygons, 1: at least two overlapping)
*/
void merge (const std::vector<db::Polygon> &in, std::vector <db::Edge> &out, unsigned int min_wc = 0);
/**
* @brief Merge the given polygons
*
* In contrast to "simple_merge", this merge implementation considers each polygon individually before merging them.
* Thus self-overlaps are effectively removed before the output is computed and holes are correctly merged with the
* hull. In addition, this method allows to select areas with a higher wrap count which allows to compute overlaps
* of polygons on the same layer. Because this method merges the polygons before the overlap is computed, self-overlapping
* polygons do not contribute to higher wrap count areas.
*
* This method produces polygons and allows to fine-tune the parameters for that purpose.
*
* This is a convenience method that bundles filling of the edges, processing with
* a Merge operator and puts the result into an output vector.
*
* @param in The input polygons
* @param out The output polygons
* @param min_wc The minimum wrap count for output (0: all polygons, 1: at least two overlapping)
* @param resolve_holes true, if holes should be resolved into the hull
* @param min_coherence true, if touching corners should be resolved into less connected contours
*/
void merge (const std::vector<db::Polygon> &in, std::vector <db::Polygon> &out, unsigned int min_wc = 0, bool resolve_holes = true, bool min_coherence = true);
/**
* @brief Size the given polygons
*
* This method sizes a set of polygons. Before the sizing is applied, the polygons are merged. After that, sizing is applied
* on the individual result polygons of the merge step. The result may contain overlapping contours, but no self-overlaps.
*
* dx and dy describe the sizing. A positive value indicates oversize (outwards) while a negative one describes undersize (inwards).
* The sizing applied can be choosen differently in x and y direction. In this case, the sign must be identical for both
* dx and dy.
*
* The result is presented as a set of edges forming closed contours. Hulls are oriented clockwise while
* holes are oriented counter-clockwise.
*
* This is a convenience method that bundles filling of the edges and processing them
* and which puts the result into an output vector.
*
* @param in The input polygons
* @param dx The sizing value in x direction
* @param dy The sizing value in y direction
* @param out The output edges
* @param mode The sizing mode (see db::Polygon for a description)
*/
void size (const std::vector<db::Polygon> &in, db::Coord dx, db::Coord dy, std::vector <db::Edge> &out, unsigned int mode = 2);
/**
* @brief Size the given polygons into polygons
*
* This method sizes a set of polygons. Before the sizing is applied, the polygons are merged. After that, sizing is applied
* on the individual result polygons of the merge step. The result may contain overlapping polygons, but no self-overlapping ones.
* Polygon overlap occures if the polygons are close enough, so a positive sizing makes polygons overlap.
*
* dx and dy describe the sizing. A positive value indicates oversize (outwards) while a negative one describes undersize (inwards).
* The sizing applied can be choosen differently in x and y direction. In this case, the sign must be identical for both
* dx and dy.
*
* This method produces polygons and allows to fine-tune the parameters for that purpose.
*
* This is a convenience method that bundles filling of the edges, processing with
* a SimpleMerge operator and puts the result into an output vector.
*
* @param in The input polygons
* @param dx The sizing value in x direction
* @param dy The sizing value in y direction
* @param out The output polygons
* @param mode The sizing mode (see db::Polygon for a description)
* @param resolve_holes true, if holes should be resolved into the hull
* @param min_coherence true, if touching corners should be resolved into less connected contours
*/
void size (const std::vector<db::Polygon> &in, db::Coord dx, db::Coord dy, std::vector <db::Polygon> &out, unsigned int mode = 2, bool resolve_holes = true, bool min_coherence = true);
/**
* @brief Size the given polygons (isotropic)
*
* This method is equivalent to calling the anisotropic version with identical dx and dy.
*
* @param in The input polygons
* @param d The sizing value in x direction
* @param out The output edges
* @param mode The sizing mode (see db::Polygon for a description)
*/
void size (const std::vector<db::Polygon> &in, db::Coord d, std::vector <db::Edge> &out, unsigned int mode = 2)
{
size (in, d, d, out, mode);
}
/**
* @brief Size the given polygons into polygons (isotropic)
*
* This method is equivalent to calling the anisotropic version with identical dx and dy.
*
* @param in The input polygons
* @param d The sizing value in x direction
* @param out The output polygons
* @param mode The sizing mode (see db::Polygon for a description)
* @param resolve_holes true, if holes should be resolved into the hull
* @param min_coherence true, if touching corners should be resolved into less connected contours
*/
void size (const std::vector<db::Polygon> &in, db::Coord d, std::vector <db::Polygon> &out, unsigned int mode = 2, bool resolve_holes = true, bool min_coherence = true)
{
size (in, d, d, out, mode, resolve_holes, min_coherence);
}
/**
* @brief Boolean operation for a set of given polygons, creating edges
*
* This method computes the result for the given boolean operation on two sets of polygons.
* The result is presented as a set of edges forming closed contours. Hulls are oriented clockwise while
* holes are oriented counter-clockwise.
*
* This is a convenience method that bundles filling of the edges, processing with
* a Boolean operator and puts the result into an output vector.
*
* @param a The input polygons (first operand)
* @param b The input polygons (second operand)
* @param out The output edges
* @param mode The boolean mode
*/
void boolean (const std::vector<db::Polygon> &a, const std::vector<db::Polygon> &b, std::vector <db::Edge> &out, int mode);
/**
* @brief Boolean operation for a set of given polygons, creating polygons
*
* This method computes the result for the given boolean operation on two sets of polygons.
* This method produces polygons on output and allows to fine-tune the parameters for that purpose.
*
* This is a convenience method that bundles filling of the edges, processing with
* a Boolean operator and puts the result into an output vector.
*
* @param a The input polygons (first operand)
* @param b The input polygons (second operand)
* @param out The output polygons
* @param mode The boolean mode
* @param resolve_holes true, if holes should be resolved into the hull
* @param min_coherence true, if touching corners should be resolved into less connected contours
*/
void boolean (const std::vector<db::Polygon> &a, const std::vector<db::Polygon> &b, std::vector <db::Polygon> &out, int mode, bool resolve_holes = true, bool min_coherence = true);
/**
* @brief Boolean operation for a set of given edges, creating edges
*
* This method computes the result for the given boolean operation on two sets of edges.
* The input edges must form closed contours where holes and hulls must be oriented differently.
* The input edges are processed with a simple non-zero wrap count rule as a whole.
*
* The result is presented as a set of edges forming closed contours. Hulls are oriented clockwise while
* holes are oriented counter-clockwise.
*
* This is a convenience method that bundles filling of the edges, processing with
* a Boolean operator and puts the result into an output vector.
*
* @param a The input edges (first operand)
* @param b The input edges (second operand)
* @param out The output edges
* @param mode The boolean mode
*/
void boolean (const std::vector<db::Edge> &a, const std::vector<db::Edge> &b, std::vector <db::Edge> &out, int mode);
/**
* @brief Boolean operation for a set of given edges, creating polygons
*
* This method computes the result for the given boolean operation on two sets of edges.
* The input edges must form closed contours where holes and hulls must be oriented differently.
* The input edges are processed with a simple non-zero wrap count rule as a whole.
*
* This method produces polygons on output and allows to fine-tune the parameters for that purpose.
*
* This is a convenience method that bundles filling of the edges, processing with
* a Boolean operator and puts the result into an output vector.
*
* @param a The input polygons (first operand)
* @param b The input polygons (second operand)
* @param out The output polygons
* @param mode The boolean mode
* @param resolve_holes true, if holes should be resolved into the hull
* @param min_coherence true, if touching corners should be resolved into less connected contours
*/
void boolean (const std::vector<db::Edge> &a, const std::vector<db::Edge> &b, std::vector <db::Polygon> &out, int mode, bool resolve_holes = true, bool min_coherence = true);
private:
std::vector <WorkEdge> *mp_work_edges;
std::vector <CutPoints> *mp_cpvector;
bool m_report_progress;
std::string m_progress_desc;
static size_t count_edges (const db::Polygon &q)
{
size_t n = q.hull ().size ();
for (unsigned int h = 0; h < q.holes (); ++h) {
n += q.hole (h).size ();
}
return n;
}
static size_t count_edges (const std::vector<db::Polygon> &v)
{
size_t n = 0;
for (std::vector<db::Polygon>::const_iterator p = v.begin (); p != v.end (); ++p) {
n += count_edges (*p);
}
return n;
}
};
}
#endif