model-converter-python/d3/model/formats/stl.py

117 lines
3.4 KiB
Python
Raw Normal View History

2017-01-17 09:47:57 +00:00
from ..basemodel import TextModelParser, Exporter, Vertex, FaceVertex, Face
2016-12-02 14:52:01 +00:00
from ..mesh import MeshPart
2016-11-30 13:57:58 +00:00
import os.path
def is_stl(filename):
2017-01-18 14:18:31 +00:00
"""Checks that the file is a .stl file
Only checks the extension of the file
:param filename: path to the file
"""
2016-11-30 13:57:58 +00:00
return filename[-4:] == '.stl'
2017-01-17 09:47:57 +00:00
class STLParser(TextModelParser):
2017-01-18 14:18:31 +00:00
"""Parser that parses a .stl file
"""
2016-11-30 13:57:58 +00:00
2016-11-30 14:37:58 +00:00
def __init__(self, up_conversion = None):
super().__init__(up_conversion)
2016-11-30 13:57:58 +00:00
self.parsing_solid = False
self.parsing_face = False
self.parsing_loop = False
self.current_face = None
self.face_vertices = None
def parse_line(self, string):
2017-01-18 14:18:31 +00:00
"""Parses a line of .stl file
2016-11-30 13:57:58 +00:00
2017-01-18 14:18:31 +00:00
:param string: the line to parse
"""
2016-11-30 13:57:58 +00:00
if string == '':
return
split = string.split()
if split[0] == 'solid':
self.parsing_solid = True
return
if split[0] == 'endsolid':
self.parsing_solid = False
return
if self.parsing_solid:
if split[0] == 'facet' and split[1] == 'normal':
self.parsing_face = True
self.face_vertices = [FaceVertex(), FaceVertex(), FaceVertex()]
self.current_face = Face(*self.face_vertices)
return
if self.parsing_face:
if split[0] == 'outer' and split[1] == 'loop':
self.parsing_loop = True
return
if split[0] == 'endloop':
self.parsing_loop = False
return
if self.parsing_loop:
if split[0] == 'vertex':
current_vertex = Vertex().from_array(split[1:])
self.add_vertex(current_vertex)
self.face_vertices[0].vertex = len(self.vertices) - 1
self.face_vertices.pop(0)
return
if split[0] == 'endfacet':
self.parsing_face = False
self.add_face(self.current_face)
self.current_face = None
self.face_vertices = None
class STLExporter(Exporter):
2017-01-18 14:18:31 +00:00
"""Exporter to .stl format
"""
2016-11-30 13:57:58 +00:00
def __init__(self, model):
2017-01-18 14:18:31 +00:00
"""Creates an exporter from the model
:param model: Model to export
"""
super().__init__(model)
2016-11-30 13:57:58 +00:00
super().__init__(model)
def __str__(self):
2017-01-18 14:18:31 +00:00
"""Exports the model
"""
2016-11-30 13:57:58 +00:00
string = 'solid {}\n'.format(os.path.basename(self.model.path[:-4]))
self.model.generate_face_normals()
faces = sum(map(lambda x: x.faces, self.model.parts), [])
for face in faces:
n = self.model.normals[face.a.normal]
v1 = self.model.vertices[face.a.vertex]
v2 = self.model.vertices[face.b.vertex]
v3 = self.model.vertices[face.c.vertex]
string += "facet normal {} {} {}\n".format(n.x, n.y, n.z)
string += "\touter loop\n"
string += "\t\tvertex {} {} {}\n".format(v1.x, v1.y, v1.z)
string += "\t\tvertex {} {} {}\n".format(v2.x, v2.y, v2.z)
string += "\t\tvertex {} {} {}\n".format(v3.x, v3.y, v3.z)
string += "\tendloop\n"
string += "endfacet\n"
string += 'endsolid {}'.format(os.path.basename(self.model.path[:-4]))
return string