$search
00001 from Triangle import Triangle 00002 #from Numeric import * 00003 from numpy import * 00004 from numpy.linalg import * 00005 import vtk 00006 import time 00007 import os.path 00008 from Cell import Cell 00009 00010 class TesselatedSphere: 00011 def __init__(self, levels, inter): 00012 self.triangles = list() 00013 self.icosahedron = list() 00014 self.polygons = list() 00015 self.max_levels = levels 00016 self.resolution = 0 00017 self.interpolateNormals = inter 00018 self.useLut = False 00019 self.convexHullPoints = dict() 00020 self.useNormalsOnSurface = True 00021 00022 def resetPolygons(self): 00023 for cell in self.polygons[self.max_levels]: 00024 cell.reset() 00025 00026 def construct(self): 00027 00028 #if file with lookup table exist, read it from file together with the 00029 #corresponding cells 00030 00031 #create icosahedron vertices 00032 #define regular icosahedron vertex coordinates 00033 #http://en.wikipedia.org/wiki/Icosahedron 00034 00035 tau = 0.8506508084 # t=(1+sqrt(5))/2, tau=t/sqrt(1+t^2) 00036 one = 0.5257311121 # one=1/sqrt(1+t^2) , unit sphere 00037 00038 ZA = [tau, one, 0] 00039 ZB = [-tau, one, 0] 00040 ZC = [-tau, -one, 0] 00041 ZD = [tau, -one, 0] 00042 YA = [one, 0 , tau] 00043 YB = [one, 0 , -tau] 00044 YC = [-one, 0 , -tau] 00045 YD = [-one, 0 , tau] 00046 XA = [0 , tau, one] 00047 XB = [0 , -tau, one] 00048 XC = [0 , -tau, -one] 00049 XD = [0 , tau, -one] 00050 00051 self.icosahedron.append(Triangle([YA, XA, YD])) 00052 self.icosahedron.append(Triangle([YA, YD, XB])) 00053 self.icosahedron.append(Triangle([YB, YC, XD])) 00054 self.icosahedron.append(Triangle([YB, XC, YC])) 00055 self.icosahedron.append(Triangle([ZA, YA, ZD])) 00056 self.icosahedron.append(Triangle([ZA, ZD, YB])) 00057 self.icosahedron.append(Triangle([ZC, YD, ZB])) 00058 self.icosahedron.append(Triangle([ZC, ZB, YC])) 00059 self.icosahedron.append(Triangle([XA, ZA, XD])) 00060 self.icosahedron.append(Triangle([XA, XD, ZB])) 00061 self.icosahedron.append(Triangle([XB, XC, ZD])) 00062 self.icosahedron.append(Triangle([XB, ZC, XC])) 00063 self.icosahedron.append(Triangle([XA, YA, ZA])) 00064 self.icosahedron.append(Triangle([XD, ZA, YB])) 00065 self.icosahedron.append(Triangle([YA, XB, ZD])) 00066 self.icosahedron.append(Triangle([YB, ZD, XC])) 00067 self.icosahedron.append(Triangle([YD, XA, ZB])) 00068 self.icosahedron.append(Triangle([YC, ZB, XD])) 00069 self.icosahedron.append(Triangle([YD, ZC, XB])) 00070 self.icosahedron.append(Triangle([YC, XC, ZC])) 00071 00072 self.polygons.append(self.icosahedron) 00073 00074 #with the starting triangles of the icoseahedron, start to divide each triangle in four triangles 00075 #by a level of 2, each starting triangle will be splitted in four parts and these four parts again in four parts 00076 #more by level 2, therefore, giving 4x4x20=320 faces => (4^n)*20 00077 #level 3 => 1280, level 4 => 5120, level 5 => 20480 00078 00079 for l in xrange(self.max_levels): 00080 #print l 00081 #print len(self.polygons[l]) 00082 self.polygons.append(list()) 00083 for tri in self.polygons[l]: 00084 #print tri 00085 #subdivide triangle into 4 triangles 00086 subdivision = tri.subdivide() 00087 self.polygons[l+1].append(subdivision[0]) 00088 self.polygons[l+1].append(subdivision[1]) 00089 self.polygons[l+1].append(subdivision[2]) 00090 self.polygons[l+1].append(subdivision[3]) 00091 #print subdivision[0].normal, " ", subdivision[1].normal, " ", subdivision[2].normal , " ", subdivision[3].normal 00092 00093 print "number of cells in tesselated sphere:", len(self.polygons[self.max_levels]) 00094 00095 self.resolution = 2.1993 / sqrt(len(self.polygons[self.max_levels])) * 180 / pi * sqrt(2) 00096 return 00097 00098 def findCell(self, normal): 00099 #find best cell in icosahedron aproximation 00100 00101 maxDot = -1000 00102 cell = 0 00103 00104 for tri in self.icosahedron: 00105 dotP = dot(tri.normal, normal) 00106 if dotP > maxDot: 00107 maxDot = dotP 00108 cell = tri 00109 00110 #RECURSIVE METHOD 00111 #refinedCell = cell.findCell(normal) 00112 #return refinedCell 00113 00114 #ITERATIVE METHOD (its faster, almost 25% faster) 00115 #still very sloowww!!!! use loookup table 00116 00117 while len(cell.childs) > 0: 00118 maxDot = -1000 00119 selCell = 0 00120 00121 for chi in cell.childs: 00122 dotP = dot(normal,chi.normal) 00123 if dotP > maxDot: 00124 maxDot = dotP 00125 selCell = chi 00126 00127 cell = selCell 00128 00129 return cell 00130 00131 def supportingVertices(self, normalCenter, sphereCell, dist, factor): 00132 supportVerts = list() 00133 for ver in sphereCell.mappedNormals: 00134 normal = array(normalCenter[1]) / linalg.norm(array(normalCenter[1])) 00135 if abs(dot(normal,(array(ver[0]) - array(normalCenter[0])))) < (dist/factor): 00136 supportVerts.append(ver) 00137 00138 normalSum = array([0, 0, 0]) 00139 centerSum = array([0, 0, 0]) 00140 00141 for ver in supportVerts: 00142 normalSum = normalSum + ver[1] 00143 centerSum = centerSum + ver[0] 00144 00145 return (normalSum/len(supportVerts),supportVerts,centerSum/len(supportVerts)) 00146 00147 def getOrderedTuple(self, pt1, pt2): 00148 if pt1 > pt2: 00149 return pt2,pt1 00150 return pt1,pt2 00151 00152 def emptyCells(self): 00153 nonEmpty=0 00154 for cell in self.polygons[self.max_levels]: 00155 if len(cell.mappedNormals) > 0: 00156 nonEmpty += 1 00157 00158 return len(self.polygons[self.max_levels]) - nonEmpty 00159 00160 def SplitNormals180Degrees(self, normal, point): 00161 for nc in point: 00162 angle = arccos( dot(nc, normal) / (linalg.norm(nc)*linalg.norm(nc1))) * 180 / math.pi 00163 00164 def computeConvexHull(self, polyDataNormals): 00165 length = polyDataNormals.GetPointData().GetNumberOfTuples() 00166 00167 print "number of normals:", length 00168 00169 normals = polyDataNormals.GetPointData().GetNormals() 00170 f = open('coordinates.txt', 'w') 00171 f.write('3\n') 00172 f.write(str(length) + '\n') 00173 00174 k=0 00175 indicesPoints = [] 00176 while (k < length): 00177 center = polyDataNormals.GetPoint(k) 00178 normal = normals.GetTuple3(k) 00179 00180 strCoordinates = str(center[0]) + " " + str(center[1]) + " " + str(center[2]) + "\n" 00181 #print strCoordinates 00182 f.write(strCoordinates) 00183 indicesPoints.insert(k, center) 00184 k+=1 00185 00186 #call qconvex 00187 00188 os.system("qconvex Qt o < coordinates.txt > convexHull.off") 00189 os.system("meshconv convexHull.off -c ply -tri") 00190 00191 def computeEGIFromVTKNormals(self, polyDataNormals, CoM): 00192 #print polyDataNormals 00193 #print polyDataNormals.GetCellData() #contains the normals of the cells (polygons -> triangles) 00194 #print polyDataNormals.GetPointData() #contains the normals of the vertices 00195 00196 #some vertices will have more than one normal associated, if these associated normals 00197 #have an angle of 90 degrees between them, generate normals between them with a certain 00198 #discretization 00199 00200 self.useNormalsOnSurface = 1 00201 if self.useNormalsOnSurface: 00202 length = polyDataNormals.GetCellData().GetNumberOfTuples() 00203 normals = polyDataNormals.GetCellData().GetNormals() 00204 k=0 00205 while (k < length): 00206 triangle = polyDataNormals.GetCell(k) 00207 pts = triangle.GetPoints() 00208 points = pts.GetData() 00209 pt1 = points.GetTuple3(0) 00210 pt2 = points.GetTuple3(1) 00211 pt3 = points.GetTuple3(2) 00212 center = [0,0,0] 00213 normal = normals.GetTuple3(k) 00214 00215 triangle.TriangleCenter(pt1, pt2, pt3, center) 00216 cell = self.findCell(normal) 00217 cell.addInfo(center,normal, 1, k) 00218 k+=1 00219 00220 return self.polygons[self.max_levels] 00221 00222 def computeCenterOfMass(self, polydata): 00223 #print polydata 00224 comx = 0 00225 comy = 0 00226 comz = 0 00227 00228 cells = polydata.GetNumberOfCells() 00229 totalArea = 0 00230 for k in range(cells): 00231 triangle = polydata.GetCell(k) #each cell represents a triangle in the mesh 00232 pts = triangle.GetPoints() 00233 points = pts.GetData() 00234 pt1 = points.GetTuple3(0) 00235 pt2 = points.GetTuple3(1) 00236 pt3 = points.GetTuple3(2) 00237 center = [0,0,0] 00238 triangle.TriangleCenter(pt1, pt2, pt3, center) 00239 area = triangle.TriangleArea(pt1,pt2,pt3) 00240 comx += center[0] * area 00241 comy += center[1] * area 00242 comz += center[2] * area 00243 00244 totalArea += area 00245 00246 CoM = [comx/totalArea, comy/totalArea, comz/totalArea] 00247 return CoM