Copy and transform shapes in all subcells

Hi,

I am programming a script that should iterate over all shapes of a given layer, including all subcells of the current view. The shapes will be copied into another layer after applying a transform.
The following example works fine:

shape_iterator = cell.begin_shapes_rec(source_layer)
shapes_destination = cell.shapes(destination_layer)

while not shape_iterator.at_end():
  sh = shape_iterator.shape()
  instance_offset = shape_iterator.dtrans()
  shapes_destination.insert(transformation*instance_offset*sh.dpolygon)
  shape_iterator.next()

Above, the polygons get placed into the current topmost cell. However, I would prefer to have the transformed polygons appear in the subcells of their original counterpart. I have tried the following adapted code for this:

shape_iterator = cell.begin_shapes_rec(source_layer)

while not shape_iterator.at_end():
  sh = shape_iterator.shape()
  current_subcell = shape_iterator.cell()

  shapes_destination = current_subcell.shapes(destination_layer)
  shapes_destination.insert(transformation*sh.dpolygon)
  shape_iterator.next()

which will throw the following error:

Error: cannot call non-const method on a const reference in Shapes.insert

(Actually, the 2nd version will execute without an error, as long as there are no subcells present)

Is there any way to acheive the desired behaviour?
Thanks in advance!

Comments

  • Hi @shadowmaster,

    The Python API shares some concepts with C++ - namely the constness of certain objects. In C++, the cell delivered by "RecursiveShapeIterator#cell" is a "const reference". This means you should not manipulate it. In the end, this is why "Shapes#insert" will refuse to manipulate the cell.

    You can dismiss this warning and obtain a non-const reference via the cell index:

    shape_iterator = cell.begin_shapes_rec(source_layer)
    layout = cell.layout()
    
    while not shape_iterator.at_end():
      sh = shape_iterator.shape()
      current_subcell = layout.cell(shape_iterator.cell_index())
    
      shapes_destination = current_subcell.shapes(destination_layer)
      shapes_destination.insert(transformation*sh.dpolygon)
      shape_iterator.next()
    

    This is a great way to mess with the internals however. Minimum safety can be achieved if you disable on-the-fly updates during this process:

    shape_iterator = cell.begin_shapes_rec(source_layer)
    layout = cell.layout()
    
    # freezes the layout (e.g. quad tree recomputation)
    layout.start_changes()
    
    while not shape_iterator.at_end():
      sh = shape_iterator.shape()
      current_subcell = layout.cell(shape_iterator.cell_index())
    
      shapes_destination = current_subcell.shapes(destination_layer)
      shapes_destination.insert(transformation*sh.dpolygon)
      shape_iterator.next()
    
    # unfreezes the layout
    layout.end_changes()
    

    Caution: if you forget to do "end_changes" you will experience some weird behavior later.

    Matthias

  • Hi Matthias,
    thank you very much! The script now works with the suggested modifications. I have tested it a bit and it seems that it works as intended without causing any problems.

Sign In or Register to comment.