13 if not line: |
13 if not line: |
14 return linetypes.EmptyLine() |
14 return linetypes.EmptyLine() |
15 elif line == '0': |
15 elif line == '0': |
16 return linetypes.Comment('') |
16 return linetypes.Comment('') |
17 elif line.startswith('0 '): |
17 elif line.startswith('0 '): |
18 return linetypes.Comment(line[2:].strip()) |
18 return linetypes.Comment(line[2:]) |
19 elif line.startswith('1 '): |
19 elif line.startswith('1 '): |
20 return parse_ldraw_subfile_reference(line) |
20 return parse_ldraw_subfile_reference(line) |
21 elif line.startswith('2 '): |
21 elif line.startswith('2 '): |
22 return parse_ldraw_line(line) |
22 return parse_ldraw_line(line) |
23 elif line.startswith('3 '): |
23 elif line.startswith('3 '): |
24 return parse_ldraw_triangle(line) |
24 return parse_ldraw_triangle(line) |
25 elif line.startswith('4 '): |
25 elif line.startswith('4 '): |
26 return parse_ldraw_quadrilateral(line) |
26 return parse_ldraw_quadrilateral(line) |
27 elif line.startswith('5 '): |
27 elif line.startswith('5 '): |
28 return parse_ldraw_contour(line) |
28 return parse_ldraw_conditional_line(line) |
29 else: |
29 else: |
30 raise BadLdrawLine('unknown line type') |
30 raise BadLdrawLine('unknown line type') |
31 |
31 |
32 def parse_ldraw_subfile_reference(line): |
32 def parse_ldraw_subfile_reference(line): |
33 pattern = r'^1\s+([^ ]+)' + r'\s+([^ ]+)' * (3 + 9 + 1) + r'\s*$' |
33 pattern = r'^1\s+([^ ]+)' + r'\s+([^ ]+)' * (3 + 9 + 1) + r'\s*$' |
53 matrix = Matrix3x3(matrix_values), |
53 matrix = Matrix3x3(matrix_values), |
54 subfile_path = groups[indices['subfile_path']] |
54 subfile_path = groups[indices['subfile_path']] |
55 ) |
55 ) |
56 |
56 |
57 def generic_parse_polygon(line, *, type_code, vertex_count): |
57 def generic_parse_polygon(line, *, type_code, vertex_count): |
58 pattern = r'^' \ |
58 pattern = r'^' # matches the start of line |
59 + str(type_code) \ |
59 pattern += str(type_code) # matches the type code |
60 + '\s+([^ ]+)' \ |
60 pattern += '\s+([^ ]+)' # matches the colour |
61 + r'\s+([^ ]+)' * (vertex_count * 3) \ |
61 pattern += r'\s+([^ ]+)' * (vertex_count * 3) # matches the vertices |
62 + r'\s*$' |
62 pattern += r'\s*$' # matches any trailing space |
63 match = re.search(pattern, line) |
63 match = re.search(pattern, line) |
64 if not match: |
64 if not match: |
65 raise BadLdrawLine(str.format('cannot parse type-{} line', type_code)) |
65 raise BadLdrawLine(str.format('cannot parse type-{} line', type_code)) |
66 vertices = [] |
66 vertices = [] |
67 for vertex_index in range(vertex_count): |
67 for vertex_index in range(vertex_count): |
98 return linetypes.Quadrilateral( |
98 return linetypes.Quadrilateral( |
99 colour = parse_result['colour'], |
99 colour = parse_result['colour'], |
100 geometry = Polygon(parse_result['vertices']), |
100 geometry = Polygon(parse_result['vertices']), |
101 ) |
101 ) |
102 |
102 |
103 def parse_ldraw_contour(line): |
103 def parse_ldraw_conditional_line(line): |
104 parse_result = generic_parse_polygon(line, type_code = 5, vertex_count = 4) |
104 parse_result = generic_parse_polygon(line, type_code = 5, vertex_count = 4) |
105 return linetypes.Contour( |
105 return linetypes.ConditionalLine( |
106 colour = parse_result['colour'], |
106 colour = parse_result['colour'], |
107 geometry = LineSegment(*parse_result['vertices'][0:2]), |
107 geometry = LineSegment(*parse_result['vertices'][0:2]), |
108 control_points = parse_result['vertices'][2:], |
108 control_points = parse_result['vertices'][2:], |
109 ) |
109 ) |