diff --git a/src/db/db/dbDeepShapeStore.cc b/src/db/db/dbDeepShapeStore.cc index 19f3a7255..4c32c396b 100644 --- a/src/db/db/dbDeepShapeStore.cc +++ b/src/db/db/dbDeepShapeStore.cc @@ -268,6 +268,16 @@ DeepShapeStore::DeepShapeStore () ++s_instance_count; } +DeepShapeStore::DeepShapeStore (const std::string &topcell_name, double dbu) + : m_threads (1), m_max_area_ratio (3.0), m_max_vertex_count (16), m_text_property_name (), m_text_enlargement (-1) +{ + ++s_instance_count; + + m_layouts.push_back (new LayoutHolder (db::ICplxTrans ())); + m_layouts.back ()->layout.dbu (dbu); + m_layouts.back ()->layout.add_cell (topcell_name.c_str ()); +} + DeepShapeStore::~DeepShapeStore () { --s_instance_count; @@ -278,6 +288,33 @@ DeepShapeStore::~DeepShapeStore () m_layouts.clear (); } +DeepLayer DeepShapeStore::create_from_flat (const db::Region ®ion, double max_area_ratio, size_t max_vertex_count, const db::ICplxTrans &trans) +{ + require_singular (); + + unsigned int layer = layout ().insert_layer (); + + if (max_area_ratio == 0.0) { + max_area_ratio = m_max_area_ratio; + } + if (max_vertex_count == 0) { + max_vertex_count = m_max_vertex_count; + } + + db::Shapes *shapes = &initial_cell ().shapes (layer); + db::Box world = db::Box::world (); + + // The chain of operators for producing clipped and reduced polygon references + db::PolygonReferenceHierarchyBuilderShapeReceiver refs (&layout (), m_text_enlargement, m_text_property_name); + db::ReducingHierarchyBuilderShapeReceiver red (&refs, max_area_ratio, max_vertex_count); + + for (db::Region::const_iterator p = region.begin (); ! p.at_end (); ++p) { + red.push (*p, trans, world, 0, shapes); + } + + return DeepLayer (this, 0 /*singular layout index*/, layer); +} + bool DeepShapeStore::is_singular () const { return m_layouts.size () == 1; diff --git a/src/db/db/dbDeepShapeStore.h b/src/db/db/dbDeepShapeStore.h index 1f197d424..d08e47c3f 100644 --- a/src/db/db/dbDeepShapeStore.h +++ b/src/db/db/dbDeepShapeStore.h @@ -232,6 +232,14 @@ public: */ DeepShapeStore (); + /** + * @brief The constructor for a singular DSS + * + * This DSS will be initialized with one layout and the given database unit + * and top level cell name. + */ + DeepShapeStore (const std::string &topcell_name, double dbu); + /** * @brief The destructor */ @@ -251,6 +259,14 @@ public: */ bool is_singular () const; + /** + * @brief Creates a new layer from a flat region (or the region is made flat) + * + * This method is intended for use with singular-created DSS objects (see + * singular constructor). + */ + DeepLayer create_from_flat (const db::Region ®ion, double max_area_ratio = 0.0, size_t max_vertex_count = 0, const db::ICplxTrans &trans = db::ICplxTrans ()); + /** * @brief Inserts a polygon layer into the deep shape store * diff --git a/src/db/db/dbEdgePairsDelegate.h b/src/db/db/dbEdgePairsDelegate.h index d894013b4..c7eb85082 100644 --- a/src/db/db/dbEdgePairsDelegate.h +++ b/src/db/db/dbEdgePairsDelegate.h @@ -27,6 +27,7 @@ #include "dbCommon.h" #include "dbEdgePair.h" +#include "tlUniqueId.h" namespace db { @@ -58,6 +59,7 @@ public: * @brief The delegate for the actual edge set implementation */ class DB_PUBLIC EdgePairsDelegate + : public tl::UniqueId { public: typedef db::Coord coord_type; diff --git a/src/db/db/dbEdgesDelegate.h b/src/db/db/dbEdgesDelegate.h index 5bd4651dd..420e406e1 100644 --- a/src/db/db/dbEdgesDelegate.h +++ b/src/db/db/dbEdgesDelegate.h @@ -29,6 +29,7 @@ #include "dbEdge.h" #include "dbEdgePairs.h" #include "dbEdgePairRelations.h" +#include "tlUniqueId.h" #include @@ -185,6 +186,7 @@ public: * @brief The delegate for the actual edge set implementation */ class DB_PUBLIC EdgesDelegate + : public tl::UniqueId { public: typedef db::Coord coord_type; diff --git a/src/db/db/dbLayoutToNetlist.cc b/src/db/db/dbLayoutToNetlist.cc index bb7bd6549..04dfa6af7 100644 --- a/src/db/db/dbLayoutToNetlist.cc +++ b/src/db/db/dbLayoutToNetlist.cc @@ -38,7 +38,7 @@ static bool is_deep (const db::Region &r) // the iterator provides the hierarchical selection (enabling/disabling cells etc.) LayoutToNetlist::LayoutToNetlist (const db::RecursiveShapeIterator &iter) - : m_iter (iter), m_netlist_extracted (false) + : m_iter (iter), m_netlist_extracted (false), m_is_flat (false) { // check the iterator if (iter.has_complex_region () || iter.region () != db::Box::world ()) { @@ -48,46 +48,68 @@ LayoutToNetlist::LayoutToNetlist (const db::RecursiveShapeIterator &iter) init (); } +LayoutToNetlist::LayoutToNetlist (db::DeepShapeStore *dss, unsigned int layout_index) + : mp_dss (dss), m_netlist_extracted (false), m_is_flat (false) +{ + m_iter = db::RecursiveShapeIterator (dss->layout (layout_index), dss->initial_cell (layout_index), std::set ()); + + init (); +} + +LayoutToNetlist::LayoutToNetlist (const std::string &topcell_name, double dbu) + : m_iter (), m_netlist_extracted (false), m_is_flat (true) +{ + mp_internal_dss.reset (new db::DeepShapeStore (topcell_name, dbu)); + mp_dss.reset (mp_internal_dss.get ()); + + init (); +} + LayoutToNetlist::LayoutToNetlist () - : m_iter (), m_netlist_extracted (false) + : m_iter (), mp_internal_dss (new db::DeepShapeStore ()), mp_dss (mp_internal_dss.get ()), m_netlist_extracted (false), m_is_flat (true) { init (); } void LayoutToNetlist::init () { - m_dss.set_text_enlargement (1); - m_dss.set_text_property_name (tl::Variant ("LABEL")); + if (! mp_dss.get ()) { + mp_internal_dss.reset (new db::DeepShapeStore ()); + mp_dss.reset (mp_internal_dss.get ()); + } + + dss ().set_text_enlargement (1); + dss ().set_text_property_name (tl::Variant ("LABEL")); } void LayoutToNetlist::set_threads (int n) { - m_dss.set_threads (n); + dss ().set_threads (n); } int LayoutToNetlist::threads () const { - return m_dss.threads (); + return dss ().threads (); } void LayoutToNetlist::set_area_ratio (double ar) { - m_dss.set_max_area_ratio (ar); + dss ().set_max_area_ratio (ar); } double LayoutToNetlist::area_ratio () const { - return m_dss.max_area_ratio (); + return dss ().max_area_ratio (); } void LayoutToNetlist::set_max_vertex_count (size_t n) { - m_dss.set_max_vertex_count (n); + dss ().set_max_vertex_count (n); } size_t LayoutToNetlist::max_vertex_count () const { - return m_dss.max_vertex_count (); + return dss ().max_vertex_count (); } db::Region *LayoutToNetlist::make_layer (const std::string &n) @@ -95,7 +117,7 @@ db::Region *LayoutToNetlist::make_layer (const std::string &n) db::RecursiveShapeIterator si (m_iter); si.shape_flags (db::ShapeIterator::Nothing); - std::auto_ptr region (new db::Region (si, m_dss)); + std::auto_ptr region (new db::Region (si, dss ())); if (! n.empty ()) { register_layer (*region, n); } @@ -108,7 +130,7 @@ db::Region *LayoutToNetlist::make_layer (unsigned int layer_index, const std::st si.set_layer (layer_index); si.shape_flags (db::ShapeIterator::All); - std::auto_ptr region (new db::Region (si, m_dss)); + std::auto_ptr region (new db::Region (si, dss ())); if (! n.empty ()) { register_layer (*region, n); } @@ -121,7 +143,7 @@ db::Region *LayoutToNetlist::make_text_layer (unsigned int layer_index, const st si.set_layer (layer_index); si.shape_flags (db::ShapeIterator::Texts); - std::auto_ptr region (new db::Region (si, m_dss)); + std::auto_ptr region (new db::Region (si, dss ())); if (! n.empty ()) { register_layer (*region, n); } @@ -134,7 +156,7 @@ db::Region *LayoutToNetlist::make_polygon_layer (unsigned int layer_index, const si.set_layer (layer_index); si.shape_flags (db::ShapeIterator::Paths | db::ShapeIterator::Polygons | db::ShapeIterator::Boxes); - std::auto_ptr region (new db::Region (si, m_dss)); + std::auto_ptr region (new db::Region (si, dss ())); if (! n.empty ()) { register_layer (*region, n); } @@ -149,7 +171,7 @@ void LayoutToNetlist::extract_devices (db::NetlistDeviceExtractor &extractor, co if (! mp_netlist.get ()) { mp_netlist.reset (new db::Netlist ()); } - extractor.extract(m_dss, layers, *mp_netlist, m_net_clusters); + extractor.extract(dss (), layers, *mp_netlist, m_net_clusters); } void LayoutToNetlist::connect (const db::Region &l) @@ -236,7 +258,7 @@ void LayoutToNetlist::extract_netlist (bool join_nets_by_label) } db::NetlistExtractor netex; - netex.extract_nets(m_dss, m_conn, *mp_netlist, m_net_clusters, join_nets_by_label); + netex.extract_nets(dss (), m_conn, *mp_netlist, m_net_clusters, join_nets_by_label); m_netlist_extracted = true; } @@ -248,30 +270,30 @@ void LayoutToNetlist::set_netlist_extracted () const db::Layout *LayoutToNetlist::internal_layout () const { - return &m_dss.const_layout (); + return &dss ().const_layout (); } const db::Cell *LayoutToNetlist::internal_top_cell () const { - return &m_dss.const_initial_cell (); + return &dss ().const_initial_cell (); } void LayoutToNetlist::ensure_internal_layout () { - if (m_dss.layouts () == 0) { + if (dss ().layouts () == 0) { // the dummy layer acts as a reference holder for the layout - m_dummy_layer = m_dss.create_polygon_layer (db::RecursiveShapeIterator ()); + m_dummy_layer = dss ().create_polygon_layer (db::RecursiveShapeIterator ()); } } db::Layout *LayoutToNetlist::internal_layout () { - return &m_dss.layout (); + return &dss ().layout (); } db::Cell *LayoutToNetlist::internal_top_cell () { - return &m_dss.initial_cell (); + return &dss ().initial_cell (); } void LayoutToNetlist::register_layer (const db::Region ®ion, const std::string &n) @@ -280,18 +302,38 @@ void LayoutToNetlist::register_layer (const db::Region ®ion, const std::strin throw tl::Exception (tl::to_string (tr ("Layer name is already used: ")) + n); } - db::DeepRegion *delegate = dynamic_cast (region.delegate()); - if (! delegate) { - throw tl::Exception (tl::to_string (tr ("Layer is not a deep region"))); + db::DeepLayer dl; + + if (m_is_flat) { + + dl = dss ().create_from_flat (region); + + } else { + + db::DeepRegion *delegate = dynamic_cast (region.delegate()); + if (! delegate) { + + if (region.empty ()) { + dl = dss ().empty_layer (); + } else { + throw tl::Exception (tl::to_string (tr ("Layer is not a deep region"))); + } + + } else { + + if (is_persisted (region)) { + std::string prev_name = name (region); + m_named_regions.erase (prev_name); + } + + dl = delegate->deep_layer (); + + } + } - if (is_persisted (region)) { - std::string prev_name = name (region); - m_named_regions.erase (prev_name); - } - - m_named_regions [n] = delegate->deep_layer (); - m_name_of_layer [layer_of (region)] = n; + m_named_regions [n] = dl; + m_name_of_layer [dl.layer ()] = n; } std::string LayoutToNetlist::name (const db::Region ®ion) const @@ -359,7 +401,7 @@ db::CellMapping LayoutToNetlist::cell_mapping_into (db::Layout &layout, db::Cell } } - return m_dss.cell_mapping_to_original (layout_index, &layout, cell.cell_index (), &device_cells); + return dss ().cell_mapping_to_original (layout_index, &layout, cell.cell_index (), &device_cells); } db::CellMapping LayoutToNetlist::const_cell_mapping_into (const db::Layout &layout, const db::Cell &cell) diff --git a/src/db/db/dbLayoutToNetlist.h b/src/db/db/dbLayoutToNetlist.h index 30a46063d..3c57b9c7a 100644 --- a/src/db/db/dbLayoutToNetlist.h +++ b/src/db/db/dbLayoutToNetlist.h @@ -82,6 +82,28 @@ public: */ LayoutToNetlist (const db::RecursiveShapeIterator &iter); + /** + * @brief Alternative constructor using an external deep shape storage + * + * This constructor allows using an external DSS. It's intended to be used + * with existing DSS instances. Existing layers can be registered with + * "register_layer". The LayoutToNetlist object will hold a weak reference + * to the DSS but not own the DSS. + * + * NOTE: if using make_layer, these new layers will be created in the DSS + * given in this constructor. + */ + LayoutToNetlist (db::DeepShapeStore *dss, unsigned int layout_index); + + /** + * @brief Alternative constructor for flat mode + * + * In flat mode, the internal DSS will be initialized to a top-level only + * layout. All layers entered through "register_layer" or created with + * "make_layer" will become flat ones. + */ + LayoutToNetlist (const std::string &topcell_name, double dbu); + /** * @brief The default constructor */ @@ -467,7 +489,8 @@ private: LayoutToNetlist &operator= (const db::LayoutToNetlist &other); db::RecursiveShapeIterator m_iter; - db::DeepShapeStore m_dss; + std::auto_ptr mp_internal_dss; + tl::weak_ptr mp_dss; db::Connectivity m_conn; db::hier_clusters m_net_clusters; std::auto_ptr mp_netlist; @@ -475,8 +498,21 @@ private: std::map m_named_regions; std::map m_name_of_layer; bool m_netlist_extracted; + bool m_is_flat; db::DeepLayer m_dummy_layer; + db::DeepShapeStore &dss () + { + tl_assert (mp_dss.get () != 0); + return *mp_dss; + } + + const db::DeepShapeStore &dss () const + { + tl_assert (mp_dss.get () != 0); + return *mp_dss; + } + void init (); size_t search_net (const db::ICplxTrans &trans, const db::Cell *cell, const db::local_cluster &test_cluster, std::vector &rev_inst_path); void build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map &lmap, const char *net_cell_name_prefix, const char *cell_name_prefix, const char *device_cell_name_prefix, std::map, db::cell_index_type> &cmap, const ICplxTrans &tr) const; diff --git a/src/db/db/dbRegionDelegate.h b/src/db/db/dbRegionDelegate.h index fbeb35198..f5eb945d7 100644 --- a/src/db/db/dbRegionDelegate.h +++ b/src/db/db/dbRegionDelegate.h @@ -30,6 +30,7 @@ #include "dbEdges.h" #include "dbEdgePairs.h" #include "dbEdgePairRelations.h" +#include "tlUniqueId.h" #include @@ -181,6 +182,7 @@ public: * @brief The delegate for the actual region implementation */ class DB_PUBLIC RegionDelegate + : public tl::UniqueId { public: typedef db::Coord coord_type; diff --git a/src/db/db/gsiDeclDbDeepShapeStore.cc b/src/db/db/gsiDeclDbDeepShapeStore.cc index 77ac2fc30..471c6fe67 100644 --- a/src/db/db/gsiDeclDbDeepShapeStore.cc +++ b/src/db/db/gsiDeclDbDeepShapeStore.cc @@ -30,6 +30,13 @@ Class decl_dbDeepShapeStore ("db", "DeepShapeStore", gsi::method ("instance_count", &db::DeepShapeStore::instance_count, "@hide\n" ) + + gsi::method ("is_singular?", &db::DeepShapeStore::is_singular, + "@brief Gets a value indicating whether there is a single layout variant\n" + "\n" + "Specifically for network extraction, singular DSS objects are required. " + "Multiple layouts may be present if different sources of layouts have " + "been used. Such DSS objects are not usable for network extraction." + ) + gsi::method ("threads=", &db::DeepShapeStore::set_threads, gsi::arg ("n"), "@brief Sets the number of threads to allocate for the hierarchical processor\n" ) + diff --git a/src/db/db/gsiDeclDbEdgePairs.cc b/src/db/db/gsiDeclDbEdgePairs.cc index 62e20011e..6bef742c6 100644 --- a/src/db/db/gsiDeclDbEdgePairs.cc +++ b/src/db/db/gsiDeclDbEdgePairs.cc @@ -174,6 +174,11 @@ static bool is_deep (const db::EdgePairs *ep) return dynamic_cast (ep->delegate ()) != 0; } +static size_t id (const db::EdgePairs *ep) +{ + return tl::id_of (ep->delegate ()); +} + Class decl_EdgePairs ("db", "EdgePairs", constructor ("new", &new_v, "@brief Default constructor\n" @@ -312,6 +317,11 @@ Class decl_EdgePairs ("db", "EdgePairs", "\n" "This method has been added in version 0.26." ) + + method_ext ("data_id", &id, + "@brief Returns the data ID (a unique identifier for the underlying data storage)\n" + "\n" + "This method has been added in version 0.26." + ) + method ("+", &db::EdgePairs::operator+, "@brief Returns the combined edge pair collection of self and the other one\n" "\n" diff --git a/src/db/db/gsiDeclDbEdges.cc b/src/db/db/gsiDeclDbEdges.cc index 1cf48d1cf..39163911a 100644 --- a/src/db/db/gsiDeclDbEdges.cc +++ b/src/db/db/gsiDeclDbEdges.cc @@ -400,6 +400,10 @@ static db::Edges *new_texts_as_dots2 (const db::RecursiveShapeIterator &si, db:: return new db::Edges (db::OriginalLayerRegion (si, false).texts_as_dots (pat, pattern, dss)); } +static size_t id (const db::Edges *e) +{ + return tl::id_of (e->delegate ()); +} Class dec_Edges ("db", "Edges", constructor ("new", &new_v, @@ -1466,6 +1470,11 @@ Class dec_Edges ("db", "Edges", "\n" "This method has been added in version 0.26." ) + + method_ext ("data_id", &id, + "@brief Returns the data ID (a unique identifier for the underlying data storage)\n" + "\n" + "This method has been added in version 0.26." + ) + method ("is_merged?", &db::Edges::is_merged, "@brief Returns true if the edge collection is merged\n" "If the region is merged, coincident edges have been merged into single edges. You can ensure merged state " diff --git a/src/db/db/gsiDeclDbLayoutToNetlist.cc b/src/db/db/gsiDeclDbLayoutToNetlist.cc index 153b6601b..37dc8650f 100644 --- a/src/db/db/gsiDeclDbLayoutToNetlist.cc +++ b/src/db/db/gsiDeclDbLayoutToNetlist.cc @@ -39,6 +39,16 @@ static db::LayoutToNetlist *make_l2n_default () return new db::LayoutToNetlist (); } +static db::LayoutToNetlist *make_l2n_from_existing_dss (db::DeepShapeStore *dss, unsigned int layout_index) +{ + return new db::LayoutToNetlist (dss, layout_index); +} + +static db::LayoutToNetlist *make_l2n_flat (const std::string &topcell_name, double dbu) +{ + return new db::LayoutToNetlist (topcell_name, dbu); +} + static db::Layout *l2n_internal_layout (db::LayoutToNetlist *l2n) { // although this isn't very clean, we dare to do so as const references are pretty useless in script languages. @@ -99,6 +109,24 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist", "@brief Creates a new and empty extractor object\n" "The main objective for this constructor is to create an object suitable for reading an annotated netlist.\n" ) + + gsi::constructor ("new", &make_l2n_from_existing_dss, gsi::arg ("dss"), gsi::arg ("layout_index", 0), + "@brief Creates a new extractor object reusing an existing \\DeepShapeStore object\n" + "This constrcutor can be used if there is a DSS object already from which the " + "shapes can be taken. NOTE: in this case, the make_... functions will create " + "new layers inside this DSS. To register existing layers (regions) use \\register.\n" + ) + + gsi::constructor ("new", &make_l2n_flat, gsi::arg ("topcell_name"), gsi::arg ("dbu"), + "@brief Creates a new extractor object with a flat DSS\n" + "@param topcell_name The name of the top cell of the internal flat layout\n" + "@param dbu The database unit to use for the internal flat layout\n" + "\n" + "This constructor will create an extractor for flat extraction. Layers registered " + "with \\register will be flattened. New layers created with make_... will be flat " + "layers.\n" + "\n" + "The database unit is mandatory because the physical parameter extraction " + "for devices requires this unit for translation of layout to physical dimensions.\n" + ) + gsi::method ("threads=", &db::LayoutToNetlist::set_threads, gsi::arg ("n"), "@brief Sets the number of threads to use for operations which support multiple threads\n" ) + @@ -382,6 +410,10 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist", " finding a net by probing a specific location.\n" "@li\n" "\n" + "Another use model is using the extractor with an existing \\DeepShapeStore object " + "or even flat data. In this case, the preparation step is importing by " + "taking existing region data using the \\register method.\n" + "\n" "This class has been introduced in version 0.26." ); diff --git a/src/db/db/gsiDeclDbRegion.cc b/src/db/db/gsiDeclDbRegion.cc index e55c1ba9d..78f7e41e4 100644 --- a/src/db/db/gsiDeclDbRegion.cc +++ b/src/db/db/gsiDeclDbRegion.cc @@ -600,6 +600,11 @@ static bool is_deep (const db::Region *region) return dynamic_cast (region->delegate ()) != 0; } +static size_t id (const db::Region *r) +{ + return tl::id_of (r->delegate ()); +} + // provided by gsiDeclDbPolygon.cc: int td_simple (); int po_any (); @@ -2231,6 +2236,11 @@ Class decl_Region ("db", "Region", "\n" "This method has been added in version 0.26." ) + + method_ext ("data_id", &id, + "@brief Returns the data ID (a unique identifier for the underlying data storage)\n" + "\n" + "This method has been added in version 0.26." + ) + method ("is_merged?", &db::Region::is_merged, "@brief Returns true if the region is merged\n" "If the region is merged, polygons will not touch or overlap. You can ensure merged state " diff --git a/testdata/ruby/dbEdgePairsTest.rb b/testdata/ruby/dbEdgePairsTest.rb index ba029ec51..5df2cc5f1 100644 --- a/testdata/ruby/dbEdgePairsTest.rb +++ b/testdata/ruby/dbEdgePairsTest.rb @@ -33,8 +33,10 @@ class DBEdgePairs_TestClass < TestBase assert_equal(r.is_empty?, true) assert_equal(r.size, 0) assert_equal(r.bbox.to_s, "()") + data_id = r.data_id r.insert(RBA::Edge::new(0, 0, 0, 100), RBA::Edge::new(-10, 0, -20, 50)) + assert_equal(data_id != r.data_id, true) assert_equal(r.to_s, "(0,0;0,100)/(-10,0;-20,50)") r.clear @@ -55,6 +57,7 @@ class DBEdgePairs_TestClass < TestBase assert_equal(r.moved(-10, 10).to_s, "(-10,10;-10,110)/(-20,10;-30,60)") assert_equal(r.moved(RBA::Point::new(-10, 10)).to_s, "(-10,10;-10,110)/(-20,10;-30,60)") rr = r.dup + assert_equal(rr.data_id != r.data_id, true) rr.move(-10, 10) assert_equal(rr.to_s, "(-10,10;-10,110)/(-20,10;-30,60)") rr = r.dup diff --git a/testdata/ruby/dbEdgesTest.rb b/testdata/ruby/dbEdgesTest.rb index 52e3c9062..9b3435200 100644 --- a/testdata/ruby/dbEdgesTest.rb +++ b/testdata/ruby/dbEdgesTest.rb @@ -34,8 +34,10 @@ class DBEdges_TestClass < TestBase assert_equal(r.size, 0) assert_equal(r.bbox.to_s, "()") assert_equal(r.is_merged?, true) + data_id = r.data_id r.assign(RBA::Edges::new([RBA::Edge::new(10, 20, 100, 200)])) + assert_equal(data_id != r.data_id, true) assert_equal(r.to_s, "(10,20;100,200)") assert_equal(r.is_empty?, false) assert_equal(r.size, 1) @@ -72,6 +74,7 @@ class DBEdges_TestClass < TestBase assert_equal(r.moved(RBA::Point::new(10, 20)).bbox.to_s, "(20,40;110,220)") assert_equal(r.moved(10, 20).bbox.to_s, "(20,40;110,220)") rr = r.dup + assert_equal(rr.data_id != r.data_id, true) rr.move(RBA::Point::new(10, 20)) assert_equal(rr.bbox.to_s, "(20,40;110,220)") rr = r.dup diff --git a/testdata/ruby/dbRegionTest.rb b/testdata/ruby/dbRegionTest.rb index ec04f7d2d..92f10f144 100644 --- a/testdata/ruby/dbRegionTest.rb +++ b/testdata/ruby/dbRegionTest.rb @@ -35,8 +35,10 @@ class DBRegion_TestClass < TestBase assert_equal(r.bbox.to_s, "()") assert_equal(r.is_merged?, true) assert_equal(r.is_box?, false) + data_id = r.data_id r.assign(RBA::Region::new(RBA::Box::new(10, 20, 100, 200))) + assert_equal(data_id != r.data_id, true) assert_equal(r.to_s, "(10,20;10,200;100,200;100,20)") assert_equal(r.is_empty?, false) assert_equal(r.size, 1) @@ -48,6 +50,7 @@ class DBRegion_TestClass < TestBase assert_equal(r.moved(RBA::Point::new(10, 20)).bbox.to_s, "(20,40;110,220)") assert_equal(r.moved(10, 20).bbox.to_s, "(20,40;110,220)") rr = r.dup + assert_equal(rr.data_id != r.data_id, true) rr.move(RBA::Point::new(10, 20)) assert_equal(rr.bbox.to_s, "(20,40;110,220)") rr = r.dup