Proposal for new ruler variation (Arc)

edited September 2021 in KLayout Development

Hi folks,

I have a proposal for a new ruler variation to measure the radius of an arc. The method, I think of, would be, to click three points on the curvature of an arc, which then produces an arc ruler, which shows the radius of this arc, maybe with a nice arrow pointing to the mid of the curvature. I already wanted to write a small ruby script myself, but currently I am totally overloaded with other work, so I simply throw my idea in the ring.

So please tell me, what you think about the idea and if you know some better or easier way of determing the radius of an arc in klayout, please tell me. Have a very nice time.

Comments

  • edited September 2021

    @floz Nice proposal, thanks.

    It will however not be easy to implement as rulers currently have a maximum number of two points. But basically it should be possible to extend annotations to three points as well.

    I have created a ticket for this request, but I can't promise a quick implementation: https://github.com/KLayout/klayout/issues/906

    Arcs are not common in (usual) chip design, so curved features are not well supported as of now. I wonder if there is a broader interest here. Maybe others want to comment?

    Thanks,

    Matthias

  • I confirmed that I have sometimes to follow some design rules with a defined radius ... that is double checked by my subcontractor ... this arc ruler definitly has some application !

    Laurent

  • Hello Matthias,
    We use circles to measure the correct radius - an arc ruler is always on top of our designers wish list.
    All our BJT and MOS use radius and this is our main working area for klayout.
    Best Regards,
    Andy

  • Ok, understood :)

    It's on the issue tracker. Stay tuned.

    Matthias

  • edited September 2021

    Hi Matthias,

    fortunately, I had some time to play around with Python and wrote code to implement the ARC ruler in KLayout. The usage is pretty easy: Choose ARC Ruler from menu, click three points on the arc and get a circle style ruler with center and radius of the arc. Please see code below.

    # Python3 implementation of the approach
    from math import sqrt
    import pya
    coords = []
    h = 0
    k = 0
    r = 0
    
    # Enter your Python code here ..
    # Register this macro as "autorun" to enable the plugin
    
    # First thing is to implement a "plugin factory". This 
    # object is asked to provide a plugin for each view
    
    class GetXYOnMouseClickPluginFactory(pya.PluginFactory):
    
      def __init__(self):
        super(GetXYOnMouseClickPluginFactory, self).__init__()
        pya.MainWindow.instance()  # (workaround for bug 191)
        self.register(-1000, "ARCRuler", "ARC Ruler")
    
      def create_plugin(self, manager, root, view):
        return GetXYOnMouseClickPlugin()
    
      # Keeps the singleton instance
      instance = None
      
    GetXYOnMouseClickPluginFactory.instance = GetXYOnMouseClickPluginFactory()
    
    # Second thing is the actual plugin
    
    class GetXYOnMouseClickPlugin(pya.Plugin):
    
      def __init__(self):
        super(GetXYOnMouseClickPlugin, self).__init__()
        pass
    
      def activated(self):
        pya.MainWindow.instance().message("Click on point to start arc ruler", 10000)
    
      def deactivated(self):
        pya.MainWindow.instance().message("", 0)
    
      def mouse_click_event(self, p, buttons, prio):
        # This is where everything happens
        if prio:
          pya.MainWindow.instance().message("Mouse Clicked at X/Y = " + str(p), 10000)
          coords.append([p.x, p.y])
          if len(coords) == 3:
            #End mouse process coords entered
            self.ungrab_mouse()
            pya.MainWindow.instance().cancel()
            pya.MainWindow.instance().menu().action("@toolbar.select").trigger()
            #Process Coords
            process_coords(coords)
          return True
        return False
    
    # Function to find the circle on
    # which the given three points lie
    def findCircle(x1, y1, x2, y2, x3, y3) :
      x12 = x1 - x2;
      x13 = x1 - x3;
    
      y12 = y1 - y2;
      y13 = y1 - y3;
    
      y31 = y3 - y1;
      y21 = y2 - y1;
    
      x31 = x3 - x1;
      x21 = x2 - x1;
    
      # x1^2 - x3^2
      sx13 = pow(x1, 2) - pow(x3, 2);
    
      # y1^2 - y3^2
      sy13 = pow(y1, 2) - pow(y3, 2);
    
      sx21 = pow(x2, 2) - pow(x1, 2);
      sy21 = pow(y2, 2) - pow(y1, 2);
    
      f = (((sx13) * (x12) + (sy13) *
            (x12) + (sx21) * (x13) +
            (sy21) * (x13)) // (2 *
            ((y31) * (x12) - (y21) * (x13))));
    
      g = (((sx13) * (y12) + (sy13) * (y12) +
            (sx21) * (y13) + (sy21) * (y13)) //
            (2 * ((x31) * (y12) - (x21) * (y13))));
    
      c = (-pow(x1, 2) - pow(y1, 2) -
           2 * g * x1 - 2 * f * y1);
    
      # eqn of circle be x^2 + y^2 + 2*g*x + 2*f*y + c = 0
      # where centre is (h = -g, k = -f) and
      # radius r as r^2 = h^2 + k^2 - c
      h = -g;
      k = -f;
      r = sqrt(pow(h, 2) + pow(k, 2) - c);
    
      return h, k, r
    
    def process_coords(coords):
      # TODO: put in your code to do what you like to do below
      # Unlimited things can be done
      app =  pya.Application.instance()
      mw =  app.main_window()
      view = mw.current_view()
      ant =   pya.Annotation()
      
      h, k, r = findCircle(coords[0][0], coords[0][1], coords[1][0], coords[1][1], coords[2][0], coords[2][1])
    
      ant = pya.Annotation()
      ant.p1 = pya.DPoint(h - r, k - r)
      ant.p2 = pya.DPoint(h + r, k + r)
    
      ant.style = pya.Annotation.StyleRuler
      ant.outline = pya.Annotation.OutlineEllipse
      ant.main_position = pya.Annotation.PositionCenter
      ant.fmt = 'M = ' + str(h) + ', ' + str(k) + ', r = ' + str(round(r, 1))
      ant.fmt_x = ''
      ant.fmt_y = ''
    
      view.insert_annotation(ant)
    
      coords.clear()

  • edited October 2021

    @floz I'm impressed! :)

    Thanks for sharing the code!

    The ruler does not have the original points, so you cannot fine adjust it by dragging them. But maybe this solution is already good for a lot of use cases.

    Thanks again,

    Matthias

  • Perfect if dragging would be possible - thanks a lot for sharing.

Sign In or Register to comment.