parse.py

changeset 54
0c686d10eb49
parent 47
4da025d0b283
child 62
f0a6bf48b05e
equal deleted inserted replaced
53:0cc196c634f1 54:0c686d10eb49
1 import linetypes 1 import linetypes
2 import re 2 import re
3 from geometry import * 3 from geometry import *
4 from colours import Colour 4 from colours import Colour
5 from testsuite import error 5 from testsuite import error
6 import header
6 7
7 class BadLdrawLine(Exception): 8 class BadLdrawLine(Exception):
8 pass 9 pass
10
11 class Model:
12 def __init__(self, header, body, *, ldraw_directories, header_size = 0):
13 self.header = header
14 self.body = body
15 self.header_size = header_size
16 self.ldraw_directories = ldraw_directories
17 def filter_by_type(self, type):
18 yield from [
19 element
20 for element in self.body
21 if isinstance(element, type)
22 ]
23 @property
24 def subfile_references(self):
25 yield from self.filter_by_type(linetypes.SubfileReference)
26 @property
27 def line_segments(self):
28 yield from self.filter_by_type(linetypes.LineSegment)
29 @property
30 def triangles(self):
31 yield from self.filter_by_type(linetypes.Triangle)
32 @property
33 def quadrilaterals(self):
34 yield from self.filter_by_type(linetypes.Quadrilateral)
35 @property
36 def has_header(self):
37 return self.header and not isinstance(self.header, header.BadHeader)
38
39 def model_vertices(
40 model,
41 transformation_matrix = None,
42 file_cache = None,
43 ):
44 if transformation_matrix is None:
45 transformation_matrix = complete_matrix(Matrix3x3(), Vertex(0, 0, 0))
46 if file_cache is None:
47 import filecache
48 file_cache = filecache.SubfileCache(model.ldraw_directories)
49 for element in model.body:
50 if isinstance(element, linetypes.BasePolygon):
51 for point in element.geometry.vertices:
52 yield point @ transformation_matrix
53 if isinstance(element, linetypes.ConditionalLine):
54 for point in element.control_points:
55 yield point @ transformation_matrix
56 if isinstance(element, linetypes.SubfileReference):
57 subfile = file_cache.prepare_file(element.subfile_path)
58 for point in subfile.vertices:
59 matrix_4x4 = complete_matrix(element.matrix, element.anchor)
60 point @= matrix_4x4
61 yield point @ transformation_matrix
62
63 def read_ldraw(file, *, ldraw_directories, name = ''):
64 model_body = [
65 parse_ldraw_code(line)
66 for line in file
67 ]
68 headerparser = header.HeaderParser()
69 try:
70 header_parse_result = headerparser.parse(model_body)
71 header_object = header_parse_result['header']
72 end = header_parse_result['end-index']
73 except header.HeaderError as error:
74 header_object = header.BadHeader(error.index, error.reason)
75 end = 0
76 model = Model(
77 header = header_object,
78 body = model_body,
79 header_size = end,
80 ldraw_directories = ldraw_directories)
81 model.name = name
82 return model
9 83
10 def parse_ldraw_code(line): 84 def parse_ldraw_code(line):
11 try: 85 try:
12 if isinstance(line, bytes): 86 if isinstance(line, bytes):
13 line = line.decode() 87 line = line.decode()

mercurial