96 lines
2.2 KiB
Python
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)
|