Can now write dat files, added direct color handling

Mon, 11 Dec 2017 00:46:35 +0200

author
Santeri Piippo
date
Mon, 11 Dec 2017 00:46:35 +0200
changeset 3
1dc58f44d556
parent 2
50d3086070df
child 4
8eb83f200486

Can now write dat files, added direct color handling

geometry.py file | annotate | diff | comparison | revisions
ldraw.py file | annotate | diff | comparison | revisions
ldverify.py file | annotate | diff | comparison | revisions
linetypes.py file | annotate | diff | comparison | revisions
parse.py file | annotate | diff | comparison | revisions
--- a/geometry.py	Sun Dec 10 15:46:47 2017 +0200
+++ b/geometry.py	Mon Dec 11 00:46:35 2017 +0200
@@ -11,12 +11,18 @@
             (self.y - other.y) ** 2 +
             (self.z - other.z) ** 2
         )
+    @property
+    def coordinates(self):
+        return self.x, self.y, self.z
 
 class LineSegment:
     def __init__(self, v1, v2):
         self.v1, self.v2 = v1, v2
     def __repr__(self):
         return str.format('LineSegment({!r}, {!r})', self.v1, self.v2)
+    @property
+    def vertices(self):
+        return self.v1, self.v2
 
 class Polygon:
     def __init__(self, vertices):
--- a/ldraw.py	Sun Dec 10 15:46:47 2017 +0200
+++ b/ldraw.py	Mon Dec 11 00:46:35 2017 +0200
@@ -1,16 +1,11 @@
-#!/usr/bin/env python3
-from parse import parse_ldraw_code
-
-def read_ldraw(file, *, libraries):
-    result = list()
-    for line in file:
-        result.append(parse_ldraw_code(line))
-    return result
-
-if __name__ == '__main__':
-    from sys import argv
-    libraries = [{'path': '/home/teemu/ldraw', 'role': 'official'}]
-    with open(argv[1], 'r') as file:
-        model = read_ldraw(file, libraries = libraries)
-        from pprint import pprint
-        pprint(model)
+class Color:
+    def __init__(self, index):
+        self.index = int(index, 0)
+    def __str__(self):
+        if self.is_direct_color():
+            # write direct colors with hex codes
+            return '0x%07X' % self.index
+        else:
+            return str(self.index)
+    def is_direct_color(self):
+        return self.index >= 0x2000000
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ldverify.py	Mon Dec 11 00:46:35 2017 +0200
@@ -0,0 +1,17 @@
+#!/usr/bin/env python3
+from parse import parse_ldraw_code
+
+def read_ldraw(file, *, libraries):
+    result = list()
+    for line in file:
+        result.append(parse_ldraw_code(line))
+    return result
+
+if __name__ == '__main__':
+    from sys import argv
+    libraries = [{'path': '/home/teemu/ldraw', 'role': 'official'}]
+    with open(argv[1], 'r') as file:
+        model = read_ldraw(file, libraries = libraries)
+        for entry in model:
+            #print(repr(entry))
+            print(entry.textual_representation().strip(), end = '\r\n')
--- a/linetypes.py	Sun Dec 10 15:46:47 2017 +0200
+++ b/linetypes.py	Mon Dec 11 00:46:35 2017 +0200
@@ -1,11 +1,23 @@
+def ldraw_str(value):
+    ' Like str() except removes unneeded ".0"-suffixes '
+    rep = str(value)
+    if isinstance(value, float):
+        if rep.endswith('.0'):
+            rep = rep[:-2]
+        if rep == '-0':
+            rep = '0'
+    return rep
+
 class EmptyLine:
     def __repr__(self):
         return 'linetypes.EmptyLine()'
+    def textual_representation(self):
+        return ''
 
 class Comment:
     def __init__(self, text, style = 'old'):
         if style == 'old' and text.startswith('//'):
-            self.text = text[3:].strip()
+            self.text = text[2:].strip()
             self.style = 'new'
         else:
             self.text = text
@@ -15,6 +27,11 @@
             text = self.text,
             style = self.style,
         )
+    def textual_representation(self):
+        if self.style == 'old':
+            return '0 ' + self.text
+        else:
+            return '0 // ' + self.text
 
 class SubfileReference:
     def __init__(self, *, color, subfile_path, anchor, matrix):
@@ -26,8 +43,17 @@
             'subfile_path = {subfile_path!r}, ' \
             'anchor = {anchor!r}, ' \
             'matrix = {matrix!r})', **self.__dict__)
+    def textual_representation(self):
+        args = [
+            1,
+            self.color,
+            *self.anchor.coordinates,
+            *self.matrix.values,
+            self.subfile_path,
+        ]
+        return ' '.join(ldraw_str(arg) for arg in args)
 
-class LineSegment:
+class BasePolygon:
     def __init__(self, *, color, geometry):
         self.color, self.geometry = color, geometry
     def __repr__(self):
@@ -38,12 +64,23 @@
             color = self.color,
             geometry = self.geometry,
         )
+    def base_textual_representation(self):
+        args = [self.color]
+        for vertex in self.geometry.vertices:
+            args += vertex.coordinates
+        return ' '.join(ldraw_str(arg) for arg in args)
 
-class Triangle(LineSegment):
-    pass
+class LineSegment(BasePolygon):
+    def textual_representation(self):
+        return '2 ' + self.base_textual_representation()
 
-class Quadrilateral(LineSegment):
-    pass
+class Triangle(BasePolygon):
+    def textual_representation(self):
+        return '3 ' + self.base_textual_representation()
+
+class Quadrilateral(BasePolygon):
+    def textual_representation(self):
+        return '4 ' + self.base_textual_representation()
 
 class Contour(LineSegment):
     def __init__(self, *, color, geometry, control_points):
@@ -55,3 +92,10 @@
             'color = {color!r}, ' \
             'geometry = {geometry!r}, ' \
             'control_points = {control_points!r})', **self.__dict__)
+    def textual_representation(self):
+        result = '5 ' + self.base_textual_representation()
+        for control_point in self.control_points:
+            strings = (ldraw_str(value) for value in control_point.coordinates)
+            result += ' '
+            result += ' '.join(strings)
+        return result
--- a/parse.py	Sun Dec 10 15:46:47 2017 +0200
+++ b/parse.py	Mon Dec 11 00:46:35 2017 +0200
@@ -1,6 +1,7 @@
 import linetypes
 import re
 from geometry import *
+from ldraw import Color
 
 class BadLdrawLine(Exception):
     pass
@@ -27,19 +28,19 @@
         raise BadLdrawLine('unknown line type')
 
 def parse_ldraw_subfile_reference(line):
-    pattern = r'^1\s+(\d+)' + r'\s+([^ ]+)' * (3 + 9 + 1) + r'\s*$'
+    pattern = r'^1\s+([^ ]+)' + r'\s+([^ ]+)' * (3 + 9 + 1) + r'\s*$'
     match = re.search(pattern, line)
     if not match:
         raise BadLdrawLine('unable to parse')
     groups = list(match.groups())
     indices = {
-        'color': 0,
+        'color_index': 0,
         'anchor': slice(1, 4),
         'matrix': slice(4, 13),
         'subfile_path': 13
     }
     try:
-        color = int(groups[indices['color']])
+        color = Color(groups[indices['color_index']])
         vertex_values = [float(x) for x in groups[indices['anchor']]]
         matrix_values = [float(x) for x in groups[indices['matrix']]]
     except ValueError:
@@ -54,7 +55,7 @@
 def generic_parse_polygon(line, *, type_code, vertex_count):
     pattern = r'^' \
         + str(type_code) \
-        + '\s+(\d+)' \
+        + '\s+([^ ]+)' \
         + r'\s+([^ ]+)' * (vertex_count * 3) \
         + r'\s*$'
     match = re.search(pattern, line)
@@ -72,7 +73,7 @@
             raise BadLdrawLine('bad numeric values')
         vertices.append(Vertex(*coordinates))
     return {
-        'color': int(match.group(1)),
+        'color': Color(match.group(1)),
         'vertices': vertices,
     }
 

mercurial