I am a new KLayout user. Trying to make a macro using ruby which requires X and Y co-ordinate of the point where mouse is clicked. Any help is really appreciated
I have made some modifications to the example Matthias provided ,
one thing I noticed you have to load the script twice
before it works other wise it crashes ??? Reason I have no idea.
This works in Python not sure how to get the same script to work in Ruby,
it's a mystery, mouse functions should not be this elaborate.
As discussed in this example https://www.klayout.de/forum/discussion/1151/capture-a-mouse-click-and-its-location
import pya
# 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, "get_xy", "Get X/Y")
def create_plugin(self, manager, root, view):
return GetXYOnMouseClickPlugin()
# Keeps the singleton instance
instance = None
# Create and store the singleton instance
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 Get X/Y", 10000)
def deactivated(self):
pya.MainWindow.instance().message("", 0)
def mouse_click_event(self, p, buttons, prio):
# This is where everything happens
if prio:
#print("Mouse clicked at X/Y" + str(p))
pya.MainWindow.instance().message("Mouse Clicked at X/Y = " + str(p), 10000)
return True
return False
To combat the behavior change noted here, ruler snap to vertex, I want to automate the actions of the ruler. Specifically:
1. Popup dialog for user to pick 3 vertices of a polygon.
2. on each mouse click, capture the x,y coordinate of the mouse location in drawn space and the nearest x,y coordinate of the selected vertex. They must agree with some tolerance.
3. After 3 points found, calculate the x,y coordinate of the midpoint of the hypotenuse of the triangle defined by the 3 points.
4. Repeat for the next polygon.
5. Calculate the distance between the 2 found centers.
Interesting things on rulers https://www.klayout.de/doc-qt5/code/class_Annotation.html#method89
Annotation objects provide a way to attach measurements or descriptive information to a layout view.
Annotation objects can appear as rulers for example.
Annotation objects can be configured in different ways using the styles provided.
By configuring an annotation object properly, it can appear as a rectangle or a plain line for example.
See Ruler properties for more details about the appearance options.
Below are Python/Ruby Versions of this
Update Fixed the Python
#Python Version Ruler Annotation
app = pya.Application.instance()
mw = app.main_window()
view = mw.current_view()
ant = pya.Annotation()
ant.p1 = pya.DPoint(0, 0)
ant.p2 = pya.DPoint(100, 0)
ant.style = pya.Annotation.StyleRuler
view.insert_annotation(ant)
#Ruby Version Ruler Annotation this works
app = RBA::Application.instance
mw = app.main_window
view = mw.current_view
ant = RBA::Annotation::new
ant.p1 = RBA::DPoint::new(0, 0)
ant.p2 = RBA::DPoint::new(100, 0)
ant.style = RBA::Annotation::StyleRuler
view.insert_annotation(ant)
I am using this code to find the center of the two shapes and measure the distance between them. How do I save the info of coordinate for finding the center and calculation of the distance between them
at the end. Because with a layout open it's executed immediately and at this point the GetXYOnMouseClickPlugin class isn't defined. With this fix I don't see any crashes (Ubuntu 20, version 0.26.11).
Apart from that: "mouse functions should not be this elaborate" ... we had this topic before. If anyone has a better solution, please drop me a pull request on GitHub and I'll take a look. After all it's open source and it's not my responsibility to make you happy. My focus is on architecture. KLayout is a highly scalable application. This does not come for free.
Some updates regarding interesting things with rulers
Code below allows too ad multi-segment rulers
It's buggy at best at the present time,
Need too add Marker shape to follow Entered path and Snap.
Double click First mouse button, then Right Click end's Point Entry and adds annotated Ruler.
At process_coords():
# TODO: put in your code to do what you like to do below #Unlimited things can be done
If anybody has ideas too follow the coords for the marker layer and snap
Please feel free to update. My mouse is entering an limited life span
Regards
Tracy
#Tracy Groller
#3/3/21
#Prelimaniary Code, Rough at best and Buggy
#Testing Ideas :=]
#Process Rulers with Multi Coords
#Need too add Marker and Snap
#Adds Right Click to end , no need to select another tool
#This will put a Ruler Path in the Tool Bar
import pya
import gc
app = pya.Application.instance
buffer = []
class GetXYOnMouseClickPluginFactory(pya.PluginFactory):
def __init__(self):
super(GetXYOnMouseClickPluginFactory, self).__init__()
pya.MainWindow.instance() # (workaround for bug 191)
self.register(-1000, "get_xy", "Ruler Path")
def create_plugin(self, manager, root, view):
return GetXYOnMouseClickPlugin()
# Keeps the singleton instance
instance = None
# Create and store the singleton instance
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 Ruler", 10000)
def mouse_click_event(self, p, buttons, prio):
# This is where everything happens
#self.set_cursor(pya.Cursor.Cross)
if buttons == pya.ButtonState.RightButton :
#Right Click ends it process coords entered
self.ungrab_mouse()
pya.MainWindow.instance().cancel()
pya.MainWindow.instance().menu().action("@toolbar.select").trigger()
#Process Coords
process_coords()
if prio:
pya.MainWindow.instance().message("Ruler Points are = " + str(p), 10000)
x = p.x
y = p.y
data(buffer,x,y)
return True
return False
#buffer = []
def data(buffer,x,y):
buffer.append([x,y])
def process_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()
wdt = 10
blen = len(buffer)
prev = buffer[0]
curr = buffer[1]
print(buffer)
#Process Prev and Curr and Nxt coords
for nxt in buffer[2:]:
print(f'prev: {prev}, curr: {curr}, next: {nxt}')
prev = curr
curr = nxt
x1p = prev[0]
y1p = prev[1]
x1c = curr[0]
y1c = curr[1]
#Testing
#x1n = nxt[0]
#y1n = nxt[1]
#print("Xp = ", x1p)
#print("Yp = ", y1p)
#print("Xc = ", x1c)
#print("Yc = ", y1c)
#print("Xn = ", x1n)
#print("Yn = ", y1n)
#Prev and Curr for coords
ant = pya.Annotation()
ant.p1 = pya.DPoint(x1p, y1p)
ant.p2 = pya.DPoint(x1c, y1c)
ant.style = pya.Annotation.StyleRuler
view.insert_annotation(ant)
buffer.clear()
So Matthias @Matthias
yes we have had ... this topic before, so I am gonna stay within the framework.
I have been able to make multi-part segmented rulers within PluginFactory,
with right click to end and then process the mouse inputs,
So looking at the code below, I have tried to get this to work with paths to no avail
Comments Suggestions https://www.klayout.de/forum/discussion/comment/7180#Comment_7180
Regards
Tracy
I am able to grab x and y coordinates with the above python code. But I would like to select/highlight the box when I click three vertices of the box by mouse input. Thanks!
I am trying to get actual x and y coordinates of the selected polygon/box. How can I change this code
in order to get actual x and y coordinates. Any help is greatly appreciated
I am trying to get actual x and y coordinates of the selected polygon/box. How can I change this code
in order to get actual x and y coordinates. Any help is greatly appreciated
module ExtractPoints
include RBA
myListx = []
myListy = []
ly = CellView::active.layout
ly.read('C:/28200.gds')
view = RBA::LayoutView::current
layer = RBA::LayerInfo::new(12, 0)
li = view.begin_layers
while !li.at_end?
lp = li.current
new_lp = lp.dup
new_lp.visible = (lp.source_layer == 12 && lp.source_datatype == 0)
view.set_layer_properties(li, new_lp)
li.next
end
ly = CellView::active.layout
lv = Application::instance.main_window.current_view
lv.each_object_selected
{
|obj|
shape = obj.shape
if shape.is_polygon?||shape.is_box?
shape.polygon.each_point_hull
{
|pt|
x, y = pt.x*ly.dbu, pt.y*ly.dbu
myListx << x
myListy << y
}
end
}
p "#{myListx}", "#{myListy}"
end
I would like to turnoff all layer except two layers having pads and die border. I could turn off all layers except one layer with the code below. How can I change this code to turn on two layers
include RBA
myListx = []
myListy = []
ly = CellView::active.layout
ly.read('C:/28200.gds')
view = RBA::LayoutView::current
layer = RBA::LayerInfo::new(12, 0)
li = view.begin_layers
while !li.at_end?
lp = li.current
new_lp = lp.dup
new_lp.visible = (lp.source_layer == 12 && lp.source_datatype == 0)
view.set_layer_properties(li, new_lp)
li.next
end
lv = Application::instance.main_window.current_view
lv.each_object_selected {
|obj|
shape = obj.shape
if shape.is_polygon?||shape.is_box?
# NOTE "transformed" - this transforms the polygon into the current cell
shape.polygon.transformed(obj.trans).each_point_hull {
|pt|
(x, y) = pt.x*ly.dbu, pt.y*ly.dbu
myListx << x
myListy << y
}
end
}
puts "#{myListx}", "#{myListy}"
end
Comments
Maybe you should check here before you continue: https://www.klayout.de/forum/discussion/comment/7260#Comment_7260
There is some more:
Matthias
A Better example is listed here to get the XY or Origin
https://www.klayout.de/forum/discussion/1151/capture-a-mouse-click-and-its-location
I have made some modifications to the example Matthias provided ,
one thing I noticed you have to load the script twice
before it works other wise it crashes ??? Reason I have no idea.
This works in Python not sure how to get the same script to work in Ruby,
it's a mystery, mouse functions should not be this elaborate.
As discussed in this example
https://www.klayout.de/forum/discussion/1151/capture-a-mouse-click-and-its-location
To combat the behavior change noted here, ruler snap to vertex, I want to automate the actions of the ruler. Specifically:
1. Popup dialog for user to pick 3 vertices of a polygon.
2. on each mouse click, capture the x,y coordinate of the mouse location in drawn space and the nearest x,y coordinate of the selected vertex. They must agree with some tolerance.
3. After 3 points found, calculate the x,y coordinate of the midpoint of the hypotenuse of the triangle defined by the 3 points.
4. Repeat for the next polygon.
5. Calculate the distance between the 2 found centers.
Interesting things on rulers
https://www.klayout.de/doc-qt5/code/class_Annotation.html#method89
Annotation objects provide a way to attach measurements or descriptive information to a layout view.
Annotation objects can appear as rulers for example.
Annotation objects can be configured in different ways using the styles provided.
By configuring an annotation object properly, it can appear as a rectangle or a plain line for example.
See Ruler properties for more details about the appearance options.
Below are Python/Ruby Versions of this
Update Fixed the Python
I am using this code to find the center of the two shapes and measure the distance between them. How do I save the info of coordinate for finding the center and calculation of the distance between them
@tagger5896 Thanks for your "Get X/Y" code above.
You should put these line
at the end. Because with a layout open it's executed immediately and at this point the GetXYOnMouseClickPlugin class isn't defined. With this fix I don't see any crashes (Ubuntu 20, version 0.26.11).
Apart from that: "mouse functions should not be this elaborate" ... we had this topic before. If anyone has a better solution, please drop me a pull request on GitHub and I'll take a look. After all it's open source and it's not my responsibility to make you happy. My focus is on architecture. KLayout is a highly scalable application. This does not come for free.
Matthias
@Matthias
@skywalk
@raji
@dick_freebird
Some updates regarding interesting things with rulers
Code below allows too ad multi-segment rulers
It's buggy at best at the present time,
Need too add Marker shape to follow Entered path and Snap.
Double click First mouse button, then Right Click end's Point Entry and adds annotated Ruler.
At process_coords():
# TODO: put in your code to do what you like to do below
#Unlimited things can be done
If anybody has ideas too follow the coords for the marker layer and snap
Please feel free to update. My mouse is entering an limited life span
Regards
Tracy
So Matthias
@Matthias
yes we have had ... this topic before, so I am gonna stay within the framework.
I have been able to make multi-part segmented rulers within PluginFactory,
with right click to end and then process the mouse inputs,
So looking at the code below, I have tried to get this to work with paths to no avail
Comments Suggestions
https://www.klayout.de/forum/discussion/comment/7180#Comment_7180
Regards
Tracy
I am able to grab x and y coordinates with the above python code. But I would like to select/highlight the box when I click three vertices of the box by mouse input. Thanks!
I am trying to get actual x and y coordinates of the selected polygon/box. How can I change this code
in order to get actual x and y coordinates. Any help is greatly appreciated
module ExtractPoints
include RBA
myListx = []
myListy = []
ly = CellView::active.layout
ly.read('C:/28200.gds')
view = RBA::LayoutView::current
layer = RBA::LayerInfo::new(12, 0)
li = view.begin_layers
while !li.at_end?
lp = li.current
new_lp = lp.dup
new_lp.visible = (lp.source_layer == 12 && lp.source_datatype == 0)
view.set_layer_properties(li, new_lp)
li.next
end
ly = CellView::active.layout
lv = Application::instance.main_window.current_view
lv.each_object_selected { |obj|
shape = obj.shape
if shape.is_polygon?||shape.is_box?
shape.polygon.each_point_hull { |pt|
x, y = pt.xly.dbu, pt.yly.dbu
myListx << x
myListy << y
}
end
}
p "#{myListx}", "#{myListy}"
end
I am trying to get actual x and y coordinates of the selected polygon/box. How can I change this code
in order to get actual x and y coordinates. Any help is greatly appreciated
@raji The bottom part of the script actually provides the solution with a few modifications:
Vou can select a shape and then call the script to get the coordinates. The list will be printed to stdout or the console if the macro IDE is open.
Matthias
Thanks Matthias!
I would like to turnoff all layer except two layers having pads and die border. I could turn off all layers except one layer with the code below. How can I change this code to turn on two layers
Is this related to the original discussion? Maybe you want to open a new one.
Matthias