Hole representation

edited September 2009 in KLayout Support
Hi Matthias

In some areas it is customary to use a polygon inside
some other polygon to mean that the smaller polygon should be deleted.

If we separate these polygons into two layers: regular
polygons and holes, then we can use the Boolean operations on the layers to get the real layout.

Do you have any plans to implement some kind of
"automatic hole extraction" algorithm?
(Or is it already there and I just did not search well enough?)

- Till

Comments

  • edited September 2009

    Hi Till,

    if I understand you correctly, the functionality you look for is already there. It is not necessary to use two separate layers and the whole-layer booleans to get the effect.

    You can draw two or more shapes on the same layer: a larger hull polygon and one or several "future" holes inside the hull polygon. Then you first select the hull polygon and then the hole polygons. "then" refers to selecting them separately: first you click at the hull polygon and then you click at the holes using the Shift button to add them to the selection.

    Internally, KLayout will divide the selected shapes into two groups: one which was selected in the first step ("primary selection") and the others selected additionally with the Shift button pressed ("secondary selection").

    Keeping that in mind, it is probably easier to understand the intention behind the shapewise boolean operations found in the "Selection" submenu of the "Edit" menu: for example, "Subtraction - Others From First" will subtract the secondary selection from the primary selection. Similar, "Intersection - Others With First" will compute the intersection of the primary selection with the secondary selection.

    In effect, you can simply use the "Intersection - Others With First" method to achieve the desired effect when you first select the hull and then (separately) the holes.

    Best regards,

    Matthias

  • edited 1:29AM
    Hi Matthias,

    I think I was very unclear. We get bigger GDS files
    where there are many (1000s) hole-representing polygons.

    Currently we have to select them by hand which is error prone and somewhat time consuming.

    What I was trying to ask is whether there is/will be
    a method which will select all these polygons automatically.

    -Till
  • edited September 2009

    Hi Till,

    I had the feeling that the shapewise booleans are not well documented and they would need some detailed explanation. Sorry for assuming that you have not tried them.

    I guess I now understand better what you need. I could offer a solution like some "cancellation" of overlapping regions, i.e. where two shapes overlap, a "void" is generated. In other words, some kind of "intra-layer XOR". Would that fulfill your requirements?

    Best regards,

    Matthias

  • edited 1:29AM
    Hi Matthias,

    that would be perfect. Thanks.

    - Till
  • edited September 2009

    Hi Till,

    I have created a Ruby script that emulates the functionality (requires version 0.18 at least).

    It registers a new function "Overlaps To Void" in the "Edit/Selection" menu. It works on the selection (not the whole layer) - but since you can select "everything" by dragging the selection rectangle around the whole layout with only the required layer visible I think it is useful as well. If that is still to tedious, the script can be adjusted to work on "everything" on the selected layer.

    Basically is detects overlaps and subtracts them from the original layer.
    To install it, copy the script to the installation directory with a ".rbm" suffix, i.e. "overlaps_to_void.rbm" or call KLayout with the script given in a "-rm" option (klayout -rm overlaps_to_void.rbm ...).

    Here is the script:

    class MenuAction < RBA::Action
      def initialize( title, shortcut, &action ) 
        self.title = title
        self.shortcut = shortcut
        @action = action
      end
      def triggered 
        @action.call( self ) 
      end
    private
      @action
    end
    
    menu_handler = MenuAction.new( "Overlaps To Void", "" ) do 
    
      app = RBA::Application.instance
      mw = app.main_window
    
      lv = mw.current_view
      if lv == nil
        raise "Overlaps To Void: No view selected"
      end
    
      # start transaction for "undo"
      lv.transaction( "Overlaps To Void" )
    
      begin
    
        # because objects might be referenced multiple times (thru different hierarchy paths)
        # we must first copy and then delete them
    
        input_polygons = []
    
        output_layer = nil
    
        lv.each_object_selected do |sel|
          shape = sel.shape
          if shape.is_path? || shape.is_box? || shape.is_polygon?
    
            # Save "area type" shapes in the selection to polygons and delete them
            input_polygons.push(RBA::Polygon::from_dpoly(shape.polygon.transformed_cplx(sel.trans)))
            cv = lv.cellview(sel.cv_index)
            source = cv.layout.cell(sel.cell_index)
            source.shapes(sel.layer).erase(shape)
    
            # Remember the input layer for the output
            output_layer ||= sel.layer
    
          end
        end
    
        if input_polygons.size > 0
    
          # perform the "overlaps to void" operation
          # first step: detect overlaps
          ep = RBA::EdgeProcessor::new
          overlaps = ep.merge_to_polygon(input_polygons, 1, false, false)
    
          # second step: remove the overlaps from original
          result = ep.boolean_to_polygon(input_polygons, overlaps, RBA::EdgeProcessor::mode_anotb, true, false)
    
          # write the result to the output
          output_cv = lv.cellview(lv.active_cellview_index)
          target = output_cv.cell.shapes(output_layer)
          result.each { |p| target.insert(p) }
    
        end
    
      ensure
    
        # always execute that code:
    
        # commit transaction
        lv.commit
    
        # clear selection and cancel all other edit operations, so 
        # nothing refers to shapes that might have been deleted.
        lv.cancel
    
      end
    
    end
    
    app = RBA::Application.instance
    mw = app.main_window
    
    menu = mw.menu
    menu.insert_item("edit_menu.selection_menu.intersection", "overlaps_to_void", menu_handler)
    
  • Thanks from a user 12 years later! Very useful for .dxf to .gds conversions that produce polygons where a void is intended.

Sign In or Register to comment.