FreeCAD

Форк
0
/
OpenSCADCommands.py 
603 строки · 26.7 Кб
1
#***************************************************************************
2
#*   Copyright (c) 2012 Sebastian Hoogen <github@sebastianhoogen.de>       *
3
#*                                                                         *
4
#*   This program is free software; you can redistribute it and/or modify  *
5
#*   it under the terms of the GNU Lesser General Public License (LGPL)    *
6
#*   as published by the Free Software Foundation; either version 2 of     *
7
#*   the License, or (at your option) any later version.                   *
8
#*   for detail see the LICENCE text file.                                 *
9
#*                                                                         *
10
#*   This program is distributed in the hope that it will be useful,       *
11
#*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12
#*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13
#*   GNU Library General Public License for more details.                  *
14
#*                                                                         *
15
#*   You should have received a copy of the GNU Library General Public     *
16
#*   License along with this program; if not, write to the Free Software   *
17
#*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
18
#*   USA                                                                   *
19
#*                                                                         *
20
#***************************************************************************
21

22
__title__ = "FreeCAD OpenSCAD Workbench - GUI Commands"
23
__author__ = "Sebastian Hoogen"
24
__url__ = ["https://www.freecad.org"]
25

26
'''
27
This Script includes the GUI Commands of the OpenSCAD module
28
'''
29

30
import FreeCAD
31
import OpenSCADUtils
32

33
if FreeCAD.GuiUp:
34
    import FreeCADGui
35
    from PySide import QtCore, QtGui
36
    gui = True
37
else:
38
    gui = False
39

40
translate = FreeCAD.Qt.translate
41

42
class ExplodeGroup:
43
    "Ungroup Objects"
44
    def IsActive(self):
45
        return FreeCADGui.Selection.countObjectsOfType('Part::Feature') > 0
46

47
    def Activated(self):
48
        def isdefault(shapecolor):
49
            def comparefloat(f1,f2):
50
                if f1 == 0.0:
51
                    return f1 == f2
52
                else:
53
                    return abs((f1-f2)/f1) < 2**-24
54
            scol=FreeCAD.ParamGet("User parameter:BaseApp/Preferences/View").GetUnsigned('DefaultShapeColor',0xccccccff)
55
            defaultcolor = (((scol >> 24) & 0xff) / 255.0,
56
                           ((scol >> 16) & 0xff) / 255.0,
57
                           ((scol >>  8) & 0xff) / 255.0, 0.0)
58
            return all(all(comparefloat(fcc,dcc) for fcc,dcc in \
59
                    zip(facecolor,defaultcolor))  for facecolor in shapecolor)
60

61
        def isgrey(shapecolor):
62
            defaultcolor=(float.fromhex('0x1.99999ap-1'),float.fromhex(\
63
                    '0x1.99999ap-1'),float.fromhex('0x1.99999ap-1'),0.0)
64
            return all(facecolor == defaultcolor  for facecolor in shapecolor)
65

66
        def randomcolor(transp=0.0):
67
            import random
68
            return (random.random(),random.random(),random.random(),transp)
69

70
        def explode(obj,color=True):
71
            if obj.isDerivedFrom('Part::Fuse') or \
72
                    obj.isDerivedFrom('Part::MultiFuse') or \
73
                    obj.isDerivedFrom('Part::Compound'):
74
                plm = obj.Placement
75
                outlist = obj.OutList[:]
76
                if plm.isNull() or all((len(oo.InList)==1 and \
77
                        not oo.isDerivedFrom('PartDesign::Feature')) \
78
                        for oo in obj.OutList):
79
                    obj.Document.removeObject(obj.Name)
80
                    for oo in outlist:
81
                        if not plm.isNull():
82
                            oo.Placement=plm.multiply(oo.Placement)
83
                        if FreeCAD.GuiUp:
84
                            import FreeCADGui
85
                            oo.ViewObject.show()
86
                            if color and isdefault(oo.ViewObject.DiffuseColor):
87
                                if color:
88
                                    oo.ViewObject.DiffuseColor=randomcolor()
89
                                else:
90
                                    oo.ViewObject.DiffuseColor=color
91
                else:
92
                    FreeCAD.Console.PrintError(translate('OpenSCAD', 'Unable to explode %s') % obj.Name + '\n')
93

94
        for obj in FreeCADGui.Selection.getSelection():
95
            if len(obj.InList) == 0: # allowed only for for top level objects
96
                explode(obj)
97

98
    def GetResources(self):
99
        return {'Pixmap'  : 'OpenSCAD_Explode_Group',
100
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ExplodeGroup', 'Explode Group'),
101
                'ToolTip':  QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ExplodeGroup', 'Remove fusion, apply placement to children, and color randomly')}
102

103
class ColorCodeShape:
104
    "Change the Color of selected or all Shapes based on their validity"
105
    def Activated(self):
106
        import colorcodeshapes
107
        selection=FreeCADGui.Selection.getSelectionEx()
108
        if len(selection) > 0:
109
            objs=[selobj.Object for selobj in selection]
110

111
        else:
112
            objs=FreeCAD.ActiveDocument.Objects
113
        colorcodeshapes.colorcodeshapes(objs)
114
    def GetResources(self):
115
        return {'Pixmap'  : 'OpenSCAD_ColorCodeShape',
116
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ColorCodeShape', 'Color Shapes'),
117
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ColorCodeShape', 'Color Shapes by validity and type')}
118

119
class Edgestofaces:
120
    def IsActive(self):
121
        return FreeCADGui.Selection.countObjectsOfType('Part::Feature') > 0
122

123
    def Activated(self):
124
        from OpenSCAD2Dgeom import edgestofaces,Overlappingfaces
125
        selection=FreeCADGui.Selection.getSelectionEx()
126
        edges=[]
127
        for selobj in selection:
128
            edges.extend(selobj.Object.Shape.Edges)
129
        Overlappingfaces(edgestofaces(edges,None)).makefeatures(FreeCAD.ActiveDocument)
130
        for selobj in selection:
131
            selobj.Object.ViewObject.hide()
132
        FreeCAD.ActiveDocument.recompute()
133

134
    def GetResources(self):
135
        return {'Pixmap'  : 'OpenSCAD_Edgestofaces',
136
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_Edgestofaces', 'Convert Edges To Faces'),
137
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD', 'Convert Edges to Faces')}
138

139
class RefineShapeFeature:
140
    def IsActive(self):
141
        return FreeCADGui.Selection.countObjectsOfType('Part::Feature') > 0
142

143
    def Activated(self):
144
        import Part
145
        import OpenSCADFeatures
146
        selection=FreeCADGui.Selection.getSelectionEx()
147
        for selobj in selection:
148
            newobj=selobj.Document.addObject("Part::FeaturePython",'refine')
149
            OpenSCADFeatures.RefineShape(newobj,selobj.Object)
150
            OpenSCADFeatures.ViewProviderTree(newobj.ViewObject)
151
            newobj.Label='refine_%s' % selobj.Object.Label
152
            selobj.Object.ViewObject.hide()
153
        FreeCAD.ActiveDocument.recompute()
154
    def GetResources(self):
155
        return {'Pixmap'  : 'OpenSCAD_RefineShapeFeature',
156
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_RefineShapeFeature', 'Refine Shape Feature'),
157
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD_RefineShapeFeature', 'Create Refine Shape Feature')}
158

159
class MirrorMeshFeature:
160
    def IsActive(self):
161
        return FreeCADGui.Selection.countObjectsOfType('Mesh::Feature') > 0
162

163
    def Activated(self):
164
        selection=FreeCADGui.Selection.getSelectionEx()
165
        for selobj in selection:
166
            newobj=selobj.Document.addObject("Mesh::Feature",'mirror')
167
            newobj.Label='mirror_%s' % selobj.Object.Label
168
            msh=selobj.Object.Mesh
169
            items=["[1;0;0]","[0;1;0]","[0;0;1]","[1;1;0]","[0;1;1]","[1;0;1]","[1;1;1]"]
170
            item, ok = QtGui.QInputDialog.getItem(QtGui.QApplication.activeWindow(),'Mirror about which Axis?','Select Axis (or enter custom value):',items,editable=True)
171
            if ok:
172
                splits = list(item.replace('[','').replace(']','').split(';'))
173
                x = float(splits[0])
174
                y = float(splits[1])
175
                z = float(splits[2])
176
                vec = FreeCAD.Base.Vector(x,y,z)
177
                newmesh=OpenSCADUtils.mirrormesh(msh, vec)
178
                newobj.Mesh=newmesh
179
                selobj.Object.ViewObject.hide()
180
            else:
181
                selobj.Document.removeObject(newobj.Name)
182

183
        FreeCAD.ActiveDocument.recompute()
184
    def GetResources(self):
185
        return {'Pixmap'  : 'OpenSCAD_MirrorMeshFeature',
186
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_MirrorMeshFeature', 'Mirror Mesh Feature...'),
187
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD_MirrorMeshFeature', 'Create Mirror Mesh Feature')}
188

189
class ScaleMeshFeature:
190
    def IsActive(self):
191
        return FreeCADGui.Selection.countObjectsOfType('Mesh::Feature') > 0
192

193
    def Activated(self):
194
        selection=FreeCADGui.Selection.getSelectionEx()
195
        for selobj in selection:
196
            newobj=selobj.Document.addObject("Mesh::Feature",'scale')
197
            newobj.Label='scale_%s' % selobj.Object.Label
198
            msh=selobj.Object.Mesh
199
            items=["[1;1;1]"]
200
            item, ok = QtGui.QInputDialog.getItem(QtGui.QApplication.activeWindow(),'Scale about which Axis?','Enter scaling value:',items,editable=True)
201
            if ok:
202
                splits = list(item.replace('[','').replace(']','').split(';'))
203
                x = float(splits[0])
204
                y = float(splits[1])
205
                z = float(splits[2])
206
                vec = FreeCAD.Base.Vector(x,y,z)
207
                newmesh=OpenSCADUtils.scalemesh(msh, vec)
208
                newobj.Mesh=newmesh
209
                selobj.Object.ViewObject.hide()
210
            else:
211
                selobj.Document.removeObject(newobj.Name)
212
        FreeCAD.ActiveDocument.recompute()
213
    def GetResources(self):
214
        return {'Pixmap'  : 'OpenSCAD_ScaleMeshFeature',
215
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ScaleMeshFeature', 'Scale Mesh Feature...'),
216
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ScaleMeshFeature', 'Create Scale Mesh Feature')}
217

218

219
class ResizeMeshFeature:
220
    def IsActive(self):
221
        return FreeCADGui.Selection.countObjectsOfType('Mesh::Feature') > 0
222

223
    def Activated(self):
224
        selection=FreeCADGui.Selection.getSelectionEx()
225
        for selobj in selection:
226
            newobj=selobj.Document.addObject("Mesh::Feature",'resize')
227
            newobj.Label='resize_%s' % selobj.Object.Label
228
            msh=selobj.Object.Mesh
229
            items=["[1;1;1]"]
230
            item, ok = QtGui.QInputDialog.getItem(QtGui.QApplication.activeWindow(),'Resize about which Axis?','Enter resizing value:',items,editable=True)
231
            if ok:
232
                splits = list(item.replace('[','').replace(']','').split(';'))
233
                x = float(splits[0])
234
                y = float(splits[1])
235
                z = float(splits[2])
236
                vec = FreeCAD.Base.Vector(x,y,z)
237
                newmesh=OpenSCADUtils.resizemesh(msh, vec)
238
                newobj.Mesh=newmesh
239
                selobj.Object.ViewObject.hide()
240
            else:
241
                selobj.Document.removeObject(newobj.Name)
242
        FreeCAD.ActiveDocument.recompute()
243
    def GetResources(self):
244
        return {'Pixmap'  : 'OpenSCAD_ResizeMeshFeature',
245
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ResizeMeshFeature', 'Resize Mesh Feature...'),
246
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ResizeMeshFeature', 'Create Resize Mesh Feature')}
247

248

249
class IncreaseToleranceFeature:
250
    def IsActive(self):
251
        return FreeCADGui.Selection.countObjectsOfType('Part::Feature') > 0
252

253
    def Activated(self):
254
        import Part
255
        import OpenSCADFeatures
256
        selection=FreeCADGui.Selection.getSelectionEx()
257
        for selobj in selection:
258
            newobj=selobj.Document.addObject("Part::FeaturePython",'tolerance')
259
            OpenSCADFeatures.IncreaseTolerance(newobj,selobj.Object)
260
            OpenSCADFeatures.ViewProviderTree(newobj.ViewObject)
261
            newobj.Label='tolerance_%s' % selobj.Object.Label
262
            selobj.Object.ViewObject.hide()
263
        FreeCAD.ActiveDocument.recompute()
264
    def GetResources(self):
265
        return {'Pixmap'  : 'OpenSCAD_IncreaseToleranceFeature',
266
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_IncreaseToleranceFeature', 'Increase Tolerance Feature'),
267
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD_IncreaseToleranceFeature', 'Create Feature that allows increasing the tolerance')}
268

269
class ExpandPlacements:
270
    '''This should aid interactive repair in the future
271
    but currently it breaks extrusions, as axis, base and so on have to be
272
    recalculated'''
273
    def IsActive(self):
274
        return FreeCADGui.Selection.countObjectsOfType('Part::Feature') > 0
275

276
    def Activated(self):
277
        import expandplacements
278
        for selobj in FreeCADGui.Selection.getSelectionEx():
279
            expandplacements.expandplacements(selobj.Object,FreeCAD.Placement())
280
        FreeCAD.ActiveDocument.recompute()
281
    def GetResources(self):
282
        return {'Pixmap'  : 'OpenSCAD_ExpandPlacements',
283
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ExpandPlacements', 'Expand Placements'),
284
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ExpandPlacements', 'Expand all placements downwards in the Tree view')}
285

286
class ReplaceObject:
287
    def IsActive(self):
288
        nobj = FreeCADGui.Selection.countObjectsOfType('Part::Feature')
289
        if nobj == 3: return True
290
        elif nobj == 2: return tuple((len(obj.InList)) for obj in \
291
                FreeCADGui.Selection.getSelection()) in ((0,1),(1,0))
292
        #else: return False
293

294
    def Activated(self):
295
        import replaceobj
296
        objs=FreeCADGui.Selection.getSelection()
297
        if len(objs)==3 or \
298
                tuple((len(obj.InList)) for obj in objs) in ((0,1),(1,0)):
299
            replaceobj.replaceobjfromselection(objs)
300
        else:
301
            FreeCAD.Console.PrintError(translate('OpenSCAD', 'Please select 3 objects first')+ '\n')
302
    def GetResources(self):
303
        return {'Pixmap'  : 'OpenSCAD_ReplaceObject',
304
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ReplaceObject', 'Replace Object'),
305
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ReplaceObject', 'Replace an object in the Tree view. Please select old, new, and parent object')}
306

307
class RemoveSubtree:
308
    def IsActive(self):
309
        return FreeCADGui.Selection.countObjectsOfType('Part::Feature') > 0
310
    def Activated(self):
311
        import OpenSCADUtils
312
        import FreeCADGui
313
        OpenSCADUtils.removesubtree(FreeCADGui.Selection.getSelection())
314

315
    def GetResources(self):
316
        return {'Pixmap'  : 'OpenSCAD_RemoveSubtree',
317
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_RemoveSubtree', 'Remove Objects and their Children'),
318
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD_RemoveSubtree', 'Removes the selected objects and all children that are not referenced from other objects')}
319

320
class AddSCADWidget(QtGui.QWidget):
321
    def __init__(self,*args):
322
        QtGui.QWidget.__init__(self,*args)
323
        # Main text area
324
        self.textEdit=QtGui.QTextEdit()
325
        self.textEdit.setAcceptRichText(False)
326
        #print(self.textEdit.maximumHeight())
327
        #print(self.textEdit.maximumViewportSize())
328
        # Message Area
329
        self.textMsg=QtGui.QPlainTextEdit()
330
        self.textMsg.setReadOnly(True)
331
        h = int(2.5 * self.textMsg.fontMetrics().height())
332
        self.textMsg.setMaximumHeight(h)
333
        self.textMsg.resize(self.textMsg.width(),h)
334
        self.buttonadd = QtGui.QPushButton(translate('OpenSCAD','Add'))
335
        self.buttonrefresh = QtGui.QPushButton(translate('OpenSCAD','Refresh'))
336
        self.buttonclear = QtGui.QPushButton(translate('OpenSCAD','Clear code'))
337
        self.buttonload = QtGui.QPushButton(translate('OpenSCAD','Open...'))
338
        self.buttonsave = QtGui.QPushButton(translate('OpenSCAD','Save...'))
339
        self.checkboxmesh = QtGui.QCheckBox(translate('OpenSCAD','as Mesh'))
340
        layouth=QtGui.QHBoxLayout()
341
        layouth.addWidget(self.buttonadd)
342
        layouth.addWidget(self.buttonrefresh)
343
        layouth.addWidget(self.buttonload)
344
        layouth.addWidget(self.buttonsave)
345
        layouth.addWidget(self.buttonclear)
346
        layout= QtGui.QVBoxLayout()
347
        layout.addLayout(layouth)
348
        layout.addWidget(self.checkboxmesh)
349
        layout.addWidget(self.textEdit)
350
        layout.addWidget(self.textMsg)
351
        self.setLayout(layout)
352
        self.setWindowTitle(translate('OpenSCAD','Add OpenSCAD Element'))
353
        self.textEdit.setText(u'cube();')
354

355
        def undoable_clear():
356
            """Clears the textEdit in a way that allows undo of the action"""
357
            self.textEdit.setFocus()
358
            self.textEdit.selectAll()
359
            keypress = QtGui.QKeyEvent(QtGui.QKeyEvent.KeyPress, QtCore.Qt.Key_Delete, QtCore.Qt.NoModifier)
360
            QtGui.QGuiApplication.sendEvent(self.textEdit, keypress)
361

362
        self.buttonclear.clicked.connect(undoable_clear)
363

364
    def retranslateUi(self, widget=None):
365
        self.buttonadd.setText(translate('OpenSCAD','Add'))
366
        self.buttonload.setText(translate('OpenSCAD','Load'))
367
        self.buttonsave.setText(translate('OpenSCAD','Save'))
368
        self.buttonrefresh.setText(translate('OpenSCAD','Refresh'))
369
        self.buttonclear.setText(translate('OpenSCAD','Clear'))
370
        self.checkboxmesh.setText(translate('OpenSCAD','as Mesh'))
371
        self.setWindowTitle(translate('OpenSCAD','Add OpenSCAD Element'))
372

373
class AddSCADTask:
374
    def __init__(self):
375
        self.form = AddSCADWidget()
376
        self.form.buttonadd.clicked.connect(self.addelement)
377
        self.form.buttonload.clicked.connect(self.loadelement)
378
        self.form.buttonsave.clicked.connect(self.saveelement)
379
        self.form.buttonrefresh.clicked.connect(self.refreshelement)
380

381
    def getStandardButtons(self):
382
        return int(QtGui.QDialogButtonBox.Close)
383

384
    def isAllowedAlterSelection(self):
385
        return True
386

387
    def isAllowedAlterView(self):
388
        return True
389

390
    def isAllowedAlterDocument(self):
391
        return True
392

393
    def addelement(self):
394
        scadstr=self.form.textEdit.toPlainText()
395
        asmesh=self.form.checkboxmesh.checkState()
396
        import OpenSCADUtils
397
        import os
398
        extension= 'stl' if asmesh else 'csg'
399
        try:
400
            tmpfilename=OpenSCADUtils.callopenscadstring(scadstr,extension)
401
            doc=FreeCAD.activeDocument() or FreeCAD.newDocument()
402
            if asmesh:
403
                import Mesh
404
                Mesh.insert(tmpfilename,doc.Name)
405
            else:
406
                import importCSG
407
                importCSG.insert(tmpfilename,doc.Name)
408
            try:
409
                os.unlink(tmpfilename)
410
            except OSError:
411
                pass
412

413
        except OpenSCADUtils.OpenSCADError as e:
414
            self.form.textMsg.setPlainText(e.value)
415
            FreeCAD.Console.PrintError(e.value)
416

417
    def refreshelement(self):
418
        self.form.textMsg.setPlainText('')
419
        doc=FreeCAD.activeDocument()
420
        if doc :
421
            for obj in doc.Objects :
422
                doc.removeObject(obj.Name)
423
        self.addelement()
424

425
    def loadelement(self):
426
        filename, _ = QtGui.QFileDialog.getOpenFileName(
427
            parent=self.form,
428
            caption=translate("OpenSCAD", "Open file"),
429
            dir='.',
430
            filter=translate("OpenSCAD", "OpenSCAD Files") + " (*.scad *.csg)"
431
        )
432

433
        if filename:
434
            print('filename :'+filename)
435
            with open(filename,'r') as fp :
436
                data = fp.read()
437
                self.form.textEdit.setText(data)
438

439
    def saveelement(self) :
440
        filename, _ = QtGui.QFileDialog.getSaveFileName(
441
            parent=self.form,
442
            caption=translate("OpenSCAD", "Save file"),
443
            dir='.',
444
            filter=translate("OpenSCAD", "OpenSCAD Files") + " (*.scad *.csg)"
445
        )
446

447
        if filename:
448
            Text = self.form.textEdit.toPlainText()
449
            with open(filename,'w') as fp :
450
                fp.write(Text)
451

452
class OpenSCADMeshBooleanWidget(QtGui.QWidget):
453
    def __init__(self,*args):
454
        QtGui.QWidget.__init__(self,*args)
455
        #self.textEdit=QtGui.QTextEdit()
456
        self.buttonadd = QtGui.QPushButton(translate('OpenSCAD','Perform'))
457
        self.rb_group = QtGui.QButtonGroup()
458
        self.rb_group_box = QtGui.QGroupBox()
459
        self.rb_group_box_layout = QtGui.QVBoxLayout()
460
        self.rb_group_box.setLayout(self.rb_group_box_layout)
461
        self.rb_union = QtGui.QRadioButton("Union")
462
        self.rb_group.addButton(self.rb_union)
463
        self.rb_group_box_layout.addWidget(self.rb_union)
464
        self.rb_intersection = QtGui.QRadioButton("Intersection")
465
        self.rb_group.addButton(self.rb_intersection)
466
        self.rb_group_box_layout.addWidget(self.rb_intersection)
467
        self.rb_difference = QtGui.QRadioButton("Difference")
468
        self.rb_group.addButton(self.rb_difference)
469
        self.rb_group_box_layout.addWidget(self.rb_difference)
470
        self.rb_hull = QtGui.QRadioButton("Hull")
471
        self.rb_group.addButton(self.rb_hull)
472
        self.rb_group_box_layout.addWidget(self.rb_hull)
473
        self.rb_minkowski = QtGui.QRadioButton("Minkowski sum")
474
        self.rb_group.addButton(self.rb_minkowski)
475
        self.rb_group_box_layout.addWidget(self.rb_minkowski)
476
        layouth=QtGui.QHBoxLayout()
477
        layouth.addWidget(self.buttonadd)
478
        layout= QtGui.QVBoxLayout()
479
        layout.addLayout(layouth)
480
        layout.addWidget(self.rb_group_box)
481
        self.setLayout(layout)
482
        self.setWindowTitle(translate('OpenSCAD','Mesh Boolean'))
483

484
    def retranslateUi(self, widget=None):
485
        self.buttonadd.setText(translate('OpenSCAD','Perform'))
486
        self.setWindowTitle(translate('OpenSCAD','Mesh Boolean'))
487
        self.rb_minkowski.setText(translate('OpenSCAD','Minkowski sum'))
488

489
class OpenSCADMeshBooleanTask:
490
    def __init__(self):
491
        self.form = OpenSCADMeshBooleanWidget()
492
        self.form.buttonadd.clicked.connect(self.doboolean)
493

494
    def getStandardButtons(self):
495
        return int(QtGui.QDialogButtonBox.Close)
496

497
    def isAllowedAlterSelection(self):
498
        return False
499

500
    def isAllowedAlterView(self):
501
        return False
502

503
    def isAllowedAlterDocument(self):
504
        return True
505

506
    def doboolean(self):
507
        from OpenSCADUtils import meshoponobjs
508
        if self.form.rb_intersection.isChecked(): opname = 'intersection'
509
        elif self.form.rb_difference.isChecked(): opname = 'difference'
510
        elif self.form.rb_hull.isChecked():       opname = 'hull'
511
        elif self.form.rb_minkowski.isChecked():  opname = 'minkowski'
512
        else: opname = 'union'
513
        newmesh,objsused = meshoponobjs(opname,FreeCADGui.Selection.getSelection())
514
        if len(objsused) > 0:
515
            newmeshobj = FreeCAD.activeDocument().addObject('Mesh::Feature',opname) #create a Feature for the result
516
            newmeshobj.Mesh = newmesh #assign the result to the new Feature
517
            for obj in objsused:
518
                obj.ViewObject.hide() #hide the selected Features
519

520
class AddOpenSCADElement:
521
    def IsActive(self):
522
        return not FreeCADGui.Control.activeDialog()
523

524
    def Activated(self):
525
        panel = AddSCADTask()
526
        FreeCADGui.Control.showDialog(panel)
527

528
    def GetResources(self):
529
        return {'Pixmap'  : 'OpenSCAD_AddOpenSCADElement',
530
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_AddOpenSCADElement', 'Add OpenSCAD Element...'),
531
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD_AddOpenSCADElement',
532
                            'Add an OpenSCAD element by entering OpenSCAD code and executing the OpenSCAD binary')}
533

534
class OpenSCADMeshBoolean:
535
    def IsActive(self):
536
        return not FreeCADGui.Control.activeDialog() and \
537
            len(FreeCADGui.Selection.getSelection()) >= 1
538

539
    def Activated(self):
540
        panel = OpenSCADMeshBooleanTask()
541
        FreeCADGui.Control.showDialog(panel)
542

543
    def GetResources(self):
544
        return {'Pixmap'  : 'OpenSCAD_MeshBooleans',
545
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_MeshBoolean','Mesh Boolean...'),
546
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD_MeshBoolean',
547
                            'Export objects as meshes and use OpenSCAD to perform a boolean operation')}
548

549
class Hull:
550
    def IsActive(self):
551
        return len(FreeCADGui.Selection.getSelection()) >= 1
552

553
    def Activated(self):
554
        import Part
555
        import OpenSCADFeatures
556
        import importCSG
557
        selection=FreeCADGui.Selection.getSelectionEx()
558
        objList = []
559
        for selobj in selection:
560
            objList.append(selobj.Object)
561
            selobj.Object.ViewObject.hide()
562
        importCSG.process_ObjectsViaOpenSCAD(FreeCAD.activeDocument(),objList,"hull")
563
        FreeCAD.ActiveDocument.recompute()
564
    def GetResources(self):
565
        return {'Pixmap'  : 'OpenSCAD_Hull',
566
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_Hull', 'Hull'),
567
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD_Hull', 'Use OpenSCAD to create a hull')}
568

569
class Minkowski:
570
    def IsActive(self):
571
        return len(FreeCADGui.Selection.getSelection()) >= 1
572

573
    def Activated(self):
574
        import Part
575
        import OpenSCADFeatures
576
        import importCSG
577
        selection=FreeCADGui.Selection.getSelectionEx()
578
        objList = []
579
        for selobj in selection:
580
            objList.append(selobj.Object)
581
            selobj.Object.ViewObject.hide()
582
        importCSG.process_ObjectsViaOpenSCAD(FreeCAD.activeDocument(),objList,"minkowski")
583
        FreeCAD.ActiveDocument.recompute()
584
    def GetResources(self):
585
        return {'Pixmap'  : 'OpenSCAD_Minkowski',
586
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_Minkowski', 'Minkowski sum'),
587
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD_Minkowski', 'Use OpenSCAD to create a Minkowski sum')}
588

589
FreeCADGui.addCommand('OpenSCAD_ColorCodeShape',ColorCodeShape())
590
FreeCADGui.addCommand('OpenSCAD_ExplodeGroup',ExplodeGroup())
591
FreeCADGui.addCommand('OpenSCAD_Edgestofaces',Edgestofaces())
592
FreeCADGui.addCommand('OpenSCAD_RefineShapeFeature',RefineShapeFeature())
593
FreeCADGui.addCommand('OpenSCAD_MirrorMeshFeature',MirrorMeshFeature())
594
FreeCADGui.addCommand('OpenSCAD_ScaleMeshFeature',ScaleMeshFeature())
595
FreeCADGui.addCommand('OpenSCAD_ResizeMeshFeature',ResizeMeshFeature())
596
FreeCADGui.addCommand('OpenSCAD_IncreaseToleranceFeature',IncreaseToleranceFeature())
597
FreeCADGui.addCommand('OpenSCAD_ExpandPlacements',ExpandPlacements())
598
FreeCADGui.addCommand('OpenSCAD_ReplaceObject',ReplaceObject())
599
FreeCADGui.addCommand('OpenSCAD_RemoveSubtree',RemoveSubtree())
600
FreeCADGui.addCommand('OpenSCAD_AddOpenSCADElement',AddOpenSCADElement())
601
FreeCADGui.addCommand('OpenSCAD_MeshBoolean',OpenSCADMeshBoolean())
602
FreeCADGui.addCommand('OpenSCAD_Hull',Hull())
603
FreeCADGui.addCommand('OpenSCAD_Minkowski',Minkowski())
604

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.