klayout/src/db/dbBoxConvert.h

673 lines
16 KiB
C
Raw Normal View History

/*
KLayout Layout Viewer
2017-02-12 15:28:14 +01:00
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_dbBoxConvert
#define HDR_dbBoxConvert
#include "dbText.h"
#include "dbPolygon.h"
#include "dbEdge.h"
#include "dbEdgePair.h"
#include "dbUserObject.h"
#include "dbBox.h"
#include "dbPath.h"
#include "dbArray.h"
#include "dbObjectWithProperties.h"
namespace db
{
class Cell;
class CellInst;
class Layout;
/**
* @brief A tag class to indicate "simple" box computation
*
* Using this tag as a typedef for box_convert<T>::complexity
* enables algorithms to simply use the box without caching it.
*/
struct DB_PUBLIC simple_bbox_tag { };
/**
* @brief A tag class to indicate "complex" box computation
*
* Using this tag as a typedef for box_convert<T>::complexity
* enables algorithms to use cached bboxes, i.e. for the dbBoxTree.
*/
struct DB_PUBLIC complex_bbox_tag { };
/**
* @brief The generic box converter for the shapes
*
* The box converter is supposed to convert a given
* shape (i.e. edge, polygon etc) into a box covering
* the shape as close as possible).
* This is just the template declaration. The specializations
* provide the correct implementation.
*
* The AllowEmpty flag is ignored currently.
*/
template <class Sh, bool AllowEmpty>
struct box_convert
{
};
/**
* @brief The shape-with-properties box converter
*
* The AllowEmpty flag is ignored currently.
*/
template <class Sh, bool AllowEmpty>
struct box_convert< db::object_with_properties<Sh>, AllowEmpty >
{
typedef db::box_convert<Sh> base_convert;
typedef typename base_convert::complexity complexity;
typedef typename base_convert::box_type box_type;
box_type operator() (const db::object_with_properties<Sh> &s) const
{
return bconvert (s);
}
base_convert bconvert;
};
/**
* @brief The text box converter
*
* The text is just a point, so the box returned is
* degenerated, but usable.
*
* The AllowEmpty flag is ignored currently.
*/
template <class C, bool AllowEmpty>
struct box_convert< db::text<C>, AllowEmpty >
{
typedef db::text<C> text_type;
typedef db::box<C> box_type;
typedef simple_bbox_tag complexity;
box_type operator() (const text_type &t) const
{
return t.box ();
}
};
/**
* @brief The text reference box converter
*
* The text is just a point, so the box returned is
* degenerated, but usable.
*
* The AllowEmpty flag is ignored currently.
*/
template <class Text, class Trans, bool AllowEmpty>
struct box_convert< db::text_ref<Text, Trans>, AllowEmpty >
{
typedef db::text_ref<Text, Trans> text_ref_type;
typedef typename Text::coord_type coord_type;
typedef db::box<coord_type> box_type;
typedef simple_bbox_tag complexity;
box_type operator() (const text_ref_type &t) const
{
return t.box ();
}
};
/**
* @brief The text reference array box converter
*
* The text is just a point, so the box returned is
* degenerated, but usable.
*
* The AllowEmpty flag is ignored currently.
*/
template <class Text, class Trans, class ArrayTrans, bool AllowEmpty>
struct box_convert< db::array< db::text_ref<Text, Trans>, ArrayTrans>, AllowEmpty >
{
typedef db::text_ref<Text, Trans> text_ref_type;
typedef db::array<text_ref_type, ArrayTrans> text_ref_array_type;
typedef typename Text::coord_type coord_type;
typedef db::box<coord_type> box_type;
typedef simple_bbox_tag complexity;
box_type operator() (const text_ref_array_type &t) const
{
box_convert< db::text_ref<Text, Trans> > bc;
return t.bbox (bc);
}
};
/**
* @brief The path box converter
*
* This maps the box to the bounding box of the polygon.
*
* The AllowEmpty flag is ignored currently.
*/
template <class C, bool AllowEmpty>
struct box_convert < db::path<C>, AllowEmpty >
{
typedef db::path <C> path_type;
typedef db::box <C> box_type;
typedef complex_bbox_tag complexity;
box_type operator() (const path_type &p) const
{
return p.box ();
}
};
/**
* @brief The path reference box converter
*
* This maps the box to the bounding box of the polygon.
*
* The AllowEmpty flag is ignored currently.
*/
template <class Path, class Trans, bool AllowEmpty>
struct box_convert < db::path_ref<Path, Trans>, AllowEmpty >
{
typedef db::path_ref <Path, Trans> path_ref_type;
typedef typename Path::coord_type coord_type;
typedef db::box <coord_type> box_type;
typedef complex_bbox_tag complexity;
box_type operator() (const path_ref_type &p) const
{
return p.box ();
}
};
/**
* @brief The path reference array box converter
*
* This maps the box to the bounding box of the polygon.
*
* The AllowEmpty flag is ignored currently.
*/
template <class Path, class Trans, class ArrayTrans, bool AllowEmpty>
struct box_convert < db::array< db::path_ref<Path, Trans>, ArrayTrans >, AllowEmpty >
{
typedef db::path_ref <Path, Trans> path_ref_type;
typedef db::array<path_ref_type, ArrayTrans> path_ref_array_type;
typedef typename Path::coord_type coord_type;
typedef db::box <coord_type> box_type;
typedef complex_bbox_tag complexity;
box_type operator() (const path_ref_array_type &p) const
{
box_convert< db::path_ref<Path, Trans> > bc;
return p.bbox (bc);
}
};
/**
* @brief The polygon box converter
*
* This maps the box to the bounding box of the polygon.
*
* The AllowEmpty flag is ignored currently.
*/
template <class C, bool AllowEmpty>
struct box_convert< db::polygon<C>, AllowEmpty >
{
typedef db::polygon<C> polygon_type;
typedef db::box<C> box_type;
typedef simple_bbox_tag complexity;
const box_type &operator() (const polygon_type &p) const
{
return p.box ();
}
};
/**
* @brief The simple polygon box converter
*
* This maps the box to the bounding box of the polygon.
*
* The AllowEmpty flag is ignored currently.
*/
template <class C, bool AllowEmpty>
struct box_convert< db::simple_polygon<C>, AllowEmpty >
{
typedef db::simple_polygon<C> simple_polygon_type;
typedef db::box<C> box_type;
typedef simple_bbox_tag complexity;
const box_type &operator() (const simple_polygon_type &p) const
{
return p.box ();
}
};
/**
* @brief The polygon reference box converter
*
* This maps the box to the bounding box of the polygon.
*
* The AllowEmpty flag is ignored currently.
*/
template <class Poly, class Trans, bool AllowEmpty>
struct box_convert< db::polygon_ref<Poly, Trans>, AllowEmpty >
{
typedef db::polygon_ref<Poly, Trans> polygon_ref_type;
typedef typename Poly::coord_type coord_type;
typedef db::box<coord_type> box_type;
typedef simple_bbox_tag complexity;
box_type operator() (const polygon_ref_type &p) const
{
return p.box ();
}
};
/**
* @brief The polygon reference box converter
*
* This maps the box to the bounding box of the polygon.
*
* The AllowEmpty flag is ignored currently.
*/
template <class Poly, class Trans, class ArrayTrans, bool AllowEmpty>
struct box_convert< db::array< db::polygon_ref<Poly, Trans>, ArrayTrans >, AllowEmpty >
{
typedef db::polygon_ref<Poly, Trans> polygon_ref_type;
typedef db::array<polygon_ref_type, ArrayTrans> polygon_ref_array_type;
typedef typename Poly::coord_type coord_type;
typedef db::box<coord_type> box_type;
typedef simple_bbox_tag complexity;
box_type operator() (const polygon_ref_array_type &p) const
{
box_convert< db::polygon_ref<Poly, Trans> > bc;
return p.bbox (bc);
}
};
/**
* @brief The point box converter
*
* This maps the box to a degenerated box with just one point.
*
* The AllowEmpty flag is ignored currently.
*/
template <class C, bool AllowEmpty>
struct box_convert< db::point<C>, AllowEmpty >
{
typedef db::point<C> point_type;
typedef db::box<C> box_type;
typedef simple_bbox_tag complexity;
box_type operator() (const point_type &p) const
{
return box_type (p, p);
}
};
/**
* @brief The vector box converter
*
* This maps the box to a degenerated box with just one point.
*
* The AllowEmpty flag is ignored currently.
*/
template <class C, bool AllowEmpty>
struct box_convert< db::vector<C>, AllowEmpty >
{
typedef db::vector<C> vector_type;
typedef db::point<C> point_type;
typedef db::box<C> box_type;
typedef simple_bbox_tag complexity;
box_type operator() (const vector_type &p) const
{
return box_type (point_type () + p, point_type () + p);
}
};
/**
* @brief The edge pair box converter
*
* This maps the box to the bounding box of the edge pair, which may
* be degenerate, i.e. for horizontal edges.
*
* The AllowEmpty flag is ignored currently.
*/
template <class C, bool AllowEmpty>
struct box_convert< db::edge_pair<C>, AllowEmpty >
{
typedef db::edge_pair<C> edge_pair_type;
typedef db::box<C> box_type;
typedef simple_bbox_tag complexity;
box_type operator() (const edge_pair_type &e) const
{
return e.bbox ();
}
};
/**
* @brief The edge box converter
*
* This maps the box to the bounding box of the edge, which may
* be degenerate, i.e. for horizontal edges.
*
* The AllowEmpty flag is ignored currently.
*/
template <class C, bool AllowEmpty>
struct box_convert< db::edge<C>, AllowEmpty >
{
typedef db::edge<C> edge_type;
typedef db::box<C> box_type;
typedef simple_bbox_tag complexity;
box_type operator() (const edge_type &e) const
{
return box_type (e.p1 (), e.p2 ());
}
};
/**
* @brief The user object box converter
*
* The AllowEmpty flag is ignored currently.
*/
template <class C, bool AllowEmpty>
struct box_convert< db::user_object<C>, AllowEmpty >
{
typedef db::user_object<C> user_object_type;
typedef db::box<C> box_type;
typedef complex_bbox_tag complexity;
box_type operator() (const user_object_type &r) const
{
return r.box ();
}
};
/**
* @brief The box-to-box converter
*
* This is the trivial case where a box becomes a box.
*
* The AllowEmpty flag is ignored currently.
*/
template <class C, bool AllowEmpty>
struct box_convert <db::box <C>, AllowEmpty >
{
typedef db::box <C> box_type;
typedef simple_bbox_tag complexity;
const box_type &operator() (const box_type &b) const
{
return b;
}
};
/**
* @brief The box array box converter
*
* The AllowEmpty flag is ignored currently.
*/
template <class C, class ArrayTrans, bool AllowEmpty>
struct box_convert< db::array< db::box<C>, ArrayTrans >, AllowEmpty >
{
typedef C coord_type;
typedef db::box<coord_type> box_type;
typedef db::array<box_type, ArrayTrans> box_array_type;
typedef simple_bbox_tag complexity;
box_type operator() (const box_array_type &a) const
{
box_convert<box_type> bc;
return a.bbox (bc);
}
};
/**
* @brief The box-to-box converter for the case of boxes with special internal representation
*
* This is the trivial case where a box becomes a box.
*
* The AllowEmpty flag is ignored currently.
*/
template <class C, class R, bool AllowEmpty>
struct box_convert <db::box <C, R>, AllowEmpty >
{
typedef db::box <C> box_type;
typedef simple_bbox_tag complexity;
box_type operator() (const db::box<C, R> &b) const
{
return box_type (b);
}
};
/**
* @brief The box array box converter for boxes with special internal representation
*
* The AllowEmpty flag is ignored currently.
*/
template <class C, class R, class ArrayTrans, bool AllowEmpty>
struct box_convert< db::array< db::box<C, R>, ArrayTrans >, AllowEmpty >
{
typedef db::box<C> box_type;
typedef db::array< db::box<C, R>, ArrayTrans> box_array_type;
typedef simple_bbox_tag complexity;
box_type operator() (const box_array_type &a) const
{
box_convert< box<C, R> > bc;
return a.bbox (bc);
}
};
// Note: the implementation is delegated, so we don't need to make box_convert dllexport.
DB_PUBLIC db::Box cell_box_convert_impl (const db::Cell &c, int layer, bool allow_empty);
/**
* @brief The cell box converter
*
* This class is used as a function to obtain the bounding box of
* a cell, whether layer-wise or global.
*
* If AllowEmpty is false, the box converter treats empty cells as single points at 0, 0.
*/
template <bool AllowEmpty>
struct DB_PUBLIC box_convert <db::Cell, AllowEmpty>
{
typedef db::Cell cell_type;
typedef db::Box box_type;
typedef complex_bbox_tag complexity;
box_convert ()
: m_layer (-1)
{ }
box_convert (unsigned int l)
: m_layer (l)
{ }
box_type operator() (const cell_type &c) const
{
return cell_box_convert_impl (c, m_layer, AllowEmpty);
}
private:
int m_layer;
};
// Note: the implementation is delegated, so we don't need to make box_convert dllexport.
DB_PUBLIC db::Box cellinst_box_convert_impl (const db::CellInst &inst, const db::Layout *layout, int layer, bool allow_empty);
/**
* @brief The cell inst box converter
*
* This class is used as a function to convert a cell instance
* to a box for a given layer. This requires that the per-layer
* bounding boxes of the cell have been computed already.
*
* If AllowEmpty is false, the box converter treats empty cells as single points at 0, 0.
*/
template <bool AllowEmpty>
struct box_convert <db::CellInst, AllowEmpty>
{
typedef db::CellInst cell_inst_type;
typedef db::Layout layout_type;
typedef db::Box box_type;
typedef complex_bbox_tag complexity;
box_convert ()
: mp_layout (0), m_layer (-1)
{ }
box_convert (const layout_type &ly, unsigned int l)
: mp_layout (&ly), m_layer (l)
{ }
box_convert (const layout_type &ly)
: mp_layout (&ly), m_layer (-1)
{ }
box_type operator() (const cell_inst_type &t) const
{
return cellinst_box_convert_impl (t, mp_layout, m_layer, AllowEmpty);
}
private:
const layout_type *mp_layout;
int m_layer;
};
/**
* @brief The cell inst array box converter
*
* This class is used as a function to convert a cell instance array
* to a box for a given layer or for all layers. This requires that
* the per-layer or overall bounding boxes of the cell have been
* computed already.
*
* If AllowEmpty is false, the box converter treats empty cells as single points at 0, 0.
*/
template <class ArrayTrans, bool AllowEmpty>
struct box_convert <db::array <db::CellInst, ArrayTrans>, AllowEmpty>
{
typedef db::CellInst cell_inst_type;
typedef db::Layout layout_type;
typedef db::Box box_type;
typedef complex_bbox_tag complexity;
box_convert ()
: m_bc ()
{ }
box_convert (const layout_type &g, unsigned int l)
: m_bc (g, l)
{ }
box_convert (const layout_type &g)
: m_bc (g)
{ }
box_type operator() (const db::array <cell_inst_type, ArrayTrans> &t) const
{
return t.bbox (m_bc);
}
private:
box_convert <cell_inst_type, AllowEmpty> m_bc;
};
/**
* @brief The cell-inst-array-with-properties box converter
*
* If AllowEmpty is false, the box converter treats empty cells as single points at 0, 0.
*/
template <class ArrayTrans, bool AllowEmpty>
struct box_convert< db::object_with_properties< db::array <db::CellInst, ArrayTrans> >, AllowEmpty>
{
typedef db::array <db::CellInst, ArrayTrans> cell_inst_array;
typedef db::box_convert<cell_inst_array, AllowEmpty> base_convert;
typedef db::Layout layout_type;
typedef typename base_convert::complexity complexity;
typedef typename base_convert::box_type box_type;
box_convert ()
: bconvert ()
{ }
box_convert (const layout_type &g, unsigned int l)
: bconvert (g, l)
{ }
box_convert (const layout_type &g)
: bconvert (g)
{ }
box_type operator() (const db::object_with_properties<cell_inst_array> &s) const
{
return bconvert (s);
}
base_convert bconvert;
};
}
#endif