def calculateVolume(allTris, triPoints, pointXYZ): '''calculates whole area based on triangles and a random point (0,0,0). individual formula is based on http://mathworld.wolfram.com/Plane.html''' volume = 0.0 areaTotalCheck = 0.0 origin = (0., 0., 0.) # could be any point, but this one is fine for tri in allTris: #calculate volume triPointXYZ = [] # 3 points will be here soon for point in triPoints[tri-1][1:]: triPointXYZ.append(pointXYZ[point-1][1:]) area = geometry.calcTriAreaList(triPointXYZ) normal = geometry.getTriNormalList(triPointXYZ) centerTri = geometry.getAverage(triPointXYZ) planeD = geometry.calculatePlaneD(normal, centerTri) #print triPointXYZ, normal, area height = geometry.planeDistToOrigin(normal+[planeD]) #this height is signed and we can just add it to volume. #volume is 1/3 area * height thisVol = area * height / 3. #print area, normal #print height, thisVol, volume += thisVol areaTotalCheck += area # free to check other computation. #determine whether the point is on the same side as the normal. +/- #can do this but not necessary #side = geometry.checkPlaneSide(normal+[planeD], origin) #if (side and thisVol < 0.) or (not side and thisVol > 0.) or thisVol == 0.: # print side, thisVol if volume > 0.: return volume else: return -volume # since sometimes the origin is inside the shape
def tstEdgeCurvature(trianglePoint, pointXyz, pointTriangle, pointNeighbor): '''for each edge, calculate the angle between the triangles around it. calculate point curvature based on average of these for each point''' triXyz = {} for triPtList in trianglePoint: tri = triPtList[0] xyz = [] for pt in triPtList[1:]: xyz.append(pointXyz[pt-1][1:]) triXyz[tri] = xyz edgeAngle = {} # store edge angles as they are found so don't duplicate work pointMeanAngle = [] # once all edges found, find mean, store in tst format pointWeightedMeanAngle = [] # weight by edge length for pointNeighborList in pointNeighbor: mainPt = pointNeighborList[0] angles = [] weightedAngles = [] for otherPt in pointNeighborList[2:]: # pN[1] is count ptList = [mainPt, otherPt] ptList.sort() ptTuple = tuple(ptList) # canonicalized format edgeLength = geometry.distL2( pointXyz[mainPt-1][1:], pointXyz[otherPt-1][1:]) if ptTuple in edgeAngle: # already done angles.append(edgeAngle[ptTuple]) weightedAngles.append(edgeAngle[ptTuple] * edgeLength) else: # have to compute it mainTris = set(pointTriangle[mainPt-1][2:]) otherTris = set(pointTriangle[otherPt-1][2:]) tris = list(mainTris.intersection(otherTris)) #will almost always be 2 #for now assume only 2 normalA = geometry.getTriNormalList(triXyz[tris[0]]) normalB = geometry.getTriNormalList(triXyz[tris[1]]) unsignedAngle = geometry.getAngle(normalA, normalB) # unsigned centerTriA = geometry.getAverage(triXyz[tris[0]]) planeA = geometry.calculatePlaneD(normalA, centerTriA) ptsB = set(trianglePoint[tris[1]-1][1:]) edgePts = set(ptList) otherB = pointXyz[list(ptsB.difference(edgePts))[0]-1][1:] side = geometry.checkPlaneSide(normalA+[planeA], otherB) if side: angle = - unsignedAngle * 180 / math.pi # concave negative else: angle = unsignedAngle * 180 / math.pi # convex positive edgeAngle[ptTuple] = angle angles.append(angle) weightedAngles.append(angle*edgeLength) pointMeanAngle.append([mainPt, statistics.computeMean(angles)]) pointWeightedMeanAngle.append( [mainPt, statistics.computeMean(weightedAngles)]) return edgeAngle, pointMeanAngle, pointWeightedMeanAngle
def calcNormals(pointXyz, triPointDict, pointTriDict): '''calculate normals for each point by averaging the adjacent tri normals''' triNormals = {} for tri in triPointDict.keys(): points = triPointDict[tri] coords = [] for point in points: coords.append(pointXyz[point-1][1:]) triNormals[tri] = geometry.getTriNormalList(coords) outputList = [] for pointXyzRecord in pointXyz: pointNum = pointXyzRecord[0] normals = [] for tri in pointTriDict[pointNum]: normals.append(triNormals[tri]) thisNormal = geometry.getAverage(normals) # just average the normals outputList.append([pointNum, thisNormal[0], thisNormal[1], thisNormal[2]]) return outputList
def pca3d(pointList): '''sets up the pca for a list of points in 3d. solves eig problem''' matrixList = [[0, 0, 0], [0, 0, 0], [0, 0, 0]] # init to 0 avgPt = geometry.getAverage(pointList) diffs = [0, 0, 0] for point in pointList: for index in range(3): diffs[index] = point[index] - avgPt[index] #matrix is old plus a2 ab ac # ba b2 bc # ca cb c2 only compute upper diagonal now matrixList[0][0] += diffs[0] * diffs[0] # just hardcode it matrixList[0][1] += diffs[0] * diffs[1] matrixList[0][2] += diffs[0] * diffs[2] matrixList[1][1] += diffs[1] * diffs[1] matrixList[1][2] += diffs[1] * diffs[2] matrixList[2][2] += diffs[2] * diffs[2] #make symmetric matrixList[1][0] = matrixList[0][1] matrixList[2][0] = matrixList[0][2] matrixList[2][1] = matrixList[1][2] actualMatrix = Matrix(matrixList) val, vec = eigenvectors(actualMatrix) return val, vec