Skip to content

Commit cee66ff

Browse files
Better assy solver implementation (#1063)
* Add casadi to the reqs * Casadi-based assy solver * Handle root object location * Update solve_result_check * Type center and diagonal * Assy solver refactoring - scaling - minimal quat paramterization - dummy variables * Remove useless check * More tweaks - Different axis cost - Restructured remaining costs - Perturbed starting point * Simplified costs * Better settings * Use extrinsic convention * Raise for single unary constraint * Add param handling for the point constraint * Additional tests * Rework after review
1 parent 803a05e commit cee66ff

File tree

7 files changed

+396
-154
lines changed

7 files changed

+396
-154
lines changed

cadquery/assembly.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -357,13 +357,16 @@ def solve(self) -> "Assembly":
357357
ents = {}
358358

359359
i = 0
360-
locked = []
360+
locked: List[int] = []
361+
361362
for c in self.constraints:
362363
for name in c.objects:
363364
if name not in ents:
364365
ents[name] = i
365366
i += 1
366-
if c.kind == "Fixed" or name == self.name:
367+
if (c.kind == "Fixed" or name == self.name) and ents[
368+
name
369+
] not in locked:
367370
locked.append(ents[name])
368371

369372
# Lock the first occuring entity if needed.
@@ -402,15 +405,32 @@ def solve(self) -> "Assembly":
402405
if not constraints:
403406
raise ValueError("At least one constraint required")
404407

408+
# check if at least two entities are present
409+
if len(ents) < 2:
410+
raise ValueError("At least two entities need to be constrained")
411+
405412
# instantiate the solver
406-
solver = ConstraintSolver(locs, constraints, locked=locked)
413+
scale = self.toCompound().BoundingBox().DiagonalLength
414+
solver = ConstraintSolver(locs, constraints, locked=locked, scale=scale)
407415

408416
# solve
409417
locs_new, self._solve_result = solver.solve()
410418

411419
# update positions
420+
421+
# find the inverse root loc
422+
loc_root_inv = Location()
423+
424+
if self.obj:
425+
for loc_new, n in zip(locs_new, ents):
426+
if n == self.name:
427+
loc_root_inv = loc_new.inverse
428+
break
429+
430+
# update the positions
412431
for loc_new, n in zip(locs_new, ents):
413-
self.objects[n].loc = loc_new
432+
if n != self.name:
433+
self.objects[n].loc = loc_root_inv * loc_new
414434

415435
return self
416436

cadquery/occ_impl/geom.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,9 @@ class BoundBox(object):
790790
zmax: float
791791
zlen: float
792792

793+
center: Vector
794+
DiagonalLength: float
795+
793796
def __init__(self, bb: Bnd_Box) -> None:
794797
self.wrapped = bb
795798
XMin, YMin, ZMin, XMax, YMax, ZMax = bb.Get()

0 commit comments

Comments
 (0)