Drawing an array of rectangles in separate layers

edited May 2015 in Ruby Scripting
Hello,

I'm very new to Ruby language and KLayout. For a project, I need to generate a series of rectangles (each in a different layer) in KLayout using Macro development. This way, depending on an input/variable assignment from the user, say N, the program can generate N Rectangles in N different layers. Something like this figure:

http://i60.tinypic.com/xayw6.jpg

Comments

  • edited November -1

    Hi,

    you'll find a lot of details in the documentation about Ruby script programming: http://klayout.de/doc/programming/index.html.

    Here is a simple script that creates a layout with one layer and produces a rectangle on this layer. You can extend that script using a loop to create the layers and formulas to compute the rectangle positions and dimensions:

    # save this script to "generate.rb" and run it with "klayout -r generate.rb -b"
    layout = RBA::Layout::new
    
    # database unit 1nm:
    layout.dbu = 0.001
    
    # create a top cell
    top = layout.cell(layout.add_cell("TOP"))
    
    # create a layer: layer number 1, datatype 0
    layer = layout.insert_layer(RBA::LayerInfo::new(1, 0))
    
    # create one rectangle with lower-left coordinates at 0,0
    # and width of 1um and heigth of 2um (coordinates are in
    # database units)
    top.shapes(layer).insert(RBA::Box::new(0, 0, 1000, 2000))
    
    # write to x.gds
    layout.write("x.gds")
    

    Matthias

  • edited November -1
    Hello Matthias,

    Thank you so much for your help!

    I managed to generate the following array of rectangles:
    http://tinypic.com/r/z0fop/8

    This was the code I used:

    layout = RBA::Layout::new

    # database unit 1nm:
    layout.dbu = 0.001

    layer = []


    x=1
    32.times {
    layer_id= layout.insert_layer( RBA::LayerInfo.new(x,0) )
    ln = RBA::LayerPropertiesNode::new
    ln.width = 1
    ln.source_layer_index = layer_id

    layer.push( layer_id )
    x+=1
    }

    layer.push(layer[31])

    top_id = layout.add_cell("TOP")
    top = layout.cell(top_id)


    y=0
    x=0
    16.times {
    box = RBA::Box::new( x , y , (x + 1) , (x + 2) )
    top.shapes( layer[x] ).insert( box )
    x += 1
    }

    16.times {
    box = RBA::Box::new( x , y , (x + 1) , (33 - x) )
    top.shapes( layer[x] ).insert( box )
    x += 1
    }


    layout.write("final.dxf")

    Now, I need to use this idea to generate a circle, such that an array of rectangles fit into a circular boundary.

    Could you please suggest for I can implement it?

    Thanks again!

    Pallavi
  • edited May 2015

    I haven't tried your code, but in answer to your question (plus a couple other thoughts):

    • When pasting code here, indent each line by at least four spaces, and choose the "Markdown" radio button below the textbox where you are typing. See http://daringfireball.net/projects/markdown/
    • One of your questions is how to draw a circle. Here's one way (untested)

    =

    include RBA
    dbu = layout.dbu
    radius = 10 #um
    num_pts = 100
    dtheta = 2*Math::PI / num_pts
    pts = []
    num_pts.times { |i|
      x = radius * Math.cos(i*dtheta)
      y = radius * Math.sin(i*dtheta)
      pts << Point.new(x/dbu,y/dbu)
    }
    circle = Polygon.new(pts)
    top.shapes(circle_layer).insert(circle)
    

    You could also instance the Basic.CIRCLE PCell instead. For that, google some examples, there are some on this forum. But I recommend the above method for you.

    • Your second question was how to make such an array of rectangles fit inside the circle. I'm sure you can figure out how to make an array of heights (let's call it 'h') such that h[i] = 2*Math.sqrt(radius^2 - x[i]^2) (the equation of a circle, times two, since I presume that's what you meant), where i is the array index and x is your array of horizontal positions of the rectangles. Then with this array in hand you just apply the elements sequentially when you create the boxes. It's just a bit of math, let us know if you're really stuck.

    • Instead of x=1;32.times { [some statements here]; x+=1}, use 32.times { |x| [some statements here] }. It is the same but the "ruby way". But, in this case x starts at 0. So replace x with x+1 in your "[some statements here]"

    Hope this helps,

    David

  • edited November -1

    Hi all,

    @David: thanks again for you notes :-)

    I have not really understood the request. Do you mean you want to select those rectangles that fit into a circle (like a wafer map)?

    You have a full programming language available - producing shapes is just one feature. Apart from that you have access to all mathematical features within Ruby, so basically you should be able to code whatever you need to.

    Matthias

  • edited November -1
    Pallavi,

    I'm not sure how to code it, but you could build a straight array of the rectangles, then with a bit of maths work out how far each rectangle is away from a centre point. Any rectangles over a certain distance could be deleted, thus forming the circle you require.

    Pete
Sign In or Register to comment.