mirror of https://github.com/KLayout/klayout.git
Some utility features derived from the latest code changes
- Subtraction of boxes (pya/RBA: Box minus operator) - Shape#rectangle, Shape#drectangle - EdgePairs#write, Edges#write, Texts#write, Region#write for debugging
This commit is contained in:
parent
3fc32e77c3
commit
5699c91d3f
|
|
@ -254,6 +254,27 @@ struct DB_PUBLIC_TEMPLATE box
|
|||
*/
|
||||
box<C, R> &operator+= (const point<C> &p);
|
||||
|
||||
/**
|
||||
* @brief Subtraction of boxes.
|
||||
*
|
||||
* The -= operator subtracts the argument box from *this.
|
||||
* Subtraction leaves the bounding box of the region resulting
|
||||
* from the geometrical NOT of *this and the argument box.
|
||||
* Subtracting a box from itself gives an empty box.
|
||||
* Subtracting a box that does not cover a full side of
|
||||
* *this will not modify the box.
|
||||
*
|
||||
* @param b The box to subtract from *this.
|
||||
*
|
||||
* @return The result box.
|
||||
*/
|
||||
box<C, R> &operator-= (const box<C, R> &b);
|
||||
|
||||
/**
|
||||
* @brief A method version for operator- (mainly for automation purposes)
|
||||
*/
|
||||
box<C, R> subtracted (const box<C, R> &b) const;
|
||||
|
||||
/**
|
||||
* @brief Intersection of boxes.
|
||||
*
|
||||
|
|
@ -784,6 +805,50 @@ box<C, R>::operator+= (const point<C> &p)
|
|||
return *this;
|
||||
}
|
||||
|
||||
template <class C, class R>
|
||||
inline box<C, R>
|
||||
box<C, R>::subtracted (const box<C, R> &b) const
|
||||
{
|
||||
box<C, R> r (*this);
|
||||
r -= b;
|
||||
return r;
|
||||
}
|
||||
|
||||
template <class C, class R>
|
||||
inline box<C, R> &
|
||||
box<C, R>::operator-= (const box<C, R> &bx)
|
||||
{
|
||||
if (bx.empty () || empty ()) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
coord_type l = m_p1.x (), r = m_p2.x ();
|
||||
coord_type b = m_p1.y (), t = m_p2.y ();
|
||||
|
||||
if (bx.bottom () <= bottom () && bx.top () >= top ()) {
|
||||
if (bx.left () <= left ()) {
|
||||
l = std::max (bx.right (), left ());
|
||||
}
|
||||
if (bx.right () >= right ()) {
|
||||
r = std::min (bx.left (), right ());
|
||||
}
|
||||
}
|
||||
|
||||
if (bx.left () <= left () && bx.right () >= right ()) {
|
||||
if (bx.bottom () <= bottom ()) {
|
||||
b = std::max (bx.top (), bottom ());
|
||||
}
|
||||
if (bx.top () >= top ()) {
|
||||
t = std::min (bx.bottom (), top ());
|
||||
}
|
||||
}
|
||||
|
||||
m_p1 = point_type (l, b);
|
||||
m_p2 = point_type (r, t);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class C, class R>
|
||||
inline box<C, R> &
|
||||
box<C, R>::operator&= (const box<C, R> &b)
|
||||
|
|
@ -1363,6 +1428,23 @@ operator+ (const box<C> &b1, const box<C> &b2)
|
|||
return bb;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Box subtraction mapped on the - operator
|
||||
*
|
||||
* @param b1 The first box
|
||||
* @param b2 The second box to subtract from the first
|
||||
*
|
||||
* @return The bounding box of the region formed but subtracting b2 from b1
|
||||
*/
|
||||
template <class C>
|
||||
inline box<C>
|
||||
operator- (const box<C> &b1, const box<C> &b2)
|
||||
{
|
||||
box<C> bb (b1);
|
||||
bb -= b2;
|
||||
return bb;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief "Folding" of two boxes
|
||||
*
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@
|
|||
#include "dbOriginalLayerEdgePairs.h"
|
||||
#include "dbEdges.h"
|
||||
#include "dbRegion.h"
|
||||
#include "dbLayout.h"
|
||||
#include "dbWriter.h"
|
||||
#include "tlStream.h"
|
||||
|
||||
#include "tlVariant.h"
|
||||
|
||||
|
|
@ -93,6 +96,23 @@ EdgePairs::EdgePairs (const RecursiveShapeIterator &si, DeepShapeStore &dss, con
|
|||
mp_delegate = new DeepEdgePairs (si, dss, trans);
|
||||
}
|
||||
|
||||
void
|
||||
EdgePairs::write (const std::string &fn) const
|
||||
{
|
||||
// method provided for debugging purposes
|
||||
|
||||
db::Layout layout;
|
||||
const db::Cell &top = layout.cell (layout.add_cell ("EDGE_PAIRS"));
|
||||
unsigned int li = layout.insert_layer (db::LayerProperties (0, 0));
|
||||
insert_into (&layout, top.cell_index (), li);
|
||||
|
||||
tl::OutputStream os (fn);
|
||||
db::SaveLayoutOptions opt;
|
||||
opt.set_format_from_filename (fn);
|
||||
db::Writer writer (opt);
|
||||
writer.write (layout, os);
|
||||
}
|
||||
|
||||
template <class Sh>
|
||||
void EdgePairs::insert (const Sh &shape)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -185,6 +185,14 @@ public:
|
|||
*/
|
||||
explicit EdgePairs (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans);
|
||||
|
||||
/**
|
||||
* @brief Writes the edge pair collection to a file
|
||||
*
|
||||
* This method is provided for debugging purposes. A flat image of the
|
||||
* region is written to a layout file with a single top cell on layer 0/0.
|
||||
*/
|
||||
void write (const std::string &fn) const;
|
||||
|
||||
/**
|
||||
* @brief Implementation of the ShapeCollection interface
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@
|
|||
#include "dbFlatEdges.h"
|
||||
#include "dbEdgesUtils.h"
|
||||
#include "dbRegion.h"
|
||||
#include "dbLayout.h"
|
||||
#include "dbWriter.h"
|
||||
#include "tlStream.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
|
@ -141,6 +144,23 @@ Edges::set_delegate (EdgesDelegate *delegate, bool keep_attributes)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Edges::write (const std::string &fn) const
|
||||
{
|
||||
// method provided for debugging purposes
|
||||
|
||||
db::Layout layout;
|
||||
const db::Cell &top = layout.cell (layout.add_cell ("EDGES"));
|
||||
unsigned int li = layout.insert_layer (db::LayerProperties (0, 0));
|
||||
insert_into (&layout, top.cell_index (), li);
|
||||
|
||||
tl::OutputStream os (fn);
|
||||
db::SaveLayoutOptions opt;
|
||||
opt.set_format_from_filename (fn);
|
||||
db::Writer writer (opt);
|
||||
writer.write (layout, os);
|
||||
}
|
||||
|
||||
void
|
||||
Edges::clear ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -833,6 +833,14 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes the edge collection to a file
|
||||
*
|
||||
* This method is provided for debugging purposes. A flat image of the
|
||||
* region is written to a layout file with a single top cell on layer 0/0.
|
||||
*/
|
||||
void write (const std::string &fn) const;
|
||||
|
||||
/**
|
||||
* @brief Intersections with other edges
|
||||
* Intersections are similar to "AND", but will also report
|
||||
|
|
|
|||
|
|
@ -918,64 +918,6 @@ RecursiveShapeIterator::new_layer () const
|
|||
}
|
||||
}
|
||||
|
||||
static
|
||||
RecursiveShapeIterator::box_type
|
||||
shape_box (const RecursiveShapeIterator::shape_type &shape)
|
||||
{
|
||||
if (shape.is_box ()) {
|
||||
return shape.box ();
|
||||
}
|
||||
|
||||
switch (shape.type ()) {
|
||||
case db::Shape::Polygon:
|
||||
return shape.polygon ().is_box () ? shape.polygon ().box () : RecursiveShapeIterator::box_type ();
|
||||
case db::Shape::PolygonRef:
|
||||
case db::Shape::PolygonPtrArrayMember:
|
||||
return shape.polygon_ref ().is_box () ? shape.polygon_ref ().box () : RecursiveShapeIterator::box_type ();
|
||||
case db::Shape::SimplePolygon:
|
||||
return shape.simple_polygon ().is_box () ? shape.simple_polygon ().box () : RecursiveShapeIterator::box_type ();
|
||||
case db::Shape::SimplePolygonRef:
|
||||
case db::Shape::SimplePolygonPtrArrayMember:
|
||||
return shape.simple_polygon_ref ().is_box () ? shape.simple_polygon_ref ().box () : RecursiveShapeIterator::box_type ();
|
||||
default:
|
||||
return RecursiveShapeIterator::box_type ();
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
RecursiveShapeIterator::box_type
|
||||
subtract_box (const RecursiveShapeIterator::box_type &from, const RecursiveShapeIterator::box_type &box)
|
||||
{
|
||||
RecursiveShapeIterator::box_type res (from);
|
||||
if (box.empty ()) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (! res.empty ()) {
|
||||
if (box.bottom () <= res.bottom () && box.top () >= res.top ()) {
|
||||
if (box.left () <= res.left ()) {
|
||||
res.set_left (std::max (box.right (), res.left ()));
|
||||
}
|
||||
if (box.right () >= res.right ()) {
|
||||
res.set_right (std::min (box.left (), res.right ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! res.empty ()) {
|
||||
if (box.left () <= res.left () && box.right () >= res.right ()) {
|
||||
if (box.bottom () <= res.bottom ()) {
|
||||
res.set_bottom (std::max (box.top (), res.bottom ()));
|
||||
}
|
||||
if (box.top () >= res.top ()) {
|
||||
res.set_top (std::min (box.bottom (), res.top ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
RecursiveShapeIterator::new_cell (RecursiveShapeReceiver *receiver) const
|
||||
{
|
||||
|
|
@ -1002,7 +944,7 @@ RecursiveShapeIterator::new_cell (RecursiveShapeReceiver *receiver) const
|
|||
|
||||
if (m_for_merged_input && (! m_has_layers || m_layers.size () == 1) && ! m_shape.at_end ()) {
|
||||
|
||||
box_type box = shape_box (*m_shape);
|
||||
box_type box = m_shape->rectangle ();
|
||||
if (! box.empty ()) {
|
||||
|
||||
// Need to enlarge the empty area somewhat so we really exclude instances
|
||||
|
|
@ -1013,7 +955,7 @@ RecursiveShapeIterator::new_cell (RecursiveShapeReceiver *receiver) const
|
|||
|
||||
const box_type ®ion = m_local_region_stack.back ();
|
||||
unsigned int l = m_has_layers ? m_layers.front () : m_layer;
|
||||
box = subtract_box (cell ()->bbox (l) & region, box);
|
||||
box = (cell ()->bbox (l) & region) - box;
|
||||
m_local_region_stack.back () = box;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@
|
|||
#include "dbFlatEdges.h"
|
||||
#include "dbPolygonTools.h"
|
||||
#include "dbCompoundOperation.h"
|
||||
#include "dbLayout.h"
|
||||
#include "dbWriter.h"
|
||||
#include "tlStream.h"
|
||||
#include "tlGlobPattern.h"
|
||||
|
||||
// NOTE: include this to provide the symbols for "make_variant"
|
||||
|
|
@ -129,6 +132,23 @@ Region::Region (DeepShapeStore &dss)
|
|||
mp_delegate = new db::DeepRegion (db::DeepLayer (&dss, layout_index, dss.layout (layout_index).insert_layer ()));
|
||||
}
|
||||
|
||||
void
|
||||
Region::write (const std::string &fn) const
|
||||
{
|
||||
// method provided for debugging purposes
|
||||
|
||||
db::Layout layout;
|
||||
const db::Cell &top = layout.cell (layout.add_cell ("REGION"));
|
||||
unsigned int li = layout.insert_layer (db::LayerProperties (0, 0));
|
||||
insert_into (&layout, top.cell_index (), li);
|
||||
|
||||
tl::OutputStream os (fn);
|
||||
db::SaveLayoutOptions opt;
|
||||
opt.set_format_from_filename (fn);
|
||||
db::Writer writer (opt);
|
||||
writer.write (layout, os);
|
||||
}
|
||||
|
||||
const db::RecursiveShapeIterator &
|
||||
Region::iter () const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -248,6 +248,14 @@ public:
|
|||
*/
|
||||
explicit Region (DeepShapeStore &dss);
|
||||
|
||||
/**
|
||||
* @brief Writes the region to a file
|
||||
*
|
||||
* This method is provided for debugging purposes. A flat image of the
|
||||
* region is written to a layout file with a single top cell on layer 0/0.
|
||||
*/
|
||||
void write (const std::string &fn) const;
|
||||
|
||||
/**
|
||||
* @brief Implementation of the ShapeCollection interface
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -807,6 +807,61 @@ Shape::box_type Shape::bbox () const
|
|||
}
|
||||
}
|
||||
|
||||
Shape::box_type Shape::rectangle () const
|
||||
{
|
||||
if (is_box ()) {
|
||||
return box ();
|
||||
}
|
||||
|
||||
switch (m_type) {
|
||||
case db::Shape::Polygon:
|
||||
return polygon ().is_box () ? polygon ().box () : box_type ();
|
||||
case db::Shape::PolygonRef:
|
||||
case db::Shape::PolygonPtrArrayMember:
|
||||
return polygon_ref ().is_box () ? polygon_ref ().box () : box_type ();
|
||||
case db::Shape::SimplePolygon:
|
||||
return simple_polygon ().is_box () ? simple_polygon ().box () : box_type ();
|
||||
case db::Shape::SimplePolygonRef:
|
||||
case db::Shape::SimplePolygonPtrArrayMember:
|
||||
return simple_polygon_ref ().is_box () ? simple_polygon_ref ().box () : box_type ();
|
||||
case db::Shape::Path:
|
||||
{
|
||||
const path_type &p = path ();
|
||||
if (! p.round () && p.points () <= 2 && p.points () > 0) {
|
||||
point_type p1 = *p.begin ();
|
||||
point_type p2 = p1;
|
||||
if (p.points () == 2) {
|
||||
p2 = *++p.begin ();
|
||||
}
|
||||
if (p1.x () == p2.x () || p1.y () == p2.y ()) {
|
||||
return p.box ();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case db::Shape::PathRef:
|
||||
case db::Shape::PathPtrArrayMember:
|
||||
{
|
||||
const path_ref_type &p = path_ref ();
|
||||
if (! p.ptr ()->round () && p.ptr ()->points () <= 2 && p.ptr ()->points () > 0) {
|
||||
point_type p1 = *p.begin ();
|
||||
point_type p2 = p1;
|
||||
if (p.ptr ()->points () == 2) {
|
||||
p2 = *++p.begin ();
|
||||
}
|
||||
if (p1.x () == p2.x () || p1.y () == p2.y ()) {
|
||||
return p.box ();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return box_type ();
|
||||
}
|
||||
|
||||
std::string
|
||||
Shape::to_string () const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2651,6 +2651,16 @@ public:
|
|||
*/
|
||||
box_type bbox () const;
|
||||
|
||||
/**
|
||||
* @brief Returns the box if the object represents a rectangle or an empty box if not
|
||||
*
|
||||
* This method returns the rectangle (aka box) the shape represents a polygon
|
||||
* that is a rectangle, a path with two points and no rounded ends or an actual box.
|
||||
*
|
||||
* If not, an empty box is returned.
|
||||
*/
|
||||
box_type rectangle () const;
|
||||
|
||||
/**
|
||||
* @brief Compute the area of the shape
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -30,7 +30,9 @@
|
|||
#include "dbOriginalLayerTexts.h"
|
||||
#include "dbEdges.h"
|
||||
#include "dbRegion.h"
|
||||
|
||||
#include "dbLayout.h"
|
||||
#include "dbWriter.h"
|
||||
#include "tlStream.h"
|
||||
#include "tlVariant.h"
|
||||
|
||||
#include <sstream>
|
||||
|
|
@ -90,6 +92,23 @@ Texts::Texts (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::I
|
|||
mp_delegate = new DeepTexts (si, dss, trans);
|
||||
}
|
||||
|
||||
void
|
||||
Texts::write (const std::string &fn) const
|
||||
{
|
||||
// method provided for debugging purposes
|
||||
|
||||
db::Layout layout;
|
||||
const db::Cell &top = layout.cell (layout.add_cell ("TEXTS"));
|
||||
unsigned int li = layout.insert_layer (db::LayerProperties (0, 0));
|
||||
insert_into (&layout, top.cell_index (), li);
|
||||
|
||||
tl::OutputStream os (fn);
|
||||
db::SaveLayoutOptions opt;
|
||||
opt.set_format_from_filename (fn);
|
||||
db::Writer writer (opt);
|
||||
writer.write (layout, os);
|
||||
}
|
||||
|
||||
template <class Sh>
|
||||
void Texts::insert (const Sh &shape)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -181,6 +181,14 @@ public:
|
|||
*/
|
||||
explicit Texts (const RecursiveShapeIterator &si, DeepShapeStore &dss, const db::ICplxTrans &trans);
|
||||
|
||||
/**
|
||||
* @brief Writes the text collection to a file
|
||||
*
|
||||
* This method is provided for debugging purposes. A flat image of the
|
||||
* region is written to a layout file with a single top cell on layer 0/0.
|
||||
*/
|
||||
void write (const std::string &fn) const;
|
||||
|
||||
/**
|
||||
* @brief Implementation of the ShapeCollection interface
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -324,6 +324,21 @@ struct box_defs
|
|||
"\n"
|
||||
"@return The joined box\n"
|
||||
) +
|
||||
method ("-", &C::subtracted, gsi::arg ("box"),
|
||||
"@brief Subtraction of boxes\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"The - operator subtracts the argument box from self.\n"
|
||||
"This will return the bounding box of the are covered by self, but not by argument box. "
|
||||
"Subtracting a box from itself will render an empty box. Subtracting another box from "
|
||||
"self will modify the first box only if the argument box covers one side entirely.\n"
|
||||
"\n"
|
||||
"@param box The box to subtract from this box.\n"
|
||||
"\n"
|
||||
"@return The result box\n"
|
||||
"\n"
|
||||
"This feature has been introduced in version 0.29."
|
||||
) +
|
||||
method ("&", &C::intersection, gsi::arg ("box"),
|
||||
"@brief Returns the intersection of this box with another box\n"
|
||||
"\n"
|
||||
|
|
|
|||
|
|
@ -602,6 +602,12 @@ Class<db::EdgePairs> decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs",
|
|||
"\n"
|
||||
"This constructor has been introduced in version 0.26."
|
||||
) +
|
||||
method ("write", &db::EdgePairs::write, gsi::arg ("filename"),
|
||||
"@brief Writes the region to a file\n"
|
||||
"This method is provided for debugging purposes. It writes the object to a flat layer 0/0 in a single top cell.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.29."
|
||||
) +
|
||||
method ("insert_into", &db::EdgePairs::insert_into, gsi::arg ("layout"), gsi::arg ("cell_index"), gsi::arg ("layer"),
|
||||
"@brief Inserts this edge pairs into the given layout, below the given cell and into the given layer.\n"
|
||||
"If the edge pair collection is a hierarchical one, a suitable hierarchy will be built below the top cell or "
|
||||
|
|
|
|||
|
|
@ -1567,6 +1567,12 @@ Class<db::Edges> decl_Edges (decl_dbShapeCollection, "db", "Edges",
|
|||
"\n"
|
||||
"This method has been added in version 0.28.\n"
|
||||
) +
|
||||
method ("write", &db::Edges::write, gsi::arg ("filename"),
|
||||
"@brief Writes the region to a file\n"
|
||||
"This method is provided for debugging purposes. It writes the object to a flat layer 0/0 in a single top cell.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.29."
|
||||
) +
|
||||
method ("clear", &db::Edges::clear,
|
||||
"@brief Clears the edge collection\n"
|
||||
) +
|
||||
|
|
|
|||
|
|
@ -1221,6 +1221,12 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"This method has been introduced in version 0.26."
|
||||
) +
|
||||
method ("write", &db::Region::write, gsi::arg ("filename"),
|
||||
"@brief Writes the region to a file\n"
|
||||
"This method is provided for debugging purposes. It writes the object to a flat layer 0/0 in a single top cell.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.29."
|
||||
) +
|
||||
factory_ext ("texts", &texts_as_boxes1, gsi::arg ("expr", std::string ("*")), gsi::arg ("as_pattern", true), gsi::arg ("enl", 1),
|
||||
"@hide\n"
|
||||
"This method is provided for DRC implementation only."
|
||||
|
|
|
|||
|
|
@ -669,6 +669,26 @@ static tl::Variant get_dbox (const db::Shape *s)
|
|||
}
|
||||
}
|
||||
|
||||
static tl::Variant get_rectangle (const db::Shape *s)
|
||||
{
|
||||
db::Shape::box_type b = s->rectangle ();
|
||||
if (! b.empty ()) {
|
||||
return tl::Variant (b);
|
||||
} else {
|
||||
return tl::Variant ();
|
||||
}
|
||||
}
|
||||
|
||||
static tl::Variant get_drectangle (const db::Shape *s)
|
||||
{
|
||||
db::Shape::box_type b = s->rectangle ();
|
||||
if (! b.empty ()) {
|
||||
return tl::Variant (db::CplxTrans (shape_dbu (s)) * b);
|
||||
} else {
|
||||
return tl::Variant ();
|
||||
}
|
||||
}
|
||||
|
||||
static tl::Variant get_edge (const db::Shape *s)
|
||||
{
|
||||
db::Shape::edge_type p;
|
||||
|
|
@ -1982,6 +2002,22 @@ Class<db::Shape> decl_Shape ("db", "Shape",
|
|||
"\n"
|
||||
"This method has been added in version 0.25.\n"
|
||||
) +
|
||||
gsi::method_ext ("rectangle", &get_rectangle,
|
||||
"@brief Gets the rectangle if the object represents one or nil if not\n"
|
||||
"\n"
|
||||
"If the shape represents a rectangle - i.e. a box or box polygon, a path with two points and no round ends - "
|
||||
"this method returns the box. If not, nil is returned.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.29."
|
||||
) +
|
||||
gsi::method_ext ("drectangle", &get_drectangle,
|
||||
"@brief Gets the rectangle in micron units if the object represents one or nil if not\n"
|
||||
"\n"
|
||||
"If the shape represents a rectangle - i.e. a box or box polygon, a path with two points and no round ends - "
|
||||
"this method returns the box. If not, nil is returned.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.29."
|
||||
) +
|
||||
gsi::method ("is_user_object?", &db::Shape::is_user_object,
|
||||
"@brief Returns true if the shape is a user defined object\n"
|
||||
) +
|
||||
|
|
|
|||
|
|
@ -436,6 +436,12 @@ Class<db::Texts> decl_Texts (decl_dbShapeCollection, "db", "Texts",
|
|||
"r = RBA::Texts::new(layout.begin_shapes(cell, layer), RBA::ICplxTrans::new(layout.dbu / dbu))\n"
|
||||
"@/code\n"
|
||||
) +
|
||||
method ("write", &db::Texts::write, gsi::arg ("filename"),
|
||||
"@brief Writes the region to a file\n"
|
||||
"This method is provided for debugging purposes. It writes the object to a flat layer 0/0 in a single top cell.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.29."
|
||||
) +
|
||||
method ("insert_into", &db::Texts::insert_into, gsi::arg ("layout"), gsi::arg ("cell_index"), gsi::arg ("layer"),
|
||||
"@brief Inserts this texts into the given layout, below the given cell and into the given layer.\n"
|
||||
"If the text collection is a hierarchical one, a suitable hierarchy will be built below the top cell or "
|
||||
|
|
|
|||
|
|
@ -49,6 +49,17 @@ TEST(2)
|
|||
EXPECT_EQ (b & db::Box (110, 220, 120, 250), empty);
|
||||
EXPECT_EQ (b & db::Box (50, 100, 120, 250), db::Box (50, 100, 100, 200));
|
||||
EXPECT_EQ (b & db::Box (50, 100, 60, 120), db::Box (50, 100, 60, 120));
|
||||
EXPECT_EQ (b - b, db::Box ());
|
||||
EXPECT_EQ (b - db::Box (), b);
|
||||
EXPECT_EQ (db::Box () - b, db::Box ());
|
||||
EXPECT_EQ (db::Box () - db::Box (), db::Box ());
|
||||
EXPECT_EQ (b - db::Box (0, 0, 50, 50), b);
|
||||
EXPECT_EQ (b - db::Box (0, 0, 50, 200), db::Box (50, 0, 100, 200));
|
||||
EXPECT_EQ (b - db::Box (50, 0, 100, 200), db::Box (0, 0, 50, 200));
|
||||
EXPECT_EQ (b - db::Box (0, 0, 100, 100), db::Box (0, 100, 100, 200));
|
||||
EXPECT_EQ (b - db::Box (0, 100, 100, 200), db::Box (0, 0, 100, 100));
|
||||
EXPECT_EQ (db::Box::world () - b, db::Box::world ());
|
||||
EXPECT_EQ (b - db::Box::world (), db::Box ());
|
||||
|
||||
empty.move (db::Vector (10, 20));
|
||||
EXPECT_EQ (empty == db::Box (), true);
|
||||
|
|
|
|||
|
|
@ -1630,20 +1630,6 @@ TEST(12_ForMerged)
|
|||
}
|
||||
|
||||
|
||||
static void write (const db::Region ®ion, const std::string &fn)
|
||||
{
|
||||
db::Layout layout;
|
||||
const db::Cell &top = layout.cell (layout.add_cell ("TOP"));
|
||||
unsigned int li = layout.insert_layer (db::LayerProperties (0, 0));
|
||||
region.insert_into (&layout, top.cell_index (), li);
|
||||
|
||||
tl::OutputStream os (fn);
|
||||
db::SaveLayoutOptions opt;
|
||||
opt.set_format_from_filename (fn);
|
||||
db::Writer writer (opt);
|
||||
writer.write (layout, os);
|
||||
}
|
||||
|
||||
TEST(13_ForMergedPerformance)
|
||||
{
|
||||
test_is_long_runner ();
|
||||
|
|
|
|||
|
|
@ -948,3 +948,89 @@ TEST(9)
|
|||
EXPECT_EQ (si.at_end (), true);
|
||||
}
|
||||
|
||||
// Rectangle
|
||||
TEST(10)
|
||||
{
|
||||
db::Manager m (true);
|
||||
db::Shapes s (&m, 0, db::default_editable_mode ());
|
||||
db::ShapeIterator si;
|
||||
|
||||
s.insert (db::Point (100, 200));
|
||||
si = s.begin (db::ShapeIterator::All);
|
||||
EXPECT_EQ (si->rectangle ().empty (), true);
|
||||
|
||||
s.clear ();
|
||||
s.insert (db::Edge (db::Point (100, 200), db::Point (200, 400)));
|
||||
si = s.begin (db::ShapeIterator::All);
|
||||
EXPECT_EQ (si->rectangle ().empty (), true);
|
||||
|
||||
s.clear ();
|
||||
s.insert (db::EdgePair (db::Edge (db::Point (100, 200), db::Point (200, 400)), db::Edge (db::Point (0, 300), db::Point (100, 500))));
|
||||
si = s.begin (db::ShapeIterator::All);
|
||||
EXPECT_EQ (si->rectangle ().empty (), true);
|
||||
|
||||
s.clear ();
|
||||
s.insert (db::Box (0, 0, 1000, 2000));
|
||||
si = s.begin (db::ShapeIterator::All);
|
||||
EXPECT_EQ (si->rectangle (), db::Box (0, 0, 1000, 2000));
|
||||
|
||||
s.clear ();
|
||||
s.insert (db::ShortBox (0, 0, 1000, 2000));
|
||||
si = s.begin (db::ShapeIterator::All);
|
||||
EXPECT_EQ (si->rectangle (), db::Box (0, 0, 1000, 2000));
|
||||
|
||||
s.clear ();
|
||||
s.insert (db::Polygon (db::Box (0, 0, 1000, 2000)));
|
||||
si = s.begin (db::ShapeIterator::All);
|
||||
EXPECT_EQ (si->rectangle (), db::Box (0, 0, 1000, 2000));
|
||||
|
||||
s.clear ();
|
||||
s.insert (db::Polygon ());
|
||||
si = s.begin (db::ShapeIterator::All);
|
||||
EXPECT_EQ (si->rectangle ().empty (), true);
|
||||
|
||||
s.clear ();
|
||||
s.insert (db::SimplePolygon (db::Box (0, 0, 1000, 2000)));
|
||||
si = s.begin (db::ShapeIterator::All);
|
||||
EXPECT_EQ (si->rectangle (), db::Box (0, 0, 1000, 2000));
|
||||
|
||||
s.clear ();
|
||||
s.insert (db::SimplePolygon ());
|
||||
si = s.begin (db::ShapeIterator::All);
|
||||
EXPECT_EQ (si->rectangle ().empty (), true);
|
||||
|
||||
s.clear ();
|
||||
s.insert (db::Path ());
|
||||
si = s.begin (db::ShapeIterator::All);
|
||||
EXPECT_EQ (si->rectangle ().empty (), true);
|
||||
|
||||
db::Point pts1 [1] = { db::Point (0, 0) };
|
||||
db::Point pts2 [2] = { db::Point (0, 0), db::Point (1000, 0) };
|
||||
db::Point pts2b [2] = { db::Point (0, 0), db::Point (1000, 1000) };
|
||||
db::Point pts3 [3] = { db::Point (0, 0), db::Point (1000, 0), db::Point (1000, 1000) };
|
||||
|
||||
s.clear ();
|
||||
s.insert (db::Path (pts1 + 0, pts1 + 1, 1000, 500, 500));
|
||||
si = s.begin (db::ShapeIterator::All);
|
||||
EXPECT_EQ (si->rectangle (), db::Box (-500, -500, 500, 500));
|
||||
|
||||
s.clear ();
|
||||
s.insert (db::Path (pts2 + 0, pts2 + 2, 1000, 500, 500));
|
||||
si = s.begin (db::ShapeIterator::All);
|
||||
EXPECT_EQ (si->rectangle (), db::Box (-500, -500, 1500, 500));
|
||||
|
||||
s.clear ();
|
||||
s.insert (db::Path (pts2 + 0, pts2 + 2, 1000, 500, 500, true));
|
||||
si = s.begin (db::ShapeIterator::All);
|
||||
EXPECT_EQ (si->rectangle ().empty (), true);
|
||||
|
||||
s.clear ();
|
||||
s.insert (db::Path (pts2b + 0, pts2b + 2, 1000, 500, 500));
|
||||
si = s.begin (db::ShapeIterator::All);
|
||||
EXPECT_EQ (si->rectangle ().empty (), true);
|
||||
|
||||
s.clear ();
|
||||
s.insert (db::Path (pts3 + 0, pts3 + 3, 1000, 500, 500));
|
||||
si = s.begin (db::ShapeIterator::All);
|
||||
EXPECT_EQ (si->rectangle ().empty (), true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -146,6 +146,9 @@ class DBBox_TestClass < TestBase
|
|||
assert_equal( a + b, b )
|
||||
assert_equal( (b + c).to_s, "(1,-10;22,22)" )
|
||||
|
||||
assert_equal( b - a, b )
|
||||
assert_equal( (b - c).to_s, "(1,-1;17,22)" )
|
||||
|
||||
assert_equal( a + RBA::DPoint::new( 1, -5 ), RBA::DBox::new( 1, -5, 1, -5 ) )
|
||||
assert_equal( (b + RBA::DPoint::new( 1, -5 )).to_s, "(1,-5;17,22)" )
|
||||
|
||||
|
|
|
|||
|
|
@ -178,6 +178,7 @@ class DBShapes_TestClass < TestBase
|
|||
assert_equal( arr[0].is_polygon?, false )
|
||||
assert_equal( arr[0].is_box?, true )
|
||||
assert_equal( arr[0].box.to_s, "(10,-10;50,40)" )
|
||||
assert_equal( arr[0].rectangle.to_s, "(10,-10;50,40)" )
|
||||
assert_equal( arr[0].bbox.to_s, "(10,-10;50,40)" )
|
||||
|
||||
# edges
|
||||
|
|
@ -198,6 +199,7 @@ class DBShapes_TestClass < TestBase
|
|||
assert_equal( arr[0].edge.to_s, "(-1,2;5,2)" )
|
||||
assert_equal( arr[0].edge_pair.inspect, "nil" )
|
||||
assert_equal( arr[0].box.inspect, "nil" )
|
||||
assert_equal( arr[0].rectangle.inspect, "nil" )
|
||||
assert_equal( arr[0].path.inspect, "nil" )
|
||||
assert_equal( arr[0].text.inspect, "nil" )
|
||||
assert_equal( arr[0].edge == a, true )
|
||||
|
|
@ -533,6 +535,7 @@ class DBShapes_TestClass < TestBase
|
|||
assert_equal( arr[0].dedge.inspect, "nil" )
|
||||
assert_equal( arr[0].dedge_pair.inspect, "nil" )
|
||||
assert_equal( arr[0].dbox.to_s, "(0.01,-0.01;0.05,0.04)" )
|
||||
assert_equal( arr[0].drectangle.to_s, "(0.01,-0.01;0.05,0.04)" )
|
||||
assert_equal( arr[0].dpath.inspect, "nil" )
|
||||
assert_equal( arr[0].dtext.inspect, "nil" )
|
||||
assert_equal( arr[0].is_polygon?, false )
|
||||
|
|
@ -557,6 +560,7 @@ class DBShapes_TestClass < TestBase
|
|||
assert_equal( arr[0].dedge.to_s, "(-0.001,0.002;0.005,0.002)" )
|
||||
assert_equal( arr[0].dedge_pair.inspect, "nil" )
|
||||
assert_equal( arr[0].dbox.inspect, "nil" )
|
||||
assert_equal( arr[0].drectangle.inspect, "nil" )
|
||||
assert_equal( arr[0].dpath.inspect, "nil" )
|
||||
assert_equal( arr[0].dtext.inspect, "nil" )
|
||||
assert_equal( arr[0].dbbox.to_s, "(-0.001,0.002;0.005,0.002)" )
|
||||
|
|
|
|||
Loading…
Reference in New Issue