ldraw.py

changeset 0
55b4c97d44c5
child 1
5411a25cfca7
equal deleted inserted replaced
-1:000000000000 0:55b4c97d44c5
1 #!/usr/bin/env python3
2 import linetypes
3 import re
4 from geometry import *
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 if line == '0':
14 return linetypes.Comment('')
15 if line.startswith('0 '):
16 return linetypes.Comment(line[2:].strip())
17 if line.startswith('1 '):
18 return parse_ldraw_subfile_reference(line)
19 if line.startswith('2 '):
20 return parse_ldraw_line(line)
21 ...
22
23 def parse_ldraw_subfile_reference(line):
24 pattern = r'^1\s+(\d+)' + r'\s+([^ ]+)' * (3 + 9 + 1) + r'\s*$'
25 match = re.search(pattern, line)
26 if not match:
27 raise BadLdrawLine('unable to parse')
28 groups = list(match.groups())
29 indices = {
30 'color': 0,
31 'anchor': slice(1, 4),
32 'matrix': slice(4, 13),
33 'subfile_path': 13
34 }
35 try:
36 color = int(groups[indices['color']])
37 vertex_values = [float(x) for x in groups[indices['anchor']]]
38 matrix_values = [float(x) for x in groups[indices['matrix']]]
39 except ValueError:
40 raise BadLdrawLine('bad numeric values')
41 return linetypes.SubfileReference(
42 color = color,
43 anchor = Vertex(*vertex_values),
44 matrix = TransformationMatrix(matrix_values),
45 subfile_path = groups[indices['subfile_path']]
46 )
47
48 def generic_parse_polygon(line, *, type_code, vertex_count):
49 pattern = r'^' \
50 + str(type_code) \
51 + '\s+(\d+)' \
52 + r'\s+([^ ]+)' * (vertex_count * 3) \
53 + r'\s*$'
54 match = re.search(pattern, line)
55 if not match:
56 raise BadLdrawLine(str.format('cannot parse type-{} line', type_code))
57 vertices = []
58 for vertex_index in range(vertex_count):
59 slice_begin = 1 + vertex_index * 3
60 slice_end = 1 + (vertex_index + 1) * 3
61 coordinates = match.groups()[slice_begin:slice_end]
62 assert(len(coordinates) == 3)
63 try:
64 coordinates = [float(x) for x in coordinates]
65 except ValueError:
66 raise BadLdrawLine('bad numeric values')
67 vertices.append(Vertex(*coordinates))
68 return {
69 'color': int(match.group(1)),
70 'vertices': vertices,
71 }
72
73 def parse_ldraw_line(line):
74 parse_result = generic_parse_polygon(line, type_code = 2, vertex_count = 2)
75 line_segment = LineSegment(*parse_result['vertices'])
76 return linetypes.LineSegment(
77 color = parse_result['color'],
78 geometry = line_segment)
79
80 def read_ldraw(file, *, libraries):
81 result = list()
82 for line in file:
83 result.append(parse_ldraw_code(line))
84 return result
85
86 if __name__ == '__main__':
87 from sys import argv
88 libraries = [{'path': '/home/teemu/ldraw', 'role': 'official'}]
89 with open(argv[1], 'r') as file:
90 model = read_ldraw(file, libraries = libraries)
91 from pprint import pprint
92 pprint(model)

mercurial