solver: solver rollback on failure while dragging
This commit is contained in:
parent
5ac1dd7971
commit
eb06ef8fbd
15
assembly.py
15
assembly.py
|
@ -1473,6 +1473,7 @@ class AsmMovingPart(object):
|
|||
self.subname = info.SubnameRef
|
||||
self.undos = None
|
||||
self.part = info.Part
|
||||
self.partName = info.PartName
|
||||
|
||||
fixed = Constraint.getFixedTransform(self.assembly.getConstraints())
|
||||
fixed = fixed.get(info.Part,None)
|
||||
|
@ -1509,6 +1510,7 @@ class AsmMovingPart(object):
|
|||
pos = shape.Placement.Base
|
||||
pla = FreeCAD.Placement(pos,rot)
|
||||
|
||||
self.oldPlacement = info.Placement.copy()
|
||||
self.offset = pla.copy()
|
||||
self.offsetInv = pla.inverse()
|
||||
self.draggerPlacement = info.Placement.multiply(pla)
|
||||
|
@ -1517,7 +1519,9 @@ class AsmMovingPart(object):
|
|||
|
||||
def update(self):
|
||||
info = getPartInfo(self.parent,self.subname)
|
||||
self.oldPlacement = info.Placement.copy()
|
||||
self.part = info.Part
|
||||
self.partName = info.PartName
|
||||
pla = info.Placement.multiply(FreeCAD.Placement(self.offset))
|
||||
logger.trace('part move update {}: {}'.format(objName(self.parent),pla))
|
||||
self.draggerPlacement = pla
|
||||
|
@ -1539,12 +1543,14 @@ class AsmMovingPart(object):
|
|||
pla = obj.ViewObject.DraggingPlacement
|
||||
|
||||
update = True
|
||||
rollback = []
|
||||
if self.fixedTransform:
|
||||
fixed = self.fixedTransform
|
||||
movement = self.draggerPlacement.inverse().multiply(pla)
|
||||
if not fixed.Shape:
|
||||
# The moving part has completely fixed placement, so we move the
|
||||
# parent assembly instead
|
||||
rollback.append((obj.Name,obj,obj.Placement.copy()))
|
||||
pla = obj.Placement.multiply(movement)
|
||||
setPlacement(obj,pla,self.undos,self._undoName)
|
||||
update = False
|
||||
|
@ -1563,6 +1569,7 @@ class AsmMovingPart(object):
|
|||
# obtain and update the part placement
|
||||
pla = pla.multiply(self.offsetInv)
|
||||
setPlacement(self.part,pla,self.undos,self._undoName)
|
||||
rollback.append((self.partName,self.part,self.oldPlacement.copy()))
|
||||
|
||||
if not asm3.gui.AsmCmdManager.AutoRecompute:
|
||||
# AsmCmdManager.AutoRecompute means auto re-solve the system. The
|
||||
|
@ -1571,12 +1578,12 @@ class AsmMovingPart(object):
|
|||
obj.recompute(True)
|
||||
return
|
||||
|
||||
System.touch(obj)
|
||||
|
||||
# calls asm3.solver.solve(obj) and redirect all the exceptions message
|
||||
# to logger only.
|
||||
logger.catch('solver exception when moving part',
|
||||
asm3.solver.solve,self.objs)
|
||||
if not logger.catch('solver exception when moving part',
|
||||
asm3.solver.solve,
|
||||
self.objs, dragPart=self.part, rollback=rollback):
|
||||
obj.recompute(True)
|
||||
|
||||
# self.draggerPlacement, which holds the intended dragger placement, is
|
||||
# updated by the above solver call through the following chain,
|
||||
|
|
|
@ -831,8 +831,3 @@ class EqualRadius(Base):
|
|||
_entityDef = (_c,_c)
|
||||
|
||||
|
||||
class WhereDragged(Base):
|
||||
_id = 34
|
||||
_entityDef = (_p,)
|
||||
_workplane = True
|
||||
|
||||
|
|
64
solver.py
64
solver.py
|
@ -18,7 +18,7 @@ PartInfo = namedtuple('SolverPartInfo',
|
|||
('PartName','Placement','Params','Workplane','EntityMap','Group'))
|
||||
|
||||
class Solver(object):
|
||||
def __init__(self,assembly,reportFailed,undo):
|
||||
def __init__(self,assembly,reportFailed,undo,dragPart,recompute,rollback):
|
||||
self.system = System.getSystem(assembly)
|
||||
cstrs = assembly.Proxy.getConstraints()
|
||||
if not cstrs:
|
||||
|
@ -49,6 +49,22 @@ class Solver(object):
|
|||
else:
|
||||
self._cstrMap[ret] = cstr
|
||||
|
||||
if dragPart:
|
||||
# TODO: this is ugly, need a better way to expose dragging interface
|
||||
addDragPoint = getattr(self.system,'addWhereDragged')
|
||||
if addDragPoint:
|
||||
if dragPart in self._fixedParts:
|
||||
raise RuntimeError('cannot drag fixed part')
|
||||
info = self._partMap.get(dragPart,None)
|
||||
if not info:
|
||||
raise RuntimeError('invalid dragging part')
|
||||
|
||||
# add dragging point
|
||||
self.system.log('add drag point {}'.format(info.Workplane[1]))
|
||||
# TODO: slvs addWhereDragged doesn't work as expected, need to
|
||||
# investigate more
|
||||
# addDragPoint(info.Workplane[1],group=self.group)
|
||||
|
||||
self.system.log('solving {}'.format(objName(assembly)))
|
||||
try:
|
||||
self.system.solve(group=self.group,reportFailed=reportFailed)
|
||||
|
@ -77,6 +93,7 @@ class Solver(object):
|
|||
self.system.log('done sloving')
|
||||
|
||||
undoDocs = set() if undo else None
|
||||
touched = False
|
||||
for part,partInfo in self._partMap.items():
|
||||
if part in self._fixedParts:
|
||||
continue
|
||||
|
@ -87,9 +104,17 @@ class Solver(object):
|
|||
if isSamePlacement(partInfo.Placement,pla):
|
||||
self.system.log('not moving {}'.format(partInfo.PartName))
|
||||
else:
|
||||
touched = True
|
||||
self.system.log('moving {} {} {} {}'.format(
|
||||
partInfo.PartName,partInfo.Params,params,pla))
|
||||
asm.setPlacement(part,pla,undoDocs)
|
||||
if rollback is not None:
|
||||
rollback.append((partInfo.PartName,
|
||||
part,
|
||||
partInfo.Placement.copy()))
|
||||
|
||||
if recompute and touched:
|
||||
assembly.recompute(True)
|
||||
|
||||
if undo:
|
||||
for doc in undoDocs:
|
||||
|
@ -128,7 +153,8 @@ class Solver(object):
|
|||
self._partMap[info.Part] = partInfo
|
||||
return partInfo
|
||||
|
||||
def solve(objs=None,recursive=None,reportFailed=True,recompute=True,undo=True):
|
||||
def solve(objs=None,recursive=None,reportFailed=True,
|
||||
recompute=True,undo=True,dragPart=None,rollback=None):
|
||||
if not objs:
|
||||
sels = FreeCADGui.Selection.getSelectionEx('',False)
|
||||
if len(sels):
|
||||
|
@ -164,33 +190,35 @@ def solve(objs=None,recursive=None,reportFailed=True,recompute=True,undo=True):
|
|||
# now
|
||||
objs = FreeCAD.getDependentObjects(assemblies,False,True)
|
||||
assemblies = []
|
||||
touched = False
|
||||
for obj in objs:
|
||||
if not asm.isTypeOf(obj,asm.Assembly):
|
||||
continue
|
||||
if System.isDisabled(obj):
|
||||
logger.debug('skip disabled assembly {}'.format(objName(obj)))
|
||||
continue
|
||||
if not touched:
|
||||
if not System.isTouched(obj):
|
||||
logger.debug('skip untouched assembly {}'.format(
|
||||
objName(obj)))
|
||||
continue
|
||||
touched = True
|
||||
logger.debug('adding assembly {}'.format(objName(obj)))
|
||||
assemblies.append(obj)
|
||||
|
||||
if not assemblies:
|
||||
raise RuntimeError('no assembly need to be solved')
|
||||
|
||||
assembly = None
|
||||
for assembly in assemblies:
|
||||
if recompute:
|
||||
assembly.recompute(True)
|
||||
Solver(assembly,reportFailed,undo)
|
||||
System.touch(assembly,False)
|
||||
try:
|
||||
for assembly in assemblies:
|
||||
if recompute:
|
||||
assembly.recompute(True)
|
||||
if not System.isTouched(assembly):
|
||||
logger.debug('skip untouched assembly '
|
||||
'{}'.format(objName(assembly)))
|
||||
continue
|
||||
Solver(assembly,reportFailed,undo,dragPart,recompute,rollback)
|
||||
System.touch(assembly,False)
|
||||
except Exception:
|
||||
if rollback is not None:
|
||||
for name,part,pla in reversed(rollback):
|
||||
logger.debug('roll back {} to {}'.format(name,pla))
|
||||
asm.setPlacement(part,pla,None)
|
||||
raise
|
||||
|
||||
return True
|
||||
|
||||
if assembly and recompute:
|
||||
assembly.recompute(True)
|
||||
System.touch(assembly,False)
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user