[Solved] Help with a macro

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
jfc4120
Posts: 448
Joined: Sat Jul 02, 2022 11:16 pm

[Solved] Help with a macro

Post by jfc4120 »

Code: Select all

OS: Windows 10 Version 2009
Word size of FreeCAD: 64-bit
Version: 0.20.2.29177 +426 (Git)
Build type: Release
Branch: (HEAD detached from 0.20.2)
Hash: 930dd9a76203a3260b1e6256c70c1c3cad8c5cb8
Python 3.8.10, Qt 5.15.2, Coin 4.0.1, Vtk 8.2.0, OCC 7.6.3
Locale: English/United States (en_US)
Installed mods: 
  * Help 1.0.3
I have two macros, one works only if there are two lines to get angle, the other works if a closed wire and gets the angle between two selected edges.

They are still in work, but do work. I am trying to figure out how to handle all in a single macro.

I would also like the macro to get the angle between an edge and a line from sketcher (all in same plane) of course.

Angle between lines macro:

Code: Select all

import FreeCAD, FreeCADGui
# -*- coding: utf-8 -*-
import FreeCAD, FreeCADGui
import Draft
import math
# from math import cos, sin, radians
from PySide import QtGui

convert = 25.4
TOTAL = 0
getDouble = QtGui.QInputDialog.getDouble
Vector, Placement = App.Vector, App.Placement
doc = App.ActiveDocument

start_point = Vector(0, 0, 0)

#inserted
edge = FreeCADGui.Selection.getSelectionEx()[0].SubObjects[0]
edgePt1 = edge.Vertexes[0].Point
edgePt2 = edge.Vertexes[1].Point
vect = edgePt1 - edgePt2
#here
s=Gui.Selection.getSelectionEx()
edge=s[0].SubObjects[0]
x0 = edge.firstVertex().Point.x * .039370078
y0 = edge.firstVertex().Point.y * .039370078
z0 = edge.firstVertex().Point.z * .039370078


x1 = edge.lastVertex().Point.x * .039370078
y1 = edge.lastVertex().Point.y * .039370078
z1 = edge.lastVertex().Point.z * .039370078


edge2=s[1].SubObjects[0]
x2 = edge2.firstVertex().Point.x * .039370078
y2 = edge2.firstVertex().Point.y * .039370078
z2 = edge2.firstVertex().Point.z * .039370078


x3 = edge2.lastVertex().Point.x * .039370078
y3 = edge2.lastVertex().Point.y * .039370078
z3 = edge2.lastVertex().Point.z * .039370078

if x0 == x2 and y0 == y2:
    p1 = App.Vector(x0, y0, z0)
    p2 = App.Vector(x1, y1, z1)
    p3 = App.Vector(x3, y3, z3)

if x0 == x3 and y0 == y3:
    p1 = App.Vector(x0, y0, z0)
    p2 = App.Vector(x1, y1, z1)
    p3 = App.Vector(x2, y2, z2)

if x1 == x2 and y1 == y2:
    p1 = App.Vector(x1, y1, z1)
    p2 = App.Vector(x0, y0, z0)
    p3 = App.Vector(x3, y3, z3)

if x1 == x3 and y1 == y3:
    p1 = App.Vector(x1, y1, z1)
    p2 = App.Vector(x0, y0, z0)
    p3 = App.Vector(x2, y2, z2)


ang1 = math.degrees((p2 - p1).getAngle(p3 - p1))
print(ang1)
#good ang2 = math.degrees((p3 - p2).getAngle(p1 - p2))
#ang2 = math.degrees((p1 - p2).getAngle(p3 - p2))
#print(ang2)
#ang3 = degrees((p1 - p3).getAngle(p2 - p3))

#The side lengths are:

#Code: Select all

#L12 = (p1 - p2).Length
L12 = (p2 - p1).Length
print(L12)
#L23 = (p2 - p3).Length
#L31 = (p3 - p1).Length

#pt = App.Vector(multlist[0][0] * convert, multlist[0][1] * convert, multlist[0][2] * convert)
#t1 = round(ang1, 3)
#t11 = str(t1)
#text1 = Draft.make_text(t11, pt)
#print('p1',p1)

Angle between edges code:

Code: Select all

import FreeCAD, FreeCADGui
# -*- coding: utf-8 -*-
import FreeCAD, FreeCADGui
import Draft
import math
# from math import cos, sin, radians
from PySide import QtGui

convert = 25.4
TOTAL = 0
getDouble = QtGui.QInputDialog.getDouble
Vector, Placement = App.Vector, App.Placement
doc = App.ActiveDocument

start_point = Vector(0, 0, 0)

#inserted
edge = FreeCADGui.Selection.getSelectionEx()[0].SubObjects[0]

edgePt1 = edge.Vertexes[0].Point
edgePt2 = edge.Vertexes[1].Point
vect = edgePt1 - edgePt2
#here

x0 = edge.Vertexes[0].Point.x * .039370078
y0 = edge.Vertexes[0].Point.y * .039370078
z0 = edge.Vertexes[0].Point.z * .039370078


x1 = edge.Vertexes[1].Point.x * .039370078
y1 = edge.Vertexes[1].Point.y * .039370078
z1 = edge.Vertexes[1].Point.z * .039370078


edge2 = FreeCADGui.Selection.getSelectionEx()[0].SubObjects[1]
x2 = edge2.Vertexes[0].Point.x * .039370078
y2 = edge2.Vertexes[0].Point.y * .039370078
z2 = edge2.Vertexes[0].Point.z * .039370078


x3 = edge2.Vertexes[1].Point.x * .039370078
y3 = edge2.Vertexes[1].Point.y * .039370078
z3 = edge2.Vertexes[1].Point.z * .039370078

if x0 == x2 and y0 == y2:
    p1 = App.Vector(x0, y0, z0)
    p2 = App.Vector(x1, y1, z1)
    p3 = App.Vector(x3, y3, z3)

if x0 == x3 and y0 == y3:
    p1 = App.Vector(x0, y0, z0)
    p2 = App.Vector(x1, y1, z1)
    p3 = App.Vector(x2, y2, z2)

if x1 == x2 and y1 == y2:
    p1 = App.Vector(x1, y1, z1)
    p2 = App.Vector(x0, y0, z0)
    p3 = App.Vector(x3, y3, z3)

if x1 == x3 and y1 == y3:
    p1 = App.Vector(x1, y1, z1)
    p2 = App.Vector(x0, y0, z0)
    p3 = App.Vector(x2, y2, z2)

ang1 = math.degrees((p2 - p1).getAngle(p3 - p1))
print(ang1)
#good ang2 = math.degrees((p3 - p2).getAngle(p1 - p2))
#ang2 = math.degrees((p1 - p2).getAngle(p3 - p2))
#print(ang2)
#ang3 = degrees((p1 - p3).getAngle(p2 - p3))

#The side lengths are:

#Code: Select all

#L12 = (p1 - p2).Length
L12 = (p2 - p1).Length
print(L12)
#L23 = (p2 - p3).Length
#L31 = (p3 - p1).Length

#pt = App.Vector(multlist[0][0] * convert, multlist[0][1] * convert, multlist[0][2] * convert)
#t1 = round(ang1, 3)
#t11 = str(t1)
#text1 = Draft.make_text(t11, pt)
#print('p1',p1)
And I haven't figured out the other yet. I have another macro that does all 3 using points that works, but I'd like to do it with just 2 lines / edges selected.

Thanks.
Attachments
angles.png
angles.png (37.86 KiB) Viewed 1070 times
angle_test22.FCStd
(11.98 KiB) Downloaded 13 times
Last edited by jfc4120 on Thu Feb 02, 2023 4:33 am, edited 1 time in total.
jfc4120
Posts: 448
Joined: Sat Jul 02, 2022 11:16 pm

Re: Help with a macro

Post by jfc4120 »

For now I am not going to go ahead with it, here's why:

Code: Select all

18:50:28  x0 -15.627980554039395
18:50:28  x0 -24.59290367941755
18:50:28  x2 -61.32742673799614
18:50:28  x3 -24.59290367941754

When printing out values for test, even though above x0 is supposed to be equal to x3, it's not.

Even though draft snap to end point was used. I will just use my 3 point macro that @edwilliams16 helped me with.

But if anyone figures this out please reply.
edwilliams16
Veteran
Posts: 3112
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: Help with a macro

Post by edwilliams16 »

Let me see if I understand what you want. You want the angle between two coplanar edges that you select.
  • Do the two edges share a vertex?
  • If they don't, should we check if they are actually coplanar?
  • Are they edges of the same object, or could they be from different objects?
  • Should we check if two edges have actually been chosen?
  • Which angle, interior or exterior do you want to return?
  • Do the two edges belong to objects in a common coordinate system
  • If not, could either object be a linked object?
Note that in your code, you convert inches to mm. This is unnecessary if you are computing angles as they don't depend on the length unit.
jfc4120
Posts: 448
Joined: Sat Jul 02, 2022 11:16 pm

Re: Help with a macro

Post by jfc4120 »

Yes coplanar, they could be two separate lines or two wires connected. And yes always a vertex. Unless there's a fairly simple way to find the angle even if they don't have a vertex would be good too.

And I have dropped the idea about the sketch line I will just use the three points macro for that.

I played around a little more and got the one with two separate lines working by rounding to six decimal places.

I just thought it would be nice to have one where you can select two edges or two lines.

One problem also is I have to click with mouse to select if you select from the tree then the end points show and there are errors you probably know what I mean.

I am almost positive I have gotten in over my head here.

At least I have the three-point macro that definitely works.
dan-miel
Posts: 391
Joined: Thu Sep 13, 2018 12:29 am
Location: Spokane WA. USA

Re: Help with a macro

Post by dan-miel »

jfc4120 wrote: Wed Feb 01, 2023 10:50 pm And I haven't figured out the other yet. I have another macro that does all 3 using points that works, but I'd like to do it with just 2 lines / edges selected.
You might install the Quick Measure Add-in and take a look at the code. It measures edges and other features and returns measurements in the units that are in the settings. I hope the coding helps.
Dan
edwilliams16
Veteran
Posts: 3112
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: Help with a macro

Post by edwilliams16 »

edwilliams16 wrote: Thu Feb 02, 2023 1:35 am Let me see if I understand what you want. You want the angle between two coplanar edges that you select.
  • Do the two edges share a vertex?
Not necessarily
  • If they don't, should we check if they are actually coplanar?
Yes
  • Are they edges of the same object, or could they be from different objects?
Either
  • Should we check if two edges have actually been chosen?
Yes
  • Which angle, interior or exterior do you want to return?
Both
  • Do the two edges belong to objects in a common coordinate system
Use global coordinates
  • If not, could either object be a linked object?
Can be

Code: Select all

from math import degrees
vlocs =[] #collect locations of vertices
for sel in Gui.Selection.getSelectionEx('',0):
    for path in sel.SubElementNames if sel.SubElementNames else ['']:
        subObj = sel.Object.getSubObject(path)
        if subObj.ShapeType == 'Edge':
            vlocs.append(subObj.Vertexes[0].Point) #global vertex location
            vlocs.append(subObj.Vertexes[1].Point)


if len(vlocs) == 4: #two edges selected
    print(vlocs)
    if vlocs[2].isEqual(vlocs[0], 1e-7) or vlocs[2].isEqual(vlocs[1], 1e-7):#swap 2 & 3 if 2 is vertex
       temp = vlocs[2]
       vlocs[2] = vlocs[3]
       vlocs[3] = temp

    p = Part.Plane(vlocs[0], vlocs[1], vlocs[2])
    if abs(p.projectPoint(vlocs[3], "Distance")[0]) < 1e-7: #check coplanar
        ang = degrees((vlocs[0]-vlocs[1]).getAngle(vlocs[2] - vlocs[3]))
        print(f'Angles are {ang}  {180 - ang}')
    else:
        print('Edges are not coplanar')
else:
    print('Select two edges')


EDIT: fixed bug if two endpoints were the same.
Last edited by edwilliams16 on Thu Feb 02, 2023 4:17 am, edited 2 times in total.
jfc4120
Posts: 448
Joined: Sat Jul 02, 2022 11:16 pm

Re: Help with a macro

Post by jfc4120 »

Working on 2 wire edges or 2 lines, but two other edges not.

See the selected in image:

I get:

Edges are not coplanar, but they are. FIle attached also.

In one image, sorry I mis-spelled menu.
Attachments
angle_test22.FCStd
(13.21 KiB) Downloaded 21 times
angle1.png
angle1.png (11.44 KiB) Viewed 858 times
Last edited by jfc4120 on Thu Feb 02, 2023 4:21 am, edited 2 times in total.
jfc4120
Posts: 448
Joined: Sat Jul 02, 2022 11:16 pm

Re: Help with a macro

Post by jfc4120 »

Another test, front view worked, home view did not, attached.
Attachments
three_points.png
three_points.png (102.2 KiB) Viewed 795 times
home.png
home.png (95.04 KiB) Viewed 841 times
front.png
front.png (34.29 KiB) Viewed 841 times
angle_test222.FCStd
(11.07 KiB) Downloaded 16 times
Last edited by jfc4120 on Thu Feb 02, 2023 4:23 am, edited 1 time in total.
edwilliams16
Veteran
Posts: 3112
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: Help with a macro

Post by edwilliams16 »

@jfc4120
Yes. I forgot two edge endpoints could coincide. Fixed above...
jfc4120
Posts: 448
Joined: Sat Jul 02, 2022 11:16 pm

Re: Help with a macro

Post by jfc4120 »

@edwilliams16 Believe it or not, as short as that code is, I don't understand how it works, but it does. :? :D 8-)

Thanks, it's nice to do a quick angular measure in draft home view, if you saw the other post, freecad does not give accurate angular dimensions in home view, the 3d home view.

@dan-miel Thank you for your reply, I will have a look.
Post Reply