Fri, 18 Sep 2020 21:08:41 +0300
added mirrored studs test
| 2 | 1 | import linetypes |
| 2 | import re | |
| 3 | from geometry import * | |
| 8 | 4 | from colours import Colour |
|
54
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
5 | import header |
| 2 | 6 | |
| 7 | class BadLdrawLine(Exception): | |
| 8 | pass | |
| 9 | ||
|
54
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
10 | class Model: |
|
94
109fb7cf658f
added a check for non-DOS line endings
Teemu Piippo <teemu@hecknology.net>
parents:
69
diff
changeset
|
11 | def __init__( |
|
109fb7cf658f
added a check for non-DOS line endings
Teemu Piippo <teemu@hecknology.net>
parents:
69
diff
changeset
|
12 | self, header, body, *, ldraw_directories, \ |
|
109fb7cf658f
added a check for non-DOS line endings
Teemu Piippo <teemu@hecknology.net>
parents:
69
diff
changeset
|
13 | header_size = 0, line_ending_errors = None |
|
109fb7cf658f
added a check for non-DOS line endings
Teemu Piippo <teemu@hecknology.net>
parents:
69
diff
changeset
|
14 | ): |
|
54
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
15 | self.header = header |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
16 | self.body = body |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
17 | self.header_size = header_size |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
18 | self.ldraw_directories = ldraw_directories |
|
94
109fb7cf658f
added a check for non-DOS line endings
Teemu Piippo <teemu@hecknology.net>
parents:
69
diff
changeset
|
19 | self.line_ending_errors = line_ending_errors |
|
54
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
20 | def filter_by_type(self, type): |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
21 | yield from [ |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
22 | element |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
23 | for element in self.body |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
24 | if isinstance(element, type) |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
25 | ] |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
26 | @property |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
27 | def subfile_references(self): |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
28 | yield from self.filter_by_type(linetypes.SubfileReference) |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
29 | @property |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
30 | def line_segments(self): |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
31 | yield from self.filter_by_type(linetypes.LineSegment) |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
32 | @property |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
33 | def triangles(self): |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
34 | yield from self.filter_by_type(linetypes.Triangle) |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
35 | @property |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
36 | def quadrilaterals(self): |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
37 | yield from self.filter_by_type(linetypes.Quadrilateral) |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
38 | @property |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
39 | def has_header(self): |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
40 | return self.header and not isinstance(self.header, header.BadHeader) |
|
69
a24c4490d9f2
added a check for keywords in non-parts
Teemu Piippo <teemu@hecknology.net>
parents:
62
diff
changeset
|
41 | def find_first_header_object(self, object_type): |
|
101
745f2c3aec0a
added ability to get other header elements than just the first one
Teemu Piippo <teemu@hecknology.net>
parents:
94
diff
changeset
|
42 | return self.find_header_object(object_type, 0) |
|
745f2c3aec0a
added ability to get other header elements than just the first one
Teemu Piippo <teemu@hecknology.net>
parents:
94
diff
changeset
|
43 | def find_header_object(self, object_type, n): |
|
127
97de6058109e
added bfc declaration tests
Teemu Piippo <teemu@hecknology.net>
parents:
101
diff
changeset
|
44 | try: |
|
97de6058109e
added bfc declaration tests
Teemu Piippo <teemu@hecknology.net>
parents:
101
diff
changeset
|
45 | return self.body[self.header.occurrences[object_type][n]] |
|
97de6058109e
added bfc declaration tests
Teemu Piippo <teemu@hecknology.net>
parents:
101
diff
changeset
|
46 | except IndexError: |
|
97de6058109e
added bfc declaration tests
Teemu Piippo <teemu@hecknology.net>
parents:
101
diff
changeset
|
47 | raise KeyError(str.format( |
|
97de6058109e
added bfc declaration tests
Teemu Piippo <teemu@hecknology.net>
parents:
101
diff
changeset
|
48 | '{type} not found in header', |
|
97de6058109e
added bfc declaration tests
Teemu Piippo <teemu@hecknology.net>
parents:
101
diff
changeset
|
49 | type = object_type |
|
97de6058109e
added bfc declaration tests
Teemu Piippo <teemu@hecknology.net>
parents:
101
diff
changeset
|
50 | )) |
|
54
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
51 | |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
52 | def model_vertices( |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
53 | model, |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
54 | transformation_matrix = None, |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
55 | file_cache = None, |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
56 | ): |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
57 | if transformation_matrix is None: |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
58 | transformation_matrix = complete_matrix(Matrix3x3(), Vertex(0, 0, 0)) |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
59 | if file_cache is None: |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
60 | import filecache |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
61 | file_cache = filecache.SubfileCache(model.ldraw_directories) |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
62 | for element in model.body: |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
63 | if isinstance(element, linetypes.BasePolygon): |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
64 | for point in element.geometry.vertices: |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
65 | yield point @ transformation_matrix |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
66 | if isinstance(element, linetypes.ConditionalLine): |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
67 | for point in element.control_points: |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
68 | yield point @ transformation_matrix |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
69 | if isinstance(element, linetypes.SubfileReference): |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
70 | subfile = file_cache.prepare_file(element.subfile_path) |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
71 | for point in subfile.vertices: |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
72 | matrix_4x4 = complete_matrix(element.matrix, element.anchor) |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
73 | point @= matrix_4x4 |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
74 | yield point @ transformation_matrix |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
75 | |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
76 | def read_ldraw(file, *, ldraw_directories, name = ''): |
|
94
109fb7cf658f
added a check for non-DOS line endings
Teemu Piippo <teemu@hecknology.net>
parents:
69
diff
changeset
|
77 | line_ending_errors = { |
|
109fb7cf658f
added a check for non-DOS line endings
Teemu Piippo <teemu@hecknology.net>
parents:
69
diff
changeset
|
78 | 'count': 0, |
|
109fb7cf658f
added a check for non-DOS line endings
Teemu Piippo <teemu@hecknology.net>
parents:
69
diff
changeset
|
79 | 'first-at': None, |
|
109fb7cf658f
added a check for non-DOS line endings
Teemu Piippo <teemu@hecknology.net>
parents:
69
diff
changeset
|
80 | } |
|
109fb7cf658f
added a check for non-DOS line endings
Teemu Piippo <teemu@hecknology.net>
parents:
69
diff
changeset
|
81 | model_body = [] |
|
109fb7cf658f
added a check for non-DOS line endings
Teemu Piippo <teemu@hecknology.net>
parents:
69
diff
changeset
|
82 | for i, line in enumerate(file.readlines()): |
|
109fb7cf658f
added a check for non-DOS line endings
Teemu Piippo <teemu@hecknology.net>
parents:
69
diff
changeset
|
83 | # check line endings |
|
109fb7cf658f
added a check for non-DOS line endings
Teemu Piippo <teemu@hecknology.net>
parents:
69
diff
changeset
|
84 | if not line.endswith(b'\r\n'): |
|
109fb7cf658f
added a check for non-DOS line endings
Teemu Piippo <teemu@hecknology.net>
parents:
69
diff
changeset
|
85 | if line_ending_errors['first-at'] is None: |
|
109fb7cf658f
added a check for non-DOS line endings
Teemu Piippo <teemu@hecknology.net>
parents:
69
diff
changeset
|
86 | line_ending_errors['first-at'] = i |
|
109fb7cf658f
added a check for non-DOS line endings
Teemu Piippo <teemu@hecknology.net>
parents:
69
diff
changeset
|
87 | line_ending_errors['count'] += 1 |
|
109fb7cf658f
added a check for non-DOS line endings
Teemu Piippo <teemu@hecknology.net>
parents:
69
diff
changeset
|
88 | model_body.append(parse_ldraw_code(line)) |
|
109fb7cf658f
added a check for non-DOS line endings
Teemu Piippo <teemu@hecknology.net>
parents:
69
diff
changeset
|
89 | if line_ending_errors['count'] == 0: |
|
109fb7cf658f
added a check for non-DOS line endings
Teemu Piippo <teemu@hecknology.net>
parents:
69
diff
changeset
|
90 | line_ending_errors = None |
|
54
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
91 | headerparser = header.HeaderParser() |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
92 | try: |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
93 | header_parse_result = headerparser.parse(model_body) |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
94 | header_object = header_parse_result['header'] |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
95 | end = header_parse_result['end-index'] |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
96 | except header.HeaderError as error: |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
97 | header_object = header.BadHeader(error.index, error.reason) |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
98 | end = 0 |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
99 | model = Model( |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
100 | header = header_object, |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
101 | body = model_body, |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
102 | header_size = end, |
|
94
109fb7cf658f
added a check for non-DOS line endings
Teemu Piippo <teemu@hecknology.net>
parents:
69
diff
changeset
|
103 | ldraw_directories = ldraw_directories, |
|
109fb7cf658f
added a check for non-DOS line endings
Teemu Piippo <teemu@hecknology.net>
parents:
69
diff
changeset
|
104 | line_ending_errors = line_ending_errors, |
|
109fb7cf658f
added a check for non-DOS line endings
Teemu Piippo <teemu@hecknology.net>
parents:
69
diff
changeset
|
105 | ) |
|
54
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
106 | model.name = name |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
107 | return model |
|
0c686d10eb49
added tests for moved-to files and scaling in flat dimensions
Teemu Piippo <teemu@hecknology.net>
parents:
47
diff
changeset
|
108 | |
| 2 | 109 | def parse_ldraw_code(line): |
|
38
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
110 | try: |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
111 | if isinstance(line, bytes): |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
112 | line = line.decode() |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
113 | line = line.strip() |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
114 | if not line: |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
115 | return linetypes.EmptyLine() |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
116 | elif line == '0': |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
117 | return linetypes.MetaCommand('') |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
118 | elif line.startswith('0 '): |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
119 | return parse_ldraw_meta_line(line) |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
120 | elif line.startswith('1 '): |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
121 | return parse_ldraw_subfile_reference(line) |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
122 | elif line.startswith('2 '): |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
123 | return parse_ldraw_line(line) |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
124 | elif line.startswith('3 '): |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
125 | return parse_ldraw_triangle(line) |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
126 | elif line.startswith('4 '): |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
127 | return parse_ldraw_quadrilateral(line) |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
128 | elif line.startswith('5 '): |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
129 | return parse_ldraw_conditional_line(line) |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
130 | else: |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
131 | raise BadLdrawLine('unknown line type') |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
132 | except BadLdrawLine as error: |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
133 | return linetypes.Error(line, str(error)) |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
134 | |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
135 | def parse_ldraw_meta_line(line): |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
136 | if line.startswith('0 //'): |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
137 | return linetypes.Comment(line[4:]) |
| 2 | 138 | else: |
|
38
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
139 | return linetypes.MetaCommand(line[2:]) |
| 2 | 140 | |
| 141 | def parse_ldraw_subfile_reference(line): | |
|
3
1dc58f44d556
Can now write dat files, added direct color handling
Santeri Piippo
parents:
2
diff
changeset
|
142 | pattern = r'^1\s+([^ ]+)' + r'\s+([^ ]+)' * (3 + 9 + 1) + r'\s*$' |
| 2 | 143 | match = re.search(pattern, line) |
| 144 | if not match: | |
| 145 | raise BadLdrawLine('unable to parse') | |
| 146 | groups = list(match.groups()) | |
| 147 | indices = { | |
| 4 | 148 | 'colour_index': 0, |
| 2 | 149 | 'anchor': slice(1, 4), |
| 150 | 'matrix': slice(4, 13), | |
| 151 | 'subfile_path': 13 | |
| 152 | } | |
| 153 | try: | |
| 4 | 154 | colour = Colour(groups[indices['colour_index']]) |
| 2 | 155 | vertex_values = [float(x) for x in groups[indices['anchor']]] |
| 156 | matrix_values = [float(x) for x in groups[indices['matrix']]] | |
| 157 | except ValueError: | |
| 158 | raise BadLdrawLine('bad numeric values') | |
| 159 | return linetypes.SubfileReference( | |
| 4 | 160 | colour = colour, |
| 2 | 161 | anchor = Vertex(*vertex_values), |
|
6
6da1e81c5652
Added code to compute areas of triangles and quadrilaterals
Santeri Piippo
parents:
4
diff
changeset
|
162 | matrix = Matrix3x3(matrix_values), |
| 2 | 163 | subfile_path = groups[indices['subfile_path']] |
| 164 | ) | |
| 165 | ||
| 166 | def generic_parse_polygon(line, *, type_code, vertex_count): | |
| 35 | 167 | pattern = r'^' # matches the start of line |
| 168 | pattern += str(type_code) # matches the type code | |
| 169 | pattern += '\s+([^ ]+)' # matches the colour | |
| 170 | pattern += r'\s+([^ ]+)' * (vertex_count * 3) # matches the vertices | |
| 171 | pattern += r'\s*$' # matches any trailing space | |
| 2 | 172 | match = re.search(pattern, line) |
| 173 | if not match: | |
| 174 | raise BadLdrawLine(str.format('cannot parse type-{} line', type_code)) | |
| 175 | vertices = [] | |
| 176 | for vertex_index in range(vertex_count): | |
| 177 | slice_begin = 1 + vertex_index * 3 | |
| 178 | slice_end = 1 + (vertex_index + 1) * 3 | |
| 179 | coordinates = match.groups()[slice_begin:slice_end] | |
| 180 | assert(len(coordinates) == 3) | |
| 181 | try: | |
| 182 | coordinates = [float(x) for x in coordinates] | |
| 183 | except ValueError: | |
| 184 | raise BadLdrawLine('bad numeric values') | |
| 185 | vertices.append(Vertex(*coordinates)) | |
|
38
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
186 | try: |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
187 | colour = int(match.group(1), 0) |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
188 | except ValueError: |
|
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
189 | raise BadLdrawLine('invalid syntax for colour: ' + repr(match.group(1))) |
| 2 | 190 | return { |
|
38
66c9591b733d
added proper handling of syntax errors
Teemu Piippo <teemu@hecknology.net>
parents:
35
diff
changeset
|
191 | 'colour': Colour(colour), |
| 2 | 192 | 'vertices': vertices, |
| 193 | } | |
| 194 | ||
| 195 | def parse_ldraw_line(line): | |
| 196 | parse_result = generic_parse_polygon(line, type_code = 2, vertex_count = 2) | |
| 197 | return linetypes.LineSegment( | |
| 4 | 198 | colour = parse_result['colour'], |
| 2 | 199 | geometry = LineSegment(*parse_result['vertices']), |
| 200 | ) | |
| 201 | ||
| 202 | def parse_ldraw_triangle(line): | |
| 203 | parse_result = generic_parse_polygon(line, type_code = 3, vertex_count = 3) | |
| 204 | return linetypes.Triangle( | |
| 4 | 205 | colour = parse_result['colour'], |
| 2 | 206 | geometry = Polygon(parse_result['vertices']), |
| 207 | ) | |
| 208 | ||
| 209 | def parse_ldraw_quadrilateral(line): | |
| 210 | parse_result = generic_parse_polygon(line, type_code = 4, vertex_count = 4) | |
| 211 | return linetypes.Quadrilateral( | |
| 4 | 212 | colour = parse_result['colour'], |
| 2 | 213 | geometry = Polygon(parse_result['vertices']), |
| 214 | ) | |
| 215 | ||
| 35 | 216 | def parse_ldraw_conditional_line(line): |
| 2 | 217 | parse_result = generic_parse_polygon(line, type_code = 5, vertex_count = 4) |
| 35 | 218 | return linetypes.ConditionalLine( |
| 4 | 219 | colour = parse_result['colour'], |
| 2 | 220 | geometry = LineSegment(*parse_result['vertices'][0:2]), |
| 221 | control_points = parse_result['vertices'][2:], | |
| 222 | ) |