@@ -6,6 +6,13 @@ Supported file formats are `.stl`, `.asc` and `dxf`.
66For comprehensive information about the supported file formats, refer to the documentation at
77[Read geometries from file](@ref read_geometries_from_file).
88
9+ !!! note
10+ ASCII STL files may contain multiple `solid ... endsolid` patches. In that case
11+ the function returns a `Vector{TriangleMesh}` with one `TriangleMesh` per patch.
12+ For single-patch files the function returns a single `TriangleMesh`.
13+ If you prefer a single combined geometry instead of multiple patches, call
14+ `union(geometries...)` on the returned vector to merge all patches into one `TriangleMesh`.
15+
916# Arguments
1017- `filename`: Name of the file to be loaded.
1118
132139
133140# FileIO.jl docs:
134141# https://juliaio.github.io/FileIO.jl/stable/implementing/#All-at-once-I/O:-implementing-load-and-save
135- function load (fn:: FileIO.File{FileIO.format"STL_BINARY"} ; element_types... )
142+ function load (fn:: Union {FileIO. File{FileIO. format " STL_BINARY" },
143+ FileIO. File{FileIO. format " STL_ASCII" }}; element_types... )
136144 open (fn) do s
137145 FileIO. skipmagic (s) # skip over the magic bytes
138146 load (s; element_types... )
@@ -155,6 +163,81 @@ function load(fs::FileIO.Stream{FileIO.format"STL_BINARY"}; ELTYPE=Float64)
155163 return TriangleMesh (face_vertices, normals, vertices)
156164end
157165
166+ function load (fs:: FileIO.Stream{FileIO.format"STL_ASCII"} ; ELTYPE= Float64)
167+ # ASCII STL (solid ... endsolid)
168+ io = FileIO. stream (fs)
169+
170+ # Unlike the binary STL format, the ASCII STL does not include a face count up front;
171+ # faces must be discovered by parsing until the end of the file.
172+ face_vertices = Tuple{SVector{3 , ELTYPE}, SVector{3 , ELTYPE}, SVector{3 , ELTYPE}}[]
173+ vertices = SVector{3 , ELTYPE}[]
174+ normals = SVector{3 , ELTYPE}[]
175+ # ASCII STL files may contain multiple "solid ... endsolid" patches.
176+ # Collect each patch as a separate `TriangleMesh` and return a Vector.
177+ # If the file contains only one patch we return the single `TriangleMesh`.
178+ geometries = TriangleMesh[]
179+
180+ load_data_ascii! (geometries, face_vertices, vertices, normals, io)
181+
182+ length (geometries) == 1 && return first (geometries)
183+
184+ return geometries
185+ end
186+
187+ function load_data_ascii! (geometries,
188+ face_vertices:: Vector {Tuple{SVector{3 , T}, SVector{3 , T},
189+ SVector{3 , T}}},
190+ vertices, normals, io) where {T}
191+ while ! eof (io)
192+ line = strip (readline (io))
193+ low = lowercase (line)
194+
195+ if startswith (low, " endsolid" )
196+ # First patch finished
197+ push! (geometries,
198+ TriangleMesh (copy (face_vertices), copy (normals), copy (vertices)))
199+
200+ empty! (face_vertices)
201+ empty! (normals)
202+ empty! (vertices)
203+ end
204+
205+ # look for facet normal ...
206+ if startswith (low, " facet" )
207+ parts = split (line)
208+ # Expect: `["facet", "normal", nx, ny, nz]`
209+ @assert length (parts)>= 5 " Unexpected facet normal line: $line "
210+ n = SVector {3, T} (parse (T, parts[3 ]), parse (T, parts[4 ]), parse (T, parts[5 ]))
211+ push! (normals, n)
212+
213+ # Consume "outer loop"
214+ while ! eof (io)
215+ lowercase (strip (readline (io))) == " outer loop" && break
216+ end
217+
218+ # Read three vertex lines
219+ for _ in 1 : 3
220+ l = strip (readline (io))
221+ partv = split (l)
222+ @assert lowercase (partv[1 ])== " vertex" " Unexpected vertex line: $l "
223+ vertex = SVector {3, T} (parse (T, partv[2 ]), parse (T, partv[3 ]),
224+ parse (T, partv[4 ]))
225+
226+ push! (vertices, vertex)
227+ end
228+
229+ push! (face_vertices, (vertices[end - 2 ], vertices[end - 1 ], vertices[end ]))
230+
231+ # Consume "endloop" and "endfacet"
232+ while ! eof (io)
233+ lowercase (strip (readline (io))) == " endfacet" && break
234+ end
235+ end
236+ end
237+
238+ return geometries
239+ end
240+
158241function load_data! (face_vertices:: Vector {Tuple{SVector{3 , T}, SVector{3 , T},
159242 SVector{3 , T}}},
160243 vertices, normals, io) where {T}
0 commit comments