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.subname = info.SubnameRef
|
||||||
self.undos = None
|
self.undos = None
|
||||||
self.part = info.Part
|
self.part = info.Part
|
||||||
|
self.partName = info.PartName
|
||||||
|
|
||||||
fixed = Constraint.getFixedTransform(self.assembly.getConstraints())
|
fixed = Constraint.getFixedTransform(self.assembly.getConstraints())
|
||||||
fixed = fixed.get(info.Part,None)
|
fixed = fixed.get(info.Part,None)
|
||||||
|
@ -1509,6 +1510,7 @@ class AsmMovingPart(object):
|
||||||
pos = shape.Placement.Base
|
pos = shape.Placement.Base
|
||||||
pla = FreeCAD.Placement(pos,rot)
|
pla = FreeCAD.Placement(pos,rot)
|
||||||
|
|
||||||
|
self.oldPlacement = info.Placement.copy()
|
||||||
self.offset = pla.copy()
|
self.offset = pla.copy()
|
||||||
self.offsetInv = pla.inverse()
|
self.offsetInv = pla.inverse()
|
||||||
self.draggerPlacement = info.Placement.multiply(pla)
|
self.draggerPlacement = info.Placement.multiply(pla)
|
||||||
|
@ -1517,7 +1519,9 @@ class AsmMovingPart(object):
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
info = getPartInfo(self.parent,self.subname)
|
info = getPartInfo(self.parent,self.subname)
|
||||||
|
self.oldPlacement = info.Placement.copy()
|
||||||
self.part = info.Part
|
self.part = info.Part
|
||||||
|
self.partName = info.PartName
|
||||||
pla = info.Placement.multiply(FreeCAD.Placement(self.offset))
|
pla = info.Placement.multiply(FreeCAD.Placement(self.offset))
|
||||||
logger.trace('part move update {}: {}'.format(objName(self.parent),pla))
|
logger.trace('part move update {}: {}'.format(objName(self.parent),pla))
|
||||||
self.draggerPlacement = pla
|
self.draggerPlacement = pla
|
||||||
|
@ -1539,12 +1543,14 @@ class AsmMovingPart(object):
|
||||||
pla = obj.ViewObject.DraggingPlacement
|
pla = obj.ViewObject.DraggingPlacement
|
||||||
|
|
||||||
update = True
|
update = True
|
||||||
|
rollback = []
|
||||||
if self.fixedTransform:
|
if self.fixedTransform:
|
||||||
fixed = self.fixedTransform
|
fixed = self.fixedTransform
|
||||||
movement = self.draggerPlacement.inverse().multiply(pla)
|
movement = self.draggerPlacement.inverse().multiply(pla)
|
||||||
if not fixed.Shape:
|
if not fixed.Shape:
|
||||||
# The moving part has completely fixed placement, so we move the
|
# The moving part has completely fixed placement, so we move the
|
||||||
# parent assembly instead
|
# parent assembly instead
|
||||||
|
rollback.append((obj.Name,obj,obj.Placement.copy()))
|
||||||
pla = obj.Placement.multiply(movement)
|
pla = obj.Placement.multiply(movement)
|
||||||
setPlacement(obj,pla,self.undos,self._undoName)
|
setPlacement(obj,pla,self.undos,self._undoName)
|
||||||
update = False
|
update = False
|
||||||
|
@ -1563,6 +1569,7 @@ class AsmMovingPart(object):
|
||||||
# obtain and update the part placement
|
# obtain and update the part placement
|
||||||
pla = pla.multiply(self.offsetInv)
|
pla = pla.multiply(self.offsetInv)
|
||||||
setPlacement(self.part,pla,self.undos,self._undoName)
|
setPlacement(self.part,pla,self.undos,self._undoName)
|
||||||
|
rollback.append((self.partName,self.part,self.oldPlacement.copy()))
|
||||||
|
|
||||||
if not asm3.gui.AsmCmdManager.AutoRecompute:
|
if not asm3.gui.AsmCmdManager.AutoRecompute:
|
||||||
# AsmCmdManager.AutoRecompute means auto re-solve the system. The
|
# AsmCmdManager.AutoRecompute means auto re-solve the system. The
|
||||||
|
@ -1571,12 +1578,12 @@ class AsmMovingPart(object):
|
||||||
obj.recompute(True)
|
obj.recompute(True)
|
||||||
return
|
return
|
||||||
|
|
||||||
System.touch(obj)
|
|
||||||
|
|
||||||
# calls asm3.solver.solve(obj) and redirect all the exceptions message
|
# calls asm3.solver.solve(obj) and redirect all the exceptions message
|
||||||
# to logger only.
|
# to logger only.
|
||||||
logger.catch('solver exception when moving part',
|
if not logger.catch('solver exception when moving part',
|
||||||
asm3.solver.solve,self.objs)
|
asm3.solver.solve,
|
||||||
|
self.objs, dragPart=self.part, rollback=rollback):
|
||||||
|
obj.recompute(True)
|
||||||
|
|
||||||
# self.draggerPlacement, which holds the intended dragger placement, is
|
# self.draggerPlacement, which holds the intended dragger placement, is
|
||||||
# updated by the above solver call through the following chain,
|
# updated by the above solver call through the following chain,
|
||||||
|
|
|
@ -831,8 +831,3 @@ class EqualRadius(Base):
|
||||||
_entityDef = (_c,_c)
|
_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'))
|
('PartName','Placement','Params','Workplane','EntityMap','Group'))
|
||||||
|
|
||||||
class Solver(object):
|
class Solver(object):
|
||||||
def __init__(self,assembly,reportFailed,undo):
|
def __init__(self,assembly,reportFailed,undo,dragPart,recompute,rollback):
|
||||||
self.system = System.getSystem(assembly)
|
self.system = System.getSystem(assembly)
|
||||||
cstrs = assembly.Proxy.getConstraints()
|
cstrs = assembly.Proxy.getConstraints()
|
||||||
if not cstrs:
|
if not cstrs:
|
||||||
|
@ -49,6 +49,22 @@ class Solver(object):
|
||||||
else:
|
else:
|
||||||
self._cstrMap[ret] = cstr
|
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)))
|
self.system.log('solving {}'.format(objName(assembly)))
|
||||||
try:
|
try:
|
||||||
self.system.solve(group=self.group,reportFailed=reportFailed)
|
self.system.solve(group=self.group,reportFailed=reportFailed)
|
||||||
|
@ -77,6 +93,7 @@ class Solver(object):
|
||||||
self.system.log('done sloving')
|
self.system.log('done sloving')
|
||||||
|
|
||||||
undoDocs = set() if undo else None
|
undoDocs = set() if undo else None
|
||||||
|
touched = False
|
||||||
for part,partInfo in self._partMap.items():
|
for part,partInfo in self._partMap.items():
|
||||||
if part in self._fixedParts:
|
if part in self._fixedParts:
|
||||||
continue
|
continue
|
||||||
|
@ -87,9 +104,17 @@ class Solver(object):
|
||||||
if isSamePlacement(partInfo.Placement,pla):
|
if isSamePlacement(partInfo.Placement,pla):
|
||||||
self.system.log('not moving {}'.format(partInfo.PartName))
|
self.system.log('not moving {}'.format(partInfo.PartName))
|
||||||
else:
|
else:
|
||||||
|
touched = True
|
||||||
self.system.log('moving {} {} {} {}'.format(
|
self.system.log('moving {} {} {} {}'.format(
|
||||||
partInfo.PartName,partInfo.Params,params,pla))
|
partInfo.PartName,partInfo.Params,params,pla))
|
||||||
asm.setPlacement(part,pla,undoDocs)
|
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:
|
if undo:
|
||||||
for doc in undoDocs:
|
for doc in undoDocs:
|
||||||
|
@ -128,7 +153,8 @@ class Solver(object):
|
||||||
self._partMap[info.Part] = partInfo
|
self._partMap[info.Part] = partInfo
|
||||||
return 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:
|
if not objs:
|
||||||
sels = FreeCADGui.Selection.getSelectionEx('',False)
|
sels = FreeCADGui.Selection.getSelectionEx('',False)
|
||||||
if len(sels):
|
if len(sels):
|
||||||
|
@ -164,33 +190,35 @@ def solve(objs=None,recursive=None,reportFailed=True,recompute=True,undo=True):
|
||||||
# now
|
# now
|
||||||
objs = FreeCAD.getDependentObjects(assemblies,False,True)
|
objs = FreeCAD.getDependentObjects(assemblies,False,True)
|
||||||
assemblies = []
|
assemblies = []
|
||||||
touched = False
|
|
||||||
for obj in objs:
|
for obj in objs:
|
||||||
if not asm.isTypeOf(obj,asm.Assembly):
|
if not asm.isTypeOf(obj,asm.Assembly):
|
||||||
continue
|
continue
|
||||||
if System.isDisabled(obj):
|
if System.isDisabled(obj):
|
||||||
logger.debug('skip disabled assembly {}'.format(objName(obj)))
|
logger.debug('skip disabled assembly {}'.format(objName(obj)))
|
||||||
continue
|
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)))
|
logger.debug('adding assembly {}'.format(objName(obj)))
|
||||||
assemblies.append(obj)
|
assemblies.append(obj)
|
||||||
|
|
||||||
if not assemblies:
|
if not assemblies:
|
||||||
raise RuntimeError('no assembly need to be solved')
|
raise RuntimeError('no assembly need to be solved')
|
||||||
|
|
||||||
assembly = None
|
try:
|
||||||
for assembly in assemblies:
|
for assembly in assemblies:
|
||||||
if recompute:
|
if recompute:
|
||||||
assembly.recompute(True)
|
assembly.recompute(True)
|
||||||
Solver(assembly,reportFailed,undo)
|
if not System.isTouched(assembly):
|
||||||
System.touch(assembly,False)
|
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