TriangleMesh * CorrespondTemplates::computeSurface(char * exportFilename, bool useMapping) { int i, j, counter, numTetNodes; TriangleMesh * resultMesh = new TriangleMesh(); vector<int> surfaceIds; //Find the surface: findSurfaceNodes(); numTetNodes = volumetricMeshNodes.numberOfItems(); surfaceIds.resize(numTetNodes); g_NodeContainer nodesSurf; if ( useMapping ) nodesSurf = rigidlyAlignedSurfaceTemplate->nodes(); //Add the nodes: counter = 0; for(i = 0; i < numTetNodes; i++) { if(surfaceNodes[i] == -1) surfaceIds[i] = -1; else { surfaceIds[i] = counter; counter++; g_Vector coord; if ( useMapping ) { coord = mappingWeightsTet[3*i] * nodesSurf[mappingIndicesTet[3*i]]->coordinate(); coord += mappingWeightsTet[3*i+1] * nodesSurf[mappingIndicesTet[3*i+1]]->coordinate(); coord += mappingWeightsTet[3*i+2] * nodesSurf[mappingIndicesTet[3*i+2]]->coordinate(); } else { coord = volumetricMeshNodes[i]->coordinate(); } g_Node * newNode = new g_Node(coord); resultMesh->node(newNode); } } //Add the triangles (find the correct orientation): for(i = 0; i < trianglesOnSurface.size(); i++) { g_Element * elem = new g_Element(); for(j = 0; j < allTetrahedra.size(); j++) { set<int> triangle; triangle.insert(allTetrahedra[j][0]); triangle.insert(allTetrahedra[j][1]); triangle.insert(allTetrahedra[j][2]); if(trianglesOnSurface[i] == triangle) { elem->node(resultMesh->nodes()[surfaceIds[allTetrahedra[j][0]]]); elem->node(resultMesh->nodes()[surfaceIds[allTetrahedra[j][2]]]); elem->node(resultMesh->nodes()[surfaceIds[allTetrahedra[j][1]]]); break; } triangle.clear(); triangle.insert(allTetrahedra[j][0]); triangle.insert(allTetrahedra[j][1]); triangle.insert(allTetrahedra[j][3]); if(trianglesOnSurface[i] == triangle) { elem->node(resultMesh->nodes()[surfaceIds[allTetrahedra[j][0]]]); elem->node(resultMesh->nodes()[surfaceIds[allTetrahedra[j][1]]]); elem->node(resultMesh->nodes()[surfaceIds[allTetrahedra[j][3]]]); break; } triangle.clear(); triangle.insert(allTetrahedra[j][0]); triangle.insert(allTetrahedra[j][2]); triangle.insert(allTetrahedra[j][3]); if(trianglesOnSurface[i] == triangle) { elem->node(resultMesh->nodes()[surfaceIds[allTetrahedra[j][0]]]); elem->node(resultMesh->nodes()[surfaceIds[allTetrahedra[j][3]]]); elem->node(resultMesh->nodes()[surfaceIds[allTetrahedra[j][2]]]); break; } triangle.clear(); triangle.insert(allTetrahedra[j][1]); triangle.insert(allTetrahedra[j][2]); triangle.insert(allTetrahedra[j][3]); if(trianglesOnSurface[i] == triangle) { elem->node(resultMesh->nodes()[surfaceIds[allTetrahedra[j][1]]]); elem->node(resultMesh->nodes()[surfaceIds[allTetrahedra[j][2]]]); elem->node(resultMesh->nodes()[surfaceIds[allTetrahedra[j][3]]]); break; } } resultMesh->element(elem); } //Export: if(exportFilename != NULL) { exportMeshWrapper(exportFilename, resultMesh); } return resultMesh; }
void CorrespondTemplates::computeMappings(char * outfileMappingTet, char * outfileMappingSurf, g_Node * contactPoint) { //Compute the mappings using barycentric coordinates findSurfaceNodes(); maptet2surfID = surfaceNodes; // output tetmesh surface computeSurface( "tet_mesh_surf.wrl" ); deformVolumetricMeshRigidly(); int i, j, k, numNodesTet, numElemsTet, numNodesSurf, numElemsSurf; double dist, minDist, d, mind, distContactPoint, minDistContactPoint; numNodesTet = volumetricMeshNodes.numberOfItems(); numElemsTet = trianglesOnSurface.size(); numNodesSurf = rigidlyAlignedSurfaceTemplate->getNumberOfNodes(); numElemsSurf = rigidlyAlignedSurfaceTemplate->getNumberOfTriangles(); //First compute the mapping from the tetrahedral mesh to the surface mesh mappingIndicesTet.resize(3*numNodesTet); mappingWeightsTet.resize(3*numNodesTet); offsetsTet.resize(numNodesTet); for(i = 0; i < numNodesTet; i++) { if(surfaceNodes[i] == -1) { mappingIndicesTet[3*i] = mappingIndicesTet[3*i+1] = mappingIndicesTet[3*i+2] = -1; mappingWeightsTet[3*i] = mappingWeightsTet[3*i+1] = mappingWeightsTet[3*i+2] = -1; } else { for(j = 0; j < numElemsSurf; j++) { // g_Vector closestPoint = computeClosestPoint(volumetricMeshNodes[i], rigidlyAlignedSurfaceTemplate->elements()[j]); // dist = closestPoint.DistanceTo(volumetricMeshNodes[i]->coordinate()); g_Vector closestPoint; dist = computeClosestPoint(*volumetricMeshNodes[i], *rigidlyAlignedSurfaceTemplate->elements()[j], closestPoint ); dist = sqrt(dist); if((j == 0) || (dist < minDist)) { minDist = dist; mappingIndicesTet[3*i] = rigidlyAlignedSurfaceTemplate->elements()[j]->nodes()[0]->id()-1; mappingIndicesTet[3*i+1] = rigidlyAlignedSurfaceTemplate->elements()[j]->nodes()[1]->id()-1; mappingIndicesTet[3*i+2] = rigidlyAlignedSurfaceTemplate->elements()[j]->nodes()[2]->id()-1; //---------------------- for(int n = 0; n < 3; n++){ d = volumetricMeshNodes[i]->coordinate().DistanceTo(rigidlyAlignedSurfaceTemplate->elements()[j]->nodes()[n]->coordinate()); if((n == 0) || (d < mind)){ mind = d; maptet2surfID[i] = rigidlyAlignedSurfaceTemplate->elements()[j]->nodes()[n]->id()-1; } } //------------------------ vector<double> barycentrics = computeBarycentrics(volumetricMeshNodes[i]->coordinate(), closestPoint, rigidlyAlignedSurfaceTemplate->elements()[j]); mappingWeightsTet[3*i] = barycentrics[0]; mappingWeightsTet[3*i+1] = barycentrics[1]; mappingWeightsTet[3*i+2] = barycentrics[2]; offsetsTet[i] = barycentrics[3]; } } } } //Export if(outfileMappingTet != NULL) { #if 0 FILE * fp = fopen(outfileMappingTet, "w"); if(fp == NULL) { cout<<"Problem writing "<<outfileMappingTet<<endl; return; } for(i = 0; i < numNodesTet; i++) fprintf(fp, "%d %d %d %f %f %f %f\n", mappingIndicesTet[3*i], mappingIndicesTet[3*i+1], mappingIndicesTet[3*i+2], mappingWeightsTet[3*i], mappingWeightsTet[3*i+1], mappingWeightsTet[3*i+2], offsetsTet[i]); fclose(fp); #else // Make a surface mesh using the tetmesh surface plus the coordinates from the surface mesh computeSurface( outfileMappingTet, true ); #endif } //Second compute the mapping from the surface mesh to the tetrahedral mesh mappingIndicesSurf.resize(3*numNodesSurf); mappingWeightsSurf.resize(3*numNodesSurf); offsetsSurf.resize(numNodesSurf); contactTriangleId.resize(3); contactWeights.resize(3); contactoffset.resize(1); for(i = 0; i < numNodesSurf; i++) { for(j = 0; j < numElemsTet; j++) { g_Element elem; set<int>::iterator triangleIt; for(triangleIt = trianglesOnSurface[j].begin(); triangleIt != trianglesOnSurface[j].end(); triangleIt++) elem.node(volumetricMeshNodes[*triangleIt]); // g_Vector closestPoint = computeClosestPoint(rigidlyAlignedSurfaceTemplate->nodes()[i], &elem); // dist = closestPoint.DistanceTo(rigidlyAlignedSurfaceTemplate->nodes()[i]->coordinate()); g_Vector closestPoint; dist = computeClosestPoint(*rigidlyAlignedSurfaceTemplate->nodes()[i], elem, closestPoint ); dist = sqrt(dist); if((j == 0) || (dist < minDist)) { minDist = dist; k = 0; for(triangleIt = trianglesOnSurface[j].begin(); triangleIt != trianglesOnSurface[j].end(); triangleIt++, k++) mappingIndicesSurf[3*i+k] = *triangleIt; vector<double> barycentrics = computeBarycentrics(rigidlyAlignedSurfaceTemplate->nodes()[i]->coordinate(), closestPoint, &elem); mappingWeightsSurf[3*i] = barycentrics[0]; mappingWeightsSurf[3*i+1] = barycentrics[1]; mappingWeightsSurf[3*i+2] = barycentrics[2]; offsetsSurf[i] = barycentrics[3]; } //--------------------------- if(i == 0 && contactPoint != NULL){ g_Vector closestContactPoint; distContactPoint = computeClosestPoint(*contactPoint, elem, closestContactPoint ); distContactPoint = sqrt(distContactPoint); // g_Vector closestContactPoint = computeClosestPoint(contactPoint, &elem); // distContactPoint = closestContactPoint.DistanceTo(contactPoint->coordinate()); if((j == 0) || (distContactPoint < minDistContactPoint)) { minDistContactPoint = distContactPoint; k = 0; for(triangleIt = trianglesOnSurface[j].begin(); triangleIt != trianglesOnSurface[j].end(); triangleIt++, k++) contactTriangleId[3*i+k] = *triangleIt; vector<double> barycentricsContactPoint = computeBarycentrics(contactPoint->coordinate(), closestContactPoint, &elem); contactWeights[3*i] = barycentricsContactPoint[0]; contactWeights[3*i+1] = barycentricsContactPoint[1]; contactWeights[3*i+2] = barycentricsContactPoint[2]; contactoffset[i] = barycentricsContactPoint[3]; } } //---------------------------- } } //Export if(outfileMappingSurf != NULL) { #if 0 FILE * fp = fopen(outfileMappingSurf, "w"); if(fp == NULL) { cout<<"Problem writing "<<outfileMappingSurf<<endl; return; } for(i = 0; i < numNodesSurf; i++) fprintf(fp, "%d %d %d %f %f %f %f\n", mappingIndicesSurf[3*i], mappingIndicesSurf[3*i+1], mappingIndicesSurf[3*i+2], mappingWeightsSurf[3*i], mappingWeightsSurf[3*i+1], mappingWeightsSurf[3*i+2], offsetsSurf[i]); fclose(fp); #else // Make a surface mesh using the tetmesh surface plus the coordinates from the surface mesh TriangleMesh surfTet; for (int i=0; i<numNodesSurf; ++i ) { // std::cerr << i << " " << std::endl; g_Vector coord = mappingWeightsSurf[3*i] * volumetricMeshNodes[mappingIndicesSurf[3*i]]->coordinate(); coord += mappingWeightsSurf[3*i+1] * volumetricMeshNodes[mappingIndicesSurf[3*i+1]]->coordinate(); coord += mappingWeightsSurf[3*i+2] * volumetricMeshNodes[mappingIndicesSurf[3*i+2]]->coordinate(); surfTet.node(new g_Node( coord )); } // std::cerr << std::endl; g_ElementContainer eleSurf = rigidlyAlignedSurfaceTemplate->elements(); g_NodeContainer newNodes = surfTet.nodes(); for ( g_ElementContainer::const_iterator fIt=eleSurf.begin(); fIt != eleSurf.end(); ++fIt ) { g_Element *ele = new g_Element(); g_NodeContainer faceNodes = (*fIt)->nodes(); for ( g_NodeContainer::const_iterator nIt = faceNodes.begin(); nIt != faceNodes.end(); ++nIt ) { ele->node(newNodes[(*nIt)->id()-1]); } surfTet.element(ele); } exportMeshWrapper( outfileMappingSurf, &surfTet ); #endif } }