Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 276 lines (230 sloc) 8.501 kb
f3ede73f » jterrace
2011-03-30 Updated license headers and updated documentation
1 ####################################################################
2 # #
3 # THIS FILE IS PART OF THE pycollada LIBRARY SOURCE CODE. #
4 # USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS #
5 # GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE #
6 # IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. #
7 # #
8 # THE pycollada SOURCE CODE IS (C) COPYRIGHT 2011 #
9 # by Jeff Terrace and contributors #
10 # #
11 ####################################################################
12
b5bc453a » jterrace
2011-04-15 Updated __str__ for most objects and added test cases to call them to…
13 """This module contains utility functions"""
14
616caa5c » jterrace
2011-01-25 Adding util file with vector normalize function
15 import numpy
931497c4 » jterrace
2011-04-18 Added function to test if an Effect is almost equal to another Effect
16 import math
e33e822a » skrat
2011-10-30 py3k compatibility + PEPified code style
17 import sys
18
19 if sys.version_info[0] > 2:
20 import unittest
21 from io import StringIO, BytesIO
d4032b86 » skrat
2011-11-01 abstraction over ElementTree API, works with both lxml and py3k's xml…
22
e33e822a » skrat
2011-10-30 py3k compatibility + PEPified code style
23 bytes = bytes
24 basestring = (str,bytes)
25 xrange = range
26 else:
50097019 » OleLaursen
2012-07-11 Do a feature detect for finding out whether unittest2 is needed; it's…
27 import unittest
28 if not hasattr(unittest.TestCase, "assertIsNone"):
29 # external dependency unittest2 required for Python <= 2.6
30 import unittest2 as unittest
e33e822a » skrat
2011-10-30 py3k compatibility + PEPified code style
31 from StringIO import StringIO
d4032b86 » skrat
2011-11-01 abstraction over ElementTree API, works with both lxml and py3k's xml…
32
e33e822a » skrat
2011-10-30 py3k compatibility + PEPified code style
33 BytesIO = StringIO
34 def bytes(s, encoding='utf-8'):
35 return s
36 basestring = basestring
37 xrange = xrange
38
39 from collada.common import DaeMalformedError, E, tag
616caa5c » jterrace
2011-01-25 Adding util file with vector normalize function
40
d592cb09 » jterrace
2011-02-01 Forgot include
41
931497c4 » jterrace
2011-04-18 Added function to test if an Effect is almost equal to another Effect
42 def falmostEqual(a, b, rtol=1.0000000000000001e-05, atol=1e-08):
43 """Checks if the given floats are almost equal. Uses the algorithm
44 from numpy.allclose.
e33e822a » skrat
2011-10-30 py3k compatibility + PEPified code style
45
931497c4 » jterrace
2011-04-18 Added function to test if an Effect is almost equal to another Effect
46 :param float a:
47 First float to compare
48 :param float b:
49 Second float to compare
50 :param float rtol:
51 The relative tolerance parameter
52 :param float atol:
53 The absolute tolerance parameter
e33e822a » skrat
2011-10-30 py3k compatibility + PEPified code style
54
931497c4 » jterrace
2011-04-18 Added function to test if an Effect is almost equal to another Effect
55 :rtype: bool
e33e822a » skrat
2011-10-30 py3k compatibility + PEPified code style
56
931497c4 » jterrace
2011-04-18 Added function to test if an Effect is almost equal to another Effect
57 """
e33e822a » skrat
2011-10-30 py3k compatibility + PEPified code style
58
931497c4 » jterrace
2011-04-18 Added function to test if an Effect is almost equal to another Effect
59 return math.fabs(a - b) <= (atol + rtol * math.fabs(b))
60
616caa5c » jterrace
2011-01-25 Adding util file with vector normalize function
61 def toUnitVec(vec):
d04bb746 » jterrace
2011-04-13 Finished with current documentation
62 """Converts the given vector to a unit vector
e33e822a » skrat
2011-10-30 py3k compatibility + PEPified code style
63
d04bb746 » jterrace
2011-04-13 Finished with current documentation
64 :param numpy.array vec:
65 The vector to transform to unit length
e33e822a » skrat
2011-10-30 py3k compatibility + PEPified code style
66
d04bb746 » jterrace
2011-04-13 Finished with current documentation
67 :rtype: numpy.array
e33e822a » skrat
2011-10-30 py3k compatibility + PEPified code style
68
d04bb746 » jterrace
2011-04-13 Finished with current documentation
69 """
616caa5c » jterrace
2011-01-25 Adding util file with vector normalize function
70 return vec / numpy.sqrt(numpy.vdot(vec, vec))
112e868e » jterrace
2011-01-29 Added support for <polylist>
71
72 def checkSource( source, components, maxindex):
73 """Check if a source objects complies with the needed `components` and has the needed length
74
d04bb746 » jterrace
2011-04-13 Finished with current documentation
75 :param collada.source.Source source:
76 A source instance to check
77 :param tuple components:
78 A tuple describing the needed channels, e.g. ``('X','Y','Z')``
79 :param int maxindex:
80 The maximum index that refers to this source
112e868e » jterrace
2011-01-29 Added support for <polylist>
81
82 """
83 if len(source.data) <= maxindex:
4cd8a171 » jterrace
2011-03-08 Better error message
84 raise DaeMalformedError(
85 "Indexes (maxindex=%d) for source '%s' (len=%d) go beyond the limits of the source"
86 % (maxindex, source.id, len(source.data)) )
36578257 » jterrace
2011-03-15 Adding hack to work with some failed file output
87
88 #some files will write sources with no named parameters
89 #by spec, these params should just be skipped, but we need to
90 #adapt to the failed output of others...
5f586dab » jterrace
2011-08-13 Made source param names even more lenient because of the garbage that…
91 if len(source.components) == len(components):
36578257 » jterrace
2011-03-15 Adding hack to work with some failed file output
92 source.components = components
e33e822a » skrat
2011-10-30 py3k compatibility + PEPified code style
93
112e868e » jterrace
2011-01-29 Added support for <polylist>
94 if source.components != components:
95 raise DaeMalformedError('Wrong format in source %s'%source.id)
96 return source
ad8c5adb » jterrace
2011-03-11 Added util function for normalizing a n,3 vector
97
98 def normalize_v3(arr):
d04bb746 » jterrace
2011-04-13 Finished with current documentation
99 """Normalize a numpy array of 3 component vectors with shape (N,3)
e33e822a » skrat
2011-10-30 py3k compatibility + PEPified code style
100
d04bb746 » jterrace
2011-04-13 Finished with current documentation
101 :param numpy.array arr:
102 The numpy array to normalize
e33e822a » skrat
2011-10-30 py3k compatibility + PEPified code style
103
d04bb746 » jterrace
2011-04-13 Finished with current documentation
104 :rtype: numpy.array
e33e822a » skrat
2011-10-30 py3k compatibility + PEPified code style
105
d04bb746 » jterrace
2011-04-13 Finished with current documentation
106 """
ad8c5adb » jterrace
2011-03-11 Added util function for normalizing a n,3 vector
107 lens = numpy.sqrt( arr[:,0]**2 + arr[:,1]**2 + arr[:,2]**2 )
a3e9d9c7 » jterrace
2011-04-21 Prevent NaN from being the result of a normalize_v3 call
108 lens[numpy.equal(lens, 0)] = 1
ad8c5adb » jterrace
2011-03-11 Added util function for normalizing a n,3 vector
109 arr[:,0] /= lens
110 arr[:,1] /= lens
111 arr[:,2] /= lens
65c1e30f » jterrace
2011-05-24 Added a method to generate texture tangents and binormals
112 return arr
113
114 def dot_v3(arr1, arr2):
115 """Calculates the dot product for each vector in two arrays
e33e822a » skrat
2011-10-30 py3k compatibility + PEPified code style
116
65c1e30f » jterrace
2011-05-24 Added a method to generate texture tangents and binormals
117 :param numpy.array arr1:
118 The first array, shape Nx3
119 :param numpy.array arr2:
120 The second array, shape Nx3
e33e822a » skrat
2011-10-30 py3k compatibility + PEPified code style
121
65c1e30f » jterrace
2011-05-24 Added a method to generate texture tangents and binormals
122 :rtype: numpy.array
e33e822a » skrat
2011-10-30 py3k compatibility + PEPified code style
123
65c1e30f » jterrace
2011-05-24 Added a method to generate texture tangents and binormals
124 """
125 return arr1[:,0]*arr2[:,0] + arr1[:,1]*arr2[:,1] + arr2[:,2]*arr1[:,2]
f544aee1 » jterrace
2011-03-30 Changed main collada object from using xById attributes to using an I…
126
127 class IndexedList(list):
128 """
129 Class that combines a list and a dict into a single class
130 - Written by Hugh Bothwell (http://stackoverflow.com/users/33258/hugh-bothwell)
131 - Original source available at:
132 http://stackoverflow.com/questions/5332841/python-list-dict-property-best-practice/5334686#5334686
133 - Modifications by Jeff Terrace
134 Given an object, obj, that has a property x, this allows you to create an IndexedList like so:
135 L = IndexedList([], ('x'))
136 o = obj()
137 o.x = 'test'
138 L.append(o)
139 L[0] # = o
140 L['test'] # = o
141 """
142 def __init__(self, items, attrs):
143 super(IndexedList, self).__init__(items)
144 # do indexing
145 self._attrs = tuple(attrs)
146 self._index = {}
147 _add = self._addindex
148 for obj in self:
149 _add(obj)
150
151 def _addindex(self, obj):
152 _idx = self._index
153 for attr in self._attrs:
154 _idx[getattr(obj, attr)] = obj
155
156 def _delindex(self, obj):
157 _idx = self._index
158 for attr in self._attrs:
159 try:
160 del _idx[getattr(obj, attr)]
161 except KeyError:
162 pass
163
164 def __delitem__(self, ind):
165 try:
166 obj = list.__getitem__(self, ind)
167 except (IndexError, TypeError):
168 obj = self._index[ind]
169 ind = list.index(self, obj)
170 self._delindex(obj)
171 return list.__delitem__(self, ind)
172
173 def __delslice__(self, i, j):
fe9f782e » jterrace
2011-06-19 Fixed bugs in IndexedList from Issue #13
174 return list.__delslice__(self, i, j)
f544aee1 » jterrace
2011-03-30 Changed main collada object from using xById attributes to using an I…
175
176 def __getitem__(self, ind):
177 try:
178 return self._index[ind]
179 except KeyError:
180 if isinstance(ind, str):
181 raise
182 return list.__getitem__(self, ind)
183
184 def get(self, key, default=None):
185 try:
186 return self._index[key]
187 except KeyError:
188 return default
189
190 def __contains__(self, item):
191 if item in self._index:
192 return True
193 return list.__contains__(self, item)
194
fe9f782e » jterrace
2011-06-19 Fixed bugs in IndexedList from Issue #13
195 def __getslice__(self, i, j):
196 return IndexedList(list.__getslice__(self, i, j), self._attrs)
f544aee1 » jterrace
2011-03-30 Changed main collada object from using xById attributes to using an I…
197
198 def __setitem__(self, ind, new_obj):
199 try:
200 obj = list.__getitem__(self, ind)
201 except (IndexError, TypeError):
202 obj = self._index[ind]
203 ind = list.index(self, obj)
204 self._delindex(obj)
205 self._addindex(new_obj)
206 return list.__setitem__(ind, new_obj)
207
208 def __setslice__(self, i, j, newItems):
209 _get = self.__getitem__
210 _add = self._addindex
211 _del = self._delindex
212 newItems = list(newItems)
213 # remove indexing of items to remove
214 for ind in xrange(i, j):
215 _del(_get(ind))
216 # add new indexing
217 if isinstance(newList, IndexedList):
218 self._index.update(newList._index)
219 else:
220 for obj in newList:
221 _add(obj)
222 # replace items
223 return list.__setslice__(self, i, j, newList)
224
225 def append(self, obj):
226 self._addindex(obj)
227 return list.append(self, obj)
228
229 def extend(self, newList):
230 newList = list(newList)
231 if isinstance(newList, IndexedList):
232 self._index.update(newList._index)
233 else:
234 _add = self._addindex
235 for obj in newList:
236 _add(obj)
237 return list.extend(self, newList)
238
239 def insert(self, ind, new_obj):
240 # ensure that ind is a numeric index
241 try:
242 obj = list.__getitem__(self, ind)
243 except (IndexError, TypeError):
244 obj = self._index[ind]
245 ind = list.index(self, obj)
246 self._addindex(new_obj)
247 return list.insert(self, ind, new_obj)
248
249 def pop(self, ind= -1):
250 # ensure that ind is a numeric index
251 try:
252 obj = list.__getitem__(self, ind)
253 except (IndexError, TypeError):
254 obj = self._index[ind]
255 ind = list.index(self, obj)
256 self._delindex(obj)
257 return list.pop(self, ind)
258
259 def remove(self, ind_or_obj):
260 try:
261 obj = self._index[ind_or_obj]
262 ind = list.index(self, obj)
263 except KeyError:
264 ind = list.index(self, ind_or_obj)
265 obj = list.__getitem__(self, ind)
266 self._delindex(obj)
267 return list.remove(self, ind)
268
a70722f9 » jterrace
2011-08-30 Refactored asset information into a separate module, added test cases…
269 def _correctValInNode(outernode, tagname, value):
270 innernode = outernode.find( tag(tagname) )
271 if value is None and innernode is not None:
272 outernode.remove(innernode)
273 elif innernode is not None:
274 innernode.text = str(value)
275 elif value is not None:
e33e822a » skrat
2011-10-30 py3k compatibility + PEPified code style
276 outernode.append(E(tagname, str(value)))
d4032b86 » skrat
2011-11-01 abstraction over ElementTree API, works with both lxml and py3k's xml…
277
Something went wrong with that request. Please try again.