mirror of https://github.com/KLayout/klayout.git
Region: hierarchical text object detection implementated.
This commit is contained in:
parent
c7b17fb65a
commit
3c6aafcc0c
|
|
@ -426,6 +426,33 @@ DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator
|
|||
return DeepLayer (this, layout_index, layer_index);
|
||||
}
|
||||
|
||||
DeepLayer DeepShapeStore::create_custom_layer (const db::RecursiveShapeIterator &si, HierarchyBuilderShapeReceiver *pipe, const db::ICplxTrans &trans)
|
||||
{
|
||||
unsigned int layout_index = layout_for_iter (si, trans);
|
||||
|
||||
db::Layout &layout = m_layouts[layout_index]->layout;
|
||||
db::HierarchyBuilder &builder = m_layouts[layout_index]->builder;
|
||||
|
||||
unsigned int layer_index = layout.insert_layer ();
|
||||
builder.set_target_layer (layer_index);
|
||||
|
||||
// Build the working hierarchy from the recursive shape iterator
|
||||
try {
|
||||
|
||||
tl::SelfTimer timer (tl::verbosity () >= 41, tl::to_string (tr ("Building working hierarchy")));
|
||||
|
||||
builder.set_shape_receiver (pipe);
|
||||
db::RecursiveShapeIterator (si).push (& builder);
|
||||
builder.set_shape_receiver (0);
|
||||
|
||||
} catch (...) {
|
||||
builder.set_shape_receiver (0);
|
||||
throw;
|
||||
}
|
||||
|
||||
return DeepLayer (this, layout_index, layer_index);
|
||||
}
|
||||
|
||||
DeepLayer DeepShapeStore::create_edge_layer (const db::RecursiveShapeIterator &si, bool as_edges, const db::ICplxTrans &trans)
|
||||
{
|
||||
unsigned int layout_index = layout_for_iter (si, trans);
|
||||
|
|
|
|||
|
|
@ -285,6 +285,15 @@ public:
|
|||
*/
|
||||
DeepLayer create_edge_pair_layer (const db::RecursiveShapeIterator &si, const ICplxTrans &trans = db::ICplxTrans ());
|
||||
|
||||
/**
|
||||
* @brief Inserts a polygon layer into the deep shape store using a custom preparation pipeline
|
||||
*
|
||||
* This method will create a new layer inside the deep shapes store and
|
||||
* feed it through the given pipeline. The pipeline may perform shape translations and
|
||||
* finally will feed the target hierarchy.
|
||||
*/
|
||||
DeepLayer create_custom_layer (const db::RecursiveShapeIterator &si, HierarchyBuilderShapeReceiver *pipe, const ICplxTrans &trans = db::ICplxTrans ());
|
||||
|
||||
/**
|
||||
* @brief Inserts the deep layer's shapes into some target layout
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -23,8 +23,13 @@
|
|||
|
||||
#include "dbOriginalLayerRegion.h"
|
||||
#include "dbFlatRegion.h"
|
||||
#include "dbFlatEdges.h"
|
||||
#include "dbRegion.h"
|
||||
#include "dbShapeProcessor.h"
|
||||
#include "dbDeepEdges.h"
|
||||
#include "dbDeepRegion.h"
|
||||
#include "dbDeepShapeStore.h"
|
||||
#include "tlGlobPattern.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
|
@ -279,4 +284,165 @@ OriginalLayerRegion::ensure_merged_polygons_valid () const
|
|||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
template <class Container>
|
||||
struct dot_delivery
|
||||
{
|
||||
typedef Container container_type;
|
||||
|
||||
dot_delivery ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void insert (const db::Point &pt, Container *container) const
|
||||
{
|
||||
container->insert (db::Edge (pt, pt));
|
||||
}
|
||||
};
|
||||
|
||||
template <class Container>
|
||||
struct box_delivery
|
||||
{
|
||||
typedef Container container_type;
|
||||
|
||||
box_delivery (db::Coord enl)
|
||||
: m_d (enl, enl)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void insert (const db::Point &pt, Container *container) const
|
||||
{
|
||||
container->insert (db::Box (pt - m_d, pt + m_d));
|
||||
}
|
||||
|
||||
private:
|
||||
db::Vector m_d;
|
||||
};
|
||||
|
||||
template <class Iter, class Delivery>
|
||||
static void fill_texts (const Iter &iter, const std::string &pat, bool pattern, const Delivery &delivery, typename Delivery::container_type *container)
|
||||
{
|
||||
tl::GlobPattern glob_pat;
|
||||
bool all = false;
|
||||
if (pattern) {
|
||||
if (pat == "*") {
|
||||
all = true;
|
||||
} else {
|
||||
glob_pat = tl::GlobPattern (pat);
|
||||
}
|
||||
}
|
||||
|
||||
for (Iter si = iter; ! si.at_end (); ++si) {
|
||||
if (si->is_text () &&
|
||||
(all || (pattern && glob_pat.match (si->text_string ())) || (!pattern && si->text_string () == pat))) {
|
||||
db::Text t;
|
||||
si->text (t);
|
||||
t.transform (si.trans ());
|
||||
delivery.insert (t.box ().center (), container);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class Delivery>
|
||||
class text_shape_receiver
|
||||
: public db::HierarchyBuilderShapeReceiver
|
||||
{
|
||||
public:
|
||||
text_shape_receiver (const Delivery &delivery, const std::string &pat, bool pattern)
|
||||
: m_delivery (delivery), m_glob_pat (), m_all (false), m_pattern (pattern), m_pat (pat)
|
||||
{
|
||||
if (pattern) {
|
||||
if (m_pat == "*") {
|
||||
m_all = true;
|
||||
} else {
|
||||
m_glob_pat = tl::GlobPattern (pat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box ®ion, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
|
||||
{
|
||||
if (shape.is_text () &&
|
||||
(m_all || (m_pattern && m_glob_pat.match (shape.text_string ())) || (!m_pattern && shape.text_string () == m_pat))) {
|
||||
|
||||
db::Point pt = shape.bbox ().center ();
|
||||
|
||||
if (! complex_region) {
|
||||
if (region.contains (pt)) {
|
||||
m_delivery.insert (pt.transformed (trans), target);
|
||||
}
|
||||
} else {
|
||||
if (! complex_region->begin_overlapping (db::Box (pt, pt), db::box_convert<db::Box> ()).at_end ()) {
|
||||
m_delivery.insert (pt.transformed (trans), target);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
virtual void push (const db::Box &, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
|
||||
virtual void push (const db::Polygon &, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
|
||||
|
||||
private:
|
||||
Delivery m_delivery;
|
||||
tl::GlobPattern m_glob_pat;
|
||||
bool m_all;
|
||||
bool m_pattern;
|
||||
std::string m_pat;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
db::EdgesDelegate *
|
||||
OriginalLayerRegion::texts_as_dots (const std::string &pat, bool pattern) const
|
||||
{
|
||||
db::RecursiveShapeIterator iter (m_iter);
|
||||
iter.shape_flags (db::ShapeIterator::Texts);
|
||||
|
||||
std::auto_ptr<db::FlatEdges> res (new db::FlatEdges ());
|
||||
res->set_merged_semantics (false);
|
||||
|
||||
fill_texts (iter, pat, pattern, dot_delivery<db::FlatEdges> (), res.get ());
|
||||
|
||||
return res.release ();
|
||||
}
|
||||
|
||||
db::EdgesDelegate *
|
||||
OriginalLayerRegion::texts_as_dots (const std::string &pat, bool pattern, db::DeepShapeStore &store) const
|
||||
{
|
||||
db::RecursiveShapeIterator iter (m_iter);
|
||||
iter.shape_flags (db::ShapeIterator::Texts);
|
||||
|
||||
text_shape_receiver<dot_delivery<db::Shapes> > pipe = text_shape_receiver<dot_delivery<db::Shapes> > (dot_delivery<db::Shapes> (), pat, pattern);
|
||||
return new db::DeepEdges (store.create_custom_layer (iter, &pipe));
|
||||
}
|
||||
|
||||
db::RegionDelegate *
|
||||
OriginalLayerRegion::texts_as_boxes (const std::string &pat, bool pattern, db::Coord enl) const
|
||||
{
|
||||
db::RecursiveShapeIterator iter (m_iter);
|
||||
iter.shape_flags (db::ShapeIterator::Texts);
|
||||
|
||||
std::auto_ptr<db::FlatRegion> res (new db::FlatRegion ());
|
||||
res->set_merged_semantics (false);
|
||||
|
||||
fill_texts (iter, pat, pattern, box_delivery<db::FlatRegion> (enl), res.get ());
|
||||
|
||||
return res.release ();
|
||||
}
|
||||
|
||||
db::RegionDelegate *
|
||||
OriginalLayerRegion::texts_as_boxes (const std::string &pat, bool pattern, db::Coord enl, db::DeepShapeStore &store) const
|
||||
{
|
||||
db::RecursiveShapeIterator iter (m_iter);
|
||||
iter.shape_flags (db::ShapeIterator::Texts);
|
||||
|
||||
text_shape_receiver<box_delivery<db::Shapes> > pipe = text_shape_receiver<box_delivery<db::Shapes> > (box_delivery<db::Shapes> (enl), pat, pattern);
|
||||
return new db::DeepRegion (store.create_custom_layer (iter, &pipe));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@
|
|||
|
||||
namespace db {
|
||||
|
||||
class EdgesDelegate;
|
||||
class RegionDelegate;
|
||||
class DeepShapeStore;
|
||||
|
||||
/**
|
||||
* @brief An original layerregion based on a RecursiveShapeIterator
|
||||
*/
|
||||
|
|
@ -64,6 +68,11 @@ public:
|
|||
virtual bool equals (const Region &other) const;
|
||||
virtual bool less (const Region &other) const;
|
||||
|
||||
db::EdgesDelegate *texts_as_dots (const std::string &pat, bool pattern) const;
|
||||
db::EdgesDelegate *texts_as_dots (const std::string &pat, bool pattern, db::DeepShapeStore &store) const;
|
||||
db::RegionDelegate *texts_as_boxes (const std::string &pat, bool pattern, db::Coord enl) const;
|
||||
db::RegionDelegate *texts_as_boxes (const std::string &pat, bool pattern, db::Coord enl, db::DeepShapeStore &store) const;
|
||||
|
||||
protected:
|
||||
virtual void merged_semantics_changed ();
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "dbEdgesUtils.h"
|
||||
#include "dbDeepEdges.h"
|
||||
#include "dbRegion.h"
|
||||
#include "dbOriginalLayerRegion.h"
|
||||
#include "dbLayoutUtils.h"
|
||||
|
||||
namespace gsi
|
||||
|
|
@ -389,6 +390,17 @@ static bool is_deep (const db::Edges *e)
|
|||
return dynamic_cast<const db::DeepEdges *> (e->delegate ()) != 0;
|
||||
}
|
||||
|
||||
static db::Edges *new_texts_as_dots1 (const db::RecursiveShapeIterator &si, const std::string &pat, bool pattern)
|
||||
{
|
||||
return new db::Edges (db::OriginalLayerRegion (si, false).texts_as_dots (pat, pattern));
|
||||
}
|
||||
|
||||
static db::Edges *new_texts_as_dots2 (const db::RecursiveShapeIterator &si, db::DeepShapeStore &dss, const std::string &pat, bool pattern)
|
||||
{
|
||||
return new db::Edges (db::OriginalLayerRegion (si, false).texts_as_dots (pat, pattern, dss));
|
||||
}
|
||||
|
||||
|
||||
Class<db::Edges> dec_Edges ("db", "Edges",
|
||||
constructor ("new", &new_v,
|
||||
"@brief Default constructor\n"
|
||||
|
|
@ -519,6 +531,47 @@ Class<db::Edges> dec_Edges ("db", "Edges",
|
|||
"r = RBA::Edges::new(layout.begin_shapes(cell, layer), dss, RBA::ICplxTrans::new(layout.dbu / dbu), false)\n"
|
||||
"@/code\n"
|
||||
) +
|
||||
constructor ("new", &new_texts_as_dots1, gsi::arg("shape_iterator"), gsi::arg ("expr"), gsi::arg ("as_pattern", true),
|
||||
"@brief Constructor from a text set\n"
|
||||
"\n"
|
||||
"@param shape_iterator The iterator from which to derive the texts\n"
|
||||
"@param expr The selection string\n"
|
||||
"@param as_pattern If true, the selection string is treated as a glob pattern. Otherwise the match is exact.\n"
|
||||
"\n"
|
||||
"This special constructor will create dot-like edges from the text objects delivered by the shape iterator. "
|
||||
"Each text object will give a degenerated edge (a dot) that represents the text origin.\n"
|
||||
"Texts can be selected by their strings - either through a glob pattern or by exact comparison with "
|
||||
"the given string. The following options are available:\n"
|
||||
"\n"
|
||||
"@code\n"
|
||||
"dots = RBA::Edges::new(iter, \"*\") # all texts\n"
|
||||
"dots = RBA::Edges::new(iter, \"A*\") # all texts starting with an 'A'\n"
|
||||
"dots = RBA::Edges::new(iter, \"A*\", false) # all texts exactly matchin 'A*'\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.\n"
|
||||
) +
|
||||
constructor ("new", &new_texts_as_dots2, gsi::arg("shape_iterator"), gsi::arg ("dss"), gsi::arg ("expr"), gsi::arg ("as_pattern", true),
|
||||
"@brief Constructor from a text set\n"
|
||||
"\n"
|
||||
"@param shape_iterator The iterator from which to derive the texts\n"
|
||||
"@param dss The \\DeepShapeStore object that acts as a heap for hierarchical operations.\n"
|
||||
"@param expr The selection string\n"
|
||||
"@param as_pattern If true, the selection string is treated as a glob pattern. Otherwise the match is exact.\n"
|
||||
"\n"
|
||||
"This special constructor will create a deep edge set from the text objects delivered by the shape iterator. "
|
||||
"Each text object will give a degenerated edge (a dot) that represents the text origin.\n"
|
||||
"Texts can be selected by their strings - either through a glob pattern or by exact comparison with "
|
||||
"the given string. The following options are available:\n"
|
||||
"\n"
|
||||
"@code\n"
|
||||
"region = RBA::Region::new(iter, dss, \"*\") # all texts\n"
|
||||
"region = RBA::Region::new(iter, dss, \"A*\") # all texts starting with an 'A'\n"
|
||||
"region = RBA::Region::new(iter, dss, \"A*\", false) # all texts exactly matchin 'A*'\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.\n"
|
||||
) +
|
||||
method ("insert_into", &db::Edges::insert_into, gsi::arg ("layout"), gsi::arg ("cell_index"), gsi::arg ("layer"),
|
||||
"@brief Inserts this edge collection into the given layout, below the given cell and into the given layer.\n"
|
||||
"If the edge collection is a hierarchical one, a suitable hierarchy will be built below the top cell or "
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include "dbRegion.h"
|
||||
#include "dbRegionUtils.h"
|
||||
#include "dbDeepRegion.h"
|
||||
#include "dbOriginalLayerRegion.h"
|
||||
#include "dbPolygonTools.h"
|
||||
#include "dbLayoutUtils.h"
|
||||
#include "dbShapes.h"
|
||||
|
|
@ -77,77 +78,43 @@ static db::Region *new_shapes (const db::Shapes &s)
|
|||
return r;
|
||||
}
|
||||
|
||||
struct DotDelivery
|
||||
static db::Region *new_texts_as_boxes1 (const db::RecursiveShapeIterator &si, const std::string &pat, bool pattern, db::Coord enl)
|
||||
{
|
||||
typedef db::Edges container_type;
|
||||
|
||||
DotDelivery () : container ()
|
||||
{
|
||||
container.reset (new container_type ());
|
||||
container->set_merged_semantics (false);
|
||||
}
|
||||
|
||||
void insert (const db::Point &pt)
|
||||
{
|
||||
container->insert (db::Edge (pt, pt));
|
||||
}
|
||||
|
||||
std::auto_ptr<container_type> container;
|
||||
};
|
||||
|
||||
struct BoxDelivery
|
||||
{
|
||||
typedef db::Region container_type;
|
||||
|
||||
BoxDelivery () : container ()
|
||||
{
|
||||
container.reset (new container_type ());
|
||||
}
|
||||
|
||||
void insert (const db::Point &pt)
|
||||
{
|
||||
container->insert (db::Box (pt - db::Vector (1, 1), pt + db::Vector (1, 1)));
|
||||
}
|
||||
|
||||
std::auto_ptr<container_type> container;
|
||||
};
|
||||
|
||||
template <class Delivery>
|
||||
static typename Delivery::container_type *new_texts (const db::RecursiveShapeIterator &si_in, const std::string &pat, bool pattern)
|
||||
{
|
||||
db::RecursiveShapeIterator si (si_in);
|
||||
si.shape_flags (db::ShapeIterator::Texts);
|
||||
|
||||
tl::GlobPattern glob_pat;
|
||||
bool all = false;
|
||||
if (pattern) {
|
||||
if (pat == "*") {
|
||||
all = true;
|
||||
} else {
|
||||
glob_pat = tl::GlobPattern (pat);
|
||||
}
|
||||
}
|
||||
|
||||
Delivery delivery;
|
||||
|
||||
while (! si.at_end ()) {
|
||||
if (si.shape ().is_text () &&
|
||||
(all || (pattern && glob_pat.match (si.shape ().text_string ())) || (!pattern && si.shape ().text_string () == pat))) {
|
||||
db::Text t;
|
||||
si.shape ().text (t);
|
||||
t.transform (si.trans ());
|
||||
delivery.insert (t.box ().center ());
|
||||
}
|
||||
si.next ();
|
||||
}
|
||||
|
||||
return delivery.container.release ();
|
||||
return new db::Region (db::OriginalLayerRegion (si, false).texts_as_boxes (pat, pattern, enl));
|
||||
}
|
||||
|
||||
template <class Delivery>
|
||||
static typename Delivery::container_type *texts (const db::Region *r, const std::string &pat, bool pattern)
|
||||
static db::Region *new_texts_as_boxes2 (const db::RecursiveShapeIterator &si, db::DeepShapeStore &dss, const std::string &pat, bool pattern, db::Coord enl)
|
||||
{
|
||||
return new_texts<Delivery> (r->iter (), pat, pattern);
|
||||
return new db::Region (db::OriginalLayerRegion (si, false).texts_as_boxes (pat, pattern, enl, dss));
|
||||
}
|
||||
|
||||
static const db::OriginalLayerRegion *org_layer (const db::Region *r)
|
||||
{
|
||||
const db::OriginalLayerRegion *org_layer = dynamic_cast<const db::OriginalLayerRegion *> (r->delegate ());
|
||||
if (! org_layer) {
|
||||
throw tl::Exception (tl::to_string (tr ("Texts can only be identified on an original layer")));
|
||||
}
|
||||
return org_layer;
|
||||
}
|
||||
|
||||
static db::Edges *texts_as_dots1 (const db::Region *r, const std::string &pat, bool pattern)
|
||||
{
|
||||
return new db::Edges (org_layer (r)->texts_as_dots (pat, pattern));
|
||||
}
|
||||
|
||||
static db::Edges *texts_as_dots2 (const db::Region *r, db::DeepShapeStore &dss, const std::string &pat, bool pattern)
|
||||
{
|
||||
return new db::Edges (org_layer (r)->texts_as_dots (pat, pattern, dss));
|
||||
}
|
||||
|
||||
static db::Region *texts_as_boxes1 (const db::Region *r, const std::string &pat, bool pattern, db::Coord enl)
|
||||
{
|
||||
return new db::Region (org_layer (r)->texts_as_boxes (pat, pattern, enl));
|
||||
}
|
||||
|
||||
static db::Region *texts_as_boxes2 (const db::Region *r, db::DeepShapeStore &dss, const std::string &pat, bool pattern, db::Coord enl)
|
||||
{
|
||||
return new db::Region (org_layer (r)->texts_as_boxes (pat, pattern, enl, dss));
|
||||
}
|
||||
|
||||
static db::Edges corners_to_dots (const db::Region *r, double angle_start, double angle_end)
|
||||
|
|
@ -730,12 +697,13 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"\n"
|
||||
"This method has been introduced in version 0.26.\n"
|
||||
) +
|
||||
constructor ("new", &new_texts<BoxDelivery>, gsi::arg("shape_iterator"), gsi::arg ("expr"), gsi::arg ("as_pattern", true),
|
||||
constructor ("new", &new_texts_as_boxes1, gsi::arg("shape_iterator"), gsi::arg ("expr"), gsi::arg ("as_pattern", true), gsi::arg ("enl", 1),
|
||||
"@brief Constructor from a text set\n"
|
||||
"\n"
|
||||
"@param shape_iterator The iterator from which to derive the texts\n"
|
||||
"@param expr The selection string\n"
|
||||
"@param as_pattern If true, the selection string is treated as a glob pattern. Otherwise the match is exact.\n"
|
||||
"@param enl The per-side enlargement of the box to mark the text (1 gives a 2x2 DBU box)"
|
||||
"\n"
|
||||
"This special constructor will create a region from the text objects delivered by the shape iterator. "
|
||||
"Each text object will give a small (non-empty) box that represents the text origin.\n"
|
||||
|
|
@ -748,7 +716,29 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"region = RBA::Region::new(iter, \"A*\", false) # all texts exactly matchin 'A*'\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25."
|
||||
"This method has been introduced in version 0.25. The enlargement parameter has been added in version 0.26.\n"
|
||||
) +
|
||||
constructor ("new", &new_texts_as_boxes2, gsi::arg("shape_iterator"), gsi::arg ("dss"), gsi::arg ("expr"), gsi::arg ("as_pattern", true), gsi::arg ("enl", 1),
|
||||
"@brief Constructor from a text set\n"
|
||||
"\n"
|
||||
"@param shape_iterator The iterator from which to derive the texts\n"
|
||||
"@param dss The \\DeepShapeStore object that acts as a heap for hierarchical operations.\n"
|
||||
"@param expr The selection string\n"
|
||||
"@param as_pattern If true, the selection string is treated as a glob pattern. Otherwise the match is exact.\n"
|
||||
"@param enl The per-side enlargement of the box to mark the text (1 gives a 2x2 DBU box)"
|
||||
"\n"
|
||||
"This special constructor will create a deep region from the text objects delivered by the shape iterator. "
|
||||
"Each text object will give a small (non-empty) box that represents the text origin.\n"
|
||||
"Texts can be selected by their strings - either through a glob pattern or by exact comparison with "
|
||||
"the given string. The following options are available:\n"
|
||||
"\n"
|
||||
"@code\n"
|
||||
"region = RBA::Region::new(iter, dss, \"*\") # all texts\n"
|
||||
"region = RBA::Region::new(iter, dss, \"A*\") # all texts starting with an 'A'\n"
|
||||
"region = RBA::Region::new(iter, dss, \"A*\", false) # all texts exactly matchin 'A*'\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"This variant has been introduced in version 0.26.\n"
|
||||
) +
|
||||
method ("insert_into", &db::Region::insert_into, gsi::arg ("layout"), gsi::arg ("cell_index"), gsi::arg ("layer"),
|
||||
"@brief Inserts this region into the given layout, below the given cell and into the given layer.\n"
|
||||
|
|
@ -757,11 +747,19 @@ Class<db::Region> decl_Region ("db", "Region",
|
|||
"\n"
|
||||
"This method has been introduced in version 0.26."
|
||||
) +
|
||||
factory_ext ("texts", &texts<BoxDelivery>, gsi::arg ("expr", std::string ("*")), gsi::arg ("as_pattern", true),
|
||||
factory_ext ("texts", &texts_as_boxes1, gsi::arg ("expr", std::string ("*")), gsi::arg ("as_pattern", true), gsi::arg ("enl", 1),
|
||||
"@hide\n"
|
||||
"This method is provided for DRC implementation only."
|
||||
) +
|
||||
factory_ext ("texts_dots", &texts<DotDelivery>, gsi::arg ("expr", std::string ("*")), gsi::arg ("as_pattern", true),
|
||||
factory_ext ("texts", &texts_as_boxes2, gsi::arg ("dss"), gsi::arg ("expr", std::string ("*")), gsi::arg ("as_pattern", true), gsi::arg ("enl", 1),
|
||||
"@hide\n"
|
||||
"This method is provided for DRC implementation only."
|
||||
) +
|
||||
factory_ext ("texts_dots", &texts_as_dots1, gsi::arg ("expr", std::string ("*")), gsi::arg ("as_pattern", true),
|
||||
"@hide\n"
|
||||
"This method is provided for DRC implementation only."
|
||||
) +
|
||||
factory_ext ("texts_dots", &texts_as_dots2, gsi::arg ("dss"), gsi::arg ("expr", std::string ("*")), gsi::arg ("as_pattern", true),
|
||||
"@hide\n"
|
||||
"This method is provided for DRC implementation only."
|
||||
) +
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "dbRegionProcessors.h"
|
||||
#include "dbEdgesUtils.h"
|
||||
#include "dbDeepShapeStore.h"
|
||||
#include "dbOriginalLayerRegion.h"
|
||||
#include "tlUnitTest.h"
|
||||
#include "tlStream.h"
|
||||
|
||||
|
|
@ -1178,6 +1179,57 @@ TEST(22_TwoLayoutsWithDifferentDBU)
|
|||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au22.gds");
|
||||
}
|
||||
|
||||
TEST(23_Texts)
|
||||
{
|
||||
db::Layout ly;
|
||||
{
|
||||
std::string fn (tl::testsrc ());
|
||||
fn += "/testdata/algo/deep_region_l1.gds";
|
||||
tl::InputStream stream (fn);
|
||||
db::Reader reader (stream);
|
||||
reader.read (ly);
|
||||
}
|
||||
|
||||
db::cell_index_type top_cell_index = *ly.begin_top_down ();
|
||||
db::Cell &top_cell = ly.cell (top_cell_index);
|
||||
|
||||
db::DeepShapeStore dss;
|
||||
|
||||
unsigned int l6 = ly.get_layer (db::LayerProperties (6, 1));
|
||||
unsigned int l8 = ly.get_layer (db::LayerProperties (8, 1));
|
||||
|
||||
db::Region r6boxes (db::OriginalLayerRegion (db::RecursiveShapeIterator (ly, top_cell, l6)).texts_as_boxes ("*", true, 100, dss));
|
||||
db::Region r6dots;
|
||||
db::Edges (db::OriginalLayerRegion (db::RecursiveShapeIterator (ly, top_cell, l6)).texts_as_dots ("*", true, dss)).extended (r6dots, 20, 20, 20, 20);
|
||||
db::Region r8boxes (db::OriginalLayerRegion (db::RecursiveShapeIterator (ly, top_cell, l8)).texts_as_boxes ("VDD", false, 100, dss));
|
||||
db::Region r8dots;
|
||||
db::Edges (db::OriginalLayerRegion (db::RecursiveShapeIterator (ly, top_cell, l8)).texts_as_dots ("V*", true, dss)).extended (r8dots, 20, 20, 20, 20);
|
||||
|
||||
db::Region rf6boxes (db::OriginalLayerRegion (db::RecursiveShapeIterator (ly, top_cell, l6)).texts_as_boxes ("*", true, 100));
|
||||
db::Region rf6dots;
|
||||
db::Edges (db::OriginalLayerRegion (db::RecursiveShapeIterator (ly, top_cell, l6)).texts_as_dots ("*", true)).extended (rf6dots, 20, 20, 20, 20);
|
||||
db::Region rf8boxes (db::OriginalLayerRegion (db::RecursiveShapeIterator (ly, top_cell, l8)).texts_as_boxes ("VDD", false, 100));
|
||||
db::Region rf8dots;
|
||||
db::Edges (db::OriginalLayerRegion (db::RecursiveShapeIterator (ly, top_cell, l8)).texts_as_dots ("V*", true)).extended (rf8dots, 20, 20, 20, 20);
|
||||
|
||||
{
|
||||
db::Layout target;
|
||||
unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index));
|
||||
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r6boxes);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r6dots);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), rf6boxes);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), rf6dots);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r8boxes);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), r8dots);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (22, 0)), rf8boxes);
|
||||
target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (23, 0)), rf8dots);
|
||||
|
||||
CHECKPOINT();
|
||||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au23.gds");
|
||||
}
|
||||
}
|
||||
|
||||
TEST(100_Integration)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -786,6 +786,62 @@ class DBRegion_TestClass < TestBase
|
|||
|
||||
end
|
||||
|
||||
# texts
|
||||
def test_15
|
||||
|
||||
r = RBA::Region::new
|
||||
ex = nil
|
||||
begin
|
||||
t = r.texts("*", true)
|
||||
rescue => ex
|
||||
end
|
||||
assert_equal(ex.to_s, "Texts can only be identified on an original layer in Region::texts")
|
||||
|
||||
r.insert(RBA::Box::new(1, 2, 3, 4))
|
||||
ex = nil
|
||||
begin
|
||||
t = r.texts("*", true)
|
||||
rescue => ex
|
||||
end
|
||||
assert_equal(ex.to_s, "Texts can only be identified on an original layer in Region::texts")
|
||||
|
||||
ly = RBA::Layout::new
|
||||
top = ly.create_cell("TOP")
|
||||
l1 = ly.layer(1, 0)
|
||||
top.shapes(l1).insert(RBA::Text::new("ABC", RBA::Trans::new(RBA::Vector::new(100, 200))))
|
||||
|
||||
r = RBA::Region::new(top.begin_shapes_rec(l1))
|
||||
t = r.texts("*", true)
|
||||
assert_equal(t.to_s, "(99,199;99,201;101,201;101,199)")
|
||||
assert_equal(t.is_deep?, false)
|
||||
t = r.texts("*", true, 10)
|
||||
assert_equal(t.to_s, "(90,190;90,210;110,210;110,190)")
|
||||
t = r.texts("A*", true, 10)
|
||||
assert_equal(t.to_s, "(90,190;90,210;110,210;110,190)")
|
||||
t = r.texts("A*", false, 10)
|
||||
assert_equal(t.to_s, "")
|
||||
t = r.texts("ABC", false, 10)
|
||||
assert_equal(t.to_s, "(90,190;90,210;110,210;110,190)")
|
||||
|
||||
dss = RBA::DeepShapeStore::new
|
||||
r = RBA::Region::new(top.begin_shapes_rec(l1))
|
||||
t = r.texts(dss, "*", true)
|
||||
assert_equal(t.to_s, "(99,199;99,201;101,201;101,199)")
|
||||
assert_equal(t.is_deep?, true)
|
||||
|
||||
r = RBA::Region::new(top.begin_shapes_rec(l1))
|
||||
t = r.texts_dots("*", true)
|
||||
assert_equal(t.to_s, "(100,200;100,200)")
|
||||
assert_equal(t.is_deep?, false)
|
||||
|
||||
dss = RBA::DeepShapeStore::new
|
||||
r = RBA::Region::new(top.begin_shapes_rec(l1))
|
||||
t = r.texts_dots(dss, "A*", true)
|
||||
assert_equal(t.to_s, "(100,200;100,200)")
|
||||
assert_equal(t.is_deep?, true)
|
||||
|
||||
end
|
||||
|
||||
# deep region tests
|
||||
def test_deep1
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue