Available helper functions for scripting

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
User avatar
onekk
Veteran
Posts: 6222
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: Available helper functions for scripting

Post by onekk »

You will find in my former answer a solution to your problem , hoping it will work, but as someone has told you in another thread, your problem has undefined solution for arcs that are half circles, but as you are using sketcher that work in XY plane, there are other way, my solution generally will work in XY case, given a center and two points you will find and arc calculating the midpoint of the arc, assuming the point are under "trigonometric conventions" in other word, in the undefined case of the "half circle", you obtain the upper half as the circle is intended to be in counterclockwise direction.


If you want a manual or a list of functions, FreeCAD at this point of development, has no this type of list nor a proper manual:

1) most of developer and users, intend FreeCAD as a GUI only software. not a correct assumption, but it may be an "sentiment" for many of people that use script to "drive" FreeCAD.

2) documentation is "time consuming" and generally is done when "a stable" version is fixed. Sadly FreeCAD is in "rolling release" state so no "stable 1.0" version in sight for now, but it is highly usable, and for pratical use there is no need to have a 1.0 point release.

3) documentation is generally done by people who "knows the program" and "knows the language on which they are writing", so maybe other people have a "not very good" English language skills to put in place a decent documentation.

4) to add some arguments to point 2) in this state of development, a list of functions has to be update very often and will be a "waste of time" to hav such lists. so "use the source Luke".

Some work are in progress to document many of the things, in the wiki, but it is a big work and people are few.

Solutions, could be found, just ask, this thread is the "proof of concept" that if you ask politely some people will step in an do some help.

Many times, however people are been in this forum only to solve their problem, perhaps for "some classroom work" or event to make some "video tutorials" or other piece of software, maybe also for commercial use.

Said so it is not a sin, to ask for help, and usually you will find some help, (and you have found it many times here).

Maybe one thing is lack in this discussion, much of FreeCAD work is made by volunteers, I have obtained some help here and if I can i will repay the help I've had with another help I do.

Other could contribute to development using LIberapay or other places to "help development" (as I'm unemployed I could only pay using some help to other users in the hope that this will spread the user base and maybe someone will make some donations, for now it's my only viable way to help developing FreeCAD).

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: 9010
Joined: Sun Mar 02, 2014 4:35 pm

Re: Available helper functions for scripting

Post by drmacro »

onekk wrote: Sun May 02, 2021 10:41 am You will find in my former answer a solution to your problem , hoping it will work, but as someone has told you in another thread, your problem has undefined solution for arcs that are half circles, but as you are using sketcher that work in XY plane, there are other way, my solution generally will work in XY case, given a center and two points you will find and arc calculating the midpoint of the arc, assuming the point are under "trigonometric conventions" in other word, in the undefined case of the "half circle", you obtain the upper half as the circle is intended to be in counterclockwise direction.
Admittedly I happen to have found, on my initial attempt to use the function, a particular case that fails.

To be honest, I looked at your solution early in my attempt to get what I needed and now have made so many 'trial and error' attempts, that I don't remember why I chose to look for different solutions... :roll:

But, I will be looking at your previous post again as I work through my issues.
If you want a manual or a list of functions, FreeCAD at this point of development, has no this type of list nor a proper manual:

1) most of developer and users, intend FreeCAD as a GUI only software. not a correct assumption, but it may be an "sentiment" for many of people that use script to "drive" FreeCAD.
Driving FreeCAD with the UI can probably be argued to be the default use case. And if the use of python and macros to make the product extensible is intended as a tool only for developers, then maybe the main menu should not feature prominently a macro recording capability. I say this in jest of course, but...
2) documentation is "time consuming" and generally is done when "a stable" version is fixed. Sadly FreeCAD is in "rolling release" state so no "stable 1.0" version in sight for now, but it is highly usable, and for pratical use there is no need to have a 1.0 point release.

3) documentation is generally done by people who "knows the program" and "knows the language on which they are writing", so maybe other people have a "not very good" English language skills to put in place a decent documentation.
Documentation is definitely a time consuming and mostly thankless task.
I would argue that, at this stage of development, that thorough documentation should be very important. There is of course code documentation and user documentation, they aren't always the same thing.

Code documentation should be done by developers so they know what they wrote when they look at it next year and so others looking at it can figure out the intent and functionality...and, the corner cases that will fail.

The best user documentation I ever saw was done by people who had, specifically, not written the code.
4) to add some arguments to point 2) in this state of development, a list of functions has to be update very often and will be a "waste of time" to hav such lists. so "use the source Luke".
Well, I did use the source...and here we are discussing my first attempt hitting a corner case that fails. Did I interpret the name of the function wrong, apparently yes. Did I misinterpret the the arguments, somewhat, yes.

And that's why I'm asking a lot of questions, for me the answers aren't obvious in the source. I am not a "reading" learner, so this my problem and my frustration with my own progress does show in my posts; I try not to let that happen...to varying degrees of success.
Some work are in progress to document many of the things, in the wiki, but it is a big work and people are few.
I am very aware of this and am helping with the documentation where I can and when asked.
Solutions, could be found, just ask, this thread is the "proof of concept" that if you ask politely some people will step in an do some help.

Many times, however people are been in this forum only to solve their problem, perhaps for "some classroom work" or event to make some "video tutorials" or other piece of software, maybe also for commercial use.

Said so it is not a sin, to ask for help, and usually you will find some help, (and you have found it many times here).
Indeed, I have found lots of answers to my many, many questions. I am very grateful for those answers and the effort people make to offer those answers.
Maybe one thing is lack in this discussion, much of FreeCAD work is made by volunteers, I have obtained some help here and if I can i will repay the help I've had with another help I do.

Other could contribute to development using LIberapay or other places to "help development" (as I'm unemployed I could only pay using some help to other users in the hope that this will spread the user base and maybe someone will make some donations, for now it's my only viable way to help developing FreeCAD).

Regards

Carlo D.
I too am unemployed by way of retirement, so financial support of things, on a fixed income, is not really an option.

I tutor new users on several social media platforms, including these forums. I moderate the Facebook group where it is approaching 8000 members rapidly. And created a pdf introductory series.

I edit and add to the wiki as much as I can.

So, I consider myself one of those volunteers. Maybe this is presumptuous of me.

And, hope to do similar things with scripting for FreeCAD.
Star Trek II: The Wrath of Khan: Spock: "...His pattern indicates two-dimensional thinking."
User avatar
onekk
Veteran
Posts: 6222
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: Available helper functions for scripting

Post by onekk »

I'm happy that your answer could have been written by me, so our point of view is very similar to mine.

Assumed that scripting is a "not very well supported task" (trying to be gentle).

See this code, reworked after chrisb in another post (maybe mnade by you) has pointed out that a portion of a circle could be extracted using toShape()

Code: Select all

import FreeCAD
import FreeCADGui
from FreeCAD import Base, Rotation, Vector

from draftgeoutils.edges import findMidpoint
from draftgeoutils.intersections import findIntersection

p1 = Vector(30.36, 74.38, 0.0)
p2 = Vector(135.88, 21.80, 0.0)

obj3 = doc.addObject("Part::Feature", "point_p1")
obj3.Shape = Part.Vertex(p1)
obj3.ViewObject.PointColor = (0.000,1.000,0.000)
obj3.ViewObject.PointSize = 5

obj4 = doc.addObject("Part::Feature", "point_p2")
obj4.Shape =  Part.Vertex(p2)
obj4.ViewObject.PointColor = (0.000,0.000,0.498)
obj4.ViewObject.PointSize = 5

l_a = Part.LineSegment(p1, p2).toShape()

center = findMidpoint(l_a)

obj5 = doc.addObject("Part::Feature", "center")
obj5.Shape =  Part.Vertex(center)
obj5.ViewObject.PointColor = (0.000,0.000,1.000)
obj5.ViewObject.PointSize = 5

radius = center.distanceToPoint(p1)

ip1 = circle.Curve.parameter(p1)
ip2 = circle.Curve.parameter(p2)

print(ip1, "parameter of point p1")
print(ip2, "parameter of point p2")

if ip1 > ip2:
    midp = ip1 + (ip1 - ip2) * 0.5
    lim1 = ip1
    lim2 = ip2
else:
    midp = ip2 + (ip2 - ip1) * 0.5
    lim1 = ip2
    lim2 = ip1

print(lim1, "limit 1 of circle")
print(lim2, "limit 2 of circle")

ci = Part.Circle(center, Vector(0,0,1), radius)  # a circle GEOMETRY
myEdge = ci.toShape(lim1, lim2)

midp = circle.valueAt(midp)

obj3 = doc.addObject("Part::Feature", "arc_midpoint")
obj3.Shape = Part.Vertex(midp)
obj3.ViewObject.PointColor = (1.000,0.000,0.498)
obj3.ViewObject.PointSize = 5

Part.show(myEdge, "myedge")

doc.recompute()
Let's try to make some viable solutions!

What is the final intent of the code?

This has to be clear, as if it is some modelling task, some trial and error could be a "minor damage" as if you intend to make something, it is always possible (maybe very tedious but possible) to find some workaround and maybe some tests (to be more "programmer" some if then else clauses) to avoid corner cases and make a "method" that work on most cases.

If you are trying to make a Macro that has to end in some "button on the GUI", so it has to be used "as is" from other users that don't and want not know anything about the "code behind", it's another and "more difficult" case.

As example I was in need for a a generic way to transform some point in a wire, with fillet and arcs interpolated, I've build wome methods that make "thing done", not so elegant, maybe involute but starting from a tuple containing coordinates and some "directives" like:

Code: Select all

    pl1 = (
        (0.0, 61.43, 0.0),
        (42.80, 61.40, 0.0, "f"),
        (71.25, 41.79, 0.0),
        (75.16, 0.0, 0.0),
        (61.76, 0.0, 0.0),
        (56.82, 30.148, 0.0, "a3"), 
        (52.337, 37.213, 0.0), # arc center
        (43.88, 41.39, 0.0),
        (-1.307, 48.159, 0.0),
        (0.0, 61.43, 0.0)
          )
         
I could obtain this:
polyg.png
polyg.png (3.19 KiB) Viewed 1023 times
Points are taken using a simple interpolation, in my case, using gimp to derive some coordinates from the scanned image of a blueprint.

to make thing happens, I have to cope with a "generic fillet", so I have to find the tangent points of a circle that is "almost near" two lines, so I have to find a way to extend lines, find the intersection between them, and as the tangent could be calculated only if the distance from the "intersection point of the two lines" and the "intersection point of the circle and the two line", i have to cheat finding a common distance between the "real points" and the circle points, (in other words, i 've tried to minimize errors between the scanned points and the calculated points).

Some math and many search on internet, plus some help from the forum was involved but I've managed to get job done.

So it is not impossible to make things, only difficult.

If some "good documentation" was available i maybe have already a method to calculate this points.

Another scenario rotation is boring and rotation and translation are even worse, so without a decent order you can't cope with adjusting things, so i have created a method to "manage" a list of transformation, this could be done in a different way, but it is as easy to:

Code: Select all

lfbp1 = (("X", 90), ("Z", 180),
      ("M", Vector(bdx, 25.20, b_thi * -0.5)))
pro_rot(bmp1, lfbp1)
That is in words Rotate in "X direction 90 degree" then in "Z direction 180 deg" then "translate to position (Vector())"

It could be done using multiply an rotation math, but as I'm "not to young" and my math was studied around 20 or more years ago, this is the way I've found to manage my difficulties.

Not much of my code, is "bullet proof" nor "elegant" but if it works it could be "good enough" to make jobs.

As said, returning to the problem:

1) code documentation is not "the best", but it is "decent" at least you have sources available to try to guess what is done (in sources sometimes there are comments that are much valuable that the whole docstring itself)

2) something could be derived from other places, like some explanation done in some docstrings.

3) the remaining could be asked and generally and recently there are people that are willing to help, and usually better answers are generated that good questions.

To be clear, many of this post is not made to criticize, but with an "educational intent" not adressed to you "drmacro" but for peoples that in future will have same problems and are frustrated by the lack of documentation.

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: 9010
Joined: Sun Mar 02, 2014 4:35 pm

Re: Available helper functions for scripting

Post by drmacro »

I will look through your example and try to understand it.

The attached animation shows what I believed to be a good exercise to learn from.

The arc to close these ends should be a simple. The call should take 4 arguments:
  • begin vector
  • end vector
  • center vector
  • CW or CCW
I think I just have no idea what it would be called...
Attachments
AddArcs2Sausage.gif
AddArcs2Sausage.gif (514.03 KiB) Viewed 1004 times
Star Trek II: The Wrath of Khan: Spock: "...His pattern indicates two-dimensional thinking."
User avatar
onekk
Veteran
Posts: 6222
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: Available helper functions for scripting

Post by onekk »

OK let's see.

you could extract two vertexes, in my code they are p1 and p2.

now with p1 and p2 you could calculate center, that is already calculated in:

Code: Select all

l_a = Part.LineSegment(p1, p2).toShape()

center = findMidpoint(l_a)
so the problem is How to determine the direction to make the arc from p1 to p2 or form p2 to p1 (in other word the semicircle is the "upper" portion or the "lower portion" of the circle.)

I suppose that if you could once selected the two point move the mouse to one direction and then click, you could find a 3rd point, that is the intersection between the circle and the line going from the center and the 3rd click point, in this manner, the arc could be calculated with lim1 and lim2 in the correct places or using the intersection point and pass it to Part.Arc(p1, 3rdpt, p2).

Now what is missing.

calculation are not difficult, suppose you have a third point p3, i have purposely calculated a 3rd point over the line l_a, circle is the complete circle, so the intercept point will works for generic cases. try to put the point in another place under the l_a and over the circle at bottom, and the bottom half of the circle will be drawn instead:

add this to he code in previous post

Code: Select all


p3 = Vector(128, 90, 0)


obj7 = doc.addObject("Part::Feature", "third_point")
obj7.Shape = Part.Vertex(p3)
obj7.ViewObject.PointColor = (1.000,0.000,0.498)
obj7.ViewObject.PointSize = 5

l_b = Part.LineSegment(center, p3).toShape()

Part.show(l_b, "line_:b")

pt3 = findIntersection(circle, l_b)[0]

print(pt3, "point_3")


obj8 = doc.addObject("Part::Feature", "pt3")
obj8.Shape = Part.Vertex(pt3)
obj8.ViewObject.PointColor = (1.000,0.000,0.498)
obj8.ViewObject.PointSize = 5


arc = Part.Arc(p1, pt3, p2).toShape()

Part.show(arc, "arc_3p")

I suppose that extracting the 3rd click point and convert it to model coordinate (sorry I don't know the exact name), it is not a great problem.

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/
BryanL
Posts: 17
Joined: Mon Feb 15, 2021 5:56 am

Re: Available helper functions for scripting

Post by BryanL »

Is there a reason you can't use Part.Arc(vStart, vMid, vEnd) or Part.ArcOfCircle(circle, vStart, vEnd) ?

I believe order of vStart, vEnd determines direction ?
User avatar
onekk
Veteran
Posts: 6222
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: Available helper functions for scripting

Post by onekk »

problem is not defining the arc, is to define third point, when the two points are the diameter, so in one case it is right, in ohter cases it is wrong.

in fact the code uses it:

Code: Select all

arc = Part.Arc(p1, pt3, p2).toShape()
i.e if you see the example in one case the user want/need "upper" part in the other case it want/need "lower" part of the circle with radius p1, p2.

The "problem" is to teach the "build routine" what part to use to build the arc, what i have in mind was to draw the arc and with a third click on the mouse define the direction of the segment and use this to calculate the correct "half circle".

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/
BryanL
Posts: 17
Joined: Mon Feb 15, 2021 5:56 am

Re: Available helper functions for scripting

Post by BryanL »

Carlos,

I know FC is a work in progress but...

Any Cad or 3d drawing package has a set of vector / geometry / maths functions that are fundamental to their operation. They would be one of the first things created and once debugged not going to change much.

I know that different workbenches have their own specific functions that may be in a state of flux.

I know documentation takes time and I see some people have put in a lot of good effort.
If I continue with FC I will maybe document what I learn. It is quite a learning curve...

It is handy to have the method / attribute list in the python console. But I don't even know where to find the source code (other than it is on Github) and i don't read C very well, so i am not going to go there too often - maybe later...

Not meant to be a criticism either. Just I like to jump in the deep end but end up swimming around in circles... :roll:
BryanL
Posts: 17
Joined: Mon Feb 15, 2021 5:56 am

Re: Available helper functions for scripting

Post by BryanL »

onekk wrote: Sun May 02, 2021 4:34 pm problem is not defining the arc, is to define third point, when the two points are the diameter, so in one case it is right, in ohter cases it is wrong.

in fact the code uses it:

Code: Select all

arc = Part.Arc(p1, pt3, p2).toShape()
i.e if you see the example in one case the user want/need "upper" part in the other case it want/need "lower" part of the circle with radius p1, p2.

The "problem" is to teach the "build routine" what part to use to build the arc, what i have in mind was to draw the arc and with a third click on the mouse define the direction of the segment and use this to calculate the correct "half circle".

Regards

Carlo D.
My understanding is that pt3 lies on the segment you want, upper or lower.

I thought he wanted code not drawing with mouse...
edwilliams16
Veteran
Posts: 3192
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: Available helper functions for scripting

Post by edwilliams16 »

It seems like this algorithm is being discussed in two threads, which is inefficient at best. I've provided a solution in the other one.
https://forum.freecadweb.org/viewtopic. ... 10#p501223
I've seen so much struggling here over vector math, which crucially underlies a lot a scripting, I made a cut at a wiki page. It has yet to draw any significant comment for improvement - which would be welcomed. https://wiki.freecadweb.org/Sandbox:Edwilliams16
Post Reply