WIP: properties for regions, starting with deep regions

This commit is contained in:
Matthias Koefferlein 2023-01-09 00:05:31 +01:00
parent 0ba719ad84
commit 478b838589
6 changed files with 246 additions and 124 deletions

View File

@ -481,13 +481,14 @@ DeepLayer DeepShapeStore::create_from_flat (const db::Region &region, bool for_n
// try to maintain the texts on top level - go through shape iterator // try to maintain the texts on top level - go through shape iterator
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> ii = region.begin_iter (); std::pair<db::RecursiveShapeIterator, db::ICplxTrans> ii = region.begin_iter ();
bool regard_props = ((ii.first.shape_flags () & db::ShapeIterator::RegardProperties) != 0);
db::ICplxTrans ttop = trans * ii.second; db::ICplxTrans ttop = trans * ii.second;
while (! ii.first.at_end ()) { while (! ii.first.at_end ()) {
if (for_netlist && ii.first->is_text () && ii.first.layout () && ii.first.cell () != ii.first.top_cell ()) { if (for_netlist && ii.first->is_text () && ii.first.layout () && ii.first.cell () != ii.first.top_cell ()) {
// Skip texts on levels below top cell. For the reasoning see the description of this method. // Skip texts on levels below top cell. For the reasoning see the description of this method.
} else { } else {
red.push (*ii.first, ttop * ii.first.trans (), world, 0, shapes); red.push (*ii.first, regard_props ? ii.first->prop_id () : 0, ttop * ii.first.trans (), world, 0, shapes);
} }
++ii.first; ++ii.first;
@ -518,9 +519,10 @@ DeepLayer DeepShapeStore::create_from_flat (const db::Edges &edges, const db::IC
db::EdgeBuildingHierarchyBuilderShapeReceiver eb (false); db::EdgeBuildingHierarchyBuilderShapeReceiver eb (false);
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> ii = edges.begin_iter (); std::pair<db::RecursiveShapeIterator, db::ICplxTrans> ii = edges.begin_iter ();
bool regard_props = ((ii.first.shape_flags () & db::ShapeIterator::RegardProperties) != 0);
db::ICplxTrans ttop = trans * ii.second; db::ICplxTrans ttop = trans * ii.second;
while (! ii.first.at_end ()) { while (! ii.first.at_end ()) {
eb.push (*ii.first, ttop * ii.first.trans (), world, 0, shapes); eb.push (*ii.first, regard_props ? ii.first->prop_id () : 0, ttop * ii.first.trans (), world, 0, shapes);
++ii.first; ++ii.first;
} }
@ -548,9 +550,10 @@ DeepLayer DeepShapeStore::create_from_flat (const db::Texts &texts, const db::IC
db::TextBuildingHierarchyBuilderShapeReceiver tb (&layout ()); db::TextBuildingHierarchyBuilderShapeReceiver tb (&layout ());
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> ii = texts.begin_iter (); std::pair<db::RecursiveShapeIterator, db::ICplxTrans> ii = texts.begin_iter ();
bool regard_props = ((ii.first.shape_flags () & db::ShapeIterator::RegardProperties) != 0);
db::ICplxTrans ttop = trans * ii.second; db::ICplxTrans ttop = trans * ii.second;
while (! ii.first.at_end ()) { while (! ii.first.at_end ()) {
tb.push (*ii.first, ttop * ii.first.trans (), world, 0, shapes); tb.push (*ii.first, regard_props ? ii.first->prop_id () : 0, ttop * ii.first.trans (), world, 0, shapes);
++ii.first; ++ii.first;
} }
@ -905,7 +908,7 @@ DeepLayer DeepShapeStore::create_copy (const DeepLayer &source, HierarchyBuilder
db::Shapes &into = c->shapes (layer_index); db::Shapes &into = c->shapes (layer_index);
const db::Shapes &from = c->shapes (from_layer_index); const db::Shapes &from = c->shapes (from_layer_index);
for (db::Shapes::shape_iterator s = from.begin (db::ShapeIterator::All); ! s.at_end (); ++s) { for (db::Shapes::shape_iterator s = from.begin (db::ShapeIterator::All); ! s.at_end (); ++s) {
pipe->push (*s, trans, region, 0, &into); pipe->push (*s, s->prop_id (), trans, region, 0, &into);
} }
} }

View File

@ -152,13 +152,13 @@ static std::pair<bool, std::set<db::Box> > compute_clip_variant (const db::Box &
} }
HierarchyBuilder::HierarchyBuilder (db::Layout *target, unsigned int target_layer, const db::ICplxTrans &trans, HierarchyBuilderShapeReceiver *pipe) HierarchyBuilder::HierarchyBuilder (db::Layout *target, unsigned int target_layer, const db::ICplxTrans &trans, HierarchyBuilderShapeReceiver *pipe)
: mp_target (target), m_initial_pass (true), m_cm_new_entry (false), m_target_layer (target_layer), m_trans (trans) : mp_target (target), m_initial_pass (true), m_ignore_properties (true), m_cm_new_entry (false), m_target_layer (target_layer), m_trans (trans)
{ {
set_shape_receiver (pipe); set_shape_receiver (pipe);
} }
HierarchyBuilder::HierarchyBuilder (db::Layout *target, const db::ICplxTrans &trans, HierarchyBuilderShapeReceiver *pipe) HierarchyBuilder::HierarchyBuilder (db::Layout *target, const db::ICplxTrans &trans, HierarchyBuilderShapeReceiver *pipe)
: mp_target (target), m_initial_pass (true), m_cm_new_entry (false), m_target_layer (0), m_trans (trans) : mp_target (target), m_initial_pass (true), m_ignore_properties (true), m_cm_new_entry (false), m_target_layer (0), m_trans (trans)
{ {
set_shape_receiver (pipe); set_shape_receiver (pipe);
} }
@ -179,6 +179,7 @@ HierarchyBuilder::reset ()
{ {
m_initial_pass = true; m_initial_pass = true;
mp_initial_cell = 0; mp_initial_cell = 0;
m_ignore_properties = true;
m_cells_to_be_filled.clear (); m_cells_to_be_filled.clear ();
m_cell_map.clear (); m_cell_map.clear ();
@ -244,6 +245,8 @@ HierarchyBuilder::begin (const RecursiveShapeIterator *iter)
tl_assert (compare_iterators_with_respect_to_target_hierarchy (m_source, *iter) == 0); tl_assert (compare_iterators_with_respect_to_target_hierarchy (m_source, *iter) == 0);
} }
m_ignore_properties = ((iter->shape_flags () & db::ShapeIterator::RegardProperties) == 0);
m_cell_stack.clear (); m_cell_stack.clear ();
m_cells_seen.clear (); m_cells_seen.clear ();
@ -275,6 +278,7 @@ HierarchyBuilder::end (const RecursiveShapeIterator *iter)
{ {
tl_assert (! iter->layout () || ! iter->top_cell () || m_cell_stack.size () == 1); tl_assert (! iter->layout () || ! iter->top_cell () || m_cell_stack.size () == 1);
m_ignore_properties = true;
m_initial_pass = false; m_initial_pass = false;
m_cells_seen.clear (); m_cells_seen.clear ();
mp_initial_cell = m_cell_stack.empty () ? 0 : m_cell_stack.front ().second.front (); mp_initial_cell = m_cell_stack.empty () ? 0 : m_cell_stack.front ().second.front ();
@ -411,7 +415,7 @@ HierarchyBuilder::shape (const RecursiveShapeIterator * /*iter*/, const db::Shap
{ {
for (std::vector<db::Cell *>::const_iterator c = m_cell_stack.back ().second.begin (); c != m_cell_stack.back ().second.end (); ++c) { for (std::vector<db::Cell *>::const_iterator c = m_cell_stack.back ().second.begin (); c != m_cell_stack.back ().second.end (); ++c) {
db::Shapes &shapes = (*c)->shapes (m_target_layer); db::Shapes &shapes = (*c)->shapes (m_target_layer);
mp_pipe->push (shape, m_trans * apply_always, region, complex_region, &shapes); mp_pipe->push (shape, m_ignore_properties ? 0 : shape.prop_id (), m_trans * apply_always, region, complex_region, &shapes);
} }
} }
@ -424,54 +428,54 @@ ClippingHierarchyBuilderShapeReceiver::ClippingHierarchyBuilderShapeReceiver (Hi
} }
void void
ClippingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) ClippingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
{ {
static db::Box world = db::Box::world (); static db::Box world = db::Box::world ();
if (region == world || is_inside (shape.bbox (), region, complex_region)) { if (region == world || is_inside (shape.bbox (), region, complex_region)) {
mp_pipe->push (shape, trans, world, 0, target); mp_pipe->push (shape, prop_id, trans, world, 0, target);
} else if (! is_outside (shape.bbox (), region, complex_region)) { } else if (! is_outside (shape.bbox (), region, complex_region)) {
// clip the shape if required // clip the shape if required
if (shape.is_text () || shape.is_edge () || shape.is_edge_pair ()) { if (shape.is_text () || shape.is_edge () || shape.is_edge_pair ()) {
mp_pipe->push (shape, trans, world, 0, target); mp_pipe->push (shape, prop_id, trans, world, 0, target);
} else if (shape.is_box ()) { } else if (shape.is_box ()) {
insert_clipped (shape.box (), trans, region, complex_region, target); insert_clipped (shape.box (), prop_id, trans, region, complex_region, target);
} else if (shape.is_polygon () || shape.is_simple_polygon () || shape.is_path ()) { } else if (shape.is_polygon () || shape.is_simple_polygon () || shape.is_path ()) {
db::Polygon poly; db::Polygon poly;
shape.polygon (poly); shape.polygon (poly);
insert_clipped (poly, trans, region, complex_region, target); insert_clipped (poly, prop_id, trans, region, complex_region, target);
} }
} }
} }
void void
ClippingHierarchyBuilderShapeReceiver::push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) ClippingHierarchyBuilderShapeReceiver::push (const db::Box &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
{ {
static db::Box world = db::Box::world (); static db::Box world = db::Box::world ();
if (! complex_region) { if (! complex_region) {
db::Box r = shape & region; db::Box r = shape & region;
if (! r.empty()) { if (! r.empty()) {
mp_pipe->push (r, trans, world, 0, target); mp_pipe->push (r, prop_id, trans, world, 0, target);
} }
} else { } else {
insert_clipped (shape, trans, region, complex_region, target); insert_clipped (shape, prop_id, trans, region, complex_region, target);
} }
} }
void void
ClippingHierarchyBuilderShapeReceiver::push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) ClippingHierarchyBuilderShapeReceiver::push (const db::Polygon &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
{ {
static db::Box world = db::Box::world (); static db::Box world = db::Box::world ();
if (region == world || (shape.box ().inside (region) && ! complex_region)) { if (region == world || (shape.box ().inside (region) && ! complex_region)) {
mp_pipe->push (shape, trans, world, 0, target); mp_pipe->push (shape, prop_id, trans, world, 0, target);
} else { } else {
insert_clipped (shape, trans, region, complex_region, target); insert_clipped (shape, prop_id, trans, region, complex_region, target);
} }
} }
@ -529,7 +533,7 @@ ClippingHierarchyBuilderShapeReceiver::is_outside (const db::Box &box, const db:
} }
void void
ClippingHierarchyBuilderShapeReceiver::insert_clipped (const db::Box &box, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) ClippingHierarchyBuilderShapeReceiver::insert_clipped (const db::Box &box, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
{ {
db::Box bb = box & region; db::Box bb = box & region;
static db::Box world = db::Box::world (); static db::Box world = db::Box::world ();
@ -538,16 +542,16 @@ ClippingHierarchyBuilderShapeReceiver::insert_clipped (const db::Box &box, const
for (db::RecursiveShapeReceiver::box_tree_type::overlapping_iterator cr = complex_region->begin_overlapping (bb, db::box_convert<db::Box> ()); ! cr.at_end (); ++cr) { for (db::RecursiveShapeReceiver::box_tree_type::overlapping_iterator cr = complex_region->begin_overlapping (bb, db::box_convert<db::Box> ()); ! cr.at_end (); ++cr) {
db::Box bc = *cr & bb; db::Box bc = *cr & bb;
if (! bc.empty ()) { if (! bc.empty ()) {
mp_pipe->push (bc, trans, world, 0, target); mp_pipe->push (bc, prop_id, trans, world, 0, target);
} }
} }
} else if (! bb.empty ()) { } else if (! bb.empty ()) {
mp_pipe->push (bb, trans, world, 0, target); mp_pipe->push (bb, prop_id, trans, world, 0, target);
} }
} }
void void
ClippingHierarchyBuilderShapeReceiver::insert_clipped (const db::Polygon &poly, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) ClippingHierarchyBuilderShapeReceiver::insert_clipped (const db::Polygon &poly, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
{ {
std::vector<db::Polygon> clipped_poly; std::vector<db::Polygon> clipped_poly;
static db::Box world = db::Box::world (); static db::Box world = db::Box::world ();
@ -562,7 +566,7 @@ ClippingHierarchyBuilderShapeReceiver::insert_clipped (const db::Polygon &poly,
} }
for (std::vector<db::Polygon>::const_iterator p = clipped_poly.begin (); p != clipped_poly.end (); ++p) { for (std::vector<db::Polygon>::const_iterator p = clipped_poly.begin (); p != clipped_poly.end (); ++p) {
mp_pipe->push (*p, trans, world, 0, target); mp_pipe->push (*p, prop_id, trans, world, 0, target);
} }
} }
@ -575,33 +579,33 @@ ReducingHierarchyBuilderShapeReceiver::ReducingHierarchyBuilderShapeReceiver (Hi
} }
void void
ReducingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) ReducingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
{ {
if (shape.is_text () || shape.is_edge () || shape.is_edge_pair ()) { if (shape.is_text () || shape.is_edge () || shape.is_edge_pair ()) {
mp_pipe->push (shape, trans, region, complex_region, target); mp_pipe->push (shape, prop_id, trans, region, complex_region, target);
} else if (shape.is_box ()) { } else if (shape.is_box ()) {
mp_pipe->push (shape.box (), trans, region, complex_region, target); mp_pipe->push (shape.box (), prop_id, trans, region, complex_region, target);
} else if (shape.is_polygon () || shape.is_simple_polygon () || shape.is_path ()) { } else if (shape.is_polygon () || shape.is_simple_polygon () || shape.is_path ()) {
db::Polygon poly; db::Polygon poly;
shape.polygon (poly); shape.polygon (poly);
reduce (poly, trans, region, complex_region, target); reduce (poly, prop_id, trans, region, complex_region, target);
} }
} }
void void
ReducingHierarchyBuilderShapeReceiver::push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) ReducingHierarchyBuilderShapeReceiver::push (const db::Box &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
{ {
mp_pipe->push (shape, trans, region, complex_region, target); mp_pipe->push (shape, prop_id, trans, region, complex_region, target);
} }
void void
ReducingHierarchyBuilderShapeReceiver::push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) ReducingHierarchyBuilderShapeReceiver::push (const db::Polygon &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
{ {
reduce (shape, trans, region, complex_region, target); reduce (shape, prop_id, trans, region, complex_region, target);
} }
void void
ReducingHierarchyBuilderShapeReceiver::reduce (const db::Polygon &poly, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target, bool check) ReducingHierarchyBuilderShapeReceiver::reduce (const db::Polygon &poly, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target, bool check)
{ {
if (check && m_reject_odd_polygons && is_non_orientable_polygon (poly)) { if (check && m_reject_odd_polygons && is_non_orientable_polygon (poly)) {
// non-orientable polygons generate an error // non-orientable polygons generate an error
@ -620,11 +624,11 @@ ReducingHierarchyBuilderShapeReceiver::reduce (const db::Polygon &poly, const db
db::split_polygon (poly, split_polygons); db::split_polygon (poly, split_polygons);
for (std::vector <db::Polygon>::const_iterator sp = split_polygons.begin (); sp != split_polygons.end (); ++sp) { for (std::vector <db::Polygon>::const_iterator sp = split_polygons.begin (); sp != split_polygons.end (); ++sp) {
reduce (*sp, trans, region, complex_region, target, false); reduce (*sp, prop_id, trans, region, complex_region, target, false);
} }
} else { } else {
mp_pipe->push (poly, trans, region, complex_region, target); mp_pipe->push (poly, prop_id, trans, region, complex_region, target);
} }
} }
@ -639,7 +643,7 @@ PolygonReferenceHierarchyBuilderShapeReceiver::PolygonReferenceHierarchyBuilderS
} }
} }
void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target) void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
{ {
if (shape.is_box () || shape.is_polygon () || shape.is_simple_polygon () || shape.is_path ()) { if (shape.is_box () || shape.is_polygon () || shape.is_simple_polygon () || shape.is_path ()) {
@ -652,7 +656,11 @@ void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Shape &shape
// NOTE: as this is a specialized receiver for the purpose of building region // NOTE: as this is a specialized receiver for the purpose of building region
// representations we don't need empty polygons here // representations we don't need empty polygons here
if (poly.area2 () > 0) { if (poly.area2 () > 0) {
target->insert (db::PolygonRef (poly, mp_layout->shape_repository ())); if (prop_id != 0) {
target->insert (db::PolygonRefWithProperties (db::PolygonRef (poly, mp_layout->shape_repository ()), prop_id));
} else {
target->insert (db::PolygonRef (poly, mp_layout->shape_repository ()));
}
} }
} else if (shape.is_text () && m_text_enlargement >= 0) { } else if (shape.is_text () && m_text_enlargement >= 0) {
@ -672,23 +680,36 @@ void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Shape &shape
target->insert (db::PolygonRefWithProperties (pref, pid)); target->insert (db::PolygonRefWithProperties (pref, pid));
} else { } else {
target->insert (pref);
if (prop_id != 0) {
target->insert (db::PolygonRefWithProperties (pref, prop_id));
} else {
target->insert (pref);
}
} }
} }
} }
void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target) void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Box &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
{ {
if (shape.area () > 0) { if (shape.area () > 0) {
target->insert (db::PolygonRef (db::Polygon (shape.transformed (trans)), mp_layout->shape_repository ())); if (prop_id != 0) {
target->insert (db::PolygonRefWithProperties (db::PolygonRef (db::Polygon (shape.transformed (trans)), mp_layout->shape_repository ()), prop_id));
} else {
target->insert (db::PolygonRef (db::Polygon (shape.transformed (trans)), mp_layout->shape_repository ()));
}
} }
} }
void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target) void PolygonReferenceHierarchyBuilderShapeReceiver::push (const db::Polygon &shape, properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
{ {
if (shape.area2 () > 0) { if (shape.area2 () > 0) {
target->insert (db::PolygonRef (shape.transformed (trans), mp_layout->shape_repository ())); if (prop_id != 0) {
target->insert (db::PolygonRefWithProperties (db::PolygonRef (shape.transformed (trans), mp_layout->shape_repository ()), prop_id));
} else {
target->insert (db::PolygonRef (shape.transformed (trans), mp_layout->shape_repository ()));
}
} }
} }
@ -700,34 +721,49 @@ EdgeBuildingHierarchyBuilderShapeReceiver::EdgeBuildingHierarchyBuilderShapeRece
// .. nothing yet .. // .. nothing yet ..
} }
void EdgeBuildingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) void EdgeBuildingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
{ {
if (m_as_edges && (shape.is_polygon () || shape.is_simple_polygon () || shape.is_path ())) { if (m_as_edges && (shape.is_polygon () || shape.is_simple_polygon () || shape.is_path ())) {
db::Polygon poly; db::Polygon poly;
shape.polygon (poly); shape.polygon (poly);
push (poly, trans, region, complex_region, target); push (poly, prop_id, trans, region, complex_region, target);
} else if (m_as_edges && shape.is_box ()) { } else if (m_as_edges && shape.is_box ()) {
push (shape.box (), trans, region, complex_region, target); push (shape.box (), prop_id, trans, region, complex_region, target);
} else if (shape.is_edge ()) { } else if (shape.is_edge ()) {
target->insert (shape.edge ()); if (prop_id != 0) {
target->insert (db::EdgeWithProperties (shape.edge (), shape.prop_id ()));
} else {
target->insert (shape.edge ());
}
} }
} }
void EdgeBuildingHierarchyBuilderShapeReceiver::push (const db::Box &box, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target) void EdgeBuildingHierarchyBuilderShapeReceiver::push (const db::Box &box, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
{ {
if (m_as_edges && ! box.empty ()) { if (m_as_edges && ! box.empty ()) {
target->insert (db::Edge (box.p1 (), box.upper_left ()).transformed (trans)); if (prop_id != 0) {
target->insert (db::Edge (box.upper_left (), box.p2 ()).transformed (trans)); target->insert (db::EdgeWithProperties (db::Edge (box.p1 (), box.upper_left ()).transformed (trans), prop_id));
target->insert (db::Edge (box.p2 (), box.lower_right ()).transformed (trans)); target->insert (db::EdgeWithProperties (db::Edge (box.upper_left (), box.p2 ()).transformed (trans), prop_id));
target->insert (db::Edge (box.lower_right (), box.p1 ()).transformed (trans)); target->insert (db::EdgeWithProperties (db::Edge (box.p2 (), box.lower_right ()).transformed (trans), prop_id));
target->insert (db::EdgeWithProperties (db::Edge (box.lower_right (), box.p1 ()).transformed (trans), prop_id));
} else {
target->insert (db::Edge (box.p1 (), box.upper_left ()).transformed (trans));
target->insert (db::Edge (box.upper_left (), box.p2 ()).transformed (trans));
target->insert (db::Edge (box.p2 (), box.lower_right ()).transformed (trans));
target->insert (db::Edge (box.lower_right (), box.p1 ()).transformed (trans));
}
} }
} }
void EdgeBuildingHierarchyBuilderShapeReceiver::push (const db::Polygon &poly, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target) void EdgeBuildingHierarchyBuilderShapeReceiver::push (const db::Polygon &poly, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
{ {
if (m_as_edges) { if (m_as_edges) {
for (db::Polygon::polygon_edge_iterator e = poly.begin_edge (); ! e.at_end (); ++e) { for (db::Polygon::polygon_edge_iterator e = poly.begin_edge (); ! e.at_end (); ++e) {
target->insert ((*e).transformed (trans)); if (prop_id != 0) {
target->insert (db::EdgeWithProperties ((*e).transformed (trans), prop_id));
} else {
target->insert ((*e).transformed (trans));
}
} }
} }
} }
@ -739,10 +775,14 @@ EdgePairBuildingHierarchyBuilderShapeReceiver::EdgePairBuildingHierarchyBuilderS
// .. nothing yet .. // .. nothing yet ..
} }
void EdgePairBuildingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box & /*region*/, const db::RecursiveShapeReceiver::box_tree_type * /*complex_region*/, db::Shapes *target) void EdgePairBuildingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box & /*region*/, const db::RecursiveShapeReceiver::box_tree_type * /*complex_region*/, db::Shapes *target)
{ {
if (shape.is_edge_pair ()) { if (shape.is_edge_pair ()) {
target->insert (shape.edge_pair ().transformed (trans)); if (prop_id != 0) {
target->insert (db::EdgePairWithProperties (shape.edge_pair ().transformed (trans), prop_id));
} else {
target->insert (shape.edge_pair ().transformed (trans));
}
} }
} }
@ -754,13 +794,17 @@ TextBuildingHierarchyBuilderShapeReceiver::TextBuildingHierarchyBuilderShapeRece
// .. nothing yet .. // .. nothing yet ..
} }
void TextBuildingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box & /*region*/, const db::RecursiveShapeReceiver::box_tree_type * /*complex_region*/, db::Shapes *target) void TextBuildingHierarchyBuilderShapeReceiver::push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box & /*region*/, const db::RecursiveShapeReceiver::box_tree_type * /*complex_region*/, db::Shapes *target)
{ {
if (shape.is_text ()) { if (shape.is_text ()) {
// NOTE: we intentionally skip all the text attributes (font etc.) here because in the context // NOTE: we intentionally skip all the text attributes (font etc.) here because in the context
// of a text collections we're only interested in the locations. // of a text collections we're only interested in the locations.
db::Text t (shape.text_string (), shape.text_trans ()); db::Text t (shape.text_string (), shape.text_trans ());
target->insert (db::TextRef (t.transformed (trans), mp_layout->shape_repository ())); if (prop_id != 0) {
target->insert (db::TextRefWithProperties (db::TextRef (t.transformed (trans), mp_layout->shape_repository ()), prop_id));
} else {
target->insert (db::TextRef (t.transformed (trans), mp_layout->shape_repository ()));
}
} }
} }

View File

@ -55,9 +55,9 @@ public:
HierarchyBuilderShapeReceiver () { } HierarchyBuilderShapeReceiver () { }
virtual ~HierarchyBuilderShapeReceiver () { } virtual ~HierarchyBuilderShapeReceiver () { }
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) = 0; virtual void push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) = 0;
virtual void push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) = 0; virtual void push (const db::Box &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) = 0;
virtual void push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) = 0; virtual void push (const db::Polygon &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) = 0;
}; };
/** /**
@ -69,28 +69,45 @@ class DB_PUBLIC HierarchyBuilderShapeInserter
public: public:
HierarchyBuilderShapeInserter () { } HierarchyBuilderShapeInserter () { }
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target) virtual void push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
{ {
tl::ident_map<db::Layout::properties_id_type> pm; tl::const_map<db::Layout::properties_id_type> pm (prop_id);
target->insert (shape, trans, pm); target->insert (shape, trans, pm);
} }
virtual void push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target) virtual void push (const db::Box &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
{ {
if (trans.is_ortho ()) { if (trans.is_ortho ()) {
target->insert (shape.transformed (trans)); if (prop_id != 0) {
target->insert (db::BoxWithProperties (shape.transformed (trans), prop_id));
} else {
target->insert (shape.transformed (trans));
}
} else { } else {
db::Polygon poly (shape); if (prop_id != 0) {
target->insert (poly.transformed (trans)); db::PolygonWithProperties poly (db::Polygon (shape), prop_id);
target->insert (poly.transformed (trans));
} else {
db::Polygon poly (shape);
target->insert (poly.transformed (trans));
}
} }
} }
virtual void push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target) virtual void push (const db::Polygon &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target)
{ {
if (trans.is_unity ()) { if (trans.is_unity ()) {
target->insert (shape); if (prop_id != 0) {
target->insert (db::PolygonWithProperties (shape, prop_id));
} else {
target->insert (shape);
}
} else { } else {
target->insert (shape.transformed (trans)); if (prop_id != 0) {
target->insert (db::PolygonWithProperties (shape.transformed (trans), prop_id));
} else {
target->insert (shape.transformed (trans));
}
} }
} }
}; };
@ -104,13 +121,13 @@ class DB_PUBLIC ClippingHierarchyBuilderShapeReceiver
public: public:
ClippingHierarchyBuilderShapeReceiver (HierarchyBuilderShapeReceiver *pipe = 0); ClippingHierarchyBuilderShapeReceiver (HierarchyBuilderShapeReceiver *pipe = 0);
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target); virtual void push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target); virtual void push (const db::Box &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target); virtual void push (const db::Polygon &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
private: private:
void insert_clipped (const db::Box &box, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target); void insert_clipped (const db::Box &box, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target);
void insert_clipped (const db::Polygon &poly, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target); void insert_clipped (const db::Polygon &poly, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target);
static bool is_inside (const db::Box &box, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region); static bool is_inside (const db::Box &box, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region);
static bool is_outside (const db::Box &box, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region); static bool is_outside (const db::Box &box, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region);
@ -126,12 +143,12 @@ class DB_PUBLIC ReducingHierarchyBuilderShapeReceiver
public: public:
ReducingHierarchyBuilderShapeReceiver (HierarchyBuilderShapeReceiver *pipe = 0, double area_ratio = 3.0, size_t max_vertex_count = 16, bool reject_odd_polygons = false); ReducingHierarchyBuilderShapeReceiver (HierarchyBuilderShapeReceiver *pipe = 0, double area_ratio = 3.0, size_t max_vertex_count = 16, bool reject_odd_polygons = false);
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target); virtual void push (const db::Shape &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target); virtual void push (const db::Box &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target); virtual void push (const db::Polygon &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
private: private:
void reduce (const db::Polygon &poly, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target, bool check = true); void reduce (const db::Polygon &poly, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target, bool check = true);
HierarchyBuilderShapeReceiver *mp_pipe; HierarchyBuilderShapeReceiver *mp_pipe;
double m_area_ratio; double m_area_ratio;
@ -148,9 +165,9 @@ class DB_PUBLIC PolygonReferenceHierarchyBuilderShapeReceiver
public: public:
PolygonReferenceHierarchyBuilderShapeReceiver (db::Layout *layout, int text_enlargement = -1, const tl::Variant &text_prop_name = tl::Variant ()); PolygonReferenceHierarchyBuilderShapeReceiver (db::Layout *layout, int text_enlargement = -1, const tl::Variant &text_prop_name = tl::Variant ());
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target); virtual void push (const db::Shape &shape, properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target); virtual void push (const db::Box &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target); virtual void push (const db::Polygon &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
private: private:
db::Layout *mp_layout; db::Layout *mp_layout;
@ -168,9 +185,9 @@ class DB_PUBLIC EdgeBuildingHierarchyBuilderShapeReceiver
public: public:
EdgeBuildingHierarchyBuilderShapeReceiver (bool as_edges); EdgeBuildingHierarchyBuilderShapeReceiver (bool as_edges);
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target); virtual void push (const db::Shape &shape, properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Box &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target); virtual void push (const db::Box &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Polygon &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target); virtual void push (const db::Polygon &shape, db::properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
private: private:
bool m_as_edges; bool m_as_edges;
@ -185,9 +202,9 @@ class DB_PUBLIC EdgePairBuildingHierarchyBuilderShapeReceiver
public: public:
EdgePairBuildingHierarchyBuilderShapeReceiver (); EdgePairBuildingHierarchyBuilderShapeReceiver ();
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target); virtual void push (const db::Shape &shape, properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Box &, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { } virtual void push (const db::Box &, db::properties_id_type, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
virtual void push (const db::Polygon &, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { } virtual void push (const db::Polygon &, db::properties_id_type, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
}; };
/** /**
@ -199,9 +216,9 @@ class DB_PUBLIC TextBuildingHierarchyBuilderShapeReceiver
public: public:
TextBuildingHierarchyBuilderShapeReceiver (db::Layout *layout); TextBuildingHierarchyBuilderShapeReceiver (db::Layout *layout);
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target); virtual void push (const db::Shape &shape, properties_id_type prop_id, const db::ICplxTrans &trans, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *target);
virtual void push (const db::Box &, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { } virtual void push (const db::Box &, db::properties_id_type, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
virtual void push (const db::Polygon &, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { } virtual void push (const db::Polygon &, db::properties_id_type, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
private: private:
db::Layout *mp_layout; db::Layout *mp_layout;
@ -380,6 +397,7 @@ private:
tl::weak_ptr<db::Layout> mp_target; tl::weak_ptr<db::Layout> mp_target;
HierarchyBuilderShapeReceiver *mp_pipe; HierarchyBuilderShapeReceiver *mp_pipe;
bool m_initial_pass; bool m_initial_pass;
bool m_ignore_properties;
db::RecursiveShapeIterator m_source; db::RecursiveShapeIterator m_source;
cell_map_type m_cell_map; cell_map_type m_cell_map;
original_target_to_variants_map_type m_original_targets_to_variants_map; original_target_to_variants_map_type m_original_targets_to_variants_map;

View File

@ -455,7 +455,7 @@ public:
} }
} }
virtual void push (const db::Shape &shape, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target) virtual void push (const db::Shape &shape, db::properties_id_type, const db::ICplxTrans &trans, const db::Box &region, const db::RecursiveShapeReceiver::box_tree_type *complex_region, db::Shapes *target)
{ {
bool is_text = false; bool is_text = false;
std::string text_string; std::string text_string;
@ -498,8 +498,8 @@ public:
} }
} }
virtual void push (const db::Box &, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { } virtual void push (const db::Box &, db::properties_id_type, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
virtual void push (const db::Polygon &, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { } virtual void push (const db::Polygon &, db::properties_id_type, const db::ICplxTrans &, const db::Box &, const db::RecursiveShapeReceiver::box_tree_type *, db::Shapes *) { }
private: private:
Delivery m_delivery; Delivery m_delivery;

View File

@ -469,6 +469,8 @@ template <class Trans>
Shapes::shape_type Shapes::shape_type
Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_delegate_base <db::properties_id_type> &pm) Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_delegate_base <db::properties_id_type> &pm)
{ {
db::properties_id_type new_pid = shape.has_prop_id () ? pm (shape.prop_id ()) : 0;
switch (shape.m_type) { switch (shape.m_type) {
case shape_type::Null: case shape_type::Null:
default: default:
@ -478,10 +480,10 @@ Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_del
shape_type::polygon_type p (shape.polygon ()); shape_type::polygon_type p (shape.polygon ());
// Hint: we don't compress so we don't loose information // Hint: we don't compress so we don't loose information
p.transform (t, false); p.transform (t, false);
if (! shape.has_prop_id ()) { if (new_pid == 0) {
return insert (p); return insert (p);
} else { } else {
return insert (db::object_with_properties<shape_type::polygon_type> (p, pm (shape.prop_id ()))); return insert (db::object_with_properties<shape_type::polygon_type> (p, new_pid));
} }
} }
case shape_type::PolygonRef: case shape_type::PolygonRef:
@ -492,10 +494,10 @@ Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_del
// Hint: we don't compress so we don't loose information // Hint: we don't compress so we don't loose information
p.transform (t, false); p.transform (t, false);
// TODO: could create a reference again, but this is what a transform would to as well. // TODO: could create a reference again, but this is what a transform would to as well.
if (! shape.has_prop_id ()) { if (new_pid == 0) {
return insert (p); return insert (p);
} else { } else {
return insert (db::object_with_properties<shape_type::polygon_type> (p, pm (shape.prop_id ()))); return insert (db::object_with_properties<shape_type::polygon_type> (p, new_pid));
} }
} }
case shape_type::SimplePolygon: case shape_type::SimplePolygon:
@ -503,10 +505,10 @@ Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_del
shape_type::simple_polygon_type p (shape.simple_polygon ()); shape_type::simple_polygon_type p (shape.simple_polygon ());
// Hint: we don't compress so we don't loose information // Hint: we don't compress so we don't loose information
p.transform (t, false); p.transform (t, false);
if (! shape.has_prop_id ()) { if (new_pid == 0) {
return insert (p); return insert (p);
} else { } else {
return insert (db::object_with_properties<shape_type::simple_polygon_type> (p, pm (shape.prop_id ()))); return insert (db::object_with_properties<shape_type::simple_polygon_type> (p, new_pid));
} }
} }
case shape_type::SimplePolygonRef: case shape_type::SimplePolygonRef:
@ -517,50 +519,50 @@ Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_del
// Hint: we don't compress so we don't loose information // Hint: we don't compress so we don't loose information
p.transform (t, false); p.transform (t, false);
// TODO: could create a reference again, but this is what a transform would to as well. // TODO: could create a reference again, but this is what a transform would to as well.
if (! shape.has_prop_id ()) { if (new_pid == 0) {
return insert (p); return insert (p);
} else { } else {
return insert (db::object_with_properties<shape_type::simple_polygon_type> (p, pm (shape.prop_id ()))); return insert (db::object_with_properties<shape_type::simple_polygon_type> (p, new_pid));
} }
} }
case shape_type::Edge: case shape_type::Edge:
{ {
shape_type::edge_type p (shape.edge ()); shape_type::edge_type p (shape.edge ());
p.transform (t); p.transform (t);
if (! shape.has_prop_id ()) { if (new_pid == 0) {
return insert (p); return insert (p);
} else { } else {
return insert (db::object_with_properties<shape_type::edge_type> (p, pm (shape.prop_id ()))); return insert (db::object_with_properties<shape_type::edge_type> (p, new_pid));
} }
} }
case shape_type::Point: case shape_type::Point:
{ {
shape_type::point_type p (shape.point ()); shape_type::point_type p (shape.point ());
p = t.trans (p); p = t.trans (p);
if (! shape.has_prop_id ()) { if (new_pid == 0) {
return insert (p); return insert (p);
} else { } else {
return insert (db::object_with_properties<shape_type::point_type> (p, pm (shape.prop_id ()))); return insert (db::object_with_properties<shape_type::point_type> (p, new_pid));
} }
} }
case shape_type::EdgePair: case shape_type::EdgePair:
{ {
shape_type::edge_pair_type p (shape.edge_pair ()); shape_type::edge_pair_type p (shape.edge_pair ());
p.transform (t); p.transform (t);
if (! shape.has_prop_id ()) { if (new_pid == 0) {
return insert (p); return insert (p);
} else { } else {
return insert (db::object_with_properties<shape_type::edge_pair_type> (p, pm (shape.prop_id ()))); return insert (db::object_with_properties<shape_type::edge_pair_type> (p, new_pid));
} }
} }
case shape_type::Path: case shape_type::Path:
{ {
shape_type::path_type p (shape.path ()); shape_type::path_type p (shape.path ());
p.transform (t); p.transform (t);
if (! shape.has_prop_id ()) { if (new_pid == 0) {
return insert (p); return insert (p);
} else { } else {
return insert (db::object_with_properties<shape_type::path_type> (p, pm (shape.prop_id ()))); return insert (db::object_with_properties<shape_type::path_type> (p, new_pid));
} }
} }
case shape_type::PathRef: case shape_type::PathRef:
@ -570,10 +572,10 @@ Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_del
shape.path (p); shape.path (p);
p.transform (t); p.transform (t);
// TODO: could create a reference again, but this is what a transform would to as well. // TODO: could create a reference again, but this is what a transform would to as well.
if (! shape.has_prop_id ()) { if (new_pid == 0) {
return insert (p); return insert (p);
} else { } else {
return insert (db::object_with_properties<shape_type::path_type> (p, pm (shape.prop_id ()))); return insert (db::object_with_properties<shape_type::path_type> (p, new_pid));
} }
} }
case shape_type::Box: case shape_type::Box:
@ -584,19 +586,19 @@ Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_del
if (t.is_ortho ()) { if (t.is_ortho ()) {
shape_type::box_type p (shape.box ()); shape_type::box_type p (shape.box ());
p.transform (t); p.transform (t);
if (! shape.has_prop_id ()) { if (new_pid == 0) {
return insert (p); return insert (p);
} else { } else {
return insert (db::object_with_properties<shape_type::box_type> (p, pm (shape.prop_id ()))); return insert (db::object_with_properties<shape_type::box_type> (p, new_pid));
} }
} else { } else {
// A box cannot stay a box in this case ... // A box cannot stay a box in this case ...
shape_type::simple_polygon_type p (shape.box ()); shape_type::simple_polygon_type p (shape.box ());
p.transform (t); p.transform (t);
if (! shape.has_prop_id ()) { if (new_pid == 0) {
return insert (p); return insert (p);
} else { } else {
return insert (db::object_with_properties<shape_type::simple_polygon_type> (p, pm (shape.prop_id ()))); return insert (db::object_with_properties<shape_type::simple_polygon_type> (p, new_pid));
} }
} }
} }
@ -604,10 +606,10 @@ Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_del
{ {
shape_type::text_type p (shape.text ()); shape_type::text_type p (shape.text ());
p.transform (t); p.transform (t);
if (! shape.has_prop_id ()) { if (new_pid == 0) {
return insert (p); return insert (p);
} else { } else {
return insert (db::object_with_properties<shape_type::text_type> (p, pm (shape.prop_id ()))); return insert (db::object_with_properties<shape_type::text_type> (p, new_pid));
} }
} }
case shape_type::TextRef: case shape_type::TextRef:
@ -617,20 +619,20 @@ Shapes::do_insert (const Shapes::shape_type &shape, const Trans &t, tl::func_del
shape.text (p); shape.text (p);
p.transform (t); p.transform (t);
// TODO: could create a reference again, but this is what a transform would to as well. // TODO: could create a reference again, but this is what a transform would to as well.
if (! shape.has_prop_id ()) { if (new_pid == 0) {
return insert (p); return insert (p);
} else { } else {
return insert (db::object_with_properties<shape_type::text_type> (p, pm (shape.prop_id ()))); return insert (db::object_with_properties<shape_type::text_type> (p, new_pid));
} }
} }
case shape_type::UserObject: case shape_type::UserObject:
{ {
shape_type::user_object_type p (shape.user_object ()); shape_type::user_object_type p (shape.user_object ());
p.transform (t); p.transform (t);
if (! shape.has_prop_id ()) { if (new_pid == 0) {
return insert (p); return insert (p);
} else { } else {
return insert (db::object_with_properties<shape_type::user_object_type> (p, pm (shape.prop_id ()))); return insert (db::object_with_properties<shape_type::user_object_type> (p, new_pid));
} }
} }
case shape_type::PolygonPtrArray: case shape_type::PolygonPtrArray:
@ -709,7 +711,7 @@ Shapes::replace_prop_id (const Shapes::shape_type &ref, db::properties_id_type p
throw tl::Exception (tl::to_string (tr ("Function 'replace_prop_id' is permitted only in editable mode"))); throw tl::Exception (tl::to_string (tr ("Function 'replace_prop_id' is permitted only in editable mode")));
} }
if (ref.with_props ()) { if (ref.has_prop_id ()) {
// this assumes we can simply patch the properties ID .. // this assumes we can simply patch the properties ID ..
switch (ref.m_type) { switch (ref.m_type) {
@ -1241,7 +1243,7 @@ Shapes::reinsert_member_with_props (typename db::object_tag<Sh1>, const shape_ty
} }
// the shape types are not equal - resolve into erase and insert (of new) // the shape types are not equal - resolve into erase and insert (of new)
if (! ref.with_props ()) { if (! ref.has_prop_id ()) {
erase_shape (ref); erase_shape (ref);
return insert (sh); return insert (sh);
} else { } else {
@ -1260,7 +1262,7 @@ Shapes::replace_member_with_props (typename db::object_tag<Sh1>, const shape_typ
} }
// the shape types are not equal - resolve into erase and insert (of new) // the shape types are not equal - resolve into erase and insert (of new)
if (! ref.with_props ()) { if (! ref.has_prop_id ()) {
erase_shape (ref); erase_shape (ref);
return insert (sh); return insert (sh);
} else { } else {
@ -1310,7 +1312,7 @@ Shapes::replace_member_with_props (typename db::object_tag<Sh> tag, const shape_
throw tl::Exception (tl::to_string (tr ("Function 'replace' is permitted only in editable mode"))); throw tl::Exception (tl::to_string (tr ("Function 'replace' is permitted only in editable mode")));
} }
if (! ref.with_props ()) { if (! ref.has_prop_id ()) {
if (manager () && manager ()->transacting ()) { if (manager () && manager ()->transacting ()) {
check_is_editable_for_undo_redo (); check_is_editable_for_undo_redo ();

View File

@ -2199,6 +2199,61 @@ TEST(51_PropertiesFlatFromLayout)
EXPECT_EQ (s.at_end (), true); EXPECT_EQ (s.at_end (), true);
} }
TEST(52_PropertiesDeep)
{
db::DeepShapeStore dss ("TOP", 0.001);
db::Region r (dss);
// Fill flat region with parts with properties
r.insert (db::Box (0, 0, 100, 200));
r.insert (db::BoxWithProperties (db::Box (1, 2, 101, 202), 1));
r.insert (db::Box (10, 20, 110, 220));
r.insert (db::BoxWithProperties (db::Box (11, 12, 111, 212), 42));
EXPECT_EQ (r.count (), size_t (4));
db::Region::const_iterator s = r.begin ();
EXPECT_EQ (s.at_end (), false);
EXPECT_EQ (s.prop_id (), db::properties_id_type (0));
EXPECT_EQ (s->to_string (), "(0,0;0,200;100,200;100,0)");
++s;
EXPECT_EQ (s.at_end (), false);
EXPECT_EQ (s.prop_id (), db::properties_id_type (0));
EXPECT_EQ (s->to_string (), "(10,20;10,220;110,220;110,20)");
++s;
EXPECT_EQ (s.at_end (), false);
EXPECT_EQ (s.prop_id (), db::properties_id_type (1));
EXPECT_EQ (s->to_string (), "(1,2;1,202;101,202;101,2)");
++s;
EXPECT_EQ (s.at_end (), false);
EXPECT_EQ (s.prop_id (), db::properties_id_type (42));
EXPECT_EQ (s->to_string (), "(11,12;11,212;111,212;111,12)");
++s;
EXPECT_EQ (s.at_end (), true);
s = r.begin_merged ();
EXPECT_EQ (s.at_end (), false);
EXPECT_EQ (s.prop_id (), db::properties_id_type (0));
// property #0 elements are merged
EXPECT_EQ (s->to_string (), "(0,0;0,200;10,200;10,220;110,220;110,20;100,20;100,0)");
++s;
EXPECT_EQ (s.at_end (), false);
EXPECT_EQ (s.prop_id (), db::properties_id_type (1));
// a single property #1 element
EXPECT_EQ (s->to_string (), "(1,2;1,202;101,202;101,2)");
++s;
EXPECT_EQ (s.at_end (), false);
EXPECT_EQ (s.prop_id (), db::properties_id_type (42));
// a single property #42 element
EXPECT_EQ (s->to_string (), "(11,12;11,212;111,212;111,12)");
++s;
EXPECT_EQ (s.at_end (), true);
}
TEST(100_Processors) TEST(100_Processors)
{ {
db::Region r; db::Region r;