Getting information about each array element of an instance of CellInstArray

edited January 2016 in Ruby Scripting

I have a cell, call it 'top'. In top is an instance of CellInstArray, call it 'array_inst'.

How does one conveniently get information about each element placed by array_inst?
I would like to get an array of bounding boxes for the elements in array_inst, but don't see the methods that I might use to do it. I can do the math if necessary, but it seems like something that would already exist.

Any pointers?

Any help is greatly appreciated.
Thanks,
Dave

Comments

  • edited January 2016

    I did the math. The following code returns the origins of each
    instance and from that I get the bounding boxes:

    # This require is for the next aref-related methods.
    require 'matrix'
    
    # Returns an array of CellInstArray attributes:
    #   * the displacement, _disp_, an RBA::Point instance
    #   * the shift vector, _a_, a Vector instance.
    #   * the shift vector, _b_, a Vector instance.
    #   * the number of steps in 'a', _na_, a FixNum
    #   * the number of steps in 'b', _nb_, a FixNum
    # The Vector class is defined in the Ruby Standard Library,
    # 'matrix'.
    def self.aref_info(aref)
        disp    = aref.trans.disp
        a_shift = aref.a
        a_shift = Vector[a_shift.x, a_shift.y]
        b_shift = aref.b
        b_shift = Vector[b_shift.x, b_shift.y]
        na      = aref.na
        nb      = aref.nb
        [ disp, a_shift, b_shift, na, nb ]
    end
    
    # Given CellInstArray instance attributes, _disp_, _a_shift_,
    # _b_shift_, _na_, and _nb_, return the origins of each
    # cell placement.  Note that a_shift_ and _b_shift_ are
    # expected to be Vector instances as defined by 'matrix'
    # of the Ruby Standard Library (as of 1.9.3).  See the
    # method *aref_info* in this module.
    def self.aref_origins(disp, a_shift, b_shift, na, nb)
        origins = []
        na.times do |i|
            nb.times do |j|
                tmp_vector = i * a_shift + j * b_shift
                origins << disp + RBA::Point.new(*tmp_vector)
            end
        end
        origins
    end
    
  • edited November -1

    Hi Dave,

    in fact KLayout offers the functionality you require itself. The equivalent of the matrix is the "transformation":

    • RBA::Trans for a simple transformation (rotation by multiples of 90 degree, no magnification) in integer coordinate space
    • RBA::DTrans for the same in floating-point coordinate space
    • RBA::CplxTrans for the enhanced transformation (rotation by arbitrary angles, magnification supported) in integer coordinate space
    • RBA::DCplxTrans for the same in floating-point coordinate space

    Transformations can be combined using the "*" operator which means you can simply combine a translation formed from the array element vector and the basic transformation.

    There is no particular "vector" object (yet) - the "point serves as the container for a x/y coordinate pair:

    • RBA::Point for a point or vector in integer coordinate space
    • RBA::DPoint for a point or vector in floating-point coordinate space

    Points can be multiplied with scalars and added/subtracted.

    Here is some code that puts together these pieces. It will print the expanded instantiations of the array:

    # Loop over all selected objects
    RBA::LayoutView::current.each_object_selected do |sel|
    
      # Only treat cell instance arrays
      if sel.is_cell_inst? && sel.inst.is_regular_array?
    
        # Two nested loops: one for the "a" and one for the "b" axis
        sel.inst.na.times do |ia|
          sel.inst.nb.times do |ib|
    
            # Compute the effective transformation by combining a translation with the basic transformation.
            # To be as generic we use complex transformations which cover magnification and arbitrary rotation
            # angles. 
            # Note that the translation is formed by first creating a simple transformation and converting it
            # to a complex one in the second step.
            translation = RBA::CplxTrans::new(RBA::Trans::new(sel.inst.a * ia + sel.inst.b * ib))
            basic = sel.inst.cplx_trans
            t = translation * basic
            puts "Instance [#{ia},#{ib}] of cell #{sel.inst.cell.name} with transformation #{t.to_s}"
    
          end
        end
    
      end
    
    end
    

    Matthias

  • edited November -1

    Thank you Matthias for your incite and assistance. You are always
    remarkably helpful.

    It might be handy to have iterator methods in CellInstArray. This
    allows each element of the array to be presented to another tool.
    In my case, I needed three things: origin, bbox, and center of
    instance bbox information.
    Though one can write such things, it cost me hours to write the code
    and tests.

    Thanks,
    Dave

  • edited November -1

    Hi Dave,

    you're right about the iterator. In fact, internally there is such a thing. I just did not consider it important to be exported to the script environment.

    BTW: if you plan to work with the shapes inside the instances, you can use the "RecursiveShapeIterator" concept which will provide deep iteration over the layout's shapes. This will also include expansion of cell arrays.

    Regards,

    Matthias

  • edited November -1

    Good to know.
    Thanks,
    Dave

Sign In or Register to comment.