diff -r 0cc196c634f1 -r 0c686d10eb49 parse.py --- 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):