mirror of https://github.com/KLayout/klayout.git
Added some convenience methods for building RDB entries from shapes.
This commit is contained in:
parent
89b4397aa4
commit
f538885fb3
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 "
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue