//vGetNormal() finds the gradient of the scalar field at a point //This gradient can be used as a very accurate vertx normal for lighting calculations GLvoid vGetNormal(GLvector &rfNormal, GLfloat fX, GLfloat fY, GLfloat fZ) { rfNormal.fX = fSample(fX-0.01, fY, fZ) - fSample(fX+0.01, fY, fZ); rfNormal.fY = fSample(fX, fY-0.01, fZ) - fSample(fX, fY+0.01, fZ); rfNormal.fZ = fSample(fX, fY, fZ-0.01) - fSample(fX, fY, fZ+0.01); vNormalizeVector(rfNormal, rfNormal); }
void statistics::RF_statistics::printContrastImportance(ofstream& toFile) { size_t nFeatures = contrastImportanceMat_[0].size(); size_t nPerms = contrastImportanceMat_.size(); for ( size_t featureIdx = 0; featureIdx < nFeatures; ++featureIdx ) { vector<num_t> fSample( nPerms ); for( size_t permIdx = 0; permIdx < nPerms; ++permIdx ) { fSample[permIdx] = contrastImportanceMat_[permIdx][featureIdx]; } num_t mu = math::mean( utils::removeNANs(fSample) ); toFile << mu << endl; } }
//vMarchCube2 performs the Marching Tetrahedrons algorithm on a single cube by making six calls to vMarchTetrahedron GLvoid vMarchCube2(GLfloat fX, GLfloat fY, GLfloat fZ, GLfloat fScale) { GLint iVertex, iTetrahedron, iVertexInACube; GLvector asCubePosition[8]; GLfloat afCubeValue[8]; GLvector asTetrahedronPosition[4]; GLfloat afTetrahedronValue[4]; //Make a local copy of the cube's corner positions for(iVertex = 0; iVertex < 8; iVertex++) { asCubePosition[iVertex].fX = fX + a2fVertexOffset[iVertex][0]*fScale; asCubePosition[iVertex].fY = fY + a2fVertexOffset[iVertex][1]*fScale; asCubePosition[iVertex].fZ = fZ + a2fVertexOffset[iVertex][2]*fScale; } //Make a local copy of the cube's corner values for(iVertex = 0; iVertex < 8; iVertex++) { afCubeValue[iVertex] = fSample(asCubePosition[iVertex].fX, asCubePosition[iVertex].fY, asCubePosition[iVertex].fZ); } for(iTetrahedron = 0; iTetrahedron < 6; iTetrahedron++) { for(iVertex = 0; iVertex < 4; iVertex++) { iVertexInACube = a2iTetrahedronsInACube[iTetrahedron][iVertex]; asTetrahedronPosition[iVertex].fX = asCubePosition[iVertexInACube].fX; asTetrahedronPosition[iVertex].fY = asCubePosition[iVertexInACube].fY; asTetrahedronPosition[iVertex].fZ = asCubePosition[iVertexInACube].fZ; afTetrahedronValue[iVertex] = afCubeValue[iVertexInACube]; } vMarchTetrahedron(asTetrahedronPosition, afTetrahedronValue); } }
//vMarchCube1 performs the Marching Cubes algorithm on a single cube GLvoid vMarchCube1(GLfloat fX, GLfloat fY, GLfloat fZ, GLfloat fScale) { extern GLint aiCubeEdgeFlags[256]; extern GLint a2iTriangleConnectionTable[256][16]; GLint iCorner, iVertex, iVertexTest, iEdge, iTriangle, iFlagIndex, iEdgeFlags; GLfloat fOffset; GLvector sColor; GLfloat afCubeValue[8]; GLvector asEdgeVertex[12]; GLvector asEdgeNorm[12]; //Make a local copy of the values at the cube's corners for(iVertex = 0; iVertex < 8; iVertex++) { afCubeValue[iVertex] = fSample(fX + a2fVertexOffset[iVertex][0]*fScale, fY + a2fVertexOffset[iVertex][1]*fScale, fZ + a2fVertexOffset[iVertex][2]*fScale); } //Find which vertices are inside of the surface and which are outside iFlagIndex = 0; for(iVertexTest = 0; iVertexTest < 8; iVertexTest++) { if(afCubeValue[iVertexTest] <= fTargetValue) iFlagIndex |= 1<<iVertexTest; } //Find which edges are intersected by the surface iEdgeFlags = aiCubeEdgeFlags[iFlagIndex]; //If the cube is entirely inside or outside of the surface, then there will be no intersections if(iEdgeFlags == 0) { return; } //Find the point of intersection of the surface with each edge //Then find the normal to the surface at those points for(iEdge = 0; iEdge < 12; iEdge++) { //if there is an intersection on this edge if(iEdgeFlags & (1<<iEdge)) { fOffset = fGetOffset(afCubeValue[ a2iEdgeConnection[iEdge][0] ], afCubeValue[ a2iEdgeConnection[iEdge][1] ], fTargetValue); asEdgeVertex[iEdge].fX = fX + (a2fVertexOffset[ a2iEdgeConnection[iEdge][0] ][0] + fOffset * a2fEdgeDirection[iEdge][0]) * fScale; asEdgeVertex[iEdge].fY = fY + (a2fVertexOffset[ a2iEdgeConnection[iEdge][0] ][1] + fOffset * a2fEdgeDirection[iEdge][1]) * fScale; asEdgeVertex[iEdge].fZ = fZ + (a2fVertexOffset[ a2iEdgeConnection[iEdge][0] ][2] + fOffset * a2fEdgeDirection[iEdge][2]) * fScale; vGetNormal(asEdgeNorm[iEdge], asEdgeVertex[iEdge].fX, asEdgeVertex[iEdge].fY, asEdgeVertex[iEdge].fZ); } } //Draw the triangles that were found. There can be up to five per cube for(iTriangle = 0; iTriangle < 5; iTriangle++) { if(a2iTriangleConnectionTable[iFlagIndex][3*iTriangle] < 0) break; for(iCorner = 0; iCorner < 3; iCorner++) { iVertex = a2iTriangleConnectionTable[iFlagIndex][3*iTriangle+iCorner]; vGetColor(sColor, asEdgeVertex[iVertex], asEdgeNorm[iVertex]); glColor3f(sColor.fX, sColor.fY, sColor.fZ); glNormal3f(asEdgeNorm[iVertex].fX, asEdgeNorm[iVertex].fY, asEdgeNorm[iVertex].fZ); glVertex3f(asEdgeVertex[iVertex].fX, asEdgeVertex[iVertex].fY, asEdgeVertex[iVertex].fZ); } } }
void marchCube(vec3& pos, vec3& step, std::vector<vec3>& vertices) { int iFlagIndex; float afCubeValue[8]; vec3 vertlist[12]; //calculate cube's vertices const float x = pos.x; const float y = pos.y; const float z = pos.z; vec3 edges[8] = { vec3( x, y, z ), vec3( x + step.x, y, z ), vec3( x + step.x, y + step.y, z ), vec3( x, y + step.y, z ), vec3( x, y, z + step.z ), vec3( x + step.x, y, z + step.z ), vec3( x + step.x, y + step.y, z + step.z ), vec3( x, y + step.x, z + step.z ) }; //calculate the distance function for the current cube for (int i = 0; i < 8; i++) afCubeValue[i] = fSample(edges[i]); //Find which vertices are inside of the surface and which are outside iFlagIndex = 0; if (afCubeValue[0] < 0.0) iFlagIndex |= 1; if (afCubeValue[1] < 0.0) iFlagIndex |= 1 << 1; if (afCubeValue[2] < 0.0) iFlagIndex |= 1 << 2; if (afCubeValue[3] < 0.0) iFlagIndex |= 1 << 3; if (afCubeValue[4] < 0.0) iFlagIndex |= 1 << 4; if (afCubeValue[5] < 0.0) iFlagIndex |= 1 << 5; if (afCubeValue[6] < 0.0) iFlagIndex |= 1 << 6; if (afCubeValue[7] < 0.0) iFlagIndex |= 1 << 7; if (iFlagIndex == 0 || iFlagIndex == 255) return; //Find which edges are intersected by the surface //iEdgeFlags = aiCubeEdgeFlags[iFlagIndex]; if (/*iEdgeFlags & 1*/(iFlagIndex & 0x1) != (iFlagIndex & 0x2)) vertlist[0] = interpolate(edges[0], edges[1], afCubeValue[0], afCubeValue[1]); if (/*iEdgeFlags & 2*/(iFlagIndex & 0x2) != (iFlagIndex & 0x4)) vertlist[1] = interpolate(edges[1], edges[2], afCubeValue[1], afCubeValue[2]); if (/*iEdgeFlags & 4*/(iFlagIndex & 0x4) != (iFlagIndex & 0x8)) vertlist[2] = interpolate(edges[2], edges[3], afCubeValue[2], afCubeValue[3]); if (/*iEdgeFlags & 8*/(iFlagIndex & 0x8) != (iFlagIndex & 0x1)) vertlist[3] = interpolate(edges[3], edges[0], afCubeValue[3], afCubeValue[0]); if (/*iEdgeFlags & 16*/(iFlagIndex & 0x10) != (iFlagIndex & 0x20)) vertlist[4] = interpolate(edges[4], edges[5], afCubeValue[4], afCubeValue[5]); if (/*iEdgeFlags & 32*/(iFlagIndex & 0x20) != (iFlagIndex & 0x40)) vertlist[5] = interpolate(edges[5], edges[6], afCubeValue[5], afCubeValue[6]); if (/*iEdgeFlags & 64*/(iFlagIndex & 0x40) != (iFlagIndex & 0x80)) vertlist[6] = interpolate(edges[6], edges[7], afCubeValue[6], afCubeValue[7]); if (/*iEdgeFlags & 128*/(iFlagIndex & 0x80) != (iFlagIndex & 0x10)) vertlist[7] = interpolate(edges[7], edges[4], afCubeValue[7], afCubeValue[4]); if (/*iEdgeFlags & 256*/(iFlagIndex & 0x1) != (iFlagIndex & 0x10)) vertlist[8] = interpolate(edges[0], edges[4], afCubeValue[0], afCubeValue[4]); if (/*iEdgeFlags & 512*/(iFlagIndex & 0x2) != (iFlagIndex & 0x20)) vertlist[9] = interpolate(edges[1], edges[5], afCubeValue[1], afCubeValue[5]); if (/*iEdgeFlags & 1024*/(iFlagIndex & 0x4) != (iFlagIndex & 0x40)) vertlist[10] = interpolate(edges[2], edges[6], afCubeValue[2], afCubeValue[6]); if (/*iEdgeFlags & 2048*/(iFlagIndex & 0x8) != (iFlagIndex & 0x80)) vertlist[11] = interpolate(edges[3], edges[7], afCubeValue[3], afCubeValue[7]); //Generate triangles!!! signed char* connectionTable = a2iTriangleConnectionTable[iFlagIndex]; for (int i = 0; connectionTable[i] != -1; i += 3) { vertices.push_back(vertlist[connectionTable[i ]]); vertices.push_back(vertlist[connectionTable[i+1 ]]); vertices.push_back(vertlist[connectionTable[i+2 ]]); } }
//vMarchCube performs the Marching Cubes algorithm on a single cube void vMarchCube(int iX, int iY, int iZ) { extern GLint aiCubeEdgeFlags[256]; extern GLint a2iTriangleConnectionTable[256][16]; int iValueIndex; GLfloat fX, fY, fZ; GLfloat fXScale, fYScale, fZScale; GLfloat fCentralPoint = 0.0; GLfloat fDeltaValue, fDeltaX, fDeltaY, fDeltaZ; GLint iCorner, iVertex, iVertexTest, iEdge, iTriangle, iFlagIndex, iEdgeFlags; GLfloat fOffset; GLvector sColor; GLfloat afCubeValue[8]; GLvector asEdgeVertex[12]; GLvector asEdgeNorm[12]; int iX0, iY0, iZ0; int iX1, iY1, iZ1; GLfloat fValue0, fValue1; //Make a local copy of the values at the cube's corners for(iVertex = 0; iVertex < 8; iVertex++) { afCubeValue[iVertex] = fSample(iX + a2fVertexOffset[iVertex][0]*iXStep, iY + a2fVertexOffset[iVertex][1]*iYStep, iZ + a2fVertexOffset[iVertex][2]*iZStep); fCentralPoint += afCubeValue[iVertex]; } if (iUseGridPointers) { fX = fSourceXPointer[iX]; fY = fSourceYPointer[iY]; fZ = fSourceZPointer[iZ]; /* this can be calculated beforehand ... */ if ((iX+iXStep) < iXDataSetSize) { fXScale = fSourceXPointer[iX+iXStep] - fX; }else{ fXScale = 0.0; } if ((iY+iYStep) < iYDataSetSize) { fYScale = fSourceYPointer[iY+iYStep] - fY; }else{ fYScale = 0.0; } if ((iZ+iZStep) < iZDataSetSize) { fZScale = fSourceZPointer[iZ+iZStep] - fZ; }else{ fZScale = 0.0; } } else { iValueIndex = iX * (iYDataSetSize * iZDataSetSize) + \ iY * (iZDataSetSize) + iZ; fX = fSourceDataVerticesPointer[iValueIndex].fX; fY = fSourceDataVerticesPointer[iValueIndex].fY; fZ = fSourceDataVerticesPointer[iValueIndex].fZ; iValueIndex = (iX+iXStep) * (iYDataSetSize * iZDataSetSize) + \ (iY +iYStep) * (iZDataSetSize) + (iZ+iZStep); fXScale = fSourceDataVerticesPointer[iValueIndex].fX - fX; fYScale = fSourceDataVerticesPointer[iValueIndex].fY - fY; fZScale = fSourceDataVerticesPointer[iValueIndex].fZ - fZ; } /* Normal calucation */ /* Store the value of the scalar field at the center of the cube */ fCentralPoint *= 0.125; /* The central point has coordinates fCentralPointX = fX + 0.5 * fXScale fCentralPointY = fY + 0.5 * fYScale fCentralPointZ = fZ + 0.5 * fZScale */ //Find which vertices are inside of the surface and which are outside iFlagIndex = 0; for(iVertexTest = 0; iVertexTest < 8; iVertexTest++) { if(afCubeValue[iVertexTest] <= fTargetValue) iFlagIndex |= 1<<iVertexTest; } //Find which edges are intersected by the surface iEdgeFlags = aiCubeEdgeFlags[iFlagIndex]; //If the cube is entirely inside or outside of the surface, then there will be no intersections if((iEdgeFlags == 0) || (iEdgeFlags == 255)) { return; } //Find the point of intersection of the surface with each edge //Then find the normal to the surface at those points for(iEdge = 0; iEdge < 12; iEdge++) { //if there is an intersection on this edge if(iEdgeFlags & (1<<iEdge)) { fOffset = fGetOffset(afCubeValue[ a2iEdgeConnection[iEdge][0] ], afCubeValue[ a2iEdgeConnection[iEdge][1] ], fTargetValue); //The vertex value in actual coordenates asEdgeVertex[iEdge].fX = fX + fXScale * (a2fVertexOffset[ a2iEdgeConnection[iEdge][0] ][0] + fOffset * a2fEdgeDirection[iEdge][0]); asEdgeVertex[iEdge].fY = fY + fYScale * (a2fVertexOffset[ a2iEdgeConnection[iEdge][0] ][1] + fOffset * a2fEdgeDirection[iEdge][1]); asEdgeVertex[iEdge].fZ = fZ + fZScale * (a2fVertexOffset[ a2iEdgeConnection[iEdge][0] ][2] + fOffset * a2fEdgeDirection[iEdge][2]); if (0) { //This would be for the interpolating case: vGetNormal(&asEdgeNorm[iEdge], asEdgeVertex[iEdge].fX, asEdgeVertex[iEdge].fY, asEdgeVertex[iEdge].fZ); } else { /* This is for the "regular" grid */ if (1){ /* the correct way ... (hopefully) */ /* calculate the indices of the two vertices */ iX0 = a2fVertexOffset[ a2iEdgeConnection[iEdge][0] ][0]; iY0 = a2fVertexOffset[ a2iEdgeConnection[iEdge][0] ][1]; iZ0 = a2fVertexOffset[ a2iEdgeConnection[iEdge][0] ][2]; iX1 = a2fVertexOffset[ a2iEdgeConnection[iEdge][1] ][0]; iY1 = a2fVertexOffset[ a2iEdgeConnection[iEdge][1] ][1]; iZ1 = a2fVertexOffset[ a2iEdgeConnection[iEdge][1] ][2]; /* I have the indices */ /* The derivative in the first vertex respect to X*/ if (fXScale != 0){ fValue0 = fSample(iX + (iX0 + 1) * iXStep, iY + iY0 * iYStep, iZ + iZ0 * iZStep) -\ fSample(iX + (iX0 - 1) * iXStep, iY + iY0 * iYStep, iZ + iZ0 * iZStep); fValue1 = fSample(iX + (iX1 + 1) * iXStep, iY + iY1 * iYStep, iZ + iZ1 * iZStep) -\ fSample(iX + (iX1 - 1) * iXStep, iY + iY1 * iYStep, iZ + iZ1 * iZStep); asEdgeNorm[iEdge].fX = 0.5 * (fValue1 - fValue0) / fXScale; }else{ asEdgeNorm[iEdge].fX = 0.0; } /* The derivative in the first vertex respect to X */ if (fXScale != 0){ fValue0 = fSample(iX + (iX0 + 1) * iXStep, iY + iY0 * iYStep, iZ + iZ0 * iZStep) -\ fSample(iX + (iX0 - 1) * iXStep, iY + iY0 * iYStep, iZ + iZ0 * iZStep); fValue1 = fSample(iX + (iX1 + 1) * iXStep, iY + iY1 * iYStep, iZ + iZ1 * iZStep) -\ fSample(iX + (iX1 - 1) * iXStep, iY + iY1 * iYStep, iZ + iZ1 * iZStep); asEdgeNorm[iEdge].fX = 0.5 * (fValue0 + fOffset * fValue1) / fXScale; }else{ asEdgeNorm[iEdge].fX = 0.0; } /* The derivative in the first vertex respect to Y */ if (fYScale != 0){ fValue0 = fSample(iX * iXStep, iY + (iY0 + 1) * iYStep, iZ + iZ0 * iZStep) -\ fSample(iX * iXStep, iY + (iY0 - 1) * iYStep, iZ + iZ0 * iZStep); fValue1 = fSample(iX + iX1 * iXStep, iY + (iY1 + 1) * iYStep, iZ + iZ1 * iZStep) -\ fSample(iX + iX1 * iXStep, iY + (iY1 - 1) * iYStep, iZ + iZ1 * iZStep); asEdgeNorm[iEdge].fY = 0.5 * (fValue0 + fOffset * fValue1) / fYScale; }else{ asEdgeNorm[iEdge].fY = 0.0; } /* The derivative in the first vertex respect to Z */ if (fYScale != 0){ fValue0 = fSample(iX * iXStep, iY + iY0 * iYStep, iZ + (iZ0 + 1) * iZStep) -\ fSample(iX * iXStep, iY + iY0 * iYStep, iZ + (iZ0 - 1) * iZStep); fValue1 = fSample(iX + iX1 * iXStep, iY + iY1 * iYStep, iZ + (iZ1 + 1) * iZStep) -\ fSample(iX + iX1 * iXStep, iY + iY1 * iYStep, iZ + (iZ1 - 1) * iZStep); asEdgeNorm[iEdge].fZ = 0.5 * (fValue0 + fOffset * fValue1) / fZScale; }else{ asEdgeNorm[iEdge].fZ = 0.0; } }else { /* calculate all respect to the center */ fDeltaValue = fTargetValue - fCentralPoint; fDeltaX = asEdgeVertex[iEdge].fX - fX - 0.5 * fXScale; fDeltaY = asEdgeVertex[iEdge].fY - fY - 0.5 * fYScale; fDeltaZ = asEdgeVertex[iEdge].fZ - fZ - 0.5 * fZScale; if (fDeltaX > 0) { asEdgeNorm[iEdge].fX = fDeltaValue/fDeltaX; }else{ asEdgeNorm[iEdge].fX = 0.0; } if (fDeltaY > 0) { asEdgeNorm[iEdge].fY = fDeltaValue/fDeltaY; }else{ asEdgeNorm[iEdge].fY = 0.0; } if (fDeltaZ > 0) { asEdgeNorm[iEdge].fZ = fDeltaValue/fDeltaZ; }else{ asEdgeNorm[iEdge].fZ = 0.0; } } vNormalizeVector(&asEdgeNorm[iEdge], asEdgeNorm[iEdge]); } } } //Draw the triangles that were found. There can be up to five per cube for(iTriangle = 0; iTriangle < 5; iTriangle++) { if(a2iTriangleConnectionTable[iFlagIndex][3*iTriangle] < 0) break; for(iCorner = 0; iCorner < 3; iCorner++) { iVertex = a2iTriangleConnectionTable[iFlagIndex][3*iTriangle+iCorner]; if ((fIsoColor[0] < 0) || (fIsoColor[2] < 0) || (fIsoColor[3] < 0)) { vGetColor(&sColor, asEdgeVertex[iVertex], asEdgeNorm[iVertex]); glColor3f(sColor.fX, sColor.fY, sColor.fZ); } else { //glColor4f(fIsoColor[0], fIsoColor[1], fIsoColor[2], fIsoColor[3]); } glNormal3f(asEdgeNorm[iVertex].fX, asEdgeNorm[iVertex].fY, asEdgeNorm[iVertex].fZ); glVertex3f(asEdgeVertex[iVertex].fX, asEdgeVertex[iVertex].fY, asEdgeVertex[iVertex].fZ); /* if ((asEdgeVertex[iVertex].fZ > 1.93) || (asEdgeVertex[iVertex].fZ < 1.8)) { printf("iVertex = %d Z = %f\n", iVertex, asEdgeVertex[iVertex].fZ); printf("iX = %d iY = %d iZ = %d\n", iX, iY, iZ); printf("fx = %f, fy = %f, fz = %f\n", fX, fY, fZ); printf("scalex = %f, scaley = %f, scalez = %f\n", fXScale , fYScale , fZScale ); exit(1); } */ } iNTotalTriangles++; /* This was for some tests */ if (0) { if (iNTotalTriangles < 2) { printf("Triangle %d\n", iNTotalTriangles); printf("Target value =%f\n", fTargetValue); printf("Indices = %d, %d, %d\n", iX, iY, iZ); iValueIndex = iX * (iYDataSetSize * iZDataSetSize) + \ iY * (iZDataSetSize) + iZ; printf("Value index = %d, value =%f, vertex = %f, %f, %f\n", iValueIndex, *fSourceDataValuesPointer, fX, fY, fZ); printf("iFlagIndex=%d\n", iFlagIndex); printf("Edge flags =%d\n", iEdgeFlags); printf("Cube limits\n"); for(iVertex = 0; iVertex < 8; iVertex++) { printf("vertex = %d, value = %f\n", iVertex, afCubeValue[iVertex]); } } } } }