constraint: add LockAngle option
LockAngle option is available to the following constraints, * PlaneCoincident * PlaneAlignment * AxialAlignment * MultiParallel
This commit is contained in:
parent
9e98a55b07
commit
c2662d8cfd
|
@ -28,7 +28,7 @@ def _p(solver,partInfo,subname,shape):
|
||||||
partInfo.EntityMap[key] = h
|
partInfo.EntityMap[key] = h
|
||||||
return h
|
return h
|
||||||
|
|
||||||
def _n(solver,partInfo,subname,shape):
|
def _n(solver,partInfo,subname,shape,retAll=False):
|
||||||
'return a handle of a transformed normal quaterion derived from shape'
|
'return a handle of a transformed normal quaterion derived from shape'
|
||||||
if not solver:
|
if not solver:
|
||||||
if utils.isPlanar(shape):
|
if utils.isPlanar(shape):
|
||||||
|
@ -40,13 +40,24 @@ def _n(solver,partInfo,subname,shape):
|
||||||
if h:
|
if h:
|
||||||
system.log('cache {}: {}'.format(key,h))
|
system.log('cache {}: {}'.format(key,h))
|
||||||
else:
|
else:
|
||||||
|
h = []
|
||||||
|
|
||||||
system.NameTag = subname
|
system.NameTag = subname
|
||||||
e = system.addNormal3dV(*utils.getElementNormal(shape))
|
rot = utils.getElementRotation(shape)
|
||||||
|
e = system.addNormal3dV(*utils.getNormal(rot))
|
||||||
system.NameTag = partInfo.PartName
|
system.NameTag = partInfo.PartName
|
||||||
h = system.addTransform(e,*partInfo.Params,group=partInfo.Group)
|
h.append(system.addTransform(e,*partInfo.Params,group=partInfo.Group))
|
||||||
|
|
||||||
|
# also add x axis pointing quaterion for convenience
|
||||||
|
rot = FreeCAD.Rotation(FreeCAD.Vector(0,1,0),90).multiply(rot)
|
||||||
|
system.NameTag = subname + '.nx'
|
||||||
|
e = system.addNormal3dV(*utils.getNormal(rot))
|
||||||
|
system.NameTag = partInfo.PartName + '.nx'
|
||||||
|
h.append(system.addTransform(e,*partInfo.Params,group=partInfo.Group))
|
||||||
|
|
||||||
system.log('{}: {},{}'.format(key,h,partInfo.Group))
|
system.log('{}: {},{}'.format(key,h,partInfo.Group))
|
||||||
partInfo.EntityMap[key] = h
|
partInfo.EntityMap[key] = h
|
||||||
return h
|
return h if retAll else h[0]
|
||||||
|
|
||||||
def _l(solver,partInfo,subname,shape,retAll=False):
|
def _l(solver,partInfo,subname,shape,retAll=False):
|
||||||
'return a pair of handle of the end points of an edge in "shape"'
|
'return a pair of handle of the end points of an edge in "shape"'
|
||||||
|
@ -97,10 +108,10 @@ def _w(solver,partInfo,subname,shape,retAll=False):
|
||||||
system.log('cache {}: {}'.format(key,h))
|
system.log('cache {}: {}'.format(key,h))
|
||||||
else:
|
else:
|
||||||
p = _p(solver,partInfo,subname,shape)
|
p = _p(solver,partInfo,subname,shape)
|
||||||
n = _n(solver,partInfo,subname,shape)
|
n = _n(solver,partInfo,subname,shape,True)
|
||||||
system.NameTag = partInfo.PartName
|
system.NameTag = partInfo.PartName
|
||||||
h = system.addWorkplane(p,n,group=partInfo.Group)
|
h = system.addWorkplane(p,n[0],group=partInfo.Group)
|
||||||
h = (h,p,n)
|
h = [h,p] + n
|
||||||
system.log('{}: {},{}'.format(key,h,partInfo.Group))
|
system.log('{}: {},{}'.format(key,h,partInfo.Group))
|
||||||
partInfo.EntityMap[key] = h
|
partInfo.EntityMap[key] = h
|
||||||
return h if retAll else h[0]
|
return h if retAll else h[0]
|
||||||
|
@ -134,13 +145,14 @@ def _c(solver,partInfo,subname,shape,requireArc=False):
|
||||||
raise RuntimeError('shape is not an arc')
|
raise RuntimeError('shape is not an arc')
|
||||||
else:
|
else:
|
||||||
system.NameTag = partInfo.PartName
|
system.NameTag = partInfo.PartName
|
||||||
h.append(solver.addDistanceV(r))
|
h.append(system.addDistanceV(r))
|
||||||
h = system.addCircle(*h,group=partInfo.Group)
|
h = system.addCircle(*h,group=partInfo.Group)
|
||||||
system.log('{}: {},{}'.format(key,h,partInfo.Group))
|
system.log('{}: {},{}'.format(key,h,partInfo.Group))
|
||||||
partInfo.EntityMap[key] = h
|
partInfo.EntityMap[key] = h
|
||||||
return h
|
return h
|
||||||
|
|
||||||
def _a(solver,partInfo,subname,shape):
|
def _a(solver,partInfo,subname,shape):
|
||||||
|
'return a handle of a transformed arc derived from "shape"'
|
||||||
return _c(solver,partInfo,subname,shape,True)
|
return _c(solver,partInfo,subname,shape,True)
|
||||||
|
|
||||||
|
|
||||||
|
@ -294,6 +306,7 @@ _makeProp('Distance','App::PropertyDistance',getter=propGetValue)
|
||||||
_makeProp('Offset','App::PropertyDistance',getter=propGetValue)
|
_makeProp('Offset','App::PropertyDistance',getter=propGetValue)
|
||||||
_makeProp('Cascade','App::PropertyBool',internal=True)
|
_makeProp('Cascade','App::PropertyBool',internal=True)
|
||||||
_makeProp('Angle','App::PropertyAngle',getter=propGetValue)
|
_makeProp('Angle','App::PropertyAngle',getter=propGetValue)
|
||||||
|
_makeProp('LockAngle','App::PropertyBool')
|
||||||
_makeProp('Ratio','App::PropertyFloat')
|
_makeProp('Ratio','App::PropertyFloat')
|
||||||
_makeProp('Difference','App::PropertyFloat')
|
_makeProp('Difference','App::PropertyFloat')
|
||||||
_makeProp('Diameter','App::PropertyFloat')
|
_makeProp('Diameter','App::PropertyFloat')
|
||||||
|
@ -593,7 +606,7 @@ class BaseCascade(BaseMulti):
|
||||||
class PlaneCoincident(BaseCascade):
|
class PlaneCoincident(BaseCascade):
|
||||||
_id = 35
|
_id = 35
|
||||||
_iconName = 'Assembly_ConstraintCoincidence.svg'
|
_iconName = 'Assembly_ConstraintCoincidence.svg'
|
||||||
_props = ['Cascade','Offset']
|
_props = ['Cascade','Offset','LockAngle','Angle']
|
||||||
_menuItem = True
|
_menuItem = True
|
||||||
_tooltip = \
|
_tooltip = \
|
||||||
'Add a "{}" constraint to conincide planes of two or more parts.\n'\
|
'Add a "{}" constraint to conincide planes of two or more parts.\n'\
|
||||||
|
@ -603,7 +616,7 @@ class PlaneCoincident(BaseCascade):
|
||||||
class PlaneAlignment(BaseCascade):
|
class PlaneAlignment(BaseCascade):
|
||||||
_id = 37
|
_id = 37
|
||||||
_iconName = 'Assembly_ConstraintAlignment.svg'
|
_iconName = 'Assembly_ConstraintAlignment.svg'
|
||||||
_props = ['Cascade','Offset']
|
_props = ['Cascade','Offset','LockAngle','Angle']
|
||||||
_menuItem = True
|
_menuItem = True
|
||||||
_tooltip = 'Add a "{}" constraint to rotate planes of two or more parts\n'\
|
_tooltip = 'Add a "{}" constraint to rotate planes of two or more parts\n'\
|
||||||
'into the same orientation'
|
'into the same orientation'
|
||||||
|
@ -612,6 +625,7 @@ class PlaneAlignment(BaseCascade):
|
||||||
class AxialAlignment(BaseMulti):
|
class AxialAlignment(BaseMulti):
|
||||||
_id = 36
|
_id = 36
|
||||||
_iconName = 'Assembly_ConstraintAxial.svg'
|
_iconName = 'Assembly_ConstraintAxial.svg'
|
||||||
|
_props = ['LockAngle','Angle']
|
||||||
_menuItem = True
|
_menuItem = True
|
||||||
_tooltip = 'Add a "{}" constraint to align planes of two or more parts.\n'\
|
_tooltip = 'Add a "{}" constraint to align planes of two or more parts.\n'\
|
||||||
'The planes are aligned at the direction of their surface normal axis.'
|
'The planes are aligned at the direction of their surface normal axis.'
|
||||||
|
@ -661,6 +675,7 @@ class MultiParallel(BaseMulti):
|
||||||
_id = 291
|
_id = 291
|
||||||
_entityDef = (_ln,)
|
_entityDef = (_ln,)
|
||||||
_iconName = 'Assembly_ConstraintMultiParallel.svg'
|
_iconName = 'Assembly_ConstraintMultiParallel.svg'
|
||||||
|
_props = ['LockAngle','Angle']
|
||||||
_menuItem = True
|
_menuItem = True
|
||||||
_tooltip = 'Add a "{}" constraint to make planes or linear edges of two\n'\
|
_tooltip = 'Add a "{}" constraint to make planes or linear edges of two\n'\
|
||||||
'or more parts parallel.'
|
'or more parts parallel.'
|
||||||
|
|
32
system.py
32
system.py
|
@ -107,12 +107,12 @@ class SystemExtension(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.NameTag = ''
|
self.NameTag = ''
|
||||||
|
|
||||||
def addPlaneCoincident(self,d,e1,e2,group=0):
|
def addPlaneCoincident(self,d,lockAngle,angle,e1,e2,group=0):
|
||||||
if not group:
|
if not group:
|
||||||
group = self.GroupHandle
|
group = self.GroupHandle
|
||||||
d = abs(d)
|
d = abs(d)
|
||||||
_,p1,n1 = e1
|
_,p1,n1,nx1 = e1
|
||||||
w2,p2,n2 = e2
|
w2,p2,n2,nx2 = e2
|
||||||
h = []
|
h = []
|
||||||
if d>0.0:
|
if d>0.0:
|
||||||
h.append(self.addPointPlaneDistance(d,p1,w2,group=group))
|
h.append(self.addPointPlaneDistance(d,p1,w2,group=group))
|
||||||
|
@ -120,34 +120,44 @@ class SystemExtension(object):
|
||||||
else:
|
else:
|
||||||
h.append(self.addPointsCoincident(p1,p2,group=group))
|
h.append(self.addPointsCoincident(p1,p2,group=group))
|
||||||
h.append(self.addParallel(n1,n2,group=group))
|
h.append(self.addParallel(n1,n2,group=group))
|
||||||
|
if lockAngle:
|
||||||
|
h.append(self.addAngle(angle,False,nx1,nx2,group=group))
|
||||||
return h
|
return h
|
||||||
|
|
||||||
def addPlaneAlignment(self,d,e1,e2,group=0):
|
def addPlaneAlignment(self,d,lockAngle,angle,e1,e2,group=0):
|
||||||
if not group:
|
if not group:
|
||||||
group = self.GroupHandle
|
group = self.GroupHandle
|
||||||
d = abs(d)
|
d = abs(d)
|
||||||
_,p1,n1 = e1
|
_,p1,n1,nx1 = e1
|
||||||
w2,_,n2 = e2
|
w2,_,n2,nx2 = e2
|
||||||
h = []
|
h = []
|
||||||
if d>0.0:
|
if d>0.0:
|
||||||
h.append(self.addPointPlaneDistance(d,p1,w2,group=group))
|
h.append(self.addPointPlaneDistance(d,p1,w2,group=group))
|
||||||
else:
|
else:
|
||||||
h.append(self.addPointInPlane(p1,w2,group=group))
|
h.append(self.addPointInPlane(p1,w2,group=group))
|
||||||
h.append(self.addParallel(n1,n2,group=group))
|
h.append(self.addParallel(n1,n2,group=group))
|
||||||
|
if lockAngle:
|
||||||
|
h.append(self.addAngle(angle,False,nx1,nx2,group=group))
|
||||||
return h
|
return h
|
||||||
|
|
||||||
def addAxialAlignment(self,e1,e2,group=0):
|
def addAxialAlignment(self,lockAngle,angle,e1,e2,group=0):
|
||||||
if not group:
|
if not group:
|
||||||
group = self.GroupHandle
|
group = self.GroupHandle
|
||||||
_,p1,n1 = e1
|
_,p1,n1,nx1 = e1
|
||||||
w2,p2,n2 = e2
|
w2,p2,n2,nx2 = e2
|
||||||
h = []
|
h = []
|
||||||
h.append(self.addPointsCoincident(p1,p2,w2,group=group))
|
h.append(self.addPointsCoincident(p1,p2,w2,group=group))
|
||||||
h.append(self.addParallel(n1,n2,group=group))
|
h.append(self.addParallel(n1,n2,group=group))
|
||||||
|
if lockAngle:
|
||||||
|
h.append(self.addAngle(angle,False,nx1,nx2,group=group))
|
||||||
return h
|
return h
|
||||||
|
|
||||||
def addMultiParallel(self,e1,e2,group=0):
|
def addMultiParallel(self,lockAngle,angle,e1,e2,group=0):
|
||||||
return self.addParallel(e1,e2,group=group)
|
h = []
|
||||||
|
h.append(self.addParallel(e1,e2,group=group))
|
||||||
|
if lockAngle:
|
||||||
|
h.append(self.addAngle(angle,False,e1,e2,group=group))
|
||||||
|
return h
|
||||||
|
|
||||||
def addPlacement(self,pla,group=0):
|
def addPlacement(self,pla,group=0):
|
||||||
q = pla.Rotation.Q
|
q = pla.Rotation.Q
|
||||||
|
|
13
utils.py
13
utils.py
|
@ -285,12 +285,17 @@ def getElementRotation(obj,reverse=False):
|
||||||
[L.tangent(0)[0] for L in lines]) #D(irections)
|
[L.tangent(0)[0] for L in lines]) #D(irections)
|
||||||
if np.std( D, axis=0 ).max() < 10**-9: #then linear curve
|
if np.std( D, axis=0 ).max() < 10**-9: #then linear curve
|
||||||
return D[0]
|
return D[0]
|
||||||
if axis:
|
if not axis:
|
||||||
|
return FreeCAD.Rotation()
|
||||||
return FreeCAD.Rotation(FreeCAD.Vector(0,0,-1 if reverse else 1),axis)
|
return FreeCAD.Rotation(FreeCAD.Vector(0,0,-1 if reverse else 1),axis)
|
||||||
|
|
||||||
def getElementNormal(obj,reverse=False):
|
def getNormal(obj):
|
||||||
rot = getElementRotation(obj,reverse)
|
if isinstance(obj,FreeCAD.Rotation):
|
||||||
if rot:
|
rot = obj
|
||||||
|
elif isinstance(obj,FreeCAD.Placement):
|
||||||
|
rot = obj.Rotation
|
||||||
|
else:
|
||||||
|
rot = getElementRotation(obj)
|
||||||
q = rot.Q
|
q = rot.Q
|
||||||
return q[3],q[0],q[1],q[2]
|
return q[3],q[0],q[1],q[2]
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user