diff --git a/src/db/db/db.pro b/src/db/db/db.pro index eafb681ba..38eb8638d 100644 --- a/src/db/db/db.pro +++ b/src/db/db/db.pro @@ -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") { diff --git a/src/db/db/dbCellVariants.cc b/src/db/db/dbCellVariants.cc index 397415148..1ff5c9f76 100644 --- a/src/db/db/dbCellVariants.cc +++ b/src/db/db/dbCellVariants.cc @@ -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 > *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 > &to_commit) { + tl_assert (mp_red != 0); + if (to_commit.empty ()) { return; } diff --git a/src/db/db/dbCellVariants.h b/src/db/db/dbCellVariants.h index 59fcc8601..d3c0f69f3 100644 --- a/src/db/db/dbCellVariants.h +++ b/src/db/db/dbCellVariants.h @@ -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 > m_variants; - std::auto_ptr mp_red; + const TransformationReducer *mp_red; void add_variant (std::map &variants, const db::CellInstArray &inst, bool tl_invariant) const; void add_variant_non_tl_invariant (std::map &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 diff --git a/src/db/db/dbDeepEdges.cc b/src/db/db/dbDeepEdges.cc index d23dd71fa..2ece77a73 100644 --- a/src/db/db/dbDeepEdges.cc +++ b/src/db/db/dbDeepEdges.cc @@ -488,34 +488,50 @@ EdgesDelegate *DeepEdges::filtered (const EdgeFilterBase &filter) const std::auto_ptr vars; - if (filter.isotropic ()) { - vars.reset (new db::cell_variants_collector ()); - } else { - vars.reset (new db::cell_variants_collector ()); + 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 (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 (m_merged_edges).separate_variants (*vars); - db::Layout &layout = m_merged_edges.layout (); std::auto_ptr res (new db::DeepEdges (m_merged_edges.derived ())); for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { - const std::map &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 &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); + } + } + } } diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index 2a32c5cd8..013b1d2e2 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -857,13 +857,9 @@ DeepRegion::edges (const EdgeFilterBase *filter) const std::auto_ptr vars; - if (filter) { + if (filter && filter->vars ()) { - if (filter->isotropic ()) { - vars.reset (new db::cell_variants_collector ()); - } else { - vars.reset (new db::cell_variants_collector ()); - } + 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 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 (m_merged_polygons).separate_variants (*vars); - if (filter.isotropic ()) { - vars.reset (new db::cell_variants_collector ()); - } else { - vars.reset (new db::cell_variants_collector ()); } - 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 (m_merged_polygons).separate_variants (*vars); - db::Layout &layout = m_merged_polygons.layout (); std::auto_ptr res (new db::DeepRegion (m_merged_polygons.derived ())); for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { - const std::map &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 &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); + } + } + } } diff --git a/src/db/db/dbEdges.h b/src/db/db/dbEdges.h index e4cac3b67..3c2c7ab11 100644 --- a/src/db/db/dbEdges.h +++ b/src/db/db/dbEdges.h @@ -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; }; /** diff --git a/src/db/db/dbEdgesUtils.cc b/src/db/db/dbEdgesUtils.cc new file mode 100644 index 000000000..e69de29bb diff --git a/src/db/db/dbEdgesUtils.h b/src/db/db/dbEdgesUtils.h new file mode 100644 index 000000000..a363ff157 --- /dev/null +++ b/src/db/db/dbEdgesUtils.h @@ -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 diff --git a/src/db/db/dbRegion.h b/src/db/db/dbRegion.h index 4ac0cda62..1bc381d95 100644 --- a/src/db/db/dbRegion.h +++ b/src/db/db/dbRegion.h @@ -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::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; }; /** diff --git a/src/db/db/dbRegionUtils.cc b/src/db/db/dbRegionUtils.cc new file mode 100644 index 000000000..7b3af0289 --- /dev/null +++ b/src/db/db/dbRegionUtils.cc @@ -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 .. + +} + diff --git a/src/db/db/dbRegionUtils.h b/src/db/db/dbRegionUtils.h new file mode 100644 index 000000000..e1eef0578 --- /dev/null +++ b/src/db/db/dbRegionUtils.h @@ -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::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 + diff --git a/src/db/db/gsiDeclDbEdges.cc b/src/db/db/gsiDeclDbEdges.cc index 720dccbc8..0c4c83e57 100644 --- a/src/db/db/gsiDeclDbEdges.cc +++ b/src/db/db/gsiDeclDbEdges.cc @@ -25,6 +25,7 @@ #include "dbDeepShapeStore.h" #include "dbEdges.h" +#include "dbEdgesUtils.h" #include "dbDeepEdges.h" #include "dbRegion.h" #include "dbLayoutUtils.h" diff --git a/src/db/db/gsiDeclDbRegion.cc b/src/db/db/gsiDeclDbRegion.cc index 54820cd39..57d9b0dca 100644 --- a/src/db/db/gsiDeclDbRegion.cc +++ b/src/db/db/gsiDeclDbRegion.cc @@ -23,6 +23,7 @@ #include "gsiDecl.h" #include "dbRegion.h" +#include "dbRegionUtils.h" #include "dbDeepRegion.h" #include "dbPolygonTools.h" #include "dbLayoutUtils.h" diff --git a/src/db/unit_tests/dbDeepEdgesTests.cc b/src/db/unit_tests/dbDeepEdgesTests.cc index 6bd54f06b..9fcfed52a 100644 --- a/src/db/unit_tests/dbDeepEdgesTests.cc +++ b/src/db/unit_tests/dbDeepEdgesTests.cc @@ -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" diff --git a/src/db/unit_tests/dbDeepRegionTests.cc b/src/db/unit_tests/dbDeepRegionTests.cc index fc398e7de..65b0d908f 100644 --- a/src/db/unit_tests/dbDeepRegionTests.cc +++ b/src/db/unit_tests/dbDeepRegionTests.cc @@ -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" diff --git a/src/db/unit_tests/dbEdges.cc b/src/db/unit_tests/dbEdges.cc index eea55da20..23e7fd371 100644 --- a/src/db/unit_tests/dbEdges.cc +++ b/src/db/unit_tests/dbEdges.cc @@ -24,6 +24,7 @@ #include "tlUnitTest.h" #include "dbEdges.h" +#include "dbEdgesUtils.h" #include "dbPolygonTools.h" #include "dbRegion.h" diff --git a/src/db/unit_tests/dbRegion.cc b/src/db/unit_tests/dbRegion.cc index 954a09831..706647a2c 100644 --- a/src/db/unit_tests/dbRegion.cc +++ b/src/db/unit_tests/dbRegion.cc @@ -24,6 +24,8 @@ #include "tlUnitTest.h" #include "dbRegion.h" +#include "dbRegionUtils.h" +#include "dbEdgesUtils.h" #include "dbBoxScanner.h" #include