Merge all shapes of a certain layer of a cell

edited September 2015 in General

Hello Matthias,

I have a small problem. I want to merge all shapes of a certain layer of a cell. All shapes are already polygons. I am not sure how to do it, since you usually need an array of polygons for the merge command. The only way I know of to adress the shapes needed would be:

cell_name.each_shape(layer_name) do |shape|
  xxx
end 

But with this method I dont know how to proceed.

Another idea I tried was with the ShapeProcessor. It looks like:

processor = RBA::ShapeProcessor.new
processor.merge_to_polygon(cell_name.shapes(layer_name), 0, true, false)

The last command needs an array as argument. But the "cell.shapes()" command should give us a list of shapes according to the class documentation. Isn't a list of shapes equivalent to the required array?

Thanks for your help in advance!

Greetings,
Elias

Comments

  • edited 11:11AM

    I found the simplest solution for my problem:

    processor = RBA::ShapeProcessor.new
    processor.merge(layout, cell_name, layer_name, shape-container, false ,0,false,true)
    

    The problem at hand is solved, but just out of curiosity, I would still like to know how to make the list of shapes ( gained by: cell_name.shapes(layer_name)) to an array to use it for the command stated in the previous comment.

    Thanks again,
    Elias

  • edited September 2015

    Hi Elias,

    You can turn a Shapes container into a Shape array with a loop:

    shape_array = []    # will become and array of Shape objects
    shapes = ...        # a Shapes object
    shapes.each { |s| shape_array << s }
    

    But this is not really efficient and when you have a hierarchy of cells, this loop will just convert one cell, not it's children.

    Actually ShapeProcessor is a bit limited in it's use as is it's brother EdgeProcessor. The reasoning behind EdgeProcessor and ShapeProcessor is that the former operates on raw objects (Polygon, Edge, ...) while the latter works on the more generic Shape objects. Both classes implement polygon boolean operations. They allow a great degree of control what you do, but they are a bit unhandy.

    I'd recommend using the newer Region and Edges objects which act as polygon and edge containers and support higher level operations through their methods. Both can be created from a real layout using the RecursiveShapeIterator which is a powerful tool to address the shapes from cell trees or subtrees:

    cell = ....    # a Cell which you want to take the polygons from
    layer = ....   # the layer index from which you want to take the polygons
    
    # creates a region containing all polygons from the cell's layer plus all the
    # polygons from it's children.
    region = RBA::Region::new(cell.begin_shapes_rec(layer))
    
    # merges the polygons (in-place: the region is filled with the merged polygons)
    region.merge
    
    # clears the input layer (in all cells) and puts the 
    # merged polygons back into the cell
    cell.layout.clear_layer(layer)
    cell.shapes(layer).insert(region)
    

    The Edges class allows handling of edges (the connecting lines of the polygon vertexes). There is a rich set of methods on these containers you may like to explore. In fact, the DRC engine is built around these two objects mainly and is implemented as a thin wrapper around these. In Region and Edges you have access to these methods without your code.

    If you want to script layout manipulations alone, the DRC feature may be easier to use because it wraps all the overhead of retrieving and storing polygons. Merging a layer in a DRC script looks like this:

    # Merges the polygons on layer 10, datatype 0:
    input(10).merged.output(10)
    

    Matthias

  • edited 11:11AM

    Thank you Matthias for your thorough answer. I will look into these objects.

  • Hello,
    I know this is an old post but I am trying to perform operations such as merges.
    In python I have written the following:

    for lind in layout.layer_indexes():
    mergeReg = pya.Region(top.begin_shapes_rec(lind))
    mergeReg.merge
    top.layout.clear_layer(lint)
    top.shapes(lint).insert(mergeReg)

    I get the error :
    Caught the following exception:
    'builtin_function_or_method' object has no attribute 'clear_layer' (Class AttributeError)

    I've tried different paths to find this function but have not been successful. I'm sure I'm missing something.
    Any help would be appreciated.

  • there was a typo in my post "lint" should be "lind" it does not change the error

  • Hi hleduc,

    Comments in this forum are better formatted with Markdown. Python code specifically is nicer to read when placed in a fenced code block, by placing triple backticks ``` before and after the code block.

    The error is saying that the word before clear_layer is a buildin function or method. That's layout. I guess top is a Cell and layout a method of a Cell instance. Note that the API documentation is written with Ruby in mind. In Python you have to add parenthesis to call a buildin/function/method:

    for lind in layout.layer_indexes():
        mergeReg = pya.Region(top.begin_shapes_rec(lind))
        mergeReg.merge
        top.layout().clear_layer(lind)
        top.shapes(lind).insert(mergeReg)
    

    HTH

  • Thanks. I will learn mark down (do you use an editor?). I converted everything to ruby and it is working. I will go back and try the python version.

Sign In or Register to comment.