-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathmake_solid.py
143 lines (101 loc) · 4.01 KB
/
make_solid.py
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
'''Creates the wires and part objects'''
import math
import FreeCAD, FreeCADGui
import Mesh, Part, MeshPart
import lithophane_utils
from utils.timer import Timer, computeOverallTime
from utils.resource_utils import iconPath
import utils.qtutils as qtutils
from base_lithophane_processor import BaseLithophaneProcessor
class Neighbours:
def __init__(self, face):
self.neighbours = {}
self.addNeighbours(face)
def addNeighbours(self, face):
for index in face.NeighbourIndices:
self.neighbours[index] = True
def isNeighbour(self, face):
return face.Index in self.neighbours
class FaceGroup:
def __init__(self, face):
self.faces = [face]
self.Normal = FreeCAD.Vector(face.Normal.x, face.Normal.y, face.Normal.z)
self.Neighbours = Neighbours(face)
def matches(self, face):
normalVector = FreeCAD.Vector(face.Normal.x, face.Normal.y, face.Normal.z)
if not self.Normal.isEqual(face.Normal, 0.00001):
return False
return self.Neighbours.isNeighbour(face)
def append(self, face):
self.faces.append(face)
self.Neighbours.addNeighbours(face)
def toSegment(self):
return [face.Index for face in self.faces]
def __str__(self):
return [face.Index for face in self.faces].__str__()
def groupFaces(mesh):
faceGroups = []
for face in mesh.Facets:
matchingFaceGroups = [faceGroup for faceGroup in faceGroups if faceGroup.matches(face)]
if len(matchingFaceGroups) > 0:
matchingFaceGroups[0].append(face)
else:
faceGroups.append(FaceGroup(face))
return faceGroups
def wiresFromFaceGroups(mesh, faceGroups):
wires = []
for faceGroup in faceGroups:
wires.append(MeshPart.wireFromSegment(mesh, faceGroup.toSegment()))
return wires
class MakeSolidCommand(BaseLithophaneProcessor):
toolbarName = 'Part_Tools'
commandName = 'Make_Solid'
def __init__(self):
super(MakeSolidCommand, self).__init__('Make Solid')
def getProcessingSteps(self, fp):
return [('Group Faces', self.groupFaces),
('Calculate Wires from Groups', self.calculateWires),
('Calculate Faces from Wires', self.calculateFaces),
('Create Shell from Faces', self.computeShell),
('Recompute View', self.recomputeView)]
def GetResources(self):
return {'MenuText': "Make Solid",
'ToolTip' : "Creates a Part Object out of the selected Mesh",
'Pixmap': iconPath('MakeSolid.svg')}
def checkExecution(self):
mesh, meshLabel = lithophane_utils.findSelectedMesh()
if mesh is None:
qtutils.showInfo("No mesh selected", "Select exactly one mesh to continue")
return None
return (mesh, meshLabel)
def groupFaces(self, meshData):
return (groupFaces(meshData[0]), meshData)
def calculateWires(self, groupData):
faceGroups = groupData[0]
meshData = groupData[1]
return (wiresFromFaceGroups(meshData[0], faceGroups), meshData)
def calculateFaces(self, wireData):
wires = wireData[0]
meshData = wireData[1]
return ([Part.Face(wire) for wire in wires], meshData)
def computeShell(self, faceData):
faces = faceData[0]
meshData = faceData[1]
return (Part.Compound(faces), meshData)
def recomputeView(self, shellData):
shell = shellData[0]
meshData = shellData[1]
Part.show(shell, meshData[1] + '_Solid')
lithophane_utils.recomputeView()
def IsActive(self):
"""There should be at least an active document."""
return not FreeCAD.ActiveDocument is None
if __name__ == "__main__":
command = MakeSolidCommand();
if command.IsActive():
command.Activated()
else:
qtutils.showInfo("No open Document", "There is no open document")
else:
import toolbars
toolbars.toolbarManager.registerCommand(MakeSolidCommand())