writing macro for analitycal functions design

edited December 2016 in General

I would much apritiate help on constructing a design based on an analytical function:
size= 2x2 mm. shape of layout (f):f(x,y)=0.5+0.5*sign(cos(a*x-b*atan2(y,x))), where a&b are consts.

Thank you for any help,



  • edited December 2016

    Hi Shlomi,

    How can a such a function define a shape (polygon)? Do you mean "a polygon which includes all points where f(x,y) = 1"?

    That will be tricky because KLayout is no equation solver.

    But here is an approach:

    atan2(y,x) will give you the angle the current point (x,y) forms with the x axis. For all points along a line with a given angle s this will be a constant.

    So we can reformulate your function in polar coordinates:

    f(s,r) = 0.5+0.5*sign(cos(a*cos(s)*r-b*s))

    This function will be 1 for

    cos(u) > 0 (u = a*cos(s)*r-b*s)


    -PI/2 < u-2*PI*N < PI/2 (N = ... -2,-1,0,1,2 ...)

    Since u is linear with r this will basically become a kind of periodic dark/clear pattern: a transition from clear to dark will happen at

    u = -PI/2 + 2*PI*N

    The opposite transition will happen at

    u = PI/2 + 2*PI*N

    So each of these conditions renders a function r(s):

    r(s) = ((-PI/2+2*PI*N)+b*s)/(a*cos(s))    [ clear to dark ]
    r(s) = ((PI/2+2*PI*N)+b*s)/(a*cos(s))     [ dark to clear ]


    x = r*cos(s)
    y = r*sin(s)

    This allows you to compute a x/y trajectory which defines the border between clear and dark and another one which defines the border between dark and clear. If we connect both trajectories properly we can make them form a closed polygon. Having this is the first step towards your solution. Here is some code that illustrates that approach:

    layout = RBA::Layout.new
    top = layout.create_cell("TOP")
    l1 = layout.layer(1, 0)
    b = 0.5
    a = 1.0
    harmonics = 11
    harmonics.times do |n|
      n -= harmonics/2
      pts1 = []
      pts2 = []
      points = 100
      (points - 1).times do |i|
        # s goes from -PI/2 to PI/2 (-PI/2 and PI/2 not included)
        s = ((i + 1).to_f / points - 0.5) * Math::PI
        r1 = ((2.0*n-0.5)*Math::PI+b*s)/(a*Math.cos(s))
        r2 = ((2.0*n+0.5)*Math::PI+b*s)/(a*Math.cos(s))
        x1 = (0.5 + r1*Math.cos(s)/layout.dbu).to_i
        y1 = (0.5 + r1*Math.sin(s)/layout.dbu).to_i
        pts1 << RBA::Point::new(x1, y1)
        x2 = (0.5 + r2*Math.cos(s)/layout.dbu).to_i
        y2 = (0.5 + r2*Math.sin(s)/layout.dbu).to_i
        pts2 << RBA::Point::new(x2, y2)
      if n == 0
        poly = RBA::Polygon::new(pts1 + pts2)
        poly = RBA::Polygon::new(pts1 + pts2.reverse)
    mw = RBA::Application.instance.main_window
    cv = mw.view(mw.create_view)
    cv.show_layout(layout, true)

    Maybe that leads somewhat further. Next thing then will be to clip this down to your target rectangle with a boolean operation. But remember, KLayout is not MatLab, not even "MatLab light". And some of the solutions look kind of naughty, but maybe that's just my fantasy ...

    BTW: you're not a student trying to fool me into solving your quiz problem, are you? Your teacher is going to hate me for this ...


Sign In or Register to comment.