3 __all__ = [
'Dodecahedron']
10 """A dodecahedron with positions of faces and associated vertices.
14 withFacesOnPoles : `bool`
15 If True center a face on each pole, else put a vertex on each pole.
24 g = (1.0 + math.sqrt(5.0)) / 2.0
30 unrotFaceVecList = _computeFullVecList(faceBases)
31 unrotVertexVecList = _computeDodecahedronVertices(unrotFaceVecList)
35 vec0, vec1 = _findClosePair(unrotFaceVecList, 0)
36 rotMat = _computeCoordTransform(vec0, vec1)
39 vec0, vec1 = _findClosePair(unrotVertexVecList, 0)
40 rotMat = _computeCoordTransform(vec0, vec1, vec1NegativeX=
True)
41 self.
vertexVecListvertexVecList = [numpy.dot(rotMat, unrotVertexVec)
for unrotVertexVec
in unrotVertexVecList]
42 unsortedFaceList = [numpy.dot(rotMat, unrotFaceVec)
for unrotFaceVec
in unrotFaceVecList]
43 self.
faceVecListfaceVecList = _sortedVectorList(unsortedFaceList)
46 """Return a list of face centers.
50 results : `list` of `numpy.ndarray`
51 A list of face centers (in index order); each a unit vector.
56 """Return the center of the specified face.
61 Index of the face to look up.
65 results : `np.ndarray`
66 Face center as a unit vector.
71 """Return the vertices for a given face.
80 sortedVertexList : `list` of `numpy.ndarray`
81 A list of vertices, each a unit vector.
84 vertexList, indList = _findCloseList(self.
vertexVecListvertexVecList, faceVec)
87 sortedVertexList = [vertexList[0]]
88 vertexList =
list(vertexList[1:])
89 while len(vertexList) != 0:
90 nearVertexList, nearInd = _findCloseList(vertexList, sortedVertexList[-1])
91 sortedVertexList.append(nearVertexList[0])
92 vertexList.pop(nearInd[0])
93 return sortedVertexList
96 """Return the index of the face containing the cartesian vector.
100 vec : `numpy.ndarray`
101 Cartesian vector (length is ignored).
105 results : `numpy.ndarray`
106 Index of face containing vec.
108 return numpy.argmax(numpy.dot(self.
faceVecListfaceVecList, vec))
115 """Return a 3D rotation matrix for rotation by a specified amount around a
121 Amount of rotation (rad).
123 Axis of rotation; one of 0, 1 or 2 for x, y or z.
125 cosAng = math.cos(angle)
126 sinAng = math.sin(angle)
127 rotMat = numpy.zeros((3, 3), dtype=float)
128 rotMat[axis, axis] = 1
129 rotMat[(axis + 1) % 3, (axis + 1) % 3] = cosAng
130 rotMat[(axis + 2) % 3, (axis + 1) % 3] = sinAng
131 rotMat[(axis + 1) % 3, (axis + 2) % 3] = -sinAng
132 rotMat[(axis + 2) % 3, (axis + 2) % 3] = cosAng
136 def _computeCoordTransform(vec0, vec1, vec1NegativeX=False):
137 """Compute a rotation matrix that puts vec0 along z and vec1 along +x in
142 vec0 : `numpy.ndarray`
144 vec1 : `numpy.ndarray`
146 vec1NegativeX : `bool`
147 If True then vec1 is rotated to face negative x.
150 xAng = math.atan2(vec0[1], vec0[2])
154 vec0RotX = numpy.dot(xRotMat, vec0)
155 yAng = -math.atan2(vec0RotX[0], vec0RotX[2])
157 xyRotMat = numpy.dot(yRotMat, xRotMat)
160 vec1RotXY = numpy.dot(xyRotMat, vec1)
164 zAng = -math.atan2(vec1RotXY[1], xVal)
166 xyzRotMat = numpy.dot(zRotMat, xyRotMat)
170 def _computeDodecahedronVertices(faceVecList):
171 """Given a vector of face positions of a Dodecahedron compute the vertices.
175 for i
in range(len(faceVecList)):
176 closeIndSet = _findCloseIndexSet(faceVecList, i)
177 if len(closeIndSet) != 5:
178 raise RuntimeError(
"Found %s vertices instead of 5 near %s: %s" %
179 (len(closeIndSet), faceVecList[i], closeIndSet))
180 closeIndSetList.append(closeIndSet)
181 for i, iCloseIndSet
in enumerate(closeIndSetList):
182 for j
in iCloseIndSet:
183 jCloseIndSet = closeIndSetList[j]
184 sharedCloseIndSet = iCloseIndSet.intersection(jCloseIndSet)
185 if len(sharedCloseIndSet) != 2:
186 raise RuntimeError(
"Found %s vertices instead of 2 near %s and %s: %s" %
187 (len(sharedCloseIndSet), faceVecList[i], faceVecList[j],
189 for k
in sharedCloseIndSet:
190 key = frozenset((i, j, k))
191 if key
in vertexDict:
193 vertexVec = faceVecList[i] + faceVecList[j] + faceVecList[k]
194 vertexVec /= numpy.sqrt(numpy.sum(vertexVec**2))
195 vertexDict[key] = vertexVec
196 return list(vertexDict.values())
199 def _computeFullVecList(basisSet):
200 """Given a collection of basis vectors, compute all permutations with both
201 signs of all nonzero values.
205 [(0, 1, 2)] -> [(0, 1, 2), (0, -1, 2), (0, 1, -2), (0, -1, -2)]
208 for basisVec
in basisSet:
209 vecLen = math.sqrt(numpy.sum(numpy.array(basisVec)**2))
211 for basisValue
in basisVec:
213 valueList.append((0,))
215 valueList.append((basisValue, -basisValue))
216 fullSet +=
list(numpy.array((x, y, z))/vecLen
217 for z
in valueList[2]
218 for y
in valueList[1]
219 for x
in valueList[0]
224 def _findCloseIndexSet(vecList, ind):
225 """Given a list of cartesian vectors, return a set of indices of those
226 closest to one of them.
228 This is intended for regular grids where distances are quantized.
233 List of cartesian vectors.
235 Index of vector to be nearest.
237 dotProductList = numpy.round(numpy.dot(vecList, vecList[ind]), 2)
238 dotProductList[ind] = -9e99
239 minDist = numpy.max(dotProductList)
240 indList = numpy.arange(len(dotProductList))[dotProductList == minDist]
244 def _findCloseList(vecList, vec):
245 """Given a list of cartesian vectors, return all those closest to a
248 This is intended for regular grids where distances are quantized
253 List of cartesian vectors.
254 vec : `iterable` of `float`
260 List of closest vectors.
262 List if indices of those vectors.
264 dotProductList = numpy.round(numpy.dot(vecList, vec), 2)
265 minDist = numpy.max(dotProductList)
266 indList = numpy.arange(len(dotProductList))[dotProductList == minDist]
267 retList = numpy.take(vecList, indList, 0)
268 return retList, indList
271 def _findClosePair(vecList, ind=0):
272 """Given a list of cartesian vectors and an index, return the vector and
273 one of its closest neighbors.
277 vecList : `list` of `numpy.ndarray`
278 List of cartesian vectors.
280 Index of first vector.
283 otherVecList = vecList[0:ind] + vecList[ind+1:]
284 ind1 = numpy.argmax(numpy.dot(otherVecList, vec))
285 return vec, otherVecList[ind1]
288 def _sortedVectorList(vecList):
289 """Return a list of cartesian vectors sorted by decreasing latitude and
290 increasing longitude.
293 ang = round(math.atan2(vec[1], vec[0]), 2)
296 return (-round(vec[2], 1), ang, vec)
298 decoratedList = [vecToSort(v)
for v
in vecList]
300 return [d[2]
for d
in decoratedList]
303 if __name__ ==
"__main__":
304 numpy.set_printoptions(precision=2, suppress=
True, linewidth=120)
306 print(
"Dodecahedron with vertices on poles")
309 faceVec = vertexDodec.getFaceCtr(i)
310 print(
"Face %2d: %s" % (i, faceVec))
def getVertices(self, ind)
def getFaceCtr(self, ind)
def getWithFacesOnPoles(self)
def getFaceInd(self, vec)
def __init__(self, withFacesOnPoles=False)
daf::base::PropertyList * list
daf::base::PropertySet * set
def computeRotationMatrix(angle, axis)