[Solved] how to get an orthogonal line

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:

[Solved] how to get an orthogonal line

Post by onekk »

Hello to all.

I'm driving mad, as my 3d algebra knowledge is not very deep (in effect is very poor).

I have a line defined by two point and I want to find a line rotated by 90 degree:

Code: Select all

import FreeCAD
from FreeCAD import Base, Rotation, Vector

import math

p1 = Vector(10,10,0)
p2 = Vector(20,20,0)

p4 = Vector(10,5,0)

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

Part.show(l_a, "line_a")

l_b = Part.LineSegment(p1, p4).toShape()
Part.show(l_b, "line_b")


def a2p(a, b):
    """calculate angle given two point in 2d"""

    delta_y = b.y - a.y
    delta_x = b.x - a.x
    return (math.atan2(delta_y, delta_x))

def dest_pt(pt, angle, length):
    """calculate destination point
        Parameters:
        pt    = starting point
        angle =  rad
        length = units
    """

    dpx = pt.x + math.cos(angle) * length
    dpy = pt.y + math.sin(angle) * length

    return Vector(dpx, dpy, pt.z)

angle1 = a2p(p1, p2)

p3 = dest_pt(p1, (angle1 - math.pi * 0.5), 10)

l_c = Part.LineSegment(p1, p3).toShape()
Part.show(l_c, "line_c")

Now I'm searching a method to do this without using my helpers functions, but I'm lacking knowledge of 3D math

TIA and Regards

Carlo D.
Last edited by onekk on Thu Apr 22, 2021 6:55 am, edited 1 time 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: how to get an orthogonal line

Post by heda »

chrisb
Veteran
Posts: 54288
Joined: Tue Mar 17, 2015 9:14 am

Re: how to get an orthogonal line

Post by chrisb »

How aout letting FreeCAD do it with Attachment "Normal to edge"?
A Sketcher Lecture with in-depth information is available in English, auf Deutsch, en français, en español.
User avatar
Chris_G
Veteran
Posts: 2601
Joined: Tue Dec 31, 2013 4:10 pm
Location: France
Contact:

Re: how to get an orthogonal line

Post by Chris_G »

The problem is that in 3D, there are an infinity of lines perpendicular to a given line segment.
They are in the normal plane :

Code: Select all

import FreeCAD
from FreeCAD import Vector

p1 = Vector(10,10,0)
p2 = Vector(20,20,0)
l_a = Part.LineSegment(p1, p2).toShape()
Part.show(l_a, "line_a")

normal_plane = Part.Plane()
normal_plane.Position = p1
normal_plane.Axis = p2 - p1
If you want to fix the length of the perpendicular lines, then they are defined by a circle :

Code: Select all

circle2d = Part.Geom2d.Circle2d()
circle2d.Radius = 2.0
normal_circle = circle2d.toShape(normal_plane)
Part.show(normal_circle)
for any point P3 on normal_circle, the line P1P3 will be perpendicular to LineSegment P1P2, and of desired length
edwilliams16
Veteran
Posts: 3191
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: how to get an orthogonal line

Post by edwilliams16 »

If you just want any arbitrary vector normal to a vector v, you can use:

Code: Select all

def someNormal(v):
    'Return some unit vector normal to v'
    xaxis = FreeCAD.Vector(1, 0, 0)
    yaxis = FreeCAD.Vector(0, 1, 0)
    zaxis = FreeCAD.Vector(0, 0, 1)
    axes =[xaxis, yaxis, zaxis]
    if v.Length <= 1e-15:
        return zaxis
    else:
        for axis in axes:
            vc = v.normalize().cross(axis)
            if vc.Length > 0.5: # at least one must be >= sqrt(2/3)
                break
        return vc.normalize()
        
if you have two FreeCAD.vectors v1 and v2 (which together define a plane), a unit normal to that plane is given by:

Code: Select all

def normalTo(v1, v2):
return (v1.cross(v2)).normalize()
The direction is given by the right hand rule from v1 to v2
User avatar
onekk
Veteran
Posts: 6222
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: how to get an orthogonal line

Post by onekk »

Many thanks I will try your suggestions.

I know that there is infinite lines but if P1 P2 will define a segment (segA ) and I want a perpendicular segment of length A at P2, there is one segment perpendicular if segA direction is say 45 degree from P1 perpendicular is 90 degree so it is the line passing from point at -45deg to 135deg supposed to have a segment of length b with P2 in the middle.

I want to draw this segment as I'm doing with my helper methods that work in 2D (in 3d is more complicated but you could limit the lines choosing a plane)

In fact it is intended to make polygon on XY plane to calculate geometrically some positions like when dealing with tangent of two circle (already done with some maths found around)

"Normal" things are puzzling as I could not find relation with math Vector and FreeCAD vectors as in math they define vector as direction and with a magnitude.

In FreeCAD I don't find as Vector.Length is a different thing (this is due to my bad knowledge of math and 3d math not a Free had issue) maybe if someone skilled could put in place some "3d math for dummies" I suppose that it will de a bestseller.

Many thanks to all and 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: 3191
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: how to get an orthogonal line

Post by edwilliams16 »

Can you make a drawing, showing the known information and what you want to calculate? I couldn’t follow your written description.
User avatar
onekk
Veteran
Posts: 6222
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: how to get an orthogonal line

Post by onekk »

See the code above with a2p I will extract the angle direction between point P1 and P2 and with dest_pt I "turn" by 90 Deg from P2 to point P3 that defines my perpendicular line.

I suppose there are better built in equivalent methods in Freecad using Vector methods maybe.

TIA and 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: 6222
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: how to get an orthogonal line

Post by onekk »

I have seen this "article" but it has not been useful, using this technique didn't gave good result, maybe I have done something wrong.

Thanks

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: 6222
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: how to get an orthogonal line

Post by onekk »

edwilliams16 wrote: Wed Apr 21, 2021 8:40 am Can you make a drawing, showing the known information and what you want to calculate? I couldn’t follow your written description.

Code: Select all

import FreeCAD
from FreeCAD import Rotation, Vector

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

def tangent2L1C(l_a, l_b):

    pti = findIntersection(l_a, l_b, True, True)

    line_a = Part.makeLine(l_a.Vertexes[1].Point, pti[0])
    line_b = Part.makeLine(l_b.Vertexes[0].Point, pti[0])

    obj1 = DOC.addObject("Part::Feature", "p_line_a")
    obj1.Shape = line_a
    obj1.ViewObject.LineColor = (1.000,0.000,0.000)
    obj1.ViewObject.Visibility = True

    obj2 = DOC.addObject("Part::Feature", "p_line_b")
    obj2.Shape = line_b
    obj2.ViewObject.LineColor = (1.000,0.000,0.000)
    

def make_dbg_mk(tgt_pt, anchor, dist, desc):
    """make a marker to show point position"""

    l0_pos = dest_pt(tgt_pt, math.radians(anchor), dist)
    o_l = Draft.make_label(
        label_type="Custom",
        target_point=tgt_pt,
        placement=l0_pos,
        custom_text=desc 
        )
    o_l.ViewObject.ArrowType = "Arrow"
    o_l.ViewObject.ArrowSize = 1


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

p3 = Vector(134.88, 0.00, 0.0)
p4 = Vector(12.56, 0.00, 0.0)

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

Part.show(l_a, "line_a")

l_b = Part.LineSegment(p3, p4).toShape()
Part.show(l_b, "line_b")

res = tangent2L1C(l_a, l_b)

pti = findIntersection(l_a, l_b, True, True)[0]


make_dbg_mk(p2, 90, 10, "Point A")
make_dbg_mk(p3, 270, 10, "Point B")
I want to find the circle that is tangent to point A and point B and that round edges, like in this image:
K17id.png
K17id.png (61.86 KiB) Viewed 1121 times
I have calculated the point P, but I'm failing to find the perpendicular line to find the center, and even to trace the proper Bisection as angleBisection from draftgeoutils.intersections seems not to work .

I want to fillet the line between "point" A and "point B" with a circle that pass exactly for "point A" and "Point B", using the fillet function it will not work, so I'm trying to determine the center and the the bisection between "line a" and "line b" to pass to an Part.Arc(p1, p3, p2) to have a proper arc passing through "Point A " and "Point B"

So I have to find the intersection between the lines to find circle center, and then calculate the radius OA == OB

Probably I'm doing something wrong, or misunderstand something.

TIA and 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