windmill-gint/converters.py

96 lines
2.2 KiB
Python

with open("humanoid.stl", "r") as fp:
stl = fp.read()
#---
class Lexer:
def __init__(self, data):
assert(data.startswith("solid"))
self.data = data
self.pos = min(80, data.index("\n"))
def lex(self):
# Skip leading whitespace
while self.pos < len(self.data) and self.data[self.pos] in " \t\n":
self.pos += 1
if self.pos >= len(self.data):
return None
# Grab a word
i = self.pos
while i < len(self.data) and self.data[i] not in " \t\n":
i += 1
word = self.data[self.pos:i]
self.pos = i
return float(word) if word[0] in "+-0123456789." else word
#---
class Parser:
def __init__(self, lexer):
self.lexer = lexer
self.la = "" # look-ahead token
self.feed()
def at_end(self):
return self.la == None
def feed(self):
t = self.la
self.la = lexer.lex()
return t
def expect_keyword(self, keyword):
assert self.la == keyword
self.feed()
def expect_float(self):
assert isinstance(self.la, float)
return self.feed()
#---
def vec3(self, leading_keyword):
self.expect_keyword(leading_keyword)
x = self.expect_float()
y = self.expect_float()
z = self.expect_float()
return (x, y, z)
def outer_loop(self):
self.expect_keyword("outer")
self.expect_keyword("loop")
v1 = self.vec3("vertex")
v2 = self.vec3("vertex")
v3 = self.vec3("vertex")
self.expect_keyword("endloop")
return [v1, v2, v3]
def facet(self):
self.expect_keyword("facet")
normal = self.vec3("normal")
vertices = self.outer_loop()
self.expect_keyword("endfacet")
return {"normal": normal, "vertices": vertices}
def solid(self):
facets = []
while self.la == "facet":
facets.append(self.facet())
self.expect_keyword("endsolid")
self.feed()
assert self.at_end()
return facets
#---
lexer = Lexer(stl)
parser = Parser(lexer)
solid = parser.solid()
from pprint import pprint
pprint(solid, width=90)