[solved] contribution/bugfix/PR Macro "Align View to Face"

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
tchernomax
Posts: 2
Joined: Sat Oct 01, 2022 6:20 pm

[solved] contribution/bugfix/PR Macro "Align View to Face"

Post by tchernomax »

Hello

First, I am a **complete** beginner on FreeCAD (but I have some knowledge on python).

I tried FreeCAD for a modest DIY woodworking project of mine (to help me figuring out all the angles and measures).

When all the pieces were done I struggle to create a good "TechDraw" because I can't manage to position the view exactly above the faces I wanted.

I found the Align View to Face macro but it doesn't work when parent object of the selected one have placement with a rotation.

For example
  • create a body "Body"
  • create a sketch "Sketch" (a simple rectangle)
  • pad the sketch.
  • change the "Body" placement (e.g. angle 45, axis (1,1,1))
  • try to align the view with any of the pad face → it doesn't work
From what I found, the problem is that

Code: Select all

faceSel.normalAt(0,0)
doesn't take into account parent object rotation.
I don't know if it a bug or if it's a well known behavior.

I modified the macro to apply a combination of the previously computed rotation with all the parents rotation.

It seems to work, but as I said I am a complete beginner at FreeCAD and maybe I am doing it wrong.

I didn't found way to do a PR on this macro on github (I didn't found from where the addon manager retrieve the macro code), also I have the feeling that FreeCAD is a lot "forum driven"… so here I am :) .

Well here is my modified version of "Align View to Face" macro:

Code: Select all

from pivy import coin

def pointAt(normal, up):
    z = normal
    y = up
    x = y.cross(z)
    y = z.cross(x)
   
    rot = App.Matrix()
    rot.A11 = x.x
    rot.A21 = x.y
    rot.A31 = x.z
   
    rot.A12 = y.x
    rot.A22 = y.y
    rot.A32 = y.z
   
    rot.A13 = z.x
    rot.A23 = z.y
    rot.A33 = z.z

    return App.Placement(rot).Rotation

sel=Gui.Selection.getSelectionEx()[0]
obj=sel.Object
face=sel.SubObjects[0]
dir = face.normalAt(0,0)
cam = FreeCADGui.ActiveDocument.ActiveView.getCameraNode()

if dir.z == 1 :
    rot = pointAt(dir, App.Vector(0.0,1.0,0.0))
elif dir.z == -1 :
    rot = pointAt(dir, App.Vector(0.0,1.0,0.0))
else :
    rot = pointAt(dir, App.Vector(0.0,0.0,1.0))

def computeRotation(obj):
    if not obj.Parents:
        # the object has no parent
        return obj.Placement.Rotation
    # the object has parent
    # we compute the rotation of it's parent and multiply it with it's rotation
    return parentRotate(obj.Parents[0][0]).multiply(obj.Placement.Rotation)

if obj.Parents:
    obj_par = obj.Parents[0][0]
    rot_par = computeRotation(obj_par)
    cam.orientation.setValue(rot_par.multiply(rot).Q)
else:
    cam.orientation.setValue(rot.Q)

Gui.SendMsgToActiveView("ViewSelection")
Can someone review it and maybe merge it.

Thanks in advance
Last edited by tchernomax on Sat Oct 22, 2022 10:51 am, edited 1 time in total.
chrisb
Veteran
Posts: 53921
Joined: Tue Mar 17, 2015 9:14 am

Re: contribution/bugfix/PR Macro "Align View to Face"

Post by chrisb »

Hi and welcome to the forum!

We seldom see here first posts offering something - thanks!

Ping @rockn.
A Sketcher Lecture with in-depth information is available in English, auf Deutsch, en français, en español.
User avatar
Bernard19
Posts: 887
Joined: Sun Feb 20, 2022 7:16 pm

Re: contribution/bugfix/PR Macro "Align View to Face"

Post by Bernard19 »

Hello
I'm copied the macro instead and I have an error message when i use the macro modified
AppData/Roaming/FreeCAD/Macro/Align_View_to_Face.FCMacro", line 30, in <module> obj=sel.Objet
The problem is for this line
sel=Gui.Selection.getSelectionEx()[0]
User avatar
onekk
Veteran
Posts: 6144
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: contribution/bugfix/PR Macro "Align View to Face"

Post by onekk »

Bernard19 wrote: Tue Oct 04, 2022 4:18 pm ...
What is the error?

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
Bernard19
Posts: 887
Joined: Sun Feb 20, 2022 7:16 pm

Re: contribution/bugfix/PR Macro "Align View to Face"

Post by Bernard19 »

I'm sorry. My copy was incompled
19:15:53 Traceback (most recent call last):
File "C:/Users/berna/AppData/Roaming/FreeCAD/Macro/Align_View_to_Face.FCMacro", line 30, in <module>
obj=sel.Objet
<class 'AttributeError'>: 'Gui.SelectionObject' object has no attribute 'Objet'

Code: Select all

OS: Windows 10 Version 2009
Word size of FreeCAD: 64-bit
Version: 0.21.30256 (Git)
Build type: Release
Branch: master
Hash: 55866fd62221beadad3cfd60915278b156609a66
Python 3.10.6, Qt 5.15.4, Coin 4.0.0, Vtk 9.1.0, OCC 7.6.2
Locale: French/France (fr_FR) [ OS: French/France (fr_FR) ]
User avatar
onekk
Veteran
Posts: 6144
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: contribution/bugfix/PR Macro "Align View to Face"

Post by onekk »

Bernard19 wrote: Tue Oct 04, 2022 5:18 pm ...
Seems to be a typo.

Code: Select all

 obj=sel.Objet
probably has to be Object

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
Bernard19
Posts: 887
Joined: Sun Feb 20, 2022 7:16 pm

Re: contribution/bugfix/PR Macro "Align View to Face"

Post by Bernard19 »

@onekkI have select all the code and i have it copy in a new file. Now it's good.
Thank you for your help.
Most certainly a typing error. It's new for me to edit file.
Cordially
User avatar
onekk
Veteran
Posts: 6144
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: contribution/bugfix/PR Macro "Align View to Face"

Post by onekk »

Bernard19 wrote: Wed Oct 05, 2022 12:11 pm ...
You arer welcome!

good to know you have solved your 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/
tchernomax
Posts: 2
Joined: Sat Oct 01, 2022 6:20 pm

Re: contribution/bugfix/PR Macro "Align View to Face"

Post by tchernomax »

I didn't saw my contribution had already been taken into account.

:D

Thanks a lot
Drf5n
Posts: 26
Joined: Thu Sep 22, 2022 8:24 pm

Re: [solved] contribution/bugfix/PR Macro "Align View to Face"

Post by Drf5n »

I extended it a bit to work on lines to give the point view of a line:

Code: Select all

# -*- coding: utf-8 -*-
# Set the current view perpendicular to the selected line
# Place la vue perpendiculairement a la line selectionnee
# 2013 Jonathan Wiedemann,
# 2016 Werner Mayer, 
# 2022 tchernomax, https://forum.freecadweb.org/viewtopic.php?p=630019#p630019
#
# modifications towards a point view of a line by David Forrest 2023-10-13
__title__   = "Align_View_to_Line"
__author__  = "Jonathan Wiedemann (Rockn)"
__url__     = "https://www.freecadweb.org/"
__Wiki__    = "https://wiki.freecadweb.org/Macro_Align_View_to_Face"
__version__ = "3.0"
__date__    = "2022/10/08"  #YYYY/MM/DD
#
from pivy import coin

def pointAt(normal, up):
    z = normal
    y = up
    x = y.cross(z)
    y = z.cross(x)
   
    rot = App.Matrix()
    rot.A11 = x.x
    rot.A21 = x.y
    rot.A31 = x.z
   
    rot.A12 = y.x
    rot.A22 = y.y
    rot.A32 = y.z
   
    rot.A13 = z.x
    rot.A23 = z.y
    rot.A33 = z.z

    return App.Placement(rot).Rotation

sel=Gui.Selection.getSelectionEx()[0]
obj=sel.Object
subobj=sel.SubObjects[0]
if subobj.ShapeType == "Face" :
	dir = subobj.normalAt(0,0)
if subobj.ShapeType == "Edge" :
	V0 = subobj.Vertexes[0]
	V1 = subobj.Vertexes[1]
	dir = (V1.Point - V0.Point)/V0.Point.distanceToPoint(V1.Point)
cam = FreeCADGui.ActiveDocument.ActiveView.getCameraNode()
if dir.z == 1 :
    rot = pointAt(dir, App.Vector(0.0,1.0,0.0))
elif dir.z == -1 :
    rot = pointAt(dir, App.Vector(0.0,1.0,0.0))
else :
    rot = pointAt(dir, App.Vector(0.0,0.0,1.0))

def computeRotation(obj):
    if not obj.Parents:
        # the object has no parent
        return obj.Placement.Rotation
    # the object has parent
    # we compute the rotation of it's parent and multiply it with it's rotation
    return parentRotate(obj.Parents[0][0]).multiply(obj.Placement.Rotation)

if obj.Parents:
    obj_par = obj.Parents[0][0]
    rot_par = computeRotation(obj_par)
    cam.orientation.setValue(rot_par.multiply(rot).Q)
else:
    cam.orientation.setValue(rot.Q)

Gui.SendMsgToActiveView("ViewSelection")
Post Reply