diff --git a/src/db/db/db.pro b/src/db/db/db.pro index 6ee1e93fd..89b1eccde 100644 --- a/src/db/db/db.pro +++ b/src/db/db/db.pro @@ -196,7 +196,8 @@ SOURCES = \ dbOriginalLayerTexts.cc \ dbNetShape.cc \ dbShapeCollection.cc \ - gsiDeclDbShapeCollection.cc + gsiDeclDbShapeCollection.cc \ + dbShapeCollectionUtils.cc HEADERS = \ dbArray.h \ @@ -353,7 +354,8 @@ HEADERS = \ dbTextsUtils.h \ dbOriginalLayerTexts.h \ dbNetShape.h \ - dbShapeCollection.h + dbShapeCollection.h \ + dbShapeCollectionUtils.h !equals(HAVE_QT, "0") { diff --git a/src/db/db/dbAsIfFlatEdgePairs.cc b/src/db/db/dbAsIfFlatEdgePairs.cc index 4ed4ee3e9..4b3ecbb1d 100644 --- a/src/db/db/dbAsIfFlatEdgePairs.cc +++ b/src/db/db/dbAsIfFlatEdgePairs.cc @@ -125,6 +125,28 @@ void AsIfFlatEdgePairs::invalidate_bbox () m_bbox_valid = false; } +RegionDelegate * +AsIfFlatEdgePairs::processed_to_polygons (const EdgePairToPolygonProcessorBase &filter) const +{ + std::auto_ptr region (new FlatRegion ()); + + if (filter.result_must_not_be_merged ()) { + region->set_merged_semantics (false); + } + + std::vector res_polygons; + + for (EdgePairsIterator e (begin ()); ! e.at_end (); ++e) { + res_polygons.clear (); + filter.process (*e, res_polygons); + for (std::vector::const_iterator pr = res_polygons.begin (); pr != res_polygons.end (); ++pr) { + region->insert (*pr); + } + } + + return region.release (); +} + EdgePairsDelegate * AsIfFlatEdgePairs::filtered (const EdgePairFilterBase &filter) const { diff --git a/src/db/db/dbAsIfFlatEdgePairs.h b/src/db/db/dbAsIfFlatEdgePairs.h index d379cefbb..dc14b8ca1 100644 --- a/src/db/db/dbAsIfFlatEdgePairs.h +++ b/src/db/db/dbAsIfFlatEdgePairs.h @@ -51,6 +51,8 @@ public: virtual EdgePairsDelegate *filtered (const EdgePairFilterBase &) const; + virtual RegionDelegate *processed_to_polygons (const EdgePairToPolygonProcessorBase &filter) const; + virtual EdgePairsDelegate *add_in_place (const EdgePairs &other) { return add (other); diff --git a/src/db/db/dbAsIfFlatTexts.cc b/src/db/db/dbAsIfFlatTexts.cc index fe9c86da3..263f05d07 100644 --- a/src/db/db/dbAsIfFlatTexts.cc +++ b/src/db/db/dbAsIfFlatTexts.cc @@ -152,6 +152,28 @@ AsIfFlatTexts::filtered (const TextFilterBase &filter) const return new_texts.release (); } +RegionDelegate * +AsIfFlatTexts::processed_to_polygons (const TextToPolygonProcessorBase &filter) const +{ + std::auto_ptr region (new FlatRegion ()); + + if (filter.result_must_not_be_merged ()) { + region->set_merged_semantics (false); + } + + std::vector res_polygons; + + for (TextsIterator e (begin ()); ! e.at_end (); ++e) { + res_polygons.clear (); + filter.process (*e, res_polygons); + for (std::vector::const_iterator pr = res_polygons.begin (); pr != res_polygons.end (); ++pr) { + region->insert (*pr); + } + } + + return region.release (); +} + RegionDelegate * AsIfFlatTexts::polygons (db::Coord e) const { diff --git a/src/db/db/dbAsIfFlatTexts.h b/src/db/db/dbAsIfFlatTexts.h index b0f4611fe..d3d4e2a49 100644 --- a/src/db/db/dbAsIfFlatTexts.h +++ b/src/db/db/dbAsIfFlatTexts.h @@ -53,6 +53,8 @@ public: virtual TextsDelegate *filtered (const TextFilterBase &) const; + virtual RegionDelegate *processed_to_polygons (const TextToPolygonProcessorBase &filter) const; + virtual TextsDelegate *add_in_place (const Texts &other) { return add (other); diff --git a/src/db/db/dbCellVariants.cc b/src/db/db/dbCellVariants.cc index afb4a137f..1676d1641 100644 --- a/src/db/db/dbCellVariants.cc +++ b/src/db/db/dbCellVariants.cc @@ -57,6 +57,22 @@ db::Trans MagnificationReducer::reduce (const db::Trans &) const // ------------------------------------------------------------------------------------------ +db::ICplxTrans XYAnisotropyAndMagnificationReducer::reduce (const db::ICplxTrans &trans) const +{ + double a = trans.angle (); + if (a > 180.0 - db::epsilon) { + a -= 180.0; + } + return db::ICplxTrans (trans.mag (), a, false, db::Vector ()); +} + +db::Trans XYAnisotropyAndMagnificationReducer::reduce (const db::Trans &trans) const +{ + return db::Trans (trans.angle () % 2, false, db::Vector ()); +} + +// ------------------------------------------------------------------------------------------ + db::ICplxTrans MagnificationAndOrientationReducer::reduce (const db::ICplxTrans &trans) const { db::ICplxTrans res (trans); diff --git a/src/db/db/dbCellVariants.h b/src/db/db/dbCellVariants.h index c1f639648..921f162c2 100644 --- a/src/db/db/dbCellVariants.h +++ b/src/db/db/dbCellVariants.h @@ -81,6 +81,18 @@ struct DB_PUBLIC MagnificationReducer db::Trans reduce (const db::Trans &) const; }; +/** + * @brief A reducer for magnification and XYAnisotropy + * + * This reducer is used for cases where an x and y-value is given, e.g. anisotropic size. + */ +struct DB_PUBLIC XYAnisotropyAndMagnificationReducer + : public TransformationReducer +{ + db::ICplxTrans reduce (const db::ICplxTrans &trans) const; + db::Trans reduce (const db::Trans &trans) const; +}; + /** * @brief A magnification and orientation reducer * diff --git a/src/db/db/dbDeepEdgePairs.cc b/src/db/db/dbDeepEdgePairs.cc index 95d105d91..00e2702f9 100644 --- a/src/db/db/dbDeepEdgePairs.cc +++ b/src/db/db/dbDeepEdgePairs.cc @@ -240,6 +240,12 @@ EdgePairsDelegate *DeepEdgePairs::filtered (const EdgePairFilterBase &filter) co return AsIfFlatEdgePairs::filtered (filter); } +RegionDelegate * +DeepEdgePairs::processed_to_polygons (const EdgePairToPolygonProcessorBase &filter) const +{ + return shape_collection_processed_impl (deep_layer (), filter); +} + RegionDelegate *DeepEdgePairs::polygons (db::Coord e) const { db::DeepLayer new_layer = deep_layer ().derived (); diff --git a/src/db/db/dbDeepEdgePairs.h b/src/db/db/dbDeepEdgePairs.h index c75355a35..a030652cc 100644 --- a/src/db/db/dbDeepEdgePairs.h +++ b/src/db/db/dbDeepEdgePairs.h @@ -63,6 +63,7 @@ public: virtual EdgePairsDelegate *filter_in_place (const EdgePairFilterBase &filter); virtual EdgePairsDelegate *filtered (const EdgePairFilterBase &) const; + virtual RegionDelegate *processed_to_polygons (const EdgePairToPolygonProcessorBase &filter) const; virtual EdgePairsDelegate *add_in_place (const EdgePairs &other); virtual EdgePairsDelegate *add (const EdgePairs &other) const; diff --git a/src/db/db/dbDeepEdges.cc b/src/db/db/dbDeepEdges.cc index d9c3fe21c..5f0961b00 100644 --- a/src/db/db/dbDeepEdges.cc +++ b/src/db/db/dbDeepEdges.cc @@ -525,146 +525,19 @@ EdgesDelegate *DeepEdges::process_in_place (const EdgeProcessorBase &filter) EdgesDelegate * DeepEdges::processed (const EdgeProcessorBase &filter) const { - return processed_impl (filter); + return shape_collection_processed_impl (filter.requires_raw_input () ? deep_layer () : merged_deep_layer (), filter); } EdgePairsDelegate * DeepEdges::processed_to_edge_pairs (const EdgeToEdgePairProcessorBase &filter) const { - return processed_impl (filter); + return shape_collection_processed_impl (filter.requires_raw_input () ? deep_layer () : merged_deep_layer (), filter); } RegionDelegate * DeepEdges::processed_to_polygons (const EdgeToPolygonProcessorBase &filter) const { - return processed_impl (filter); -} - -namespace -{ - -template struct delivery; - -template <> -struct delivery -{ - delivery (db::Layout *layout, db::Shapes *shapes) - : mp_layout (layout), mp_shapes (shapes) - { } - - void put (const db::Polygon &result) - { - tl::MutexLocker locker (&mp_layout->lock ()); - mp_shapes->insert (db::PolygonRef (result, mp_layout->shape_repository ())); - } - -private: - db::Layout *mp_layout; - db::Shapes *mp_shapes; -}; - -template -struct delivery -{ - delivery (db::Layout *, db::Shapes *shapes) - : mp_shapes (shapes) - { } - - void put (const Result &result) - { - mp_shapes->insert (result); - } - -private: - db::Shapes *mp_shapes; -}; - -} - -template -OutputContainer * -DeepEdges::processed_impl (const edge_processor &filter) const -{ - const db::DeepLayer &edges = filter.requires_raw_input () ? deep_layer () : merged_deep_layer (); - - std::auto_ptr vars; - if (filter.vars ()) { - - vars.reset (new db::VariantsCollectorBase (filter.vars ())); - - vars->collect (edges.layout (), edges.initial_cell ()); - - if (filter.wants_variants ()) { - const_cast (edges).separate_variants (*vars); - } - - } - - db::Layout &layout = const_cast (edges.layout ()); - - std::vector heap; - std::map > to_commit; - - std::auto_ptr res (new OutputContainer (edges.derived ())); - if (filter.result_must_not_be_merged ()) { - res->set_merged_semantics (false); - } - - for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { - - const db::Shapes &s = c->shapes (filter.requires_raw_input () ? edges.layer () : edges.layer ()); - - if (vars.get ()) { - - const std::map &vv = vars->variants (c->cell_index ()); - for (std::map::const_iterator v = vv.begin (); v != vv.end (); ++v) { - - db::Shapes *st; - if (vv.size () == 1) { - st = & c->shapes (res->deep_layer ().layer ()); - } else { - st = & to_commit [c->cell_index ()] [v->first]; - } - - delivery delivery (&layout, st); - - const db::ICplxTrans &tr = v->first; - db::ICplxTrans trinv = tr.inverted (); - - for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) { - heap.clear (); - filter.process (si->edge ().transformed (tr), heap); - for (typename std::vector::const_iterator i = heap.begin (); i != heap.end (); ++i) { - delivery.put (i->transformed (trinv)); - } - } - - } - - } else { - - db::Shapes &st = c->shapes (res->deep_layer ().layer ()); - delivery delivery (&layout, &st); - - for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::Edges); ! si.at_end (); ++si) { - filter.process (si->edge (), heap); - for (typename std::vector::const_iterator i = heap.begin (); i != heap.end (); ++i) { - delivery.put (*i); - } - } - - } - - } - - if (! to_commit.empty () && vars.get ()) { - res->deep_layer ().commit_shapes (*vars, to_commit); - } - - if (filter.result_is_merged ()) { - res->set_is_merged (true); - } - return res.release (); + return shape_collection_processed_impl (filter.requires_raw_input () ? deep_layer () : merged_deep_layer (), filter); } EdgesDelegate * diff --git a/src/db/db/dbDeepEdges.h b/src/db/db/dbDeepEdges.h index 8ed87c971..7d2eb83ea 100644 --- a/src/db/db/dbDeepEdges.h +++ b/src/db/db/dbDeepEdges.h @@ -149,9 +149,10 @@ public: return this; } + void set_is_merged (bool f); + protected: virtual void merged_semantics_changed (); - void set_is_merged (bool f); private: friend class DeepRegion; diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index e0ba85dc5..a9ef537dd 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -955,152 +955,19 @@ DeepRegion::process_in_place (const PolygonProcessorBase &filter) EdgesDelegate * DeepRegion::processed_to_edges (const PolygonToEdgeProcessorBase &filter) const { - return processed_impl (filter); + return shape_collection_processed_impl (filter.requires_raw_input () ? deep_layer () : merged_deep_layer (), filter); } EdgePairsDelegate * DeepRegion::processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &filter) const { - return processed_impl (filter); + return shape_collection_processed_impl (filter.requires_raw_input () ? deep_layer () : merged_deep_layer (), filter); } RegionDelegate * DeepRegion::processed (const PolygonProcessorBase &filter) const { - return processed_impl (filter); -} - -namespace -{ - -template struct delivery; - -template <> -struct delivery -{ - delivery (db::Layout *layout, db::Shapes *shapes) - : mp_layout (layout), mp_shapes (shapes) - { } - - void put (const db::Polygon &result) - { - tl::MutexLocker locker (&mp_layout->lock ()); - mp_shapes->insert (db::PolygonRef (result, mp_layout->shape_repository ())); - } - -private: - db::Layout *mp_layout; - db::Shapes *mp_shapes; -}; - -template -struct delivery -{ - delivery (db::Layout *, db::Shapes *shapes) - : mp_shapes (shapes) - { } - - void put (const Result &result) - { - mp_shapes->insert (result); - } - -private: - db::Shapes *mp_shapes; -}; - -} - -template -OutputContainer * -DeepRegion::processed_impl (const polygon_processor &filter) const -{ - const db::DeepLayer &polygons = filter.requires_raw_input () ? deep_layer () : merged_deep_layer (); - - std::auto_ptr vars; - if (filter.vars ()) { - - vars.reset (new db::VariantsCollectorBase (filter.vars ())); - - vars->collect (polygons.layout (), polygons.initial_cell ()); - - if (filter.wants_variants ()) { - const_cast (polygons).separate_variants (*vars); - } - - } - - db::Layout &layout = const_cast (polygons.layout ()); - - std::vector heap; - std::map > to_commit; - - std::auto_ptr res (new OutputContainer (polygons.derived ())); - if (filter.result_must_not_be_merged ()) { - res->set_merged_semantics (false); - } - - for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { - - const db::Shapes &s = c->shapes (polygons.layer ()); - - if (vars.get ()) { - - const std::map &vv = vars->variants (c->cell_index ()); - for (std::map::const_iterator v = vv.begin (); v != vv.end (); ++v) { - - db::Shapes *st; - if (vv.size () == 1) { - st = & c->shapes (res->deep_layer ().layer ()); - } else { - st = & to_commit [c->cell_index ()] [v->first]; - } - - delivery delivery (&layout, st); - - const db::ICplxTrans &tr = v->first; - db::ICplxTrans trinv = tr.inverted (); - - for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) { - db::Polygon poly; - si->polygon (poly); - poly.transform (tr); - heap.clear (); - filter.process (poly, heap); - for (typename std::vector::const_iterator i = heap.begin (); i != heap.end (); ++i) { - delivery.put (i->transformed (trinv)); - } - } - - } - - } else { - - db::Shapes &st = c->shapes (res->deep_layer ().layer ()); - delivery delivery (&layout, &st); - - for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) { - db::Polygon poly; - si->polygon (poly); - heap.clear (); - filter.process (poly, heap); - for (typename std::vector::const_iterator i = heap.begin (); i != heap.end (); ++i) { - delivery.put (*i); - } - } - - } - - } - - if (! to_commit.empty () && vars.get ()) { - res->deep_layer ().commit_shapes (*vars, to_commit); - } - - if (filter.result_is_merged ()) { - res->set_is_merged (true); - } - return res.release (); + return shape_collection_processed_impl (filter.requires_raw_input () ? deep_layer () : merged_deep_layer (), filter); } RegionDelegate * @@ -1318,29 +1185,6 @@ DeepRegion::sized (coord_type d, unsigned int mode) const return res.release (); } -namespace -{ - -struct XYAnisotropyAndMagnificationReducer - : public db::TransformationReducer -{ - db::ICplxTrans reduce (const db::ICplxTrans &trans) const - { - double a = trans.angle (); - if (a > 180.0 - db::epsilon) { - a -= 180.0; - } - return db::ICplxTrans (trans.mag (), a, false, db::Vector ()); - } - - db::Trans reduce (const db::Trans &trans) const - { - return db::Trans (trans.angle () % 2, false, db::Vector ()); - } -}; - -} - RegionDelegate * DeepRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const { diff --git a/src/db/db/dbDeepRegion.h b/src/db/db/dbDeepRegion.h index 28dcdf0f8..1c672d430 100644 --- a/src/db/db/dbDeepRegion.h +++ b/src/db/db/dbDeepRegion.h @@ -164,10 +164,11 @@ public: return this; } + void set_is_merged (bool f); + protected: virtual void merged_semantics_changed (); virtual void min_coherence_changed (); - void set_is_merged (bool f); private: friend class DeepEdges; diff --git a/src/db/db/dbDeepTexts.cc b/src/db/db/dbDeepTexts.cc index 50f6e2623..264a36485 100644 --- a/src/db/db/dbDeepTexts.cc +++ b/src/db/db/dbDeepTexts.cc @@ -333,6 +333,12 @@ DeepTexts *DeepTexts::apply_filter (const TextFilterBase &filter) const return res.release (); } +RegionDelegate * +DeepTexts::processed_to_polygons (const TextToPolygonProcessorBase &filter) const +{ + return shape_collection_processed_impl (deep_layer (), filter); +} + RegionDelegate *DeepTexts::polygons (db::Coord e) const { db::DeepLayer new_layer = deep_layer ().derived (); diff --git a/src/db/db/dbDeepTexts.h b/src/db/db/dbDeepTexts.h index 812582b0d..8a447e4c4 100644 --- a/src/db/db/dbDeepTexts.h +++ b/src/db/db/dbDeepTexts.h @@ -65,6 +65,8 @@ public: virtual TextsDelegate *filter_in_place (const TextFilterBase &filter); virtual TextsDelegate *filtered (const TextFilterBase &) const; + virtual RegionDelegate *processed_to_polygons (const TextToPolygonProcessorBase &filter) const; + virtual TextsDelegate *add_in_place (const Texts &other); virtual TextsDelegate *add (const Texts &other) const; diff --git a/src/db/db/dbEdgePairs.cc b/src/db/db/dbEdgePairs.cc index fbafdcdff..36cd42b9d 100644 --- a/src/db/db/dbEdgePairs.cc +++ b/src/db/db/dbEdgePairs.cc @@ -143,6 +143,11 @@ EdgePairs::iter () const return *(i ? i : &def_iter); } +void EdgePairs::processed (Region &output, const EdgePairToPolygonProcessorBase &filter) const +{ + output = Region (mp_delegate->processed_to_polygons (filter)); +} + void EdgePairs::polygons (Region &output, db::Coord e) const { output.set_delegate (mp_delegate->polygons (e)); diff --git a/src/db/db/dbEdgePairs.h b/src/db/db/dbEdgePairs.h index 07947deaf..05cc26de0 100644 --- a/src/db/db/dbEdgePairs.h +++ b/src/db/db/dbEdgePairs.h @@ -465,6 +465,14 @@ public: return EdgePairs (mp_delegate->filtered (filter)); } + /** + * @brief Processes the edge pairs into polygons + * + * This method will run the processor over all edge pairs and return a region + * with the outputs of the processor. + */ + void processed (Region &output, const EdgePairToPolygonProcessorBase &filter) const; + /** * @brief Transforms the edge pair set */ diff --git a/src/db/db/dbEdgePairsDelegate.h b/src/db/db/dbEdgePairsDelegate.h index 0cd9798b6..83378446b 100644 --- a/src/db/db/dbEdgePairsDelegate.h +++ b/src/db/db/dbEdgePairsDelegate.h @@ -27,6 +27,7 @@ #include "dbCommon.h" #include "dbEdgePair.h" #include "dbShapeCollection.h" +#include "dbShapeCollectionUtils.h" namespace db { @@ -37,6 +38,8 @@ class RegionDelegate; class EdgesDelegate; class Layout; +typedef shape_collection_processor EdgePairToPolygonProcessorBase; + /** * @brief The edge pair set iterator delegate */ @@ -97,6 +100,7 @@ public: virtual EdgePairsDelegate *filter_in_place (const EdgePairFilterBase &filter) = 0; virtual EdgePairsDelegate *filtered (const EdgePairFilterBase &filter) const = 0; + virtual RegionDelegate *processed_to_polygons (const EdgePairToPolygonProcessorBase &filter) const = 0; virtual RegionDelegate *polygons (db::Coord e) const = 0; virtual EdgesDelegate *edges () const = 0; diff --git a/src/db/db/dbEdgesDelegate.h b/src/db/db/dbEdgesDelegate.h index 7b2ff0b18..6175dd69a 100644 --- a/src/db/db/dbEdgesDelegate.h +++ b/src/db/db/dbEdgesDelegate.h @@ -30,6 +30,7 @@ #include "dbEdgePairs.h" #include "dbEdgePairRelations.h" #include "dbShapeCollection.h" +#include "dbShapeCollectionUtils.h" #include @@ -128,32 +129,9 @@ public: virtual bool wants_variants () const = 0; }; -/** - * @brief A edge processor base class - */ -class DB_PUBLIC EdgeProcessorBase - : public edge_processor -{ - // .. nothing yet .. -}; - -/** - * @brief An edge-to-polygon processor base class - */ -class DB_PUBLIC EdgeToPolygonProcessorBase - : public edge_processor -{ - // .. nothing yet .. -}; - -/** - * @brief An edge-to-edge pair processor base class - */ -class DB_PUBLIC EdgeToEdgePairProcessorBase - : public edge_processor -{ - // .. nothing yet .. -}; +typedef shape_collection_processor EdgeProcessorBase; +typedef shape_collection_processor EdgeToPolygonProcessorBase; +typedef shape_collection_processor EdgeToEdgePairProcessorBase; class RecursiveShapeIterator; class EdgeFilterBase; diff --git a/src/db/db/dbEmptyEdgePairs.cc b/src/db/db/dbEmptyEdgePairs.cc index 6b14ac63c..9ea8afb3c 100644 --- a/src/db/db/dbEmptyEdgePairs.cc +++ b/src/db/db/dbEmptyEdgePairs.cc @@ -53,6 +53,12 @@ EmptyEdgePairs::polygons (db::Coord) const return new EmptyRegion (); } +RegionDelegate * +EmptyEdgePairs::processed_to_polygons (const EdgePairToPolygonProcessorBase &) const +{ + return new EmptyRegion (); +} + EdgesDelegate * EmptyEdgePairs::edges () const { diff --git a/src/db/db/dbEmptyEdgePairs.h b/src/db/db/dbEmptyEdgePairs.h index f811b5080..28a7a5401 100644 --- a/src/db/db/dbEmptyEdgePairs.h +++ b/src/db/db/dbEmptyEdgePairs.h @@ -55,6 +55,7 @@ public: virtual EdgePairsDelegate *filter_in_place (const EdgePairFilterBase &) { return this; } virtual EdgePairsDelegate *filtered (const EdgePairFilterBase &) const { return new EmptyEdgePairs (); } + virtual RegionDelegate *processed_to_polygons (const EdgePairToPolygonProcessorBase &filter) const; virtual RegionDelegate *polygons (db::Coord e) const; virtual EdgesDelegate *edges () const; diff --git a/src/db/db/dbEmptyTexts.cc b/src/db/db/dbEmptyTexts.cc index 9ef48abc2..09c4f902d 100644 --- a/src/db/db/dbEmptyTexts.cc +++ b/src/db/db/dbEmptyTexts.cc @@ -54,6 +54,12 @@ EmptyTexts::polygons (db::Coord) const return new EmptyRegion (); } +RegionDelegate * +EmptyTexts::processed_to_polygons (const TextToPolygonProcessorBase &) const +{ + return new EmptyRegion (); +} + EdgesDelegate * EmptyTexts::edges () const { diff --git a/src/db/db/dbEmptyTexts.h b/src/db/db/dbEmptyTexts.h index 99b1623ac..2724f3f59 100644 --- a/src/db/db/dbEmptyTexts.h +++ b/src/db/db/dbEmptyTexts.h @@ -56,6 +56,8 @@ public: virtual TextsDelegate *filter_in_place (const TextFilterBase &) { return this; } virtual TextsDelegate *filtered (const TextFilterBase &) const { return new EmptyTexts (); } + virtual RegionDelegate *processed_to_polygons (const TextToPolygonProcessorBase &) const; + virtual RegionDelegate *polygons (db::Coord e) const; virtual EdgesDelegate *edges () const; diff --git a/src/db/db/dbRegionDelegate.h b/src/db/db/dbRegionDelegate.h index 562f08ca7..e69f1d2e9 100644 --- a/src/db/db/dbRegionDelegate.h +++ b/src/db/db/dbRegionDelegate.h @@ -135,32 +135,9 @@ public: virtual bool wants_variants () const = 0; }; -/** - * @brief A polygon-to-polygon processor base class - */ -class DB_PUBLIC PolygonProcessorBase - : public polygon_processor -{ - // .. nothing yet .. -}; - -/** - * @brief A polygon-to-edge processor base class - */ -class DB_PUBLIC PolygonToEdgeProcessorBase - : public polygon_processor -{ - // .. nothing yet .. -}; - -/** - * @brief A polygon-to-edge pair processor base class - */ -class DB_PUBLIC PolygonToEdgePairProcessorBase - : public polygon_processor -{ - // .. nothing yet .. -}; +typedef shape_collection_processor PolygonProcessorBase; +typedef shape_collection_processor PolygonToEdgeProcessorBase; +typedef shape_collection_processor PolygonToEdgePairProcessorBase; /** * @brief The region iterator delegate diff --git a/src/db/db/dbRegionProcessors.cc b/src/db/db/dbRegionProcessors.cc index a41fc0f37..c03f76185 100644 --- a/src/db/db/dbRegionProcessors.cc +++ b/src/db/db/dbRegionProcessors.cc @@ -87,28 +87,6 @@ void CornerDetectorCore::detect_corners (const db::Polygon &poly, const CornerPo } } -// ----------------------------------------------------------------------------------- -// Extents implementation - -void Extents::process (const db::Polygon &poly, std::vector &result) const -{ - db::Box box = poly.box ().enlarged (db::Vector (m_dx, m_dy)); - if (! box.empty ()) { - result.push_back (db::Polygon (box)); - } -} - -const TransformationReducer *Extents::vars () const -{ - if (m_dx == 0 && m_dy == 0) { - return 0; - } else if (m_dx == m_dy) { - return & m_isotropic_reducer; - } else { - return & m_anisotropic_reducer; - } -} - // ----------------------------------------------------------------------------------- // RelativeExtents implementation diff --git a/src/db/db/dbRegionProcessors.h b/src/db/db/dbRegionProcessors.h index ce5ad5757..8d185075f 100644 --- a/src/db/db/dbRegionProcessors.h +++ b/src/db/db/dbRegionProcessors.h @@ -158,34 +158,6 @@ public: // ----------------------------------------------------------------------------------- // Extents -/** - * @brief A processor delivering the extents (bounding box) of the merged polygons - * This processor allows over- or undersizing of the resulting box by a given amount - */ -class DB_PUBLIC Extents - : public db::PolygonProcessorBase -{ -public: - Extents (db::Coord dx, db::Coord dy) - : m_dx (dx), m_dy (dy) - { - // .. nothing yet .. - } - - void process (const db::Polygon &poly, std::vector &result) const; - - virtual const TransformationReducer *vars () const; - virtual bool result_is_merged () const { return false; } - virtual bool result_must_not_be_merged () const { return false; } - virtual bool requires_raw_input () const { return false; } - virtual bool wants_variants () const { return true; } - -private: - db::Coord m_dx, m_dy; - db::MagnificationAndOrientationReducer m_anisotropic_reducer; - db::MagnificationReducer m_isotropic_reducer; -}; - /** * @brief A processor delivering the relative extents (bounding box) of the merged polygons * This processor allows over- or undersizing of the resulting box by a given amount and delivery diff --git a/src/db/db/dbShapeCollectionUtils.cc b/src/db/db/dbShapeCollectionUtils.cc new file mode 100644 index 000000000..0aa81e7ce --- /dev/null +++ b/src/db/db/dbShapeCollectionUtils.cc @@ -0,0 +1,23 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2020 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "dbShapeCollectionUtils.h" diff --git a/src/db/db/dbShapeCollectionUtils.h b/src/db/db/dbShapeCollectionUtils.h new file mode 100644 index 000000000..4f3fc8f0b --- /dev/null +++ b/src/db/db/dbShapeCollectionUtils.h @@ -0,0 +1,302 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2020 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#ifndef HDR_dbShapeCollectionUtils +#define HDR_dbShapeCollectionUtils + +#include "dbCommon.h" + +#include "dbShape.h" +#include "dbShapes.h" +#include "dbLayout.h" +#include "dbCellVariants.h" +#include "dbShapeCollection.h" +#include "dbDeepShapeStore.h" + +#include + +namespace db { + +/** + * @brief A template base class for edge processors + * + * A polygon processor can turn a edge into something else. + */ +template +class DB_PUBLIC_TEMPLATE shape_collection_processor +{ +public: + /** + * @brief Constructor + */ + shape_collection_processor () { } + + /** + * @brief Destructor + */ + virtual ~shape_collection_processor () { } + + /** + * @brief Performs the actual processing + * This method will take the input edge from "edge" and puts the results into "res". + * "res" can be empty - in this case, the edge will be skipped. + */ + virtual void process (const Shape &shape, std::vector &res) const = 0; + + /** + * @brief Returns the transformation reducer for building cell variants + * This method may return 0. In this case, not cell variants are built. + */ + virtual const TransformationReducer *vars () const = 0; + + /** + * @brief Returns true, if the result of this operation can be regarded "merged" always. + */ + virtual bool result_is_merged () const = 0; + + /** + * @brief Returns true, if the result of this operation must not be merged. + * This feature can be used, if the result represents "degenerated" objects such + * as point-like edges. These must not be merged. Otherwise they disappear. + */ + virtual bool result_must_not_be_merged () const = 0; + + /** + * @brief Returns true, if the processor wants raw (not merged) input + */ + virtual bool requires_raw_input () const = 0; + + /** + * @brief Returns true, if the processor wants to build variants + * If not true, the processor accepts shape propagation as variant resolution. + */ + virtual bool wants_variants () const = 0; +}; + +/** + * @brief A shape delivery class for the shape collection processor + */ +template struct shape_collection_processor_delivery; + +/** + * @brief A shape delivery implementation for polygons + */ +template <> +struct DB_PUBLIC shape_collection_processor_delivery +{ + shape_collection_processor_delivery (db::Layout *layout, db::Shapes *shapes) + : mp_layout (layout), mp_shapes (shapes) + { } + + void put (const db::Polygon &result) + { + tl::MutexLocker locker (&mp_layout->lock ()); + mp_shapes->insert (db::PolygonRef (result, mp_layout->shape_repository ())); + } + +private: + db::Layout *mp_layout; + db::Shapes *mp_shapes; +}; + +/** + * @brief A shape delivery implementation for texts + */ +template <> +struct DB_PUBLIC shape_collection_processor_delivery +{ + shape_collection_processor_delivery (db::Layout *layout, db::Shapes *shapes) + : mp_layout (layout), mp_shapes (shapes) + { } + + void put (const db::Text &result) + { + tl::MutexLocker locker (&mp_layout->lock ()); + mp_shapes->insert (db::TextRef (result, mp_layout->shape_repository ())); + } + +private: + db::Layout *mp_layout; + db::Shapes *mp_shapes; +}; + +/** + * @brief A generic delivery + */ +template +struct DB_PUBLIC shape_collection_processor_delivery +{ + shape_collection_processor_delivery (db::Layout *, db::Shapes *shapes) + : mp_shapes (shapes) + { } + + void put (const Result &result) + { + mp_shapes->insert (result); + } + +private: + db::Shapes *mp_shapes; +}; + +/** + * @brief Provides a generic implementation of the shape collection processor + */ +template +DB_PUBLIC_TEMPLATE +OutputContainer * +shape_collection_processed_impl (const db::DeepLayer &input, const shape_collection_processor &filter) +{ + std::auto_ptr vars; + if (filter.vars ()) { + + vars.reset (new db::VariantsCollectorBase (filter.vars ())); + + vars->collect (input.layout (), input.initial_cell ()); + + if (filter.wants_variants ()) { + const_cast (input).separate_variants (*vars); + } + + } + + db::Layout &layout = const_cast (input.layout ()); + + std::vector heap; + std::map > to_commit; + + std::auto_ptr res (new OutputContainer (input.derived ())); + if (filter.result_must_not_be_merged ()) { + res->set_merged_semantics (false); + } + + for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) { + + const db::Shapes &s = c->shapes (input.layer ()); + + if (vars.get ()) { + + const std::map &vv = vars->variants (c->cell_index ()); + for (std::map::const_iterator v = vv.begin (); v != vv.end (); ++v) { + + db::Shapes *st; + if (vv.size () == 1) { + st = & c->shapes (res->deep_layer ().layer ()); + } else { + st = & to_commit [c->cell_index ()] [v->first]; + } + + shape_collection_processor_delivery delivery (&layout, st); + + const db::ICplxTrans &tr = v->first; + db::ICplxTrans trinv = tr.inverted (); + + for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) { + Shape s; + si->instantiate (s); + s.transform (tr); + heap.clear (); + filter.process (s, heap); + for (typename std::vector::const_iterator i = heap.begin (); i != heap.end (); ++i) { + delivery.put (i->transformed (trinv)); + } + } + + } + + } else { + + db::Shapes &st = c->shapes (res->deep_layer ().layer ()); + shape_collection_processor_delivery delivery (&layout, &st); + + for (db::Shapes::shape_iterator si = s.begin (db::ShapeIterator::All); ! si.at_end (); ++si) { + Shape s; + si->instantiate (s); + heap.clear (); + filter.process (s, heap); + for (typename std::vector::const_iterator i = heap.begin (); i != heap.end (); ++i) { + delivery.put (*i); + } + } + + } + + } + + if (! to_commit.empty () && vars.get ()) { + res->deep_layer ().commit_shapes (*vars, to_commit); + } + + if (filter.result_is_merged ()) { + res->set_is_merged (true); + } + return res.release (); +} + +/** + * @brief A generic processor to compute the extents of an object + */ +template +class extents_processor + : public db::shape_collection_processor +{ +public: + extents_processor (db::Coord dx, db::Coord dy) + : m_dx (dx), m_dy (dy) + { } + + virtual void process (const Shape &s, std::vector &res) const + { + db::box_convert bc; + db::Box box = bc (s).enlarged (db::Vector (m_dx, m_dy)); + if (! box.empty ()) { + res.push_back (db::Polygon (box)); + } + } + + virtual const db::TransformationReducer *vars () const + { + if (m_dx == 0 && m_dy == 0) { + return 0; + } else if (m_dx == m_dy) { + return & m_isotropic_reducer; + } else { + return & m_anisotropic_reducer; + } + } + + virtual bool result_is_merged () const { return false; } + virtual bool requires_raw_input () const { return false; } + virtual bool result_must_not_be_merged () const { return false; } + virtual bool wants_variants () const { return true; } + +private: + db::XYAnisotropyAndMagnificationReducer m_anisotropic_reducer; + db::MagnificationReducer m_isotropic_reducer; + db::Coord m_dx, m_dy; +}; + +} + +#endif + diff --git a/src/db/db/dbTexts.cc b/src/db/db/dbTexts.cc index 6d1fbc5fd..1918be998 100644 --- a/src/db/db/dbTexts.cc +++ b/src/db/db/dbTexts.cc @@ -176,6 +176,11 @@ FlatTexts *Texts::flat_texts () return texts; } +void Texts::processed (Region &output, const TextToPolygonProcessorBase &filter) const +{ + output = Region (mp_delegate->processed_to_polygons (filter)); +} + void Texts::pull_interacting (Region &output, const Region &other) const { output = Region (mp_delegate->pull_interacting (other)); diff --git a/src/db/db/dbTexts.h b/src/db/db/dbTexts.h index 35ce50c05..3c11c92db 100644 --- a/src/db/db/dbTexts.h +++ b/src/db/db/dbTexts.h @@ -454,6 +454,14 @@ public: return Texts (mp_delegate->filtered (filter)); } + /** + * @brief Processes the edges into polygons + * + * This method will run the processor over all edges and return a region + * with the outputs of the processor. + */ + void processed (Region &output, const TextToPolygonProcessorBase &filter) const; + /** * @brief Selects all polygons of the other region set which include the texts of this text collection * diff --git a/src/db/db/dbTextsDelegate.h b/src/db/db/dbTextsDelegate.h index 551f91389..300be5c82 100644 --- a/src/db/db/dbTextsDelegate.h +++ b/src/db/db/dbTextsDelegate.h @@ -26,6 +26,7 @@ #include "dbCommon.h" #include "dbShapeCollection.h" +#include "dbShapeCollectionUtils.h" #include "dbText.h" namespace db { @@ -38,6 +39,8 @@ class RegionDelegate; class EdgesDelegate; class Layout; +typedef shape_collection_processor TextToPolygonProcessorBase; + /** * @brief The edge pair set iterator delegate */ @@ -98,6 +101,7 @@ public: virtual TextsDelegate *filter_in_place (const TextFilterBase &filter) = 0; virtual TextsDelegate *filtered (const TextFilterBase &filter) const = 0; + virtual RegionDelegate *processed_to_polygons (const TextToPolygonProcessorBase &filter) const = 0; virtual RegionDelegate *polygons (db::Coord e) const = 0; virtual EdgesDelegate *edges () const = 0; diff --git a/src/db/db/gsiDeclDbEdgePairs.cc b/src/db/db/gsiDeclDbEdgePairs.cc index c3d51f2a6..ec76c1b00 100644 --- a/src/db/db/gsiDeclDbEdgePairs.cc +++ b/src/db/db/gsiDeclDbEdgePairs.cc @@ -123,12 +123,9 @@ static db::Region polygons2 (const db::EdgePairs *e, db::Coord d) static db::Region extents2 (const db::EdgePairs *r, db::Coord dx, db::Coord dy) { - db::Region e; - e.reserve (r->size ()); - for (db::EdgePairs::const_iterator i = r->begin (); ! i.at_end (); ++i) { - e.insert (i->bbox ().enlarged (db::Vector (dx, dy))); - } - return e; + db::Region output; + r->processed (output, db::extents_processor (dx, dy)); + return output; } static db::Region extents1 (const db::EdgePairs *r, db::Coord d) diff --git a/src/db/db/gsiDeclDbEdges.cc b/src/db/db/gsiDeclDbEdges.cc index 6563e9c55..39d943395 100644 --- a/src/db/db/gsiDeclDbEdges.cc +++ b/src/db/db/gsiDeclDbEdges.cc @@ -325,12 +325,9 @@ static db::Region pull_interacting (const db::Edges *r, const db::Region &other) static db::Region extents2 (const db::Edges *r, db::Coord dx, db::Coord dy) { - db::Region e; - e.reserve (r->size ()); - for (db::Edges::const_iterator i = r->begin (); ! i.at_end (); ++i) { - e.insert (i->bbox ().enlarged (db::Vector (dx, dy))); - } - return e; + db::Region output; + r->processed (output, db::extents_processor (dx, dy)); + return output; } static db::Region extents1 (const db::Edges *r, db::Coord d) diff --git a/src/db/db/gsiDeclDbRegion.cc b/src/db/db/gsiDeclDbRegion.cc index a1c87aade..3adf813e4 100644 --- a/src/db/db/gsiDeclDbRegion.cc +++ b/src/db/db/gsiDeclDbRegion.cc @@ -259,7 +259,7 @@ static db::Region moved_xy (const db::Region *r, db::Coord x, db::Coord y) static db::Region extents2 (const db::Region *r, db::Coord dx, db::Coord dy) { - return r->processed (db::Extents (dx, dy)); + return r->processed (db::extents_processor (dx, dy)); } static db::Region extents1 (const db::Region *r, db::Coord d) diff --git a/src/db/db/gsiDeclDbTexts.cc b/src/db/db/gsiDeclDbTexts.cc index f7c33c1cb..e2b6339b2 100644 --- a/src/db/db/gsiDeclDbTexts.cc +++ b/src/db/db/gsiDeclDbTexts.cc @@ -116,12 +116,9 @@ static db::Region polygons0 (const db::Texts *e, db::Coord d) static db::Region extents1 (const db::Texts *r, db::Coord dx, db::Coord dy) { - db::Region e; - e.reserve (r->size ()); - for (db::Texts::const_iterator i = r->begin (); ! i.at_end (); ++i) { - e.insert (i->box ().enlarged (db::Vector (dx, dy))); - } - return e; + db::Region output; + r->processed (output, db::extents_processor (dx, dy)); + return output; } static db::Region extents0 (const db::Texts *r, db::Coord d) diff --git a/src/db/unit_tests/dbDeepRegionTests.cc b/src/db/unit_tests/dbDeepRegionTests.cc index 22b4e6ef3..e4792df01 100644 --- a/src/db/unit_tests/dbDeepRegionTests.cc +++ b/src/db/unit_tests/dbDeepRegionTests.cc @@ -1176,8 +1176,8 @@ TEST(21_Processors) target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), r1.processed (db::CornersAsRectangles (-180.0, 180.0, 2000))); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (14, 0)), r1.processed (db::CornersAsRectangles (0.0, 180.0, 2000))); - target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r1.processed (db::Extents (0, 0))); - target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), r1.processed (db::Extents (1000, 2000))); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r1.processed (db::extents_processor (0, 0))); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), r1.processed (db::extents_processor (1000, 2000))); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (22, 0)), r1.processed (db::RelativeExtents (0, 0, 1.0, 1.0, 0, 0))); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (23, 0)), r1.processed (db::RelativeExtents (0.25, 0.4, 0.75, 0.6, 1000, 2000))); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (24, 0)), r1.processed (db::RelativeExtentsAsEdges (0, 0, 1.0, 1.0))); diff --git a/src/db/unit_tests/dbRegionTests.cc b/src/db/unit_tests/dbRegionTests.cc index 6addaa424..c5b7c56fc 100644 --- a/src/db/unit_tests/dbRegionTests.cc +++ b/src/db/unit_tests/dbRegionTests.cc @@ -1589,8 +1589,8 @@ TEST(100_Processors) EXPECT_EQ (r.processed (db::CornersAsRectangles (-180.0, 180.0, 2)).to_string (), "(98,-2;98,2;102,2;102,-2);(-2,-2;-2,2;2,2;2,-2);(-2,198;-2,202;2,202;2,198);(98,198;98,202;102,202;102,198);(198,298;198,302;202,302;202,298);(-2,298;-2,302;2,302;2,298);(-2,398;-2,402;2,402;2,398);(98,398;98,402;102,402;102,398);(98,498;98,502;102,502;102,498);(198,498;198,502;202,502;202,498)"); EXPECT_EQ (r.processed (db::CornersAsRectangles (0.0, 180.0, 2)).to_string (), "(98,398;98,402;102,402;102,398)"); - EXPECT_EQ (r.processed (db::Extents (0, 0)).to_string (), "(0,0;0,200;100,200;100,0);(0,300;0,500;200,500;200,300)"); - EXPECT_EQ (r.processed (db::Extents (10, 20)).to_string (), "(-10,-20;-10,220;110,220;110,-20);(-10,280;-10,520;210,520;210,280)"); + EXPECT_EQ (r.processed (db::extents_processor (0, 0)).to_string (), "(0,0;0,200;100,200;100,0);(0,300;0,500;200,500;200,300)"); + EXPECT_EQ (r.processed (db::extents_processor (10, 20)).to_string (), "(-10,-20;-10,220;110,220;110,-20);(-10,280;-10,520;210,520;210,280)"); EXPECT_EQ (r.processed (db::RelativeExtents (0, 0, 1.0, 1.0, 0, 0)).to_string (), "(0,0;0,200;100,200;100,0);(0,300;0,500;200,500;200,300)"); EXPECT_EQ (r.processed (db::RelativeExtents (0.25, 0.4, 0.75, 0.6, 10, 20)).to_string (), "(15,60;15,140;85,140;85,60);(40,360;40,440;160,440;160,360)"); EXPECT_EQ (r.processed (db::RelativeExtentsAsEdges (0, 0, 1.0, 1.0)).to_string (), "(0,0;100,200);(0,300;200,500)"); diff --git a/src/drc/unit_tests/drcSimpleTests.cc b/src/drc/unit_tests/drcSimpleTests.cc index dad8bbc50..c7d80eb95 100644 --- a/src/drc/unit_tests/drcSimpleTests.cc +++ b/src/drc/unit_tests/drcSimpleTests.cc @@ -714,3 +714,44 @@ TEST(15_issue548) db::compare_layouts (_this, layout, au, db::NoNormalization); } + +// Edges::extents isn't deep-enabled +TEST(16_issue570) +{ + std::string rs = tl::testsrc (); + rs += "/testdata/drc/drcSimpleTests_16.drc"; + + std::string input = tl::testsrc (); + input += "/testdata/drc/drcSimpleTests_16.gds"; + + std::string au = tl::testsrc (); + au += "/testdata/drc/drcSimpleTests_au16.gds"; + + std::string output = this->tmp_file ("tmp.gds"); + + { + // Set some variables + lym::Macro config; + config.set_text (tl::sprintf ( + "$drc_test_source = '%s'\n" + "$drc_test_target = '%s'\n" + , input, output) + ); + config.set_interpreter (lym::Macro::Ruby); + EXPECT_EQ (config.run (), 0); + } + + lym::Macro drc; + drc.load_from (rs); + EXPECT_EQ (drc.run (), 0); + + db::Layout layout; + + { + tl::InputStream stream (output); + db::Reader reader (stream); + reader.read (layout); + } + + db::compare_layouts (_this, layout, au, db::NoNormalization); +} diff --git a/testdata/drc/drcSimpleTests_16.drc b/testdata/drc/drcSimpleTests_16.drc new file mode 100644 index 000000000..d25a60456 --- /dev/null +++ b/testdata/drc/drcSimpleTests_16.drc @@ -0,0 +1,16 @@ + +source($drc_test_source) +target($drc_test_target) + +deep + +input(2,0).output(2, 0) +input(3,0).output(3, 0) +input(4,0).output(4, 0) +input(9,0).output(9, 0) + +input(2,0).edges.extents(10.nm, 10.nm).output(102, 0) +input(3,0).edges.extents(10.nm, 20.nm).output(103, 0) +input(4,0).edges.extents(20.nm, 10.nm).output(104, 0) +input(9,0).edges.extents(20.nm).output(109, 0) + diff --git a/testdata/drc/drcSimpleTests_16.gds b/testdata/drc/drcSimpleTests_16.gds new file mode 100644 index 000000000..c6807b1fd Binary files /dev/null and b/testdata/drc/drcSimpleTests_16.gds differ diff --git a/testdata/drc/drcSimpleTests_au16.gds b/testdata/drc/drcSimpleTests_au16.gds new file mode 100644 index 000000000..a57544a24 Binary files /dev/null and b/testdata/drc/drcSimpleTests_au16.gds differ diff --git a/testdata/drc/ringo.gds b/testdata/drc/ringo.gds index fa116f14d..6163496d4 100644 Binary files a/testdata/drc/ringo.gds and b/testdata/drc/ringo.gds differ