Voila une macro qui tourne un objet pour minimiser le volume de la boite englobante, cf la vue rapport pour la taille finale.
- Capture d’écran_2021-05-20_23-11-44.png (43.47 KiB) Viewed 1676 times
Sélectionnez l'objet et lancer la macro, une copie simple est créée.
Code: Select all
# -*- coding: utf-8 -*-
#Stop conditions
EPSILON = 1e-4 #mm² : minimum gain for face area optimization
MAXITER = 1e2 #maximum count for each loop
def BBVol(bb):
'''returns the given BoundBox volume'''
return bb.XLength*bb.YLength*bb.ZLength
def BBSize(bb):
'''returns a string representation of a BoundBox'''
return "size (x,y,z) : %g %g %g volume : %g mm³" % (bb.XLength, bb.YLength, bb.ZLength, BBVol(bb) )
if len(Gui.Selection.getSelection()) != 1:
raise ValueError("Please select ONE object")
s=Gui.Selection.getSelection()[0].Shape.copy() #simple copy of the selected object
Msg("initial %s %s\n" % (s.BoundBox, BBSize(s.BoundBox)))
UPSILON = s.Volume/1e6 # minimum gain for volume optimization
Msg("volume gain stop condition : %g mm³\n" % UPSILON)
# main loop initialization
angleX = angleY = angleZ = 0
gItter = 0
gDeltaAngle = 45
initVol = minVol = lastVol = gDelta = BBVol(s.BoundBox)
# main loop which minimize boundbox volume
while abs(gDelta) > UPSILON and gItter < MAXITER:
#sub-loops minimize boundbox face area in the rotation axis direction
#Z axis, XY face
deltaAngle = gDeltaAngle
minArea = lastArea = deltaXY = s.BoundBox.XLength * s.BoundBox.YLength
itter = 0
while abs(deltaXY) > EPSILON and itter < MAXITER:
angleZ += deltaAngle
s.Placement.Rotation = App.Rotation(angleZ, angleY, angleX)
newArea = s.BoundBox.XLength * s.BoundBox.ZLength
deltaXY = lastArea - newArea
if newArea >= minArea: #if this step increases the face area
deltaAngle = - deltaAngle/2 #switch rotation direction and reduce movement
else:
minArea = newArea #keep rotation direction and amount until volume increase
lastArea = newArea
itter += 1
#Y axis, XZ face
deltaAngle = gDeltaAngle
minArea = lastArea = s.BoundBox.XLength * s.BoundBox.ZLength
deltaXZ = lastArea
itter = 0
while abs(deltaXZ) > EPSILON and itter < MAXITER:
angleY += deltaAngle
s.Placement.Rotation = App.Rotation(angleZ, angleY, angleX)
newArea = s.BoundBox.XLength * s.BoundBox.ZLength
deltaXZ = lastArea - newArea
if newArea >= minArea:
deltaAngle = - deltaAngle/2
else:
minArea = newArea
lastArea = newArea
itter += 1
#X axis, YZ face
deltaAngle = gDeltaAngle
minArea = lastArea = s.BoundBox.YLength * s.BoundBox.ZLength
deltaYZ =lastArea
itter = 0
while abs(deltaYZ) > EPSILON and itter < MAXITER:
angleX += deltaAngle
s.Placement.Rotation = App.Rotation(angleZ, angleY, angleX)
newArea = s.BoundBox.YLength * s.BoundBox.ZLength
deltaYZ = lastArea - newArea
if newArea >= minArea:
deltaAngle = - deltaAngle/2
else:
minArea = newArea
lastArea = newArea
itter += 1
#compute stop criterion
newVol = BBVol(s.BoundBox)
gDelta = lastVol - newVol
if newVol >= minVol: #if this step increases the boundbox volume
gDeltaAngle = -gDeltaAngle/2 #switch rotation direction and reduce movement
else:
minVol = newVol #keep rotation direction and amount until volume increase
lastVol = newVol
gItter += 1
Msg("nb itter : %i, last delta : %g mm³, angleX : %g, angleY : %g\n" % (gItter ,gDelta, angleX, angleY))
Msg("%s %s\n" % (s.BoundBox, BBSize(s.BoundBox)))
Msg("gain : %g %%\n" % ((initVol - BBVol(s.BoundBox))/initVol * 100))
Part.show(s, "BBOptimized")
EDIT 21/05/21: code commenté