Lattice2/lattice2Slice.py
DeepSOIC 0b591d5189 active body awareness
disable some commands when in body
2018-06-14 01:39:28 +03:00

180 lines
8.4 KiB
Python

#***************************************************************************
#* *
#* Copyright (c) 2016 - Victor Titov (DeepSOIC) *
#* <vv.titov@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program 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 Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
from lattice2Common import *
import lattice2CompoundExplorer as LCE
__title__="LatticeSlice module for FreeCAD"
__author__ = "DeepSOIC"
# -------------------------- document object --------------------------------------------------
def makeLatticeSlice(name):
'''makeLatticeSlice(name): makes a LatticeSlice object.'''
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name)
LatticeSlice(obj)
obj.Refine = getParamRefine()
if FreeCAD.GuiUp:
ViewProviderLatticeSlice(obj.ViewObject)
return obj
def float_fuzzy_equal(v1, v2, rel_tol):
return abs(v1-v2) <= (abs(v1)+abs(v2))*0.5*rel_tol
class LatticeSlice:
"The LatticeSlice object"
def __init__(self,obj):
self.Type = "LatticeSlice"
obj.addProperty("App::PropertyLink","Base","LatticeSlice","Object to slice. Can be almost anything, including invalid compounds.")
obj.addProperty("App::PropertyLink","Tool","LatticeSlice","Slicer object. Must be a solid, or a face/shell. If compound, children will be used for successive slices.")
obj.addProperty("App::PropertyBool","Refine","LatticeSlice","True = refine resulting shape. False = output as is.")
obj.Proxy = self
def execute(self,obj):
rst = []
pieces = LCE.AllLeaves(screen(obj.Base).Shape)
cutters = LCE.AllLeaves(screen(obj.Tool).Shape)
# prepare cutter shapes by converting them to solids
cutters_solids = []
for cutter in cutters:
if cutter.ShapeType == "Face":
cutter = Part.makeShell([cutter])
if cutter.ShapeType == "Shell":
cutter = Part.makeSolid(cutter)
if cutter.ShapeType == "Solid":
# all right, nothing to do
cutters_solids.append(cutter)
else:
raise TypeError("Cannot slice with shape of type '{typ}'".format(typ= cutter.ShapeType))
# cut everything successively with one cutter at a time
for cutter in cutters_solids:
pieces_old = pieces
pieces = []
for piece in pieces_old:
pieces_1 = LCE.AllLeaves(piece.cut(cutter))
pieces_2 = LCE.AllLeaves(piece.common(cutter))
# when cutting with shells, and object doesn't intersect cutter, duplicates are sometimes produced. This is probably as occ bug.
# But we can filter the duplicates out. The trick is to test, if the result of a cut is the same as the original, which can be done by simply comparing masses.
pieces_12 = pieces_1+pieces_2
all_same = True
for piece_test in pieces_12:
if float_fuzzy_equal(piece_test.Mass, piece.Mass, 1e-9):
# piece doesn't intersect cutter (probably).
# this test may fail, if the piece cut off by the cutter is very small.... So we discard cut result only if all masses are equal (no smaller objects are found)
pass
else:
all_same = False
break
if all_same:
#the object doesn't intersect with cutter. Special processing, to remove duplicates if we are cutting with shells.
pieces += [piece]
else:
pieces += pieces_1 + pieces_2
if obj.Refine:
pieces_old = pieces
pieces = []
for piece in pieces_old:
pieces.append(piece.removeSplitter())
obj.Shape = Part.makeCompound(pieces)
class ViewProviderLatticeSlice:
"A View Provider for the LatticeSlice object"
def __init__(self,vobj):
vobj.Proxy = self
def getIcon(self):
return getIconPath("Lattice2_Slice.svg")
def attach(self, vobj):
self.ViewObject = vobj
self.Object = vobj.Object
def __getstate__(self):
return None
def __setstate__(self,state):
return None
def claimChildren(self):
return [screen(self.Object.Base), screen(self.Object.Tool)]
def onDelete(self, feature, subelements): # subelements is a tuple of strings
try:
screen(self.Object.Base).ViewObject.show()
screen(self.Object.Tool).ViewObject.show()
except Exception as err:
FreeCAD.Console.PrintError("Error in onDelete: " + str(err))
return True
# -------------------------- /document object --------------------------------------------------
# -------------------------- Gui command --------------------------------------------------
def CreateLatticeSlice(name):
FreeCAD.ActiveDocument.openTransaction("Create LatticeSlice")
FreeCADGui.addModule("lattice2Slice")
FreeCADGui.addModule("lattice2Executer")
FreeCADGui.doCommand("sel = FreeCADGui.Selection.getSelectionEx()")
FreeCADGui.doCommand("f = lattice2Slice.makeLatticeSlice(name = '"+name+"')")
FreeCADGui.doCommand("f.Base = sel[0].Object")
FreeCADGui.doCommand("f.Tool = sel[1].Object")
FreeCADGui.doCommand("lattice2Executer.executeFeature(f)")
FreeCADGui.doCommand("f.Base.ViewObject.hide()")
FreeCADGui.doCommand("f.Tool.ViewObject.hide()")
FreeCAD.ActiveDocument.commitTransaction()
class CommandLatticeSlice:
"Command to create LatticeSlice feature"
def GetResources(self):
return {'Pixmap' : getIconPath("Lattice2_Slice.svg"),
'MenuText': QtCore.QT_TRANSLATE_NOOP("Lattice2Slice","Slice"),
'Accel': "",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Lattice2Slice","Lattice Slice: Split object by cutting it with another object, and pack resulting pieces as compound.")}
def Activated(self):
try:
if len(FreeCADGui.Selection.getSelectionEx()) == 2 :
CreateLatticeSlice(name = "Slice")
else:
infoMessage("Lattice Slice","Please select object to be sliced, first, then the cutter object. Then invoke this tool.\n\n"
"Object to be sliced: any shape, or compound of shapes (self-intersecting compounds are allowed).\n\n"
"Cutter object: face, shell, or solid. Or a compound of any of these (self-intersecting compound allowed). Shells must be manifold (no triple-connected edges are allowed; non-closed is OK).")
except Exception as err:
msgError(err)
def IsActive(self):
if FreeCAD.ActiveDocument:
return activeBody() is None
else:
return False
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Lattice2Slice', CommandLatticeSlice())
exportedCommands = ['Lattice2Slice']
# -------------------------- /Gui command --------------------------------------------------