mirror of https://github.com/KLayout/klayout.git
Merge branch 'api-enhancements'
This commit is contained in:
commit
2ed572e684
|
|
@ -42,10 +42,69 @@ namespace db
|
|||
// --------------------------------------------------------------------------------
|
||||
// Some utilities
|
||||
|
||||
bool check_trailing_reserved_word (const tl::Extractor &ex0)
|
||||
static const char *s_select = "select";
|
||||
static const char *s_delete = "delete";
|
||||
static const char *s_or = "or";
|
||||
static const char *s_of = "of";
|
||||
static const char *s_on = "on";
|
||||
static const char *s_do = "do";
|
||||
static const char *s_from = "from";
|
||||
static const char *s_layer = "layer";
|
||||
static const char *s_layers = "layers";
|
||||
static const char *s_cell = "cell";
|
||||
static const char *s_cells = "cells";
|
||||
static const char *s_where = "where";
|
||||
static const char *s_shapes = "shapes";
|
||||
static const char *s_polygons = "polygons";
|
||||
static const char *s_boxes = "boxes";
|
||||
static const char *s_edges = "edges";
|
||||
static const char *s_paths = "paths";
|
||||
static const char *s_texts = "texts";
|
||||
static const char *s_instances = "instances";
|
||||
static const char *s_arrays = "arrays";
|
||||
static const char *s_sorted = "sorted";
|
||||
static const char *s_unique = "unique";
|
||||
static const char *s_by = "by";
|
||||
static const char *s_with = "with";
|
||||
static const char *s_pass = "pass";
|
||||
|
||||
const char *s_reserved_words[] = {
|
||||
s_select,
|
||||
s_delete,
|
||||
s_or,
|
||||
s_of,
|
||||
s_on,
|
||||
s_do,
|
||||
s_from,
|
||||
s_layer,
|
||||
s_layers,
|
||||
s_cell,
|
||||
s_cells,
|
||||
s_where,
|
||||
s_shapes,
|
||||
s_polygons,
|
||||
s_boxes,
|
||||
s_edges,
|
||||
s_paths,
|
||||
s_texts,
|
||||
s_instances,
|
||||
s_arrays,
|
||||
s_sorted,
|
||||
s_unique,
|
||||
s_by,
|
||||
s_with,
|
||||
s_pass
|
||||
};
|
||||
|
||||
bool check_trailing_reserved_word (const tl::Extractor &ex0)
|
||||
{
|
||||
tl::Extractor ex = ex0;
|
||||
return (ex.test ("do") || ex.test ("sorted") || ex.test ("pass") || ex.test ("where"));
|
||||
for (size_t i = 0; i < sizeof (s_reserved_words) / sizeof (s_reserved_words[0]); ++i) {
|
||||
if (ex.test (s_reserved_words[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
|
|
@ -202,7 +261,9 @@ struct ShapeFilterPropertyIDs
|
|||
ShapeFilterPropertyIDs (LayoutQuery *q)
|
||||
{
|
||||
bbox = q->register_property ("bbox", LQ_box);
|
||||
dbbox = q->register_property ("dbbox", LQ_dbox);
|
||||
shape_bbox = q->register_property ("shape_bbox", LQ_box);
|
||||
shape_dbbox = q->register_property ("shape_dbbox", LQ_dbox);
|
||||
shape = q->register_property ("shape", LQ_shape);
|
||||
layer_info = q->register_property ("layer_info", LQ_layer);
|
||||
layer_index = q->register_property ("layer_index", LQ_variant);
|
||||
|
|
@ -211,7 +272,9 @@ struct ShapeFilterPropertyIDs
|
|||
}
|
||||
|
||||
unsigned int bbox; // bbox -> The shape's bounding box
|
||||
unsigned int dbbox; // dbbox -> The shape's bounding box in micrometer units
|
||||
unsigned int shape_bbox; // shape_bbox -> == box
|
||||
unsigned int shape_dbbox; // shape_dbbox -> == dbox
|
||||
unsigned int shape; // shape -> The shape object
|
||||
unsigned int layer_info; // layer_info -> The layer (a LayerInfo object)
|
||||
unsigned int layer_index; // layer_index -> The layer index
|
||||
|
|
@ -309,6 +372,12 @@ public:
|
|||
v = tl::Variant::make_variant (m_shape->bbox ());
|
||||
return true;
|
||||
|
||||
} else if (id == m_pids.dbbox || id == m_pids.shape_dbbox) {
|
||||
|
||||
tl_assert (mp_parent->layout ());
|
||||
v = tl::Variant::make_variant (db::CplxTrans (mp_parent->layout ()->dbu ()) * m_shape->bbox ());
|
||||
return true;
|
||||
|
||||
} else if (id == m_pids.shape) {
|
||||
|
||||
if (m_reading) {
|
||||
|
|
@ -418,7 +487,9 @@ struct ChildCellFilterPropertyIDs
|
|||
parent_cell_name = q->register_property ("parent_cell_name", LQ_variant);
|
||||
hier_levels = q->register_property ("hier_levels", LQ_variant);
|
||||
bbox = q->register_property ("bbox", LQ_box);
|
||||
dbbox = q->register_property ("dbbox", LQ_dbox);
|
||||
cell_bbox = q->register_property ("cell_bbox", LQ_box);
|
||||
cell_dbbox = q->register_property ("cell_dbbox", LQ_dbox);
|
||||
|
||||
// with instance_mode == NoInstances:
|
||||
if (instance_mode == NoInstances) {
|
||||
|
|
@ -434,21 +505,31 @@ struct ChildCellFilterPropertyIDs
|
|||
// with instance_mode != NoInstances:
|
||||
if (instance_mode != NoInstances) {
|
||||
path_trans = q->register_property ("path_trans", LQ_trans);
|
||||
path_dtrans = q->register_property ("path_dtrans", LQ_dtrans);
|
||||
trans = q->register_property ("trans", LQ_trans);
|
||||
dtrans = q->register_property ("dtrans", LQ_dtrans);
|
||||
inst_bbox = q->register_property ("inst_bbox", LQ_box);
|
||||
inst_dbbox = q->register_property ("inst_dbbox", LQ_box);
|
||||
inst = q->register_property ("inst", LQ_instance);
|
||||
array_a = q->register_property ("array_a", LQ_point);
|
||||
array_da = q->register_property ("array_da", LQ_dpoint);
|
||||
array_na = q->register_property ("array_na", LQ_variant);
|
||||
array_b = q->register_property ("array_b", LQ_point);
|
||||
array_db = q->register_property ("array_db", LQ_dpoint);
|
||||
array_nb = q->register_property ("array_nb", LQ_variant);
|
||||
} else {
|
||||
path_trans = std::numeric_limits<unsigned int>::max ();
|
||||
path_dtrans = std::numeric_limits<unsigned int>::max ();
|
||||
trans = std::numeric_limits<unsigned int>::max ();
|
||||
dtrans = std::numeric_limits<unsigned int>::max ();
|
||||
inst_bbox = std::numeric_limits<unsigned int>::max ();
|
||||
inst_dbbox = std::numeric_limits<unsigned int>::max ();
|
||||
inst = std::numeric_limits<unsigned int>::max ();
|
||||
array_a = std::numeric_limits<unsigned int>::max ();
|
||||
array_da = std::numeric_limits<unsigned int>::max ();
|
||||
array_na = std::numeric_limits<unsigned int>::max ();
|
||||
array_b = std::numeric_limits<unsigned int>::max ();
|
||||
array_db = std::numeric_limits<unsigned int>::max ();
|
||||
array_nb = std::numeric_limits<unsigned int>::max ();
|
||||
}
|
||||
|
||||
|
|
@ -475,7 +556,9 @@ struct ChildCellFilterPropertyIDs
|
|||
unsigned int parent_cell_name; // parent_cell_name -> Name of parent cell (next in path) or nil
|
||||
unsigned int hier_levels; // hier_levels -> Number of hierarchy levels in path (length of path - 1)
|
||||
unsigned int bbox; // bbox -> Cell bounding box
|
||||
unsigned int dbbox; // dbbox -> Cell bounding box in micrometer units
|
||||
unsigned int cell_bbox; // cell_bbox -> == bbox
|
||||
unsigned int cell_dbbox; // cell_dbbox -> == dbbox
|
||||
|
||||
// with instance_mode == NoInstances:
|
||||
unsigned int references; // references -> The number of instances (arefs count as 1) of this cell in the parent cell
|
||||
|
|
@ -484,17 +567,22 @@ struct ChildCellFilterPropertyIDs
|
|||
|
||||
// with instance_mode != NoInstances:
|
||||
unsigned int path_trans; // path_trans -> The transformation of that instance into the top cell
|
||||
unsigned int path_dtrans; // path_dtrans -> The transformation of that instance into the top cell in micrometer units
|
||||
unsigned int trans; // trans -> The transformation of that instance (first instance if an array)
|
||||
unsigned int dtrans; // dtrans -> The transformation of that instance (first instance if an array) in micrometer units
|
||||
unsigned int inst_bbox; // inst_bbox -> The instance bounding box in the top cell
|
||||
unsigned int inst_dbbox; // inst_dbbox -> The instance bounding box in the top cell in micrometer units
|
||||
unsigned int inst; // inst -> The instance object
|
||||
unsigned int array_a; // array_a -> The a vector for an array instance
|
||||
unsigned int array_da; // array_da -> The a vector for an array instance in micrometer units
|
||||
unsigned int array_na; // array_na -> The a axis array dimension
|
||||
unsigned int array_b; // array_b -> The b vector for an array instance
|
||||
unsigned int array_db; // array_db -> The b vector for an array instance in micrometer units
|
||||
unsigned int array_nb; // array_nb -> The b axis array dimension
|
||||
|
||||
// with instance_mode == ExplodedInstances:
|
||||
unsigned int array_ia; // array_ia -> The a index when an array is iterated
|
||||
unsigned int array_ib; // array_ib -> The b index when an array is iterated
|
||||
unsigned int array_ib; // array_ib -> The b index when an array is iterated
|
||||
};
|
||||
|
||||
class DB_PUBLIC ChildCellFilterState
|
||||
|
|
@ -764,6 +852,15 @@ public:
|
|||
}
|
||||
return true;
|
||||
|
||||
} else if (id == m_pids.dbbox || id == m_pids.cell_dbbox) {
|
||||
|
||||
if (! layout ()->is_valid_cell_index (cell_index ())) {
|
||||
v = tl::Variant ();
|
||||
} else {
|
||||
v = tl::Variant::make_variant (db::CplxTrans (layout ()->dbu ()) * layout ()->cell (cell_index ()).bbox ());
|
||||
}
|
||||
return true;
|
||||
|
||||
} else if (id == m_pids.cell_name) {
|
||||
|
||||
if (! layout ()->is_valid_cell_index (cell_index ())) {
|
||||
|
|
@ -983,6 +1080,35 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
} else if (id == m_pids.inst_dbbox) {
|
||||
|
||||
if (mp_parent) {
|
||||
|
||||
if (m_instance_mode == ExplodedInstances) {
|
||||
|
||||
db::ICplxTrans t = m_parent_trans;
|
||||
t *= (*m_inst)->complex_trans (*m_array_iter);
|
||||
db::DBox box (db::CplxTrans (layout ()->dbu ()) * t * layout ()->cell ((*m_inst)->object ().cell_index ()).bbox ());
|
||||
v = tl::Variant::make_variant (box);
|
||||
return true;
|
||||
|
||||
} else if (m_instance_mode == ArrayInstances) {
|
||||
|
||||
db::ICplxTrans t = m_parent_trans;
|
||||
t *= (*m_inst)->complex_trans ();
|
||||
db::box_convert <db::CellInst> bc (*layout ());
|
||||
db::DBox box (db::CplxTrans (layout ()->dbu ()) * t * (*m_inst)->bbox (bc));
|
||||
v = tl::Variant::make_variant (box);
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (id == m_pids.path_trans) {
|
||||
|
||||
if (mp_parent) {
|
||||
|
|
@ -1011,6 +1137,36 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
} else if (id == m_pids.path_dtrans) {
|
||||
|
||||
if (mp_parent) {
|
||||
|
||||
if (m_instance_mode == ExplodedInstances) {
|
||||
|
||||
db::ICplxTrans t = m_parent_trans;
|
||||
t *= (*m_inst)->complex_trans (*m_array_iter);
|
||||
db::CplxTrans tdbu (layout ()->dbu ());
|
||||
v = tl::Variant::make_variant (tdbu * t * tdbu.inverted ());
|
||||
return true;
|
||||
|
||||
} else if (m_instance_mode == ArrayInstances) {
|
||||
|
||||
db::ICplxTrans t = m_parent_trans;
|
||||
t *= (*m_inst)->complex_trans ();
|
||||
db::CplxTrans tdbu (layout ()->dbu ());
|
||||
v = tl::Variant::make_variant (tdbu * t * tdbu.inverted ());
|
||||
return true;
|
||||
|
||||
} else {
|
||||
v = tl::Variant::make_variant (db::ICplxTrans ());
|
||||
return true;
|
||||
}
|
||||
|
||||
} else {
|
||||
v = tl::Variant::make_variant (db::ICplxTrans ());
|
||||
return true;
|
||||
}
|
||||
|
||||
} else if (id == m_pids.trans) {
|
||||
|
||||
if (mp_parent) {
|
||||
|
|
@ -1033,6 +1189,30 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
} else if (id == m_pids.dtrans) {
|
||||
|
||||
if (mp_parent) {
|
||||
|
||||
if (m_instance_mode == ExplodedInstances) {
|
||||
|
||||
db::CplxTrans tdbu (layout ()->dbu ());
|
||||
v = tl::Variant::make_variant (tdbu * (*m_inst)->complex_trans (*m_array_iter) * tdbu.inverted ());
|
||||
return true;
|
||||
|
||||
} else if (m_instance_mode == ArrayInstances) {
|
||||
|
||||
db::CplxTrans tdbu (layout ()->dbu ());
|
||||
v = tl::Variant::make_variant (tdbu * (*m_inst)->complex_trans () * tdbu.inverted ());
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (id == m_pids.inst) {
|
||||
|
||||
if (! mp_parent || m_instance_mode == NoInstances) {
|
||||
|
|
@ -1064,7 +1244,7 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
} else if (id == m_pids.array_a || id == m_pids.array_b || id == m_pids.array_na || id == m_pids.array_nb) {
|
||||
} else if (id == m_pids.array_a || id == m_pids.array_b || id == m_pids.array_da || id == m_pids.array_db || id == m_pids.array_na || id == m_pids.array_nb) {
|
||||
|
||||
if (! mp_parent || m_instance_mode == NoInstances) {
|
||||
return false;
|
||||
|
|
@ -1074,8 +1254,12 @@ public:
|
|||
if ((*m_inst)->is_regular_array (a, b, na, nb)) {
|
||||
if (id == m_pids.array_a) {
|
||||
v = tl::Variant::make_variant (a);
|
||||
} else if (id == m_pids.array_da) {
|
||||
v = tl::Variant::make_variant (db::CplxTrans (layout ()->dbu ()) * a);
|
||||
} else if (id == m_pids.array_b) {
|
||||
v = tl::Variant::make_variant (b);
|
||||
} else if (id == m_pids.array_db) {
|
||||
v = tl::Variant::make_variant (db::CplxTrans (layout ()->dbu ()) * b);
|
||||
} else if (id == m_pids.array_na) {
|
||||
v = na;
|
||||
} else if (id == m_pids.array_nb) {
|
||||
|
|
@ -1178,8 +1362,11 @@ struct CellFilterPropertyIDs
|
|||
tot_weight = q->register_property ("tot_weight", LQ_variant);
|
||||
instances = q->register_property ("instances", LQ_variant);
|
||||
bbox = q->register_property ("bbox", LQ_box);
|
||||
dbbox = q->register_property ("dbbox", LQ_dbox);
|
||||
cell_bbox = q->register_property ("cell_bbox", LQ_box);
|
||||
cell_dbbox = q->register_property ("cell_dbbox", LQ_dbox);
|
||||
path_trans = q->register_property ("path_trans", LQ_trans);
|
||||
path_dtrans = q->register_property ("path_dtrans", LQ_dtrans);
|
||||
}
|
||||
|
||||
unsigned int path; // path -> Variant array with the indexes of the cells in that path
|
||||
|
|
@ -1200,8 +1387,11 @@ struct CellFilterPropertyIDs
|
|||
unsigned int tot_weight; // tot_weight -> The number of instances of this cell in the initial cell along the given path
|
||||
unsigned int instances; // instances -> The number of instances of this cell in the previous cell (or over all if there is no previous cell)
|
||||
unsigned int bbox; // bbox -> Cell bounding box
|
||||
unsigned int dbbox; // dbbox -> Cell bounding box in micrometer units
|
||||
unsigned int cell_bbox; // cell_bbox -> == bbox
|
||||
unsigned int cell_dbbox; // cell_dbbox -> == dbbox
|
||||
unsigned int path_trans; // parent_trans -> transformation to initial cell
|
||||
unsigned int path_dtrans; // parent_dtrans -> transformation to initial cell in micrometer units
|
||||
};
|
||||
|
||||
class DB_PUBLIC CellFilterState
|
||||
|
|
@ -1283,6 +1473,15 @@ public:
|
|||
}
|
||||
return true;
|
||||
|
||||
} else if (id == m_pids.dbbox || id == m_pids.cell_dbbox) {
|
||||
|
||||
if (! layout ()->is_valid_cell_index (*m_cell)) {
|
||||
v = tl::Variant ();
|
||||
} else {
|
||||
v = tl::Variant::make_variant (db::CplxTrans (layout ()->dbu ()) * layout ()->cell (*m_cell).bbox ());
|
||||
}
|
||||
return true;
|
||||
|
||||
} else if (id == m_pids.cell_name || id == m_pids.initial_cell_name) {
|
||||
|
||||
if (! layout ()->is_valid_cell_index (*m_cell)) {
|
||||
|
|
@ -1363,6 +1562,11 @@ public:
|
|||
v = tl::Variant::make_variant (db::ICplxTrans ());
|
||||
return true;
|
||||
|
||||
} else if (id == m_pids.path_dtrans) {
|
||||
|
||||
v = tl::Variant::make_variant (db::DCplxTrans ());
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return FilterStateBase::get_property (id, v);
|
||||
}
|
||||
|
|
@ -2225,7 +2429,7 @@ parse_cell_name_filter_element (tl::Extractor &ex, LayoutQuery *q, ChildCellFilt
|
|||
std::unique_ptr<FilterBracket> b (new FilterBracket (q));
|
||||
do {
|
||||
parse_cell_name_filter_seq (ex, q, b.get (), instance_mode, reading);
|
||||
} while (ex.test (",") || ex.test ("or"));
|
||||
} while (ex.test (",") || ex.test (s_or));
|
||||
|
||||
// TODO: do this in the optimization
|
||||
if (b->children ().size () == 1 && dynamic_cast<FilterBracket *> (b->children ()[0])) {
|
||||
|
|
@ -2362,21 +2566,21 @@ parse_cell_filter (tl::Extractor &ex, LayoutQuery *q, FilterBracket *bracket, bo
|
|||
|
||||
std::unique_ptr<FilterBracket> b (new FilterBracket (q));
|
||||
|
||||
if (ex.test ("instances")) {
|
||||
(ex.test ("of") || ex.test ("from")) && (ex.test ("cells") || ex.test ("cell"));
|
||||
if (ex.test (s_instances)) {
|
||||
(ex.test (s_of) || ex.test (s_from)) && (ex.test (s_cells) || ex.test (s_cell));
|
||||
// Because an array member cannot be modified we use ArrayInstances in the modification case always
|
||||
parse_cell_name_filter_seq (ex, q, b.get (), reading ? ExplodedInstances : ArrayInstances, reading);
|
||||
} else if (ex.test ("arrays")) {
|
||||
(ex.test ("of") || ex.test ("from")) && (ex.test ("cells") || ex.test ("cell"));
|
||||
} else if (ex.test (s_arrays)) {
|
||||
(ex.test (s_of) || ex.test (s_from)) && (ex.test (s_cells) || ex.test (s_cell));
|
||||
parse_cell_name_filter_seq (ex, q, b.get (), ArrayInstances, reading);
|
||||
} else {
|
||||
ex.test ("cells") || ex.test ("cell");
|
||||
ex.test (s_cells) || ex.test (s_cell);
|
||||
parse_cell_name_filter_seq (ex, q, b.get (), NoInstances, reading);
|
||||
}
|
||||
|
||||
FilterBase *fl = 0, *f = 0;
|
||||
|
||||
if (with_where_clause && ex.test ("where")) {
|
||||
if (with_where_clause && ex.test (s_where)) {
|
||||
|
||||
std::string expr = tl::Eval::parse_expr (ex, true);
|
||||
|
||||
|
|
@ -2407,22 +2611,22 @@ parse_filter (tl::Extractor &ex, LayoutQuery *q, FilterBracket *bracket, bool re
|
|||
{
|
||||
unsigned int sf = (unsigned int) db::ShapeIterator::Nothing;
|
||||
do {
|
||||
if (ex.test ("shapes")) {
|
||||
if (ex.test (s_shapes)) {
|
||||
sf |= (unsigned int) db::ShapeIterator::All;
|
||||
} else if (ex.test ("polygons")) {
|
||||
} else if (ex.test (s_polygons)) {
|
||||
sf |= (unsigned int) db::ShapeIterator::Polygons;
|
||||
} else if (ex.test ("boxes")) {
|
||||
} else if (ex.test (s_boxes)) {
|
||||
sf |= (unsigned int) db::ShapeIterator::Boxes;
|
||||
} else if (ex.test ("edges")) {
|
||||
} else if (ex.test (s_edges)) {
|
||||
sf |= (unsigned int) db::ShapeIterator::Edges;
|
||||
} else if (ex.test ("paths")) {
|
||||
} else if (ex.test (s_paths)) {
|
||||
sf |= (unsigned int) db::ShapeIterator::Paths;
|
||||
} else if (ex.test ("texts")) {
|
||||
} else if (ex.test (s_texts)) {
|
||||
sf |= (unsigned int) db::ShapeIterator::Texts;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while (ex.test (",") || ex.test ("or"));
|
||||
} while (ex.test (",") || ex.test (s_or));
|
||||
|
||||
db::ShapeIterator::flags_type shapes = (db::ShapeIterator::flags_type) sf;
|
||||
|
||||
|
|
@ -2430,12 +2634,12 @@ parse_filter (tl::Extractor &ex, LayoutQuery *q, FilterBracket *bracket, bool re
|
|||
|
||||
db::LayerMap lm;
|
||||
|
||||
if (ex.test ("on")) {
|
||||
ex.test ("layer") || ex.test ("layers");
|
||||
if (ex.test (s_on)) {
|
||||
ex.test (s_layer) || ex.test (s_layers);
|
||||
lm.map_expr (ex, 0);
|
||||
}
|
||||
|
||||
ex.test ("of") || ex.test ("from");
|
||||
ex.test (s_of) || ex.test (s_from);
|
||||
|
||||
std::unique_ptr<FilterBracket> b (new FilterBracket (q));
|
||||
parse_cell_filter (ex, q, b.get (), false, reading);
|
||||
|
|
@ -2451,7 +2655,7 @@ parse_filter (tl::Extractor &ex, LayoutQuery *q, FilterBracket *bracket, bool re
|
|||
bracket->add_child (f);
|
||||
fl->connect (f);
|
||||
|
||||
if (ex.test ("where")) {
|
||||
if (ex.test (s_where)) {
|
||||
|
||||
std::string expr = tl::Eval::parse_expr (ex, true);
|
||||
|
||||
|
|
@ -2472,7 +2676,7 @@ parse_filter (tl::Extractor &ex, LayoutQuery *q, FilterBracket *bracket, bool re
|
|||
void
|
||||
parse_statement (tl::Extractor &ex, LayoutQuery *q, FilterBracket *bracket, bool reading)
|
||||
{
|
||||
if (ex.test ("select")) {
|
||||
if (ex.test (s_select)) {
|
||||
|
||||
std::vector<std::string> expressions;
|
||||
|
||||
|
|
@ -2480,7 +2684,7 @@ parse_statement (tl::Extractor &ex, LayoutQuery *q, FilterBracket *bracket, bool
|
|||
expressions.push_back (tl::Eval::parse_expr (ex, true));
|
||||
} while (ex.test (","));
|
||||
|
||||
ex.expect ("from");
|
||||
ex.expect (s_from);
|
||||
|
||||
std::unique_ptr<FilterBracket> b (new FilterBracket (q));
|
||||
parse_filter (ex, q, b.get (), true);
|
||||
|
|
@ -2488,10 +2692,10 @@ parse_statement (tl::Extractor &ex, LayoutQuery *q, FilterBracket *bracket, bool
|
|||
bool unique = false;
|
||||
|
||||
std::string sort_expression;
|
||||
if (ex.test ("sorted")) {
|
||||
ex.test ("by");
|
||||
if (ex.test (s_sorted)) {
|
||||
ex.test (s_by);
|
||||
sort_expression = tl::Eval::parse_expr (ex, true);
|
||||
unique = ex.test ("unique");
|
||||
unique = ex.test (s_unique);
|
||||
}
|
||||
|
||||
FilterBase *f = b.release ();
|
||||
|
|
@ -2504,16 +2708,16 @@ parse_statement (tl::Extractor &ex, LayoutQuery *q, FilterBracket *bracket, bool
|
|||
|
||||
bracket->connect_exit (ff);
|
||||
|
||||
} else if (! reading && ex.test ("with")) {
|
||||
} else if (! reading && ex.test (s_with)) {
|
||||
|
||||
std::unique_ptr<FilterBracket> b (new FilterBracket (q));
|
||||
parse_filter (ex, q, b.get (), false);
|
||||
|
||||
ex.expect ("do");
|
||||
ex.expect (s_do);
|
||||
|
||||
std::string expression = tl::Eval::parse_expr (ex, true);
|
||||
|
||||
bool transparent = ex.test ("pass");
|
||||
bool transparent = ex.test (s_pass);
|
||||
|
||||
FilterBase *f = b.release ();
|
||||
bracket->add_child (f);
|
||||
|
|
@ -2525,12 +2729,12 @@ parse_statement (tl::Extractor &ex, LayoutQuery *q, FilterBracket *bracket, bool
|
|||
|
||||
bracket->connect_exit (ff);
|
||||
|
||||
} else if (! reading && ex.test ("delete")) {
|
||||
} else if (! reading && ex.test (s_delete)) {
|
||||
|
||||
std::unique_ptr<FilterBracket> b (new FilterBracket (q));
|
||||
parse_filter (ex, q, b.get (), false);
|
||||
|
||||
bool transparent = ex.test ("pass");
|
||||
bool transparent = ex.test (s_pass);
|
||||
|
||||
FilterBase *f = b.release ();
|
||||
bracket->add_child (f);
|
||||
|
|
@ -2554,7 +2758,10 @@ LayoutQuery::LayoutQuery (const std::string &query)
|
|||
|
||||
tl::Extractor ex (query.c_str ());
|
||||
parse_statement (ex, this, r.get (), false);
|
||||
ex.expect_end ();
|
||||
|
||||
if (! ex.at_end ()) {
|
||||
ex.error (tl::to_string (tr ("Unexpected text")));
|
||||
}
|
||||
|
||||
r->optimize ();
|
||||
mp_root = r.release ();
|
||||
|
|
|
|||
|
|
@ -51,11 +51,14 @@ enum LayoutQueryPropertyType
|
|||
LQ_variant,
|
||||
LQ_shape,
|
||||
LQ_trans,
|
||||
LQ_dtrans,
|
||||
LQ_layer,
|
||||
LQ_instance,
|
||||
LQ_cell,
|
||||
LQ_point,
|
||||
LQ_dpoint,
|
||||
LQ_box,
|
||||
LQ_dbox,
|
||||
LQ_polygon,
|
||||
LQ_path,
|
||||
LQ_edge,
|
||||
|
|
|
|||
|
|
@ -83,7 +83,6 @@ RecursiveInstanceIterator &RecursiveInstanceIterator::operator= (const Recursive
|
|||
RecursiveInstanceIterator::RecursiveInstanceIterator ()
|
||||
{
|
||||
// anything. Not necessary reasonable.
|
||||
mp_layout = 0;
|
||||
mp_top_cell = 0;
|
||||
mp_cell = 0;
|
||||
m_overlapping = false;
|
||||
|
|
@ -97,7 +96,7 @@ RecursiveInstanceIterator::RecursiveInstanceIterator ()
|
|||
RecursiveInstanceIterator::RecursiveInstanceIterator (const layout_type &layout, const cell_type &cell, const box_type ®ion, bool overlapping)
|
||||
: m_box_convert (layout)
|
||||
{
|
||||
mp_layout = &layout;
|
||||
mp_layout = const_cast<db::Layout *> (&layout);
|
||||
mp_top_cell = &cell;
|
||||
m_overlapping = overlapping;
|
||||
init ();
|
||||
|
|
@ -107,7 +106,7 @@ RecursiveInstanceIterator::RecursiveInstanceIterator (const layout_type &layout,
|
|||
RecursiveInstanceIterator::RecursiveInstanceIterator (const layout_type &layout, const cell_type &cell, const region_type ®ion, bool overlapping)
|
||||
: m_box_convert (layout)
|
||||
{
|
||||
mp_layout = &layout;
|
||||
mp_layout = const_cast<db::Layout *> (&layout);
|
||||
mp_top_cell = &cell;
|
||||
m_overlapping = overlapping;
|
||||
init ();
|
||||
|
|
@ -117,7 +116,7 @@ RecursiveInstanceIterator::RecursiveInstanceIterator (const layout_type &layout,
|
|||
RecursiveInstanceIterator::RecursiveInstanceIterator (const layout_type &layout, const cell_type &cell)
|
||||
: m_box_convert (layout)
|
||||
{
|
||||
mp_layout = &layout;
|
||||
mp_layout = const_cast<db::Layout *> (&layout);
|
||||
mp_top_cell = &cell;
|
||||
m_overlapping = false;
|
||||
init ();
|
||||
|
|
@ -272,6 +271,7 @@ RecursiveInstanceIterator::validate (RecursiveInstanceReceiver *receiver) const
|
|||
m_inst_array_iterators.clear ();
|
||||
m_cells.clear ();
|
||||
m_trans = cplx_trans_type ();
|
||||
m_target_tree.clear ();
|
||||
|
||||
m_local_region_stack.clear ();
|
||||
m_local_region_stack.push_back (m_region);
|
||||
|
|
@ -300,10 +300,9 @@ RecursiveInstanceIterator::validate (RecursiveInstanceReceiver *receiver) const
|
|||
|
||||
}
|
||||
|
||||
if (mp_top_cell) {
|
||||
if (mp_top_cell && mp_layout) {
|
||||
|
||||
if (! m_all_targets) {
|
||||
m_target_tree.clear ();
|
||||
mp_top_cell->collect_called_cells (m_target_tree);
|
||||
}
|
||||
|
||||
|
|
@ -501,6 +500,8 @@ RecursiveInstanceIterator::next_instance (RecursiveInstanceReceiver *receiver) c
|
|||
void
|
||||
RecursiveInstanceIterator::down (RecursiveInstanceReceiver *receiver) const
|
||||
{
|
||||
tl_assert (mp_layout);
|
||||
|
||||
m_trans_stack.push_back (m_trans);
|
||||
m_cells.push_back (mp_cell);
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "dbLayout.h"
|
||||
#include "dbInstElement.h"
|
||||
#include "tlAssert.h"
|
||||
#include "tlObject.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
|
@ -180,7 +181,7 @@ public:
|
|||
*/
|
||||
const layout_type *layout () const
|
||||
{
|
||||
return mp_layout;
|
||||
return mp_layout.get ();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -544,7 +545,7 @@ private:
|
|||
std::set<db::cell_index_type> m_targets;
|
||||
bool m_all_targets;
|
||||
|
||||
const layout_type *mp_layout;
|
||||
tl::weak_ptr<layout_type> mp_layout;
|
||||
const cell_type *mp_top_cell;
|
||||
|
||||
box_type m_region;
|
||||
|
|
|
|||
|
|
@ -93,7 +93,6 @@ RecursiveShapeIterator::RecursiveShapeIterator ()
|
|||
// anything. Not necessary reasonable.
|
||||
m_layer = 0;
|
||||
m_has_layers = false;
|
||||
mp_layout = 0;
|
||||
mp_shapes = 0;
|
||||
mp_top_cell = 0;
|
||||
mp_cell = 0;
|
||||
|
|
@ -113,7 +112,6 @@ RecursiveShapeIterator::RecursiveShapeIterator (const shapes_type &shapes)
|
|||
{
|
||||
m_layer = 0;
|
||||
m_has_layers = false;
|
||||
mp_layout = 0;
|
||||
mp_shapes = &shapes;
|
||||
mp_top_cell = 0;
|
||||
m_overlapping = false;
|
||||
|
|
@ -125,7 +123,6 @@ RecursiveShapeIterator::RecursiveShapeIterator (const shapes_type &shapes, const
|
|||
{
|
||||
m_layer = 0;
|
||||
m_has_layers = false;
|
||||
mp_layout = 0;
|
||||
mp_shapes = &shapes;
|
||||
mp_top_cell = 0;
|
||||
m_overlapping = overlapping;
|
||||
|
|
@ -137,7 +134,6 @@ RecursiveShapeIterator::RecursiveShapeIterator (const shapes_type &shapes, const
|
|||
{
|
||||
m_layer = 0;
|
||||
m_has_layers = false;
|
||||
mp_layout = 0;
|
||||
mp_shapes = &shapes;
|
||||
mp_top_cell = 0;
|
||||
m_overlapping = overlapping;
|
||||
|
|
@ -150,7 +146,7 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
|
|||
{
|
||||
m_layer = layer;
|
||||
m_has_layers = false;
|
||||
mp_layout = &layout;
|
||||
mp_layout.reset (const_cast<db::Layout *> (&layout));
|
||||
mp_shapes = 0;
|
||||
mp_top_cell = &cell;
|
||||
m_overlapping = overlapping;
|
||||
|
|
@ -163,7 +159,7 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
|
|||
{
|
||||
m_layer = layer;
|
||||
m_has_layers = false;
|
||||
mp_layout = &layout;
|
||||
mp_layout.reset (const_cast<db::Layout *> (&layout));
|
||||
mp_shapes = 0;
|
||||
mp_top_cell = &cell;
|
||||
m_overlapping = overlapping;
|
||||
|
|
@ -176,7 +172,7 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
|
|||
{
|
||||
m_layer = layer;
|
||||
m_has_layers = false;
|
||||
mp_layout = &layout;
|
||||
mp_layout.reset (const_cast<db::Layout *> (&layout));
|
||||
mp_shapes = 0;
|
||||
mp_top_cell = &cell;
|
||||
m_overlapping = false;
|
||||
|
|
@ -190,7 +186,7 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
|
|||
m_layer = 0;
|
||||
m_layers = layers;
|
||||
m_has_layers = true;
|
||||
mp_layout = &layout;
|
||||
mp_layout.reset (const_cast<db::Layout *> (&layout));
|
||||
mp_shapes = 0;
|
||||
mp_top_cell = &cell;
|
||||
m_overlapping = overlapping;
|
||||
|
|
@ -204,7 +200,7 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
|
|||
m_layer = 0;
|
||||
m_layers = layers;
|
||||
m_has_layers = true;
|
||||
mp_layout = &layout;
|
||||
mp_layout.reset (const_cast<db::Layout *> (&layout));
|
||||
mp_shapes = 0;
|
||||
mp_top_cell = &cell;
|
||||
m_overlapping = overlapping;
|
||||
|
|
@ -218,7 +214,7 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
|
|||
m_layer = 0;
|
||||
m_layers = layers;
|
||||
m_has_layers = true;
|
||||
mp_layout = &layout;
|
||||
mp_layout.reset (const_cast<db::Layout *> (&layout));
|
||||
mp_shapes = 0;
|
||||
mp_top_cell = &cell;
|
||||
m_overlapping = false;
|
||||
|
|
@ -232,7 +228,7 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
|
|||
m_layer = 0;
|
||||
m_layers.insert (m_layers.end (), layers.begin (), layers.end ());
|
||||
m_has_layers = true;
|
||||
mp_layout = &layout;
|
||||
mp_layout.reset (const_cast<db::Layout *> (&layout));
|
||||
mp_shapes = 0;
|
||||
mp_top_cell = &cell;
|
||||
m_overlapping = overlapping;
|
||||
|
|
@ -246,7 +242,7 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
|
|||
m_layer = 0;
|
||||
m_layers.insert (m_layers.end (), layers.begin (), layers.end ());
|
||||
m_has_layers = true;
|
||||
mp_layout = &layout;
|
||||
mp_layout.reset (const_cast<db::Layout *> (&layout));
|
||||
mp_shapes = 0;
|
||||
mp_top_cell = &cell;
|
||||
m_overlapping = overlapping;
|
||||
|
|
@ -260,7 +256,7 @@ RecursiveShapeIterator::RecursiveShapeIterator (const layout_type &layout, const
|
|||
m_layer = 0;
|
||||
m_layers.insert (m_layers.end (), layers.begin (), layers.end ());
|
||||
m_has_layers = true;
|
||||
mp_layout = &layout;
|
||||
mp_layout.reset (const_cast<db::Layout *> (&layout));
|
||||
mp_shapes = 0;
|
||||
mp_top_cell = &cell;
|
||||
m_overlapping = false;
|
||||
|
|
@ -691,6 +687,8 @@ RecursiveShapeIterator::next_shape (RecursiveShapeReceiver *receiver) const
|
|||
|
||||
if (! m_inst.at_end () && int (m_inst_iterators.size ()) < m_max_depth) {
|
||||
|
||||
tl_assert (mp_layout);
|
||||
|
||||
// determine whether the cell is empty with respect to the layers specified
|
||||
bool is_empty = false;
|
||||
if (! m_has_layers) {
|
||||
|
|
@ -754,6 +752,8 @@ RecursiveShapeIterator::next_shape (RecursiveShapeReceiver *receiver) const
|
|||
void
|
||||
RecursiveShapeIterator::down (RecursiveShapeReceiver *receiver) const
|
||||
{
|
||||
tl_assert (mp_layout);
|
||||
|
||||
m_trans_stack.push_back (m_trans);
|
||||
m_cells.push_back (mp_cell);
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "dbLayout.h"
|
||||
#include "dbInstElement.h"
|
||||
#include "tlAssert.h"
|
||||
#include "tlObject.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
|
@ -306,7 +307,7 @@ public:
|
|||
*/
|
||||
const layout_type *layout () const
|
||||
{
|
||||
return mp_layout;
|
||||
return mp_layout.get ();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -765,7 +766,7 @@ private:
|
|||
std::set<db::cell_index_type> m_start, m_stop;
|
||||
cplx_trans_type m_global_trans;
|
||||
|
||||
const layout_type *mp_layout;
|
||||
tl::weak_ptr<layout_type> mp_layout;
|
||||
const cell_type *mp_top_cell;
|
||||
const shapes_type *mp_shapes;
|
||||
|
||||
|
|
|
|||
|
|
@ -49,6 +49,11 @@ struct box_defs
|
|||
return c.release ();
|
||||
}
|
||||
|
||||
static C world ()
|
||||
{
|
||||
return C::world ();
|
||||
}
|
||||
|
||||
static C *new_v ()
|
||||
{
|
||||
return new C ();
|
||||
|
|
@ -132,6 +137,22 @@ struct box_defs
|
|||
"are not provided in the correct order (i.e. right < left), these are "
|
||||
"swapped."
|
||||
) +
|
||||
method ("world", &world,
|
||||
"@brief Gets the 'world' box\n"
|
||||
"The world box is the biggest box that can be represented. So it is basically 'all'. The "
|
||||
"world box behaves neutral on intersections for example. In other operations such as displacement or transformations, "
|
||||
"the world box may render unexpected results because of coordinate overflow.\n"
|
||||
"\n"
|
||||
"The world box can be used\n"
|
||||
"@ul\n"
|
||||
" @li for comparison ('==', '!=', '<') @/li\n"
|
||||
" @li in union and intersection ('+' and '&') @/li\n"
|
||||
" @li in relations (\\contains?, \\overlaps?, \\touches?) @/li\n"
|
||||
" @li as 'all' argument in region queries @/li\n"
|
||||
"@/ul\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28."
|
||||
) +
|
||||
method ("p1", &C::p1,
|
||||
"@brief Gets the lower left point of the box\n"
|
||||
) +
|
||||
|
|
|
|||
|
|
@ -68,6 +68,12 @@ struct cell_inst_array_defs
|
|||
return new C ();
|
||||
}
|
||||
|
||||
static C *
|
||||
new_cell_inst_vector (db::cell_index_type ci, const vector_type &v)
|
||||
{
|
||||
return new C (db::CellInst (ci), trans_type (v));
|
||||
}
|
||||
|
||||
static C *
|
||||
new_cell_inst (db::cell_index_type ci, const trans_type &t)
|
||||
{
|
||||
|
|
@ -84,6 +90,13 @@ struct cell_inst_array_defs
|
|||
}
|
||||
}
|
||||
|
||||
static C *
|
||||
new_cell_inst_array_vector (db::cell_index_type ci, const vector_type &v,
|
||||
const vector_type &a, const vector_type &b, unsigned int na, unsigned int nb)
|
||||
{
|
||||
return new C (db::CellInst (ci), trans_type (v), a, b, na, nb);
|
||||
}
|
||||
|
||||
static C *
|
||||
new_cell_inst_array (db::cell_index_type ci, const trans_type &t,
|
||||
const vector_type &a, const vector_type &b, unsigned int na, unsigned int nb)
|
||||
|
|
@ -397,6 +410,12 @@ struct cell_inst_array_defs
|
|||
"@param cell_index The cell to instantiate\n"
|
||||
"@param trans The transformation by which to instantiate the cell\n"
|
||||
) +
|
||||
gsi::constructor ("new", &new_cell_inst_vector, gsi::arg ("cell_index"), gsi::arg ("disp"),
|
||||
"@brief Creates a single cell instance\n"
|
||||
"@param cell_index The cell to instantiate\n"
|
||||
"@param disp The displacement\n"
|
||||
"This convenience initializer has been introduced in version 0.28."
|
||||
) +
|
||||
gsi::constructor ("new", &new_cell_inst_cplx, gsi::arg ("cell_index"), gsi::arg ("trans"),
|
||||
"@brief Creates a single cell instance with a complex transformation\n"
|
||||
"@param cell_index The cell to instantiate\n"
|
||||
|
|
@ -415,6 +434,17 @@ struct cell_inst_array_defs
|
|||
"Starting with version 0.25 the displacements are of vector type."
|
||||
)
|
||||
) +
|
||||
gsi::constructor ("new", &new_cell_inst_array_vector, gsi::arg ("cell_index"), gsi::arg ("disp"), gsi::arg ("a"), gsi::arg ("b"), gsi::arg ("na"), gsi::arg ("nb"),
|
||||
"@brief Creates a single cell instance\n"
|
||||
"@param cell_index The cell to instantiate\n"
|
||||
"@param disp The basic displacement of the first instance\n"
|
||||
"@param a The displacement vector of the array in the 'a' axis\n"
|
||||
"@param b The displacement vector of the array in the 'b' axis\n"
|
||||
"@param na The number of placements in the 'a' axis\n"
|
||||
"@param nb The number of placements in the 'b' axis\n"
|
||||
"\n"
|
||||
"This convenience initializer has been introduced in version 0.28."
|
||||
) +
|
||||
gsi::constructor ("new", &new_cell_inst_array_cplx, gsi::arg ("cell_index"), gsi::arg ("trans"), gsi::arg ("a"), gsi::arg ("b"), gsi::arg ("na"), gsi::arg ("nb"),
|
||||
"@brief Creates a single cell instance with a complex transformation\n"
|
||||
"@param cell_index The cell to instantiate\n"
|
||||
|
|
|
|||
|
|
@ -353,6 +353,33 @@ static db::cell_index_type clip (db::Layout *l, db::cell_index_type c, const db:
|
|||
return cc [0];
|
||||
}
|
||||
|
||||
static db::cell_index_type clip_dbox (db::Layout *l, db::cell_index_type c, const db::DBox &box)
|
||||
{
|
||||
std::vector <db::Box> boxes;
|
||||
boxes.push_back (db::CplxTrans (l->dbu ()).inverted () * box);
|
||||
std::vector <db::cell_index_type> cc = db::clip_layout(*l, *l, c, boxes, true);
|
||||
tl_assert (! cc.empty ());
|
||||
return cc [0];
|
||||
}
|
||||
|
||||
static db::Cell *clip_cell_dbox (db::Layout *l, const db::Cell &c, const db::DBox &box)
|
||||
{
|
||||
std::vector <db::Box> boxes;
|
||||
boxes.push_back (db::CplxTrans (l->dbu ()).inverted () * box);
|
||||
std::vector <db::cell_index_type> cc = db::clip_layout(*l, *l, c.cell_index (), boxes, true);
|
||||
tl_assert (! cc.empty ());
|
||||
return &l->cell (cc [0]);
|
||||
}
|
||||
|
||||
static db::Cell *clip_cell (db::Layout *l, const db::Cell &c, const db::Box &box)
|
||||
{
|
||||
std::vector <db::Box> boxes;
|
||||
boxes.push_back (box);
|
||||
std::vector <db::cell_index_type> cc = db::clip_layout(*l, *l, c.cell_index (), boxes, true);
|
||||
tl_assert (! cc.empty ());
|
||||
return &l->cell (cc [0]);
|
||||
}
|
||||
|
||||
static db::cell_index_type clip_into (const db::Layout *l, db::cell_index_type c, db::Layout *t, const db::Box &box)
|
||||
{
|
||||
std::vector <db::Box> boxes;
|
||||
|
|
@ -362,14 +389,92 @@ static db::cell_index_type clip_into (const db::Layout *l, db::cell_index_type c
|
|||
return cc [0];
|
||||
}
|
||||
|
||||
static db::cell_index_type clip_into_dbox (const db::Layout *l, db::cell_index_type c, db::Layout *t, const db::DBox &box)
|
||||
{
|
||||
std::vector <db::Box> boxes;
|
||||
boxes.push_back (db::CplxTrans (l->dbu ()).inverted () * box);
|
||||
std::vector <db::cell_index_type> cc = db::clip_layout(*l, *t, c, boxes, true);
|
||||
tl_assert (! cc.empty ());
|
||||
return cc [0];
|
||||
}
|
||||
|
||||
static db::Cell *clip_into_cell (const db::Layout *l, const db::Cell &c, db::Layout *t, const db::Box &box)
|
||||
{
|
||||
std::vector <db::Box> boxes;
|
||||
boxes.push_back (box);
|
||||
std::vector <db::cell_index_type> cc = db::clip_layout(*l, *t, c.cell_index (), boxes, true);
|
||||
tl_assert (! cc.empty ());
|
||||
return &t->cell (cc [0]);
|
||||
}
|
||||
|
||||
static db::Cell *clip_into_cell_dbox (const db::Layout *l, const db::Cell &c, db::Layout *t, const db::DBox &box)
|
||||
{
|
||||
std::vector <db::Box> boxes;
|
||||
boxes.push_back (db::CplxTrans (l->dbu ()).inverted () * box);
|
||||
std::vector <db::cell_index_type> cc = db::clip_layout(*l, *t, c.cell_index (), boxes, true);
|
||||
tl_assert (! cc.empty ());
|
||||
return &t->cell (cc [0]);
|
||||
}
|
||||
|
||||
static std::vector<db::Box> transform_boxes (const db::Layout *l, const std::vector<db::DBox> &boxes)
|
||||
{
|
||||
std::vector<db::Box> result;
|
||||
result.reserve (boxes.size ());
|
||||
db::VCplxTrans t = db::CplxTrans (l->dbu ()).inverted ();
|
||||
for (std::vector<db::DBox>::const_iterator i = boxes.begin (); i != boxes.end (); ++i) {
|
||||
result.push_back (t * *i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::vector<db::Cell *> to_cell_refs (db::Layout *l, const std::vector<db::cell_index_type> &cell_indexes)
|
||||
{
|
||||
std::vector<db::Cell *> result;
|
||||
result.reserve (cell_indexes.size ());
|
||||
for (std::vector<db::cell_index_type>::const_iterator i = cell_indexes.begin (); i != cell_indexes.end (); ++i) {
|
||||
result.push_back (&l->cell (*i));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::vector<db::cell_index_type> multi_clip (db::Layout *l, db::cell_index_type c, const std::vector<db::Box> &boxes)
|
||||
{
|
||||
return db::clip_layout(*l, *l, c, boxes, true);
|
||||
return db::clip_layout (*l, *l, c, boxes, true);
|
||||
}
|
||||
|
||||
static std::vector<db::Cell *> multi_clip_cells (db::Layout *l, const db::Cell &c, const std::vector<db::Box> &boxes)
|
||||
{
|
||||
return to_cell_refs (l, db::clip_layout (*l, *l, c.cell_index (), boxes, true));
|
||||
}
|
||||
|
||||
static std::vector<db::cell_index_type> multi_clip_dboxes (db::Layout *l, db::cell_index_type c, const std::vector<db::DBox> &boxes)
|
||||
{
|
||||
return db::clip_layout (*l, *l, c, transform_boxes (l, boxes), true);
|
||||
}
|
||||
|
||||
static std::vector<db::Cell *> multi_clip_cells_dboxes (db::Layout *l, const db::Cell &c, const std::vector<db::DBox> &boxes)
|
||||
{
|
||||
return to_cell_refs (l, db::clip_layout (*l, *l, c.cell_index (), transform_boxes (l, boxes), true));
|
||||
}
|
||||
|
||||
static std::vector<db::cell_index_type> multi_clip_into (db::Layout *l, db::cell_index_type c, db::Layout *t, const std::vector<db::Box> &boxes)
|
||||
{
|
||||
return db::clip_layout(*l, *t, c, boxes, true);
|
||||
return db::clip_layout (*l, *t, c, boxes, true);
|
||||
}
|
||||
|
||||
static std::vector<db::Cell *> multi_clip_into_cells (db::Layout *l, const db::Cell &c, db::Layout *t, const std::vector<db::Box> &boxes)
|
||||
{
|
||||
return to_cell_refs (l, db::clip_layout (*l, *t, c.cell_index (), boxes, true));
|
||||
}
|
||||
|
||||
static std::vector<db::cell_index_type> multi_clip_into_dboxes (db::Layout *l, db::cell_index_type c, db::Layout *t, const std::vector<db::DBox> &boxes)
|
||||
{
|
||||
return db::clip_layout (*l, *t, c, transform_boxes (l, boxes), true);
|
||||
}
|
||||
|
||||
static std::vector<db::Cell *> multi_clip_into_cells_dboxes (db::Layout *l, const db::Cell &c, db::Layout *t, const std::vector<db::DBox> &boxes)
|
||||
{
|
||||
return to_cell_refs (l, db::clip_layout (*l, *t, c.cell_index (), transform_boxes (l, boxes), true));
|
||||
}
|
||||
|
||||
static unsigned int get_layer0 (db::Layout *l)
|
||||
|
|
@ -1104,7 +1209,18 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"@param properties_id The properties ID to get the properties for\n"
|
||||
"@return The array of variants (see \\properties_id)\n"
|
||||
) +
|
||||
gsi::method_ext ("top_cell", &top_cell,
|
||||
gsi::method ("unique_cell_name", &db::Layout::uniquify_cell_name, gsi::arg ("name"),
|
||||
"@brief Creates a new unique cell name from the given name\n"
|
||||
"@return A unique name derived from the argument\n"
|
||||
"\n"
|
||||
"If a cell with the given name exists, a suffix will be added to make the name unique. "
|
||||
"Otherwise, the argument will be returned unchanged.\n"
|
||||
"\n"
|
||||
"The returned name can be used to rename cells without risk of creating name clashes.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28."
|
||||
) +
|
||||
gsi::method_ext ("top_cell", &top_cell,
|
||||
"@brief Returns the top cell object\n"
|
||||
"@return The \\Cell object of the top cell\n"
|
||||
"If the layout has a single top cell, this method returns the top cell's \\Cell object.\n"
|
||||
|
|
@ -1146,14 +1262,21 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"\n"
|
||||
"This method has been introduce in version 0.23 and replaces \\add_cell.\n"
|
||||
) +
|
||||
gsi::method_ext ("create_cell", &create_cell2, gsi::arg ("name"), gsi::arg ("params"),
|
||||
"@brief Creates a cell as a PCell variant with the given name\n"
|
||||
"@param name The name of the PCell and the name of the cell to create\n"
|
||||
gsi::method_ext ("create_cell", &create_cell2, gsi::arg ("pcell_name"), gsi::arg ("params"),
|
||||
"@brief Creates a cell as a PCell variant for the PCell with the given name\n"
|
||||
"@param pcell_name The name of the PCell and also the name of the cell to create\n"
|
||||
"@param params The PCell parameters (key/value dictionary)\n"
|
||||
"@return The \\Cell object of the newly created cell.\n"
|
||||
"@return The \\Cell object of the newly created cell or an existing cell if the PCell has already been used with these parameters.\n"
|
||||
"\n"
|
||||
"This method will look up the PCell by the given name and create a new PCell variant "
|
||||
"with the given parameters. The parameters are specified as a key/value dictionary with "
|
||||
"PCells are instantiated by creating a PCell variant. A PCell variant is linked to the PCell and represents "
|
||||
"this PCell with a particular parameter set.\n"
|
||||
"\n"
|
||||
"This method will look up the PCell by the PCell name and create a new PCell variant "
|
||||
"for the given parameters. If the PCell has already been instantiated with the same parameters, the "
|
||||
"original variant will be returned. Hence this method is not strictly creating a cell - only if the required variant has "
|
||||
"not been created yet.\n"
|
||||
"\n"
|
||||
"The parameters are specified as a key/value dictionary with "
|
||||
"the names being the ones from the PCell declaration.\n"
|
||||
"\n"
|
||||
"If no PCell with the given name exists, nil is returned.\n"
|
||||
|
|
@ -1164,25 +1287,34 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"@brief Creates a cell with the given name\n"
|
||||
"@param name The name of the library cell and the name of the cell to create\n"
|
||||
"@param lib_name The name of the library where to take the cell from\n"
|
||||
"@return The \\Cell object of the newly created cell.\n"
|
||||
"@return The \\Cell object of the newly created cell or an existing cell if the library cell has already been used in this layout.\n"
|
||||
"\n"
|
||||
"Library cells are imported by creating a 'library proxy'. This is a cell which represents "
|
||||
"the library cell in the framework of the current layout. The library proxy is linked to the "
|
||||
"library and will be updated if the library cell is changed.\n"
|
||||
"\n"
|
||||
"This method will look up the cell by the given name in the specified library and create a new library proxy for this cell.\n"
|
||||
"If the same library cell has already been used, the original library proxy is returned. Hence, strictly speaking this "
|
||||
"method does not always create a new cell but may return a reference to an existing cell.\n"
|
||||
"\n"
|
||||
"This method will look up the cell by the given name in the specified library and create a new library proxy to this cell.\n"
|
||||
"If the library name is not valid, nil is returned.\n"
|
||||
"\n"
|
||||
"This method has been introduce in version 0.24.\n"
|
||||
) +
|
||||
gsi::method_ext ("create_cell", &create_cell4, gsi::arg ("name"), gsi::arg ("lib_name"), gsi::arg ("params"),
|
||||
"@brief Creates a cell with the given name\n"
|
||||
"@param name The name of the PCell and the name of the cell to create\n"
|
||||
gsi::method_ext ("create_cell", &create_cell4, gsi::arg ("pcell_name"), gsi::arg ("lib_name"), gsi::arg ("params"),
|
||||
"@brief Creates a cell for a PCell with the given PCell name from the given library\n"
|
||||
"@param pcell_name The name of the PCell and also the name of the cell to create\n"
|
||||
"@param lib_name The name of the library where to take the PCell from\n"
|
||||
"@param params The PCell parameters (key/value dictionary)\n"
|
||||
"@return The \\Cell object of the newly created cell.\n"
|
||||
"@return The \\Cell object of the newly created cell or an existing cell if this PCell has already been used with the given parameters\n"
|
||||
"\n"
|
||||
"This method will look up the PCell by the given name in the specified library and create a new PCell variant "
|
||||
"with the given parameters. The parameters are specified as a key/value dictionary with "
|
||||
"This method will look up the PCell by the PCell name in the specified library and create a new PCell variant "
|
||||
"for the given parameters plus the library proxy. The parameters must be specified as a key/value dictionary with "
|
||||
"the names being the ones from the PCell declaration.\n"
|
||||
"\n"
|
||||
"If no PCell with the given name exists or the library name is not valid, nil is returned.\n"
|
||||
"If no PCell with the given name exists or the library name is not valid, nil is returned. Note that "
|
||||
"this function - despite the name - may not always create a new cell, but return an existing cell if the "
|
||||
"PCell from the library has already been used with the given parameters.\n"
|
||||
"\n"
|
||||
"This method has been introduce in version 0.24.\n"
|
||||
) +
|
||||
|
|
@ -1194,7 +1326,10 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"is returns a \\Cell object (\\create_cell).\n"
|
||||
) +
|
||||
gsi::method ("rename_cell", &db::Layout::rename_cell, gsi::arg ("index"), gsi::arg ("name"),
|
||||
"@brief name\n"
|
||||
"@brief Renames the cell with given index\n"
|
||||
"The cell with the given index is renamed to the given name. NOTE: it is not ensured that the name is unique. "
|
||||
"This method allows assigning identical names to different cells which usually breaks things.\n"
|
||||
"Consider using \\unique_cell_name to generate truely unique names.\n"
|
||||
) +
|
||||
gsi::method ("delete_cell", &db::Layout::delete_cell, gsi::arg ("cell_index"),
|
||||
"@brief Deletes a cell \n"
|
||||
|
|
@ -1916,6 +2051,30 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"\n"
|
||||
"This method has been added in version 0.21.\n"
|
||||
) +
|
||||
gsi::method_ext ("clip", &clip_dbox, gsi::arg ("cell"), gsi::arg ("box"),
|
||||
"@brief Clips the given cell by the given rectangle and produce a new cell with the clip\n"
|
||||
"@param cell The cell index of the cell to clip\n"
|
||||
"@param box The clip box in micrometer units\n"
|
||||
"@return The index of the new cell\n"
|
||||
"\n"
|
||||
"This variant which takes a micrometer-unit box has been added in version 0.28."
|
||||
) +
|
||||
gsi::method_ext ("clip", &clip_cell, gsi::arg ("cell"), gsi::arg ("box"),
|
||||
"@brief Clips the given cell by the given rectangle and produce a new cell with the clip\n"
|
||||
"@param cell The cell reference of the cell to clip\n"
|
||||
"@param box The clip box in database units\n"
|
||||
"@return The reference to the new cell\n"
|
||||
"\n"
|
||||
"This variant which takes cell references instead of cell indexes has been added in version 0.28."
|
||||
) +
|
||||
gsi::method_ext ("clip", &clip_cell_dbox, gsi::arg ("cell"), gsi::arg ("box"),
|
||||
"@brief Clips the given cell by the given rectangle and produce a new cell with the clip\n"
|
||||
"@param cell The cell reference of the cell to clip\n"
|
||||
"@param box The clip box in micrometer units\n"
|
||||
"@return The reference to the new cell\n"
|
||||
"\n"
|
||||
"This variant which takes a micrometer-unit box and cell references has been added in version 0.28."
|
||||
) +
|
||||
gsi::method_ext ("clip_into", &clip_into, gsi::arg ("cell"), gsi::arg ("target"), gsi::arg ("box"),
|
||||
"@brief Clips the given cell by the given rectangle and produce a new cell with the clip\n"
|
||||
"@param cell The cell index of the cell to clip\n"
|
||||
|
|
@ -1935,8 +2094,35 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"\n"
|
||||
"This method has been added in version 0.21.\n"
|
||||
) +
|
||||
gsi::method_ext ("clip_into", &clip_into_dbox, gsi::arg ("cell"), gsi::arg ("target"), gsi::arg ("box"),
|
||||
"@brief Clips the given cell by the given rectangle and produce a new cell with the clip\n"
|
||||
"@param cell The cell index of the cell to clip\n"
|
||||
"@param box The clip box in micrometer units\n"
|
||||
"@param target The target layout\n"
|
||||
"@return The index of the new cell in the target layout\n"
|
||||
"\n"
|
||||
"This variant which takes a micrometer-unit box has been added in version 0.28."
|
||||
) +
|
||||
gsi::method_ext ("clip_into", &clip_into_cell, gsi::arg ("cell"), gsi::arg ("target"), gsi::arg ("box"),
|
||||
"@brief Clips the given cell by the given rectangle and produce a new cell with the clip\n"
|
||||
"@param cell The reference to the cell to clip\n"
|
||||
"@param box The clip box in database units\n"
|
||||
"@param target The target layout\n"
|
||||
"@return The reference to the new cell in the target layout\n"
|
||||
"\n"
|
||||
"This variant which takes cell references instead of cell indexes has been added in version 0.28."
|
||||
) +
|
||||
gsi::method_ext ("clip_into", &clip_into_cell_dbox, gsi::arg ("cell"), gsi::arg ("target"), gsi::arg ("box"),
|
||||
"@brief Clips the given cell by the given rectangle and produce a new cell with the clip\n"
|
||||
"@param cell The reference to the cell to clip\n"
|
||||
"@param box The clip box in micrometer units\n"
|
||||
"@param target The target layout\n"
|
||||
"@return The reference to the new cell in the target layout\n"
|
||||
"\n"
|
||||
"This variant which takes a micrometer-unit box and cell references has been added in version 0.28."
|
||||
) +
|
||||
gsi::method_ext ("multi_clip", &multi_clip, gsi::arg ("cell"), gsi::arg ("boxes"),
|
||||
"@brief Clips the given cell by the given rectangles and produce new cells with the clips, one for each rectangle.\n"
|
||||
"@brief Clips the given cell by the given rectangles and produces new cells with the clips, one for each rectangle.\n"
|
||||
"@param cell The cell index of the cell to clip\n"
|
||||
"@param boxes The clip boxes in database units\n"
|
||||
"@return The indexes of the new cells\n"
|
||||
|
|
@ -1949,8 +2135,32 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"\n"
|
||||
"This method has been added in version 0.21.\n"
|
||||
) +
|
||||
gsi::method_ext ("multi_clip", &multi_clip_dboxes, gsi::arg ("cell"), gsi::arg ("boxes"),
|
||||
"@brief Clips the given cell by the given rectangles and produces new cells with the clips, one for each rectangle.\n"
|
||||
"@param cell The cell index of the cell to clip\n"
|
||||
"@param boxes The clip boxes in micrometer units\n"
|
||||
"@return The indexes of the new cells\n"
|
||||
"\n"
|
||||
"This variant which takes micrometer-unit boxes has been added in version 0.28."
|
||||
) +
|
||||
gsi::method_ext ("multi_clip", &multi_clip_cells, gsi::arg ("cell"), gsi::arg ("boxes"),
|
||||
"@brief Clips the given cell by the given rectangles and produces new cells with the clips, one for each rectangle.\n"
|
||||
"@param cell The reference to the cell to clip\n"
|
||||
"@param boxes The clip boxes in database units\n"
|
||||
"@return The references to the new cells\n"
|
||||
"\n"
|
||||
"This variant which takes cell references has been added in version 0.28."
|
||||
) +
|
||||
gsi::method_ext ("multi_clip", &multi_clip_cells_dboxes, gsi::arg ("cell"), gsi::arg ("boxes"),
|
||||
"@brief Clips the given cell by the given rectangles and produces new cells with the clips, one for each rectangle.\n"
|
||||
"@param cell The reference to the cell to clip\n"
|
||||
"@param boxes The clip boxes in micrometer units\n"
|
||||
"@return The references to the new cells\n"
|
||||
"\n"
|
||||
"This variant which takes cell references and micrometer-unit boxes has been added in version 0.28."
|
||||
) +
|
||||
gsi::method_ext ("multi_clip_into", &multi_clip_into, gsi::arg ("cell"), gsi::arg ("target"), gsi::arg ("boxes"),
|
||||
"@brief Clips the given cell by the given rectangles and produce new cells with the clips, one for each rectangle.\n"
|
||||
"@brief Clips the given cell by the given rectangles and produces new cells with the clips, one for each rectangle.\n"
|
||||
"@param cell The cell index of the cell to clip\n"
|
||||
"@param boxes The clip boxes in database units\n"
|
||||
"@param target The target layout\n"
|
||||
|
|
@ -1969,6 +2179,33 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"\n"
|
||||
"This method has been added in version 0.21.\n"
|
||||
) +
|
||||
gsi::method_ext ("multi_clip_into", &multi_clip_into_dboxes, gsi::arg ("cell"), gsi::arg ("target"), gsi::arg ("boxes"),
|
||||
"@brief Clips the given cell by the given rectangles and produces new cells with the clips, one for each rectangle.\n"
|
||||
"@param cell The cell index of the cell to clip\n"
|
||||
"@param boxes The clip boxes in database units\n"
|
||||
"@param target The target layout\n"
|
||||
"@return The indexes of the new cells\n"
|
||||
"\n"
|
||||
"This variant which takes micrometer-unit boxes has been added in version 0.28."
|
||||
) +
|
||||
gsi::method_ext ("multi_clip_into", &multi_clip_into_cells, gsi::arg ("cell"), gsi::arg ("target"), gsi::arg ("boxes"),
|
||||
"@brief Clips the given cell by the given rectangles and produces new cells with the clips, one for each rectangle.\n"
|
||||
"@param cell The reference the cell to clip\n"
|
||||
"@param boxes The clip boxes in database units\n"
|
||||
"@param target The target layout\n"
|
||||
"@return The references to the new cells\n"
|
||||
"\n"
|
||||
"This variant which takes cell references boxes has been added in version 0.28."
|
||||
) +
|
||||
gsi::method_ext ("multi_clip_into", &multi_clip_into_cells_dboxes, gsi::arg ("cell"), gsi::arg ("target"), gsi::arg ("boxes"),
|
||||
"@brief Clips the given cell by the given rectangles and produces new cells with the clips, one for each rectangle.\n"
|
||||
"@param cell The reference the cell to clip\n"
|
||||
"@param boxes The clip boxes in micrometer units\n"
|
||||
"@param target The target layout\n"
|
||||
"@return The references to the new cells\n"
|
||||
"\n"
|
||||
"This variant which takes cell references and micrometer-unit boxes has been added in version 0.28."
|
||||
) +
|
||||
gsi::method ("convert_cell_to_static", &db::Layout::convert_cell_to_static, gsi::arg ("cell_index"),
|
||||
"@brief Converts a PCell or library cell to a usual (static) cell\n"
|
||||
"@return The index of the new cell\n"
|
||||
|
|
|
|||
|
|
@ -111,7 +111,9 @@ char shape_query_property_name[] = "shape";
|
|||
char layer_index_query_property_name[] = "layer_index";
|
||||
char inst_query_property_name[] = "inst";
|
||||
char path_trans_query_property_name[] = "path_trans";
|
||||
char path_dtrans_query_property_name[] = "path_dtrans";
|
||||
char trans_query_property_name[] = "trans";
|
||||
char dtrans_query_property_name[] = "dtrans";
|
||||
char cell_index_query_property_name[] = "cell_index";
|
||||
char cell_query_property_name[] = "cell";
|
||||
char parent_cell_index_query_property_name[] = "parent_cell_index";
|
||||
|
|
@ -138,7 +140,9 @@ Class<db::LayoutQueryIterator> decl_LayoutQueryIterator ("db", "LayoutQueryItera
|
|||
make_shortcut_method<layer_index_query_property_name>() +
|
||||
make_shortcut_method<inst_query_property_name>() +
|
||||
make_shortcut_method<path_trans_query_property_name>() +
|
||||
make_shortcut_method<path_dtrans_query_property_name>() +
|
||||
make_shortcut_method<trans_query_property_name>() +
|
||||
make_shortcut_method<dtrans_query_property_name>() +
|
||||
make_shortcut_method<cell_index_query_property_name>() +
|
||||
make_shortcut_method<cell_query_property_name>() +
|
||||
make_shortcut_method<parent_cell_index_query_property_name>() +
|
||||
|
|
|
|||
|
|
@ -965,9 +965,9 @@ struct polygon_defs
|
|||
poly->size (d, d, mode);
|
||||
}
|
||||
|
||||
static void size_d (C *poly, coord_type d)
|
||||
static void size_dvm (C *poly, const db::Vector &dv, unsigned int mode)
|
||||
{
|
||||
poly->size (d, d, 2);
|
||||
poly->size (dv.x (), dv.y (), mode);
|
||||
}
|
||||
|
||||
static C sized_xy (const C *poly, coord_type dx, coord_type dy, unsigned int mode)
|
||||
|
|
@ -980,9 +980,9 @@ struct polygon_defs
|
|||
return poly->sized (d, d, mode);
|
||||
}
|
||||
|
||||
static C sized_d (const C *poly, coord_type d)
|
||||
static C sized_dvm (const C *poly, const db::Vector &dv, unsigned int mode)
|
||||
{
|
||||
return poly->sized (d, d, 2);
|
||||
return poly->sized (dv.x (), dv.y (), mode);
|
||||
}
|
||||
|
||||
static bool inside (const C *poly, point_type pt)
|
||||
|
|
@ -1272,7 +1272,19 @@ struct polygon_defs
|
|||
"result = ep.simple_merge_p2p([ poly ], false, false, 1)\n"
|
||||
"@/code\n"
|
||||
) +
|
||||
method_ext ("size", &size_dm, gsi::arg ("d"), gsi::arg ("mode"),
|
||||
method_ext ("size", &size_dvm, gsi::arg ("dv"), gsi::arg ("mode", (unsigned int) 2),
|
||||
"@brief Sizes the polygon (biasing)\n"
|
||||
"\n"
|
||||
"This method is equivalent to\n"
|
||||
"@code\n"
|
||||
"size(dv.x, dv.y, mode)\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"See \\size for a detailed description.\n"
|
||||
"\n"
|
||||
"This version has been introduced in version 0.28.\n"
|
||||
) +
|
||||
method_ext ("size", &size_dm, gsi::arg ("d"), gsi::arg ("mode", (unsigned int) 2),
|
||||
"@brief Sizes the polygon (biasing)\n"
|
||||
"\n"
|
||||
"Shifts the contour outwards (d>0) or inwards (d<0).\n"
|
||||
|
|
@ -1294,7 +1306,19 @@ struct polygon_defs
|
|||
"\n"
|
||||
"This method has been introduced in version 0.23.\n"
|
||||
) +
|
||||
method_ext ("sized", &sized_dm, gsi::arg ("d"), gsi::arg ("mode"),
|
||||
method_ext ("sized", &sized_dvm, gsi::arg ("dv"), gsi::arg ("mode", (unsigned int) 2),
|
||||
"@brief Sizes the polygon (biasing) without modifying self\n"
|
||||
"\n"
|
||||
"This method is equivalent to\n"
|
||||
"@code\n"
|
||||
"sized(dv.x, dv.y, mode)\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"See \\size and \\sized for a detailed description.\n"
|
||||
"\n"
|
||||
"This version has been introduced in version 0.28.\n"
|
||||
) +
|
||||
method_ext ("sized", &sized_dm, gsi::arg ("d"), gsi::arg ("mode", (unsigned int) 2),
|
||||
"@brief Sizes the polygon (biasing) without modifying self\n"
|
||||
"\n"
|
||||
"Shifts the contour outwards (d>0) or inwards (d<0).\n"
|
||||
|
|
@ -1305,28 +1329,6 @@ struct polygon_defs
|
|||
"\n"
|
||||
"See \\size and \\sized for a detailed description.\n"
|
||||
) +
|
||||
method_ext ("sized", &sized_d, gsi::arg ("d"),
|
||||
"@brief Sizes the polygon (biasing)\n"
|
||||
"\n"
|
||||
"@brief Sizing (biasing) without modifying self\n"
|
||||
"This method is equivalent to\n"
|
||||
"@code\n"
|
||||
"sized(d, d, 2)\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"See \\size and \\sized for a detailed description.\n"
|
||||
) +
|
||||
method_ext ("size", &size_d, gsi::arg ("d"),
|
||||
"@brief Sizes the polygon (biasing)\n"
|
||||
"\n"
|
||||
"Shifts the contour outwards (d>0) or inwards (d<0).\n"
|
||||
"This method is equivalent to\n"
|
||||
"@code\n"
|
||||
"size(d, d, 2)\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"See \\size for a detailed description.\n"
|
||||
) +
|
||||
method ("holes", &C::holes,
|
||||
"@brief Returns the number of holes"
|
||||
) +
|
||||
|
|
|
|||
|
|
@ -30,6 +30,31 @@
|
|||
namespace gsi
|
||||
{
|
||||
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* @brief A wrapper that allows using "each" on the iterator
|
||||
*/
|
||||
class IteratorIterator
|
||||
{
|
||||
public:
|
||||
typedef db::RecursiveInstanceIterator value_type;
|
||||
typedef db::RecursiveInstanceIterator &reference;
|
||||
typedef db::RecursiveInstanceIterator *pointer;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef void difference_type;
|
||||
|
||||
IteratorIterator (db::RecursiveInstanceIterator *iter) : mp_iter (iter) { }
|
||||
bool at_end () const { return mp_iter->at_end (); }
|
||||
reference operator* () const { return *mp_iter; }
|
||||
void operator++ () { ++*mp_iter; }
|
||||
|
||||
private:
|
||||
db::RecursiveInstanceIterator *mp_iter;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// db::RecursiveInstanceIterator binding
|
||||
|
||||
|
|
@ -48,6 +73,11 @@ static db::RecursiveInstanceIterator *new_si2a (const db::Layout &layout, const
|
|||
return new db::RecursiveInstanceIterator (layout, cell, region, overlapping);
|
||||
}
|
||||
|
||||
static IteratorIterator each (db::RecursiveInstanceIterator *r)
|
||||
{
|
||||
return IteratorIterator (r);
|
||||
}
|
||||
|
||||
static db::DCplxTrans si_dtrans (const db::RecursiveInstanceIterator *r)
|
||||
{
|
||||
const db::Layout *ly = r->layout ();
|
||||
|
|
@ -184,6 +214,21 @@ Class<db::RecursiveInstanceIterator> decl_RecursiveInstanceIterator ("db", "Recu
|
|||
"bounding box touches the search region are reported. The bounding box of instances is measured taking all layers "
|
||||
"of the target cell into account.\n"
|
||||
) +
|
||||
gsi::iterator_ext ("each", &each,
|
||||
"@brief Native iteration\n"
|
||||
"This method enables native iteration, e.g.\n"
|
||||
"\n"
|
||||
"@code\n"
|
||||
" iter = ... # RecursiveInstanceIterator\n"
|
||||
" iter.each do |i|\n"
|
||||
" ... i is the iterator itself\n"
|
||||
" end\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"This is slightly more convenient than the 'at_end' .. 'next' loop.\n"
|
||||
"\n"
|
||||
"This feature has been introduced in version 0.28.\n"
|
||||
) +
|
||||
gsi::method ("max_depth=", (void (db::RecursiveInstanceIterator::*) (int)) &db::RecursiveInstanceIterator::max_depth, gsi::arg ("depth"),
|
||||
"@brief Specifies the maximum hierarchy depth to look into\n"
|
||||
"\n"
|
||||
|
|
@ -466,6 +511,11 @@ Class<db::RecursiveInstanceIterator> decl_RecursiveInstanceIterator ("db", "Recu
|
|||
" puts \"Instance of #{iter.inst_cell.name} in #{cell.name}: \" + (iter.dtrans * iter.inst_dtrans).to_s\n"
|
||||
" iter.next\n"
|
||||
"end\n"
|
||||
"\n"
|
||||
"# or shorter:\n"
|
||||
"cell.begin_instances_rec.each do |iter|\n"
|
||||
" puts \"Instance of #{iter.inst_cell.name} in #{cell.name}: \" + (iter.dtrans * iter.inst_dtrans).to_s\n"
|
||||
"end\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"Here, a target cell is specified which confines the search to instances of this particular cell.\n"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
#
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
|
|
@ -27,12 +27,39 @@
|
|||
|
||||
#include "tlGlobPattern.h"
|
||||
|
||||
#include <iterator>
|
||||
|
||||
namespace gsi
|
||||
{
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// db::RecursiveShapeIterator binding
|
||||
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* @brief A wrapper that allows using "each" on the iterator
|
||||
*/
|
||||
class IteratorIterator
|
||||
{
|
||||
public:
|
||||
typedef db::RecursiveShapeIterator value_type;
|
||||
typedef db::RecursiveShapeIterator &reference;
|
||||
typedef db::RecursiveShapeIterator *pointer;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef void difference_type;
|
||||
|
||||
IteratorIterator (db::RecursiveShapeIterator *iter) : mp_iter (iter) { }
|
||||
bool at_end () const { return mp_iter->at_end (); }
|
||||
reference operator* () const { return *mp_iter; }
|
||||
void operator++ () { ++*mp_iter; }
|
||||
|
||||
private:
|
||||
db::RecursiveShapeIterator *mp_iter;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
static db::RecursiveShapeIterator *new_si1 (const db::Layout &layout, const db::Cell &cell, unsigned int layer)
|
||||
{
|
||||
return new db::RecursiveShapeIterator (layout, cell, layer);
|
||||
|
|
@ -63,6 +90,11 @@ static db::RecursiveShapeIterator *new_si4a (const db::Layout &layout, const db:
|
|||
return new db::RecursiveShapeIterator (layout, cell, layers, region, overlapping);
|
||||
}
|
||||
|
||||
static IteratorIterator each (db::RecursiveShapeIterator *r)
|
||||
{
|
||||
return IteratorIterator (r);
|
||||
}
|
||||
|
||||
static db::DCplxTrans si_dtrans (const db::RecursiveShapeIterator *r)
|
||||
{
|
||||
const db::Layout *ly = r->layout ();
|
||||
|
|
@ -236,6 +268,21 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
|
|||
"\n"
|
||||
"This constructor has been introduced in version 0.23. The 'overlapping' parameter has been made optional in version 0.27.\n"
|
||||
) +
|
||||
gsi::iterator_ext ("each", &each,
|
||||
"@brief Native iteration\n"
|
||||
"This method enables native iteration, e.g.\n"
|
||||
"\n"
|
||||
"@code\n"
|
||||
" iter = ... # RecursiveShapeIterator\n"
|
||||
" iter.each do |i|\n"
|
||||
" ... i is the iterator itself\n"
|
||||
" end\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"This is slightly more convenient than the 'at_end' .. 'next' loop.\n"
|
||||
"\n"
|
||||
"This feature has been introduced in version 0.28.\n"
|
||||
) +
|
||||
gsi::method ("max_depth=", (void (db::RecursiveShapeIterator::*) (int)) &db::RecursiveShapeIterator::max_depth, gsi::arg ("depth"),
|
||||
"@brief Specifies the maximum hierarchy depth to look into\n"
|
||||
"\n"
|
||||
|
|
@ -560,6 +607,14 @@ Class<db::RecursiveShapeIterator> decl_RecursiveShapeIterator ("db", "RecursiveS
|
|||
" end\n"
|
||||
" iter.next\n"
|
||||
"end\n"
|
||||
"\n"
|
||||
"# or shorter:\n"
|
||||
"cell.begin_shapes_rec(layer).each do |iter|\n"
|
||||
" if iter.shape.renders_polygon?\n"
|
||||
" polygon = iter.shape.polygon.transformed(iter.itrans)\n"
|
||||
" puts \"In cell #{iter.cell.name}: \" + polygon.to_s\n"
|
||||
" end\n"
|
||||
"end\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"\\Cell offers three methods to get these iterators: begin_shapes_rec, begin_shapes_rec_touching and begin_shapes_rec_overlapping.\n"
|
||||
|
|
|
|||
|
|
@ -471,17 +471,6 @@ static void break_polygons (db::Region *r, size_t max_vertex_count, double max_a
|
|||
r->process (db::PolygonBreaker (max_vertex_count, max_area_ratio));
|
||||
}
|
||||
|
||||
static db::Region &size_ext (db::Region *r, db::Coord d)
|
||||
{
|
||||
r->size (d);
|
||||
return *r;
|
||||
}
|
||||
|
||||
static db::Region sized_ext (db::Region *r, db::Coord d)
|
||||
{
|
||||
return r->sized (d);
|
||||
}
|
||||
|
||||
static db::Region &merge_ext1 (db::Region *r, int min_wc)
|
||||
{
|
||||
r->merge (false, std::max (0, min_wc - 1));
|
||||
|
|
@ -740,6 +729,19 @@ fill_region_multi (const db::Region *fr, db::Cell *cell, db::cell_index_type fil
|
|||
db::fill_region_repeat (cell, *fr, fill_cell_index, fc_box, row_step, column_step, fill_margin, remaining_polygons, glue_box);
|
||||
}
|
||||
|
||||
static db::Region
|
||||
sized_dvm (const db::Region *region, const db::Vector &dv, unsigned int mode)
|
||||
{
|
||||
return region->sized (dv.x (), dv.y (), mode);
|
||||
}
|
||||
|
||||
static db::Region &
|
||||
size_dvm (db::Region *region, const db::Vector &dv, unsigned int mode)
|
||||
{
|
||||
region->size (dv.x (), dv.y (), mode);
|
||||
return *region;
|
||||
}
|
||||
|
||||
static db::Point default_origin;
|
||||
|
||||
// provided by gsiDeclDbPolygon.cc:
|
||||
|
|
@ -1537,7 +1539,18 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"# r now is (50,-50;50,100;100,100;100,-50)\n"
|
||||
"@/code\n"
|
||||
) +
|
||||
method ("size", (db::Region & (db::Region::*) (db::Coord, unsigned int)) &db::Region::size, gsi::arg ("d"), gsi::arg ("mode"),
|
||||
method_ext ("size", &size_dvm, gsi::arg ("dv"), gsi::arg ("mode", (unsigned int) 2),
|
||||
"@brief Anisotropic sizing (biasing)\n"
|
||||
"\n"
|
||||
"@return The region after the sizing has applied (self)\n"
|
||||
"\n"
|
||||
"This method is equivalent to \"size(dv.x, dv.y, mode)\".\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This variant has been introduced in version 0.28."
|
||||
) +
|
||||
method ("size", (db::Region & (db::Region::*) (db::Coord, unsigned int)) &db::Region::size, gsi::arg ("d"), gsi::arg ("mode", (unsigned int) 2),
|
||||
"@brief Isotropic sizing (biasing)\n"
|
||||
"\n"
|
||||
"@return The region after the sizing has applied (self)\n"
|
||||
|
|
@ -1546,39 +1559,34 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("size", size_ext, gsi::arg ("d"),
|
||||
"@brief Isotropic sizing (biasing)\n"
|
||||
"\n"
|
||||
"@return The region after the sizing has applied (self)\n"
|
||||
"\n"
|
||||
"This method is equivalent to \"size(d, d, 2)\".\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method ("sized", (db::Region (db::Region::*) (db::Coord, db::Coord, unsigned int) const) &db::Region::sized, gsi::arg ("dx"), gsi::arg ("dy"), gsi::arg ("mode"),
|
||||
"@brief Returns the anisotropically sized region\n"
|
||||
"\n"
|
||||
"@return The sized region\n"
|
||||
"\n"
|
||||
"This method is returns the sized region (see \\size), but does not modify self.\n"
|
||||
"This method returns the sized region (see \\size), but does not modify self.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method ("sized", (db::Region (db::Region::*) (db::Coord, unsigned int) const) &db::Region::sized, gsi::arg ("d"), gsi::arg ("mode"),
|
||||
method_ext ("sized", &sized_dvm, gsi::arg ("dv"), gsi::arg ("mode", (unsigned int) 2),
|
||||
"@brief Returns the (an)isotropically sized region\n"
|
||||
"\n"
|
||||
"@return The sized region\n"
|
||||
"\n"
|
||||
"This method is equivalent to \"sized(dv.x, dv.y, mode)\".\n"
|
||||
"This method returns the sized region (see \\size), but does not modify self.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
"\n"
|
||||
"This variant has been introduced in version 0.28."
|
||||
) +
|
||||
method ("sized", (db::Region (db::Region::*) (db::Coord, unsigned int) const) &db::Region::sized, gsi::arg ("d"), gsi::arg ("mode", (unsigned int) 2),
|
||||
"@brief Returns the isotropically sized region\n"
|
||||
"\n"
|
||||
"@return The sized region\n"
|
||||
"\n"
|
||||
"This method is returns the sized region (see \\size), but does not modify self.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
method_ext ("sized", sized_ext, gsi::arg ("d"),
|
||||
"@brief Isotropic sizing (biasing)\n"
|
||||
"\n"
|
||||
"@return The region after the sizing has applied (self)\n"
|
||||
"\n"
|
||||
"This method is equivalent to \"sized(d, d, 2)\".\n"
|
||||
"This method is equivalent to \"sized(d, d, mode)\".\n"
|
||||
"This method returns the sized region (see \\size), but does not modify self.\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= for a description of this concept)\n"
|
||||
) +
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
|
||||
#include "gsiDecl.h"
|
||||
#include "gsiEnums.h"
|
||||
#include "dbPoint.h"
|
||||
#include "dbText.h"
|
||||
#include "dbHash.h"
|
||||
|
|
@ -36,6 +37,7 @@ template <class C>
|
|||
struct text_defs
|
||||
{
|
||||
typedef typename C::coord_type coord_type;
|
||||
typedef typename C::box_type box_type;
|
||||
typedef typename C::point_type point_type;
|
||||
typedef typename C::vector_type vector_type;
|
||||
typedef db::simple_trans<coord_type> simple_trans_type;
|
||||
|
|
@ -101,22 +103,43 @@ struct text_defs
|
|||
return t->font ();
|
||||
}
|
||||
|
||||
static void set_halign (C *t, int f)
|
||||
static point_type get_pos (C *t)
|
||||
{
|
||||
return t->trans () * point_type ();
|
||||
}
|
||||
|
||||
static box_type get_bbox (C *t)
|
||||
{
|
||||
point_type p = get_pos (t);
|
||||
return box_type (p, p);
|
||||
}
|
||||
|
||||
static void set_halign (C *t, db::HAlign f)
|
||||
{
|
||||
t->halign (f);
|
||||
}
|
||||
|
||||
static void set_halign_int (C *t, int f)
|
||||
{
|
||||
t->halign (db::HAlign (f));
|
||||
}
|
||||
|
||||
static int get_halign (C *t)
|
||||
static db::HAlign get_halign (C *t)
|
||||
{
|
||||
return t->halign ();
|
||||
}
|
||||
|
||||
static void set_valign (C *t, int f)
|
||||
static void set_valign (C *t, db::VAlign f)
|
||||
{
|
||||
t->valign (f);
|
||||
}
|
||||
|
||||
static void set_valign_int (C *t, int f)
|
||||
{
|
||||
t->valign (db::VAlign (f));
|
||||
}
|
||||
|
||||
static int get_valign (C *t)
|
||||
static db::VAlign get_valign (C *t)
|
||||
{
|
||||
return t->valign ();
|
||||
}
|
||||
|
|
@ -186,6 +209,18 @@ struct text_defs
|
|||
method ("string", (const char *(C::*) () const) &C::string,
|
||||
"@brief Get the text string\n"
|
||||
) +
|
||||
method_ext ("position", get_pos,
|
||||
"@brief Gets the position of the text\n"
|
||||
"\n"
|
||||
"This convenience method has been added in version 0.28."
|
||||
) +
|
||||
method_ext ("bbox", get_bbox,
|
||||
"@brief Gets the bounding box of the text\n"
|
||||
"The bounding box of the text is a single point - the location of the text. "
|
||||
"Both points of the box are identical.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.28."
|
||||
) +
|
||||
method_ext ("x=", set_x, gsi::arg ("x"),
|
||||
"@brief Sets the x location of the text\n"
|
||||
"\n"
|
||||
|
|
@ -210,43 +245,54 @@ struct text_defs
|
|||
"@brief Assign a transformation (text position and orientation) to this object\n"
|
||||
) +
|
||||
method ("trans", (const simple_trans_type & (C::*) () const) &C::trans,
|
||||
"@brief Get the transformation\n"
|
||||
"@brief Gets the transformation\n"
|
||||
) +
|
||||
method ("size=", (void (C::*) (coord_type)) &C::size, gsi::arg ("s"),
|
||||
"@brief Set the text height of this object\n"
|
||||
"@brief Sets the text height of this object\n"
|
||||
) +
|
||||
method ("size", (coord_type (C::*) () const) &C::size,
|
||||
"@brief Get the text height\n"
|
||||
"@brief Gets the text height\n"
|
||||
) +
|
||||
method_ext ("font=", &set_font, gsi::arg ("f"),
|
||||
"@brief Set the font number\n"
|
||||
"@brief Sets the font number\n"
|
||||
"The font number does not play a role for KLayout. This property is provided "
|
||||
"for compatibility with other systems which allow using different fonts for the text objects."
|
||||
) +
|
||||
method_ext ("font", &get_font,
|
||||
"@brief Get the font number\n"
|
||||
"@brief Gets the font number\n"
|
||||
"See \\font= for a description of this property."
|
||||
) +
|
||||
method_ext ("#halign=", &set_halign_int, gsi::arg ("a"),
|
||||
"@brief Sets the horizontal alignment\n"
|
||||
"\n"
|
||||
"This is the version accepting integer values. It's provided for backward compatibility.\n"
|
||||
) +
|
||||
method_ext ("halign=", &set_halign, gsi::arg ("a"),
|
||||
"@brief Set the horizontal alignment\n"
|
||||
"@brief Sets the horizontal alignment\n"
|
||||
"\n"
|
||||
"This property specifies how the text is aligned relative to the anchor point. "
|
||||
"Allowed values for this property are 0 (left), 1 (center) and 2 (right)."
|
||||
"\n"
|
||||
"This property has been introduced in version 0.22.\n"
|
||||
"This property has been introduced in version 0.22 and extended to enums in 0.28.\n"
|
||||
) +
|
||||
method_ext ("halign", &get_halign,
|
||||
"@brief Get the horizontal alignment\n"
|
||||
"@brief Gets the horizontal alignment\n"
|
||||
"\n"
|
||||
"See \\halign= for a description of this property.\n"
|
||||
) +
|
||||
method_ext ("#valign=", &set_valign_int, gsi::arg ("a"),
|
||||
"@brief Sets the vertical alignment\n"
|
||||
"\n"
|
||||
"This is the version accepting integer values. It's provided for backward compatibility.\n"
|
||||
) +
|
||||
method_ext ("valign=", &set_valign, gsi::arg ("a"),
|
||||
"@brief Set the vertical alignment\n"
|
||||
"@brief Sets the vertical alignment\n"
|
||||
"\n"
|
||||
"This property specifies how the text is aligned relative to the anchor point. "
|
||||
"Allowed values for this property are 0 (top), 1 (center) and 2 (bottom)."
|
||||
"\n"
|
||||
"This property has been introduced in version 0.22.\n"
|
||||
"This property has been introduced in version 0.22 and extended to enums in 0.28.\n"
|
||||
) +
|
||||
method_ext ("valign", &get_valign,
|
||||
"@brief Get the vertical alignment\n"
|
||||
"@brief Gets the vertical alignment\n"
|
||||
"\n"
|
||||
"See \\valign= for a description of this property.\n"
|
||||
) +
|
||||
|
|
@ -303,14 +349,14 @@ struct text_defs
|
|||
"This method was introduced in version 0.23."
|
||||
) +
|
||||
method ("transformed", &C::template transformed<simple_trans_type>, gsi::arg ("t"),
|
||||
"@brief Transform the text with the given simple transformation\n"
|
||||
"@brief Transforms the text with the given simple transformation\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"@param t The transformation to apply\n"
|
||||
"@return The transformed text\n"
|
||||
) +
|
||||
method ("transformed", &C::template transformed<complex_trans_type>, gsi::arg ("t"),
|
||||
"@brief Transform the text with the given complex transformation\n"
|
||||
"@brief Transforms the text with the given complex transformation\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"@param t The magnifying transformation to apply\n"
|
||||
|
|
@ -346,7 +392,7 @@ struct text_defs
|
|||
"This method has been added in version 0.23.\n"
|
||||
) +
|
||||
method ("to_s", &C::to_string, gsi::arg ("dbu", 0.0),
|
||||
"@brief Convert to a string.\n"
|
||||
"@brief Converts the object to a string.\n"
|
||||
"If a DBU is given, the output units will be micrometers.\n"
|
||||
"\n"
|
||||
"The DBU argument has been added in version 0.27.6.\n"
|
||||
|
|
@ -451,4 +497,44 @@ Class<db::DText> decl_DText ("db", "DText",
|
|||
"database objects."
|
||||
);
|
||||
|
||||
gsi::Enum<db::HAlign> decl_HAlign ("db", "HAlign",
|
||||
gsi::enum_const ("HAlignLeft", db::HAlignLeft,
|
||||
"@brief Left horizontal alignment\n"
|
||||
) +
|
||||
gsi::enum_const ("HAlignCenter", db::HAlignCenter,
|
||||
"@brief Centered horizontal alignment\n"
|
||||
) +
|
||||
gsi::enum_const ("HAlignRight", db::HAlignRight,
|
||||
"@brief Right horizontal alignment\n"
|
||||
) +
|
||||
gsi::enum_const ("NoHAlign", db::NoHAlign,
|
||||
"@brief Undefined horizontal alignment\n"
|
||||
),
|
||||
"@brief This class represents the horizontal alignment modes.\n"
|
||||
"This enum has been introduced in version 0.28."
|
||||
);
|
||||
|
||||
gsi::Enum<db::VAlign> decl_VAlign ("db", "VAlign",
|
||||
gsi::enum_const ("VAlignBottom", db::VAlignBottom,
|
||||
"@brief Bottom vertical alignment\n"
|
||||
) +
|
||||
gsi::enum_const ("VAlignCenter", db::VAlignCenter,
|
||||
"@brief Centered vertical alignment\n"
|
||||
) +
|
||||
gsi::enum_const ("VAlignTop", db::VAlignTop,
|
||||
"@brief Top vertical alignment\n"
|
||||
) +
|
||||
gsi::enum_const ("NoVAlign", db::NoVAlign,
|
||||
"@brief Undefined vertical alignment\n"
|
||||
),
|
||||
"@brief This class represents the vertical alignment modes.\n"
|
||||
"This enum has been introduced in version 0.28."
|
||||
);
|
||||
|
||||
// Inject the alignment enums
|
||||
gsi::ClassExt<db::Text> inject_Text_HAlign_in_parent (decl_HAlign.defs ());
|
||||
gsi::ClassExt<db::DText> inject_DText_HAlign_in_parent (decl_HAlign.defs ());
|
||||
gsi::ClassExt<db::Text> inject_Text_VAlign_in_parent (decl_VAlign.defs ());
|
||||
gsi::ClassExt<db::DText> inject_DText_VAlign_in_parent (decl_VAlign.defs ());
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -742,7 +742,7 @@ struct cplx_trans_defs
|
|||
"\n"
|
||||
"@return The inverted transformation\n"
|
||||
) +
|
||||
method ("ctrans", &C::ctrans, arg ("d"),
|
||||
method ("ctrans|*", &C::ctrans, arg ("d"),
|
||||
"@brief Transforms a distance\n"
|
||||
"\n"
|
||||
"The \"ctrans\" method transforms the given distance.\n"
|
||||
|
|
|
|||
|
|
@ -232,6 +232,8 @@ TEST(1)
|
|||
EXPECT_EQ (s, "1,8");
|
||||
s = q2s_var (iq, "bbox");
|
||||
EXPECT_EQ (s, "(0,1;2,3),()");
|
||||
s = q2s_var (iq, "dbbox");
|
||||
EXPECT_EQ (s, "(0,0.001;0.002,0.003),()");
|
||||
}
|
||||
|
||||
{
|
||||
|
|
@ -568,16 +570,26 @@ TEST(2)
|
|||
EXPECT_EQ (s, "c1,c1");
|
||||
s = q2s_var (iq, "trans");
|
||||
EXPECT_EQ (s, "r0 *1 10,-20,m45 *1 -10,20");
|
||||
s = q2s_var (iq, "dtrans");
|
||||
EXPECT_EQ (s, "r0 *1 0.01,-0.02,m45 *1 -0.01,0.02");
|
||||
s = q2s_var (iq, "path_trans");
|
||||
EXPECT_EQ (s, "r0 *1 10,-20,m45 *1 -10,20");
|
||||
s = q2s_var (iq, "path_dtrans");
|
||||
EXPECT_EQ (s, "r0 *1 0.01,-0.02,m45 *1 -0.01,0.02");
|
||||
s = q2s_var (iq, "inst_bbox");
|
||||
EXPECT_EQ (s, "(10,-10;20,10),(0,20;20,30)");
|
||||
s = q2s_var (iq, "inst_dbbox");
|
||||
EXPECT_EQ (s, "(0.01,-0.01;0.02,0.01),(0,0.02;0.02,0.03)");
|
||||
s = q2s_var (iq, "inst");
|
||||
EXPECT_EQ (s, "cell_index=0 r0 10,-20,cell_index=0 m45 -10,20");
|
||||
s = q2s_var (iq, "array_a");
|
||||
EXPECT_EQ (s, "nil,nil");
|
||||
s = q2s_var (iq, "array_da");
|
||||
EXPECT_EQ (s, "nil,nil");
|
||||
s = q2s_var (iq, "array_b");
|
||||
EXPECT_EQ (s, "nil,nil");
|
||||
s = q2s_var (iq, "array_db");
|
||||
EXPECT_EQ (s, "nil,nil");
|
||||
s = q2s_var (iq, "array_na");
|
||||
EXPECT_EQ (s, "nil,nil");
|
||||
s = q2s_var (iq, "array_nb");
|
||||
|
|
@ -603,8 +615,12 @@ TEST(2)
|
|||
EXPECT_EQ (s, "cell_index=0 r0 10,-20,cell_index=0 m45 -10,20 array=(1,1,0,2 2x3),cell_index=0 m45 -10,20 array=(1,1,0,2 2x3),cell_index=0 m45 -10,20 array=(1,1,0,2 2x3),cell_index=0 m45 -10,20 array=(1,1,0,2 2x3),cell_index=0 m45 -10,20 array=(1,1,0,2 2x3),cell_index=0 m45 -10,20 array=(1,1,0,2 2x3)");
|
||||
s = q2s_var (iq, "array_a");
|
||||
EXPECT_EQ (s, "nil,1,1,1,1,1,1,1,1,1,1,1,1");
|
||||
s = q2s_var (iq, "array_da");
|
||||
EXPECT_EQ (s, "nil,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001");
|
||||
s = q2s_var (iq, "array_b");
|
||||
EXPECT_EQ (s, "nil,0,2,0,2,0,2,0,2,0,2,0,2");
|
||||
s = q2s_var (iq, "array_db");
|
||||
EXPECT_EQ (s, "nil,0,0.002,0,0.002,0,0.002,0,0.002,0,0.002,0,0.002");
|
||||
s = q2s_var (iq, "array_na");
|
||||
EXPECT_EQ (s, "nil,2,2,2,2,2,2");
|
||||
s = q2s_var (iq, "array_nb");
|
||||
|
|
@ -788,6 +804,12 @@ TEST(3)
|
|||
EXPECT_EQ (s, "0,1,1,2");
|
||||
s = q2s_var (iq, "bbox");
|
||||
EXPECT_EQ (s, "(0,1;2,3),(0,1;2,3),(0,1;2,3),(10,11;10,11)");
|
||||
s = q2s_var (iq, "dbbox");
|
||||
EXPECT_EQ (s, "(0,0.001;0.002,0.003),(0,0.001;0.002,0.003),(0,0.001;0.002,0.003),(0.01,0.011;0.01,0.011)");
|
||||
s = q2s_var (iq, "shape_bbox");
|
||||
EXPECT_EQ (s, "(0,1;2,3),(0,1;2,3),(0,1;2,3),(10,11;10,11)");
|
||||
s = q2s_var (iq, "shape_dbbox");
|
||||
EXPECT_EQ (s, "(0,0.001;0.002,0.003),(0,0.001;0.002,0.003),(0,0.001;0.002,0.003),(0.01,0.011;0.01,0.011)");
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -619,3 +619,44 @@ TEST(4)
|
|||
EXPECT_EQ (db::compare_layouts (boxes2layout (selected_boxes), boxes2layout (selected_boxes2), db::layout_diff::f_verbose, 0, 100 /*max diff lines*/), true);
|
||||
}
|
||||
|
||||
TEST(5)
|
||||
{
|
||||
std::unique_ptr<db::Layout> g (new db::Layout ());
|
||||
g->insert_layer (0);
|
||||
g->insert_layer (1);
|
||||
g->insert_layer (2);
|
||||
|
||||
db::Cell &c0 (g->cell (g->add_cell ()));
|
||||
db::Cell &c1 (g->cell (g->add_cell ()));
|
||||
db::Cell &c2 (g->cell (g->add_cell ()));
|
||||
db::Cell &c3 (g->cell (g->add_cell ()));
|
||||
|
||||
db::Box b (0, 100, 1000, 1200);
|
||||
c0.shapes (0).insert (b);
|
||||
c1.shapes (0).insert (b);
|
||||
c2.shapes (0).insert (b);
|
||||
c3.shapes (0).insert (b);
|
||||
|
||||
c0.shapes (2).insert (b);
|
||||
c0.shapes (2).insert (b.moved (db::Vector (50, 50)));
|
||||
|
||||
db::Trans tt;
|
||||
c0.insert (db::CellInstArray (db::CellInst (c1.cell_index ()), tt));
|
||||
c0.insert (db::CellInstArray (db::CellInst (c2.cell_index ()), db::Trans (db::Vector (100, -100))));
|
||||
c0.insert (db::CellInstArray (db::CellInst (c3.cell_index ()), db::Trans (1)));
|
||||
c2.insert (db::CellInstArray (db::CellInst (c3.cell_index ()), db::Trans (db::Vector (1100, 0))));
|
||||
|
||||
std::string x;
|
||||
|
||||
db::RecursiveInstanceIterator i1 (*g, c0, db::Box (0, 0, 100, 100));
|
||||
x = collect(i1, *g);
|
||||
EXPECT_EQ (x, "[$1]$2 r0 0,0/[$1]$3 r0 100,-100");
|
||||
|
||||
g.reset (new db::Layout ());
|
||||
|
||||
// now the layout is gone and the iterator stays silent (weak pointer to layout)
|
||||
// NOTE: this only works on reset or re-initialization. Not during iteration.
|
||||
i1.reset ();
|
||||
x = collect(i1, *g);
|
||||
EXPECT_EQ (x, "");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1515,3 +1515,42 @@ TEST(10)
|
|||
"end\n"
|
||||
);
|
||||
}
|
||||
|
||||
TEST(11_LayoutIsWeakPointer)
|
||||
{
|
||||
std::unique_ptr<db::Layout> g (new db::Layout ());
|
||||
g->insert_layer (0);
|
||||
g->insert_layer (1);
|
||||
db::Cell &c0 (g->cell (g->add_cell ()));
|
||||
db::Cell &c1 (g->cell (g->add_cell ()));
|
||||
db::Cell &c2 (g->cell (g->add_cell ()));
|
||||
db::Cell &c3 (g->cell (g->add_cell ()));
|
||||
|
||||
db::Box b (0, 100, 1000, 1200);
|
||||
c1.shapes (0).insert (b);
|
||||
c2.shapes (0).insert (b);
|
||||
c3.shapes (0).insert (b);
|
||||
|
||||
db::Box bb (1, 101, 1001, 1201);
|
||||
c2.shapes (1).insert (bb);
|
||||
|
||||
db::Trans tt;
|
||||
c0.insert (db::CellInstArray (db::CellInst (c1.cell_index ()), tt));
|
||||
c0.insert (db::CellInstArray (db::CellInst (c2.cell_index ()), db::Trans (db::Vector (100, -100))));
|
||||
c0.insert (db::CellInstArray (db::CellInst (c3.cell_index ()), db::Trans (1)));
|
||||
c2.insert (db::CellInstArray (db::CellInst (c3.cell_index ()), db::Trans (db::Vector (1100, 0))));
|
||||
|
||||
std::string x;
|
||||
|
||||
db::RecursiveShapeIterator i1 (*g, c0, 0, db::Box (0, 0, 100, 100));
|
||||
x = collect(i1, *g);
|
||||
EXPECT_EQ (x, "[$2](0,100;1000,1200)/[$3](100,0;1100,1100)");
|
||||
|
||||
g.reset (new db::Layout ());
|
||||
|
||||
// now the layout is gone and the iterator stays silent (weak pointer to layout)
|
||||
// NOTE: this only works on reset or re-initialization. Not during iteration.
|
||||
i1.reset ();
|
||||
x = collect(i1, *g);
|
||||
EXPECT_EQ (x, "");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -388,7 +388,7 @@ shapes on layer METAL, POLY from cell TOP
|
|||
Any kind of cell query can be used inside the shape query. If a cell query renders multiple
|
||||
cells, the shape query will be applied to each of the cells returned. If instances are selected
|
||||
by the cell query, the shapes will be reported for each instance. Since the cumulated transformation
|
||||
of a specific instance into the top cell is available through the "path_trans" variable,
|
||||
of a specific instance into the top cell is available through the "path_trans" (database units) or "path_dtrans" (micrometer units) variable,
|
||||
it is possible to transform each shape into the top cell in the instance case. The following expression
|
||||
combines a "with .. do" action with a shape query to flatten all shapes below "TOP":
|
||||
</p>
|
||||
|
|
@ -603,10 +603,20 @@ delete shapes on layer 6 of cell TOP
|
|||
<td><class_ref href="Box"/></td>
|
||||
<td>The cell's bounding box.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dbbox</td>
|
||||
<td><class_ref href="DBox"/></td>
|
||||
<td>The cell's bounding box in micrometer units.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>cell_bbox</td>
|
||||
<td><class_ref href="Box"/></td>
|
||||
<td>Same as "bbox" (disambiguator for shape and instance bounding boxes).</td>
|
||||
<td>Same as "bbox" (disambiguator from shape and instance bounding boxes).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>cell_dbbox</td>
|
||||
<td><class_ref href="DBox"/></td>
|
||||
<td>Same as "dbbox" (disambiguator from shape and instance bounding boxes).</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
|
@ -631,16 +641,32 @@ delete shapes on layer 6 of cell TOP
|
|||
<td>The transformation of that instance into the top cell.
|
||||
For a plain cell that is a unit transformation.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>path_dtrans</td>
|
||||
<td><class_doc href="DCplxTrans"/></td>
|
||||
<td>The transformation of that instance into the top cell in micrometer units.
|
||||
For a plain cell that is a unit transformation.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>trans</td>
|
||||
<td><class_doc href="ICplxTrans"/></td>
|
||||
<td>The transformation of that instance (first instance if an array).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dtrans</td>
|
||||
<td><class_doc href="DCplxTrans"/></td>
|
||||
<td>The transformation of that instance (first instance if an array) in micrometer units.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>inst_bbox</td>
|
||||
<td><class_doc href="Box"/></td>
|
||||
<td>The instance bounding box in the initial cell.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>inst_dbbox</td>
|
||||
<td><class_doc href="DBox"/></td>
|
||||
<td>The instance bounding box in the initial cell in micrometer units.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>inst</td>
|
||||
<td><class_doc href="Instance"/></td>
|
||||
|
|
@ -648,9 +674,14 @@ delete shapes on layer 6 of cell TOP
|
|||
</tr>
|
||||
<tr>
|
||||
<td>array_a</td>
|
||||
<td><class_doc href="Point"/></td>
|
||||
<td><class_doc href="Vector"/></td>
|
||||
<td>The a vector for an array instance or nil if the instance is not an array.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>array_da</td>
|
||||
<td><class_doc href="DVector"/></td>
|
||||
<td>The a vector for an array instance in micrometer units or nil if the instance is not an array.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>array_na</td>
|
||||
<td>Integer</td>
|
||||
|
|
@ -658,9 +689,14 @@ delete shapes on layer 6 of cell TOP
|
|||
</tr>
|
||||
<tr>
|
||||
<td>array_b</td>
|
||||
<td><class_doc href="Point"/></td>
|
||||
<td><class_doc href="Vector"/></td>
|
||||
<td>The b vector for an array instance or nil if the instance is not an array.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>array_db</td>
|
||||
<td><class_doc href="DVector"/></td>
|
||||
<td>The b vector for an array instance in micrometer units or nil if the instance is not an array.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>array_nb</td>
|
||||
<td>Integer</td>
|
||||
|
|
@ -689,14 +725,24 @@ delete shapes on layer 6 of cell TOP
|
|||
<tr><th>Name</th><th>Value type</th><th>Description</th></tr>
|
||||
<tr>
|
||||
<td>bbox</td>
|
||||
<td><class_doc href="Box"/></td>
|
||||
<td><class_doc href="DBox"/></td>
|
||||
<td>The shape's bounding box</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dbbox</td>
|
||||
<td><class_doc href="DBox"/></td>
|
||||
<td>The shape's bounding box in micrometer units</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>shape_bbox</td>
|
||||
<td><class_doc href="Box"/></td>
|
||||
<td>Same as "bbox" (disambiguator for cell or instance bounding boxes)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>shape_dbbox</td>
|
||||
<td><class_doc href="DBox"/></td>
|
||||
<td>Same as "dbbox" (disambiguator for cell or instance bounding boxes)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>shape</td>
|
||||
<td><class_doc href="Shape"/></td>
|
||||
|
|
|
|||
|
|
@ -1699,6 +1699,55 @@ SearchReplaceDialog::result_selection_changed ()
|
|||
|
||||
}
|
||||
|
||||
} else if (index < int (m_model.data ().size ())) {
|
||||
|
||||
db::DCplxTrans as_dbu = db::DCplxTrans (layout.dbu ()).inverted ();
|
||||
|
||||
const tl::Variant &dr = m_model.data () [index];
|
||||
for (tl::Variant::const_iterator v = dr.begin (); v != dr.end (); ++v) {
|
||||
|
||||
lay::Marker *marker = new lay::Marker (view (), cv_index);
|
||||
|
||||
if (v->is_user<db::DBox> ()) {
|
||||
marker->set (v->to_user<db::DBox> (), as_dbu, global_trans);
|
||||
} else if (v->is_user<db::Box> ()) {
|
||||
marker->set (v->to_user<db::Box> (), db::ICplxTrans (), global_trans);
|
||||
} else if (v->is_user<db::DEdge> ()) {
|
||||
marker->set (v->to_user<db::DEdge> (), as_dbu, global_trans);
|
||||
} else if (v->is_user<db::Edge> ()) {
|
||||
marker->set (v->to_user<db::Edge> (), db::ICplxTrans (), global_trans);
|
||||
} else if (v->is_user<db::DPolygon> ()) {
|
||||
marker->set (v->to_user<db::DPolygon> (), as_dbu, global_trans);
|
||||
} else if (v->is_user<db::Polygon> ()) {
|
||||
marker->set (v->to_user<db::Polygon> (), db::ICplxTrans (), global_trans);
|
||||
} else if (v->is_user<db::DPath> ()) {
|
||||
marker->set (v->to_user<db::DPath> (), as_dbu, global_trans);
|
||||
} else if (v->is_user<db::Path> ()) {
|
||||
marker->set (v->to_user<db::Path> (), db::ICplxTrans (), global_trans);
|
||||
} else if (v->is_user<db::DPoint> ()) {
|
||||
db::DPoint p = v->to_user<db::DPoint> ();
|
||||
marker->set (db::DBox (p, p), as_dbu, global_trans);
|
||||
} else if (v->is_user<db::Point> ()) {
|
||||
db::Point p = v->to_user<db::Point> ();
|
||||
marker->set (db::Box (p, p), db::ICplxTrans (), global_trans);
|
||||
} else if (v->is_user<db::DVector> ()) {
|
||||
db::DPoint p = db::DPoint () + v->to_user<db::DVector> ();
|
||||
marker->set (db::DBox (p, p), as_dbu, global_trans);
|
||||
} else if (v->is_user<db::Vector> ()) {
|
||||
db::Point p = db::Point () + v->to_user<db::Vector> ();
|
||||
marker->set (db::Box (p, p), db::ICplxTrans (), global_trans);
|
||||
} else {
|
||||
delete marker;
|
||||
marker = 0;
|
||||
}
|
||||
|
||||
if (marker) {
|
||||
mp_markers.push_back (marker);
|
||||
dbox += marker->bbox ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,6 +106,13 @@ class DBBox_TestClass < TestBase
|
|||
a = RBA::DBox.new
|
||||
assert_equal( a.empty?, true )
|
||||
|
||||
a = RBA::DBox::world
|
||||
b = RBA::DBox::new(1, 2, 3, 4)
|
||||
assert_equal( a.empty?, false )
|
||||
assert_equal( a == RBA::DBox::world, true )
|
||||
assert_equal( (a + b) == RBA::DBox::world, true )
|
||||
assert_equal( (a & b) == b, true )
|
||||
|
||||
end
|
||||
|
||||
# DBox basics
|
||||
|
|
@ -303,6 +310,13 @@ class DBBox_TestClass < TestBase
|
|||
a = RBA::Box.new
|
||||
assert_equal( a.empty?, true )
|
||||
|
||||
a = RBA::Box::world
|
||||
b = RBA::Box::new(1, 2, 3, 4)
|
||||
assert_equal( a.empty?, false )
|
||||
assert_equal( a == RBA::Box::world, true )
|
||||
assert_equal( (a + b) == RBA::Box::world, true )
|
||||
assert_equal( (a & b) == b, true )
|
||||
|
||||
end
|
||||
|
||||
# Box basics
|
||||
|
|
|
|||
|
|
@ -49,6 +49,11 @@ class DBCellInst_TestClass < TestBase
|
|||
assert_equal(a.trans.to_s, "r90 0,0")
|
||||
assert_equal(a.cplx_trans.to_s, "r90 *1 0,0")
|
||||
|
||||
a = RBA::CellInstArray::new(0, RBA::Vector::new(42, -17))
|
||||
assert_equal(a.is_complex?, false)
|
||||
assert_equal(a.trans.to_s, "r0 42,-17")
|
||||
assert_equal(a.cplx_trans.to_s, "r0 *1 42,-17")
|
||||
|
||||
a = RBA::CellInstArray::new(0, RBA::ICplxTrans::new(1.5))
|
||||
assert_equal(a.is_complex?, true)
|
||||
assert_equal(a.trans.to_s, "r0 0,0")
|
||||
|
|
@ -106,6 +111,12 @@ class DBCellInst_TestClass < TestBase
|
|||
assert_equal(a.cplx_trans.to_s, "r90 *1 0,0")
|
||||
assert_equal(a.to_s, "#0 r90 0,0 [10,20*3;30,40*5]")
|
||||
|
||||
a = RBA::CellInstArray::new(0, RBA::Vector::new(42, -17), RBA::Vector::new(10, 20), RBA::Vector::new(30, 40), 3, 5)
|
||||
assert_equal(a.is_complex?, false)
|
||||
assert_equal(a.trans.to_s, "r0 42,-17")
|
||||
assert_equal(a.cplx_trans.to_s, "r0 *1 42,-17")
|
||||
assert_equal(a.to_s, "#0 r0 42,-17 [10,20*3;30,40*5]")
|
||||
|
||||
a = RBA::CellInstArray::new(0, RBA::ICplxTrans::new(1.5), RBA::Vector::new(10, 20), RBA::Vector::new(30, 40), 3, 5)
|
||||
assert_equal(a.is_complex?, true)
|
||||
assert_equal(a.trans.to_s, "r0 0,0")
|
||||
|
|
@ -178,6 +189,11 @@ class DBCellInst_TestClass < TestBase
|
|||
assert_equal(a.trans.to_s, "r90 0,0")
|
||||
assert_equal(a.cplx_trans.to_s, "r90 *1 0,0")
|
||||
|
||||
a = RBA::DCellInstArray::new(0, RBA::DVector::new(42, -17))
|
||||
assert_equal(a.is_complex?, false)
|
||||
assert_equal(a.trans.to_s, "r0 42,-17")
|
||||
assert_equal(a.cplx_trans.to_s, "r0 *1 42,-17")
|
||||
|
||||
a = RBA::DCellInstArray::new(0, RBA::DCplxTrans::new(1.5))
|
||||
assert_equal(a.is_complex?, true)
|
||||
assert_equal(a.trans.to_s, "r0 0,0")
|
||||
|
|
@ -235,6 +251,12 @@ class DBCellInst_TestClass < TestBase
|
|||
assert_equal(a.cplx_trans.to_s, "r90 *1 0,0")
|
||||
assert_equal(a.to_s, "#0 r90 0,0 [10,20*3;30,40*5]")
|
||||
|
||||
a = RBA::DCellInstArray::new(0, RBA::DVector::new(42, -17), RBA::DVector::new(10, 20), RBA::DVector::new(30, 40), 3, 5)
|
||||
assert_equal(a.is_complex?, false)
|
||||
assert_equal(a.trans.to_s, "r0 42,-17")
|
||||
assert_equal(a.cplx_trans.to_s, "r0 *1 42,-17")
|
||||
assert_equal(a.to_s, "#0 r0 42,-17 [10,20*3;30,40*5]")
|
||||
|
||||
a = RBA::DCellInstArray::new(0, RBA::DCplxTrans::new(1.5), RBA::DVector::new(10, 20), RBA::DVector::new(30, 40), 3, 5)
|
||||
assert_equal(a.is_complex?, true)
|
||||
assert_equal(a.trans.to_s, "r0 0,0")
|
||||
|
|
|
|||
|
|
@ -1043,10 +1043,31 @@ class DBLayout_TestClass < TestBase
|
|||
ci = l.clip(c0.cell_index, RBA::Box.new(0, 0, 200, 200))
|
||||
assert_equal(dump_layer_i(l, 0, ci), "(0,100;200,200); (0,100;200,200); (100,0;200,200)")
|
||||
|
||||
cic = l.clip(c0, RBA::Box.new(0, 0, 200, 200))
|
||||
assert_equal(dump_layer_i(l, 0, cic.cell_index), "(0,100;200,200); (0,100;200,200); (100,0;200,200)")
|
||||
|
||||
cid = l.clip(c0.cell_index, RBA::DBox.new(0, 0, 0.2, 0.2))
|
||||
assert_equal(dump_layer_i(l, 0, cid), "(0,100;200,200); (0,100;200,200); (100,0;200,200)")
|
||||
|
||||
cicd = l.clip(c0, RBA::DBox.new(0, 0, 0.2, 0.2))
|
||||
assert_equal(dump_layer_i(l, 0, cicd.cell_index), "(0,100;200,200); (0,100;200,200); (100,0;200,200)")
|
||||
|
||||
ci = l.multi_clip(c0.cell_index, [RBA::Box.new(0, 0, 200, 200),RBA::Box.new(1000, 0, 1300, 200)])
|
||||
assert_equal(dump_layer_i(l, 0, ci[0]), "(0,100;200,200); (0,100;200,200); (100,0;200,200)")
|
||||
assert_equal(dump_layer_i(l, 0, ci[1]), "(1000,0;1100,200); (1200,0;1300,200)")
|
||||
|
||||
cic = l.multi_clip(c0, [RBA::Box.new(0, 0, 200, 200),RBA::Box.new(1000, 0, 1300, 200)])
|
||||
assert_equal(dump_layer_i(l, 0, cic[0].cell_index), "(0,100;200,200); (0,100;200,200); (100,0;200,200)")
|
||||
assert_equal(dump_layer_i(l, 0, cic[1].cell_index), "(1000,0;1100,200); (1200,0;1300,200)")
|
||||
|
||||
cid = l.multi_clip(c0.cell_index, [RBA::DBox.new(0, 0, 0.2, 0.2),RBA::DBox.new(1.0, 0, 1.3, 0.2)])
|
||||
assert_equal(dump_layer_i(l, 0, cid[0]), "(0,100;200,200); (0,100;200,200); (100,0;200,200)")
|
||||
assert_equal(dump_layer_i(l, 0, cid[1]), "(1000,0;1100,200); (1200,0;1300,200)")
|
||||
|
||||
cidc = l.multi_clip(c0, [RBA::DBox.new(0, 0, 0.2, 0.2),RBA::DBox.new(1.0, 0, 1.3, 0.2)])
|
||||
assert_equal(dump_layer_i(l, 0, cidc[0].cell_index), "(0,100;200,200); (0,100;200,200); (100,0;200,200)")
|
||||
assert_equal(dump_layer_i(l, 0, cidc[1].cell_index), "(1000,0;1100,200); (1200,0;1300,200)")
|
||||
|
||||
ll = RBA::Layout.new
|
||||
ll.dbu = l.dbu
|
||||
ll.insert_layer_at(0, RBA::LayerInfo.new(2, 0))
|
||||
|
|
@ -1054,10 +1075,31 @@ class DBLayout_TestClass < TestBase
|
|||
ci = l.clip_into(c0.cell_index, ll, RBA::Box.new(0, 0, 200, 200))
|
||||
assert_equal(dump_layer_i(ll, 0, ci), "(0,100;200,200); (0,100;200,200); (100,0;200,200)")
|
||||
|
||||
cic = l.clip_into(c0, ll, RBA::Box.new(0, 0, 200, 200))
|
||||
assert_equal(dump_layer_i(ll, 0, cic.cell_index), "(0,100;200,200); (0,100;200,200); (100,0;200,200)")
|
||||
|
||||
cid = l.clip_into(c0.cell_index, ll, RBA::DBox.new(0, 0, 0.2, 0.2))
|
||||
assert_equal(dump_layer_i(ll, 0, cid), "(0,100;200,200); (0,100;200,200); (100,0;200,200)")
|
||||
|
||||
cicd = l.clip_into(c0, ll, RBA::DBox.new(0, 0, 0.2, 0.2))
|
||||
assert_equal(dump_layer_i(ll, 0, cicd.cell_index), "(0,100;200,200); (0,100;200,200); (100,0;200,200)")
|
||||
|
||||
ci = l.multi_clip_into(c0.cell_index, ll, [RBA::Box.new(0, 0, 200, 200),RBA::Box.new(1000, 0, 1300, 200)])
|
||||
assert_equal(dump_layer_i(ll, 0, ci[0]), "(0,100;200,200); (0,100;200,200); (100,0;200,200)")
|
||||
assert_equal(dump_layer_i(ll, 0, ci[1]), "(1000,0;1100,200); (1200,0;1300,200)")
|
||||
|
||||
cic = l.multi_clip_into(c0, ll, [RBA::Box.new(0, 0, 200, 200),RBA::Box.new(1000, 0, 1300, 200)])
|
||||
assert_equal(dump_layer_i(ll, 0, cic[0]), "(0,100;200,200); (0,100;200,200); (100,0;200,200)")
|
||||
assert_equal(dump_layer_i(ll, 0, cic[1]), "(1000,0;1100,200); (1200,0;1300,200)")
|
||||
|
||||
cid = l.multi_clip_into(c0.cell_index, ll, [RBA::DBox.new(0, 0, 0.2, 0.2),RBA::DBox.new(1.0, 0, 1.3, 0.2)])
|
||||
assert_equal(dump_layer_i(ll, 0, cid[0]), "(0,100;200,200); (0,100;200,200); (100,0;200,200)")
|
||||
assert_equal(dump_layer_i(ll, 0, cid[1]), "(1000,0;1100,200); (1200,0;1300,200)")
|
||||
|
||||
cicd = l.multi_clip_into(c0, ll, [RBA::DBox.new(0, 0, 0.2, 0.2),RBA::DBox.new(1.0, 0, 1.3, 0.2)])
|
||||
assert_equal(dump_layer_i(ll, 0, cicd[0]), "(0,100;200,200); (0,100;200,200); (100,0;200,200)")
|
||||
assert_equal(dump_layer_i(ll, 0, cicd[1]), "(1000,0;1100,200); (1200,0;1300,200)")
|
||||
|
||||
end
|
||||
|
||||
def test_8
|
||||
|
|
|
|||
|
|
@ -23,10 +23,10 @@ end
|
|||
|
||||
load("test_prologue.rb")
|
||||
|
||||
class DBLayout_TestClass < TestBase
|
||||
class DBLayoutTest_TestClass < TestBase
|
||||
|
||||
# LayerInfo
|
||||
def _test_1_Layout
|
||||
def test_1_Layout
|
||||
|
||||
lp = RBA::LayerInfo::new
|
||||
|
||||
|
|
@ -62,7 +62,7 @@ class DBLayout_TestClass < TestBase
|
|||
end
|
||||
|
||||
# Basics: cells and instances
|
||||
def _test_2_Layout
|
||||
def test_2_Layout
|
||||
|
||||
ly = RBA::Layout::new
|
||||
|
||||
|
|
@ -182,7 +182,7 @@ class DBLayout_TestClass < TestBase
|
|||
end
|
||||
|
||||
# Instances and bboxes
|
||||
def _test_5_Layout
|
||||
def test_5_Layout
|
||||
|
||||
ly = RBA::Layout::new
|
||||
|
||||
|
|
@ -223,10 +223,13 @@ class DBLayout_TestClass < TestBase
|
|||
assert_equal( c1.bbox_per_layer( lindex ).to_s, "()" )
|
||||
assert_equal( c1.bbox_per_layer( ldummy ).to_s, "()" )
|
||||
|
||||
assert_equal( ly.unique_cell_name("c3"), "c3" )
|
||||
assert_equal( ly.unique_cell_name("c1"), "c1$1" )
|
||||
|
||||
end
|
||||
|
||||
# Instances and bboxes
|
||||
def _test_6_Layout
|
||||
def test_6_Layout
|
||||
|
||||
ly = RBA::Layout::new
|
||||
|
||||
|
|
@ -398,7 +401,7 @@ class DBLayout_TestClass < TestBase
|
|||
end
|
||||
|
||||
# Instances and editable mode
|
||||
def _test_6_EditableLayout
|
||||
def test_6_EditableLayout
|
||||
|
||||
ly = RBA::Layout::new( true )
|
||||
assert_equal( ly.is_editable?, true )
|
||||
|
|
@ -470,7 +473,7 @@ class DBLayout_TestClass < TestBase
|
|||
end
|
||||
|
||||
# Instances and bboxes
|
||||
def _test_6_Layout_props
|
||||
def test_6_Layout_props
|
||||
|
||||
ly = RBA::Layout::new
|
||||
pid = ly.properties_id( { 17 => "a", "b" => [ 1, 5, 7 ] }.to_a )
|
||||
|
|
@ -648,7 +651,7 @@ class DBLayout_TestClass < TestBase
|
|||
end
|
||||
|
||||
# Properties
|
||||
def _test_6_Layout_props2
|
||||
def test_6_Layout_props2
|
||||
|
||||
ly = RBA::Layout::new(true)
|
||||
pid = ly.properties_id( { 17 => "a", "b" => [ 1, 5, 7 ] }.to_a )
|
||||
|
|
@ -697,7 +700,7 @@ class DBLayout_TestClass < TestBase
|
|||
end
|
||||
|
||||
# Instances and bboxes (editable mode)
|
||||
def _test_6_Layout_new
|
||||
def test_6_Layout_new
|
||||
|
||||
if( RBA::Application::instance.is_editable? )
|
||||
|
||||
|
|
@ -805,7 +808,7 @@ class DBLayout_TestClass < TestBase
|
|||
end
|
||||
|
||||
# Copy/move between cells
|
||||
def _test_7_cells_copy_move
|
||||
def test_7_cells_copy_move
|
||||
|
||||
# because of set_property ...
|
||||
if !RBA::Application::instance.is_editable?
|
||||
|
|
@ -879,7 +882,7 @@ class DBLayout_TestClass < TestBase
|
|||
end
|
||||
|
||||
# top cells
|
||||
def _test_8
|
||||
def test_8
|
||||
|
||||
l = RBA::Layout.new
|
||||
tc = []
|
||||
|
|
@ -916,7 +919,7 @@ class DBLayout_TestClass < TestBase
|
|||
end
|
||||
|
||||
# under construction and update
|
||||
def _test_9
|
||||
def test_9
|
||||
|
||||
ly = RBA::Layout::new
|
||||
l1 = ly.insert_layer(RBA::LayerInfo::new(1, 0))
|
||||
|
|
@ -946,7 +949,7 @@ class DBLayout_TestClass < TestBase
|
|||
end
|
||||
|
||||
# Instance editing
|
||||
def _test_10
|
||||
def test_10
|
||||
|
||||
ly = RBA::Layout::new
|
||||
|
||||
|
|
@ -1025,7 +1028,7 @@ class DBLayout_TestClass < TestBase
|
|||
end
|
||||
|
||||
# User properties
|
||||
def _test_11
|
||||
def test_11
|
||||
|
||||
ly = RBA::Layout::new
|
||||
|
||||
|
|
@ -1049,7 +1052,7 @@ class DBLayout_TestClass < TestBase
|
|||
end
|
||||
|
||||
# Meta information
|
||||
def _test_12
|
||||
def test_12
|
||||
|
||||
mi = RBA::LayoutMetaInfo::new("myinfo", "a")
|
||||
|
||||
|
|
|
|||
|
|
@ -277,8 +277,19 @@ class DBPolygon_TestClass < TestBase
|
|||
a = RBA::Polygon::new( [ RBA::Point::new( 0, 1 ), RBA::Point::new( 1, 5 ), RBA::Point::new( 5, 5 ) ] )
|
||||
assert_equal( a.to_s, "(0,1;1,5;5,5)" )
|
||||
assert_equal( a.sized(2, 0, 2).to_s, "(-2,1;-1,5;7,5;2,1)" )
|
||||
assert_equal( a.sized(RBA::Vector::new(2, 0), 2).to_s, "(-2,1;-1,5;7,5;2,1)" )
|
||||
assert_equal( a.sized(RBA::Vector::new(2, 0)).to_s, "(-2,1;-1,5;7,5;2,1)" )
|
||||
aa = a.dup
|
||||
a.size(2, 0, 2);
|
||||
assert_equal( a.to_s, "(-2,1;-1,5;7,5;2,1)" )
|
||||
a = aa
|
||||
aa = a.dup
|
||||
a.size(RBA::Vector::new(2, 0), 2);
|
||||
assert_equal( a.to_s, "(-2,1;-1,5;7,5;2,1)" )
|
||||
a = aa
|
||||
aa = a.dup
|
||||
a.size(RBA::Vector::new(2, 0));
|
||||
assert_equal( a.to_s, "(-2,1;-1,5;7,5;2,1)" )
|
||||
|
||||
a = RBA::Polygon::new
|
||||
assert_equal( a.to_s, "()" )
|
||||
|
|
|
|||
|
|
@ -27,7 +27,16 @@ class DBLayout_TestClass < TestBase
|
|||
|
||||
def collect(s, l)
|
||||
|
||||
# check native iteration here too ..
|
||||
res2 = []
|
||||
s.each do |s|
|
||||
r = "[#{s.inst_cell.name}]"
|
||||
r += (s.trans * s.inst_trans).to_s
|
||||
res2.push(r)
|
||||
end
|
||||
|
||||
res = []
|
||||
s.reset
|
||||
while !s.at_end?
|
||||
r = "[#{s.inst_cell.name}]"
|
||||
r += (s.trans * s.inst_trans).to_s
|
||||
|
|
@ -35,6 +44,8 @@ class DBLayout_TestClass < TestBase
|
|||
s.next
|
||||
end
|
||||
|
||||
assert_equal(res, res2)
|
||||
|
||||
return res.join("/")
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -27,7 +27,21 @@ class DBRecursiveShapeIterator_TestClass < TestBase
|
|||
|
||||
def collect(s, l)
|
||||
|
||||
# check native iteration here too ..
|
||||
res2 = []
|
||||
s.each do |s|
|
||||
r = "[#{l.cell_name(s.cell_index)}]"
|
||||
if s.shape.is_box?
|
||||
box = s.shape.box
|
||||
r += box.transformed(s.trans).to_s
|
||||
else
|
||||
r += "X";
|
||||
end
|
||||
res2.push(r)
|
||||
end
|
||||
|
||||
res = []
|
||||
s.reset
|
||||
while !s.at_end?
|
||||
r = "[#{l.cell_name(s.cell_index)}]"
|
||||
if s.shape.is_box?
|
||||
|
|
@ -40,6 +54,8 @@ class DBRecursiveShapeIterator_TestClass < TestBase
|
|||
res.push(r)
|
||||
end
|
||||
|
||||
assert_equal(res, res2)
|
||||
|
||||
return res.join("/")
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -318,6 +318,16 @@ class DBRegion_TestClass < TestBase
|
|||
rr.size(10, 20, 2)
|
||||
assert_equal(rr.to_s, "(-20,-40;-20,180;0,180;0,220;110,220;110,0;90,0;90,-40)")
|
||||
|
||||
assert_equal((r1 | r2).sized(RBA::Vector::new(10, 20)).to_s, "(-20,-40;-20,180;0,180;0,220;110,220;110,0;90,0;90,-40)")
|
||||
rr = (r1 | r2).dup
|
||||
rr.size(10, 20, 2)
|
||||
assert_equal(rr.to_s, "(-20,-40;-20,180;0,180;0,220;110,220;110,0;90,0;90,-40)")
|
||||
|
||||
assert_equal((r1 | r2).sized(RBA::Vector::new(10, 20), 2).to_s, "(-20,-40;-20,180;0,180;0,220;110,220;110,0;90,0;90,-40)")
|
||||
rr = (r1 | r2).dup
|
||||
rr.size(10, 20, 2)
|
||||
assert_equal(rr.to_s, "(-20,-40;-20,180;0,180;0,220;110,220;110,0;90,0;90,-40)")
|
||||
|
||||
r1.merged_semantics = false
|
||||
|
||||
assert_equal((r1 | r2).sized(10, 2).to_s, "(-20,-30;-20,170;0,170;0,210;110,210;110,10;90,10;90,-30)")
|
||||
|
|
|
|||
|
|
@ -69,12 +69,34 @@ class DBText_TestClass < TestBase
|
|||
a = RBA::DText::new( "hallo", a.trans, 22.0, 7 )
|
||||
assert_equal( a.string, "hallo" )
|
||||
assert_equal( a.trans.to_s, "m45 5,7" )
|
||||
assert_equal( a.position.to_s, "5,7" )
|
||||
assert_equal( a.bbox.to_s, "(5,7;5,7)" )
|
||||
assert_equal( a.font, 7 )
|
||||
assert_equal( a.size, 22.0 )
|
||||
|
||||
a.font = 8
|
||||
assert_equal( a.font, 8 )
|
||||
|
||||
a.halign = 1
|
||||
assert_equal( a.halign.to_i, 1 )
|
||||
assert_equal( a.halign, RBA::DText::HAlignCenter )
|
||||
assert_equal( a.halign.to_s, "HAlignCenter" )
|
||||
|
||||
a.halign = RBA::DText::HAlignRight
|
||||
assert_equal( a.halign.to_i, 2 )
|
||||
assert_equal( a.halign, RBA::DText::HAlignRight )
|
||||
assert_equal( a.halign.to_s, "HAlignRight" )
|
||||
|
||||
a.valign = 1
|
||||
assert_equal( a.valign.to_i, 1 )
|
||||
assert_equal( a.valign, RBA::DText::VAlignCenter )
|
||||
assert_equal( a.valign.to_s, "VAlignCenter" )
|
||||
|
||||
a.valign = RBA::DText::VAlignBottom
|
||||
assert_equal( a.valign.to_i, 2 )
|
||||
assert_equal( a.valign, RBA::DText::VAlignBottom )
|
||||
assert_equal( a.valign.to_s, "VAlignBottom" )
|
||||
|
||||
a.size = 23.0
|
||||
assert_equal( a.size, 23.0 )
|
||||
|
||||
|
|
@ -141,12 +163,34 @@ class DBText_TestClass < TestBase
|
|||
a = RBA::Text::new( "hallo", a.trans, 22, 7 )
|
||||
assert_equal( a.string, "hallo" )
|
||||
assert_equal( a.trans.to_s, "m45 5,7" )
|
||||
assert_equal( a.position.to_s, "5,7" )
|
||||
assert_equal( a.bbox.to_s, "(5,7;5,7)" )
|
||||
assert_equal( a.font, 7 )
|
||||
assert_equal( a.size, 22.0 )
|
||||
|
||||
a.font = 8
|
||||
assert_equal( a.font, 8 )
|
||||
|
||||
a.halign = 1
|
||||
assert_equal( a.halign.to_i, 1 )
|
||||
assert_equal( a.halign, RBA::Text::HAlignCenter )
|
||||
assert_equal( a.halign.to_s, "HAlignCenter" )
|
||||
|
||||
a.halign = RBA::Text::HAlignLeft
|
||||
assert_equal( a.halign.to_i, 0 )
|
||||
assert_equal( a.halign, RBA::Text::HAlignLeft )
|
||||
assert_equal( a.halign.to_s, "HAlignLeft" )
|
||||
|
||||
a.valign = 1
|
||||
assert_equal( a.valign.to_i, 1 )
|
||||
assert_equal( a.valign, RBA::Text::VAlignCenter )
|
||||
assert_equal( a.valign.to_s, "VAlignCenter" )
|
||||
|
||||
a.valign = RBA::Text::VAlignTop
|
||||
assert_equal( a.valign.to_i, 0 )
|
||||
assert_equal( a.valign, RBA::Text::VAlignTop )
|
||||
assert_equal( a.valign.to_s, "VAlignTop" )
|
||||
|
||||
a.size = 23
|
||||
assert_equal( a.size, 23 )
|
||||
|
||||
|
|
|
|||
|
|
@ -80,6 +80,8 @@ class DBTrans_TestClass < TestBase
|
|||
assert_equal( RBA::Trans::new(RBA::Trans::R180, RBA::DVector::new(5,-7)).to_s, "r180 5,-7" )
|
||||
assert_equal( RBA::Trans::new(RBA::Trans::R180).to_s, "r180 0,0" )
|
||||
|
||||
assert_equal( e.trans( 2.0 ).to_s, "2" )
|
||||
assert_equal( (e * 2.0).to_s, "2" )
|
||||
assert_equal( e.trans( RBA::Edge::new(0, 1, 2, 3) ).to_s, "(-3,-2;-1,0)" )
|
||||
assert_equal( ( e * RBA::Edge::new(0, 1, 2, 3) ).to_s, "(-3,-2;-1,0)" )
|
||||
assert_equal( e.trans( RBA::Box::new(0, 1, 2, 3) ).to_s, "(-3,-2;-1,0)" )
|
||||
|
|
@ -140,7 +142,9 @@ class DBTrans_TestClass < TestBase
|
|||
|
||||
assert_equal( mb.trans( RBA::DPoint::new( 1, 0 )).to_s, "17,3" )
|
||||
assert_equal( mb.ctrans(2).to_s, "4.0" )
|
||||
assert_equal( (mb * 2).to_s, "4.0" )
|
||||
assert_equal( i.ctrans(2).to_s, "1.0" )
|
||||
assert_equal( (i * 2).to_s, "1.0" )
|
||||
|
||||
end
|
||||
|
||||
|
|
@ -199,6 +203,7 @@ class DBTrans_TestClass < TestBase
|
|||
assert_equal( (c.angle - 45).abs < 1e-10, true )
|
||||
|
||||
assert_equal( c.ctrans( 5 ).to_s, "3.75" )
|
||||
assert_equal( (c * 5).to_s, "3.75" )
|
||||
assert_equal( c.trans( RBA::DPoint::new( 12, 16 ) ).to_s, "17.3492424049,-14.6213203436" )
|
||||
|
||||
assert_equal( RBA::DCplxTrans::new.to_s, "r0 *1 0,0" )
|
||||
|
|
@ -306,7 +311,9 @@ class DBTrans_TestClass < TestBase
|
|||
|
||||
assert_equal( mb.trans( RBA::Point::new( 1, 0 )).to_s, "17,3" )
|
||||
assert_equal( mb.ctrans(2).to_s, "4.0" )
|
||||
assert_equal( (mb * 2).to_s, "4.0" )
|
||||
assert_equal( i.ctrans(2).to_s, "1.0" )
|
||||
assert_equal( (i * 2).to_s, "1.0" )
|
||||
|
||||
end
|
||||
|
||||
|
|
@ -353,6 +360,7 @@ class DBTrans_TestClass < TestBase
|
|||
assert_equal( (c.angle - 45).abs < 1e-10, true )
|
||||
|
||||
assert_equal( c.ctrans( 5 ).to_s, "3.75" )
|
||||
assert_equal( (c * 5).to_s, "3.75" )
|
||||
assert_equal( c.trans( RBA::Point::new( 12, 16 ) ).to_s, "17.3492424049,-14.6213203436" )
|
||||
|
||||
assert_equal( RBA::CplxTrans::new.to_s, "r0 *1 0,0" )
|
||||
|
|
|
|||
Loading…
Reference in New Issue