constraint: reorganise constraints
Extended some constraint to support BaseMulti.
This commit is contained in:
parent
731bdb071c
commit
819dee3381
316
constraint.py
316
constraint.py
|
@ -383,6 +383,10 @@ class ConstraintCommand:
|
||||||
def _toolbarName(self):
|
def _toolbarName(self):
|
||||||
return self.tp._toolbarName
|
return self.tp._toolbarName
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _toolbarVisible(self):
|
||||||
|
return self.tp._toolbarVisible
|
||||||
|
|
||||||
def workbenchActivated(self):
|
def workbenchActivated(self):
|
||||||
self._active = None
|
self._active = None
|
||||||
|
|
||||||
|
@ -399,25 +403,15 @@ class ConstraintCommand:
|
||||||
return self.tp.GetResources()
|
return self.tp.GetResources()
|
||||||
|
|
||||||
def Activated(self):
|
def Activated(self):
|
||||||
from .assembly import AsmConstraint
|
self.tp.activate()
|
||||||
guilogger.report('constraint "{}" command exception'.format(
|
|
||||||
self.tp.getName()), AsmConstraint.make,self.tp._id)
|
|
||||||
|
|
||||||
def IsActive(self):
|
def IsActive(self):
|
||||||
if not FreeCAD.ActiveDocument:
|
if not FreeCAD.ActiveDocument:
|
||||||
return False
|
return False
|
||||||
if self._active is None:
|
if self._active is None:
|
||||||
self.checkActive()
|
self._active = self.tp.checkActive()
|
||||||
return self._active
|
return self._active
|
||||||
|
|
||||||
def checkActive(self):
|
|
||||||
from .assembly import AsmConstraint
|
|
||||||
if guilogger.catchTrace('selection "{}" exception'.format(
|
|
||||||
self.tp.getName()), AsmConstraint.getSelection, self.tp._id):
|
|
||||||
self._active = True
|
|
||||||
else:
|
|
||||||
self._active = False
|
|
||||||
|
|
||||||
def onSelectionChange(self,hasSelection):
|
def onSelectionChange(self,hasSelection):
|
||||||
self._active = None if hasSelection else False
|
self._active = None if hasSelection else False
|
||||||
|
|
||||||
|
@ -482,12 +476,12 @@ class Constraint(ProxyType):
|
||||||
return mcs.getProxy(obj).prepare(obj,solver)
|
return mcs.getProxy(obj).prepare(obj,solver)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def getFixedParts(mcs,solver,cstrs,parts):
|
def getFixedParts(mcs,solver,cstrs,partGroup):
|
||||||
firstInfo = None
|
firstInfo = None
|
||||||
ret = set()
|
ret = partGroup.Proxy.derivedParts
|
||||||
|
|
||||||
from .assembly import isTypeOf, AsmWorkPlane
|
from .assembly import isTypeOf, AsmWorkPlane
|
||||||
for obj in parts:
|
for obj in partGroup.Group:
|
||||||
if not hasattr(obj,'Placement'):
|
if not hasattr(obj,'Placement'):
|
||||||
ret.add(obj)
|
ret.add(obj)
|
||||||
elif isTypeOf(obj,AsmWorkPlane) and getattr(obj,'Fixed',False):
|
elif isTypeOf(obj,AsmWorkPlane) and getattr(obj,'Fixed',False):
|
||||||
|
@ -603,6 +597,7 @@ class Base(with_metaclass(Constraint, object)):
|
||||||
_workplane = False
|
_workplane = False
|
||||||
_props = []
|
_props = []
|
||||||
_toolbarName = 'Assembly3 Constraints'
|
_toolbarName = 'Assembly3 Constraints'
|
||||||
|
_toolbarVisible = True
|
||||||
_iconName = 'Assembly_ConstraintGeneral.svg'
|
_iconName = 'Assembly_ConstraintGeneral.svg'
|
||||||
_menuText = 'Create "{}" constraint'
|
_menuText = 'Create "{}" constraint'
|
||||||
|
|
||||||
|
@ -613,14 +608,31 @@ class Base(with_metaclass(Constraint, object)):
|
||||||
def init(cls,_obj):
|
def init(cls,_obj):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def activate(cls):
|
||||||
|
from .assembly import AsmConstraint
|
||||||
|
guilogger.report('constraint "{}" command exception'.format(
|
||||||
|
cls.getName()), AsmConstraint.make, cls._id)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def checkActive(cls):
|
||||||
|
from .assembly import AsmConstraint
|
||||||
|
if guilogger.catchTrace('selection "{}" exception'.format(
|
||||||
|
cls.getName()), AsmConstraint.getSelection, cls._id):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def getPropertyInfoList(cls):
|
def getPropertyInfoList(cls):
|
||||||
return cls._props
|
return cls._props
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def constraintFunc(cls,obj,solver):
|
def constraintFunc(cls,obj,solver,name=None):
|
||||||
try:
|
try:
|
||||||
return getattr(solver.system,'add'+cls.getName())
|
if not name:
|
||||||
|
name = getattr(cls,'_cstrFuncName','add'+cls.getName())
|
||||||
|
return getattr(solver.system,name)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
logger.warn('{} not supported in solver "{}"'.format(
|
logger.warn('{} not supported in solver "{}"'.format(
|
||||||
cstrName(obj),solver.getName()))
|
cstrName(obj),solver.getName()))
|
||||||
|
@ -689,13 +701,12 @@ class Base(with_metaclass(Constraint, object)):
|
||||||
@classmethod
|
@classmethod
|
||||||
def prepare(cls,obj,solver):
|
def prepare(cls,obj,solver):
|
||||||
func = cls.constraintFunc(obj,solver)
|
func = cls.constraintFunc(obj,solver)
|
||||||
if func:
|
if not func:
|
||||||
|
return
|
||||||
params = cls.getPropertyValues(obj) + cls.getEntities(obj,solver)
|
params = cls.getPropertyValues(obj) + cls.getEntities(obj,solver)
|
||||||
ret = func(*params,group=solver.group)
|
ret = func(*params,group=solver.group)
|
||||||
solver.system.log('{}: {}'.format(cstrName(obj),ret))
|
solver.system.log('{}: {}'.format(cstrName(obj),ret))
|
||||||
return ret
|
return ret
|
||||||
else:
|
|
||||||
logger.warn('{} no constraint func'.format(cstrName(obj)))
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def hasFixedPart(cls,_obj):
|
def hasFixedPart(cls,_obj):
|
||||||
|
@ -850,23 +861,37 @@ class BaseMulti(Base):
|
||||||
_id = -1
|
_id = -1
|
||||||
_entityDef = (_wa,)
|
_entityDef = (_wa,)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def onRegister(cls):
|
||||||
|
assert(not cls._workplane)
|
||||||
|
assert(len(cls._entityDef)<=2)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def check(cls,elements,checkCount=False):
|
def check(cls,elements,checkCount=False):
|
||||||
if checkCount and len(elements)<2:
|
if checkCount and len(elements)<2:
|
||||||
raise RuntimeError('Constraint "{}" requires at least two '
|
raise RuntimeError('Constraint "{}" requires at least two '
|
||||||
'elements'.format(cls.getName()))
|
'elements'.format(cls.getName()))
|
||||||
for info in elements:
|
count = min(len(elements),len(cls._entityDef))
|
||||||
|
for i,entityDef in enumerate(cls._entityDef[:count]):
|
||||||
|
info = elements[i]
|
||||||
|
msg = entityDef(None,info.Part,info.Subname,info.Shape)
|
||||||
|
if msg:
|
||||||
|
raise RuntimeError('Constraint "{}" requires the {} element '
|
||||||
|
'to be of {}'.format(cls.getName(),_ordinal[i],msg))
|
||||||
|
if len(elements)<=count:
|
||||||
|
return
|
||||||
|
i = len(cls._entityDef)
|
||||||
|
for info in elements[i:]:
|
||||||
msg = cls._entityDef[0](None,info.Part,info.Subname,info.Shape)
|
msg = cls._entityDef[0](None,info.Part,info.Subname,info.Shape)
|
||||||
if msg:
|
if msg:
|
||||||
raise RuntimeError('Constraint "{}" requires all the element '
|
raise RuntimeError('Constraint "{}" requires the {} element '
|
||||||
'to be of {}'.format(cls.getName(),msg))
|
'onwards to all be of {}'.format(
|
||||||
return
|
cls.getName(),_ordinal[i],msg))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def prepare(cls,obj,solver):
|
def prepare(cls,obj,solver):
|
||||||
func = cls.constraintFunc(obj,solver);
|
func = cls.constraintFunc(obj,solver);
|
||||||
if not func:
|
if not func:
|
||||||
logger.warn('{} no constraint func'.format(cstrName(obj)))
|
|
||||||
return
|
return
|
||||||
props = cls.getPropertyValues(obj)
|
props = cls.getPropertyValues(obj)
|
||||||
ret = []
|
ret = []
|
||||||
|
@ -928,17 +953,25 @@ class BaseMulti(Base):
|
||||||
logger.warn('{} has no effective constraint'.format(cstrName(obj)))
|
logger.warn('{} has no effective constraint'.format(cstrName(obj)))
|
||||||
return
|
return
|
||||||
e0 = None
|
e0 = None
|
||||||
firstInfo = None
|
e = None
|
||||||
for e in elements:
|
info0 = None
|
||||||
info = e.Proxy.getInfo()
|
idx0 = 1 if len(cls._entityDef)>1 else 0
|
||||||
|
for i,element in enumerate(elements):
|
||||||
|
info = element.Proxy.getInfo()
|
||||||
partInfo = solver.getPartInfo(info)
|
partInfo = solver.getPartInfo(info)
|
||||||
if not e0:
|
if i==idx0:
|
||||||
e0 = cls._entityDef[0](solver,partInfo,info.Subname,info.Shape)
|
e0 = cls._entityDef[idx0](
|
||||||
firstInfo = partInfo
|
solver,partInfo,info.Subname,info.Shape)
|
||||||
|
info0 = partInfo
|
||||||
else:
|
else:
|
||||||
e = cls._entityDef[0](solver,partInfo,info.Subname,info.Shape)
|
e = cls._entityDef[0](solver,partInfo,info.Subname,info.Shape)
|
||||||
|
if e0 and e:
|
||||||
|
if idx0:
|
||||||
|
params = props + [e,e0]
|
||||||
|
solver.system.checkRedundancy(obj,partInfo,info0)
|
||||||
|
else:
|
||||||
params = props + [e0,e]
|
params = props + [e0,e]
|
||||||
solver.system.checkRedundancy(obj,firstInfo,partInfo)
|
solver.system.checkRedundancy(obj,info0,partInfo)
|
||||||
h = func(*params,group=solver.group)
|
h = func(*params,group=solver.group)
|
||||||
if isinstance(h,(list,tuple)):
|
if isinstance(h,(list,tuple)):
|
||||||
ret += list(h)
|
ret += list(h)
|
||||||
|
@ -953,7 +986,6 @@ class BaseCascade(BaseMulti):
|
||||||
return super(BaseCascade,cls).prepare(obj,solver)
|
return super(BaseCascade,cls).prepare(obj,solver)
|
||||||
func = cls.constraintFunc(obj,solver);
|
func = cls.constraintFunc(obj,solver);
|
||||||
if not func:
|
if not func:
|
||||||
logger.warn('{} no constraint func'.format(cstrName(obj)))
|
|
||||||
return
|
return
|
||||||
props = cls.getPropertyValues(obj)
|
props = cls.getPropertyValues(obj)
|
||||||
prev = None
|
prev = None
|
||||||
|
@ -984,20 +1016,22 @@ class BaseCascade(BaseMulti):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
class PlaneAlignment(BaseCascade):
|
||||||
|
_id = 37
|
||||||
|
_iconName = 'Assembly_ConstraintAlignment.svg'
|
||||||
|
_props = ['Cascade','Offset'] + _AngleProps
|
||||||
|
_tooltip = \
|
||||||
|
'Add a "{}" constraint to align planar faces of two or more parts.\n'\
|
||||||
|
'The faces become coplanar or parallel with an optional distance'
|
||||||
|
|
||||||
|
|
||||||
class PlaneCoincident(BaseCascade):
|
class PlaneCoincident(BaseCascade):
|
||||||
_id = 35
|
_id = 35
|
||||||
_iconName = 'Assembly_ConstraintCoincidence.svg'
|
_iconName = 'Assembly_ConstraintCoincidence.svg'
|
||||||
_props = ['Multiply','Cascade','Offset','OffsetX','OffsetY'] + _AngleProps
|
_props = ['Multiply','Cascade','Offset','OffsetX','OffsetY'] + _AngleProps
|
||||||
_tooltip = \
|
_tooltip = \
|
||||||
'Add a "{}" constraint to conincide planes of two or more parts.\n'\
|
'Add a "{}" constraint to conincide planar faces of two or more parts.\n'\
|
||||||
'The planes are coincided at their centers with an optional distance.'
|
'The faces are coincided at their centers with an optional distance.'
|
||||||
|
|
||||||
class PlaneAlignment(BaseCascade):
|
|
||||||
_id = 37
|
|
||||||
_iconName = 'Assembly_ConstraintAlignment.svg'
|
|
||||||
_props = ['Cascade','Offset'] + _AngleProps
|
|
||||||
_tooltip = 'Add a "{}" constraint to rotate planes of two or more parts\n'\
|
|
||||||
'into the same orientation'
|
|
||||||
|
|
||||||
|
|
||||||
class AxialAlignment(BaseMulti):
|
class AxialAlignment(BaseMulti):
|
||||||
|
@ -1005,15 +1039,18 @@ class AxialAlignment(BaseMulti):
|
||||||
_entityDef = (_lna,)
|
_entityDef = (_lna,)
|
||||||
_iconName = 'Assembly_ConstraintAxial.svg'
|
_iconName = 'Assembly_ConstraintAxial.svg'
|
||||||
_props = ['Multiply'] + _AngleProps
|
_props = ['Multiply'] + _AngleProps
|
||||||
_tooltip = 'Add a "{}" constraint to align planes of two or more parts.\n'\
|
_tooltip = 'Add a "{}" constraint to align edges/faces of two or\n'\
|
||||||
'The planes are aligned at the direction of their surface normal axis.'
|
'more parts. The constraint acceps linear edges, which become\n'\
|
||||||
|
'colinear, and planar faces, which are aligned uses their surface\n'\
|
||||||
|
'normal axis, and cylindrical face, which are aligned using the\n'\
|
||||||
|
'axial direction. Different types of geometry elements can be mixed.'
|
||||||
|
|
||||||
|
|
||||||
class SameOrientation(BaseMulti):
|
class SameOrientation(BaseMulti):
|
||||||
_id = 2
|
_id = 2
|
||||||
_entityDef = (_n,)
|
_entityDef = (_n,)
|
||||||
_iconName = 'Assembly_ConstraintOrientation.svg'
|
_iconName = 'Assembly_ConstraintOrientation.svg'
|
||||||
_tooltip = 'Add a "{}" constraint to align planes of two or more parts.\n'\
|
_tooltip = 'Add a "{}" constraint to align faces of two or more parts.\n'\
|
||||||
'The planes are aligned to have the same orientation (i.e. rotation)'
|
'The planes are aligned to have the same orientation (i.e. rotation)'
|
||||||
|
|
||||||
|
|
||||||
|
@ -1022,22 +1059,18 @@ class MultiParallel(BaseMulti):
|
||||||
_entityDef = (_lw,)
|
_entityDef = (_lw,)
|
||||||
_iconName = 'Assembly_ConstraintMultiParallel.svg'
|
_iconName = 'Assembly_ConstraintMultiParallel.svg'
|
||||||
_props = _AngleProps
|
_props = _AngleProps
|
||||||
_tooltip = 'Add a "{}" constraint to make planes ormal or linear edges\n'\
|
_tooltip = 'Add a "{}" constraint to make planar faces or linear edges\n'\
|
||||||
'of two or more parts parallel.'
|
'of two or more parts parallel.'
|
||||||
|
|
||||||
|
|
||||||
class Base2(Base):
|
class Angle(Base):
|
||||||
_id = -1
|
|
||||||
_toolbarName = 'Assembly3 Constraints2'
|
|
||||||
|
|
||||||
|
|
||||||
class Angle(Base2):
|
|
||||||
_id = 27
|
_id = 27
|
||||||
_entityDef = (_ln,_ln)
|
_entityDef = (_ln,_ln)
|
||||||
_workplane = True
|
_workplane = True
|
||||||
_props = ["Angle","Supplement"]
|
_props = ["Angle","Supplement"]
|
||||||
_iconName = 'Assembly_ConstraintAngle.svg'
|
_iconName = 'Assembly_ConstraintAngle.svg'
|
||||||
_tooltip = 'Add a "{}" constraint to set the angle of planes or linear\n'\
|
_tooltip = \
|
||||||
|
'Add a "{}" constraint to set the angle of planar faces or linear\n'\
|
||||||
'edges of two parts.'
|
'edges of two parts.'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -1046,19 +1079,19 @@ class Angle(Base2):
|
||||||
obj.Angle = utils.getElementsAngle(shapes[0],shapes[1])
|
obj.Angle = utils.getElementsAngle(shapes[0],shapes[1])
|
||||||
|
|
||||||
|
|
||||||
class Perpendicular(Base2):
|
class Perpendicular(Base):
|
||||||
_id = 28
|
_id = 28
|
||||||
_entityDef = (_lw,_lw)
|
_entityDef = (_lw,_lw)
|
||||||
_workplane = True
|
_workplane = True
|
||||||
_iconName = 'Assembly_ConstraintPerpendicular.svg'
|
_iconName = 'Assembly_ConstraintPerpendicular.svg'
|
||||||
_tooltip = 'Add a "{}" constraint to make planes or linear edges of two\n'\
|
_tooltip = \
|
||||||
|
'Add a "{}" constraint to make planar faces or linear edges of two\n'\
|
||||||
'parts perpendicular.'
|
'parts perpendicular.'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def prepare(cls,obj,solver):
|
def prepare(cls,obj,solver):
|
||||||
system = solver.system
|
system = solver.system
|
||||||
params = cls.getEntities(obj,solver)
|
e1,e2 = cls.getEntities(obj,solver)[:2]
|
||||||
e1,e2 = params[0],params[1]
|
|
||||||
isPlane = isinstance(e1,list),isinstance(e2,list)
|
isPlane = isinstance(e1,list),isinstance(e2,list)
|
||||||
if all(isPlane):
|
if all(isPlane):
|
||||||
ret = system.addPerpendicular(e1[2],e2[2],group=solver.group)
|
ret = system.addPerpendicular(e1[2],e2[2],group=solver.group)
|
||||||
|
@ -1071,45 +1104,58 @@ class Perpendicular(Base2):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
class Parallel(Base2):
|
class PointsCoincident(Base):
|
||||||
_id = -1
|
|
||||||
_entityDef = (_ln,_ln)
|
|
||||||
_workplane = True
|
|
||||||
_iconName = 'Assembly_ConstraintParallel.svg'
|
|
||||||
_tooltip = 'Add a "{}" constraint to make planes or linear edges of two\n'\
|
|
||||||
'parts parallel.'
|
|
||||||
|
|
||||||
|
|
||||||
class PointsCoincident(Base2):
|
|
||||||
_id = 1
|
_id = 1
|
||||||
_entityDef = (_p,_p)
|
_entityDef = (_p,_p)
|
||||||
_workplane = True
|
_workplane = True
|
||||||
_iconName = 'Assembly_ConstraintPointsCoincident.svg'
|
_iconName = 'Assembly_ConstraintPointCoincident.svg'
|
||||||
_tooltip = 'Add a "{}" constraint to conincide two points.'
|
_tooltips = 'Add a "{}" constraint to conincide two points in 2D or 3D'
|
||||||
|
|
||||||
|
|
||||||
class PointInPlane(Base2):
|
class PointInPlane(BaseMulti):
|
||||||
_id = 3
|
_id = 3
|
||||||
_entityDef = (_p,_w)
|
_entityDef = (_p,_w)
|
||||||
_iconName = 'Assembly_ConstraintPointInPlane.svg'
|
_iconName = 'Assembly_ConstraintPointInPlane.svg'
|
||||||
_tooltip = 'Add a "{}" to constrain a point inside a plane.'
|
_tooltip = 'Add a "{}" to constrain one or more point inside a plane.'
|
||||||
|
|
||||||
|
|
||||||
class PointOnLine(Base2):
|
class PointOnLine(Base):
|
||||||
_id = 4
|
_id = 4
|
||||||
_entityDef = (_p,_l)
|
_entityDef = (_p,_lna)
|
||||||
_workplane = True
|
_workplane = True
|
||||||
_iconName = 'Assembly_ConstraintPointOnLine.svg'
|
_iconName = 'Assembly_ConstraintPointOnLine.svg'
|
||||||
_tooltip = 'Add a "{}" to constrain a point on to a line.'
|
_tooltip = 'Add a "{}" to constrain a point on to a line in 2D or 3D.'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def prepare(cls,obj,solver):
|
||||||
|
func = cls.constraintFunc(obj,solver)
|
||||||
|
if not func:
|
||||||
|
return
|
||||||
|
params = cls.getEntities(obj,solver)
|
||||||
|
if isinstance(params[1], NormalInfo):
|
||||||
|
params[1] = params[1].ln
|
||||||
|
else:
|
||||||
|
params[1] = params[1].entity
|
||||||
|
ret = func(*params,group=solver.group)
|
||||||
|
solver.system.log('{}: {}'.format(cstrName(obj),ret))
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
class PointsDistance(Base2):
|
class PointsOnCircle(BaseMulti):
|
||||||
_id = 5
|
_id = 26
|
||||||
_entityDef = (_p,_p)
|
_entityDef = (_p,_c)
|
||||||
_workplane = True
|
_iconName = 'Assembly_ConstraintPointOnCircle.svg'
|
||||||
_props = ["Distance"]
|
_tooltip='Add a "{}" to constrain one or more points on to a clyndrical\n'\
|
||||||
|
'plane defined by a cricle.'
|
||||||
|
_cstrFuncName = 'addPointOnCircle'
|
||||||
|
|
||||||
|
|
||||||
|
class PointsDistance(BaseCascade):
|
||||||
|
_id = 44
|
||||||
|
_entityDef = (_p,)
|
||||||
|
_props = ["Cascade","Distance"]
|
||||||
_iconName = 'Assembly_ConstraintPointsDistance.svg'
|
_iconName = 'Assembly_ConstraintPointsDistance.svg'
|
||||||
_tooltip = 'Add a "{}" to constrain the distance of two points.'
|
_tooltip = 'Add a "{}" to constrain the distance of two or more points.'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def init(cls,obj):
|
def init(cls,obj):
|
||||||
|
@ -1118,40 +1164,60 @@ class PointsDistance(Base2):
|
||||||
obj.Distance = points[0].distanceToPoint(points[1])
|
obj.Distance = points[0].distanceToPoint(points[1])
|
||||||
|
|
||||||
|
|
||||||
class PointsProjectDistance(Base2):
|
class PointsPlaneDistance(BaseMulti):
|
||||||
_id = 6
|
|
||||||
_entityDef = (_p,_p,_l)
|
|
||||||
_props = ["Distance"]
|
|
||||||
_iconName = 'Assembly_ConstraintPointsProjectDistance.svg'
|
|
||||||
_tooltip = 'Add a "{}" to constrain the distance of two points\n' \
|
|
||||||
'projected on a line.'
|
|
||||||
|
|
||||||
|
|
||||||
class PointPlaneDistance(Base2):
|
|
||||||
_id = 7
|
_id = 7
|
||||||
_entityDef = (_p,_w)
|
_entityDef = (_p,_w)
|
||||||
_props = ["Distance"]
|
_props = ["Distance"]
|
||||||
_iconName = 'Assembly_ConstraintPointPlaneDistance.svg'
|
_iconName = 'Assembly_ConstraintPointPlaneDistance.svg'
|
||||||
_tooltip='Add a "{}" to constrain the distance between a point and a plane'
|
_tooltip='Add a "{}" to constrain the distance between one or more points '\
|
||||||
|
'and a plane'
|
||||||
|
_cstrFuncName = 'addPointPlaneDistance'
|
||||||
|
|
||||||
|
|
||||||
class PointLineDistance(Base2):
|
class PointLineDistance(Base):
|
||||||
_id = 8
|
_id = 8
|
||||||
_entityDef = (_p,_l)
|
_entityDef = (_p,_l)
|
||||||
_workplane = True
|
_workplane = True
|
||||||
_props = ["Distance"]
|
_props = ["Distance"]
|
||||||
_iconName = 'Assembly_ConstraintPointLineDistance.svg'
|
_iconName = 'Assembly_ConstraintPointLineDistance.svg'
|
||||||
_tooltip='Add a "{}" to constrain the distance between a point and a line'
|
_tooltip='Add a "{}" to constrain the distance between a point '\
|
||||||
|
'and a linear edge in 2D or 3D'
|
||||||
|
|
||||||
|
|
||||||
class EqualPointLineDistance(Base2):
|
class More(Base):
|
||||||
_id = 13
|
_id = 47
|
||||||
_entityDef = (_p,_l,_p,_l)
|
_iconName = 'Assembly_ConstraintMore.svg'
|
||||||
|
_tooltip='Toggle toolbars for more constraints'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def activate(cls):
|
||||||
|
gui.AsmCmdManager.toggleToolbars()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def checkActive(cls):
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class Base2(Base):
|
||||||
|
_id = -1
|
||||||
|
_toolbarName = 'Assembly3 Constraints2'
|
||||||
|
_toolbarVisible = False
|
||||||
|
|
||||||
|
|
||||||
|
class PointDistance(Base2):
|
||||||
|
_id = 5
|
||||||
|
_entityDef = (_p,_p)
|
||||||
_workplane = True
|
_workplane = True
|
||||||
_iconName = 'Assembly_ConstraintEqualPointLineDistance.svg'
|
_props = ["Distance"]
|
||||||
_tooltip='Add a "{}" to constrain the distance between a point and a\n'\
|
_iconName = 'Assembly_ConstraintPointDistance.svg'
|
||||||
'line to be the same as the distance between another point\n'\
|
_tooltip = 'Add a "{}" to constrain the distance of two points in 2D or 3D.'
|
||||||
'and line.'
|
_cstrFuncName = 'addPointsDistance'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def init(cls,obj):
|
||||||
|
points = [ info.Placement.multVec(info.Shape.Vertex1.Point)
|
||||||
|
for info in obj.Proxy.getElementsInfo() ]
|
||||||
|
obj.Distance = points[0].distanceToPoint(points[1])
|
||||||
|
|
||||||
|
|
||||||
class EqualAngle(Base2):
|
class EqualAngle(Base2):
|
||||||
|
@ -1225,13 +1291,6 @@ class LineVertical(Base2):
|
||||||
_tooltip='Add a "{}" constraint to make a line segment vertical when\n'\
|
_tooltip='Add a "{}" constraint to make a line segment vertical when\n'\
|
||||||
'projected onto a plane.'
|
'projected onto a plane.'
|
||||||
|
|
||||||
class PointOnCircle(Base2):
|
|
||||||
_id = 26
|
|
||||||
_entityDef = (_p,_c)
|
|
||||||
_iconName = 'Assembly_ConstraintPointOnCircle.svg'
|
|
||||||
_tooltip='Add a "{}" to constrain a point on to a clyndrical plane\n' \
|
|
||||||
'defined by a cricle.'
|
|
||||||
|
|
||||||
|
|
||||||
class ArcLineTangent(Base2):
|
class ArcLineTangent(Base2):
|
||||||
_id = 30
|
_id = 30
|
||||||
|
@ -1241,17 +1300,11 @@ class ArcLineTangent(Base2):
|
||||||
_tooltip='Add a "{}" constraint to make a line tangent to an arc\n'\
|
_tooltip='Add a "{}" constraint to make a line tangent to an arc\n'\
|
||||||
'at the start or end point of the arc.'
|
'at the start or end point of the arc.'
|
||||||
|
|
||||||
class Colinear(Base2):
|
|
||||||
_id = 39
|
|
||||||
_entityDef = (_lna, _lna)
|
|
||||||
_workplane = True
|
|
||||||
_iconName = 'Assembly_ConstraintColinear.svg'
|
|
||||||
_tooltip='Add a "{}" constraint to make to line colinear'
|
|
||||||
|
|
||||||
|
|
||||||
class BaseSketch(Base):
|
class BaseSketch(Base):
|
||||||
_id = -1
|
_id = -1
|
||||||
_toolbarName = 'Assembly3 Sketch Constraints'
|
_toolbarName = 'Assembly3 Sketch Constraints'
|
||||||
|
_toolbarVisible = False
|
||||||
|
|
||||||
|
|
||||||
class SketchPlane(BaseSketch):
|
class SketchPlane(BaseSketch):
|
||||||
|
@ -1313,15 +1366,14 @@ class LineLength(BaseSketch):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def prepare(cls,obj,solver):
|
def prepare(cls,obj,solver):
|
||||||
func = PointsDistance.constraintFunc(obj,solver)
|
func = cls.constraintFunc(obj,solver,'addPointsDistance')
|
||||||
if func:
|
if not func:
|
||||||
|
return
|
||||||
_,p0,p1 = cls.getEntities(obj,solver,retAll=True)[0]
|
_,p0,p1 = cls.getEntities(obj,solver,retAll=True)[0]
|
||||||
params = cls.getPropertyValues(obj) + [p0,p1]
|
params = cls.getPropertyValues(obj) + [p0,p1]
|
||||||
ret = func(*params,group=solver.group)
|
ret = func(*params,group=solver.group)
|
||||||
solver.system.log('{}: {}'.format(cstrName(obj),ret))
|
solver.system.log('{}: {}'.format(cstrName(obj),ret))
|
||||||
return ret
|
return ret
|
||||||
else:
|
|
||||||
logger.warn('{} no constraint func'.format(cstrName(obj)))
|
|
||||||
|
|
||||||
|
|
||||||
class EqualLength(BaseDraftWire):
|
class EqualLength(BaseDraftWire):
|
||||||
|
@ -1414,6 +1466,34 @@ class EqualRadius(BaseSketch):
|
||||||
raise RuntimeError('Constraint "{}" requires at least one '
|
raise RuntimeError('Constraint "{}" requires at least one '
|
||||||
'Draft.Circle'.format(cls.getName()))
|
'Draft.Circle'.format(cls.getName()))
|
||||||
|
|
||||||
|
|
||||||
|
class PointsProjectDistance(BaseSketch):
|
||||||
|
_id = 6
|
||||||
|
_entityDef = (_p,_p,_l)
|
||||||
|
_props = ["Distance"]
|
||||||
|
_iconName = 'Assembly_ConstraintPointsProjectDistance.svg'
|
||||||
|
_tooltip = 'Add a "{}" to constrain the distance of two points\n' \
|
||||||
|
'projected on a line.'
|
||||||
|
|
||||||
|
|
||||||
|
class EqualPointLineDistance(BaseSketch):
|
||||||
|
_id = 13
|
||||||
|
_entityDef = (_p,_l,_p,_l)
|
||||||
|
_workplane = True
|
||||||
|
_iconName = 'Assembly_ConstraintEqualPointLineDistance.svg'
|
||||||
|
_tooltip='Add a "{}" to constrain the distance between a point and a\n'\
|
||||||
|
'line to be the same as the distance between another point\n'\
|
||||||
|
'and line.'
|
||||||
|
|
||||||
|
|
||||||
|
class Colinear(BaseSketch):
|
||||||
|
_id = 39
|
||||||
|
_entityDef = (_lna, _lna)
|
||||||
|
_workplane = True
|
||||||
|
_iconName = 'Assembly_ConstraintColinear.svg'
|
||||||
|
_tooltip='Add a "{}" constraint to make to line colinear'
|
||||||
|
|
||||||
|
|
||||||
# class CubicLineTangent(BaseSketch):
|
# class CubicLineTangent(BaseSketch):
|
||||||
# _id = 31
|
# _id = 31
|
||||||
#
|
#
|
||||||
|
|
50
gui.py
50
gui.py
|
@ -118,10 +118,41 @@ class SelectionObserver:
|
||||||
|
|
||||||
|
|
||||||
class AsmCmdManager(ProxyType):
|
class AsmCmdManager(ProxyType):
|
||||||
|
_HiddenToolbars = set()
|
||||||
Toolbars = OrderedDict()
|
Toolbars = OrderedDict()
|
||||||
Menus = OrderedDict()
|
Menus = OrderedDict()
|
||||||
_defaultMenuGroupName = '&Assembly3'
|
_defaultMenuGroupName = '&Assembly3'
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def getToolbarParams():
|
||||||
|
return FreeCAD.ParamGet('User parameter:BaseApp/MainWindow/Toolbars')
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def init(mcs):
|
||||||
|
if not mcs.getParam('Bool','GuiInited',False):
|
||||||
|
hgrp = mcs.getToolbarParams()
|
||||||
|
for toolbar in mcs._HiddenToolbars:
|
||||||
|
hgrp.SetBool(toolbar,False)
|
||||||
|
mcs.setParam('Bool','GuiInited',True)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def toggleToolbars(mcs):
|
||||||
|
hgrp = mcs.getToolbarParams()
|
||||||
|
show = False
|
||||||
|
for toolbar in mcs._HiddenToolbars:
|
||||||
|
if not hgrp.GetBool(toolbar,True):
|
||||||
|
show = True
|
||||||
|
break
|
||||||
|
from PySide import QtGui
|
||||||
|
mw = FreeCADGui.getMainWindow()
|
||||||
|
for toolbar in mcs._HiddenToolbars:
|
||||||
|
if show != hgrp.GetBool(toolbar,True):
|
||||||
|
hgrp.SetBool(toolbar,show)
|
||||||
|
tb = mw.findChild(QtGui.QToolBar,toolbar)
|
||||||
|
if not tb:
|
||||||
|
logger.error('cannot find toolbar "{}"'.format(toolbar))
|
||||||
|
tb.setVisible(show)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def register(mcs,cls):
|
def register(mcs,cls):
|
||||||
if cls._id < 0:
|
if cls._id < 0:
|
||||||
|
@ -129,22 +160,29 @@ class AsmCmdManager(ProxyType):
|
||||||
super(AsmCmdManager,mcs).register(cls)
|
super(AsmCmdManager,mcs).register(cls)
|
||||||
FreeCADGui.addCommand(cls.getName(),cls)
|
FreeCADGui.addCommand(cls.getName(),cls)
|
||||||
if cls._toolbarName:
|
if cls._toolbarName:
|
||||||
mcs.Toolbars.setdefault(cls._toolbarName,[]).append(cls)
|
tb = mcs.Toolbars.setdefault(cls._toolbarName,[])
|
||||||
|
if not tb and not getattr(cls,'_toolbarVisible',True):
|
||||||
|
mcs._HiddenToolbars.add(cls._toolbarName)
|
||||||
|
tb.append(cls)
|
||||||
|
|
||||||
if cls._menuGroupName is not None:
|
if cls._menuGroupName is not None:
|
||||||
name = cls._menuGroupName
|
name = cls._menuGroupName
|
||||||
if not name:
|
if not name:
|
||||||
name = mcs._defaultMenuGroupName
|
name = mcs._defaultMenuGroupName
|
||||||
mcs.Menus.setdefault(name,[]).append(cls)
|
mcs.Menus.setdefault(name,[]).append(cls)
|
||||||
|
|
||||||
def getParamGroup(cls):
|
@classmethod
|
||||||
|
def getParamGroup(mcs):
|
||||||
return FreeCAD.ParamGet(
|
return FreeCAD.ParamGet(
|
||||||
'User parameter:BaseApp/Preferences/Mod/Assembly3')
|
'User parameter:BaseApp/Preferences/Mod/Assembly3')
|
||||||
|
|
||||||
def getParam(cls,tp,name,default=None):
|
@classmethod
|
||||||
return getattr(cls.getParamGroup(),'Get'+tp)(name,default)
|
def getParam(mcs,tp,name,default=None):
|
||||||
|
return getattr(mcs.getParamGroup(),'Get'+tp)(name,default)
|
||||||
|
|
||||||
def setParam(cls,tp,name,v):
|
@classmethod
|
||||||
getattr(cls.getParamGroup(),'Set'+tp)(name,v)
|
def setParam(mcs,tp,name,v):
|
||||||
|
getattr(mcs.getParamGroup(),'Set'+tp)(name,v)
|
||||||
|
|
||||||
def workbenchActivated(cls):
|
def workbenchActivated(cls):
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -39,6 +39,7 @@ class Assembly3Workbench(FreeCADGui.Workbench):
|
||||||
def Initialize(self):
|
def Initialize(self):
|
||||||
from .mover import AsmDocumentObserver
|
from .mover import AsmDocumentObserver
|
||||||
from .gui import AsmCmdManager
|
from .gui import AsmCmdManager
|
||||||
|
AsmCmdManager.init()
|
||||||
cmdSet = set()
|
cmdSet = set()
|
||||||
for name,cmds in AsmCmdManager.Toolbars.items():
|
for name,cmds in AsmCmdManager.Toolbars.items():
|
||||||
cmdSet.update(cmds)
|
cmdSet.update(cmds)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user