mirror of https://github.com/KLayout/klayout.git
443 lines
13 KiB
C++
443 lines
13 KiB
C++
|
|
/*
|
|
|
|
KLayout Layout Viewer
|
|
Copyright (C) 2006-2021 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_dbRegionProcessors
|
|
#define HDR_dbRegionProcessors
|
|
|
|
#include "dbCommon.h"
|
|
#include "dbRegionDelegate.h"
|
|
#include "dbPolygonTools.h"
|
|
#include "dbEdgesUtils.h"
|
|
|
|
namespace db
|
|
{
|
|
|
|
// -----------------------------------------------------------------------------------
|
|
// Corner detection
|
|
|
|
/**
|
|
* @brief An interface to accept corners
|
|
*/
|
|
class DB_PUBLIC CornerPointDelivery
|
|
{
|
|
public:
|
|
virtual void make_point (const db::Point &pt, const db::Edge &e1, const db::Edge &e2) const = 0;
|
|
};
|
|
|
|
/**
|
|
* @brief An interface to accept corners and turns them into rectangles with 2*dim x 2*dim
|
|
*/
|
|
class DB_PUBLIC CornerRectDelivery
|
|
: public CornerPointDelivery
|
|
{
|
|
public:
|
|
CornerRectDelivery (db::Coord dim, std::vector<db::Polygon> &result)
|
|
: m_d (dim, dim), mp_result (&result)
|
|
{ }
|
|
|
|
virtual void make_point (const db::Point &pt, const db::Edge &, const db::Edge &) const
|
|
{
|
|
mp_result->push_back (db::Polygon (db::Box (pt - m_d, pt + m_d)));
|
|
}
|
|
|
|
private:
|
|
db::Vector m_d;
|
|
std::vector<db::Polygon> *mp_result;
|
|
};
|
|
|
|
/**
|
|
* @brief An interface to accept corners and turns them into degenerated edges (dots)
|
|
*/
|
|
class DB_PUBLIC CornerDotDelivery
|
|
: public CornerPointDelivery
|
|
{
|
|
public:
|
|
CornerDotDelivery (std::vector<db::Edge> &result)
|
|
: mp_result (&result)
|
|
{ }
|
|
|
|
virtual void make_point (const db::Point &pt, const db::Edge &, const db::Edge &) const
|
|
{
|
|
mp_result->push_back (db::Edge (pt, pt));
|
|
}
|
|
|
|
private:
|
|
db::Vector m_d;
|
|
std::vector<db::Edge> *mp_result;
|
|
};
|
|
|
|
/**
|
|
* @brief An interface to accept corners and turns them into edge pairs
|
|
*/
|
|
class DB_PUBLIC CornerEdgePairDelivery
|
|
: public CornerPointDelivery
|
|
{
|
|
public:
|
|
CornerEdgePairDelivery (std::vector<db::EdgePair> &result)
|
|
: mp_result (&result)
|
|
{ }
|
|
|
|
virtual void make_point (const db::Point &, const db::Edge &e1, const db::Edge &e2) const
|
|
{
|
|
mp_result->push_back (db::EdgePair (e1, e2));
|
|
}
|
|
|
|
private:
|
|
std::vector<db::EdgePair> *mp_result;
|
|
};
|
|
|
|
/**
|
|
* @brief A helper class implementing the core corner detection algorithm
|
|
*/
|
|
class DB_PUBLIC CornerDetectorCore
|
|
{
|
|
public:
|
|
CornerDetectorCore (double angle_start, bool include_angle_start, double angle_end, bool include_angle_end);
|
|
virtual ~CornerDetectorCore () { }
|
|
|
|
void detect_corners (const db::Polygon &poly, const CornerPointDelivery &delivery) const;
|
|
|
|
private:
|
|
db::EdgeAngleChecker m_checker;
|
|
};
|
|
|
|
/**
|
|
* @brief A corner detector delivering small retangles (2*dim x 2*dim) per detected corner
|
|
*/
|
|
class DB_PUBLIC CornersAsRectangles
|
|
: public db::PolygonProcessorBase, private CornerDetectorCore
|
|
{
|
|
public:
|
|
CornersAsRectangles (double angle_start, bool include_angle_start, double angle_end, bool include_angle_end, db::Coord dim = 1)
|
|
: CornerDetectorCore (angle_start, include_angle_start, angle_end, include_angle_end), m_dim (dim)
|
|
{
|
|
// .. nothing yet ..
|
|
}
|
|
|
|
void process (const db::Polygon &poly, std::vector<db::Polygon> &result) const
|
|
{
|
|
detect_corners (poly, CornerRectDelivery (m_dim, result));
|
|
}
|
|
|
|
virtual const TransformationReducer *vars () const { return &m_vars; }
|
|
virtual bool result_is_merged () const { return false; } // overlaps may happen
|
|
virtual bool result_must_not_be_merged () const { return false; }
|
|
virtual bool requires_raw_input () const { return false; }
|
|
virtual bool wants_variants () const { return false; }
|
|
|
|
private:
|
|
db::Coord m_dim;
|
|
db::MagnificationReducer m_vars;
|
|
};
|
|
|
|
/**
|
|
* @brief A corner detector delivering degenerated edges (dots) for the corners
|
|
*/
|
|
class DB_PUBLIC CornersAsDots
|
|
: public db::PolygonToEdgeProcessorBase, private CornerDetectorCore
|
|
{
|
|
public:
|
|
CornersAsDots (double angle_start, bool include_angle_start, double angle_end, bool include_angle_end)
|
|
: CornerDetectorCore (angle_start, include_angle_start, angle_end, include_angle_end)
|
|
{
|
|
// .. nothing yet ..
|
|
}
|
|
|
|
void process (const db::Polygon &poly, std::vector<db::Edge> &result) const
|
|
{
|
|
detect_corners (poly, CornerDotDelivery (result));
|
|
}
|
|
|
|
virtual const TransformationReducer *vars () const { return 0; }
|
|
virtual bool result_is_merged () const { return false; }
|
|
virtual bool result_must_not_be_merged () const { return true; } // to preserve dots
|
|
virtual bool requires_raw_input () const { return false; }
|
|
virtual bool wants_variants () const { return false; }
|
|
};
|
|
|
|
/**
|
|
* @brief A corner detector delivering edge pairs for the corners
|
|
*/
|
|
class DB_PUBLIC CornersAsEdgePairs
|
|
: public db::PolygonToEdgePairProcessorBase, private CornerDetectorCore
|
|
{
|
|
public:
|
|
CornersAsEdgePairs (double angle_start, bool include_angle_start, double angle_end, bool include_angle_end)
|
|
: CornerDetectorCore (angle_start, include_angle_start, angle_end, include_angle_end)
|
|
{
|
|
// .. nothing yet ..
|
|
}
|
|
|
|
void process (const db::Polygon &poly, std::vector<db::EdgePair> &result) const
|
|
{
|
|
detect_corners (poly, CornerEdgePairDelivery (result));
|
|
}
|
|
|
|
virtual const TransformationReducer *vars () const { return 0; }
|
|
virtual bool result_is_merged () const { return false; }
|
|
virtual bool result_must_not_be_merged () const { return true; } // to preserve dots
|
|
virtual bool requires_raw_input () const { return false; }
|
|
virtual bool wants_variants () const { return false; }
|
|
};
|
|
|
|
// -----------------------------------------------------------------------------------
|
|
// Extents
|
|
|
|
/**
|
|
* @brief A processor delivering the extents (bounding box) of the merged polygons
|
|
*/
|
|
class DB_PUBLIC Extents
|
|
: public db::PolygonProcessorBase
|
|
{
|
|
public:
|
|
Extents ()
|
|
{
|
|
// .. nothing yet ..
|
|
}
|
|
|
|
void process (const db::Polygon &poly, std::vector<db::Polygon> &result) const;
|
|
|
|
virtual const TransformationReducer *vars () const { return 0; }
|
|
virtual bool result_is_merged () const { return false; }
|
|
virtual bool result_must_not_be_merged () const { return false; }
|
|
virtual bool requires_raw_input () const { return false; }
|
|
virtual bool wants_variants () const { return false; } // variants are too common, so don't do this
|
|
};
|
|
|
|
/**
|
|
* @brief A processor delivering the relative extents (bounding box) of the merged polygons
|
|
* This processor allows over- or undersizing of the resulting box by a given amount and delivery
|
|
* of a box relative to the original box.
|
|
*/
|
|
class DB_PUBLIC RelativeExtents
|
|
: public db::PolygonProcessorBase
|
|
{
|
|
public:
|
|
RelativeExtents (double fx1, double fy1, double fx2, double fy2, db::Coord dx, db::Coord dy)
|
|
: m_fx1 (fx1), m_fy1 (fy1), m_fx2 (fx2), m_fy2 (fy2), m_dx (dx), m_dy (dy)
|
|
{
|
|
// .. nothing yet ..
|
|
}
|
|
|
|
void process (const db::Polygon &poly, std::vector<db::Polygon> &result) const;
|
|
|
|
virtual const TransformationReducer *vars () const;
|
|
virtual bool result_is_merged () const { return false; }
|
|
virtual bool result_must_not_be_merged () const { return false; }
|
|
virtual bool requires_raw_input () const { return false; }
|
|
virtual bool wants_variants () const { return false; } // variants are too common, so don't do this
|
|
|
|
private:
|
|
double m_fx1, m_fy1, m_fx2, m_fy2;
|
|
db::Coord m_dx, m_dy;
|
|
db::MagnificationAndOrientationReducer m_anisotropic_reducer;
|
|
db::MagnificationReducer m_isotropic_reducer;
|
|
};
|
|
|
|
/**
|
|
* @brief A processor delivers one edge per merged polygon
|
|
* The edge runs from the relative coordinate fx1, fy1 (0: left/bottom, 1: right/top) to
|
|
* fx2, fy2.
|
|
* This processor allows over- or undersizing of the resulting box by a given amount and delivery
|
|
* of a box relative to the original box.
|
|
*/
|
|
class DB_PUBLIC RelativeExtentsAsEdges
|
|
: public db::PolygonToEdgeProcessorBase
|
|
{
|
|
public:
|
|
RelativeExtentsAsEdges (double fx1, double fy1, double fx2, double fy2)
|
|
: m_fx1 (fx1), m_fy1 (fy1), m_fx2 (fx2), m_fy2 (fy2)
|
|
{
|
|
// .. nothing yet ..
|
|
}
|
|
|
|
void process (const db::Polygon &poly, std::vector<db::Edge> &result) const;
|
|
|
|
virtual const TransformationReducer *vars () const;
|
|
virtual bool result_is_merged () const { return false; }
|
|
virtual bool result_must_not_be_merged () const;
|
|
virtual bool requires_raw_input () const { return false; }
|
|
virtual bool wants_variants () const { return false; } // variants are too common, so don't do this
|
|
|
|
private:
|
|
double m_fx1, m_fy1, m_fx2, m_fy2;
|
|
db::MagnificationAndOrientationReducer m_anisotropic_reducer;
|
|
};
|
|
|
|
/**
|
|
* @brief A processor that delivers all edges for a polygon
|
|
*/
|
|
class DB_PUBLIC PolygonToEdgeProcessor
|
|
: public db::PolygonToEdgeProcessorBase
|
|
{
|
|
public:
|
|
PolygonToEdgeProcessor ()
|
|
{
|
|
// .. nothing yet ..
|
|
}
|
|
|
|
void process (const db::Polygon &poly, std::vector<db::Edge> &result) const;
|
|
};
|
|
|
|
/**
|
|
* @brief A decomposition processor to deliver convex-only polygons
|
|
*/
|
|
class DB_PUBLIC ConvexDecomposition
|
|
: public db::PolygonProcessorBase
|
|
{
|
|
public:
|
|
ConvexDecomposition (db::PreferredOrientation mode)
|
|
: m_mode (mode)
|
|
{
|
|
// .. nothing yet ..
|
|
}
|
|
|
|
void process (const db::Polygon &poly, std::vector<db::Polygon> &result) const;
|
|
|
|
virtual const TransformationReducer *vars () const { return &m_vars; }
|
|
virtual bool result_is_merged () const { return false; }
|
|
virtual bool result_must_not_be_merged () const { return true; } // would spoil the decomposition otherwise
|
|
virtual bool requires_raw_input () const { return false; }
|
|
virtual bool wants_variants () const { return true; }
|
|
|
|
private:
|
|
db::PreferredOrientation m_mode;
|
|
db::OrientationReducer m_vars;
|
|
};
|
|
|
|
/**
|
|
* @brief A decomposition processor to deliver trapezoids
|
|
*/
|
|
class DB_PUBLIC TrapezoidDecomposition
|
|
: public db::PolygonProcessorBase
|
|
{
|
|
public:
|
|
TrapezoidDecomposition (db::TrapezoidDecompositionMode mode)
|
|
: m_mode (mode)
|
|
{
|
|
// .. nothing yet ..
|
|
}
|
|
|
|
void process (const db::Polygon &poly, std::vector<db::Polygon> &result) const;
|
|
|
|
virtual const TransformationReducer *vars () const { return &m_vars; }
|
|
virtual bool result_is_merged () const { return false; }
|
|
virtual bool result_must_not_be_merged () const { return true; } // would spoil the decomposition otherwise
|
|
virtual bool requires_raw_input () const { return false; }
|
|
virtual bool wants_variants () const { return true; }
|
|
|
|
private:
|
|
db::TrapezoidDecompositionMode m_mode;
|
|
db::OrientationReducer m_vars;
|
|
};
|
|
|
|
/**
|
|
* @brief A polygon breaker processor
|
|
* This processor reduces polygons with more than max_vertex_count vertices and
|
|
* an bbox-to-polygon area ratio bigger than max_area_ratio.
|
|
* A zero value for these parameters means "don't care".
|
|
*/
|
|
class DB_PUBLIC PolygonBreaker
|
|
: public db::PolygonProcessorBase
|
|
{
|
|
public:
|
|
PolygonBreaker (size_t max_vertex_count, double max_area_ratio)
|
|
: m_max_vertex_count (max_vertex_count), m_max_area_ratio (max_area_ratio)
|
|
{
|
|
// .. nothing yet ..
|
|
}
|
|
|
|
void process (const db::Polygon &poly, std::vector<db::Polygon> &result) const;
|
|
|
|
virtual const TransformationReducer *vars () const { return 0; }
|
|
virtual bool result_is_merged () const { return false; }
|
|
virtual bool result_must_not_be_merged () const { return true; } // would spoil the decomposition otherwise
|
|
virtual bool requires_raw_input () const { return true; } // acts on original shapes
|
|
virtual bool wants_variants () const { return false; }
|
|
|
|
private:
|
|
size_t m_max_vertex_count;
|
|
double m_max_area_ratio;
|
|
};
|
|
|
|
/**
|
|
* @brief A sizing processor
|
|
*/
|
|
class DB_PUBLIC PolygonSizer
|
|
: public db::PolygonProcessorBase
|
|
{
|
|
public:
|
|
PolygonSizer (db::Coord dx, db::Coord dy, unsigned int mode);
|
|
~PolygonSizer ();
|
|
|
|
virtual const TransformationReducer *vars () const { return m_vars; }
|
|
|
|
void process (const db::Polygon &poly, std::vector<db::Polygon> &result) const;
|
|
|
|
virtual bool result_is_merged () const;
|
|
virtual bool result_must_not_be_merged () const { return false; }
|
|
virtual bool requires_raw_input () const { return false; }
|
|
virtual bool wants_variants () const { return true; }
|
|
|
|
private:
|
|
TransformationReducer *m_vars;
|
|
db::Coord m_dx, m_dy;
|
|
unsigned int m_mode;
|
|
};
|
|
|
|
/**
|
|
* @brief Computes the Minkowsky sum between the polygons and the given object
|
|
* The object can be Edge, Polygon, Box and std::vector<Point>
|
|
*/
|
|
template <class K>
|
|
class DB_PUBLIC_TEMPLATE minkowsky_sum_computation
|
|
: public db::PolygonProcessorBase
|
|
{
|
|
public:
|
|
minkowsky_sum_computation (const K &q)
|
|
: m_q (q)
|
|
{
|
|
// .. nothing yet ..
|
|
}
|
|
|
|
void process (const db::Polygon &poly, std::vector<db::Polygon> &result) const
|
|
{
|
|
result.push_back (db::minkowsky_sum (poly, m_q, false));
|
|
}
|
|
|
|
// TODO: could be less if the object is symmetric
|
|
virtual const TransformationReducer *vars () const { return &m_vars; }
|
|
virtual bool result_is_merged () const { return false; }
|
|
virtual bool result_must_not_be_merged () const { return false; }
|
|
virtual bool requires_raw_input () const { return false; }
|
|
virtual bool wants_variants () const { return true; }
|
|
|
|
private:
|
|
K m_q;
|
|
db::MagnificationAndOrientationReducer m_vars;
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|