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:
Matthias Koefferlein 2024-03-26 21:48:38 +01:00
parent 3fc32e77c3
commit 5699c91d3f
23 changed files with 440 additions and 75 deletions

View File

@ -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
*

View File

@ -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)
{

View File

@ -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
*/

View File

@ -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 ()
{

View File

@ -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

View File

@ -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 &region = 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;
}

View File

@ -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
{

View File

@ -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
*/

View File

@ -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
{

View File

@ -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
*/

View File

@ -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)
{

View File

@ -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
*/

View File

@ -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"

View File

@ -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 "

View File

@ -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"
) +

View File

@ -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."

View File

@ -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"
) +

View File

@ -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 "

View File

@ -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);

View File

@ -1630,20 +1630,6 @@ TEST(12_ForMerged)
}
static void write (const db::Region &region, 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 ();

View File

@ -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);
}

View File

@ -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)" )

View File

@ -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)" )