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
# -*- coding: utf-8 -*-
"""
$Id$
Copyright 2011 Lars Kruse <devel@sumpfralle.de>
This file is part of PyCAM.
PyCAM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
PyCAM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
"""
import math
import pycam.Plugins
EXTRUSION_TYPES = (("radius_up", "Radius (bulge)", "ExtrusionRadiusUpIcon"),
("radius_down", "Radius (valley)", "ExtrusionRadiusDownIcon"),
("skewed", "Chamfer", "ExtrusionChamferIcon"),
("sine", "Sine", "ExtrusionSineIcon"),
("sigmoid", "Sigmoid", "ExtrusionSigmoidIcon"),
)
class ModelExtrusion(pycam.Plugins.PluginBase):
UI_FILE = "model_extrusion.ui"
DEPENDS = ["Models"]
CATEGORIES = ["Model"]
def setup(self):
if self.gui:
extrusion_frame = self.gui.get_object("ModelExtrusionFrame")
extrusion_frame.unparent()
self._gtk_handlers = ((self.gui.get_object("ExtrudeButton"),
"clicked", self._extrude_model), )
self._event_handlers = (
("model-change-after", self._update_extrude_widgets),
("model-selection-changed", self._update_extrude_widgets))
self.core.register_ui("model_handling", "Extrusion",
extrusion_frame, 5)
self.gui.get_object("ExtrusionHeight").set_value(1)
self.gui.get_object("ExtrusionWidth").set_value(1)
self.gui.get_object("ExtrusionGrid").set_value(0.5)
extrusion_model = self.gui.get_object("ExtrusionTypeModel")
for row in EXTRUSION_TYPES:
extrusion_model.append((row[0], row[1],
self.gui.get_object(row[2]).get_pixbuf()))
self.gui.get_object("ExtrusionTypeSelector").set_active(0)
self.register_gtk_handlers(self._gtk_handlers)
self.register_event_handlers(self._event_handlers)
self._update_extrude_widgets()
return True
def teardown(self):
if self.gui:
self.core.unregister_ui("model_handling",
self.gui.get_object("ModelExtrusionFrame"))
self.unregister_gtk_handlers(self._gtk_handlers)
self.unregister_event_handlers(self._event_handlers)
def _get_extrudable_models(self):
models = self.core.get("models").get_selected()
extrudables = []
for model in models:
if (not model is None) and hasattr(model.model, "extrude"):
extrudables.append(model)
return extrudables
def _update_extrude_widgets(self):
extrude_widget = self.gui.get_object("ModelExtrusionFrame")
if self._get_extrudable_models():
extrude_widget.show()
else:
extrude_widget.hide()
def _extrude_model(self, widget=None):
selected_models = self._get_extrudable_models()
if not selected_models:
return
extrusion_type_selector = self.gui.get_object("ExtrusionTypeSelector")
type_model = extrusion_type_selector.get_model()
type_active = extrusion_type_selector.get_active()
if type_active >= 0:
type_string = type_model[type_active][0]
height = self.gui.get_object("ExtrusionHeight").get_value()
width = self.gui.get_object("ExtrusionWidth").get_value()
grid_size = self.gui.get_object("ExtrusionGrid").get_value()
if type_string == "radius_up":
func = lambda x: height * math.sqrt((width ** 2 - max(0, width - x) ** 2))
elif type_string == "radius_down":
func = lambda x: height * (1 - math.sqrt((width ** 2 - min(width, x) ** 2)) / width)
elif type_string == "skewed":
func = lambda x: height * min(1, x / width)
elif type_string == "sine":
func = lambda x: height * math.sin(min(x, width) / width * math.pi / 2)
elif type_string == "sigmoid":
func = lambda x: height * ((math.sin(((min(x, width) / width) - 0.5) * math.pi) + 1) / 2)
else:
self.log.error("Unknown extrusion type selected: %s" % type_string)
return
progress = self.core.get("progress")
progress.update(text="Extruding models")
progress.set_multiple(len(selected_models), "Model")
for model in selected_models:
new_model = model.model.extrude(stepping=grid_size, func=func,
callback=progress.update)
if new_model:
self.core.get("models").add_model(new_model,
name_template="Extruded model #%d")
else:
self.log.info("Extruded model is empty")
progress.update_multiple()
progress.finish()