Added some convenience methods for building RDB entries from shapes.

This commit is contained in:
Matthias Koefferlein 2018-04-28 09:46:42 +02:00
parent 89b4397aa4
commit f538885fb3
6 changed files with 217 additions and 63 deletions

View File

@ -9,6 +9,10 @@
Shapes can now insert from another Shapes container and
from a RecursiveShapeIterator. Possible applications are
fast flattening and fast region selection.
* Enhancement: New method to generate RDB items from shapes
RdbItem#add_value from a shape, RdbDatabase#create_items
from a shapes container or recursive shape iterator and
RdbDatabase#create_item from a shape.
* Enhancement: DXF and CIF "keep layer names"
If this option is set in the reader options, layer names
are not translated into GDS layer/datatype pairs.

View File

@ -788,36 +788,12 @@ MarkerBrowserDialog::scan_layer ()
for (db::ShapeIterator shape = cell.shapes ((*l)->layer_index ()).begin (db::ShapeIterator::All); ! shape.at_end (); ++shape) {
std::auto_ptr<rdb::ValueBase> value;
if (shape->is_polygon () || shape->is_box ()) {
db::Polygon poly;
shape->polygon (poly);
value.reset (new rdb::Value <db::DPolygon> (poly.transformed (db::CplxTrans (layout.dbu ()))));
} else if (shape->is_path ()) {
db::Path path;
shape->path (path);
value.reset (new rdb::Value <db::DPath> (path.transformed (db::CplxTrans (layout.dbu ()))));
} else if (shape->is_text ()) {
db::Text text;
shape->text (text);
value.reset (new rdb::Value <db::DText> (text.transformed (db::CplxTrans (layout.dbu ()))));
} else if (shape->is_edge ()) {
db::Edge edge;
shape->edge (edge);
value.reset (new rdb::Value <db::DEdge> (edge.transformed (db::CplxTrans (layout.dbu ()))));
std::auto_ptr<rdb::ValueBase> value (rdb::ValueBase::create_from_shape (*shape, db::CplxTrans (layout.dbu ())));
if (value.get ()) {
rdb::Item *item = rdb->create_item (rdb_cell->id (), cat->id ());
item->values ().add (value.release ());
}
rdb::Item *item = rdb->create_item (rdb_cell->id (), cat->id ());
item->values ().add (value.release ());
++progress;
}
@ -891,37 +867,12 @@ MarkerBrowserDialog::scan_layer_flat ()
db::RecursiveShapeIterator shape (layout, *cv.cell (), (*l)->layer_index ());
while (! shape.at_end ()) {
std::auto_ptr<rdb::ValueBase> value;
if (shape->is_polygon () || shape->is_box ()) {
db::Polygon poly;
shape->polygon (poly);
value.reset (new rdb::Value <db::DPolygon> (poly.transformed (db::CplxTrans (layout.dbu ()) * shape.trans ())));
} else if (shape->is_path ()) {
db::Path path;
shape->path (path);
value.reset (new rdb::Value <db::DPath> (path.transformed (db::CplxTrans (layout.dbu ()) * shape.trans ())));
} else if (shape->is_text ()) {
db::Text text;
shape->text (text);
value.reset (new rdb::Value <db::DText> (text.transformed (db::CplxTrans (layout.dbu ()) * shape.trans ())));
} else if (shape->is_edge ()) {
db::Edge edge;
shape->edge (edge);
value.reset (new rdb::Value <db::DEdge> (edge.transformed (db::CplxTrans (layout.dbu ()) * shape.trans ())));
std::auto_ptr<rdb::ValueBase> value (rdb::ValueBase::create_from_shape (*shape, db::CplxTrans (layout.dbu ()) * shape.trans ()));
if (value.get ()) {
rdb::Item *item = rdb->create_item (rdb_top_cell->id (), cat->id ());
item->values ().add (value.release ());
}
rdb::Item *item = rdb->create_item (rdb_top_cell->id (), cat->id ());
item->values ().add (value.release ());
++progress;
++shape;

View File

@ -36,6 +36,7 @@
#include "dbBox.h"
#include "dbPath.h"
#include "dbText.h"
#include "dbRecursiveShapeIterator.h"
#include "dbTilingProcessor.h"
namespace gsi
@ -289,16 +290,17 @@ Class<rdb::Category> decl_RdbCategory ("RdbCategory",
"This method has been introduced in version 0.23."
) +
gsi::method_ext ("scan_shapes", &scan_shapes,
"@brief Scans the shapes from the shape iterator into the category\n"
"@brief Scans the polygon or edge shapes from the shape iterator into the category\n"
"@args iter\n"
"Creates RDB items for each shape read from the iterator and puts them into this category.\n"
"Creates RDB items for each polygon or edge shape read from the iterator and puts them into this category.\n"
"A similar, but lower-level method is \\ReportDatabase#create_items with a \\RecursiveShapeIterator argument.\n"
"\n"
"This method has been introduced in version 0.23.\n"
) +
gsi::method_ext ("scan_layer", &scan_layer1,
"@brief Scans a layer from a layout into this category\n"
"@args layout, layer\n"
"Creates RDB items for each shape read from the each cell in the layout on the given layer and puts them into this category.\n"
"Creates RDB items for each polygon or edge shape read from the each cell in the layout on the given layer and puts them into this category.\n"
"New cells will be generated for every cell encountered in the layout.\n"
"Other settings like database unit, description, top cell etc. are not made in the RDB.\n"
"\n"
@ -307,7 +309,7 @@ Class<rdb::Category> decl_RdbCategory ("RdbCategory",
gsi::method_ext ("scan_layer", &scan_layer2,
"@brief Scans a layer from a layout into this category, starting with a given cell\n"
"@args layout, layer, cell\n"
"Creates RDB items for each shape read from the cell and it's children in the layout on the given layer and puts them into this category.\n"
"Creates RDB items for each polygon or edge shape read from the cell and it's children in the layout on the given layer and puts them into this category.\n"
"New cells will be generated when required.\n"
"Other settings like database unit, description, top cell etc. are not made in the RDB.\n"
"\n"
@ -316,7 +318,7 @@ Class<rdb::Category> decl_RdbCategory ("RdbCategory",
gsi::method_ext ("scan_layer", &scan_layer3,
"@brief Scans a layer from a layout into this category, starting with a given cell and a depth specification\n"
"@args layout, layer, cell, levels\n"
"Creates RDB items for each shape read from the cell and it's children in the layout on the given layer and puts them into this category.\n"
"Creates RDB items for each polygon or edge shape read from the cell and it's children in the layout on the given layer and puts them into this category.\n"
"New cells will be generated when required.\n"
"\"levels\" is the number of hierarchy levels to take the child cells from. 0 means to use only \"cell\" and don't descend, -1 means \"all levels\".\n"
"Other settings like database unit, description, top cell etc. are not made in the RDB.\n"
@ -713,6 +715,14 @@ static rdb::Values::const_iterator end_values (const rdb::Item *item)
return item->values ().end ();
}
static void add_value_from_shape (rdb::Item *item, const db::Shape &shape, const db::CplxTrans &trans)
{
rdb::ValueBase *value = rdb::ValueBase::create_from_shape (shape, trans);
if (value) {
item->values ().add (value);
}
}
static void add_value (rdb::Item *item, const rdb::ValueWrapper &value)
{
item->values ().add (value);
@ -837,6 +847,15 @@ Class<rdb::Item> decl_RdbItem ("RdbItem",
"@param value The value to add.\n"
"This method has been introduced in version 0.25 as a convenience method."
) +
gsi::method_ext ("add_value", &add_value_from_shape, gsi::arg ("shape"), gsi::arg ("trans"),
"@brief Adds a geometrical value object from a shape\n"
"@param value The shape object from which to take the geometrical object.\n"
"@param trans The transformation to apply.\n"
"\n"
"The transformation can be used to convert database units to micron units.\n"
"\n"
"This method has been introduced in version 0.25.3."
) +
gsi::method_ext ("clear_values", &clear_values,
"@brief Removes all values from this item\n"
) +
@ -945,6 +964,40 @@ void database_set_tag_description (rdb::Database *db, rdb::id_type tag, const st
db->set_tag_description (tag, d);
}
void create_items_from_iterator (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::RecursiveShapeIterator &iter)
{
tl_assert (iter.layout ());
double dbu = iter.layout ()->dbu ();
for (db::RecursiveShapeIterator i = iter; !i.at_end (); ++i) {
std::auto_ptr<rdb::ValueBase> value (rdb::ValueBase::create_from_shape (*i, db::CplxTrans (dbu) * i.trans ()));
if (value.get ()) {
rdb::Item *item = db->create_item (cell_id, cat_id);
item->values ().add (value.release ());
}
}
}
void create_items_from_shapes (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::Shapes &shapes, const db::CplxTrans &trans)
{
for (db::Shapes::shape_iterator s = shapes.begin (db::ShapeIterator::All); !s.at_end (); ++s) {
std::auto_ptr<rdb::ValueBase> value (rdb::ValueBase::create_from_shape (*s, trans));
if (value.get ()) {
rdb::Item *item = db->create_item (cell_id, cat_id);
item->values ().add (value.release ());
}
}
}
void create_item_from_shape (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::Shape &shape, const db::CplxTrans &trans)
{
std::auto_ptr<rdb::ValueBase> value (rdb::ValueBase::create_from_shape (shape, trans));
if (value.get ()) {
rdb::Item *item = db->create_item (cell_id, cat_id);
item->values ().add (value.release ());
}
}
void create_items_from_region (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Region &collection)
{
typedef db::Region::const_iterator iter;
@ -1226,6 +1279,47 @@ Class<rdb::Database> decl_ReportDatabase ("ReportDatabase",
"\n"
"This convenience method has been added in version 0.25.\n"
) +
gsi::method_ext ("create_items", &create_items_from_iterator, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("iter"),
"@brief Creates new items from a shape iterator\n"
"This method takes the shapes from the given iterator and produces items from them.\n"
"It accepts various kind of shapes, such as texts, polygons, boxes and paths and "
"converts them to corresponding items. "
"A similar method, which is intended for production of polygon or edge error layers is \\RdbCategory#scan_shapes.\n"
"\n"
"This method has been introduced in version 0.25.3.\n"
"\n"
"@param cell_id The ID of the cell to which the item is associated\n"
"@param category_id The ID of the category to which the item is associated\n"
"@param iter The iterator (a \\RecursiveShapeIterator object) from which to take the items\n"
) +
gsi::method_ext ("create_item", &create_item_from_shape, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("shape"), gsi::arg ("trans"),
"@brief Creates a new item from a single shape\n"
"This method produces an item from the given shape.\n"
"It accepts various kind of shapes, such as texts, polygons, boxes and paths and "
"converts them to a corresponding item. The transformation argument can be used to "
"supply the transformation that applies the database unit for example.\n"
"\n"
"This method has been introduced in version 0.25.3.\n"
"\n"
"@param cell_id The ID of the cell to which the item is associated\n"
"@param category_id The ID of the category to which the item is associated\n"
"@param shape The shape to take the geometrical object from\n"
"@param trans The transformation to apply\n"
) +
gsi::method_ext ("create_items", &create_items_from_shapes, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("shapes"), gsi::arg ("trans"),
"@brief Creates new items from a shape container\n"
"This method takes the shapes from the given container and produces items from them.\n"
"It accepts various kind of shapes, such as texts, polygons, boxes and paths and "
"converts them to corresponding items. The transformation argument can be used to "
"supply the transformation that applies the database unit for example.\n"
"\n"
"This method has been introduced in version 0.25.3.\n"
"\n"
"@param cell_id The ID of the cell to which the item is associated\n"
"@param category_id The ID of the category to which the item is associated\n"
"@param shapes The shape container from which to take the items\n"
"@param trans The transformation to apply\n"
) +
gsi::method_ext ("create_items", &create_items_from_region,
"@brief Creates new polygon items for the given cell/category combination\n"
"For each polygon in the region a single item will be created. The value of the item will be this "

View File

@ -33,6 +33,7 @@
#include "dbEdgePair.h"
#include "dbPath.h"
#include "dbText.h"
#include "dbShape.h"
#include <QFileInfo>
#include <QByteArray>
@ -250,6 +251,38 @@ ValueBase::create_from_string (tl::Extractor &ex)
}
}
ValueBase *
ValueBase::create_from_shape (const db::Shape &shape, const db::CplxTrans &trans)
{
if (shape.is_polygon () || shape.is_box ()) {
db::Polygon poly;
shape.polygon (poly);
return new rdb::Value <db::DPolygon> (poly.transformed (trans));
} else if (shape.is_path ()) {
db::Path path;
shape.path (path);
return new rdb::Value <db::DPath> (path.transformed (trans));
} else if (shape.is_text ()) {
db::Text text;
shape.text (text);
return new rdb::Value <db::DText> (text.transformed (trans));
} else if (shape.is_edge ()) {
db::Edge edge;
shape.edge (edge);
return new rdb::Value <db::DEdge> (edge.transformed (trans));
} else {
return 0;
}
}
// ------------------------------------------------------------------------------------------
// ValueWrapper implementation

View File

@ -44,6 +44,11 @@ namespace tl
class Extractor;
}
namespace db
{
class Shape;
}
namespace rdb
{
@ -441,6 +446,8 @@ public:
static ValueBase *create_from_string (const std::string &s);
static ValueBase *create_from_string (tl::Extractor &ex);
static ValueBase *create_from_shape (const db::Shape &shape, const db::CplxTrans &trans);
};
/**

View File

@ -450,15 +450,22 @@ class RDB_TestClass < TestBase
item.add_value(RBA::DBox::new(11, 12, 13, 14))
item.add_value(RBA::DEdge::new(21, 22, 23, 24))
item.add_value(RBA::DEdgePair::new(RBA::DEdge::new(31, 32, 33, 34), RBA::DEdge::new(41, 42, 43, 44)))
shapes = RBA::Shapes::new
pts = [ RBA::Point::new(0, 0), RBA::Point::new(50, 150) ]
shapes.insert(RBA::Path::new(pts, 100))
shapes.each do |s|
item.add_value(s, RBA::CplxTrans::new(0.001))
end
vv=[]
item.each_value { |v| vv.push(v) }
assert_equal(vv.size, 6)
assert_equal(vv.size, 7)
assert_equal(vv[0].to_s, "float: 1")
assert_equal(vv[1].to_s, "text: hello")
assert_equal(vv[2].to_s, "polygon: (1,2;1,4;3,4;3,2)")
assert_equal(vv[3].to_s, "box: (11,12;13,14)")
assert_equal(vv[4].to_s, "edge: (21,22;23,24)")
assert_equal(vv[5].to_s, "edge-pair: (31,32;33,34)/(41,42;43,44)")
assert_equal(vv[6].to_s, "path: (0,0;0.05,0.15) w=0.1 bx=0 ex=0 r=false")
end
@ -761,6 +768,64 @@ class RDB_TestClass < TestBase
rdb.each_cell { |c| cn << c.to_s_items }
assert_equal(cn.join(";"), "c1[polygon: (0,0.001;0,0.03;0.02,0.03;0.02,0.001),polygon: (0.01,0.021;0.01,0.051;0.031,0.051;0.031,0.021),polygon: (0.021,0.042;0.021,0.073;0.043,0.073;0.043,0.042)]")
rdb = RBA::ReportDatabase.new("neu")
cat = rdb.create_category("l1")
cat.scan_shapes(c1.begin_shapes_rec(l1))
assert_equal(cat.num_items, 3)
cn = []
rdb.each_cell { |c| cn << c.to_s_test }
assert_equal(cn.join(";"), "c1[]")
cn = []
rdb.each_cell { |c| cn << c.to_s_items }
assert_equal(cn.join(";"), "c1[polygon: (0,0.001;0,0.03;0.02,0.03;0.02,0.001),polygon: (0.01,0.021;0.01,0.051;0.031,0.051;0.031,0.021),polygon: (0.021,0.042;0.021,0.073;0.043,0.073;0.043,0.042)]")
end
# shape insertion from shape, shapes, recursive iterator
def test_12
ly = RBA::Layout::new
c0 = ly.create_cell("c0")
c1 = ly.create_cell("c1")
c2 = ly.create_cell("c2")
c3 = ly.create_cell("c3")
c1.insert(RBA::CellInstArray::new(c2.cell_index, RBA::Trans::new(10, 20)))
c2.insert(RBA::CellInstArray::new(c3.cell_index, RBA::Trans::new(11, 21)))
l1 = ly.insert_layer(RBA::LayerInfo::new(1, 0))
c0.shapes(l1).insert(RBA::Box::new(0, 1, 2, 3))
c1.shapes(l1).insert(RBA::Text::new("Hello, world!", RBA::Trans::new))
c2.shapes(l1).insert(RBA::Edge::new(0, 1, 21, 31))
c3.shapes(l1).insert(RBA::Polygon::new(RBA::Box::new(0, 1, 22, 32)))
rdb = RBA::ReportDatabase.new("neu")
cat1 = rdb.create_category("l1")
cell1 = rdb.create_cell("c1")
c0.shapes(l1).each do |s|
rdb.create_item(cell1.rdb_id, cat1.rdb_id, s, RBA::CplxTrans::new(ly.dbu))
end
assert_equal(cat1.num_items, 1)
cn = []
rdb.each_cell { |c| cn << c.to_s_items }
assert_equal(cn.join(";"), "c1[polygon: (0,0.001;0,0.003;0.002,0.003;0.002,0.001)]")
rdb = RBA::ReportDatabase.new("neu")
cat1 = rdb.create_category("l1")
cell1 = rdb.create_cell("c1")
rdb.create_items(cell1.rdb_id, cat1.rdb_id, c0.shapes(l1), RBA::CplxTrans::new(ly.dbu))
assert_equal(cat1.num_items, 1)
cn = []
rdb.each_cell { |c| cn << c.to_s_items }
assert_equal(cn.join(";"), "c1[polygon: (0,0.001;0,0.003;0.002,0.003;0.002,0.001)]")
rdb = RBA::ReportDatabase.new("neu")
cat1 = rdb.create_category("l1")
cell1 = rdb.create_cell("c1")
rdb.create_items(cell1.rdb_id, cat1.rdb_id, c1.begin_shapes_rec(l1))
assert_equal(cat1.num_items, 3)
cn = []
rdb.each_cell { |c| cn << c.to_s_items }
assert_equal(cn.join(";"), "c1[label: ('Hello, world!',r0 0,0),edge: (0.01,0.021;0.031,0.051),polygon: (0.021,0.042;0.021,0.073;0.043,0.073;0.043,0.042)]")
end
end