Snippets of python code.

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

Snippets of python code.

Post by onekk »

Hello, this post to add some ready made methods, that could be useful to other people.

They are not macro, but more some help for beginner to familiarize with code and maybe some inspiration for other to share some code.

Code: Select all


import FreeCAD
import Part
from FreeCAD import Vector
import DraftVecUtils

def calc_perp(line, p_len, p_pos=0.5, p_dir="l"):
    """Draw perpendicular line.

    calculate perpendicular line to the given line.

    Parameters:
    name    type   description
    line    obj    Part.LineSegment obj
    p_len   float  Length of the perpendicular
    p_pos   float  (0.0, 1.0) position of the perpendicular
                    0.0 = starting point 1.0 = ending point
                    if not specified middle point 0.5 is assumed
    p_dir   string  (l, r) l = left, r = right default 'left'

    """
    v1 = line.StartPoint
    v2 = line.EndPoint
    chord = v2.sub(v1)

    v_dir = -1 if p_dir == "l" else 1

    perp = chord.cross(Vector(0, 0, v_dir))
    startp = v1.add(chord.multiply(p_pos))

    if not DraftVecUtils.isNull(perp):
        perp.normalize()

    plen = perp.multiply(p_len)

    # print(plen)
    endp = startp.add(plen)

    line = Part.LineSegment(startp, endp)

    return line

EDIT: corrected some code above, not to use dir as parameter name
EDIT2: 30/11/2021 added a missing import statement
EDIT3: 01/12/2021 integrated a 'ternary if statement' with many thanks to @heda and @sliptonic


Hoping the code is clear, main code is scavenged from /Draft/ImportDXF.py where a bulge is caclulated, I've modified the code to obtain a perpendicular line to the given Part.LineSegment, see Docstring for other infos.

Process a list of "rotation" and "position" commands

Code: Select all

def pro_rot(obj, cmds):
    """Process a series of rotation commands.
    
    Helper for math impaired people.

    pass in cmds a tuple with a tuple element to obtain a rotation and
    a translation using:
    ("X, Y or Z", number in degree and sign), example ("X", 90), ("Z", -90)
    ("M", Vector(x, y, z)), example ("M", Vector(10, 0, 10))
   
    positions and placement are done "in order" of appearance, remeber to
    put a colon if the tuple is a singleton, example of cmd:
    r_pos = (("X", 90), )

    pro_rot(obj, r_pos)

    """
    m = obj.Placement.Matrix

    for cmd_pos in cmds:
        if cmd_pos[0] == "X":
            m.rotateX(math.radians(cmd_pos[1]))
        elif cmd_pos[0] == "Y":
            m.rotateY(math.radians(cmd_pos[1]))
        elif cmd_pos[0] == "Z":
            m.rotateZ(math.radians(cmd_pos[1]))
        elif cmd_pos[0] == "M":
            m.move(cmd_pos[1])

    obj.Placement.Matrix = m

This way it will be more easy and immediate to make complex rotation and moves (at least for "vectors math" impaired people like me).


If there is any error, feel free to signal them here.

Feel free to comment and maybe improve the code.

Regards

Carlo D.
Last edited by onekk on Wed Dec 01, 2021 9:16 am, edited 4 times in total.
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/
heda
Veteran
Posts: 1348
Joined: Sat Dec 12, 2015 5:49 pm

Re: Snippets of python code.

Post by heda »

nice with a docstring
my favourite construct for a simple if-statement is:

Code: Select all

v_dir = -1 if direction == "l" else 1
btw, changed dir to direction, since dir is a keyword which for good measure should not be reassigned to mean something else,
although it probably does not matter much in a function scope like this.
User avatar
onekk
Veteran
Posts: 6146
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: Snippets of python code.

Post by onekk »

Thanks, for noting.

I don't love too much one liner if statement expecially if it is have also an else.

I prefer to see the logic visually on the source code, this way is also recommended by PEP8.

But as usual is a matter of taste

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/
heron
Posts: 307
Joined: Mon Apr 20, 2020 5:32 pm

Re: Snippets of python code.

Post by heron »

onekk wrote: Mon Nov 29, 2021 1:55 pm Hello, this post to add some ready made methods, that could be useful to other people.

They are not macro, but more some help for beginner to familiarize with code and maybe some inspiration for other to share some code.
Hello,
I am trying to learn Python-FC and this post is big useful to me, so thank you a lot!

I have managed to understand the whole fragment, except one line:

Code: Select all

if not DraftVecUtils.isNull(perp):
I have been doing tests and I finally had to comment this line and the following to get the result as expected.
I have added some lines at the end to be able to execute it as a macro, also tried the code line of heda:

Code: Select all

import FreeCAD
import Part
from FreeCAD import Vector

def calc_perp(line, p_len, p_pos=0.5, p_dir="l"):

    """
    Draw perpendicular line.
    calculate perpendicular line to the given line.
    Parameters:
    name    type   description
    line       obj    Part.LineSegment obj
    p_len    float  Length of the perpendicular
    p_pos   float  (0.0, 1.0) position of the perpendicular
                    0.0 = starting point 1.0 = ending point
                    if not specified middle point 0.5 is assumed
    p_dir   string  (l, r) l = left, r = right default 'left'
    """
    v1 = line.StartPoint
    v2 = line.EndPoint
    chord = v2.sub(v1)

    #if p_dir == "l":
    #    v_dir = -1
    #else:
    #    v_dir = 1

    v_dir = -1 if p_dir == "l" else 1

    perp = chord.cross(Vector(0, 0, v_dir))
    startp = v1.add(chord.multiply(p_pos))
    #if not DraftVecUtils.isNull(perp):
    #perp.normalize()	
    plen = perp.multiply(p_len)
    print(plen)
    endp = startp.add(plen)
    line = Part.LineSegment(startp, endp)
    return line

p1 = Vector(1,2,5)
p2 = Vector(10,12,15)
mainLine = Part.LineSegment(p1, p2)
p_len = 2
myPerp = calc_perp(mainLine, p_len) 
print(myPerp)
I was drawing the vectors as lines in the draft module and this is the result:
Captura1.PNG
Captura1.PNG (62.07 KiB) Viewed 1807 times
I've had a nice afternoon and evening, thanks again :D
User avatar
sliptonic
Veteran
Posts: 3457
Joined: Tue Oct 25, 2011 10:46 pm
Location: Columbia, Missouri
Contact:

Re: Snippets of python code.

Post by sliptonic »

onekk wrote: Mon Nov 29, 2021 6:19 pm
I don't love too much one liner if statement expecially if it is have also an else.

I prefer to see the logic visually on the source code, this way is also recommended by PEP8.
Please link to that pep8 recommendation. Heda's recommendation is called a 'ternary if statement' and it is very pythonic. I believe this is straight out of jeff knupps idiomatic python book.
User avatar
onekk
Veteran
Posts: 6146
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: Snippets of python code.

Post by onekk »

heron wrote: Mon Nov 29, 2021 10:25 pm

Code: Select all

if not DraftVecUtils.isNull(perp):
It was a missing import, corrected in the original code above.

Sorry for the inconvenience.

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/
User avatar
onekk
Veteran
Posts: 6146
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: Snippets of python code.

Post by onekk »

sliptonic wrote: Tue Nov 30, 2021 2:00 am Please link to that pep8 recommendation. Heda's recommendation is called a 'ternary if statement' and it is very pythonic. I believe this is straight out of jeff knupps idiomatic python book.
From this line and the following example.

Code: Select all

Compound statements (multiple statements on the same line) are generally discouraged
It seems that the example is discouraging the writing, at least in:

https://www.python.org/dev/peps/pep-0008/#indentation

Probably I've not guessed right, but IMHO writing an entire if ... then ... else on one line is less readable, but I'm not an authority in Python.

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/
User avatar
sliptonic
Veteran
Posts: 3457
Joined: Tue Oct 25, 2011 10:46 pm
Location: Columbia, Missouri
Contact:

Re: Snippets of python code.

Post by sliptonic »

The indentation reference is where you stick the conditional logic after the colon. That's very ugly and difficult to read.

The ternary if is a bit different. The whole thing functions (and is evaluated) as a single statement. It doesn't start with "if" but with an assignment.

I like them for two reasons. First, the statement might take a second longer to understand but it makes the program easier to read. It reduces vertical scrolling. It's a very common pattern and every bit counts.

Second, they make it less likely that an inexperienced programmer will later stick additional logic inside the if clause.

For the same reason I like and use list comprehension a lot.
User avatar
onekk
Veteran
Posts: 6146
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: Snippets of python code.

Post by onekk »

sliptonic wrote: Tue Nov 30, 2021 2:13 pm The indentation reference is where you stick the conditional logic after the colon. That's very ugly and difficult to read.
....
For the same reason I like and use list comprehension a lot.

Sorry, I've not looked with attention at @heda post.
heda wrote: Mon Nov 29, 2021 5:49 pm

Code: Select all

v_dir = -1 if direction == "l" else 1

Many thanks for the hints, and for the lesson. :)

As usual, learning is a never ending process.

Many thanks again to @heda and @sliptonic

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/
Post Reply