Mon, 11 Dec 2017 00:46:35 +0200
Can now write dat files, added direct color handling
2 | 1 | import linetypes |
2 | import re | |
3 | from geometry import * | |
3
1dc58f44d556
Can now write dat files, added direct color handling
Santeri Piippo
parents:
2
diff
changeset
|
4 | from ldraw import Color |
2 | 5 | |
6 | class BadLdrawLine(Exception): | |
7 | pass | |
8 | ||
9 | def parse_ldraw_code(line): | |
10 | line = line.strip() | |
11 | if not line: | |
12 | return linetypes.EmptyLine() | |
13 | elif line == '0': | |
14 | return linetypes.Comment('') | |
15 | elif line.startswith('0 '): | |
16 | return linetypes.Comment(line[2:].strip()) | |
17 | elif line.startswith('1 '): | |
18 | return parse_ldraw_subfile_reference(line) | |
19 | elif line.startswith('2 '): | |
20 | return parse_ldraw_line(line) | |
21 | elif line.startswith('3 '): | |
22 | return parse_ldraw_triangle(line) | |
23 | elif line.startswith('4 '): | |
24 | return parse_ldraw_quadrilateral(line) | |
25 | elif line.startswith('5 '): | |
26 | return parse_ldraw_contour(line) | |
27 | else: | |
28 | raise BadLdrawLine('unknown line type') | |
29 | ||
30 | def parse_ldraw_subfile_reference(line): | |
3
1dc58f44d556
Can now write dat files, added direct color handling
Santeri Piippo
parents:
2
diff
changeset
|
31 | pattern = r'^1\s+([^ ]+)' + r'\s+([^ ]+)' * (3 + 9 + 1) + r'\s*$' |
2 | 32 | match = re.search(pattern, line) |
33 | if not match: | |
34 | raise BadLdrawLine('unable to parse') | |
35 | groups = list(match.groups()) | |
36 | indices = { | |
3
1dc58f44d556
Can now write dat files, added direct color handling
Santeri Piippo
parents:
2
diff
changeset
|
37 | 'color_index': 0, |
2 | 38 | 'anchor': slice(1, 4), |
39 | 'matrix': slice(4, 13), | |
40 | 'subfile_path': 13 | |
41 | } | |
42 | try: | |
3
1dc58f44d556
Can now write dat files, added direct color handling
Santeri Piippo
parents:
2
diff
changeset
|
43 | color = Color(groups[indices['color_index']]) |
2 | 44 | vertex_values = [float(x) for x in groups[indices['anchor']]] |
45 | matrix_values = [float(x) for x in groups[indices['matrix']]] | |
46 | except ValueError: | |
47 | raise BadLdrawLine('bad numeric values') | |
48 | return linetypes.SubfileReference( | |
49 | color = color, | |
50 | anchor = Vertex(*vertex_values), | |
51 | matrix = TransformationMatrix(matrix_values), | |
52 | subfile_path = groups[indices['subfile_path']] | |
53 | ) | |
54 | ||
55 | def generic_parse_polygon(line, *, type_code, vertex_count): | |
56 | pattern = r'^' \ | |
57 | + str(type_code) \ | |
3
1dc58f44d556
Can now write dat files, added direct color handling
Santeri Piippo
parents:
2
diff
changeset
|
58 | + '\s+([^ ]+)' \ |
2 | 59 | + r'\s+([^ ]+)' * (vertex_count * 3) \ |
60 | + r'\s*$' | |
61 | match = re.search(pattern, line) | |
62 | if not match: | |
63 | raise BadLdrawLine(str.format('cannot parse type-{} line', type_code)) | |
64 | vertices = [] | |
65 | for vertex_index in range(vertex_count): | |
66 | slice_begin = 1 + vertex_index * 3 | |
67 | slice_end = 1 + (vertex_index + 1) * 3 | |
68 | coordinates = match.groups()[slice_begin:slice_end] | |
69 | assert(len(coordinates) == 3) | |
70 | try: | |
71 | coordinates = [float(x) for x in coordinates] | |
72 | except ValueError: | |
73 | raise BadLdrawLine('bad numeric values') | |
74 | vertices.append(Vertex(*coordinates)) | |
75 | return { | |
3
1dc58f44d556
Can now write dat files, added direct color handling
Santeri Piippo
parents:
2
diff
changeset
|
76 | 'color': Color(match.group(1)), |
2 | 77 | 'vertices': vertices, |
78 | } | |
79 | ||
80 | def parse_ldraw_line(line): | |
81 | parse_result = generic_parse_polygon(line, type_code = 2, vertex_count = 2) | |
82 | return linetypes.LineSegment( | |
83 | color = parse_result['color'], | |
84 | geometry = LineSegment(*parse_result['vertices']), | |
85 | ) | |
86 | ||
87 | def parse_ldraw_triangle(line): | |
88 | parse_result = generic_parse_polygon(line, type_code = 3, vertex_count = 3) | |
89 | return linetypes.Triangle( | |
90 | color = parse_result['color'], | |
91 | geometry = Polygon(parse_result['vertices']), | |
92 | ) | |
93 | ||
94 | def parse_ldraw_quadrilateral(line): | |
95 | parse_result = generic_parse_polygon(line, type_code = 4, vertex_count = 4) | |
96 | return linetypes.Quadrilateral( | |
97 | color = parse_result['color'], | |
98 | geometry = Polygon(parse_result['vertices']), | |
99 | ) | |
100 | ||
101 | def parse_ldraw_contour(line): | |
102 | parse_result = generic_parse_polygon(line, type_code = 5, vertex_count = 4) | |
103 | return linetypes.Contour( | |
104 | color = parse_result['color'], | |
105 | geometry = LineSegment(*parse_result['vertices'][0:2]), | |
106 | control_points = parse_result['vertices'][2:], | |
107 | ) |