this Macro covers some constraint that I was not able to find around:
- Concentric constraint among non cylindrical parts
- Constraint on center Faces and/or Edges
inspired from Macro CenterFace and Macro WorkFeatures
it can be used in Assembly2, but it doesn't create any fixed constraint
Maurice
Code: Select all
# -*- coding: utf-8 -*-
# 29/04/2014
# select a face launch and list the center coordinate XYZ of face
# To change the color of the dot change
# red = 1.0 # 1 = 255
# green = 0.0 #
# blue = 0.0 #
# evolution of Macro_CenterFace
# and some part of Macro WorkFeature
#
# center objs faces/closed_edges to first obj face/closed_edge
#
__title__ = "Center Faces of Parts"
__author__ = "maurice"
__url__ = "kicad stepup"
__version__ = "0.24"
__date__ = "11.2016"
import FreeCAD, FreeCADGui, Draft, Part
from FreeCAD import Vector, Rotation, Placement
from FreeCAD import Base
cx = 1 # center x -> 1
cy = 1 # center y -> 1
cz = 1 # center z -> 1
create_points=False
use_bb = True #align center based on bounding boxes or center of mass
def say(msg):
FreeCAD.Console.PrintMessage(msg)
FreeCAD.Console.PrintMessage('\n')
def sayw(msg):
FreeCAD.Console.PrintWarning(msg)
FreeCAD.Console.PrintWarning('\n')
def angleBetween(e1, e2):
""" Return the angle (in degrees) between 2 edges.
"""
if isinstance(e1,Part.Edge) and isinstance(e2,Part.Edge):
# Create the Vector for first edge
v1 = e1.Vertexes[-1].Point
v2 = e1.Vertexes[0].Point
ve1 = v1.sub(v2)
# Create the Vector for second edge
v3 = e2.Vertexes[-1].Point
v4 = e2.Vertexes[0].Point
ve2 = v3.sub(v4)
elif isinstance(e1,Base.Vector) and isinstance(e2,Base.Vector):
ve1 = e1
ve2 = e2
elif isinstance(e1,Part.Edge) and isinstance(e2,Base.Vector):
v1 = e1.Vertexes[-1].Point
v2 = e1.Vertexes[0].Point
ve1 = v1.sub(v2)
ve2 = e2
elif isinstance(e1,Base.Vector) and isinstance(e2,Part.Edge):
ve1 = e1
v3 = e2.Vertexes[-1].Point
v4 = e2.Vertexes[0].Point
ve2 = v3.sub(v4)
else:
return
angle = ve1.getAngle(ve2)
import math
return math.degrees(angle), angle
sel = FreeCADGui.Selection.getSelection()
selEx = FreeCADGui.Selection.getSelectionEx()
say("number of objects: "+ str(len(selEx)))
objs = [selobj.Object for selobj in selEx]
say(objs)
coords = []
normals = []
coordPs = []
sEdge = []
j = 0
# .BoundBox.Center
#align faces
if (len(selEx) > 1) and (len(selEx)==len(sel)):
#s = obj.Shape
for fc in selEx:
say ("j= "+str(j))
say("len selEx "+str(len(selEx)))
s=fc
#selectedEdge = FreeCADGui.Selection.getSelectionEx()[j].SubObjects[0] # select one element SubObjects
selectedEdge = selEx[j].SubObjects[0] # select one element SubObjects
sEdge.append(selectedEdge)
pad=0
if str(fc.SubObjects[0])[1:5] != "Face":
wire = Part.Wire(selectedEdge)
fw = Part.Face(wire)
#Part.show(fw)
f=FreeCAD.ActiveDocument.addObject("Part::Feature","Facebinder")
f.Shape=fw
pad=1
#FreeCAD.ActiveDocument.recompute()
say("Label : "+ str(sel[j].Label)) # extract the Label
say("Name : "+ str(sel[j].Name)) # extract the Name
say( "Center Face Binder "+str(0)+" "+str(FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].CenterOfMass)) # Vector center mass to face
say( "Center Face Binder bb "+str(0)+" "+str(FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].BoundBox.Center)) # Vector center mass to face
else:
pad=0
f=Draft.makeFacebinder(s)
say("Label : "+ str(sel[j].Label)) # extract the Label
say("Name : "+ str(sel[j].Name)) # extract the Name
say( "Center Face Binder "+str(0)+" "+str(f.Shape.Faces[0].CenterOfMass)) # Vector center mass to face
say( "Center Face Binder bb "+str(0)+" "+str(f.Shape.Faces[0].BoundBox.Center)) # Vector center mass to face
# LineColor
red = 1.0 # 1 = 255
green = 0.0 #
blue = 0.0 #
if create_points:
if pad==0:
if use_bb:
Draft.makePoint(f.Shape.Faces[0].BoundBox.Center.x,f.Shape.Faces[0].BoundBox.Center.y,f.Shape.Faces[0].BoundBox.Center.z) # create a point
else:
Draft.makePoint(f.Shape.Faces[0].CenterOfMass.x,f.Shape.Faces[0].CenterOfMass.y,f.Shape.Faces[0].CenterOfMass.z) # create a point
FreeCADGui.activeDocument().activeObject().PointColor = (red, green, blue)
else:
if use_bb:
Draft.makePoint(FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].BoundBox.Center.x,FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].CenterOfMass.y,FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].CenterOfMass.z) # create a point
else:
Draft.makePoint(FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].CenterOfMass.x,FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].CenterOfMass.y,FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].CenterOfMass.z) # create a point
FreeCADGui.activeDocument().activeObject().PointColor = (red, green, blue)
if pad==0:
if use_bb:
coordNx = f.Shape.Faces[0].BoundBox.Center.x
coordNy = f.Shape.Faces[0].BoundBox.Center.y
coordNz = f.Shape.Faces[0].BoundBox.Center.z
coordP = f.Shape.Faces[0].BoundBox.Center
else:
coordNx = f.Shape.Faces[0].CenterOfMass.x
coordNy = f.Shape.Faces[0].CenterOfMass.y
coordNz = f.Shape.Faces[0].CenterOfMass.z
coordP = f.Shape.Faces[0].CenterOfMass
else:
if use_bb:
coordNx = FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].BoundBox.Center.x
coordNy = FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].BoundBox.Center.y
coordNz = FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].BoundBox.Center.z
coordP = FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].BoundBox.Center
else:
coordNx = FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].CenterOfMass.x
coordNy = FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].CenterOfMass.y
coordNz = FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].CenterOfMass.z
coordP = FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].CenterOfMass
coords.append ([coordNx,coordNy,coordNz])
coordPs.append (coordP)
norm = f.Shape.Faces[0].normalAt(0,0)
say (norm)
normals.append (norm)
FreeCAD.ActiveDocument.removeObject(f.Name)
if j>0:
pos=App.Vector(-coords[j][0]+coords[0][0],-coords[j][1]+coords[0][1],-coords[j][2]+coords[0][2])
## objs[j].Placement.move(pos)
m_angle, m_angle_rad = angleBetween(normals[0],normals[j])
say (m_angle)
Origin = Base.Vector(0, 0, 0)
rot_axis = normals[0].cross(normals[j])
rot_center = coordPs[j]
rot_angle = m_angle # + m_angleAlignFaces
say("axis,center,angle")
say(rot_axis)
say(rot_center)
say(rot_angle)
if rot_angle!=0:
Draft.rotate(objs[j],-rot_angle,rot_center,rot_axis)
say("Rotated : angle "+str(-rot_angle)+" center "+str(rot_center)+" axis "+str(rot_axis))
j=j+1
coords = []
normals = []
coordPs = []
j = 0
#align centers
if (len(selEx) >= 1) and (len(selEx)==len(sel)):
#s = obj.Shape
for fc in selEx:
s=fc
print j
#selectedEdge = FreeCADGui.Selection.getSelectionEx()[j].SubObjects[0] # select one element SubObjects
selectedEdge = sEdge[j] # select one element SubObjects
pad=0
if str(fc.SubObjects[0])[1:5] != "Face":
wire = Part.Wire(selectedEdge)
fw = Part.Face(wire)
#Part.show(fw)
f=FreeCAD.ActiveDocument.addObject("Part::Feature","Facebinder")
f.Shape=fw
pad=1
#FreeCAD.ActiveDocument.recompute()
else:
pad=0
f=Draft.makeFacebinder(s)
say("Label : "+ str(sel[j].Label)) # extract the Label
say("Name : "+ str(sel[j].Name)) # extract the Name
say( "Center Face Binder "+str(0)+" "+str(f.Shape.Faces[0].CenterOfMass)) # Vector center mass to face
say( "Center Face Binder bb "+str(0)+" "+str(f.Shape.Faces[0].BoundBox.Center)) # Vector center mass to face
# LineColor
red = 1.0 # 1 = 255
green = 0.0 #
blue = 0.0 #
if create_points:
if pad==0:
Draft.makePoint(f.Shape.Faces[0].CenterOfMass.x,f.Shape.Faces[0].CenterOfMass.y,f.Shape.Faces[0].CenterOfMass.z) # create a point
FreeCADGui.activeDocument().activeObject().PointColor = (red, green, blue)
else:
Draft.makePoint(FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].CenterOfMass.x,FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].CenterOfMass.y,FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].CenterOfMass.z) # create a point
FreeCADGui.activeDocument().activeObject().PointColor = (red, green, blue)
if pad==0:
if use_bb:
coordNx = f.Shape.Faces[0].BoundBox.Center.x
coordNy = f.Shape.Faces[0].BoundBox.Center.y
coordNz = f.Shape.Faces[0].BoundBox.Center.z
coordP = f.Shape.Faces[0].BoundBox.Center
else:
coordNx = f.Shape.Faces[0].CenterOfMass.x
coordNy = f.Shape.Faces[0].CenterOfMass.y
coordNz = f.Shape.Faces[0].CenterOfMass.z
coordP = f.Shape.Faces[0].CenterOfMass
norm = f.Shape.Faces[0].normalAt(0,0)
else:
if use_bb:
coordNx = FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].BoundBox.Center.x
coordNy = FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].BoundBox.Center.y
coordNz = FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].BoundBox.Center.z
coordP = FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].BoundBox.Center
else:
coordNx = FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].CenterOfMass.x
coordNy = FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].CenterOfMass.y
coordNz = FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].CenterOfMass.z
coordP = FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].CenterOfMass
norm = FreeCAD.ActiveDocument.getObject(f.Name).Shape.Faces[0].normalAt(0,0)
coords.append ([coordNx,coordNy,coordNz])
coordPs.append (coordP)
say (norm)
normals.append (norm)
FreeCAD.ActiveDocument.removeObject(f.Name)
if j>0:
pos=App.Vector(-coords[j][0]+coords[0][0],-coords[j][1]+coords[0][1],-coords[j][2]+coords[0][2])
objs[j].Placement.move(pos)
say("Moved : "+str(coordNx-coords[0][0])+" "+str(coordNy-coords[0][1])+" "+str(coordNz-coords[0][2]))
j=j+1
for obj in objs:
FreeCADGui.Selection.removeSelection(obj)
# except:
# App.Console.PrintError( "select a face"+"\n")