## Faces or Edges constraint among non cylindrical parts Macro

Need help, or want to share a macro? Post here!
easyw-fc
Posts: 2915
Joined: Thu Jul 09, 2015 9:34 am

### Faces or Edges constraint among non cylindrical parts Macro

Hi,
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
center-align-faces-edges.gif (939.34 KiB) Viewed 2910 times

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"
__version__ = "0.24"
__date__    = "11.2016"

from FreeCAD import Vector, Rotation, Placement

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):

def sayw(msg):

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

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)
if str(fc.SubObjects[0])[1:5] != "Face":
wire = Part.Wire(selectedEdge)
fw = Part.Face(wire)
#Part.show(fw)
f.Shape=fw
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:
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 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
else:
if use_bb:
else:
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:
else:
coords.append ([coordNx,coordNy,coordNz])
coordPs.append (coordP)
norm = f.Shape.Faces[0].normalAt(0,0)
say (norm)
normals.append (norm)
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 (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
if str(fc.SubObjects[0])[1:5] != "Face":
wire = Part.Wire(selectedEdge)
fw = Part.Face(wire)
#Part.show(fw)
f.Shape=fw
else:
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:
Draft.makePoint(f.Shape.Faces[0].CenterOfMass.x,f.Shape.Faces[0].CenterOfMass.y,f.Shape.Faces[0].CenterOfMass.z) # create a point
else:
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:
else:
coords.append ([coordNx,coordNy,coordNz])
coordPs.append (coordP)
say (norm)
normals.append (norm)
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:

# except:
#     App.Console.PrintError( "select a face"+"\n")

``````
Last edited by easyw-fc on Mon Nov 21, 2016 5:32 pm, edited 1 time in total.
mario52
Posts: 3235
Joined: Wed May 16, 2012 2:13 pm

### Re: Faces or Edges constraint among non cylindrical parts Macro

hi
nice why not ask right to put your macros in the wiki Macros_recipes

(same style the excellent Flamingo)

mario
Maybe you need a special feature, go into Macros_recipes and Code_snippets, Topological_data_scripting, Dialog creation. My macros on Gist.github.
triplus
Posts: 9475
Joined: Mon Dec 12, 2011 4:45 pm

### Re: Faces or Edges constraint among non cylindrical parts Macro

Such tools are usable in a lot of tasks therefore thanks for sharing.
easyw-fc
Posts: 2915
Joined: Thu Jul 09, 2015 9:34 am

### Re: Faces or Edges constraint among non cylindrical parts Macro

triplus wrote:Such tools are usable in a lot of tasks therefore thanks for sharing.
thx
I just improved a bit the macro with a GUI to configure what to align and in which mode:
center-align-faces.png (12.65 KiB) Viewed 2827 times
mario52 wrote:hi
nice why not ask right to put your macros in the wiki Macros_recipes
@mario52 I tried to write the macro in the wiki (I have already the rights to do it), but when I try to create the file, I don't get the Macro Template, but just a blank page to write over... Am I missing something?

thx
Maurice

Code: Select all

``````# -*- coding: utf-8 -*-

# 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"
__version__ = "0.27"
__date__    = "11.2016"

#
# Created: Wed Nov 23 23:17:52 2016
#      by: pyside-uic 0.2.15 running on PySide 1.2.2
#
# WARNING! All changes made in this file will be lost!

from PySide import QtCore, QtGui

class Ui_CenterAlignObjectsFacesEdges(object):
def setupUi(self, CenterAlignObjectsFacesEdges):
CenterAlignObjectsFacesEdges.setObjectName("CenterAlignObjectsFacesEdges")
CenterAlignObjectsFacesEdges.setWindowModality(QtCore.Qt.NonModal)
CenterAlignObjectsFacesEdges.resize(367, 351)
CenterAlignObjectsFacesEdges.setFocusPolicy(QtCore.Qt.NoFocus)
self.verticalLayout = QtGui.QVBoxLayout(CenterAlignObjectsFacesEdges)
self.verticalLayout.setObjectName("verticalLayout")
self.verticalLayout_2 = QtGui.QVBoxLayout()
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.lbl_info = QtGui.QLabel(CenterAlignObjectsFacesEdges)
font = QtGui.QFont()
font.setWeight(75)
font.setBold(True)
self.lbl_info.setFont(font)
self.lbl_info.setObjectName("lbl_info")
self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.groupBox = QtGui.QGroupBox(CenterAlignObjectsFacesEdges)
self.groupBox.setObjectName("groupBox")
self.rb_bb.setGeometry(QtCore.QRect(11, 20, 161, 20))
self.rb_bb.setChecked(True)
self.rb_bb.setObjectName("rb_bb")
self.rb_mass.setGeometry(QtCore.QRect(200, 20, 121, 20))
self.rb_mass.setObjectName("rb_mass")
self.hLayout2 = QtGui.QHBoxLayout()
self.hLayout2.setObjectName("hLayout2")
self.groupBox_2 = QtGui.QGroupBox(CenterAlignObjectsFacesEdges)
self.groupBox_2.setObjectName("groupBox_2")
self.rb_centers.setGeometry(QtCore.QRect(20, 20, 261, 20))
self.rb_centers.setObjectName("rb_centers")
self.rb_planes.setGeometry(QtCore.QRect(20, 50, 261, 20))
self.rb_planes.setObjectName("rb_planes")
self.rb_centers_planes.setGeometry(QtCore.QRect(20, 80, 261, 20))
self.rb_centers_planes.setChecked(True)
self.rb_centers_planes.setObjectName("rb_centers_planes")
self.cb_x = QtGui.QCheckBox(self.groupBox_2)
self.cb_x.setGeometry(QtCore.QRect(290, 40, 41, 20))
self.cb_x.setChecked(True)
self.cb_x.setObjectName("cb_x")
self.cb_y = QtGui.QCheckBox(self.groupBox_2)
self.cb_y.setGeometry(QtCore.QRect(290, 60, 41, 20))
self.cb_y.setChecked(True)
self.cb_y.setObjectName("cb_y")
self.cb_z = QtGui.QCheckBox(self.groupBox_2)
self.cb_z.setGeometry(QtCore.QRect(290, 80, 41, 20))
self.cb_z.setChecked(True)
self.cb_z.setObjectName("cb_z")
self.label_2 = QtGui.QLabel(self.groupBox_2)
self.label_2.setGeometry(QtCore.QRect(270, 20, 61, 16))
self.label_2.setObjectName("label_2")
self.verticalLayout_3 = QtGui.QVBoxLayout()
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.cb_inv_normals = QtGui.QCheckBox(CenterAlignObjectsFacesEdges)
self.cb_inv_normals.setObjectName("cb_inv_normals")
self.line = QtGui.QFrame(CenterAlignObjectsFacesEdges)
self.line.setFrameShape(QtGui.QFrame.HLine)
self.line.setObjectName("line")
self.label = QtGui.QLabel(CenterAlignObjectsFacesEdges)
self.label.setObjectName("label")
self.hLayout1 = QtGui.QHBoxLayout()
self.hLayout1.setObjectName("hLayout1")
self.btnAlign = QtGui.QPushButton(CenterAlignObjectsFacesEdges)
self.btnAlign.setObjectName("btnAlign")

self.retranslateUi(CenterAlignObjectsFacesEdges)
QtCore.QMetaObject.connectSlotsByName(CenterAlignObjectsFacesEdges)

def retranslateUi(self, CenterAlignObjectsFacesEdges):
CenterAlignObjectsFacesEdges.setWindowTitle(QtGui.QApplication.translate("CenterAlignObjectsFacesEdges", "Center Align Faces/Edges", None, QtGui.QApplication.UnicodeUTF8))
self.lbl_info.setText(QtGui.QApplication.translate("CenterAlignObjectsFacesEdges", "Select multiple face(s) or closed Edges and click Align", None, QtGui.QApplication.UnicodeUTF8))
self.groupBox.setTitle(QtGui.QApplication.translate("CenterAlignObjectsFacesEdges", "reference", None, QtGui.QApplication.UnicodeUTF8))
self.rb_bb.setText(QtGui.QApplication.translate("CenterAlignObjectsFacesEdges", "Center of Bounding Box", None, QtGui.QApplication.UnicodeUTF8))
self.rb_mass.setText(QtGui.QApplication.translate("CenterAlignObjectsFacesEdges", "Center of Mass", None, QtGui.QApplication.UnicodeUTF8))
self.groupBox_2.setTitle(QtGui.QApplication.translate("CenterAlignObjectsFacesEdges", "aligning", None, QtGui.QApplication.UnicodeUTF8))
self.rb_centers.setText(QtGui.QApplication.translate("CenterAlignObjectsFacesEdges", "Align Faces/Edges Centers", None, QtGui.QApplication.UnicodeUTF8))
self.rb_planes.setText(QtGui.QApplication.translate("CenterAlignObjectsFacesEdges", "Align Faces/Edges Planes", None, QtGui.QApplication.UnicodeUTF8))
self.rb_centers_planes.setText(QtGui.QApplication.translate("CenterAlignObjectsFacesEdges", "Align Faces/Edges Centers and Planes", None, QtGui.QApplication.UnicodeUTF8))
self.cb_x.setText(QtGui.QApplication.translate("CenterAlignObjectsFacesEdges", "x", None, QtGui.QApplication.UnicodeUTF8))
self.cb_y.setText(QtGui.QApplication.translate("CenterAlignObjectsFacesEdges", "y", None, QtGui.QApplication.UnicodeUTF8))
self.cb_z.setText(QtGui.QApplication.translate("CenterAlignObjectsFacesEdges", "z", None, QtGui.QApplication.UnicodeUTF8))
self.label_2.setText(QtGui.QApplication.translate("CenterAlignObjectsFacesEdges", "center on:", None, QtGui.QApplication.UnicodeUTF8))
self.cb_inv_normals.setText(QtGui.QApplication.translate("CenterAlignObjectsFacesEdges", "invert Normal for Plane", None, QtGui.QApplication.UnicodeUTF8))
self.label.setText(QtGui.QApplication.translate("CenterAlignObjectsFacesEdges", "First Face/Edge is the Reference for alignment", None, QtGui.QApplication.UnicodeUTF8))
self.btnAlign.setText(QtGui.QApplication.translate("CenterAlignObjectsFacesEdges", "Align", None, QtGui.QApplication.UnicodeUTF8))

### ------------------------------------------------------------------------------------ ###
### ---------code to be inserted and remove from new generation------------------------- ###
### ------------------------------------------------------------------------------------ ###
self.btnAlign.clicked.connect(self.onAlign)

def onAlign(self):
say("Align clicked")
normal=0;type=0;mode=0
if self.cb_inv_normals.isChecked():
say("Align Normal Inverted")
normal=1
if self.rb_bb.isChecked():
say("centering on Bounding Boxes")
else:
say("centering on Center of Mass")
type=1
if self.rb_centers_planes.isChecked():
say("Centering and aligning Planes")
elif self.rb_centers.isChecked():
say("Centering Faces/Edges")
mode=1
else:
say("Aligning Planes")
mode=2
cx=0;cy=0;cz=0
if self.cb_x.isChecked():
cx=1
if self.cb_y.isChecked():
cy=1
if self.cb_z.isChecked():
cz=1
Align(normal,type,mode,cx,cy,cz)

def say(msg):

def sayw(msg):

def singleInstance():
app = QtGui.qApp

for i in app.topLevelWidgets():
if i.objectName() == "CenterAlignObjectsFacesEdges":
i.deleteLater()
else:
pass
#    dw=t.findChildren(QtGui.QDockWidget)
#    #print str(dw)
#    for i in dw:
#        print str(i.objectName())
#        if str(i.objectName()) == "CenterAlignObjectsFacesEdges": #"kicad StepUp 3D tools":
#            i.deleteLater()
#        else:
#            pass

singleInstance()

CenterAlignObjectsFacesEdges = QtGui.QWidget()
ui = Ui_CenterAlignObjectsFacesEdges()
ui.setupUi(CenterAlignObjectsFacesEdges)
#CenterAlignObjectsFacesEdges.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
CenterAlignObjectsFacesEdges.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint | QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowMinimizeButtonHint | QtCore.Qt.WindowSystemMenuHint);
#self.setWindowFlags(self.windowFlags() & ~QtCore.Qt.WindowStaysOnTopHint)
CenterAlignObjectsFacesEdges.show()

# def center(self):
#     frameGm = self.frameGeometry()
#     screen = QtGui.QApplication.desktop().screenNumber(QtGui.QApplication.desktop().cursor().pos())
#     #say(screen)
#     centerPoint = QtGui.QApplication.desktop().screenGeometry(screen).center()
#     #say(centerPoint)
#     frameGm.moveCenter(centerPoint)
#     self.move(frameGm.center)

#center(CenterAlignObjectsFacesEdges)
CenterAlignObjectsFacesEdges.move(10,100)
## to do:
## ok single instance
## - always on top
## - no maximize
### ------------------------------------------------------------------------------------ ###
### ---------code to be inserted and remove from new generation------------------------- ###
### ------------------------------------------------------------------------------------ ###

def Align(normal,type,mode,cx,cy,cz):
#cx = 1  # center x -> 1
#cy = 1  # center y -> 1
#cz = 1  # center z -> 1
say(str(cx)+str(cy)+str(cz))
create_points=False
use_bb = True #align center based on bounding boxes or center of mass
if type==1:
use_bb = False #align center based on bounding boxes or center of mass

#def say(msg):
#
#def sayw(msg):

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

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)
if str(fc.SubObjects[0])[1:5] != "Face":
wire = Part.Wire(selectedEdge)
fw = Part.Face(wire)
#Part.show(fw)
f.Shape=fw
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:
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 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
else:
if use_bb:
else:
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:
else:
coords.append ([coordNx,coordNy,coordNz])
coordPs.append (coordP)
#norm = f.Shape.Faces[0].normalAt(0,0)
if j==0:
if normal==1:
norm = f.Shape.Faces[0].normalAt(0,0)*-1
else:
norm = f.Shape.Faces[0].normalAt(0,0)
else:
norm = f.Shape.Faces[0].normalAt(0,0)
#else:
#    norm = f.Shape.Faces[0].normalAt(0,0)
say (norm)
normals.append (norm)
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 (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:
if mode==0 or mode==2:
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
if str(fc.SubObjects[0])[1:5] != "Face":
wire = Part.Wire(selectedEdge)
fw = Part.Face(wire)
#Part.show(fw)
f.Shape=fw
else:
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:
Draft.makePoint(f.Shape.Faces[0].CenterOfMass.x,f.Shape.Faces[0].CenterOfMass.y,f.Shape.Faces[0].CenterOfMass.z) # create a point
else:
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:
else:
coords.append ([coordNx,coordNy,coordNz])
coordPs.append (coordP)
say (norm)
normals.append (norm)
if j>0:
pos=App.Vector((-coords[j][0]+coords[0][0])*cx,(-coords[j][1]+coords[0][1])*cy,(-coords[j][2]+coords[0][2])*cz)
if mode==0 or mode==1:
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:

# except:
#     App.Console.PrintError( "select a face"+"\n")

``````
mario52
Posts: 3235
Joined: Wed May 16, 2012 2:13 pm

### Re: Faces or Edges constraint among non cylindrical parts Macro

hi
done i clicked op "Create page"
you complete your page and when you are finished, delete the template "VeryImportantMessage"
Macro_Center_Align_Objects_with_Faces_or_Edges

mario
Maybe you need a special feature, go into Macros_recipes and Code_snippets, Topological_data_scripting, Dialog creation. My macros on Gist.github.
easyw-fc
Posts: 2915
Joined: Thu Jul 09, 2015 9:34 am

### Re: Faces or Edges constraint among non cylindrical parts Macro

mario52 wrote:hi
done i clicked op "Create page"
mario
thx a lot
easyw-fc
Posts: 2915
Joined: Thu Jul 09, 2015 9:34 am

### Re: Faces or Edges constraint among non cylindrical parts Macro

I just updated the macro to work also with FC 0.17 Body containers
Macro_Center_Align_Objects_with_Faces_or_Edges
jp-willm
Posts: 364
Joined: Sat Feb 06, 2016 4:11 pm
Location: France (Alsace)
Contact:

### Re: Faces or Edges constraint among non cylindrical parts Macro

easyw-fc wrote:Hi,
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]

Hello,
Nice tool
Thank you !

I have create a svg icon :
Center_Align.svg
easyw-fc
Posts: 2915
Joined: Thu Jul 09, 2015 9:34 am

### Re: Faces or Edges constraint among non cylindrical parts Macro

jp-willm wrote: Hello,
Nice tool
Thank you !

I have create a svg icon :Center_Align.svg
Thx,