Refactoring: new concept for edge/polygon filters

This commit is contained in:
Matthias Koefferlein 2019-02-19 20:19:10 +01:00
parent 7143e75310
commit 90c1d212a4
17 changed files with 621 additions and 458 deletions

View File

@ -169,7 +169,9 @@ SOURCES = \
dbNetlistWriter.cc \
dbCellVariants.cc \
dbDeepEdges.cc \
dbDeepEdgePairs.cc
dbDeepEdgePairs.cc \
dbRegionUtils.cc \
dbEdgesUtils.cc
HEADERS = \
dbArray.h \
@ -303,7 +305,9 @@ HEADERS = \
dbNetlistWriter.h \
dbCellVariants.h \
dbDeepEdges.h \
dbDeepEdgePairs.h
dbDeepEdgePairs.h \
dbRegionUtils.h \
dbEdgesUtils.h
!equals(HAVE_QT, "0") {

View File

@ -33,7 +33,7 @@ VariantsCollectorBase::VariantsCollectorBase ()
// .. nothing yet ..
}
VariantsCollectorBase::VariantsCollectorBase (TransformationReducer *red)
VariantsCollectorBase::VariantsCollectorBase (const TransformationReducer *red)
: mp_red (red)
{
// .. nothing yet ..
@ -42,7 +42,7 @@ VariantsCollectorBase::VariantsCollectorBase (TransformationReducer *red)
void
VariantsCollectorBase::collect (const db::Layout &layout, const db::Cell &top_cell)
{
tl_assert (mp_red.get () != 0);
tl_assert (mp_red != 0);
// The top cell gets a "variant" with unit transformation
m_variants [top_cell.cell_index ()].insert (std::make_pair (db::ICplxTrans (), 1));
@ -78,7 +78,7 @@ VariantsCollectorBase::collect (const db::Layout &layout, const db::Cell &top_ce
void
VariantsCollectorBase::separate_variants (db::Layout &layout, db::Cell &top_cell, std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> > *var_table)
{
tl_assert (mp_red.get () != 0);
tl_assert (mp_red != 0);
db::LayoutLocker locker (&layout);
@ -177,6 +177,8 @@ VariantsCollectorBase::separate_variants (db::Layout &layout, db::Cell &top_cell
void
VariantsCollectorBase::commit_shapes (db::Layout &layout, db::Cell &top_cell, unsigned int layer, std::map<db::cell_index_type, std::map<db::ICplxTrans, db::Shapes> > &to_commit)
{
tl_assert (mp_red != 0);
if (to_commit.empty ()) {
return;
}

View File

@ -44,8 +44,9 @@ namespace db
*
* reduce(A*B) = reduce(reduce(A)*reduce(B))
*/
struct DB_PUBLIC TransformationReducer
class DB_PUBLIC TransformationReducer
{
public:
TransformationReducer () { }
virtual ~TransformationReducer () { }
@ -183,10 +184,8 @@ public:
/**
* @brief Creates a variant collector with the given reducer
*
* The collector will take ownership over the reducer
*/
VariantsCollectorBase (TransformationReducer *red);
VariantsCollectorBase (const TransformationReducer *red);
/**
* @brief Collects cell variants for the given layout starting from the top cell
@ -228,7 +227,7 @@ public:
private:
std::map<db::cell_index_type, std::map<db::ICplxTrans, size_t> > m_variants;
std::auto_ptr<TransformationReducer> mp_red;
const TransformationReducer *mp_red;
void add_variant (std::map<db::ICplxTrans, size_t> &variants, const db::CellInstArray &inst, bool tl_invariant) const;
void add_variant_non_tl_invariant (std::map<db::ICplxTrans, size_t> &variants, const db::CellInstArray &inst) const;
@ -252,7 +251,7 @@ public:
* @brief Creates a variant collector without a transformation reducer
*/
cell_variants_collector ()
: VariantsCollectorBase (new RED ())
: VariantsCollectorBase (&m_red)
{
// .. nothing yet ..
}
@ -263,10 +262,13 @@ public:
* The collector will take ownership over the reducer
*/
cell_variants_collector (const RED &red)
: VariantsCollectorBase (new RED (red))
: VariantsCollectorBase (&m_red), m_red (red)
{
// .. nothing yet ..
}
private:
RED m_red;
};
} // namespace db

View File

@ -488,34 +488,50 @@ EdgesDelegate *DeepEdges::filtered (const EdgeFilterBase &filter) const
std::auto_ptr<VariantsCollectorBase> vars;
if (filter.isotropic ()) {
vars.reset (new db::cell_variants_collector<db::MagnificationReducer> ());
} else {
vars.reset (new db::cell_variants_collector<db::MagnificationAndOrientationReducer> ());
if (filter.vars ()) {
vars.reset (new db::VariantsCollectorBase (filter.vars ()));
vars->collect (m_merged_edges.layout (), m_merged_edges.initial_cell ());
// NOTE: m_merged_polygons is mutable, so why is the const_cast needed?
const_cast<db::DeepLayer &> (m_merged_edges).separate_variants (*vars);
}
vars->collect (m_merged_edges.layout (), m_merged_edges.initial_cell ());
// NOTE: m_merged_polygons is mutable, so why is the const_cast needed?
const_cast<db::DeepLayer &> (m_merged_edges).separate_variants (*vars);
db::Layout &layout = m_merged_edges.layout ();
std::auto_ptr<db::DeepEdges> res (new db::DeepEdges (m_merged_edges.derived ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const std::map<db::ICplxTrans, size_t> &v = vars->variants (c->cell_index ());
tl_assert (v.size () == size_t (1));
const db::ICplxTrans &tr = v.begin ()->first;
if (vars.get ()) {
const db::Shapes &s = c->shapes (m_merged_edges.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
const std::map<db::ICplxTrans, size_t> &v = vars->variants (c->cell_index ());
tl_assert (v.size () == size_t (1));
const db::ICplxTrans &tr = v.begin ()->first;
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) {
db::Edge edge = si->edge ();
if (filter.selected (edge.transformed (tr))) {
st.insert (edge);
const db::Shapes &s = c->shapes (m_merged_edges.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) {
db::Edge edge = si->edge ();
if (filter.selected (edge.transformed (tr))) {
st.insert (edge);
}
}
} else {
const db::Shapes &s = c->shapes (m_merged_edges.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) {
db::Edge edge = si->edge ();
if (filter.selected (edge)) {
st.insert (edge);
}
}
}
}

View File

@ -857,13 +857,9 @@ DeepRegion::edges (const EdgeFilterBase *filter) const
std::auto_ptr<VariantsCollectorBase> vars;
if (filter) {
if (filter && filter->vars ()) {
if (filter->isotropic ()) {
vars.reset (new db::cell_variants_collector<db::MagnificationReducer> ());
} else {
vars.reset (new db::cell_variants_collector<db::MagnificationAndOrientationReducer> ());
}
vars.reset (new db::VariantsCollectorBase (filter->vars ()));
vars->collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ());
@ -919,36 +915,52 @@ DeepRegion::filtered (const PolygonFilterBase &filter) const
ensure_merged_polygons_valid ();
std::auto_ptr<VariantsCollectorBase> vars;
if (filter.vars ()) {
vars.reset (new db::VariantsCollectorBase (filter.vars ()));
vars->collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ());
// NOTE: m_merged_polygons is mutable, so why is the const_cast needed?
const_cast<db::DeepLayer &> (m_merged_polygons).separate_variants (*vars);
if (filter.isotropic ()) {
vars.reset (new db::cell_variants_collector<db::MagnificationReducer> ());
} else {
vars.reset (new db::cell_variants_collector<db::MagnificationAndOrientationReducer> ());
}
vars->collect (m_merged_polygons.layout (), m_merged_polygons.initial_cell ());
// NOTE: m_merged_polygons is mutable, so why is the const_cast needed?
const_cast<db::DeepLayer &> (m_merged_polygons).separate_variants (*vars);
db::Layout &layout = m_merged_polygons.layout ();
std::auto_ptr<db::DeepRegion> res (new db::DeepRegion (m_merged_polygons.derived ()));
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const std::map<db::ICplxTrans, size_t> &v = vars->variants (c->cell_index ());
tl_assert (v.size () == size_t (1));
const db::ICplxTrans &tr = v.begin ()->first;
if (vars.get ()) {
const db::Shapes &s = c->shapes (m_merged_polygons.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
const std::map<db::ICplxTrans, size_t> &v = vars->variants (c->cell_index ());
tl_assert (v.size () == size_t (1));
const db::ICplxTrans &tr = v.begin ()->first;
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
db::Polygon poly;
si->polygon (poly);
if (filter.selected (poly.transformed (tr))) {
st.insert (poly);
const db::Shapes &s = c->shapes (m_merged_polygons.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
db::Polygon poly;
si->polygon (poly);
if (filter.selected (poly.transformed (tr))) {
st.insert (poly);
}
}
} else {
const db::Shapes &s = c->shapes (m_merged_polygons.layer ());
db::Shapes &st = c->shapes (res->deep_layer ().layer ());
for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) {
db::Polygon poly;
si->polygon (poly);
if (filter.selected (poly)) {
st.insert (poly);
}
}
}
}

View File

@ -26,6 +26,7 @@
#include "dbCommon.h"
#include "dbEdgesDelegate.h"
#include "dbRecursiveShapeIterator.h"
#include "dbCellVariants.h"
#include "gsiObject.h"
@ -209,135 +210,7 @@ public:
virtual ~EdgeFilterBase () { }
virtual bool selected (const db::Edge &edge) const = 0;
virtual bool isotropic () const = 0;
};
/**
* @brief An edge length filter for use with Edges::filter or Edges::filtered
*
* This filter has two parameters: lmin and lmax.
* It will filter all edges for which the length is >= lmin and < lmax.
* There is an "invert" flag which allows to select all edges not
* matching the criterion.
*/
struct DB_PUBLIC EdgeLengthFilter
: public EdgeFilterBase
{
typedef db::Edge::distance_type length_type;
/**
* @brief Constructor
*
* @param lmin The minimum length
* @param lmax The maximum length
* @param inverse If set to true, only polygons not matching this criterion will be filtered
*/
EdgeLengthFilter (length_type lmin, length_type lmax, bool inverse)
: m_lmin (lmin), m_lmax (lmax), m_inverse (inverse)
{
// .. nothing yet ..
}
/**
* @brief Returns true if the edge length matches the criterion
*/
bool selected (const db::Edge &edge) const
{
length_type l = edge.length ();
if (! m_inverse) {
return l >= m_lmin && l < m_lmax;
} else {
return ! (l >= m_lmin && l < m_lmax);
}
}
bool isotropic () const
{
return true;
}
private:
length_type m_lmin, m_lmax;
bool m_inverse;
};
/**
* @brief An edge orientation filter for use with Edges::filter or Edges::filtered
*
* This filter has two parameters: amin and amax.
* It will filter all edges for which the orientation angle is >= amin and < amax.
* The orientation angle is measured in degree against the x axis in the mathematical sense.
* There is an "invert" flag which allows to select all edges not
* matching the criterion.
*/
struct DB_PUBLIC EdgeOrientationFilter
: public EdgeFilterBase
{
/**
* @brief Constructor
*
* @param amin The minimum angle (measured against the x axis)
* @param amax The maximum angle (measured against the x axis)
* @param inverse If set to true, only edges not matching this criterion will be filtered
*
* This filter will filter out all edges whose angle against x axis
* is larger or equal to amin and less than amax.
*/
EdgeOrientationFilter (double amin, double amax, bool inverse)
: m_inverse (inverse), m_exact (false)
{
m_emin = db::DVector (cos (amin * M_PI / 180.0), sin (amin * M_PI / 180.0));
m_emax = db::DVector (cos (amax * M_PI / 180.0), sin (amax * M_PI / 180.0));
}
/**
* @brief Constructor
*
* @param a The angle (measured against the x axis)
* @param inverse If set to true, only edges not matching this criterion will be filtered
*
* This filter will filter out all edges whose angle against x axis
* is equal to a.
*/
EdgeOrientationFilter (double a, bool inverse)
: m_inverse (inverse), m_exact (true)
{
m_emin = db::DVector (cos (a * M_PI / 180.0), sin (a * M_PI / 180.0));
}
/**
* @brief Returns true if the edge orientation matches the criterion
*/
bool selected (const db::Edge &edge) const
{
int smin = db::vprod_sign (m_emin, db::DVector (edge.d ()));
if (m_exact) {
if (! m_inverse) {
return smin == 0;
} else {
return smin != 0;
}
} else {
int smax = db::vprod_sign (m_emax, db::DVector (edge.d ()));
if (! m_inverse) {
return (smin >= 0 && smax < 0) || (smax > 0 && smin <= 0);
} else {
return ! ((smin >= 0 && smax < 0) || (smax > 0 && smin <= 0));
}
}
}
bool isotropic () const
{
return false;
}
private:
db::DVector m_emin, m_emax;
bool m_inverse;
bool m_exact;
virtual const TransformationReducer *vars () const = 0;
};
/**

View File

169
src/db/db/dbEdgesUtils.h Normal file
View File

@ -0,0 +1,169 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2019 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_dbEdgesUtils
#define HDR_dbEdgesUtils
#include "dbCommon.h"
#include "dbEdges.h"
namespace db {
/**
* @brief An edge length filter for use with Edges::filter or Edges::filtered
*
* This filter has two parameters: lmin and lmax.
* It will filter all edges for which the length is >= lmin and < lmax.
* There is an "invert" flag which allows to select all edges not
* matching the criterion.
*/
struct DB_PUBLIC EdgeLengthFilter
: public EdgeFilterBase
{
typedef db::Edge::distance_type length_type;
/**
* @brief Constructor
*
* @param lmin The minimum length
* @param lmax The maximum length
* @param inverse If set to true, only polygons not matching this criterion will be filtered
*/
EdgeLengthFilter (length_type lmin, length_type lmax, bool inverse)
: m_lmin (lmin), m_lmax (lmax), m_inverse (inverse)
{
// .. nothing yet ..
}
/**
* @brief Returns true if the edge length matches the criterion
*/
virtual bool selected (const db::Edge &edge) const
{
length_type l = edge.length ();
if (! m_inverse) {
return l >= m_lmin && l < m_lmax;
} else {
return ! (l >= m_lmin && l < m_lmax);
}
}
/**
* @brief This filter is isotropic
*/
virtual const TransformationReducer *vars () const
{
return &m_vars;
}
private:
length_type m_lmin, m_lmax;
bool m_inverse;
db::MagnificationReducer m_vars;
};
/**
* @brief An edge orientation filter for use with Edges::filter or Edges::filtered
*
* This filter has two parameters: amin and amax.
* It will filter all edges for which the orientation angle is >= amin and < amax.
* The orientation angle is measured in degree against the x axis in the mathematical sense.
* There is an "invert" flag which allows to select all edges not
* matching the criterion.
*/
struct DB_PUBLIC EdgeOrientationFilter
: public EdgeFilterBase
{
/**
* @brief Constructor
*
* @param amin The minimum angle (measured against the x axis)
* @param amax The maximum angle (measured against the x axis)
* @param inverse If set to true, only edges not matching this criterion will be filtered
*
* This filter will filter out all edges whose angle against x axis
* is larger or equal to amin and less than amax.
*/
EdgeOrientationFilter (double amin, double amax, bool inverse)
: m_inverse (inverse), m_exact (false)
{
m_emin = db::DVector (cos (amin * M_PI / 180.0), sin (amin * M_PI / 180.0));
m_emax = db::DVector (cos (amax * M_PI / 180.0), sin (amax * M_PI / 180.0));
}
/**
* @brief Constructor
*
* @param a The angle (measured against the x axis)
* @param inverse If set to true, only edges not matching this criterion will be filtered
*
* This filter will filter out all edges whose angle against x axis
* is equal to a.
*/
EdgeOrientationFilter (double a, bool inverse)
: m_inverse (inverse), m_exact (true)
{
m_emin = db::DVector (cos (a * M_PI / 180.0), sin (a * M_PI / 180.0));
}
/**
* @brief Returns true if the edge orientation matches the criterion
*/
virtual bool selected (const db::Edge &edge) const
{
int smin = db::vprod_sign (m_emin, db::DVector (edge.d ()));
if (m_exact) {
if (! m_inverse) {
return smin == 0;
} else {
return smin != 0;
}
} else {
int smax = db::vprod_sign (m_emax, db::DVector (edge.d ()));
if (! m_inverse) {
return (smin >= 0 && smax < 0) || (smax > 0 && smin <= 0);
} else {
return ! ((smin >= 0 && smax < 0) || (smax > 0 && smin <= 0));
}
}
}
/**
* @brief This filter is not isotropic
*/
virtual const TransformationReducer *vars () const
{
return &m_vars;
}
private:
db::DVector m_emin, m_emax;
bool m_inverse;
bool m_exact;
db::MagnificationAndOrientationReducer m_vars;
};
} // namespace db
#endif

View File

@ -28,6 +28,7 @@
#include "dbRegionDelegate.h"
#include "dbRecursiveShapeIterator.h"
#include "dbPolygonGenerators.h"
#include "dbCellVariants.h"
#include "gsiObject.h"
@ -39,6 +40,7 @@ class EdgeFilterBase;
class FlatRegion;
class EmptyRegion;
class DeepShapeStore;
class TransformationReducer;
/**
* @brief A base class for polygon filters
@ -49,280 +51,8 @@ public:
PolygonFilterBase () { }
virtual ~PolygonFilterBase () { }
virtual bool selected (const db::Polygon &polgon) const = 0;
virtual bool isotropic () const = 0;
};
/**
* @brief A perimeter filter for use with Region::filter or Region::filtered
*
* This filter has two parameters: pmin and pmax.
* It will filter all polygons for which the perimeter is >= pmin and < pmax.
* There is an "invert" flag which allows to select all polygons not
* matching the criterion.
*/
struct DB_PUBLIC RegionPerimeterFilter
: public PolygonFilterBase
{
typedef db::coord_traits<db::Coord>::perimeter_type perimeter_type;
/**
* @brief Constructor
*
* @param amin The min perimeter (only polygons above this value are filtered)
* @param amax The maximum perimeter (only polygons with a perimeter below this value are filtered)
* @param inverse If set to true, only polygons not matching this criterion will be filtered
*/
RegionPerimeterFilter (perimeter_type pmin, perimeter_type pmax, bool inverse)
: m_pmin (pmin), m_pmax (pmax), m_inverse (inverse)
{
// .. nothing yet ..
}
/**
* @brief Returns true if the polygon's perimeter matches the criterion
*/
virtual bool selected (const db::Polygon &poly) const
{
perimeter_type p = 0;
for (db::Polygon::polygon_edge_iterator e = poly.begin_edge (); ! e.at_end () && p < m_pmax; ++e) {
p += (*e).length ();
}
if (! m_inverse) {
return p >= m_pmin && p < m_pmax;
} else {
return ! (p >= m_pmin && p < m_pmax);
}
}
/**
* @brief This filter is isotropic
*/
virtual bool isotropic () const
{
return true;
}
private:
perimeter_type m_pmin, m_pmax;
bool m_inverse;
};
/**
* @brief An area filter for use with Region::filter or Region::filtered
*
* This filter has two parameters: amin and amax.
* It will filter all polygons for which the area is >= amin and < amax.
* There is an "invert" flag which allows to select all polygons not
* matching the criterion.
*/
struct DB_PUBLIC RegionAreaFilter
: public PolygonFilterBase
{
typedef db::Polygon::area_type area_type;
/**
* @brief Constructor
*
* @param amin The min area (only polygons above this value are filtered)
* @param amax The maximum area (only polygons with an area below this value are filtered)
* @param inverse If set to true, only polygons not matching this criterion will be filtered
*/
RegionAreaFilter (area_type amin, area_type amax, bool inverse)
: m_amin (amin), m_amax (amax), m_inverse (inverse)
{
// .. nothing yet ..
}
/**
* @brief Returns true if the polygon's area matches the criterion
*/
virtual bool selected (const db::Polygon &poly) const
{
area_type a = poly.area ();
if (! m_inverse) {
return a >= m_amin && a < m_amax;
} else {
return ! (a >= m_amin && a < m_amax);
}
}
/**
* @brief This filter is isotropic
*/
virtual bool isotropic () const
{
return true;
}
private:
area_type m_amin, m_amax;
bool m_inverse;
};
/**
* @brief A filter for rectilinear polygons
*
* This filter will select all polygons which are rectilinear.
*/
struct DB_PUBLIC RectilinearFilter
: public PolygonFilterBase
{
/**
* @brief Constructor
* @param inverse If set to true, only polygons not matching this criterion will be filtered
*/
RectilinearFilter (bool inverse)
: m_inverse (inverse)
{
// .. nothing yet ..
}
/**
* @brief Returns true if the polygon's area matches the criterion
*/
virtual bool selected (const db::Polygon &poly) const
{
return poly.is_rectilinear () != m_inverse;
}
/**
* @brief This filter is isotropic
*/
virtual bool isotropic () const
{
return true;
}
private:
bool m_inverse;
};
/**
* @brief A rectangle filter
*
* This filter will select all polygons which are rectangles.
*/
struct DB_PUBLIC RectangleFilter
: public PolygonFilterBase
{
/**
* @brief Constructor
* @param inverse If set to true, only polygons not matching this criterion will be filtered
*/
RectangleFilter (bool inverse)
: m_inverse (inverse)
{
// .. nothing yet ..
}
/**
* @brief Returns true if the polygon's area matches the criterion
*/
virtual bool selected (const db::Polygon &poly) const
{
return poly.is_box () != m_inverse;
}
/**
* @brief This filter is isotropic
*/
virtual bool isotropic () const
{
return true;
}
private:
bool m_inverse;
};
/**
* @brief A bounding box filter for use with Region::filter or Region::filtered
*
* This filter has two parameters: vmin and vmax.
* It will filter all polygons for which the selected bounding box parameter is >= vmin and < vmax.
* There is an "invert" flag which allows to select all polygons not
* matching the criterion.
*
* For bounding box parameters the following choices are available:
* - (BoxWidth) width
* - (BoxHeight) height
* - (BoxMaxDim) maximum of width and height
* - (BoxMinDim) minimum of width and height
* - (BoxAverageDim) average of width and height
*/
struct DB_PUBLIC RegionBBoxFilter
: public PolygonFilterBase
{
typedef db::Box::distance_type value_type;
/**
* @brief The parameters available
*/
enum parameter_type {
BoxWidth,
BoxHeight,
BoxMaxDim,
BoxMinDim,
BoxAverageDim
};
/**
* @brief Constructor
*
* @param vmin The min value (only polygons with bounding box parameters above this value are filtered)
* @param vmax The max value (only polygons with bounding box parameters below this value are filtered)
* @param inverse If set to true, only polygons not matching this criterion will be filtered
*/
RegionBBoxFilter (value_type vmin, value_type vmax, bool inverse, parameter_type parameter)
: m_vmin (vmin), m_vmax (vmax), m_inverse (inverse), m_parameter (parameter)
{
// .. nothing yet ..
}
/**
* @brief Returns true if the polygon's area matches the criterion
*/
virtual bool selected (const db::Polygon &poly) const
{
value_type v = 0;
db::Box box = poly.box ();
if (m_parameter == BoxWidth) {
v = box.width ();
} else if (m_parameter == BoxHeight) {
v = box.height ();
} else if (m_parameter == BoxMinDim) {
v = std::min (box.width (), box.height ());
} else if (m_parameter == BoxMaxDim) {
v = std::max (box.width (), box.height ());
} else if (m_parameter == BoxAverageDim) {
v = (box.width () + box.height ()) / 2;
}
if (! m_inverse) {
return v >= m_vmin && v < m_vmax;
} else {
return ! (v >= m_vmin && v < m_vmax);
}
}
/**
* @brief This filter is isotropic unless the parameter is width or height
*/
virtual bool isotropic () const
{
return m_parameter != BoxWidth && m_parameter != BoxHeight;
}
private:
value_type m_vmin, m_vmax;
bool m_inverse;
parameter_type m_parameter;
virtual bool selected (const db::Polygon &polygon) const = 0;
virtual const TransformationReducer *vars () const = 0;
};
/**

View File

@ -0,0 +1,31 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2019 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
*/
#include "dbRegionUtils.h"
namespace db {
// .. nothing yet ..
}

316
src/db/db/dbRegionUtils.h Normal file
View File

@ -0,0 +1,316 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2019 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_dbRegionUtils
#define HDR_dbRegionUtils
#include "dbCommon.h"
#include "dbRegion.h"
#include "dbCellVariants.h"
namespace db {
/**
* @brief A perimeter filter for use with Region::filter or Region::filtered
*
* This filter has two parameters: pmin and pmax.
* It will filter all polygons for which the perimeter is >= pmin and < pmax.
* There is an "invert" flag which allows to select all polygons not
* matching the criterion.
*/
struct DB_PUBLIC RegionPerimeterFilter
: public PolygonFilterBase
{
typedef db::coord_traits<db::Coord>::perimeter_type perimeter_type;
/**
* @brief Constructor
*
* @param amin The min perimeter (only polygons above this value are filtered)
* @param amax The maximum perimeter (only polygons with a perimeter below this value are filtered)
* @param inverse If set to true, only polygons not matching this criterion will be filtered
*/
RegionPerimeterFilter (perimeter_type pmin, perimeter_type pmax, bool inverse)
: m_pmin (pmin), m_pmax (pmax), m_inverse (inverse)
{
// .. nothing yet ..
}
/**
* @brief Returns true if the polygon's perimeter matches the criterion
*/
virtual bool selected (const db::Polygon &poly) const
{
perimeter_type p = 0;
for (db::Polygon::polygon_edge_iterator e = poly.begin_edge (); ! e.at_end () && p < m_pmax; ++e) {
p += (*e).length ();
}
if (! m_inverse) {
return p >= m_pmin && p < m_pmax;
} else {
return ! (p >= m_pmin && p < m_pmax);
}
}
/**
* @brief This filter is isotropic
*/
virtual const TransformationReducer *vars () const
{
return &m_vars;
}
private:
perimeter_type m_pmin, m_pmax;
bool m_inverse;
db::MagnificationReducer m_vars;
};
/**
* @brief An area filter for use with Region::filter or Region::filtered
*
* This filter has two parameters: amin and amax.
* It will filter all polygons for which the area is >= amin and < amax.
* There is an "invert" flag which allows to select all polygons not
* matching the criterion.
*/
struct DB_PUBLIC RegionAreaFilter
: public PolygonFilterBase
{
typedef db::Polygon::area_type area_type;
/**
* @brief Constructor
*
* @param amin The min area (only polygons above this value are filtered)
* @param amax The maximum area (only polygons with an area below this value are filtered)
* @param inverse If set to true, only polygons not matching this criterion will be filtered
*/
RegionAreaFilter (area_type amin, area_type amax, bool inverse)
: m_amin (amin), m_amax (amax), m_inverse (inverse)
{
// .. nothing yet ..
}
/**
* @brief Returns true if the polygon's area matches the criterion
*/
virtual bool selected (const db::Polygon &poly) const
{
area_type a = poly.area ();
if (! m_inverse) {
return a >= m_amin && a < m_amax;
} else {
return ! (a >= m_amin && a < m_amax);
}
}
/**
* @brief This filter is isotropic
*/
virtual const TransformationReducer *vars () const
{
return &m_vars;
}
private:
area_type m_amin, m_amax;
bool m_inverse;
db::MagnificationReducer m_vars;
};
/**
* @brief A filter for rectilinear polygons
*
* This filter will select all polygons which are rectilinear.
*/
struct DB_PUBLIC RectilinearFilter
: public PolygonFilterBase
{
/**
* @brief Constructor
* @param inverse If set to true, only polygons not matching this criterion will be filtered
*/
RectilinearFilter (bool inverse)
: m_inverse (inverse)
{
// .. nothing yet ..
}
/**
* @brief Returns true if the polygon's area matches the criterion
*/
virtual bool selected (const db::Polygon &poly) const
{
return poly.is_rectilinear () != m_inverse;
}
/**
* @brief This filter does not need variants
*/
virtual const TransformationReducer *vars () const
{
return 0;
}
private:
bool m_inverse;
};
/**
* @brief A rectangle filter
*
* This filter will select all polygons which are rectangles.
*/
struct DB_PUBLIC RectangleFilter
: public PolygonFilterBase
{
/**
* @brief Constructor
* @param inverse If set to true, only polygons not matching this criterion will be filtered
*/
RectangleFilter (bool inverse)
: m_inverse (inverse)
{
// .. nothing yet ..
}
/**
* @brief Returns true if the polygon's area matches the criterion
*/
virtual bool selected (const db::Polygon &poly) const
{
return poly.is_box () != m_inverse;
}
/**
* @brief This filter does not need variants
*/
virtual const TransformationReducer *vars () const
{
return 0;
}
private:
bool m_inverse;
};
/**
* @brief A bounding box filter for use with Region::filter or Region::filtered
*
* This filter has two parameters: vmin and vmax.
* It will filter all polygons for which the selected bounding box parameter is >= vmin and < vmax.
* There is an "invert" flag which allows to select all polygons not
* matching the criterion.
*
* For bounding box parameters the following choices are available:
* - (BoxWidth) width
* - (BoxHeight) height
* - (BoxMaxDim) maximum of width and height
* - (BoxMinDim) minimum of width and height
* - (BoxAverageDim) average of width and height
*/
struct DB_PUBLIC RegionBBoxFilter
: public PolygonFilterBase
{
typedef db::Box::distance_type value_type;
/**
* @brief The parameters available
*/
enum parameter_type {
BoxWidth,
BoxHeight,
BoxMaxDim,
BoxMinDim,
BoxAverageDim
};
/**
* @brief Constructor
*
* @param vmin The min value (only polygons with bounding box parameters above this value are filtered)
* @param vmax The max value (only polygons with bounding box parameters below this value are filtered)
* @param inverse If set to true, only polygons not matching this criterion will be filtered
*/
RegionBBoxFilter (value_type vmin, value_type vmax, bool inverse, parameter_type parameter)
: m_vmin (vmin), m_vmax (vmax), m_inverse (inverse), m_parameter (parameter)
{
// .. nothing yet ..
}
/**
* @brief Returns true if the polygon's area matches the criterion
*/
virtual bool selected (const db::Polygon &poly) const
{
value_type v = 0;
db::Box box = poly.box ();
if (m_parameter == BoxWidth) {
v = box.width ();
} else if (m_parameter == BoxHeight) {
v = box.height ();
} else if (m_parameter == BoxMinDim) {
v = std::min (box.width (), box.height ());
} else if (m_parameter == BoxMaxDim) {
v = std::max (box.width (), box.height ());
} else if (m_parameter == BoxAverageDim) {
v = (box.width () + box.height ()) / 2;
}
if (! m_inverse) {
return v >= m_vmin && v < m_vmax;
} else {
return ! (v >= m_vmin && v < m_vmax);
}
}
/**
* @brief This filter is isotropic unless the parameter is width or height
*/
virtual const TransformationReducer *vars () const
{
if (m_parameter != BoxWidth && m_parameter != BoxHeight) {
return &m_isotropic_vars;
} else {
return &m_anisotropic_vars;
}
}
private:
value_type m_vmin, m_vmax;
bool m_inverse;
parameter_type m_parameter;
db::MagnificationReducer m_isotropic_vars;
db::MagnificationAndOrientationReducer m_anisotropic_vars;
};
} // namespace db
#endif

View File

@ -25,6 +25,7 @@
#include "dbDeepShapeStore.h"
#include "dbEdges.h"
#include "dbEdgesUtils.h"
#include "dbDeepEdges.h"
#include "dbRegion.h"
#include "dbLayoutUtils.h"

View File

@ -23,6 +23,7 @@
#include "gsiDecl.h"
#include "dbRegion.h"
#include "dbRegionUtils.h"
#include "dbDeepRegion.h"
#include "dbPolygonTools.h"
#include "dbLayoutUtils.h"

View File

@ -26,6 +26,7 @@
#include "dbTestSupport.h"
#include "dbEdges.h"
#include "dbRegion.h"
#include "dbEdgesUtils.h"
#include "dbDeepShapeStore.h"
#include "tlUnitTest.h"
#include "tlStream.h"

View File

@ -26,6 +26,8 @@
#include "dbTestSupport.h"
#include "dbRegion.h"
#include "dbEdges.h"
#include "dbRegionUtils.h"
#include "dbEdgesUtils.h"
#include "dbDeepShapeStore.h"
#include "tlUnitTest.h"
#include "tlStream.h"

View File

@ -24,6 +24,7 @@
#include "tlUnitTest.h"
#include "dbEdges.h"
#include "dbEdgesUtils.h"
#include "dbPolygonTools.h"
#include "dbRegion.h"

View File

@ -24,6 +24,8 @@
#include "tlUnitTest.h"
#include "dbRegion.h"
#include "dbRegionUtils.h"
#include "dbEdgesUtils.h"
#include "dbBoxScanner.h"
#include <cstdio>