2 from __future__
import print_function
3 from builtins
import range
4 from builtins
import object
12 Contains positions of faces and associated vertices 16 """Construct a Dodecahedron 18 @param[in] withFacesOnPoles: if True center a face on each pole, else put a vertex on each pole 26 g = (1.0 + math.sqrt(5.0)) / 2.0
32 unrotFaceVecList = _computeFullVecList(faceBases)
33 unrotVertexVecList = _computeDodecahedronVertices(unrotFaceVecList)
37 vec0, vec1 = _findClosePair(unrotFaceVecList, 0)
38 rotMat = _computeCoordTransform(vec0, vec1)
41 vec0, vec1 = _findClosePair(unrotVertexVecList, 0)
42 rotMat = _computeCoordTransform(vec0, vec1, vec1NegativeX=
True)
43 self.
vertexVecList = [numpy.dot(rotMat, unrotVertexVec)
for unrotVertexVec
in unrotVertexVecList]
44 unsortedFaceList = [numpy.dot(rotMat, unrotFaceVec)
for unrotFaceVec
in unrotFaceVecList]
48 """Return a list of face centers 50 @return a list of face centers (in index order); each a unit vector (numpy array) 55 """Return the center of the specified face 57 @param[in] ind: face index 58 @return face center as a unit vector (numpy array) 63 """Return the vertices for a given face 65 @param[in] ind: face index 66 @return a list of vertices, each a unit vector (numpy array) 69 vertexList, indList = _findCloseList(self.
vertexVecList, faceVec)
72 sortedVertexList = [vertexList[0]]
73 vertexList = list(vertexList[1:])
74 while len(vertexList) != 0:
75 nearVertexList, nearInd = _findCloseList(vertexList, sortedVertexList[-1])
76 sortedVertexList.append(nearVertexList[0])
77 vertexList.pop(nearInd[0])
78 return sortedVertexList
81 """Return the index of the face containing the cartesian vector 83 @param[in] vec: cartesian vector (length is ignored) 84 @return index of face containing vec 86 return numpy.argmax(numpy.dot(self.
faceVecList, vec))
89 """Get withFacesOnPoles parameter 95 """Return a 3D rotation matrix for rotation by a specified amount around a specified axis 98 - angle: amount of rotation (rad) 99 - axis: axis of rotation; one of 0, 1 or 2 for x, y or z 101 cosAng = math.cos(angle)
102 sinAng = math.sin(angle)
103 rotMat = numpy.zeros((3, 3), dtype=float)
104 rotMat[axis, axis] = 1
105 rotMat[(axis + 1) % 3, (axis + 1) % 3] = cosAng
106 rotMat[(axis + 2) % 3, (axis + 1) % 3] = sinAng
107 rotMat[(axis + 1) % 3, (axis + 2) % 3] = -sinAng
108 rotMat[(axis + 2) % 3, (axis + 2) % 3] = cosAng
112 def _computeCoordTransform(vec0, vec1, vec1NegativeX=False):
113 """Compute a rotation matrix that puts vec0 along z and vec1 along +x in the xz plane 118 - vec1NegativeX: if True then vec1 is rotated to face negative x 121 xAng = math.atan2(vec0[1], vec0[2])
125 vec0RotX = numpy.dot(xRotMat, vec0)
126 yAng = -math.atan2(vec0RotX[0], vec0RotX[2])
128 xyRotMat = numpy.dot(yRotMat, xRotMat)
131 vec1RotXY = numpy.dot(xyRotMat, vec1)
135 zAng = -math.atan2(vec1RotXY[1], xVal)
137 xyzRotMat = numpy.dot(zRotMat, xyRotMat)
141 def _computeDodecahedronVertices(faceVecList):
142 """Given a vector of face positions of a Dodecahedron compute the vertices 146 for i
in range(len(faceVecList)):
147 closeIndSet = _findCloseIndexSet(faceVecList, i)
148 if len(closeIndSet) != 5:
149 raise RuntimeError(
"Found %s vertices instead of 5 near %s: %s" %
150 (len(closeIndSet), faceVecList[i], closeIndSet))
151 closeIndSetList.append(closeIndSet)
152 for i, iCloseIndSet
in enumerate(closeIndSetList):
153 for j
in iCloseIndSet:
154 jCloseIndSet = closeIndSetList[j]
155 sharedCloseIndSet = iCloseIndSet.intersection(jCloseIndSet)
156 if len(sharedCloseIndSet) != 2:
157 raise RuntimeError(
"Found %s vertices instead of 2 near %s and %s: %s" %
158 (len(sharedCloseIndSet), faceVecList[i], faceVecList[j],
160 for k
in sharedCloseIndSet:
161 key = frozenset((i, j, k))
162 if key
in vertexDict:
164 vertexVec = faceVecList[i] + faceVecList[j] + faceVecList[k]
165 vertexVec /= numpy.sqrt(numpy.sum(vertexVec**2))
166 vertexDict[key] = vertexVec
167 return list(vertexDict.values())
170 def _computeFullVecList(basisSet):
171 """Given a collection of basis vectors, compute all permutations with both signs of all nonzero values 173 For example: [(0, 1, 2)] -> [(0, 1, 2), (0, -1, 2), (0, 1, -2), (0, -1, -2)] 176 for basisVec
in basisSet:
177 vecLen = math.sqrt(numpy.sum(numpy.array(basisVec)**2))
179 for basisValue
in basisVec:
181 valueList.append((0,))
183 valueList.append((basisValue, -basisValue))
184 fullSet += list(numpy.array((x, y, z))/vecLen
185 for z
in valueList[2]
186 for y
in valueList[1]
187 for x
in valueList[0]
192 def _findCloseIndexSet(vecList, ind):
193 """Given a list of cartesian vectors, return a set of indices of those closest to one of them 195 This is intended for regular grids where distances are quantized 198 - vecList: list of cartesian vectors 199 - ind: index of vector to be nearest 201 dotProductList = numpy.round(numpy.dot(vecList, vecList[ind]), 2)
202 dotProductList[ind] = -9e99
203 minDist = numpy.max(dotProductList)
204 indList = numpy.arange(len(dotProductList))[dotProductList == minDist]
208 def _findCloseList(vecList, vec):
209 """Given a list of cartesian vectors, return all those closest to a specified position 211 This is intended for regular grids where distances are quantized 214 - vecList: list of cartesian vectors 215 - vec: vector to be near 218 - list of closest vectors 219 - list if indices of those vectors 221 dotProductList = numpy.round(numpy.dot(vecList, vec), 2)
222 minDist = numpy.max(dotProductList)
223 indList = numpy.arange(len(dotProductList))[dotProductList == minDist]
224 retList = numpy.take(vecList, indList, 0)
225 return retList, indList
228 def _findClosePair(vecList, ind=0):
229 """Given a list of cartesian vectors and an index, return the vector and one of its closest neighbors 232 - vecList: list of cartesian vectors 233 - ind: index of first vector 236 otherVecList = vecList[0:ind] + vecList[ind+1:]
237 ind1 = numpy.argmax(numpy.dot(otherVecList, vec))
238 return vec, otherVecList[ind1]
241 def _sortedVectorList(vecList):
242 """Return a list of cartesian vectors sorted by decreasing latitude and increasing longitude 245 ang = round(math.atan2(vec[1], vec[0]), 2)
248 return (-round(vec[2], 1), ang, vec)
250 decoratedList = [vecToSort(v)
for v
in vecList]
252 return [d[2]
for d
in decoratedList]
255 if __name__ ==
"__main__":
256 numpy.set_printoptions(precision=2, suppress=
True, linewidth=120)
258 print(
"Dodecahedron with vertices on poles")
261 faceVec = vertexDodec.getFaceCtr(i)
262 print(
"Face %2d: %s" % (i, faceVec))
def computeRotationMatrix(angle, axis)
def getFaceInd(self, vec)
def getFaceCtr(self, ind)
def getVertices(self, ind)
def __init__(self, withFacesOnPoles=False)
def getWithFacesOnPoles(self)