diff --git a/src/db/db/dbDeepEdgePairs.cc b/src/db/db/dbDeepEdgePairs.cc index 7593067c9..41938c618 100644 --- a/src/db/db/dbDeepEdgePairs.cc +++ b/src/db/db/dbDeepEdgePairs.cc @@ -311,6 +311,11 @@ const db::EdgePair *DeepEdgePairs::nth (size_t) const throw tl::Exception (tl::to_string (tr ("Random access to edge pairs is available only for flat edge pair collections"))); } +db::properties_id_type DeepEdgePairs::nth_prop_id (size_t) const +{ + throw tl::Exception (tl::to_string (tr ("Random access to edge pairs is available only for flat edge pair collections"))); +} + bool DeepEdgePairs::has_valid_edge_pairs () const { return false; diff --git a/src/db/db/dbDeepEdgePairs.h b/src/db/db/dbDeepEdgePairs.h index c55e7f97f..7ed036d6e 100644 --- a/src/db/db/dbDeepEdgePairs.h +++ b/src/db/db/dbDeepEdgePairs.h @@ -70,6 +70,7 @@ public: virtual Box bbox () const; virtual bool empty () const; virtual const db::EdgePair *nth (size_t n) const; + virtual db::properties_id_type nth_prop_id (size_t n) const; virtual bool has_valid_edge_pairs () const; virtual const db::RecursiveShapeIterator *iter () const; virtual void apply_property_translator (const db::PropertiesTranslator &pt); diff --git a/src/db/db/dbDeepEdges.cc b/src/db/db/dbDeepEdges.cc index bd80f7ac9..3872386fe 100644 --- a/src/db/db/dbDeepEdges.cc +++ b/src/db/db/dbDeepEdges.cc @@ -438,6 +438,12 @@ DeepEdges::nth (size_t /*n*/) const throw tl::Exception (tl::to_string (tr ("Random access to edges is available only for flat edge collections"))); } +db::properties_id_type +DeepEdges::nth_prop_id (size_t) const +{ + throw tl::Exception (tl::to_string (tr ("Random access to edges is available only for flat collections"))); +} + bool DeepEdges::has_valid_edges () const { diff --git a/src/db/db/dbDeepEdges.h b/src/db/db/dbDeepEdges.h index 6af2bf55a..b8cf9fc2e 100644 --- a/src/db/db/dbDeepEdges.h +++ b/src/db/db/dbDeepEdges.h @@ -76,6 +76,7 @@ public: virtual bool is_merged () const; virtual const db::Edge *nth (size_t n) const; + virtual db::properties_id_type nth_prop_id (size_t n) const; virtual bool has_valid_edges () const; virtual bool has_valid_merged_edges () const; diff --git a/src/db/db/dbDeepTexts.cc b/src/db/db/dbDeepTexts.cc index e272e25ca..d15bb3601 100644 --- a/src/db/db/dbDeepTexts.cc +++ b/src/db/db/dbDeepTexts.cc @@ -332,6 +332,12 @@ const db::Text *DeepTexts::nth (size_t) const throw tl::Exception (tl::to_string (tr ("Random access to texts is available only for flat text collections"))); } +db::properties_id_type +DeepTexts::nth_prop_id (size_t) const +{ + throw tl::Exception (tl::to_string (tr ("Random access to texts is available only for flat collections"))); +} + bool DeepTexts::has_valid_texts () const { return false; diff --git a/src/db/db/dbDeepTexts.h b/src/db/db/dbDeepTexts.h index 7425df7cd..0c9a6eabb 100644 --- a/src/db/db/dbDeepTexts.h +++ b/src/db/db/dbDeepTexts.h @@ -71,6 +71,7 @@ public: virtual Box bbox () const; virtual bool empty () const; virtual const db::Text *nth (size_t n) const; + virtual db::properties_id_type nth_prop_id (size_t n) const; virtual bool has_valid_texts () const; virtual const db::RecursiveShapeIterator *iter () const; virtual void apply_property_translator (const db::PropertiesTranslator &pt); diff --git a/src/db/db/dbEdgePairs.h b/src/db/db/dbEdgePairs.h index 271777473..0cffe8960 100644 --- a/src/db/db/dbEdgePairs.h +++ b/src/db/db/dbEdgePairs.h @@ -678,7 +678,7 @@ public: /** * @brief Returns the nth edge pair * - * This operation is available only for flat regions - i.e. such for which + * This operation is available only for flat edge pair collections - i.e. such for which * "has_valid_edge_pairs" is true. */ const db::EdgePair *nth (size_t n) const @@ -686,6 +686,17 @@ public: return mp_delegate->nth (n); } + /** + * @brief Returns the nth edge pair's property ID + * + * This operation is available only for flat edge pair collections - i.e. such for which + * "has_valid_edge_pairs" is true. + */ + db::properties_id_type nth_prop_id (size_t n) const + { + return mp_delegate->nth_prop_id (n); + } + /** * @brief Forces flattening of the edge pair collection * diff --git a/src/db/db/dbEdgePairsDelegate.h b/src/db/db/dbEdgePairsDelegate.h index d8dd18849..d4a1efd97 100644 --- a/src/db/db/dbEdgePairsDelegate.h +++ b/src/db/db/dbEdgePairsDelegate.h @@ -273,6 +273,7 @@ public: virtual EdgePairsDelegate *in (const EdgePairs &other, bool invert) const = 0; virtual const db::EdgePair *nth (size_t n) const = 0; + virtual db::properties_id_type nth_prop_id (size_t n) const = 0; virtual bool has_valid_edge_pairs () const = 0; virtual const db::RecursiveShapeIterator *iter () const = 0; diff --git a/src/db/db/dbEdges.h b/src/db/db/dbEdges.h index 6b507048a..31bdc35af 100644 --- a/src/db/db/dbEdges.h +++ b/src/db/db/dbEdges.h @@ -1440,13 +1440,24 @@ public: /** * @brief Returns the nth edge * - * This operation is available only for flat regions - i.e. such for which "has_valid_edges" is true. + * This operation is available only for flat edge collections - i.e. such for which "has_valid_edges" is true. */ const db::Edge *nth (size_t n) const { return mp_delegate->nth (n); } + /** + * @brief Returns the nth edge's property ID + * + * This operation is available only for flat edge collections - i.e. such for which + * "has_valid_edges" is true. + */ + db::properties_id_type nth_prop_id (size_t n) const + { + return mp_delegate->nth_prop_id (n); + } + /** * @brief Forces flattening of the edge collection * diff --git a/src/db/db/dbEdgesDelegate.h b/src/db/db/dbEdgesDelegate.h index 496b86931..91aea92ee 100644 --- a/src/db/db/dbEdgesDelegate.h +++ b/src/db/db/dbEdgesDelegate.h @@ -280,6 +280,7 @@ public: virtual std::pair in_and_out (const Edges &) const = 0; virtual const db::Edge *nth (size_t n) const = 0; + virtual db::properties_id_type nth_prop_id (size_t n) const = 0; virtual bool has_valid_edges () const = 0; virtual bool has_valid_merged_edges () const = 0; diff --git a/src/db/db/dbEmptyEdgePairs.h b/src/db/db/dbEmptyEdgePairs.h index f63cfd1a8..92650b923 100644 --- a/src/db/db/dbEmptyEdgePairs.h +++ b/src/db/db/dbEmptyEdgePairs.h @@ -89,6 +89,7 @@ public: virtual EdgePairsDelegate *in (const EdgePairs &, bool) const { return new EmptyEdgePairs (); } virtual const db::EdgePair *nth (size_t) const { tl_assert (false); } + virtual db::properties_id_type nth_prop_id (size_t) const { tl_assert (false); } virtual bool has_valid_edge_pairs () const { return true; } virtual const db::RecursiveShapeIterator *iter () const { return 0; } diff --git a/src/db/db/dbEmptyEdges.h b/src/db/db/dbEmptyEdges.h index 84032b448..bf45753cd 100644 --- a/src/db/db/dbEmptyEdges.h +++ b/src/db/db/dbEmptyEdges.h @@ -119,6 +119,7 @@ public: virtual std::pair in_and_out (const Edges &) const { return std::make_pair (new EmptyEdges (), new EmptyEdges ()); } virtual const db::Edge *nth (size_t) const { tl_assert (false); } + virtual db::properties_id_type nth_prop_id (size_t) const { tl_assert (false); } virtual bool has_valid_edges () const { return true; } virtual bool has_valid_merged_edges () const { return true; } diff --git a/src/db/db/dbEmptyTexts.h b/src/db/db/dbEmptyTexts.h index 37cdd6725..202a72399 100644 --- a/src/db/db/dbEmptyTexts.h +++ b/src/db/db/dbEmptyTexts.h @@ -71,6 +71,7 @@ public: virtual TextsDelegate *in (const Texts &, bool) const { return new EmptyTexts (); } virtual const db::Text *nth (size_t) const { tl_assert (false); } + virtual db::properties_id_type nth_prop_id (size_t) const { tl_assert (false); } virtual bool has_valid_texts () const { return true; } virtual const db::RecursiveShapeIterator *iter () const { return 0; } diff --git a/src/db/db/dbFlatEdgePairs.cc b/src/db/db/dbFlatEdgePairs.cc index cb554a3ea..a42bce475 100644 --- a/src/db/db/dbFlatEdgePairs.cc +++ b/src/db/db/dbFlatEdgePairs.cc @@ -173,7 +173,46 @@ EdgePairsDelegate *FlatEdgePairs::add_in_place (const EdgePairs &other) const db::EdgePair *FlatEdgePairs::nth (size_t n) const { - return n < mp_edge_pairs->size () ? &mp_edge_pairs->get_layer ().begin () [n] : 0; + // NOTE: this assumes that we iterate over non-property edge pairs first and then over edges with properties + + if (n >= mp_edge_pairs->size ()) { + return 0; + } + + const db::layer &l = mp_edge_pairs->get_layer (); + if (n < l.size ()) { + return &l.begin () [n]; + } + n -= l.size (); + + const db::layer &lp = mp_edge_pairs->get_layer (); + if (n < lp.size ()) { + return &lp.begin () [n]; + } + + return 0; +} + +db::properties_id_type FlatEdgePairs::nth_prop_id (size_t n) const +{ + // NOTE: this assumes that we iterate over non-property edge pairs first and then over edges with properties + + if (n >= mp_edge_pairs->size ()) { + return 0; + } + + const db::layer &l = mp_edge_pairs->get_layer (); + if (n < l.size ()) { + return 0; + } + n -= l.size (); + + const db::layer &lp = mp_edge_pairs->get_layer (); + if (n < lp.size ()) { + return lp.begin () [n].properties_id (); + } + + return 0; } bool FlatEdgePairs::has_valid_edge_pairs () const diff --git a/src/db/db/dbFlatEdgePairs.h b/src/db/db/dbFlatEdgePairs.h index dc38dc088..ce203c4aa 100644 --- a/src/db/db/dbFlatEdgePairs.h +++ b/src/db/db/dbFlatEdgePairs.h @@ -75,6 +75,7 @@ public: virtual EdgePairsDelegate *add (const EdgePairs &other) const; virtual const db::EdgePair *nth (size_t n) const; + virtual db::properties_id_type nth_prop_id (size_t n) const; virtual bool has_valid_edge_pairs () const; virtual const db::RecursiveShapeIterator *iter () const; diff --git a/src/db/db/dbFlatEdges.cc b/src/db/db/dbFlatEdges.cc index 44299bc8c..27e323cae 100644 --- a/src/db/db/dbFlatEdges.cc +++ b/src/db/db/dbFlatEdges.cc @@ -361,7 +361,46 @@ EdgesDelegate *FlatEdges::add_in_place (const Edges &other) const db::Edge *FlatEdges::nth (size_t n) const { - return n < mp_edges->size () ? &mp_edges->get_layer ().begin () [n] : 0; + // NOTE: this assumes that we iterate over non-property edges first and then over edges with properties + + if (n >= mp_edges->size ()) { + return 0; + } + + const db::layer &l = mp_edges->get_layer (); + if (n < l.size ()) { + return &l.begin () [n]; + } + n -= l.size (); + + const db::layer &lp = mp_edges->get_layer (); + if (n < lp.size ()) { + return &lp.begin () [n]; + } + + return 0; +} + +db::properties_id_type FlatEdges::nth_prop_id (size_t n) const +{ + // NOTE: this assumes that we iterate over non-property polygons first and then over polygons with properties + + if (n >= mp_edges->size ()) { + return 0; + } + + const db::layer &l = mp_edges->get_layer (); + if (n < l.size ()) { + return 0; + } + n -= l.size (); + + const db::layer &lp = mp_edges->get_layer (); + if (n < lp.size ()) { + return lp.begin () [n].properties_id (); + } + + return 0; } bool FlatEdges::has_valid_edges () const diff --git a/src/db/db/dbFlatEdges.h b/src/db/db/dbFlatEdges.h index f5464be30..551c33ce4 100644 --- a/src/db/db/dbFlatEdges.h +++ b/src/db/db/dbFlatEdges.h @@ -89,6 +89,7 @@ public: virtual EdgesDelegate *add (const Edges &other) const; virtual const db::Edge *nth (size_t n) const; + virtual db::properties_id_type nth_prop_id (size_t n) const; virtual bool has_valid_edges () const; virtual bool has_valid_merged_edges () const; diff --git a/src/db/db/dbFlatTexts.cc b/src/db/db/dbFlatTexts.cc index e2e0e54a2..ef6dda20d 100644 --- a/src/db/db/dbFlatTexts.cc +++ b/src/db/db/dbFlatTexts.cc @@ -171,7 +171,46 @@ TextsDelegate *FlatTexts::add_in_place (const Texts &other) const db::Text *FlatTexts::nth (size_t n) const { - return n < mp_texts->size () ? &mp_texts->get_layer ().begin () [n] : 0; + // NOTE: this assumes that we iterate over non-property texts first and then over texts with properties + + if (n >= mp_texts->size ()) { + return 0; + } + + const db::layer &l = mp_texts->get_layer (); + if (n < l.size ()) { + return &l.begin () [n]; + } + n -= l.size (); + + const db::layer &lp = mp_texts->get_layer (); + if (n < lp.size ()) { + return &lp.begin () [n]; + } + + return 0; +} + +db::properties_id_type FlatTexts::nth_prop_id (size_t n) const +{ + // NOTE: this assumes that we iterate over non-property polygons first and then over polygons with properties + + if (n >= mp_texts->size ()) { + return 0; + } + + const db::layer &l = mp_texts->get_layer (); + if (n < l.size ()) { + return 0; + } + n -= l.size (); + + const db::layer &lp = mp_texts->get_layer (); + if (n < lp.size ()) { + return lp.begin () [n].properties_id (); + } + + return 0; } bool FlatTexts::has_valid_texts () const diff --git a/src/db/db/dbFlatTexts.h b/src/db/db/dbFlatTexts.h index f7e5ff16c..553dd58d5 100644 --- a/src/db/db/dbFlatTexts.h +++ b/src/db/db/dbFlatTexts.h @@ -76,6 +76,7 @@ public: virtual TextsDelegate *add (const Texts &other) const; virtual const db::Text *nth (size_t n) const; + virtual db::properties_id_type nth_prop_id (size_t n) const; virtual bool has_valid_texts () const; virtual const db::RecursiveShapeIterator *iter () const; diff --git a/src/db/db/dbOriginalLayerEdgePairs.cc b/src/db/db/dbOriginalLayerEdgePairs.cc index 301208ebc..5038a1885 100644 --- a/src/db/db/dbOriginalLayerEdgePairs.cc +++ b/src/db/db/dbOriginalLayerEdgePairs.cc @@ -190,6 +190,12 @@ OriginalLayerEdgePairs::nth (size_t) const throw tl::Exception (tl::to_string (tr ("Random access to edge pairs is available only for flat collections"))); } +db::properties_id_type +OriginalLayerEdgePairs::nth_prop_id (size_t) const +{ + throw tl::Exception (tl::to_string (tr ("Random access to edge pairs is available only for flat collections"))); +} + bool OriginalLayerEdgePairs::has_valid_edge_pairs () const { diff --git a/src/db/db/dbOriginalLayerEdgePairs.h b/src/db/db/dbOriginalLayerEdgePairs.h index bcecf1f7c..41000da51 100644 --- a/src/db/db/dbOriginalLayerEdgePairs.h +++ b/src/db/db/dbOriginalLayerEdgePairs.h @@ -53,6 +53,7 @@ public: virtual bool empty () const; virtual const db::EdgePair *nth (size_t n) const; + virtual db::properties_id_type nth_prop_id (size_t n) const; virtual bool has_valid_edge_pairs () const; virtual const db::RecursiveShapeIterator *iter () const; diff --git a/src/db/db/dbOriginalLayerEdges.cc b/src/db/db/dbOriginalLayerEdges.cc index a01314308..3484b926e 100644 --- a/src/db/db/dbOriginalLayerEdges.cc +++ b/src/db/db/dbOriginalLayerEdges.cc @@ -233,6 +233,12 @@ OriginalLayerEdges::nth (size_t) const throw tl::Exception (tl::to_string (tr ("Random access to edges is available only for flat collections"))); } +db::properties_id_type +OriginalLayerEdges::nth_prop_id (size_t) const +{ + throw tl::Exception (tl::to_string (tr ("Random access to edges is available only for flat collections"))); +} + bool OriginalLayerEdges::has_valid_edges () const { diff --git a/src/db/db/dbOriginalLayerEdges.h b/src/db/db/dbOriginalLayerEdges.h index 89d6fc647..53254e852 100644 --- a/src/db/db/dbOriginalLayerEdges.h +++ b/src/db/db/dbOriginalLayerEdges.h @@ -58,6 +58,7 @@ public: virtual bool is_merged () const; virtual const db::Edge *nth (size_t n) const; + virtual db::properties_id_type nth_prop_id (size_t n) const; virtual bool has_valid_edges () const; virtual bool has_valid_merged_edges () const; diff --git a/src/db/db/dbOriginalLayerTexts.cc b/src/db/db/dbOriginalLayerTexts.cc index e4f53eb27..af633ebe5 100644 --- a/src/db/db/dbOriginalLayerTexts.cc +++ b/src/db/db/dbOriginalLayerTexts.cc @@ -190,6 +190,12 @@ OriginalLayerTexts::nth (size_t) const throw tl::Exception (tl::to_string (tr ("Random access to texts is available only for flat collections"))); } +db::properties_id_type +OriginalLayerTexts::nth_prop_id (size_t) const +{ + throw tl::Exception (tl::to_string (tr ("Random access to texts is available only for flat collections"))); +} + bool OriginalLayerTexts::has_valid_texts () const { diff --git a/src/db/db/dbOriginalLayerTexts.h b/src/db/db/dbOriginalLayerTexts.h index d294e2803..81971bd44 100644 --- a/src/db/db/dbOriginalLayerTexts.h +++ b/src/db/db/dbOriginalLayerTexts.h @@ -53,6 +53,7 @@ public: virtual bool empty () const; virtual const db::Text *nth (size_t n) const; + virtual db::properties_id_type nth_prop_id (size_t n) const; virtual bool has_valid_texts () const; virtual const db::RecursiveShapeIterator *iter () const; diff --git a/src/db/db/dbTexts.h b/src/db/db/dbTexts.h index a948f3366..51b05a5d6 100644 --- a/src/db/db/dbTexts.h +++ b/src/db/db/dbTexts.h @@ -495,7 +495,7 @@ public: /** * @brief Returns the nth text * - * This operation is available only for flat regions - i.e. such for which + * This operation is available only for flat text collections - i.e. such for which * "has_valid_texts" is true. */ const db::Text *nth (size_t n) const @@ -503,6 +503,17 @@ public: return mp_delegate->nth (n); } + /** + * @brief Returns the nth text's property ID + * + * This operation is available only for flat text collections - i.e. such for which + * "has_valid_texts" is true. + */ + db::properties_id_type nth_prop_id (size_t n) const + { + return mp_delegate->nth_prop_id (n); + } + /** * @brief Forces flattening of the text collection * diff --git a/src/db/db/dbTextsDelegate.h b/src/db/db/dbTextsDelegate.h index 4808e9679..895b1808e 100644 --- a/src/db/db/dbTextsDelegate.h +++ b/src/db/db/dbTextsDelegate.h @@ -109,6 +109,7 @@ public: virtual TextsDelegate *in (const Texts &other, bool invert) const = 0; virtual const db::Text *nth (size_t n) const = 0; + virtual db::properties_id_type nth_prop_id (size_t n) const = 0; virtual bool has_valid_texts () const = 0; virtual const db::RecursiveShapeIterator *iter () const = 0; diff --git a/src/db/db/gsiDeclDbEdgePair.cc b/src/db/db/gsiDeclDbEdgePair.cc index 8c34e5507..0ba631bde 100644 --- a/src/db/db/gsiDeclDbEdgePair.cc +++ b/src/db/db/gsiDeclDbEdgePair.cc @@ -370,7 +370,7 @@ static db::DEdgePairWithProperties *new_dedge_pair_with_properties2 (const db::D return new db::DEdgePairWithProperties (edge_pair, db::properties_id (db::PropertiesSet (properties.begin (), properties.end ()))); } -Class decl_DEdgePairWithProperties (decl_EdgePair, "db", "DEdgePairWithProperties", +Class decl_DEdgePairWithProperties (decl_DEdgePair, "db", "DEdgePairWithProperties", gsi::properties_support_methods () + constructor ("new", &new_dedge_pair_with_properties, gsi::arg ("edge_pair"), gsi::arg ("properties_id", db::properties_id_type (0)), "@brief Creates a new object from a property-less object and a properties ID." diff --git a/src/db/db/gsiDeclDbEdgePairs.cc b/src/db/db/gsiDeclDbEdgePairs.cc index 2a50e6747..903aba802 100644 --- a/src/db/db/gsiDeclDbEdgePairs.cc +++ b/src/db/db/gsiDeclDbEdgePairs.cc @@ -783,6 +783,16 @@ static std::vector split_with_area2 (const db::EdgePairs *r, db:: return as_2edge_pairs_vector (r->split_filter (f)); } +static tl::Variant nth (const db::EdgePairs *edge_pairs, size_t n) +{ + const db::EdgePair *ep = edge_pairs->nth (n); + if (! ep) { + return tl::Variant (); + } else { + return tl::Variant (db::EdgePairWithProperties (*ep, edge_pairs->nth_prop_id (n))); + } +} + static db::generic_shape_iterator begin_edge_pairs (const db::EdgePairs *edge_pairs) { return db::generic_shape_iterator (db::make_wp_iter (edge_pairs->delegate ()->begin ())); @@ -1855,13 +1865,15 @@ Class decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs", "\n" "Starting with version 0.30, the iterator delivers EdgePairWithProperties objects." ) + - method ("[]", &db::EdgePairs::nth, gsi::arg ("n"), + method_ext ("[]", &nth, gsi::arg ("n"), "@brief Returns the nth edge pair\n" "\n" "This method returns nil if the index is out of range. It is available for flat edge pairs only - i.e. " "those for which \\has_valid_edge_pairs? is true. Use \\flatten to explicitly flatten an edge pair collection.\n" "\n" - "The \\each iterator is the more general approach to access the edge pairs." + "The \\each iterator is the more general approach to access the edge pairs.\n" + "\n" + "Since version 0.30.1, this method returns a \\EdgePairWithProperties object." ) + method ("flatten", &db::EdgePairs::flatten, "@brief Explicitly flattens an edge pair collection\n" diff --git a/src/db/db/gsiDeclDbEdges.cc b/src/db/db/gsiDeclDbEdges.cc index d4da722f4..0383d14ac 100644 --- a/src/db/db/gsiDeclDbEdges.cc +++ b/src/db/db/gsiDeclDbEdges.cc @@ -848,6 +848,16 @@ static std::vector split_interacting_with_region (const db::Edges *r, return as_2edges_vector (r->selected_interacting_differential (other, min_count, max_count)); } +static tl::Variant nth (const db::Edges *edges, size_t n) +{ + const db::Edge *e = edges->nth (n); + if (! e) { + return tl::Variant (); + } else { + return tl::Variant (db::EdgeWithProperties (*e, edges->nth_prop_id (n))); + } +} + static db::generic_shape_iterator begin_edges (const db::Edges *edges) { return db::generic_shape_iterator (db::make_wp_iter (edges->delegate ()->begin ())); @@ -2439,14 +2449,16 @@ Class decl_Edges (decl_dbShapeCollection, "db", "Edges", "This method has been introduced in version 0.25." "Starting with version 0.30, the iterator delivers an EdgeWithProperties object." ) + - method ("[]", &db::Edges::nth, gsi::arg ("n"), + method_ext ("[]", &nth, gsi::arg ("n"), "@brief Returns the nth edge of the collection\n" "\n" "This method returns nil if the index is out of range. It is available for flat edge collections only - i.e. " "those for which \\has_valid_edges? is true. Use \\flatten to explicitly flatten an edge collection.\n" "This method returns the raw edge (not merged edges, even if merged semantics is enabled).\n" "\n" - "The \\each iterator is the more general approach to access the edges." + "The \\each iterator is the more general approach to access the edges.\n" + "\n" + "Since version 0.30.1, this method returns an \\EdgeWithProperties object." ) + method ("flatten", &db::Edges::flatten, "@brief Explicitly flattens an edge collection\n" diff --git a/src/db/db/gsiDeclDbRegion.cc b/src/db/db/gsiDeclDbRegion.cc index 11b80b936..53da87933 100644 --- a/src/db/db/gsiDeclDbRegion.cc +++ b/src/db/db/gsiDeclDbRegion.cc @@ -1379,6 +1379,16 @@ rasterize1 (const db::Region *region, const db::Point &origin, const db::Vector return rasterize2 (region, origin, pixel_size, pixel_size, nx, ny); } +static tl::Variant nth (const db::Region *region, size_t n) +{ + const db::Polygon *poly = region->nth (n); + if (! poly) { + return tl::Variant (); + } else { + return tl::Variant (db::PolygonWithProperties (*poly, region->nth_prop_id (n))); + } +} + static db::generic_shape_iterator begin_region (const db::Region *region) { return db::generic_shape_iterator (db::make_wp_iter (region->delegate ()->begin ())); @@ -4103,14 +4113,16 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "This returns the raw polygons if merged semantics is disabled or the merged ones if merged semantics is enabled.\n" "Starting with version 0.30, the iterator delivers a RegionWithProperties object." ) + - method ("[]", &db::Region::nth, gsi::arg ("n"), + method_ext ("[]", &nth, gsi::arg ("n"), "@brief Returns the nth polygon of the region\n" "\n" "This method returns nil if the index is out of range. It is available for flat regions only - i.e. " "those for which \\has_valid_polygons? is true. Use \\flatten to explicitly flatten a region.\n" "This method returns the raw polygon (not merged polygons, even if merged semantics is enabled).\n" "\n" - "The \\each iterator is the more general approach to access the polygons." + "The \\each iterator is the more general approach to access the polygons.\n" + "\n" + "Since version 0.30.1, this method returns a \\PolygonWithProperties object." ) + method ("flatten", &db::Region::flatten, "@brief Explicitly flattens a region\n" diff --git a/src/db/db/gsiDeclDbTexts.cc b/src/db/db/gsiDeclDbTexts.cc index 66e1d34a6..17a9563c9 100644 --- a/src/db/db/gsiDeclDbTexts.cc +++ b/src/db/db/gsiDeclDbTexts.cc @@ -455,6 +455,16 @@ static db::Region pull_interacting (const db::Texts *r, const db::Region &other) return out; } +static tl::Variant nth (const db::Texts *texts, size_t n) +{ + const db::Text *t = texts->nth (n); + if (! t) { + return tl::Variant (); + } else { + return tl::Variant (db::TextWithProperties (*t, texts->nth_prop_id (n))); + } +} + static db::generic_shape_iterator begin_texts (const db::Texts *texts) { return db::generic_shape_iterator (db::make_wp_iter (texts->delegate ()->begin ())); @@ -846,13 +856,15 @@ Class decl_Texts (decl_dbShapeCollection, "db", "Texts", "\n" "Starting with version 0.30, the iterator delivers TextWithProperties objects." ) + - method ("[]", &db::Texts::nth, gsi::arg ("n"), + method_ext ("[]", &nth, gsi::arg ("n"), "@brief Returns the nth text\n" "\n" "This method returns nil if the index is out of range. It is available for flat texts only - i.e. " "those for which \\has_valid_texts? is true. Use \\flatten to explicitly flatten an text collection.\n" "\n" - "The \\each iterator is the more general approach to access the texts." + "The \\each iterator is the more general approach to access the texts.\n" + "\n" + "Since version 0.30.1, this method returns a \\TextWithProperties object." ) + method ("flatten", &db::Texts::flatten, "@brief Explicitly flattens an text collection\n" diff --git a/src/db/unit_tests/dbEdgePairsTests.cc b/src/db/unit_tests/dbEdgePairsTests.cc index 1f6153c3d..1a8680fdd 100644 --- a/src/db/unit_tests/dbEdgePairsTests.cc +++ b/src/db/unit_tests/dbEdgePairsTests.cc @@ -279,3 +279,24 @@ TEST(6_add_with_properties) EXPECT_EQ ((ro1 + rf2).to_string (), "(10,20;-20,60)/(10,30;-20,70){net=>17};(-10,20;20,60)/(-10,30;20,70){net=>17}"); } +TEST(7_properties) +{ + db::PropertiesSet ps; + + ps.insert (tl::Variant ("id"), 1); + db::properties_id_type pid1 = db::properties_id (ps); + + db::EdgePairs edge_pairs; + db::Edge e1 (db::Point (0, 0), db::Point (10, 20)); + db::Edge e2 (db::Point (1, 2), db::Point (11, 22)); + edge_pairs.insert (db::EdgePairWithProperties (db::EdgePair (e1, e2), pid1)); + edge_pairs.insert (db::EdgePair (e1, e2)); + + EXPECT_EQ (edge_pairs.nth (0)->to_string (), "(0,0;10,20)/(1,2;11,22)"); + EXPECT_EQ (edge_pairs.nth (1)->to_string (), "(0,0;10,20)/(1,2;11,22)"); + EXPECT_EQ (edge_pairs.nth (2) == 0, true); + + EXPECT_EQ (edge_pairs.nth_prop_id (0), db::properties_id_type (0)); + EXPECT_EQ (edge_pairs.nth_prop_id (1), pid1); +} + diff --git a/src/db/unit_tests/dbEdgesTests.cc b/src/db/unit_tests/dbEdgesTests.cc index 15a4b562b..0db2b9676 100644 --- a/src/db/unit_tests/dbEdgesTests.cc +++ b/src/db/unit_tests/dbEdgesTests.cc @@ -1443,6 +1443,25 @@ TEST(32_add_with_properties) EXPECT_EQ ((ro1 + rf2).to_string (), "(10,20;40,60){net=>17};(-10,20;20,60){net=>17}"); } +TEST(33_properties) +{ + db::PropertiesSet ps; + + ps.insert (tl::Variant ("id"), 1); + db::properties_id_type pid1 = db::properties_id (ps); + + db::Edges edges; + edges.insert (db::EdgeWithProperties (db::Edge (db::Point (0, 0), db::Point (10, 20)), pid1)); + edges.insert (db::Edge (db::Point (0, 0), db::Point (10, 20))); + + EXPECT_EQ (edges.nth (0)->to_string (), "(0,0;10,20)"); + EXPECT_EQ (edges.nth (1)->to_string (), "(0,0;10,20)"); + EXPECT_EQ (edges.nth (2) == 0, true); + + EXPECT_EQ (edges.nth_prop_id (0), db::properties_id_type (0)); + EXPECT_EQ (edges.nth_prop_id (1), pid1); +} + // GitHub issue #72 (Edges/Region NOT issue) TEST(100) { diff --git a/src/db/unit_tests/dbTextsTests.cc b/src/db/unit_tests/dbTextsTests.cc index 2fc3e652b..e7666647e 100644 --- a/src/db/unit_tests/dbTextsTests.cc +++ b/src/db/unit_tests/dbTextsTests.cc @@ -307,3 +307,22 @@ TEST(9_polygons) EXPECT_EQ (r.to_string (), "(9,19;9,21;11,21;11,19){17=>ABC};(-11,-21;-11,-19;-9,-19;-9,-21){17=>XZY}"); } +TEST(10_properties) +{ + db::PropertiesSet ps; + + ps.insert (tl::Variant ("id"), 1); + db::properties_id_type pid1 = db::properties_id (ps); + + db::Texts texts; + texts.insert (db::TextWithProperties (db::Text ("string", db::Trans ()), pid1)); + texts.insert (db::Text ("abc", db::Trans ())); + + EXPECT_EQ (texts.nth (0)->to_string (), "('abc',r0 0,0)"); + EXPECT_EQ (texts.nth (1)->to_string (), "('string',r0 0,0)"); + EXPECT_EQ (texts.nth (2) == 0, true); + + EXPECT_EQ (texts.nth_prop_id (0), db::properties_id_type (0)); + EXPECT_EQ (texts.nth_prop_id (1), pid1); +} + diff --git a/src/gsi/gsi/gsiExpression.cc b/src/gsi/gsi/gsiExpression.cc index 4ac9fbc10..1727c2bc6 100644 --- a/src/gsi/gsi/gsiExpression.cc +++ b/src/gsi/gsi/gsiExpression.cc @@ -952,9 +952,11 @@ VariantUserClassImpl::execute_gsi (const tl::ExpressionParserContext & /*context const tl::Variant *arg = i >= int (args.size ()) ? get_kwarg (*a, kwargs) : &args[i]; if (! arg) { is_valid = a->spec ()->has_default (); - } else if (gsi::test_arg (*a, *arg, false /*strict*/)) { + } else if (gsi::test_arg (*a, *arg, false /*strict*/, false /*no object substitution*/)) { + sc += 100; + } else if (gsi::test_arg (*a, *arg, true /*loose*/, false /*no object substitution*/)) { ++sc; - } else if (test_arg (*a, *arg, true /*loose*/)) { + } else if (gsi::test_arg (*a, *arg, true /*loose*/, true /*with object substitution*/)) { // non-scoring match } else { is_valid = false; diff --git a/src/gsi/gsi/gsiVariantArgs.cc b/src/gsi/gsi/gsiVariantArgs.cc index 39dc0725e..5e1b4ffb7 100644 --- a/src/gsi/gsi/gsiVariantArgs.cc +++ b/src/gsi/gsi/gsiVariantArgs.cc @@ -46,12 +46,12 @@ inline void *get_object (tl::Variant &var) // ------------------------------------------------------------------- // Test if an argument can be converted to the given type -bool test_arg (const gsi::ArgType &atype, const tl::Variant &arg, bool loose); +bool test_arg (const gsi::ArgType &atype, const tl::Variant &arg, bool loose, bool object_substitution); template struct test_arg_func { - void operator () (bool *ret, const tl::Variant &arg, const gsi::ArgType & /*atype*/, bool /*loose*/) + void operator () (bool *ret, const tl::Variant &arg, const gsi::ArgType & /*atype*/, bool /*loose*/, bool /*object_substitution*/) { *ret = arg.can_convert_to (); } @@ -60,7 +60,16 @@ struct test_arg_func template <> struct test_arg_func { - void operator () (bool *ret, const tl::Variant & /*arg*/, const gsi::ArgType & /*atype*/, bool /*loose*/) + void operator () (bool *ret, const tl::Variant & /*arg*/, const gsi::ArgType & /*atype*/, bool /*loose*/, bool /*object_substitution*/) + { + *ret = true; + } +}; + +template <> +struct test_arg_func +{ + void operator () (bool *ret, const tl::Variant & /*arg*/, const gsi::ArgType & /*atype*/, bool /*loose*/, bool /*object_substitution*/) { *ret = true; } @@ -69,7 +78,7 @@ struct test_arg_func template <> struct test_arg_func { - void operator () (bool *ret, const tl::Variant &arg, const gsi::ArgType &atype, bool loose) + void operator () (bool *ret, const tl::Variant &arg, const gsi::ArgType &atype, bool loose, bool object_substitution) { // allow nil of pointers if ((atype.is_ptr () || atype.is_cptr ()) && arg.is_nil ()) { @@ -77,7 +86,7 @@ struct test_arg_func return; } - if (arg.is_list ()) { + if (object_substitution && arg.is_list ()) { // we may implicitly convert an array into a constructor call of a target object - // for now we only check whether the number of arguments is compatible with the array given. @@ -104,9 +113,9 @@ struct test_arg_func const tl::VariantUserClassBase *cls = arg.user_cls (); if (! cls) { *ret = false; - } else if (! cls->gsi_cls ()->is_derived_from (atype.cls ()) && (! loose || ! cls->gsi_cls ()->can_convert_to(atype.cls ()))) { - *ret = false; - } else if ((atype.is_ref () || atype.is_ptr ()) && cls->is_const ()) { + } else if (! (cls->gsi_cls () == atype.cls () || + (loose && (cls->gsi_cls ()->is_derived_from (atype.cls ()) || + (object_substitution && cls->gsi_cls ()->can_convert_to (atype.cls ())))))) { *ret = false; } else { *ret = true; @@ -117,7 +126,7 @@ struct test_arg_func template <> struct test_arg_func { - void operator () (bool *ret, const tl::Variant &arg, const gsi::ArgType &atype, bool loose) + void operator () (bool *ret, const tl::Variant &arg, const gsi::ArgType &atype, bool loose, bool /*object_substitution*/) { if (! arg.is_list ()) { *ret = false; @@ -129,7 +138,7 @@ struct test_arg_func *ret = true; for (tl::Variant::const_iterator v = arg.begin (); v != arg.end () && *ret; ++v) { - if (! test_arg (ainner, *v, loose)) { + if (! test_arg (ainner, *v, loose, true)) { *ret = false; } } @@ -139,7 +148,7 @@ struct test_arg_func template <> struct test_arg_func { - void operator () (bool *ret, const tl::Variant &arg, const gsi::ArgType &atype, bool loose) + void operator () (bool *ret, const tl::Variant &arg, const gsi::ArgType &atype, bool loose, bool /*object_substitution*/) { // Note: delegating that to the function avoids "injected class name used as template template expression" warning if (! arg.is_array ()) { @@ -152,16 +161,11 @@ struct test_arg_func const ArgType &ainner = *atype.inner (); const ArgType &ainner_k = *atype.inner_k (); - if (! arg.is_list ()) { - *ret = false; - return; - } - *ret = true; for (tl::Variant::const_array_iterator a = arg.begin_array (); a != arg.end_array () && *ret; ++a) { - if (! test_arg (ainner_k, a->first, loose)) { + if (! test_arg (ainner_k, a->first, loose, true)) { *ret = false; - } else if (! test_arg (ainner, a->second, loose)) { + } else if (! test_arg (ainner, a->second, loose, true)) { *ret = false; } } @@ -169,7 +173,7 @@ struct test_arg_func }; bool -test_arg (const gsi::ArgType &atype, const tl::Variant &arg, bool loose) +test_arg (const gsi::ArgType &atype, const tl::Variant &arg, bool loose, bool object_substitution) { // for const X * or X *, nil is an allowed value if ((atype.is_cptr () || atype.is_ptr ()) && arg.is_nil ()) { @@ -177,7 +181,7 @@ test_arg (const gsi::ArgType &atype, const tl::Variant &arg, bool loose) } bool ret = false; - gsi::do_on_type () (atype.type (), &ret, arg, atype, loose); + gsi::do_on_type () (atype.type (), &ret, arg, atype, loose, object_substitution); return ret; } diff --git a/src/gsi/gsi/gsiVariantArgs.h b/src/gsi/gsi/gsiVariantArgs.h index 75f312819..187132289 100644 --- a/src/gsi/gsi/gsiVariantArgs.h +++ b/src/gsi/gsi/gsiVariantArgs.h @@ -70,10 +70,11 @@ GSI_PUBLIC void pull_arg (gsi::SerialArgs &retlist, const gsi::ArgType &atype, t * @param atype The argument type * @param arg The value to pass to it * @param loose true for loose checking + * @param object_substitution true to substitute object arguments by lists (using constructor) or employing conversion constructors * * @return True, if the argument can be passed */ -GSI_PUBLIC bool test_arg (const gsi::ArgType &atype, const tl::Variant &arg, bool loose); +GSI_PUBLIC bool test_arg (const gsi::ArgType &atype, const tl::Variant &arg, bool loose, bool object_substitution); } diff --git a/src/gsi/unit_tests/gsiExpressionTests.cc b/src/gsi/unit_tests/gsiExpressionTests.cc index 0449850d5..a395a73d9 100644 --- a/src/gsi/unit_tests/gsiExpressionTests.cc +++ b/src/gsi/unit_tests/gsiExpressionTests.cc @@ -863,3 +863,38 @@ TEST(16) } } +// implicit conversions +TEST(17) +{ + tl::Eval e; + tl::Variant v; + + // smoke test + v = e.parse ("var rdb=ReportDatabase.new();" + "var cat=rdb.create_category('name');" + "var cell=rdb.create_cell('TOP');" + "var it=rdb.create_item(cell,cat);" + "var bwp=BoxWithProperties.new(Box.new(0,0,1,2), {1=>'value'});" + "it.add_value(bwp)").execute (); + + v = e.parse ("var rdb=ReportDatabase.new();" + "var cat=rdb.create_category('name');" + "var cell=rdb.create_cell('TOP');" + "var it=rdb.create_item(cell,cat);" + "var bwp=DBoxWithProperties.new(DBox.new(0,0,1,2), {1=>'value'});" + "it.add_value(bwp)").execute (); + + v = e.parse ("var rdb=ReportDatabase.new();" + "var cat=rdb.create_category('name');" + "var cell=rdb.create_cell('TOP');" + "var it=rdb.create_item(cell,cat);" + "var b=DBox.new(0,0,1,2);" + "it.add_value(b)").execute (); + + v = e.parse ("var rdb=ReportDatabase.new();" + "var cat=rdb.create_category('name');" + "var cell=rdb.create_cell('TOP');" + "var it=rdb.create_item(cell,cat);" + "it.add_value(17.5)").execute (); +} + diff --git a/src/pya/pya/pyaCallables.cc b/src/pya/pya/pyaCallables.cc index f9fd2c75f..829f7076f 100644 --- a/src/pya/pya/pyaCallables.cc +++ b/src/pya/pya/pyaCallables.cc @@ -413,6 +413,8 @@ match_method (int mid, PyObject *self, PyObject *args, PyObject *kwargs, bool st if (! arg) { is_valid = a->spec ()->has_default (); } else if (test_arg (*a, arg.get (), false /*strict*/, false /*object substitution*/)) { + sc += 100; + } else if (test_arg (*a, arg.get (), true /*loose*/, false /*object substitution*/)) { ++sc; } else if (test_arg (*a, arg.get (), true /*loose*/, true /*object substitution*/)) { // non-scoring match diff --git a/src/pya/pya/pyaMarshal.cc b/src/pya/pya/pyaMarshal.cc index 7a50c85e7..0326f2e18 100644 --- a/src/pya/pya/pyaMarshal.cc +++ b/src/pya/pya/pyaMarshal.cc @@ -1232,7 +1232,7 @@ struct test_arg_func return; } - if (! (cls_decl == acls || (loose && (cls_decl->is_derived_from (atype.cls ()) || cls_decl->can_convert_to (atype.cls ()))))) { + if (! (cls_decl == acls || (loose && (cls_decl->is_derived_from (atype.cls ()) || (object_substitution && cls_decl->can_convert_to (atype.cls ())))))) { *ret = false; return; } diff --git a/src/rba/rba/rba.cc b/src/rba/rba/rba.cc index 7979bc6cc..77faa3d88 100644 --- a/src/rba/rba/rba.cc +++ b/src/rba/rba/rba.cc @@ -539,6 +539,8 @@ private: if (arg == Qundef) { is_valid = a->spec ()->has_default (); } else if (test_arg (*a, arg, false /*strict*/, false /*with object substitution*/)) { + sc += 100; + } else if (test_arg (*a, arg, true /*loose*/, false /*with object substitution*/)) { ++sc; } else if (test_arg (*a, arg, true /*loose*/, true /*with object substitution*/)) { // non-scoring match diff --git a/src/rba/rba/rbaMarshal.cc b/src/rba/rba/rbaMarshal.cc index b55f82111..0781f5e7d 100644 --- a/src/rba/rba/rbaMarshal.cc +++ b/src/rba/rba/rbaMarshal.cc @@ -1217,7 +1217,7 @@ struct test_arg_func // in loose mode (second pass) try to match the types via implicit constructors, // in strict mode (first pass) require direct type match - if (p->cls_decl () == atype.cls () || (loose && (p->cls_decl ()->is_derived_from (atype.cls ()) || p->cls_decl ()->can_convert_to (atype.cls ())))) { + if (p->cls_decl () == atype.cls () || (loose && (p->cls_decl ()->is_derived_from (atype.cls ()) || (object_substitution && p->cls_decl ()->can_convert_to (atype.cls ()))))) { // type matches: check constness if ((atype.is_ref () || atype.is_ptr ()) && p->const_ref ()) { *ret = false; diff --git a/src/rdb/rdb/gsiDeclRdb.cc b/src/rdb/rdb/gsiDeclRdb.cc index 10307e96f..d2db8c0d1 100644 --- a/src/rdb/rdb/gsiDeclRdb.cc +++ b/src/rdb/rdb/gsiDeclRdb.cc @@ -999,6 +999,11 @@ Class decl_RdbItem ("rdb", "RdbItem", "@param value The box to add.\n" "This method has been introduced in version 0.25 as a convenience method." ) + + gsi::method_ext ("add_value", &add_value_t, gsi::arg ("value"), + "@brief Adds a text object to the values of this item\n" + "@param value The text to add.\n" + "This method has been introduced in version 0.30.1 to support text objects with properties." + ) + gsi::method_ext ("add_value", &add_value_t, gsi::arg ("value"), "@brief Adds an edge object to the values of this item\n" "@param value The edge to add.\n" diff --git a/testdata/python/rdbTest.py b/testdata/python/rdbTest.py index dfa2194d6..a7c34925f 100644 --- a/testdata/python/rdbTest.py +++ b/testdata/python/rdbTest.py @@ -972,6 +972,78 @@ class RDB_TestClass(unittest.TestCase): _cat_same = None self.assertEqual(_subcat.rdb_id(), _subcat_same.rdb_id()) + def test_15(self): + + p = pya.DPolygon(pya.DBox(0.5, 1, 2, 3)) + pwp = pya.DPolygonWithProperties(p, { 1: "value" }) + e = pya.DEdge(pya.DPoint(0, 0), pya.DPoint(1, 2)) + ewp = pya.DEdgeWithProperties(e, { 1: "value" }) + ep = pya.DEdgePair(e, e.moved(10, 10)) + epwp = pya.DEdgePairWithProperties(ep, { 1: "value" }) + t = pya.DText("text", pya.DTrans.R0) + twp = pya.DTextWithProperties(t, { 1: "value" }) + b = pya.DBox(0, 0, 1, 2) + bwp = pya.DBoxWithProperties(b, { 1: "value" }) + + ip = pya.Polygon(pya.Box(0, 1, 2, 3)) + ipwp = pya.PolygonWithProperties(ip, { 1: "value" }) + ie = pya.Edge(pya.Point(0, 0), pya.Point(1, 2)) + iewp = pya.EdgeWithProperties(ie, { 1: "value" }) + iep = pya.EdgePair(ie, ie.moved(10, 10)) + iepwp = pya.EdgePairWithProperties(iep, { 1: "value" }) + it = pya.Text("text", pya.Trans.R0) + itwp = pya.TextWithProperties(it, { 1: "value" }) + ib = pya.Box(0, 0, 1, 2) + ibwp = pya.BoxWithProperties(ib, { 1: "value" }) + + rdb = pya.ReportDatabase() + + cat = rdb.create_category("name") + cell = rdb.create_cell("TOP") + item = rdb.create_item(cell, cat) + + item.add_value(p) + item.add_value(pwp) + item.add_value(b) + item.add_value(bwp) + item.add_value(t) + item.add_value(twp) + item.add_value(e) + item.add_value(ewp) + item.add_value(ep) + item.add_value(epwp) + + item.add_value(ip) + item.add_value(ipwp) + item.add_value(ib) + item.add_value(ibwp) + item.add_value(it) + item.add_value(itwp) + item.add_value(ie) + item.add_value(iewp) + item.add_value(iep) + item.add_value(iepwp) + + item.add_value("string") + item.add_value(17.5) + + values = [ str(v) for v in item.each_value() ] + + self.assertEqual(values, [ + 'polygon: (0.5,1;0.5,3;2,3;2,1)', 'polygon: (0.5,1;0.5,3;2,3;2,1)', + 'box: (0,0;1,2)', 'box: (0,0;1,2)', + "label: ('text',r0 0,0)", "label: ('text',r0 0,0)", + 'edge: (0,0;1,2)', 'edge: (0,0;1,2)', + 'edge-pair: (0,0;1,2)/(10,10;11,12)', 'edge-pair: (0,0;1,2)/(10,10;11,12)', + 'polygon: (0,1;0,3;2,3;2,1)', 'polygon: (0,1;0,3;2,3;2,1)', + 'box: (0,0;1,2)', 'box: (0,0;1,2)', + "label: ('text',r0 0,0)", "label: ('text',r0 0,0)", + 'edge: (0,0;1,2)', 'edge: (0,0;1,2)', + 'edge-pair: (0,0;1,2)/(10,10;11,12)', 'edge-pair: (0,0;1,2)/(10,10;11,12)', + 'text: string', + 'float: 17.5' + ]) + # run unit tests if __name__ == '__main__': suite = unittest.TestLoader().loadTestsFromTestCase(RDB_TestClass) diff --git a/testdata/ruby/dbEdgePairsTest.rb b/testdata/ruby/dbEdgePairsTest.rb index d67bc33c6..ac157ff53 100644 --- a/testdata/ruby/dbEdgePairsTest.rb +++ b/testdata/ruby/dbEdgePairsTest.rb @@ -111,7 +111,7 @@ class DBEdgePairs_TestClass < TestBase assert_equal(csort(r.edges.to_s), csort("(0,0;0,100);(-10,0;-20,50)")) assert_equal(r.is_empty?, false) assert_equal(r.size, 1) - assert_equal(r[0].to_s, "(0,0;0,100)/(-10,0;-20,50)") + assert_equal(r[0].to_s, "(0,0;0,100)/(-10,0;-20,50) props={}") assert_equal(r[1].to_s, "") assert_equal(r.bbox.to_s, "(-20,0;0,100)") @@ -221,7 +221,7 @@ class DBEdgePairs_TestClass < TestBase r.flatten assert_equal(r.has_valid_edge_pairs?, true) - assert_equal(r[1].to_s, "(0,101;2,103)/(10,111;12,113)") + assert_equal(r[1].to_s, "(0,101;2,103)/(10,111;12,113) props={}") assert_equal(r[100].inspect, "nil") assert_equal(r.bbox.to_s, "(0,1;212,113)") @@ -622,6 +622,7 @@ class DBEdgePairs_TestClass < TestBase r = RBA::EdgePairs::new([ RBA::EdgePairWithProperties::new(RBA::EdgePair::new(RBA::Edge::new(0, 0, 100, 100), RBA::Edge::new(200, 300, 200, 500)), { 1 => "one" }) ]) assert_equal(r.to_s, "(0,0;100,100)/(200,300;200,500){1=>one}") + assert_equal(r[0].to_s, "(0,0;100,100)/(200,300;200,500) props={1=>one}") r = RBA::EdgePairs::new([]) assert_equal(r.to_s, "") diff --git a/testdata/ruby/dbEdgesTest.rb b/testdata/ruby/dbEdgesTest.rb index 086a0eb9c..7a8047b23 100644 --- a/testdata/ruby/dbEdgesTest.rb +++ b/testdata/ruby/dbEdgesTest.rb @@ -235,7 +235,7 @@ class DBEdges_TestClass < TestBase assert_equal(r.is_empty?, false) assert_equal(r.count, 12) assert_equal(r.hier_count, 12) - assert_equal(r[1].to_s, "(-10,20;10,20)") + assert_equal(r[1].to_s, "(-10,20;10,20) props={}") assert_equal(r[100].to_s, "") assert_equal(r.bbox.to_s, "(-10,-20;210,120)") assert_equal(r.is_merged?, false) @@ -252,11 +252,11 @@ class DBEdges_TestClass < TestBase r.flatten assert_equal(r.has_valid_edges?, true) - assert_equal(r[1].to_s, "(-10,80;10,120)") + assert_equal(r[1].to_s, "(-10,80;10,120) props={}") assert_equal(r[100].to_s, "") assert_equal(r.bbox.to_s, "(-10,-20;210,120)") assert_equal(r.is_merged?, false) - + r = RBA::Edges::new(ly.begin_shapes(c1.cell_index, l1), RBA::ICplxTrans::new(10, 20), true) assert_equal(r.to_s(30), "(0,0;0,40);(0,40;20,40);(20,40;20,0);(20,0;0,0);(0,100;0,140);(0,140;20,140);(20,140;20,100);(20,100;0,100);(200,100;200,140);(200,140;220,140);(220,140;220,100);(220,100;200,100)") assert_equal(r.is_empty?, false) @@ -970,6 +970,7 @@ class DBEdges_TestClass < TestBase r = RBA::Edges::new([ RBA::EdgeWithProperties::new(RBA::Edge::new(0, 0, 100, 100), { 1 => "one" }) ]) assert_equal(r.to_s, "(0,0;100,100){1=>one}") + assert_equal(r[0].to_s, "(0,0;100,100) props={1=>one}") r = RBA::Edges::new([]) assert_equal(r.to_s, "") diff --git a/testdata/ruby/dbRegionTest.rb b/testdata/ruby/dbRegionTest.rb index 5f8588f8b..985dd9406 100644 --- a/testdata/ruby/dbRegionTest.rb +++ b/testdata/ruby/dbRegionTest.rb @@ -226,10 +226,16 @@ class DBRegion_TestClass < TestBase r.flatten assert_equal(r.has_valid_polygons?, true) - assert_equal(r[1].to_s, "(-10,80;-10,120;10,120;10,80)") + assert_equal(r[1].to_s, "(-10,80;-10,120;10,120;10,80) props={}") assert_equal(r[4].to_s, "") assert_equal(r.bbox.to_s, "(-10,-20;210,120)") assert_equal(r.is_merged?, false) + + r = RBA::Region::new + r.insert(RBA::PolygonWithProperties::new(RBA::Box::new(0, 0, 10, 20), { 1 => 'value' })) + r.insert(RBA::Box::new(1, 2, 11, 22)) + assert_equal(r[0].to_s, "(1,2;1,22;11,22;11,2) props={}") + assert_equal(r[1].to_s, "(0,0;0,20;10,20;10,0) props={1=>value}") r = RBA::Region::new(ly.begin_shapes(c1.cell_index, l2), "*") assert_equal(csort(r.to_s), csort("(-11,-21;-11,-19;-9,-19;-9,-21);(9,19;9,21;11,21;11,19);(-11,79;-11,81;-9,81;-9,79);(9,119;9,121;11,121;11,119);(189,79;189,81;191,81;191,79);(209,119;209,121;211,121;211,119)")) diff --git a/testdata/ruby/dbTextsTest.rb b/testdata/ruby/dbTextsTest.rb index 145379068..4f481ef3f 100644 --- a/testdata/ruby/dbTextsTest.rb +++ b/testdata/ruby/dbTextsTest.rb @@ -103,7 +103,7 @@ class DBTexts_TestClass < TestBase assert_equal(r.is_empty?, false) assert_equal(r.count, 1) assert_equal(r.hier_count, 1) - assert_equal(r[0].to_s, "('uvw',r0 110,210)") + assert_equal(r[0].to_s, "('uvw',r0 110,210) props={}") assert_equal(r[1].to_s, "") assert_equal(r.bbox.to_s, "(110,210;110,210)") @@ -223,9 +223,13 @@ class DBTexts_TestClass < TestBase r.flatten assert_equal(r.has_valid_texts?, true) - assert_equal(r[1].to_s, "('abc',r0 100,-100)") + assert_equal(r[1].to_s, "('abc',r0 100,-100) props={}") assert_equal(r[100].inspect, "nil") assert_equal(r.bbox.to_s, "(100,-200;300,-100)") + + r = RBA::Texts::new + r.insert(RBA::TextWithProperties::new(RBA::Text::new("string", RBA::Trans::new), { 1 => "value" })) + assert_equal(r[0].to_s, "('string',r0 0,0) props={1=>value}") dss = RBA::DeepShapeStore::new r = RBA::Texts::new(ly.begin_shapes(c1.cell_index, l1), dss) diff --git a/testdata/ruby/rdbTest.rb b/testdata/ruby/rdbTest.rb index 392e0cfa4..91ecb9bf2 100644 --- a/testdata/ruby/rdbTest.rb +++ b/testdata/ruby/rdbTest.rb @@ -1131,6 +1131,80 @@ class RDB_TestClass < TestBase end + def test_15 + + p = RBA::DPolygon::new(RBA::DBox::new(0.5, 1, 2, 3)) + pwp = RBA::DPolygonWithProperties::new(p, { 1 => "value" }) + e = RBA::DEdge::new(RBA::DPoint::new(0, 0), RBA::DPoint::new(1, 2)) + ewp = RBA::DEdgeWithProperties::new(e, { 1 => "value" }) + ep = RBA::DEdgePair::new(e, e.moved(10, 10)) + epwp = RBA::DEdgePairWithProperties::new(ep, { 1 => "value" }) + t = RBA::DText::new("text", RBA::DTrans::R0) + twp = RBA::DTextWithProperties::new(t, { 1 => "value" }) + b = RBA::DBox::new(0, 0, 1, 2) + bwp = RBA::DBoxWithProperties::new(b, { 1 => "value" }) + + ip = RBA::Polygon::new(RBA::Box::new(0, 1, 2, 3)) + ipwp = RBA::PolygonWithProperties::new(ip, { 1 => "value" }) + ie = RBA::Edge::new(RBA::Point::new(0, 0), RBA::Point::new(1, 2)) + iewp = RBA::EdgeWithProperties::new(ie, { 1 => "value" }) + iep = RBA::EdgePair::new(ie, ie.moved(10, 10)) + iepwp = RBA::EdgePairWithProperties::new(iep, { 1 => "value" }) + it = RBA::Text::new("text", RBA::Trans::R0) + itwp = RBA::TextWithProperties::new(it, { 1 => "value" }) + ib = RBA::Box::new(0, 0, 1, 2) + ibwp = RBA::BoxWithProperties::new(ib, { 1 => "value" }) + + rdb = RBA::ReportDatabase::new + + cat = rdb.create_category("name") + cell = rdb.create_cell("TOP") + item = rdb.create_item(cell, cat) + + item.add_value(p) + item.add_value(pwp) + item.add_value(b) + item.add_value(bwp) + item.add_value(t) + item.add_value(twp) + item.add_value(e) + item.add_value(ewp) + item.add_value(ep) + item.add_value(epwp) + + item.add_value(ip) + item.add_value(ipwp) + item.add_value(ib) + item.add_value(ibwp) + item.add_value(it) + item.add_value(itwp) + item.add_value(ie) + item.add_value(iewp) + item.add_value(iep) + item.add_value(iepwp) + + item.add_value("string") + item.add_value(17.5) + + values = item.each_value.collect(&:to_s) + + assert_equal(values, [ + 'polygon: (0.5,1;0.5,3;2,3;2,1)', 'polygon: (0.5,1;0.5,3;2,3;2,1)', + 'box: (0,0;1,2)', 'box: (0,0;1,2)', + "label: ('text',r0 0,0)", "label: ('text',r0 0,0)", + 'edge: (0,0;1,2)', 'edge: (0,0;1,2)', + 'edge-pair: (0,0;1,2)/(10,10;11,12)', 'edge-pair: (0,0;1,2)/(10,10;11,12)', + 'polygon: (0,1;0,3;2,3;2,1)', 'polygon: (0,1;0,3;2,3;2,1)', + 'box: (0,0;1,2)', 'box: (0,0;1,2)', + "label: ('text',r0 0,0)", "label: ('text',r0 0,0)", + 'edge: (0,0;1,2)', 'edge: (0,0;1,2)', + 'edge-pair: (0,0;1,2)/(10,10;11,12)', 'edge-pair: (0,0;1,2)/(10,10;11,12)', + 'text: string', + 'float: 17.5' + ]) + + end + end load("test_epilogue.rb")