Shapes with Holes

Hi Matthias

I'm a beginner with Klayout and currently im trying to figure out how to get rid of the extra edge whenever you load in a GDS files with holes, like this.

I am aware that you can somewhat achieve this objective with DRC such as layer.holes and layer.hulls, however when it comes to overlapped shape, these method would merge the two shape into one, and that's not something I want to do.

The goal is to get holes and hull from everysingle shape without merging when they are overlapped.

My current approach is to use python script and iterate through the shape in the layer, and uses polygon.resolve_holes to get the hulls of the polygon. However it seems that the extra edge that it adds to everytime I open the file would make the program think the polygon is a simple polygon even though its not, therefore polygon.resolve_holes is not working, and that's why I wonder if there is a way to get rid of the extra edge that connect holes and the hulls.

Sorry for the rumbling, hopefully im making sense.

Thanks!
Andy

Comments

  • edited February 2022

    With some help from a friend this is the solution that I wrote

    
    import pya
    import time
    
    startTime = time.time()
    
    view = pya.LayoutView.current()
    cellview = pya.CellView.active()
    
    
    layout = cellview.layout()
    
    #obatin target layer and the source layer
    target_layer = layout.layer(10, 0)
    source_layer = layout.layer(3, 0)
    
    #get the top cell
    cell_to_add = layout.cell("TOP")
    
    
    shapeList = cell_to_add.shapes(source_layer)
    
    shapeArray = []
    
    for someShape in shapeList.each():
      #Do some operation for each shape in layer
      
      #cell_to_add.shapes(target_layer).insert(someShape)
      #noHoleZone = someShape.polygon.resolve_holes()
      #cell_to_add.shapes(target_layer).insert(noHoleZone)
      
      shapeArray.append(someShape)
      
    #Uses Overlap to get rid of the line
    for anyShape in shapeArray:
    
      r1 = pya.Region()
      r1.insert(anyShape.polygon)
      
      r2 = pya.Region()
      r2.insert(anyShape.polygon)
      
      mergedObject = r1 & r2
      cell_to_add.shapes(target_layer).insert(mergedObject)
      
      r1.destroy()
      r2.destroy()
    
    endTime = time.time()
    print("The time of execution of above program is :", endTime - startTime)
    view.add_missing_layers()
    

    Bascially what I did is to merge every single shape in a layer with themselves then put them on a new layer, and it works. However I wonder if there is a more elegent way to solve this problem, cause I can see the run time gets longer with the gds file getting more complicated. Also I have this feeling that the way how I use r1 and r2 in that loop might cause serious problem and I have no idea if the r1.destroy and r2.destroy even behave the way that I imagine they do.

  • The code is a little more complex than it needs to be.

    If you copy the shapes to a new layer, you do not need to collect the shapes first. This you only need to do if you plan to replace the shapes.

    Plus, you do not need to perform a logical AND ("&" operator) to get the merged polygons. "Region#merge" will do.

    You can also optimize the loop a little to avoid "create + destroy" of the Region objects. Like this:

    r = pya.Region()
    for anyShape in shapeList.each():
      r.clear()
      r.insert(anyShape.polygon)  
      cell_to_add.shapes(target_layer).insert(r.merged())
    

    This may be somewhat better in performance. Still it's a (slow) Python loop.

    A faster (C++) loop is this short DRC script:

    l3 = input(3, 0)
    l10 = l3.raw.drc(primary.merged)
    l10.output(10, 0)
    

    Here is a brief explanation:

    "raw" turns off "merged semantics" for l3. This means, all polygons are considered individually. "drc" is a kind of loop over all shapes - in this case without neighbourhood because there are no measurement functions inside the "drc" function's body. "primary.merged" will be executed for each considered ("primary") shape and "merged" will return the merged polygon.

    To get the hulls only use:

    l3 = input(3, 0)
    l10 = l3.raw.drc(primary.merged.hulls)
    l10.output(10, 0)
    

    See here for details about "drc": https://www.klayout.de/doc-qt5/about/drc_ref_layer.html#h2-340

    Matthias

  • Sorry for the late reply! Thank you very much Matthias, this is very helpful!

    Have a great day!
    Andy

  • @Matthias

    I wonder if there is a more elegent solution without merging, since merging at times can be very time consuming, and I think in a way it would change the original layout. I am just curious

    Thank you very much!
    Andy

  • I'm afraid with GDS there is no other elegant solution. The problem is you're basically fighting against a fundamental concept of GDS which is that touching or overlapping polygons are considered to form a large "painted" area. Edges essentially don't matter. That's why introducing the cut line is a valid and quite commonly used technique.

    You can of course adopt another view and decide that for you edges are important matter. After all, GDS is just a data container. But then GDS does not offer you a clean way of generating polygons with holes. The merge step is the only reliable way to rectify this, I'm afraid. Again, your request is somewhat exotic in terms of GDS conventions and that's why optimized tools are not available yet. The DRC loop is the best that KLayout can offer out of the box.

    Matthias

  • I see! Thank you very much for the respond!

    Andy!

  • @Matthias: I'm new to KLayout and using your python script above to remove the lines in my GDS file (I also used the simple shape shown above at the beginning of this discussion). Now, once I re-save the file and re-open it, the lines appear once again. Is there a way to permanently delete and save the file? Thanks Jesus.

  • Hi Jesucu,

    The removal of lines is done by converting the gds shape to a Klayout database object. During file saving, the object will be once again being convert back to gds format hence the line appears.

    All gds shapes needs to be able to be defined by a closed loop, so internal holes requires a cut line for looping this internal cavity.

    This additional cut line will not affect mask manufacturering, so for normal usage, the removal of the line is not necessary.

    For cased like generate FEM 3D model from gds, this extra line is not prefered, a potenetial sloution is to remove all the holes in shapes and store those holes in a separate datatype, finally use these data to extrude an 3D structure.

  • Hi RawrRanger, thanks for the explanation and agree with your points there. So far I haven't had issues when importing for 3D EM simulation (I import the DXF into CST and the software places the lines in a different folder in the tree so that they can be easily deleted). The only reason for trying to delete those lines from the GDS is because our manufacturing partner was complaining about that. It seems that in the meantime an alternative solution (outside of KLayout) has been found. Cheers!

Sign In or Register to comment.