1
2 """Read a STL file and do simple manipulations"""
3
4 from os import path
5 from PyFoam.Error import error
6
7 from PyFoam.ThirdParty.six import next as iterNext
8
10 """Store a complete STL-file and do simple manipulations with it"""
11
12 noName="<no name given>"
13
15 """
16 @param fName: filename of the STL-file. If None then an empty file is created
17 """
18 self._fp=None
19 if hasattr(fName, 'read'):
20
21 self._fp=fName
22 if hasattr(fName,'name'):
23 self._filename=fName.name
24 else:
25 self._filename="<filehandle>"
26 else:
27 self._filename=fName
28
29 if self._fp==None:
30 if fName!=None:
31 self._contents=[l.strip() for l in open(fName).readlines()]
32 else:
33 self._contents=[]
34 else:
35 self._contents=[l.strip() for l in self._fp.readlines()]
36
37 self.resetInfo()
38
40 """Set cached info to nothing"""
41 self._patchInfo=None
42
44 """The filename (without the full patch)"""
45 if self._filename==None:
46 return "<no filename given>"
47 else:
48 return path.basename(self._filename)
49
53
55 """Erase the patches in the list"""
56 processed=[]
57
58 keep=True
59 currentName=None
60
61 for l in self._contents:
62 nextState=keep
63 parts=l.split()
64 if len(parts)>0:
65 if parts[0]=="endsolid":
66 nextState=True
67 if currentName!=parts[1]:
68 error("Patch name",parts[1],"Expected",currentName)
69 currentName=None
70 elif parts[0]=="solid":
71 currentName=parts[1]
72 if currentName in patchNames:
73 keep=False
74 nextState=False
75 if keep:
76 processed.append(l)
77 keep=nextState
78
79 self._contents=processed
80
82 """Merge the patches in the list and put them into a new patch"""
83
84 processed=[]
85 saved=[]
86
87 keep=True
88 currentName=None
89
90 for l in self._contents:
91 nextState=keep
92 parts=l.split()
93 if len(parts)>0:
94 if parts[0]=="endsolid":
95 nextState=True
96 if currentName!=parts[1]:
97 error("Patch name",parts[1],"Expected",currentName)
98 currentName=None
99 elif parts[0]=="solid":
100 currentName=parts[1]
101 if currentName in patchNames:
102 keep=False
103 nextState=False
104 if keep:
105 processed.append(l)
106 elif len(parts)>0:
107 if parts[0] not in ["solid","endsolid"]:
108 saved.append(l)
109 keep=nextState
110
111 self._contents=processed
112
113 self._contents.append("solid "+targetPatchName)
114 self._contents+=saved
115 self._contents.append("endsolid "+targetPatchName)
116
118 """Get info about the patches. A list of dictionaries with the relevant information"""
119 if self._patchInfo:
120 return self._patchInfo
121
122 self._patchInfo=[]
123
124 newPatch=True
125
126 e=enumerate(self._contents)
127
128 goOn=True
129 while goOn:
130 try:
131 i,l=iterNext(e)
132 if newPatch:
133 self.expectedToken(l,"solid",i)
134 info={}
135 if len(l.split())<2:
136 info["name"]=self.noName
137 else:
138 info["name"]=l.split()[1]
139 info["start"]=i+1
140 info["facets"]=0
141 info["min"]=[1e100]*3
142 info["max"]=[-1e100]*3
143 newPatch=False
144 elif l.strip().find("endsolid")==0:
145 info["end"]=i+1
146 self._patchInfo.append(info)
147 newPatch=True
148 else:
149 self.expectedToken(l,"facet normal",i)
150 i,l=iterNext(e)
151 self.expectedToken(l,"outer loop",i)
152 for v in range(3):
153 i,l=iterNext(e)
154 self.expectedToken(l,"vertex",i)
155 info["min"]=[min(m) for m in zip(info["min"],
156 [float(v) for v in l.strip().split()[1:4]])]
157 info["max"]=[max(m) for m in zip(info["max"],
158 [float(v) for v in l.strip().split()[1:4]])]
159 i,l=iterNext(e)
160 self.expectedToken(l,"endloop",i)
161 i,l=iterNext(e)
162 self.expectedToken(l,"endfacet",i)
163 info["facets"]+=1
164 except StopIteration:
165 goOn=False
166
167
168 if not newPatch:
169 error("File",self.filename(),"seems to be incomplete")
170
171 return self._patchInfo
172
181
183 for l in self._contents:
184 yield l
185
187 self.resetInfo()
188
189 fName=path.splitext(other.filename())[0]
190 moreThanOne=len(other.patchInfo())>1
191
192 nr=1
193
194 for l in other:
195 if l.strip().find("solid")==0 or l.strip().find("endsolid")==0:
196 parts=l.split()
197 if len(parts)==1:
198 l=parts[0]+" "+fName
199 if moreThanOne:
200 l+="_%04d" % nr
201 else:
202 l=parts[0]+" %s:%s" %(fName," ".join(parts[1:]))
203 if parts[0]=="solid":
204 nr+=1
205
206 self._contents.append(l)
207
208 return self
209
210
211