-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBulkExportStackableAssortmentSystem.py
More file actions
168 lines (134 loc) · 5.73 KB
/
BulkExportStackableAssortmentSystem.py
File metadata and controls
168 lines (134 loc) · 5.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# Author-Lowell
# Description-
import json
import sys
import traceback
from contextlib import contextmanager
from datetime import datetime
from itertools import combinations_with_replacement
from pathlib import Path
import adsk.cam
import adsk.core
import adsk.fusion
base_export = Path("~/Dropbox/3D Prints/F360_Exports").expanduser()
highest_size = 4
highest_unit = 2
highest_grid = 6
@contextmanager
def get_reverting_param(design, name: str):
""" This context manager restores the original values of a paramater once we
are done varying it. """
param = design.allParameters.itemByName(name)
expression = param.expression
try:
yield param
finally:
# Reset to the original value
param.expression = expression
def dump_params(output, design):
""" Create a JSON file with all the paramters listing (including the ones tweaked during execution) """
parts1 = []
parts2 = []
for param in design.allParameters:
item = {
"name": param.name,
"expression": param.expression,
"value": param.value
}
if param.isFavorite:
parts1.append(item)
else:
parts2.append(item)
doc = {
"time": str(datetime.now()),
"design": {
"name": design.parentDocument.name,
"params": parts1 + parts2,
},
"script": sys.argv[0],
"args": {
"highest_size": highest_size,
"highest_unit": highest_unit,
"highest_grid": highest_grid,
},
}
with open(output, "w") as f:
json.dump(doc, f, indent=2)
def export_component(design, component, filename):
# Save the file as STL.
exportMgr = adsk.fusion.ExportManager.cast(design.exportManager)
stlOptions = exportMgr.createSTLExportOptions(component)
stlOptions.meshRefinement = adsk.fusion.MeshRefinementSettings.MeshRefinementMedium
stlOptions.filename = str(filename)
exportMgr.execute(stlOptions)
def run(context):
ui = None
try:
app = adsk.core.Application.get()
ui = app.userInterface
design = adsk.fusion.Design.cast(app.activeProduct)
# Avoid some verbosity..
def get_param(name: str):
return design.allParameters.itemByName(name)
def param_value(name: str):
# Drop space between value and units (mm)
v = get_param(name).expression
return v.replace(" ", "")
# Get the root component of the active design
# rootComp = design.rootComponent
box_component = next(
c for c in design.allComponents if c.name == "Box")
lid_component = next(
c for c in design.allComponents if c.name == "Lid")
grid_component = next(
c for c in design.allComponents if c.name == "Grid")
# Specify the folder to write out the results.
folder = base_export / "Stackable-Assortment-System"
folder.mkdir(exist_ok=True)
# Static params (used in output file name) (database unit is cm, we want mm)
segment_size_x = int(get_param("SegmentSizeX").value * 10)
segment_size_y = int(get_param("SegmentSizeY").value * 10)
box_height_base = int(get_param("BoxHeightBase").value * 10)
lid_height_base = int(get_param("LidHeightBase").value * 10)
if segment_size_x == segment_size_y:
segment_size = segment_size_x
is_square = True
else:
segment_size = f"{segment_size_x}x{segment_size_y}"
is_square = False
# Make a separate folder based on primary size dimensions
folder = folder / \
f"base-{param_value('BoxHeightBase')}_grid-{param_value('SegmentSizeX')}"
folder.mkdir(exist_ok=True)
dump_params(folder / "fusion360_bulk_export.json", design)
with get_reverting_param(design, "BoxSegmentsX") as segments_x_param, \
get_reverting_param(design, "BoxSegmentsY") as segments_y_param, \
get_reverting_param(design, "BoxHeightUnits") as segments_u_param:
for x, y in combinations_with_replacement(range(1, highest_size+1), 2):
segments_x_param.expression = str(x)
segments_y_param.expression = str(y)
export_component(design, lid_component,
folder / f"lid-{x}x{y}-lid-{lid_height_base}_grid-{segment_size}.stl")
for u in range(1, highest_unit + 1):
segments_u_param.expression = str(u)
# Let the view have a chance to paint just so you can watch the progress.
adsk.doEvents()
export_component(design, box_component,
folder / f"box-{x}x{y}-{u}u_base-{box_height_base}_grid-{segment_size}.stl")
# Make range of grid sizes
with get_reverting_param(design, "GridSegmentsX") as grid_x_param, \
get_reverting_param(design, "GridSegmentsY") as grid_y_param:
# We are basically assuming that the grid is square here.
# This (Otherwise 2x3 and 3x2 are NOT the same thing)
assert is_square, "We didn't code for non-square grid generation yet"
for x, y in combinations_with_replacement(range(1, highest_grid+1), 2):
grid_x_param.expression = str(x)
grid_y_param.expression = str(y)
adsk.doEvents()
export_component(design, grid_component,
folder / f"grid-{x}x{y}_base-{box_height_base}_grid-{segment_size}.stl")
adsk.doEvents()
ui.messageBox('Finished.')
except:
if ui:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))