constraint: fix constraint multiplication
This commit is contained in:
parent
59c8fa186f
commit
fc8f2f1a47
|
@ -506,6 +506,17 @@ class Constraint(ProxyType):
|
|||
|
||||
for obj in cstrs:
|
||||
cstr = mcs.getProxy(obj)
|
||||
|
||||
# Build array constraint map for constraint multiplication
|
||||
if mcs.canMultiply(obj):
|
||||
element0 = obj.Proxy.getElements()[0].Proxy
|
||||
for info in element0.getInfo(expand=True):
|
||||
solver.countArrayPartConstraint(info.Part)
|
||||
else:
|
||||
for info in obj.Proxy.getElementsInfo():
|
||||
if isinstance(info.Part,tuple):
|
||||
solver.countArrayPartConstraint(info.Part)
|
||||
|
||||
if cstr.hasFixedPart(obj):
|
||||
found = True
|
||||
for info in cstr.getFixedParts(solver,obj):
|
||||
|
@ -934,42 +945,37 @@ class BaseMulti(Base):
|
|||
logger.warn('{} no first part shape'.format(cstrName(obj)))
|
||||
return
|
||||
idx = 0
|
||||
updates = []
|
||||
for element in elements[1:]:
|
||||
infos = element.Proxy.getInfo(expand=True)
|
||||
if not infos:
|
||||
continue
|
||||
info0 = firstInfo[idx]
|
||||
partInfo0 = solver.getPartInfo(info0)
|
||||
info = infos[0]
|
||||
partInfo = solver.getPartInfo(info)
|
||||
e0 = cls._entityDef[0](
|
||||
solver,partInfo0,info0.Subname,info0.Shape)
|
||||
e = cls._entityDef[0](
|
||||
solver,partInfo,info.Subname,info.Shape)
|
||||
params = props + [e0,e]
|
||||
solver.system.checkRedundancy(obj,partInfo0,partInfo)
|
||||
h = func(*params,group=solver.group)
|
||||
if isinstance(h,(list,tuple)):
|
||||
ret += list(h)
|
||||
else:
|
||||
ret.append(h)
|
||||
idx += 1
|
||||
if idx >= count:
|
||||
return ret
|
||||
if len(infos)>1:
|
||||
updates.append((partInfo0,element,len(infos)-1))
|
||||
updates = []
|
||||
for i,info in enumerate(element.Proxy.getInfo(expand=True)):
|
||||
if idx >= count:
|
||||
break
|
||||
info0 = firstInfo[idx]
|
||||
if i and solver.getArrayPartConstraintCount(info0.Part)==1:
|
||||
# We can safely skip those coplanar edges if the part
|
||||
# array element is involved in one and only one
|
||||
# constraint (i.e. this one).
|
||||
updates.append((idx,i))
|
||||
idx += 1
|
||||
continue
|
||||
|
||||
for partInfo0,element,infoCount in updates:
|
||||
if partInfo0.Update:
|
||||
logger.warn('{} used in more than one constraint '
|
||||
'multiplication'.format(partInfo0.PartName))
|
||||
continue
|
||||
partInfo0.Update.append(idx)
|
||||
partInfo0.Update.append(element)
|
||||
idx += infoCount
|
||||
if idx >= count:
|
||||
break
|
||||
partInfo0 = solver.getPartInfo(info0)
|
||||
partInfo = solver.getPartInfo(info)
|
||||
e0 = cls._entityDef[0](
|
||||
solver,partInfo0,info0.Subname,info0.Shape)
|
||||
e = cls._entityDef[0](
|
||||
solver,partInfo,info.Subname,info.Shape)
|
||||
params = props + [e0,e]
|
||||
solver.system.checkRedundancy(obj,partInfo0,partInfo)
|
||||
h = func(*params,group=solver.group)
|
||||
if isinstance(h,(list,tuple)):
|
||||
ret += list(h)
|
||||
else:
|
||||
ret.append(h)
|
||||
idx += 1
|
||||
|
||||
if updates:
|
||||
partInfo0.Update.append((updates,element))
|
||||
|
||||
return ret
|
||||
|
||||
|
|
69
solver.py
69
solver.py
|
@ -18,7 +18,7 @@ from .system import System
|
|||
# plane of the part.
|
||||
# EntityMap: string -> entity handle map, for caching
|
||||
# Group: transforming entity group handle
|
||||
# CstrMap: map from other part to the constrains between this and the other part.
|
||||
# CstrMap: map from other part to the constrain between this and the other part.
|
||||
# This is for auto constraint DOF reduction. Only some composite
|
||||
# constraints will be mapped.
|
||||
# Update: in case the constraint uses the `Multiplication` feature, only the
|
||||
|
@ -41,6 +41,7 @@ class Solver(object):
|
|||
self.group = 1 # the solving group
|
||||
self._partMap = {}
|
||||
self._cstrMap = {}
|
||||
self._cstrArrayMap = defaultdict(int)
|
||||
self._fixedElements = set()
|
||||
|
||||
self.system.GroupHandle = self._fixedGroup
|
||||
|
@ -211,40 +212,34 @@ class Solver(object):
|
|||
# coplanar circular edges of the same radius. For performance sake, only
|
||||
# the first edge of each expansion is used for constraint. We simply
|
||||
# translate the rest of the parts with the same relative offset.
|
||||
touches = defaultdict(set)
|
||||
touched = False
|
||||
for partInfo in updates:
|
||||
idx,element = partInfo.Update
|
||||
element0 = element.Proxy.parent.Object.Group[0]
|
||||
infos0 = element0.Proxy.getInfo(expand=True)
|
||||
count = len(infos0)
|
||||
infos = element.Proxy.getInfo(expand=True)
|
||||
pos0 = infos[0].Placement.multVec(
|
||||
utils.getElementPos(infos[0].Shape))
|
||||
touched = False
|
||||
for info in infos[1:]:
|
||||
if idx >= count:
|
||||
break
|
||||
pos = info.Placement.multVec(
|
||||
utils.getElementPos(info.Shape))
|
||||
pla = partInfo.Placement.copy()
|
||||
pla.Base += pos-pos0
|
||||
info0 = infos0[idx]
|
||||
idx += 1
|
||||
if isSamePlacement(info0.Placement,pla):
|
||||
self.system.log('not moving {}'.format(info0.PartName))
|
||||
else:
|
||||
self.system.log('moving {} {}'.format(
|
||||
partInfo.PartName,pla))
|
||||
touched = True
|
||||
if rollback is not None:
|
||||
rollback.append((info0.PartName,
|
||||
info0.Part,
|
||||
info0.Placement.copy()))
|
||||
setPlacement(info0.Part,pla)
|
||||
if touched:
|
||||
touches[partInfo.Part[0].Document].add(partInfo.Part[0])
|
||||
for doc,objs in touches.items():
|
||||
doc.recompute(list(objs))
|
||||
for indices,element in partInfo.Update:
|
||||
element0 = element.Proxy.parent.Object.Group[0]
|
||||
infos0 = element0.Proxy.getInfo(expand=True)
|
||||
infos = element.Proxy.getInfo(expand=True)
|
||||
pos0 = infos[0].Placement.multVec(
|
||||
utils.getElementPos(infos[0].Shape))
|
||||
for idx0,idx in indices:
|
||||
info = infos[idx]
|
||||
pos = info.Placement.multVec(
|
||||
utils.getElementPos(info.Shape))
|
||||
pla = partInfo.Placement.copy()
|
||||
pla.Base += pos-pos0
|
||||
info0 = infos0[idx0]
|
||||
if isSamePlacement(info0.Placement,pla):
|
||||
self.system.log('not moving {}'.format(info0.PartName))
|
||||
else:
|
||||
self.system.log('moving {} {}'.format(
|
||||
partInfo.PartName,pla))
|
||||
touched = True
|
||||
if rollback is not None:
|
||||
rollback.append((info0.PartName,
|
||||
info0.Part,
|
||||
info0.Placement.copy()))
|
||||
setPlacement(info0.Part,pla)
|
||||
if touched:
|
||||
assembly.recompute(True)
|
||||
|
||||
def isFixedPart(self,part):
|
||||
if isinstance(part,tuple) and part[0] in self._fixedParts:
|
||||
|
@ -258,6 +253,12 @@ class Solver(object):
|
|||
def addFixedElement(self,part,subname):
|
||||
self._fixedElements.add((part,subname))
|
||||
|
||||
def countArrayPartConstraint(self,part):
|
||||
self._cstrArrayMap[part] += 1
|
||||
|
||||
def getArrayPartConstraintCount(self,part):
|
||||
return self._cstrArrayMap[part]
|
||||
|
||||
def getPartInfo(self,info,fixed=False,group=0):
|
||||
partInfo = self._partMap.get(info.Part,None)
|
||||
if partInfo:
|
||||
|
|
Loading…
Reference in New Issue
Block a user