chiark / gitweb /
Upload design files with mesh files when uploading to YouMagine.
[cura.git] / Cura / util / meshLoaders / amf.py
1 from __future__ import absolute_import
2 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
3
4 import cStringIO as StringIO
5 import zipfile
6 import os
7 try:
8         from xml.etree import cElementTree as ElementTree
9 except:
10         from xml.etree import ElementTree
11
12 from Cura.util import mesh
13 from Cura.util import profile
14
15 def loadScene(filename):
16         try:
17                 zfile = zipfile.ZipFile(filename)
18                 xml = zfile.read(zfile.namelist()[0])
19                 zfile.close()
20         except zipfile.BadZipfile:
21                 f = open(filename, "r")
22                 xml = f.read()
23                 f.close()
24         amf = ElementTree.fromstring(xml)
25         if 'unit' in amf.attrib:
26                 unit = amf.attrib['unit'].lower()
27         else:
28                 unit = 'millimeter'
29         if unit == 'millimeter':
30                 scale = 1.0
31         elif unit == 'meter':
32                 scale = 1000.0
33         elif unit == 'inch':
34                 scale = 25.4
35         elif unit == 'feet':
36                 scale = 304.8
37         elif unit == 'micron':
38                 scale = 0.001
39         else:
40                 print "Unknown unit in amf: %s" % (unit)
41                 scale = 1.0
42
43         ret = []
44         for amfObj in amf.iter('object'):
45                 obj = mesh.printableObject(filename)
46                 for amfMesh in amfObj.iter('mesh'):
47                         vertexList = []
48                         for vertices in amfMesh.iter('vertices'):
49                                 for vertex in vertices.iter('vertex'):
50                                         for coordinates in vertex.iter('coordinates'):
51                                                 v = [0.0,0.0,0.0]
52                                                 for t in coordinates:
53                                                         if t.tag == 'x':
54                                                                 v[0] = float(t.text)
55                                                         elif t.tag == 'y':
56                                                                 v[1] = float(t.text)
57                                                         elif t.tag == 'z':
58                                                                 v[2] = float(t.text)
59                                                 vertexList.append(v)
60
61                         for volume in amfMesh.iter('volume'):
62                                 m = obj._addMesh()
63                                 count = 0
64                                 for triangle in volume.iter('triangle'):
65                                         count += 1
66                                 m._prepareFaceCount(count)
67
68                                 for triangle in volume.iter('triangle'):
69                                         for t in triangle:
70                                                 if t.tag == 'v1':
71                                                         v1 = vertexList[int(t.text)]
72                                                 elif t.tag == 'v2':
73                                                         v2 = vertexList[int(t.text)]
74                                                 elif t.tag == 'v3':
75                                                         v3 = vertexList[int(t.text)]
76                                                         m._addFace(v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2])
77                 obj._postProcessAfterLoad()
78                 ret.append(obj)
79
80         return ret
81
82 def saveScene(filename, objects):
83         f = open(filename, 'wb')
84         saveSceneStream(f, filename, objects)
85         f.close()
86
87 def saveSceneStream(s, filename, objects):
88         xml = StringIO.StringIO()
89         xml.write('<?xml version="1.0" encoding="utf-8"?>\n')
90         xml.write('<amf unit="millimeter" version="1.1">\n')
91         n = 0
92         for obj in objects:
93                 n += 1
94                 xml.write('  <object id="%d">\n' % (n))
95                 xml.write('    <mesh>\n')
96                 xml.write('      <vertices>\n')
97                 vertexList, meshList = obj.getVertexIndexList()
98                 for v in vertexList:
99                         xml.write('        <vertex>\n')
100                         xml.write('          <coordinates>\n')
101                         xml.write('            <x>%f</x>\n' % (v[0]))
102                         xml.write('            <y>%f</y>\n' % (v[1]))
103                         xml.write('            <z>%f</z>\n' % (v[2]))
104                         xml.write('          </coordinates>\n')
105                         xml.write('        </vertex>\n')
106                 xml.write('      </vertices>\n')
107
108                 matID = 1
109                 for m in meshList:
110                         xml.write('      <volume materialid="%i">\n' % (matID))
111                         for idx in xrange(0, len(m), 3):
112                                 xml.write('        <triangle>\n')
113                                 xml.write('          <v1>%i</v1>\n' % (m[idx]))
114                                 xml.write('          <v2>%i</v2>\n' % (m[idx+1]))
115                                 xml.write('          <v3>%i</v3>\n' % (m[idx+2]))
116                                 xml.write('        </triangle>\n')
117                         xml.write('      </volume>\n')
118                         matID += 1
119                 xml.write('    </mesh>\n')
120                 xml.write('  </object>\n')
121
122         n += 1
123         xml.write('  <constellation id="%d">\n' % (n))
124         for idx in xrange(1, n):
125                 xml.write('    <instance objectid="%d">\n' % (idx))
126                 xml.write('      <deltax>0</deltax>\n')
127                 xml.write('      <deltay>0</deltay>\n')
128                 xml.write('      <deltaz>0</deltaz>\n')
129                 xml.write('      <rx>0</rx>\n')
130                 xml.write('      <ry>0</ry>\n')
131                 xml.write('      <rz>0</rz>\n')
132                 xml.write('    </instance>\n')
133         xml.write('  </constellation>\n')
134         for n in xrange(0, 4):
135                 xml.write('  <material id="%i">\n' % (n + 1))
136                 xml.write('    <metadata type="Name">Material %i</metadata>\n' % (n + 1))
137                 if n == 0:
138                         col = profile.getPreferenceColour('model_colour')
139                 else:
140                         col = profile.getPreferenceColour('model_colour%i' % (n + 1))
141                 xml.write('    <color><r>%.2f</r><g>%.2f</g><b>%.2f</b></color>\n' % (col[0], col[1], col[2]))
142                 xml.write('  </material>\n')
143         xml.write('</amf>\n')
144
145         zfile = zipfile.ZipFile(s, "w", zipfile.ZIP_DEFLATED)
146         zfile.writestr(os.path.basename(filename), xml.getvalue())
147         zfile.close()
148         xml.close()