How to use arcs.py arcFrom2Pts

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
edwilliams16
Veteran
Posts: 3112
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: How to use arcs.py arcFrom2Pts

Post by edwilliams16 »

drmacro wrote: Tue May 04, 2021 3:26 pm
I am looking through arcFromCenter2Pts, arc case and you Sandbox page.

r1 and r2 the vector from center to the end points of firstPt, lastPt respectively.
Correct.
drmacro wrote: Tue May 04, 2021 3:26 pm rot = Rotation(r1, r2) returns the angle between r1 & r2 (in radians)
Not quite. rot is the Rotation operator that would rotate the vector r1 into r2. It implicitly contains both an angle and an axis.
If we are in our sketcher case where r1 and r2 lie in the XY plane, the axis is the z-axis: Vector(0, 0, 1), but here we are treating the general 3D case.
So

Code: Select all

rot.Angle # angle from r1 to r2
rot.Axis # axis of rotation from the right hand rule, twisting r1 into r2

Code: Select all

identity = Rotation(0,0,0,1)
This is one way to create the identity rotation, the one that does nothing. Another way could be:

Code: Select all

identity = Rotation(Vector(0,0,1), 0) # 0 degrees around z-axis

Code: Select all

rothalf = rot.slerp(identity, 0.5)

returns a rotation halfway between the identity and rot. It has the same axis as rot, but half the angle. slerp is designed for this purpose, but is more general, since the two rotations could have different axes, and the angle to be interpolated is not directly accessible, as it is in our application.

In this case, we could have written

Code: Select all

import math
rothalf = Rotation(rot.Axis, math.degrees(rot.Angle/2))
which is complicated by the fact that rot.Angle returns radians, while Rotation(axis, angle) takes a degree argument. This explicitly constructs the half-angle rotation.

i

Code: Select all

IntermediatePt = center + rothalf.multVec(r1) returns the point that bisects the arc?
Exactly. rothalf.multVec(r1) rotates r1 with the operator rothalf

When you move objects around in three dimensional space, without changing their shape (what is referred to as rigid body motion), all possible moves are a combination of rotation and translation. Translations are described by vectors (e.g. Placement.Base), and rotations by Rotation (e.g. Placement.Rotation).
A point on a body p is translated by adding the translation vector t

Code: Select all

p[ -> t.add(p) = t + p
A point is rotated around the origin by operating on it with a Rotation rot

Code: Select all

p-> rot.multVec(p)
User avatar
Chris_G
Veteran
Posts: 2579
Joined: Tue Dec 31, 2013 4:10 pm
Location: France
Contact:

Re: How to use arcs.py arcFrom2Pts

Post by Chris_G »

drmacro wrote: Mon May 03, 2021 12:30 pm I admit I'm still not clear on why FC has topological and geometry. I've read it here https://wiki.freecadweb.org/Topological_data_scripting and @Chris_G answered my query about it in another post. I see that is Topology is a sort of wrapper around lesser geometries...but, it just seems to be obfuscation for no particular benefit at my current level of understanding.
This all comes from BREP :
A boundary representation of a model comprises topological components (faces, edges and vertices) and the connections between them, along with geometric definitions for those components (surfaces, curves and points, respectively).
Although it may not clearly show how it is useful if you consider a single element (a single edge, or face), topology is mainly about the assembly of these elements to build complex objects.
For this assembly purpose, the algorithms can get quite complex by themselves and the number of "gluing / sewing" situations would be pretty big, if you had to consider every type of mathematical curve or surface individually.
So it is useful to reduce the number of "base bricks" of this assembly game, hence the wrapping of all 1D objects as edges, 2D objects as faces, and 3D objects as solids.

Here is another example to show the difference between an edge and a curve :
Let's consider the top circle edge of a cylinder :

Code: Select all

cyl = Part.makeCylinder(2,10)
Part.show(cyl)
top_edge = cyl.Edge1
top_edge.Curve
# >>> Circle (Radius : 2, Position : (0, 0, 10), Direction : (0, 0, 1))
top_edge is wrapping a 3D circle.
No surprise !
But it is also a seam, because this edge is sewing the boundary of the vertical cylindrical face, and the boundary of the top round face :

Code: Select all

top_edge.curveOnSurface(0)
# >>> (<Line2d object>, <Cylinder object>, Placement [Pos=(0,0,0), Yaw-Pitch-Roll=(0,0,0)], 0.0, 6.283185307179586)
top_edge.curveOnSurface(1)
# >>> (<Circle2d object>, <Plane object>, Placement [Pos=(0,0,0), Yaw-Pitch-Roll=(0,0,0)], 0.0, 6.283185307179586)
So, you can see here that this edge, is, in fact, wrapping 3 different geometries (that all share the same location in 3D space):
- a 3D circle
- a 2D line traced on a cylinder surface
- a 2D circle traced on a planar surface

When you script in FreeCAD and work with single objects, you can easily navigate between topology / geometry, edge / curve, face / surface.
When building objects in Part module, you can choose to create geometries, or topologies :
- Part.Circle() creates a geometic curve
- Part.makeCircle() creates an edge wrapping a circle
- Part.Cylinder() creates a geometric surface
- Part.makeCylinder() creates a solid, made from 3 faces : the cylindrical face + the 2 round end caps.
- etc ...

Also, as topology does the assembly / sewing of base objects, this is where the tolerance concept appears.
And the topologies also contain the meshes needed for the 3D view display.
This is why you cannot display geometries directly.

As for the Sketcher, it works with geometries, because it has to treat specifically with each type of mathematical curve.
drmacro
Veteran
Posts: 8870
Joined: Sun Mar 02, 2014 4:35 pm

Re: How to use arcs.py arcFrom2Pts

Post by drmacro »

Chris_G wrote: Wed May 05, 2021 9:32 am ...
@Chris_G Thank you!

Ok, that clears a lot of fog in my mind. :idea:

I'm still left with the question:

If an edge is constructed thus:

Code: Select all

myedge= Part.Edge(Part.Arc(...))
Is there no way to get the Part.Arc from myedge?

:?:
Star Trek II: The Wrath of Khan: Spock: "...His pattern indicates two-dimensional thinking."
User avatar
onekk
Veteran
Posts: 6146
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: How to use arcs.py arcFrom2Pts

Post by onekk »

Yes, it is in the answer

Code: Select all

cyl = Part.makeCylinder(2,10)
Part.show(cyl)
top_edge = cyl.Edge1
top_edge.Curve
With this writing, you are assigning a geometry to an "Edge", so myedge is an edge

Code: Select all

myedge= Part.Edge(Part.Arc(...))
but if you try to do:

Code: Select all

ed1 = myedge.Edges[0] 
print(ed1)

geom1 = ed1.Curve

print(geom1)

print(geom1.TypeId)
You will se the results.

the Curve is holding the 2d object in the caseof arc that is a portion of circle the TypeId will be Part::GeomCircle note Geom in the name

Regards

Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.

Blog: https://okkmkblog.wordpress.com/
edwilliams16
Veteran
Posts: 3112
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: How to use arcs.py arcFrom2Pts

Post by edwilliams16 »

onekk wrote: Wed May 05, 2021 3:38 pm Yes, it is in the answer

Code: Select all

cyl = Part.makeCylinder(2,10)
Part.show(cyl)
top_edge = cyl.Edge1
top_edge.Curve
It doesn't seem to be as simple as saying that the Curve property of an edge is the geometry inside the Part.Edge(..) that created the edge.

It works for a circle:

Code: Select all

circ = Part.Circle()
circ.Center = Vector(0,0,0)
circ.Axis = Vector(0,0,1)
circ.Radius=1
circ
>>> Circle (Radius : 1, Position : (0, 0, 0), Direction : (0, 0, 1))
circ_edge = Part.Edge(circ)
circ_curve=circ_edge.Curve
circ_curve
>>> Circle (Radius : 1, Position : (0, 0, 0), Direction : (0, 0, 1))
where circ_curv is the same as the original circ

However:

Code: Select all

arc= Part.ArcOfCircle(circ,0,1)
>>> ArcOfCircle (Radius : 1, Position : (0, 0, 0), Direction : (0, 0, 1), Parameter : (0, 1))
arc_curve = Part.Edge(arc).Curve
arc_curve
>>> Circle (Radius : 1, Position : (0, 0, 0), Direction : (0, 0, 1))
Here we find that arc_curve is the entire circle, not just the parameterized arc.

Similar thing occurs with line_segments

Code: Select all

lineseg = Part.LineSegment(Vector(0,0,0), Vector(1,1,1))
lineseg
>>> <Line segment (0,0,0) (1,1,1) >
lineseg_edge = Part.Edge(lineseg)
lineseg_curve = lineseg_edge.Curve
lineseg_curve
>>> <Line object>
lineseg.TypeId
>>> ’Part::GeomLineSegment'
lineseg_curve.TypeId
>>> ’Part::GeomLine'
where the Curve property of the Edge returns the infinite line of which lineseg is a finite segment.

So @drmacro 's question isn't really answered. How do we get back the geometric primitive stored in an Edge object?

EDIT: I finally figured it out

Code: Select all

lineseg = Part.LineSegment(Vector(0,0,0), Vector(1,1,1))
lineseg
>>> <Line segment (0,0,0) (1,1,1) >
lineseg_edge = Part.Edge(lineseg)
lineseg_new = Part.LineSegment(lineseg_edge.Curve, *lineseg_edge.ParameterRange)
lineseg_new
>>> <Line segment (0,0,0) (1,1,1) >

Code: Select all

arc = Part.ArcOfCircle(circ,0,1)
arc_edge = Part.Edge(arc)
arc_new = Part.ArcOfCircle(arc_edge.Curve, *arc_edge.ParameterRange)
similarly works to extract arc from arc_edge

It might be relatively straightforward to make a generic routine that tests on TypeID to extract the geometry from an edge. It likely already exists somewhere!
Last edited by edwilliams16 on Wed May 05, 2021 8:38 pm, edited 1 time in total.
drmacro
Veteran
Posts: 8870
Joined: Sun Mar 02, 2014 4:35 pm

Re: How to use arcs.py arcFrom2Pts

Post by drmacro »

After reading @onekk post I went off and attempted to do as he suggested.

I was able to do it.

I ran out of time and had to leave it for today.

I will post my example code and thoughts in the morning.
Star Trek II: The Wrath of Khan: Spock: "...His pattern indicates two-dimensional thinking."
User avatar
onekk
Veteran
Posts: 6146
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: How to use arcs.py arcFrom2Pts

Post by onekk »

The point is that you are extracting the geometric primitive, so an arc is a portion of a circle, a segment is a portion of a line, ecc.

I could not test now, but maybe there is a method similar toShape() exposed as to have the "object with limits".

However if you intend to use scripting you could ever write your own helper methods.

Many of things exposed by scripting are done in this way, see for example almost all the Draft code that is done in python and in the very end create Part objects.


One of the power of FreeCAD is to have sources available, and even the C part is at least readable without many hassles, C code flow is not too involute a part from the -> part that sometimes will confuse a little, but C++ is as widespread that a basic manual could be found around at least to have an idea "how things works"

Regards

Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.

Blog: https://okkmkblog.wordpress.com/
drmacro
Veteran
Posts: 8870
Joined: Sun Mar 02, 2014 4:35 pm

Re: How to use arcs.py arcFrom2Pts

Post by drmacro »

The attached python script is a test of what we've discussed in the last couple posts.
I believe @onekk is correct and using the Edges[0] does not produce the arc but a circle:
(Note: I added the lines as reference to the vectors hardwired in the script.)
Snip macro screenshot-8d96d5.png
Snip macro screenshot-8d96d5.png (106.85 KiB) Viewed 1046 times
And looking at the object returned by Part.Edge() it appears to have no information about the arc used to create it.

(Note: the arc functions are those offered earlier in the thread and not from FreeCAD source.)
Attachments
test_arcfrom2pt.py
(2.96 KiB) Downloaded 32 times
Star Trek II: The Wrath of Khan: Spock: "...His pattern indicates two-dimensional thinking."
drmacro
Veteran
Posts: 8870
Joined: Sun Mar 02, 2014 4:35 pm

Re: How to use arcs.py arcFrom2Pts

Post by drmacro »

onekk wrote: Thu May 06, 2021 5:57 am ...
One of the power of FreeCAD is to have sources available, and even the C part is at least readable without many hassles, C code flow is not too involute a part from the -> part that sometimes will confuse a little, but C++ is as widespread that a basic manual could be found around at least to have an idea "how things works"
...
While I agree "One of the power of FreeCAD is to have sources available", I feel telling people that to become competent with scripting they need to read the source code is not the correct approach to a scripting language that is intended to make a software package extensible by the end user.
(And BTW, unlike many end users, I happen to be (or at least was in a past life :lol: ) competent in all the languages you mention, including several others. That doesn't mean I should have to march around in the internals as documentation. 8-) )

Granted, creating user documentation for such a tool is no trivial task, but if it is truly intended for serious use by end users, then it must be addressed in a more comprehensive manor.

Please note, I'm not upset or anything of that nature, this is simply editorial comment. I realize the status quo and understand why it is like it is.
Also, I am contemplating (actually started collecting notes) for a scripting handbook, with the intent of making available on my github. Maybe it will help future script-ers... :roll:
Star Trek II: The Wrath of Khan: Spock: "...His pattern indicates two-dimensional thinking."
edwilliams16
Veteran
Posts: 3112
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: How to use arcs.py arcFrom2Pts

Post by edwilliams16 »

drmacro wrote: Thu May 06, 2021 12:45 pm
And looking at the object returned by Part.Edge() it appears to have no information about the arc used to create it.

Did you miss my solution to obtaining the arc (not the circle) from the edge, which I cross-posted with you yesterday. Perhaps I should always make new posts, not amend with edits. See it for more detail.

Code: Select all

arc = Part.ArcOfCircle(circ,0,1)
arc_edge = Part.Edge(arc)
arc_new = Part.ArcOfCircle(arc_edge.Curve, *arc_edge.ParameterRange)
arc_new reproduces arc, extracting the edge back from arc_edge

By the way, I think there would be less need for "Read the Source, Luke", if code authors made more extensive use of docstrings. At a minimum, they should provide the supported argument lists for methods.
Post Reply