Perimeter

edited March 2013 in Ruby Scripting
Hello Everyone,

I recently looked at the area script which I was able to use in KLayout. Now I am trying to find the perimeter of shapes (some shapes even have curves) in KLayout. When I copy and paste the code that was provided in this forum, it doesn't work. I get a lot of errors about 'db' and it doesn't recognize many of the methods such as begin_edge(), etc.

SO I tried making my own code, and I am unsuccessful. I was wondering if someone could take a look at it for me, and let me know where I am going wrong.

Thanks in advance, Natalie

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

$compute_total_perimeter = MenuAction.new( "Compute perimeter of selected shapes", "" ) do

app = RBA::Application.instance
mw = app.main_window

lv = mw.current_view
if lv == nil
raise "No view selected"
end

total_perimeter = 0.0

lv.each_object_selected do |obj|

shape = obj.shape
layout = lv.cellview(obj.cv_index).layout

if shape.is_polygon? || shape.is_box? || shape.is_path?
poly=shape.path
shape.each_point
edge=poly.path_bgnext

while (edge!=poly.path_endext)
total_perimeter+=edge.path_width

end

end



RBA::MessageBox.info("Total points", "Total points of selected object is #{total_perimeter} microns", RBA::MessageBox.b_ok)

end

app = RBA::Application.instance
mw = app.main_window

menu = mw.menu
menu.insert_separator("tools_menu.end", "name")
menu.insert_item("tools_menu.end", "compute_total_perimeter", $compute_total_perimeter)

Comments

  • edited November -1

    Hi Natalie,

    please see me comments in the other forum entry. The problem was that this this discussion was basically about C++ code and you can't mix that with Ruby.

    Here is the correct code:

    total_perimeter = 0.0
    
    lv.each_object_selected do |obj|
    
      # TODO: check, whether the selected object is an instance ...
      shape = obj.shape
      if shape.is_polygon? || shape.is_box? || shape.is_path?
        shape.polygon.each_edge { |e| total_perimeter += e.length }
      end
    
    end
    

    Regards,

    Matthias

  • edited November -1
    Thank you so much for your help Matthias!

    The code runs and works, but there is one a slight problem. The calculated perimeter is always 1000 times larger than the actual perimeter...

    Is it possible that it doesn't know when the final edge is?

    Thanks again for all your help, Natalie
  • edited November -1
    Oh, I was able to fix.

    Here is now my corrected code. Thanks again Matthias!

    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

    $compute_total_perimeter = MenuAction.new( "Compute total perimeter of selected shape", "" ) do

    app = RBA::Application.instance
    mw = app.main_window

    lv = mw.current_view
    if lv == nil
    raise "No view selected"
    end

    total_perimeter = 0.0

    lv.each_object_selected do |obj|

    shape = obj.shape
    layout = lv.cellview(obj.cv_index).layout

    if shape.is_polygon? || shape.is_box? || shape.is_path?
    shape.polygon.each_edge { |e| total_perimeter += e.length*obj.trans.mag*layout.dbu }
    end

    end

    RBA::MessageBox.info("Total perimeter", "Total perimeter of selected object is #{total_perimeter} microns", RBA::MessageBox.b_ok)

    end

    app = RBA::Application.instance
    mw = app.main_window

    menu = mw.menu
    menu.insert_separator("tools_menu.end", "name")
    menu.insert_item("tools_menu.end", "compute_total_perimeter", $compute_total_perimeter)
  • edited November -1

    Hi Natalie,

    yes you're right, The DBU multiplication is doing the trick and again you're right that you have to take the magnification in the instantiation path into account. I forgot that. Thank you for the hint.

    Just to add some final remark: you can optimize the perimeter loop somewhat by doing the multiplication outside the loop. Ruby is not a fast language, so that might be a good idea:

    perimeter = 0
    shape.polygon.each_edge { |e| perimeter += e.length }
    total_perimeter += perimeter * obj.trans.mag * layout.dbu
    

    Regards,

    Matthias

Sign In or Register to comment.