Align Section Plane to selected Face

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Post Reply
jaisejames
Posts: 384
Joined: Sat Sep 24, 2016 6:51 am

Align Section Plane to selected Face

Post by jaisejames »

I am searching for macro for Aligning Section Plane to selected Face.

Any macro exist?
mario52
Veteran
Posts: 4697
Joined: Wed May 16, 2012 2:13 pm

Re: Align Section Plane to selected Face

Post by mario52 »

hi
example create plane to selected face (all directions)

Code: Select all

#https://forum.freecadweb.org/viewtopic.php?f=22&t=27002&p=216033&hilit=Macro_FCPlane#p216033
#Align Section Plane to selected Face
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
"""
***************************************************************************
*   Copyright (c) 2017 2018 <mario52>                                     *
*                                                                         *
*   This file is a supplement to the FreeCAD CAx development system.      *
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU Lesser General Public License (LGPL)    *
*   as published by the Free Software Foundation; either version 2 of     *
*   the License, or (at your option) any later version.                   *
*   for detail see the LICENCE text file.                                 *
**                                                                       **
*   Use at your own risk. The author assumes no liability for data loss.  *
*              It is advised to backup your data frequently.              *
*             If you do not trust the software do not use it.             *
**                                                                       **
*   This software is distributed in the hope that it will be useful,      *
*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
*   GNU Library General Public License for more details.                  *
*                                                                         *
*   You should have received a copy of the GNU Library General Public     *
*   License along with this macro; if not, write to the Free Software     *
*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
*   USA                                                                   *
***************************************************************************
*   http://www.freecadweb.org/wiki/index.php?title=Macro_FCCircularText   *
*           WARNING! All changes in this file will be lost and            *  
*                  may cause malfunction of the program                   *
***************************************************************************
"""

__Title__    = "FCPlane"
__Author__   = "Mario52"
__Version__  = "00.00"
__Date__     = "20/02/2018"

import Draft
from FreeCAD import Base
App = FreeCAD

doc = FreeCAD.ActiveDocument
if doc == None:
    doc = FreeCAD.newDocument()

selectedEdge = FreeCADGui.Selection.getSelectionEx()[0].SubObjects[0]   # select one element
sel = FreeCADGui.Selection.getSelection()
diagonalObject = int(sel[0].Shape.BoundBox.DiagonalLength)
plr = plDirection = FreeCAD.Placement()

if hasattr(selectedEdge,'Surface'):
    print( "surface")
    ########## section direction
    yL = selectedEdge.CenterOfMass
    uv = selectedEdge.Surface.parameter(yL)
    nv = selectedEdge.normalAt(uv[0], uv[1])
    direction = yL.sub(nv + yL)
    r = App.Rotation(App.Vector(0,0,1),direction)
    plDirection.Rotation.Q = r.Q
    plDirection.Base = yL
    plr = plDirection
    ########## section direction

    boundBoxLX  = boundBoxLY  = boundBoxLZ  = diagonalObject
    FCSpring = doc.addObject("App::DocumentObjectGroup","FcPlane")

    plan = App.ActiveDocument.addObject("Part::Plane","PlaneX-R")
    plan.Length=boundBoxLZ
    plan.Width=boundBoxLX
    plan.Placement = plr
    plan.Placement.Rotation = plan.Placement.Rotation.multiply(App.Rotation(0,-90,0))
    plan.Placement = plan.Placement.multiply(App.Placement(App.Vector(-float(plan.Length)/2.0,-float(plan.Width)/2.0,0.0), App.Rotation(App.Vector(0.0,0.0,0.0),0.0), App.Vector(0,0,0)))


    plan.ViewObject.LineColor = (1.00000,0.66667,0.00000)
    plan.ViewObject.ShapeColor = (0.6,0.0,0.0)
    plan.ViewObject.Transparency = 90
    plan.ViewObject.LineWidth = 1.0
    FCSpring.addObject(plan)

    ###
    plan = App.ActiveDocument.addObject("Part::Plane","PlaneY-V")
    plan.Length=boundBoxLY
    plan.Width=boundBoxLZ
    plan.Placement = plr
    plan.Placement.Rotation = plan.Placement.Rotation.multiply(App.Rotation(0,0,90))
    plan.Placement = plan.Placement.multiply(App.Placement(App.Vector(-float(plan.Length)/2.0,-float(plan.Width)/2.0,0.0), App.Rotation(App.Vector(0.0,0.0,0.0),0.0), App.Vector(0,0,0)))


    plan.ViewObject.LineColor = (1.00000,0.66667,0.00000)
    plan.ViewObject.ShapeColor = (0.0,0.6,0.0)
    plan.ViewObject.Transparency = 90
    plan.ViewObject.LineWidth = 1.0
    FCSpring.addObject(plan)

    ###
    plan = App.ActiveDocument.addObject("Part::Plane","PlaneZ-B")
    plan.Length=boundBoxLX
    plan.Width=boundBoxLY
    plan.Placement = plr
    plan.Placement = plan.Placement.multiply(App.Placement(App.Vector(-float(plan.Length)/2.0,-float(plan.Width)/2.0,0.0), App.Rotation(App.Vector(0.0,0.0,0.0),0.0), App.Vector(0,0,0)))


    plan.ViewObject.LineColor = (1.0,1.0,1.0)
    plan.ViewObject.ShapeColor = (0.0,0.0,0.6)
    plan.ViewObject.Transparency = 90
    plan.ViewObject.LineWidth = 1.0
    FCSpring.addObject(plan)

    #create axis
    points=[FreeCAD.Vector(0.0,0.0,0.0),FreeCAD.Vector(0.0,0.0,boundBoxLX)]
    centerX = Draft.makeWire(points,closed=False,face=False,support=None)
    centerX.Placement = plr
    centerX.Placement.Rotation = centerX.Placement.Rotation.multiply(App.Rotation(0,90,0))
    centerX.Placement = centerX.Placement.multiply(App.Placement(App.Vector(0.0,0.0,-float(boundBoxLX)/2.0), App.Rotation(App.Vector(0.0,0.0,0.0),0.0), App.Vector(0,0,0)))
    centerX.ViewObject.LineColor = (1.0,1.0,1.0)
    centerX.ViewObject.LineWidth = 1.0
    centerX.ViewObject.DrawStyle = str("Dashdot")
    centerX.Label = str("Axis White PlaneX")
    FCSpring.addObject(centerX)

    points=[FreeCAD.Vector(0.0,0.0,0.0),FreeCAD.Vector(0.0,0.0,boundBoxLX)]
    centerY = Draft.makeWire(points,closed=False,face=False,support=None)
    centerY.Placement = plr
    centerY.Placement.Rotation = centerY.Placement.Rotation.multiply(App.Rotation(0,90,90))
    centerY.Placement = centerY.Placement.multiply(App.Placement(App.Vector(0.0,0.0,-float(boundBoxLX)/2.0), App.Rotation(App.Vector(0.0,0.0,0.0),0.0), App.Vector(0,0,0)))
    centerY.ViewObject.LineColor = (1.0,1.0,1.0)
    centerY.ViewObject.LineWidth = 1.0
    centerY.ViewObject.DrawStyle = str("Dashdot")
    centerY.Label = str("Axis White PlaneY")
    FCSpring.addObject(centerY)

    points=[FreeCAD.Vector(0.0,0.0,0.0),FreeCAD.Vector(0.0,0.0,boundBoxLX)]
    centerZ = Draft.makeWire(points,closed=False,face=False,support=None)
    centerZ.Placement = plr
    centerZ.Placement.Rotation = centerZ.Placement.Rotation.multiply(App.Rotation(0,0,0))
    centerZ.Placement = centerZ.Placement.multiply(App.Placement(App.Vector(0.0,0.0,-float(boundBoxLX)/2.0), App.Rotation(App.Vector(0.0,0.0,0.0),0.0), App.Vector(0,0,0)))
    centerZ.ViewObject.LineColor = (1.0,1.0,1.0)
    centerZ.ViewObject.LineWidth = 1.0
    centerZ.ViewObject.DrawStyle = str("Dashdot")
    centerZ.Label = str("Axis White PlaneZ")
    FCSpring.addObject(centerZ)

##############################################
    FreeCAD.ActiveDocument.recompute()
else:
    print( "select a face")

EDIT 27/09/2021 11h09 Paris : adding the parenthesis on print() for compatible Python 3

mario
Last edited by mario52 on Mon Sep 27, 2021 9:13 am, edited 1 time in total.
Maybe you need a special feature, go into Macros_recipes and Code_snippets, Topological_data_scripting.
My macros on Gist.github here complete macros Wiki and forum.
User avatar
easyw-fc
Veteran
Posts: 3633
Joined: Thu Jul 09, 2015 9:34 am

Re: Align Section Plane to selected Face

Post by easyw-fc »

jaisejames wrote: Tue Feb 20, 2018 6:32 am I am searching for macro for Aligning Section Plane to selected Face.

Any macro exist?
you may want to see at
Manipulator WB
Aligner does it
(old macro was https://www.freecadweb.org/wiki/Macro_C ... s_or_Edges)
jaisejames
Posts: 384
Joined: Sat Sep 24, 2016 6:51 am

Re: Align Section Plane to selected Face

Post by jaisejames »

Thank you all for quick support. I will study these macros.
My aim to Draft section plane work automatically align

First I will have to create Boundbox size based on Section plane linked objects[as given code]. Then I need to align to selected face based on above macros.

Code: Select all

import Part			
ObjectsList = [ sub.Shape for sub in obj.Objects ]
pc = Part.Compound(ObjectsList)
obj.ViewObject.DisplayLength = pc.BoundBox.XLength
obj.ViewObject.DisplayHeight = pc.BoundBox.YLength
Also align based on Draft Axis. so I can generate sectional view quickly.
jaisejames
Posts: 384
Joined: Sat Sep 24, 2016 6:51 am

Re: Align Section Plane to selected Face

Post by jaisejames »

i am able to create a macro. but it is not working. pls see the below code

Code: Select all

import Arch, Part
import FreeCAD as App
import FreeCADGui as Gui

v = Gui.activeDocument().activeView()
class Select_object:
	def __init__(self,view):
		self.SectionPlane = None
		self.selectedEdge = None
		self.view = view
		App.Console.PrintMessage("choose the SectionPlane\n")
		Gui.Selection.clearSelection()
		self.klick_event = self.view.addEventCallback(
			"SoMouseButtonEvent", self.choose_SectionPlane)

	def choose_SectionPlane(self, cb):
		if cb["State"] == "DOWN":
			sel = Gui.Selection.getSelection()
			if len(sel) > 0:
				self.SectionPlane = sel[0]
				Gui.Selection.clearSelection()
				self.view.removeEventCallback(
					"SoMouseButtonEvent", self.klick_event)
				self.klick_event = self.view.addEventCallback(
					"SoMouseButtonEvent", self.choose_Face)
				App.Console.PrintMessage("choose_Face_to_Align\n")
	
	def choose_Face(self, cb):
		if cb["State"] == "DOWN":
			selectedEdge = Gui.Selection.getSelectionEx()[0].SubObjects[0]   # select one element
			sel = Gui.Selection.getSelection()
			if sel:
				self.view.removeEventCallback(
					"SoMouseButtonEvent", self.klick_event)
				self.Align_SectionPlane(self.SectionPlane,selectedEdge)

	def Align_SectionPlane(self,SectionPlane,selectedEdge):
		ObjectsList = [ obj.Shape for obj in SectionPlane.Objects ]
		pc = Part.Compound(ObjectsList)
		diagonalObject = int(pc.Shape.BoundBox.DiagonalLength)
		plr = plDirection = FreeCAD.Placement()
		
		if hasattr(selectedEdge,'Surface'):
			print "surface"
			########## section direction
			yL = selectedEdge.CenterOfMass
			uv = selectedEdge.Surface.parameter(yL)
			nv = selectedEdge.normalAt(uv[0], uv[1])
			direction = yL.sub(nv + yL)
			r = App.Rotation(App.Vector(0,0,1),direction)
			plDirection.Rotation.Q = r.Q
			plDirection.Base = yL
			plr = plDirection
			boundBoxLX  = boundBoxLY  = boundBoxLZ  = diagonalObject
		
			########## make Section Plane Aligned to selected face
			SectionPlane.ViewObject.DisplayHeight = boundBoxLX
			SectionPlane.ViewObject.DisplayLength = boundBoxLY
			SectionPlane.Placement = plr
			SectionPlane.Placement = SectionPlane.Placement.multiply(App.Placement(App.Vector(-float(boundBoxLX)/2.0,-float(boundBoxLY)/2.0,0.0), App.Rotation(App.Vector(0.0,0.0,0.0),0.0), App.Vector(0,0,0)))
			App.activeDocument().recompute()
			
			SectionPlane.ViewObject.LineColor = (1.00000,0.66667,0.00000)
			SectionPlane.ViewObject.LineWidth = 1.0

Select_object(v)
jaisejames
Posts: 384
Joined: Sat Sep 24, 2016 6:51 am

Re: Align Section Plane to selected Face

Post by jaisejames »

I change some code . now it is working

Code: Select all

import Arch, Part
import FreeCAD as App
import FreeCADGui as Gui

view = Gui.ActiveDocument.ActiveView
class Select_object(object):
	def __init__(self,view):
		self.SectionPlane = None
		self.selectedEdge = None
		self.view = Gui.ActiveDocument.ActiveView
		App.Console.PrintMessage("choose the SectionPlane\n")
		Gui.Selection.clearSelection()
		self.klick_event = self.view.addEventCallback("SoMouseButtonEvent", self.choose_SectionPlane)

	def choose_SectionPlane(self, cb):
		if cb["State"] == "DOWN":
			sel = Gui.Selection.getSelection()
			if len(sel) > 0:
				self.SectionPlane = sel[0]
				Gui.Selection.clearSelection()
				self.view.removeEventCallback("SoMouseButtonEvent", self.klick_event)
				self.klick_event = self.view.addEventCallback("SoMouseButtonEvent", self.choose_Face)
				App.Console.PrintMessage("choose_Face_to_Align\n")
	
	def choose_Face(self, cb):
		if cb["State"] == "DOWN":
			sel = Gui.Selection.getSelectionEx()
			if len(sel) > 0:
				selectedEdge = sel[0].SubObjects[0]   # select one element
				Gui.Selection.clearSelection()
				self.view.removeEventCallback("SoMouseButtonEvent", self.klick_event)
				self.Align_SectionPlane(self.SectionPlane,selectedEdge)

	def Align_SectionPlane(self,SectionPlane,selectedEdge):
		ObjectsList = [ obj.Shape for obj in SectionPlane.Objects ]
		pc = Part.Compound(ObjectsList)
		diagonalObject = int(pc.BoundBox.DiagonalLength)
		plr = plDirection = FreeCAD.Placement()
		
		if hasattr(selectedEdge,'Surface'):
			print "surface"
			########## section direction
			yL = selectedEdge.CenterOfMass
			uv = selectedEdge.Surface.parameter(yL)
			nv = selectedEdge.normalAt(uv[0], uv[1])
			direction = yL.sub(nv + yL)
			r = App.Rotation(App.Vector(0,0,1),direction)
			plDirection.Rotation.Q = r.Q
			plDirection.Base = yL
			plr = plDirection
			boundBoxLX  = boundBoxLY  = boundBoxLZ  = diagonalObject
		
			########## make Section Plane Aligned to selected face
			SectionPlane.ViewObject.DisplayHeight = boundBoxLX
			SectionPlane.ViewObject.DisplayLength = boundBoxLY
			SectionPlane.Placement = plr
			App.activeDocument().recompute()
			
			SectionPlane.ViewObject.LineColor = (1.00000,0.66667,0.00000)
			SectionPlane.ViewObject.LineWidth = 1.0

Select_object(view)
Post Reply