How do you rotate a object by a degrees other than r0,r90,r180,r270 scripting

edited November 2015 in Ruby Scripting

How do you use trans to rotate a object at a certain degree. Using something like code below with r0,r90,r180,r270 works fine.

   t = RBA::Trans::new(RBA::Trans::r90,mirror, x, y) 

How would I rotate at 45 degrees or 22 degrees. Code below does not work, it seems like it rounds to some 90 degree angle.

   t = RBA::Trans::new(22,mirror, x, y)

From the transformation page it says a arbitrary angle is fine. In the GUI if i select object properties->Geometry->Rotation angle and set it to 22 degrees it works fine. Is there no way to do this with scripting?

Thanks,
Keil

Comments

  • edited November -1

    You need to use CplxTrans or ICplxTrans class instead. Trans only supports those four rotations.

    Why? My guess is the reasoning is this. Trans will always map a polygon on to a polygon, perfectly snapped to the grid, without changing any of the vertices. CplxTrans on the other hand has the potential for slightly changing your polygon, by snapping its vertices to the new grid points. Therefore there is some (small, depending on what matters to you) risk involved. So, it is a separate class. So that you know whenever you use Trans you are safe from that. In practice this rarely matters since your grid is usually 1nm and your shapes are usually many microns large, so a snap change of 1nm over many microns doesn't matter.

  • edited November 2015

    The code below works when using trans.

      # Create a PCell variant cell
      pcell_var = ly.add_pcell_variant(lib, pcell_decl.id, pv)
    
      t = RBA::Trans::new(RBA::Trans::r90,false, 10.0, 20.0)
    
      #Get top cell 
      ly.top_cells.each { |curCell|
          pcell_inst = ly.cell(curCell.cell_index).insert(RBA::CellInstArray::new(pcell_var, t))
        break
      }
    

    This code below does not work using ICplxTrans. I get error of "No overload with matching arguments in CellInstArray::initialize".

      # Create a PCell variant cell
      pcell_var = ly.add_pcell_variant(lib, pcell_decl.id, pv)
        t = RBA::ICplxTrans::new(1.5, 90.0, false, 10.0, 20.0)
    
      #Get top cell 
      ly.top_cells.each { |curCell|
          pcell_inst = ly.cell(curCell.cell_index).insert(RBA::CellInstArray::new(pcell_var, t))
        break
      }
    

    What has to be done different for LCplxTrans?

  • edited November 2015

    Hi David (and all),

    the reason for the differentiation between the different transformation types is twofold: historical and efficiency. I guess I should go for the efficiency claim - that looks smarter :-)

    Anyway, the RBA::Trans object

    • is leaner: it requires single displacement and a one-byte orientation code
    • does not involve floating-point arithmetics, hence no rounding and comparison issues
    • maintains the shape identity: boxes stay boxes, manhattan polygons stay manhattan polygons
    • maintains the data representation: applying an integer transformation to integer coordinates will render integer coordinates without loss of precision
    • does not imply a continuum of variants - apart from displacement, only 8 variants are possible
    • is common: the big VLSI layouts are entirely made from this kind of transformation
    • was there first: in the first version, there was only a simple transformation because for the previous reason.

    In contrast to that, the RBA::CplxTrans object is more general, but also less efficient and in the strict sense will transform integer coordinates into floating-point ones. Hence there are more variants for that transformation:

    • RBA::DCPlxTrans will transform floating-point to floating-point types
    • RBA::CplxTrans will transform integer to floating-point types without rounding
    • RBA::ICplxTrans will transform integer to integer types with rounding

    As you can see from the description, the RBA::Trans transformation is a good-natured one while the RBA::CplxTrans ones are alightly stubborn objects. Using them comes with some side effects in general although of course the simple transformation is a special case of them. I think it makes some sense to encourage using the simple transformation where possible. If you don't care about efficiency and you are prepared for a few surprises, you can also use the complex transformations of course. I think, all functions accepting a simple transformation will also accept a complex one.

    This is basically the long explanation of what David was already suspecting. Not having to deal with rounding topics contributes to efficiency since you don't have to toughen your code against rounding differences.

    Thanks and best regards,

    Matthias

  • edited November -1

    Ok that makes sense and gives good reason to have multiple different methods. Should this code below work with ICplxTrans.

    module MyMacro
      # Program opens a layout and adds a Serial number with given layer,dataType and magnification
      include RBA
      inputFile="700-2000-00Atemp.gds"
      outputFile="my_layout2.gds"
      mySN="SN_SAMPLE"
      layer=1
      dataType=10
      magnification=600
      ly = RBA::Layout::new
      ly.read(inputFile)
      # create new cell TOP
      #cell_index = ly.add_cell($SN)
      cell = ly.cell(ly.top_cell.cell_index)
    
    
      # Find the lib
      lib = RBA::Library.library_by_name("Basic")
      lib || raise("Unknown lib 'Basic'")
    
      # Find the pcell
      pcell_decl = lib.layout.pcell_declaration("TEXT")
      pcell_decl || raise("Unknown PCell 'TEXT'")
    
    
      # Set the parameters (text string, layer to 10/0, magnification to 2.5)
      param = { "text" => mySN, "layer" => RBA::LayerInfo::new(layer.to_i, dataType.to_i), "mag" => magnification.to_i }
    
      # Build a param array using the param hash as a source.
      # Fill all remaining parameter with default values.
      pv = pcell_decl.get_parameters.collect do |p|
        param[p.name] || p.default
      end
    
      # Create a PCell variant cell
      pcell_var = ly.add_pcell_variant(lib, pcell_decl.id, pv)
    
    
      #t = RBA::Trans::new(RBA::Trans::r180,false, 10.0, 20.0)
      t = RBA::ICplxTrans::new(1.5, 90.0, false, 10.0, 20.0)
    
    
      #Get top cell 
      ly.top_cells.each { |curCell|
          pcell_inst = ly.cell(curCell.cell_index).insert(RBA::CellInstArray::new(pcell_var, t))
        break
      }       
      ly.write(outputFile)
    end
    

    I get error of "No overload with matching arguments in CellInstArray::initialize" when using ICplxTrans but works fine when using Trans.

    Thanks,
    Keil

  • edited November -1

    Yes there is no initializer for ICplxTrans as the 2nd argument of CellInstArray -- just one for Trans as the 2nd argument, or for CplxTrans as the 2nd argument. Docs

    Can you use CplxTrans instead? Usage should be similar.

    David

  • edited November -1

    Hi all,

    yes, RBA::CplxTrans is the object mainly used within the database. It's the one that takes the integer-typed database objects and provides a transformation to a floating point object without loss of precision. But strictly speaking the result of such a transformation is not an object that can be put into the database without casting it to integer coordinates again.

    If you need an RBA::ICplxTrans which provides a lossy, but type-preserving transformation, you can use RBA::ICPlxTrans::from_trans to create one from a RBA::CplxTrans.

    Matthias

  • edited November -1

    Thanks guys. Changing to CplxTrans works great.

      t = RBA::CplxTrans::new(1.5, 22.0, false, 10.0, 20.0)
    

    Thanks,
    Keil

Sign In or Register to comment.