parse.py

changeset 54
0c686d10eb49
parent 47
4da025d0b283
child 62
f0a6bf48b05e
--- a/parse.py	Wed May 29 16:36:23 2019 +0300
+++ b/parse.py	Thu May 30 12:03:53 2019 +0300
@@ -3,10 +3,84 @@
 from geometry import *
 from colours import Colour
 from testsuite import error
+import header
 
 class BadLdrawLine(Exception):
     pass
 
+class Model:
+    def __init__(self, header, body, *, ldraw_directories, header_size = 0):
+        self.header = header
+        self.body = body
+        self.header_size = header_size
+        self.ldraw_directories = ldraw_directories
+    def filter_by_type(self, type):
+        yield from [
+            element
+            for element in self.body
+            if isinstance(element, type)
+        ]
+    @property
+    def subfile_references(self):
+        yield from self.filter_by_type(linetypes.SubfileReference)
+    @property
+    def line_segments(self):
+        yield from self.filter_by_type(linetypes.LineSegment)
+    @property
+    def triangles(self):
+        yield from self.filter_by_type(linetypes.Triangle)
+    @property
+    def quadrilaterals(self):
+        yield from self.filter_by_type(linetypes.Quadrilateral)
+    @property
+    def has_header(self):
+        return self.header and not isinstance(self.header, header.BadHeader)
+
+def model_vertices(
+    model,
+    transformation_matrix = None,
+    file_cache = None,
+):
+    if transformation_matrix is None:
+        transformation_matrix = complete_matrix(Matrix3x3(), Vertex(0, 0, 0))
+    if file_cache is None:
+        import filecache
+        file_cache = filecache.SubfileCache(model.ldraw_directories)
+    for element in model.body:
+        if isinstance(element, linetypes.BasePolygon):
+            for point in element.geometry.vertices:
+                yield point @ transformation_matrix
+        if isinstance(element, linetypes.ConditionalLine):
+            for point in element.control_points:
+                yield point @ transformation_matrix
+        if isinstance(element, linetypes.SubfileReference):
+            subfile = file_cache.prepare_file(element.subfile_path)
+            for point in subfile.vertices:
+                matrix_4x4 = complete_matrix(element.matrix, element.anchor)
+                point @= matrix_4x4
+                yield point @ transformation_matrix
+
+def read_ldraw(file, *, ldraw_directories, name = ''):
+    model_body = [
+        parse_ldraw_code(line)
+        for line in file
+    ]
+    headerparser = header.HeaderParser()
+    try:
+        header_parse_result = headerparser.parse(model_body)
+        header_object = header_parse_result['header']
+        end = header_parse_result['end-index']
+    except header.HeaderError as error:
+        header_object = header.BadHeader(error.index, error.reason)
+        end = 0
+    model = Model(
+        header = header_object,
+        body = model_body,
+        header_size = end,
+        ldraw_directories = ldraw_directories)
+    model.name = name
+    return model
+
 def parse_ldraw_code(line):
     try:
         if isinstance(line, bytes):

mercurial