mirror of https://github.com/KLayout/klayout.git
680 lines
21 KiB
C++
680 lines
21 KiB
C++
|
|
/*
|
|
|
|
KLayout Layout Viewer
|
|
Copyright (C) 2006-2017 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_dbPolygonTools
|
|
#define HDR_dbPolygonTools
|
|
|
|
#include "dbCommon.h"
|
|
|
|
#include "dbPolygon.h"
|
|
|
|
#include <vector>
|
|
#include <limits>
|
|
#include <algorithm>
|
|
|
|
namespace db {
|
|
|
|
class SimplePolygonSink;
|
|
|
|
/**
|
|
* @brief An inside test operator
|
|
*
|
|
* This class allows to efficiently test whether multiple points are inside a given polygon.
|
|
* Since the test is efficiently implemented when the polygon edges are sorted, the sorting
|
|
* and memory allocation step is performed once in the test operator's constructor while
|
|
* each individual test is performed efficiently.
|
|
*/
|
|
|
|
template <class P>
|
|
class inside_poly_test
|
|
{
|
|
public:
|
|
typedef typename P::point_type point_type;
|
|
typedef typename P::coord_type coord_type;
|
|
typedef typename db::edge<coord_type> edge_type;
|
|
|
|
/**
|
|
* @brief Constructor
|
|
*/
|
|
inside_poly_test (const P &polygon);
|
|
|
|
/**
|
|
* @brief Actual test
|
|
*
|
|
* This function returns 1, if the point is inside (not on)
|
|
* the polygon. It returns 0, if the point is on the polygon and -1
|
|
* if outside.
|
|
*/
|
|
int operator() (const point_type &pt) const;
|
|
|
|
private:
|
|
std::vector<edge_type> m_edges;
|
|
};
|
|
|
|
// Some helper classes and functions for implementing cut_polygon
|
|
|
|
class DB_PUBLIC CutPolygonReceiverBase
|
|
{
|
|
public:
|
|
virtual ~CutPolygonReceiverBase () { }
|
|
virtual void put (const void *) = 0;
|
|
};
|
|
|
|
template <class OutputIter, class Polygon>
|
|
class cut_polygon_receiver
|
|
: public CutPolygonReceiverBase
|
|
{
|
|
public:
|
|
cut_polygon_receiver (const OutputIter &iter)
|
|
: m_iter (iter)
|
|
{ }
|
|
|
|
virtual void put (const void *polygon)
|
|
{
|
|
*m_iter++ = *((const Polygon *) polygon);
|
|
}
|
|
|
|
private:
|
|
OutputIter m_iter;
|
|
};
|
|
|
|
template <class PolygonType, class Edge>
|
|
void DB_PUBLIC cut_polygon_internal (const PolygonType &input, const Edge &line, CutPolygonReceiverBase *right_of_line);
|
|
|
|
/**
|
|
* @brief Polygon cut function
|
|
*
|
|
* This functions cuts a polygon at the given line (given by an edge)
|
|
* and produces all parts of the polygon that are "right" of the line given by "line".
|
|
*/
|
|
template <class PolygonType, class OutputIter>
|
|
void cut_polygon (const PolygonType &input, const typename PolygonType::edge_type &line, OutputIter right_of_line)
|
|
{
|
|
cut_polygon_receiver<OutputIter, PolygonType> output (right_of_line);
|
|
cut_polygon_internal (input, line, &output);
|
|
}
|
|
|
|
/**
|
|
* @brief Split a polygon into two or more parts
|
|
*
|
|
* This function splits a polygon into parts using some heuristics to determine a "suitable" cut line.
|
|
* The cut line is choosen through a vertex close to a center (either horizontal or vertical). The splitting
|
|
* is supposed to create smaller parts with less vertices or a better area ratio of polygon to bounding box area.
|
|
*
|
|
* @param polygon The input polygon
|
|
* @param output The parts
|
|
*/
|
|
template <class PolygonType>
|
|
void DB_PUBLIC split_polygon (const PolygonType &polygon, std::vector<PolygonType> &output);
|
|
|
|
/**
|
|
* @brief Determines wheter a polygon and a box interact
|
|
*
|
|
* This function determines wheter the polygon and the box share at least on common point
|
|
* and returns true in this case.
|
|
*/
|
|
template<class Polygon, class Box>
|
|
bool interact_pb (const Polygon &poly, const Box &box)
|
|
{
|
|
if (! poly.box ().touches (box)) {
|
|
return false;
|
|
}
|
|
|
|
if (poly.begin_hull () == poly.end_hull ()) {
|
|
return false;
|
|
}
|
|
|
|
// if the box center is inside or at the rim of the polygon, return true
|
|
if (db::inside_poly (poly.begin_edge (), box.center ()) >= 0 ||
|
|
box.contains (*poly.begin_hull ())) {
|
|
return true;
|
|
}
|
|
|
|
for (typename Polygon::polygon_edge_iterator e = poly.begin_edge (); ! e.at_end (); ++e) {
|
|
if ((*e).clipped (box).first) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @brief Determines whether two polygons share at least one common point.
|
|
*/
|
|
template <class Polygon1, class Polygon2>
|
|
bool interact_pp (const Polygon1 &poly1, const Polygon2 &poly2)
|
|
{
|
|
typedef typename Polygon1::coord_type coord_type;
|
|
typedef typename Polygon1::polygon_edge_iterator edge_iterator1;
|
|
typedef typename Polygon2::polygon_edge_iterator edge_iterator2;
|
|
typedef db::edge<coord_type> edge_type;
|
|
|
|
if (! poly1.box ().touches (poly2.box ())) {
|
|
return false;
|
|
}
|
|
|
|
if (poly1.begin_hull () == poly1.end_hull () ||
|
|
poly2.begin_hull () == poly2.end_hull ()) {
|
|
return false;
|
|
}
|
|
|
|
// if at least one point of poly2 is inside or at the rim of poly1, return true
|
|
if (db::inside_poly (poly1.begin_edge (), *poly2.begin_hull ()) >= 0 ||
|
|
db::inside_poly (poly2.begin_edge (), *poly1.begin_hull ()) >= 0) {
|
|
return true;
|
|
}
|
|
|
|
// in all other cases, in intersection happens if at least one of the edges of poly1 or
|
|
// poly2 intersect. This is checked with a simple scanline algorithm ...
|
|
|
|
std::vector <edge_type> edges1;
|
|
edges1.reserve (poly1.vertices ());
|
|
for (edge_iterator1 e = poly1.begin_edge (); ! e.at_end (); ++e) {
|
|
edges1.push_back (*e);
|
|
}
|
|
|
|
std::sort (edges1.begin (), edges1.end (), edge_ymin_compare<coord_type> ());
|
|
|
|
std::vector <edge_type> edges2;
|
|
edges2.reserve (poly2.vertices ());
|
|
for (edge_iterator2 e = poly2.begin_edge (); ! e.at_end (); ++e) {
|
|
edges2.push_back (*e);
|
|
}
|
|
|
|
std::sort (edges2.begin (), edges2.end (), edge_ymin_compare<coord_type> ());
|
|
|
|
coord_type y = std::min (std::min (edges1.front ().y1 (), edges1.front ().y2 ()),
|
|
std::min (edges2.front ().y1 (), edges2.front ().y2 ()));
|
|
|
|
typename std::vector <edge_type>::iterator ec1 = edges1.begin ();
|
|
typename std::vector <edge_type>::iterator ef1 = edges1.begin ();
|
|
typename std::vector <edge_type>::iterator ec2 = edges2.begin ();
|
|
typename std::vector <edge_type>::iterator ef2 = edges2.begin ();
|
|
|
|
while (ec1 != edges1.end () && ec2 != edges2.end ()) {
|
|
|
|
while (ef1 != edges1.end () && edge_ymin (*ef1) <= y) {
|
|
++ef1;
|
|
}
|
|
|
|
while (ef2 != edges2.end () && edge_ymin (*ef2) <= y) {
|
|
++ef2;
|
|
}
|
|
|
|
coord_type yy = std::numeric_limits <coord_type>::max ();
|
|
|
|
if (ef1 != edges1.end ()) {
|
|
yy = edge_ymin (*ef1);
|
|
}
|
|
|
|
if (ef2 != edges2.end ()) {
|
|
coord_type ynext = edge_ymin (*ef2);
|
|
if (ynext < yy) {
|
|
yy = ynext;
|
|
}
|
|
}
|
|
|
|
std::sort (ec1, ef1, edge_xmin_at_yinterval_compare<coord_type> (y, yy));
|
|
std::sort (ec2, ef2, edge_xmin_at_yinterval_compare<coord_type> (y, yy));
|
|
|
|
typename std::vector <edge_type>::iterator c1 = ec1;
|
|
typename std::vector <edge_type>::iterator f1 = ec1;
|
|
typename std::vector <edge_type>::iterator c2 = ec2;
|
|
typename std::vector <edge_type>::iterator f2 = ec2;
|
|
|
|
coord_type x1 = edge_xmin_at_yinterval (*ec1, y, yy);
|
|
coord_type x2 = edge_xmin_at_yinterval (*ec2, y, yy);
|
|
coord_type x = std::min (x1, x2);
|
|
|
|
while (c1 != ef1 && c2 != ef2) {
|
|
|
|
while (f1 != ef1 && edge_xmin_at_yinterval (*f1, y, yy) <= x) {
|
|
++f1;
|
|
}
|
|
|
|
while (f2 != ef2 && edge_xmin_at_yinterval (*f2, y, yy) <= x) {
|
|
++f2;
|
|
}
|
|
|
|
coord_type xx = std::numeric_limits <coord_type>::max ();
|
|
|
|
if (f1 != ef1) {
|
|
xx = edge_xmin_at_yinterval (*f1, y, yy);
|
|
}
|
|
|
|
if (f2 != ef2) {
|
|
coord_type xnext = edge_xmin_at_yinterval (*f2, y, yy);
|
|
if (xnext < xx) {
|
|
xx = xnext;
|
|
}
|
|
}
|
|
|
|
for (typename std::vector <edge_type>::iterator a = c1; a != f1; ++a) {
|
|
for (typename std::vector <edge_type>::iterator b = c2; b != f2; ++b) {
|
|
if (a->intersect (*b)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
x = xx;
|
|
|
|
for (typename std::vector <edge_type>::iterator cc = c1; cc != f1; ++cc) {
|
|
if (edge_xmax (*cc) < x || edge_xmax_at_yinterval (*cc, y, yy) < x) {
|
|
if (c1 != cc) {
|
|
std::swap (*cc, *c1);
|
|
}
|
|
++c1;
|
|
}
|
|
}
|
|
|
|
for (typename std::vector <edge_type>::iterator cc = c2; cc != f2; ++cc) {
|
|
if (edge_xmax (*cc) < x || edge_xmax_at_yinterval (*cc, y, yy) < x) {
|
|
if (c2 != cc) {
|
|
std::swap (*cc, *c2);
|
|
}
|
|
++c2;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
y = yy;
|
|
|
|
for (typename std::vector <edge_type>::iterator cc = ec1; cc != ef1; ++cc) {
|
|
if (edge_ymax (*cc) < y) {
|
|
if (ec1 != cc) {
|
|
std::swap (*cc, *ec1);
|
|
}
|
|
++ec1;
|
|
}
|
|
}
|
|
|
|
for (typename std::vector <edge_type>::iterator cc = ec2; cc != ef2; ++cc) {
|
|
if (edge_ymax (*cc) < y) {
|
|
if (ec2 != cc) {
|
|
std::swap (*cc, *ec2);
|
|
}
|
|
++ec2;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Some specializations that map all combinations to template versions
|
|
inline bool interact (const db::Box &box1, const db::Box &box2) { return box1.touches (box2); }
|
|
inline bool interact (const db::DBox &box1, const db::DBox &box2) { return box1.touches (box2); }
|
|
inline bool interact (const db::Polygon &poly, const db::Box &box) { return interact_pb (poly, box); }
|
|
inline bool interact (const db::SimplePolygon &poly, const db::Box &box) { return interact_pb (poly, box); }
|
|
inline bool interact (const db::DPolygon &poly, const db::DBox &box) { return interact_pb (poly, box); }
|
|
inline bool interact (const db::DSimplePolygon &poly, const db::DBox &box) { return interact_pb (poly, box); }
|
|
inline bool interact (const db::Polygon &poly1, const db::Polygon &poly2) { return interact_pp (poly1, poly2); }
|
|
inline bool interact (const db::SimplePolygon &poly1, const db::Polygon &poly2) { return interact_pp (poly1, poly2); }
|
|
inline bool interact (const db::Polygon &poly1, const db::SimplePolygon &poly2) { return interact_pp (poly1, poly2); }
|
|
inline bool interact (const db::SimplePolygon &poly1, const db::SimplePolygon &poly2) { return interact_pp (poly1, poly2); }
|
|
inline bool interact (const db::DPolygon &poly1, const db::DPolygon &poly2) { return interact_pp (poly1, poly2); }
|
|
inline bool interact (const db::DSimplePolygon &poly1, const db::DPolygon &poly2) { return interact_pp (poly1, poly2); }
|
|
inline bool interact (const db::DPolygon &poly1, const db::DSimplePolygon &poly2) { return interact_pp (poly1, poly2); }
|
|
inline bool interact (const db::DSimplePolygon &poly1, const db::DSimplePolygon &poly2) { return interact_pp (poly1, poly2); }
|
|
|
|
/**
|
|
* @brief Extract a corner radius from a contour
|
|
*
|
|
* This method will determine the radius of a contour if the contour was formed by rounding another contour.
|
|
* The corners must be formed by soft bending edges.
|
|
* It is possible to retrieve the original contour (or an approximation of the latter) by passing a vector
|
|
* in "new_pts" which will receive the original contour.
|
|
*
|
|
* @param from, to The iterators describing the contour
|
|
* @param rinner The inner corner radius (in dbu units) extracted (if return value is true)
|
|
* @param router The outer corner radius (in dbu units) extracted (if return value is true)
|
|
* @param n Receives the number of points per full circle (if return value is true)
|
|
* @param new_pts If != 0, this vector will receive the contour without the rounded corners (if return value is true)
|
|
* @param fallback Fallback algorithm (less strict) if true
|
|
* @return True, if the extraction was successful
|
|
*/
|
|
bool DB_PUBLIC extract_rad_from_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon_contour_iterator to, double &rinner, double &router, unsigned int &n, std::vector <db::Point> *new_pts = 0, bool fallback = false);
|
|
|
|
/**
|
|
* @brief Extract a corner radius from a contour (version for double coordinates)
|
|
*/
|
|
bool DB_PUBLIC extract_rad_from_contour (db::DPolygon::polygon_contour_iterator from, db::DPolygon::polygon_contour_iterator to, double &rinner, double &router, unsigned int &n, std::vector <db::DPoint> *new_pts = 0, bool fallback = false);
|
|
|
|
/**
|
|
* @brief Extract the radius (better: radii) from a polygon and if requested, compute the new polygon without the rounding
|
|
*
|
|
* See extract_rad_from_contour for details.
|
|
*/
|
|
bool DB_PUBLIC extract_rad (const db::Polygon &polygon, double &rinner, double &router, unsigned int &n, db::Polygon *new_polygon = 0);
|
|
|
|
/**
|
|
* @brief Extract a corner radius from a polygon (version for double coordinates)
|
|
*/
|
|
bool DB_PUBLIC extract_rad (const db::DPolygon &polygon, double &rinner, double &router, unsigned int &n, db::DPolygon *new_polygon = 0);
|
|
|
|
/**
|
|
* @brief Compute the rounded version of a polygon contour
|
|
*
|
|
* Computes the version of a contour with the corners rounded (inner corners with rinner, outer corners with router, n points per full circle=.
|
|
*
|
|
* @param from, to The iterators describing the contour
|
|
* @param new_pts Receives the new points
|
|
* @param rinner The inner corner radius (in dbu units)
|
|
* @param router The outer corner radius (in dbu units)
|
|
* @param n The number of points per full circle
|
|
*/
|
|
void DB_PUBLIC compute_rounded_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon_contour_iterator to, std::vector <db::Point> &new_pts, double rinner, double router, unsigned int n);
|
|
|
|
/**
|
|
* @brief Compute the rounded version of a polygon contour (double coordinate version)
|
|
*/
|
|
void DB_PUBLIC compute_rounded_contour (db::DPolygon::polygon_contour_iterator from, db::DPolygon::polygon_contour_iterator to, std::vector <db::DPoint> &new_pts, double rinner, double router, unsigned int n);
|
|
|
|
/**
|
|
* @brief Compute the rounded version of the polygon
|
|
*
|
|
* See compute_rounded_contour for details.
|
|
*/
|
|
db::Polygon DB_PUBLIC compute_rounded (const db::Polygon &poly, double rinner, double router, unsigned int n);
|
|
|
|
/**
|
|
* @brief Compute the rounded version of the polygon (double coordinate version)
|
|
*/
|
|
db::DPolygon DB_PUBLIC compute_rounded (const db::DPolygon &poly, double rinner, double router, unsigned int n);
|
|
|
|
/**
|
|
* @brief Smooth a contour
|
|
*
|
|
* Removes vertexes from a contour which deviate from the "average" line by more than "d".
|
|
*
|
|
* @param from The start of the contour
|
|
* @param to The end of the contour
|
|
* @param new_pts The points that make up the new contour
|
|
* @param d The distance that determines the smoothing "roughness"
|
|
*/
|
|
void DB_PUBLIC smooth_contour (db::Polygon::polygon_contour_iterator from, db::Polygon::polygon_contour_iterator to, std::vector <db::Point> &new_pts, db::Coord d);
|
|
|
|
/**
|
|
* @brief Smooth a polygon (apply smoothing to the whole polygon)
|
|
*/
|
|
db::Polygon DB_PUBLIC smooth (const db::Polygon &poly, db::Coord d);
|
|
|
|
/**
|
|
* @brief A area collector
|
|
*
|
|
* This class provides a generic 2d map of area values.
|
|
* It is used for example by the rasterize function to collect area values
|
|
* on a per-pixel basis.
|
|
*/
|
|
class DB_PUBLIC AreaMap
|
|
{
|
|
public:
|
|
typedef db::coord_traits<db::Coord>::area_type area_type;
|
|
|
|
/**
|
|
* @brief Constructor
|
|
*/
|
|
AreaMap ();
|
|
|
|
/**
|
|
* @brief Constructor
|
|
*/
|
|
AreaMap (const db::Point &p0, const db::Vector &d, size_t nx, size_t ny);
|
|
|
|
/**
|
|
* @brief Destructor
|
|
*/
|
|
~AreaMap ();
|
|
|
|
/**
|
|
* @brief Reinitialize
|
|
*/
|
|
void reinitialize (const db::Point &p0, const db::Vector &d, size_t nx, size_t ny);
|
|
|
|
/**
|
|
* @brief Swap of two maps
|
|
*/
|
|
void swap (AreaMap &other);
|
|
|
|
/**
|
|
* @brief Get the area of one pixel
|
|
*/
|
|
area_type &get (size_t x, size_t y)
|
|
{
|
|
return mp_av [y * m_nx + x];
|
|
}
|
|
|
|
/**
|
|
* @brief Get the area of one pixel (const version)
|
|
*/
|
|
const area_type &get (size_t x, size_t y) const
|
|
{
|
|
return mp_av [y * m_nx + x];
|
|
}
|
|
|
|
/**
|
|
* @brief The number of pixels in x-dimension
|
|
*/
|
|
size_t nx () const
|
|
{
|
|
return m_nx;
|
|
}
|
|
|
|
/**
|
|
* @brief The number of pixels in y-dimension
|
|
*/
|
|
size_t ny () const
|
|
{
|
|
return m_ny;
|
|
}
|
|
|
|
/**
|
|
* @brief The origin
|
|
*/
|
|
const db::Point &p0 () const
|
|
{
|
|
return m_p0;
|
|
}
|
|
|
|
/**
|
|
* @brief Move the origin
|
|
*/
|
|
void move (const db::Vector &d)
|
|
{
|
|
m_p0 += d;
|
|
}
|
|
|
|
/**
|
|
* @brief The per-pixel displacement vector (pixel size)
|
|
*/
|
|
const db::Vector &d () const
|
|
{
|
|
return m_d;
|
|
}
|
|
|
|
/**
|
|
* @brief Compute the bounding box of the area map
|
|
*/
|
|
db::Box bbox () const
|
|
{
|
|
return db::Box (m_p0, m_p0 + db::Vector (db::Coord (m_nx) * m_d.x (), db::Coord (m_ny) * m_d.y ()));
|
|
}
|
|
|
|
/**
|
|
* @brief Compute the total area
|
|
*/
|
|
area_type total_area () const;
|
|
|
|
/**
|
|
* @brief Compute the maximum (single-covered) area per pixel
|
|
*/
|
|
area_type pixel_area () const
|
|
{
|
|
return area_type (m_d.x ()) * area_type (m_d.y ());
|
|
}
|
|
|
|
/**
|
|
* @brief Clear the values
|
|
*/
|
|
void clear ();
|
|
|
|
private:
|
|
area_type *mp_av;
|
|
db::Point m_p0;
|
|
db::Vector m_d;
|
|
size_t m_nx, m_ny;
|
|
|
|
// no copying
|
|
AreaMap (const AreaMap &);
|
|
AreaMap &operator= (const AreaMap &);
|
|
};
|
|
|
|
/**
|
|
* @brief Rasterize the polygon into the given area map
|
|
*
|
|
* This will decompose the polygon and produce per-pixel area values for the given
|
|
* polygon. The area contributions will be added to the given area map.
|
|
*/
|
|
void DB_PUBLIC rasterize (const db::Polygon &polygon, db::AreaMap &am);
|
|
|
|
/**
|
|
* @brief Minkowsky sum of an edge and a polygon
|
|
*/
|
|
db::Polygon DB_PUBLIC minkowsky_sum (const db::Polygon &a, const db::Edge &b, bool resolve_holes = false);
|
|
|
|
/**
|
|
* @brief Minkowsky sum of a polygon and a polygon
|
|
*/
|
|
db::Polygon DB_PUBLIC minkowsky_sum (const db::Polygon &a, const db::Polygon &b, bool resolve_holes = false);
|
|
|
|
/**
|
|
* @brief Minkowsky sum of a polygon and a box
|
|
*/
|
|
db::Polygon DB_PUBLIC minkowsky_sum (const db::Polygon &a, const db::Box &b, bool resolve_holes = false);
|
|
|
|
/**
|
|
* @brief Minkowsky sum of a polygon and a contour
|
|
*/
|
|
db::Polygon DB_PUBLIC minkowsky_sum (const db::Polygon &a, const std::vector<db::Point> &c, bool resolve_holes = false);
|
|
|
|
/**
|
|
* @brief Resolve holes
|
|
*/
|
|
db::Polygon DB_PUBLIC resolve_holes (const db::Polygon &p);
|
|
|
|
/**
|
|
* @brief SimplePolygon to Polygon conversion
|
|
*/
|
|
db::Polygon DB_PUBLIC simple_polygon_to_polygon (const db::SimplePolygon &a);
|
|
|
|
/**
|
|
* @brief Polygon to SimplePolygon conversion (resolves holes)
|
|
*/
|
|
db::SimplePolygon DB_PUBLIC polygon_to_simple_polygon (const db::Polygon &a);
|
|
|
|
/**
|
|
* @brief The decomposition mode for decompose_convex
|
|
* This mode controls how the polygon is being cut to take off parts.
|
|
* "PO_any" will deliver a "best" cut. "PO_horizontal" will only apply
|
|
* horizontal cuts, "PO_vertical" only vertical ones. "PO_htrapezoids" will
|
|
* apply horizontal cuts to favor horizontal trapzoids. "PO_vtrapezoids"
|
|
* will favor vertical trapezoids.
|
|
*/
|
|
enum PreferredOrientation
|
|
{
|
|
PO_any = 0,
|
|
PO_horizontal = 1,
|
|
PO_vertical = 2,
|
|
PO_htrapezoids = 3,
|
|
PO_vtrapezoids = 4
|
|
};
|
|
|
|
/**
|
|
* @brief The decomposition mode for decompose_trapezoids
|
|
* This mode controls the trapezoid decomposition.
|
|
* "TD_simple" is a simple and fast mode, "TD_htrapezoids" is a mode favoring
|
|
* horizontal trapezoids. It's slower but will deliver less trapezoids in some
|
|
* cases. "TD_vtrapezoids" is similar for "TD_htrapezoids" and will produce
|
|
* vertical trapezoids where the vertical edges are parallel.
|
|
*/
|
|
enum TrapezoidDecompositionMode
|
|
{
|
|
TD_simple = 0,
|
|
TD_htrapezoids = 1,
|
|
TD_vtrapezoids = 2
|
|
};
|
|
|
|
/**
|
|
* @brief Decompose a polygon into convex (simple) polygons
|
|
*
|
|
* Returns a set of convex polygon whose sum represents the original polygon.
|
|
* If the original polygon was convex already, it will not be modified.
|
|
*
|
|
* The resulting polygons will be sent to the sink. Only "put" events will be generated
|
|
* to facilitate call chaining of multiple "decompose_convex" calls.
|
|
*/
|
|
void DB_PUBLIC decompose_convex (const db::Polygon &p, PreferredOrientation po, SimplePolygonSink &sink);
|
|
|
|
/**
|
|
* @brief Decompose a simple polygon into convex (simple) polygons
|
|
*
|
|
* See the "Polygon" version of this function for details.
|
|
*/
|
|
void DB_PUBLIC decompose_convex (const db::SimplePolygon &p, PreferredOrientation po, SimplePolygonSink &sink);
|
|
|
|
/**
|
|
* @brief Returns true, if the given polygon is a convex one
|
|
*/
|
|
bool DB_PUBLIC is_convex (const db::Polygon &poly);
|
|
|
|
/**
|
|
* @brief Returns true, if the given simple polygon is a convex one
|
|
*/
|
|
bool DB_PUBLIC is_convex (const db::SimplePolygon &poly);
|
|
|
|
/**
|
|
* @brief Decomposes the given polygon into trapezoids
|
|
*
|
|
* @param horizontal If true, delivers htrapzeoid objects, otherwise vtrapezoids
|
|
*
|
|
* The resulting single polygons will be sent to the sink. Only "put" events will be
|
|
* generated on the sink.
|
|
*/
|
|
void DB_PUBLIC decompose_trapezoids (const db::Polygon &p, TrapezoidDecompositionMode mode, SimplePolygonSink &sink);
|
|
|
|
/**
|
|
* @brief Decomposes the given simple polygon into trapezoids
|
|
*
|
|
* See the "Polygon" version of this function for details.
|
|
*/
|
|
void DB_PUBLIC decompose_trapezoids (const db::SimplePolygon &p, TrapezoidDecompositionMode mode, SimplePolygonSink &sink);
|
|
|
|
}
|
|
|
|
#endif
|
|
|