void SimMesh::ReadTetgenMesh(string mesh_name){ //Read vertices string line; stringstream temp_ss; ifstream node_file((mesh_name+".node").c_str()); if (node_file.is_open()) { while ( getline (node_file,line) ) { if(line[line.find_first_not_of(" ")] == '#' ) continue; else{ temp_ss.str(line); temp_ss >> num_vertices; break; } } while ( getline (node_file,line) ){ if(line[line.find_first_not_of(" ")] == '#' ) continue; else{ temp_ss.str(line); int counter; glm::vec4 vertex; temp_ss >> counter >> vertex.x >> vertex.y >> vertex.z; vertex.w = 1; vertices.push_back(vertex); } } } else{
int main(int argc, char** argv) { std::cout<<"exec volmesh.vtk|vtu surfmesh.vtk out_labels.txt arrayname volmesh_out.vtk scale correct_orientation(0|1)"<<std::endl; std::cout<<"Scale - rescale mesh by this factor, !!! for now works only for ALYA, for everything else put 1"<<std::endl; std::cout<<"correct_orientation - 1 or 0 whether to correct cell orientation or not"<<std::endl; std::cout<<"Labels must be celldata"<<std::endl; std::cout<<"Add extension .bsc to volmesh_out to get mesh in Alya format"<<std::endl; std::cout<<"Skip extension in volmesh_out to get mesh in Elmer format"<<std::endl; std::cout<<"out_labels.txt -- faces with labels, format: label point1 point2 point3 tetra_id"<<std::endl; if(argc<4) return -1; const char* volmesh_file = argv[1]; const char* surfmesh_file = argv[2]; const char* outfile = argv[3]; const char* array_name = argv[4]; const char* volmeshout = argv[5]; float scale = atof(argv[6]); bool correct_orientation = atoi(argv[7])==1; std::cout<<"Volumetric mesh: "<<volmesh_file<<std::endl; std::cout<<"Surface mesh: "<<surfmesh_file<<std::endl; std::cout<<"Labels: "<<outfile<<std::endl; std::cout<<"Label array: "<<array_name<<std::endl; std::cout<<"Output mesh: "<<volmeshout<<std::endl; std::cout<<"Scale: "<<scale<<std::endl; if(correct_orientation) std::cout<<"Correcting orientation: ON"<<std::endl; else std::cout<<"Correcting orientation: OFF"<<std::endl; bool vtkoutput_mesh = false; bool alyaoutput_mesh = false; if(volmeshout!=NULL) { const char *ext = volmeshout+strlen(volmeshout)-4; if(strcmp(ext,".vtk")==0) //if we are requesting .node .element volumetric mesh vtkoutput_mesh = true; else if(strcmp(ext,".bsc")==0) alyaoutput_mesh = true; } vtkSmartPointer<vtkUnstructuredGrid> volmesh = vtkSmartPointer<vtkUnstructuredGrid>::New(); if (volmesh_file[ strlen(volmesh_file)-1 ] == 'k') //vtk { vtkSmartPointer<vtkDataSetReader> vol_rdr = vtkSmartPointer<vtkDataSetReader>::New(); CommonTools::AssociateProgressFunction(vol_rdr); vol_rdr->SetFileName(volmesh_file); vol_rdr->Update(); volmesh->DeepCopy( (vtkUnstructuredGrid*)vol_rdr->GetOutput() ); } else { vtkSmartPointer<vtkXMLUnstructuredGridReader> vol_rdr = vtkSmartPointer<vtkXMLUnstructuredGridReader>::New(); CommonTools::AssociateProgressFunction(vol_rdr); vol_rdr->SetFileName(volmesh_file); vol_rdr->Update(); volmesh->DeepCopy( (vtkUnstructuredGrid*)vol_rdr->GetOutput() ); } if(volmesh->GetCell(0)->GetNumberOfPoints()<4) { std::cout<<"Supplied volumetric mesh has cells with : "<<volmesh->GetCell(0)->GetNumberOfPoints()<<" vertices"<<std::endl; std::cout<<"Make sure your mesh is actually volumetric"<<std::endl; exit(-1); } vtkSmartPointer<vtkPolyDataReader> poly_rdr = vtkSmartPointer<vtkPolyDataReader>::New(); CommonTools::AssociateProgressFunction(poly_rdr); poly_rdr->SetFileName(surfmesh_file); poly_rdr->Update(); vtkPolyData* surfmesh = poly_rdr->GetOutput(); //read cell scalars from the surface mesh (labels) auto scalars = surfmesh->GetCellData()->GetArray(array_name); vtkSmartPointer<vtkPointLocator> ptloc = vtkSmartPointer<vtkPointLocator>::New(); ptloc->SetDataSet(volmesh); ptloc->BuildLocator(); vtkSmartPointer<vtkCellLocator> cellloc = vtkSmartPointer<vtkCellLocator>::New(); cellloc->SetDataSet(volmesh); cellloc->BuildLocator(); if(volmeshout!=NULL) { //create PointData array in the volumetric mesh with labels //pass the cell array with labels to point array vtkSmartPointer<vtkCellDataToPointData> c2pdata = vtkSmartPointer<vtkCellDataToPointData>::New(); c2pdata->SetInputData(surfmesh); c2pdata->PassCellDataOn(); c2pdata->Update(); auto pscalars = c2pdata->GetOutput()->GetPointData()->GetArray(array_name); //to store ids with the tetra mesh points vtkSmartPointer<vtkShortArray> volmesh_regions = vtkSmartPointer<vtkShortArray>::New(); volmesh_regions->SetName(array_name); volmesh_regions->SetNumberOfComponents(1); volmesh_regions->SetNumberOfValues(volmesh->GetNumberOfPoints()); //fill the array of scalars to store with volumetric mesh for(vtkIdType i=0; i<volmesh->GetNumberOfPoints();i++) { volmesh_regions->SetTuple1(i,0); } //for every cell of the surface mesh for(vtkIdType i=0; i<surfmesh->GetNumberOfPoints(); i++) { vtkIdType ptid = ptloc->FindClosestPoint(surfmesh->GetPoint(i)); volmesh_regions->SetTuple1(ptid, pscalars->GetTuple1(i)); } volmesh->GetPointData()->AddArray(volmesh_regions); //:~ create PointData array in the volumetric mesh with labels } std::vector<BscEntry> labeldata; //create std::vector with information about the cell and point ids for every label //for every cell of the surface mesh std::cout<<"Looking for boundaries"<<std::endl; for(vtkIdType i=0; i<surfmesh->GetNumberOfCells(); i++) { if( i%10000 == 0 ) std::cout<<"Cell "<<i<<"/"<<surfmesh->GetNumberOfCells()<<"\r"<<std::flush; vtkCell* cell = surfmesh->GetCell(i); BscEntry entry; //if( cell->GetNumberOfPoints()!=3 ) //{ // std::cout<<"Face does not have 3 vertices. Id= "<<i<<std::endl; // continue; //} entry.id = scalars->GetTuple1(i); entry.pt1 = ptloc->FindClosestPoint(cell->GetPoints()->GetPoint(0)); entry.pt2 = ptloc->FindClosestPoint(cell->GetPoints()->GetPoint(1)); entry.pt3 = ptloc->FindClosestPoint(cell->GetPoints()->GetPoint(2)); if( cell->GetNumberOfPoints()==4 ) { entry.pt4 = ptloc->FindClosestPoint(cell->GetPoints()->GetPoint(3)); entry.nvertices=4; } else if(cell->GetNumberOfPoints()==3) { entry.nvertices=3; } else { cout<<"cell "<<i<<" has "<<cell->GetNumberOfPoints()<<" vertices, it is unsupported"<<endl; exit(-1); } double pt1[3]; double pt2[3]; double pt3[3]; double pt4[3]; volmesh->GetPoint(entry.pt1, pt1); volmesh->GetPoint(entry.pt2, pt2); volmesh->GetPoint(entry.pt3, pt3); if( entry.nvertices==4 ) { volmesh->GetPoint(entry.pt4, pt4); } else { pt4[0]=0; pt4[1]=0; pt4[2]=0; } double c[3]; c[0] = (pt1[0]+pt2[0]+pt3[0]+pt4[0])/entry.nvertices; c[1] = (pt1[1]+pt2[1]+pt3[1]+pt4[1])/entry.nvertices; c[2] = (pt1[2]+pt2[2]+pt3[2]+pt4[2])/entry.nvertices; vtkIdType cellid = cellloc->FindCell(c); if(cellid==-1) { std::cout<<"Cell not found. Look for an error. Closest point:"<<c[0]<<" "<<c[1]<<" "<<c[2]<<" "<<std::endl; } entry.tet_id = cellid; labeldata.push_back(entry); } std::cout<<std::endl; //to store labels for cells vtkSmartPointer<vtkShortArray> volmesh_regions_cells = vtkSmartPointer<vtkShortArray>::New(); volmesh_regions_cells->SetName(array_name); volmesh_regions_cells->SetNumberOfComponents(1); volmesh_regions_cells->SetNumberOfValues(volmesh->GetNumberOfCells()); for(vtkIdType i1=0; i1<volmesh->GetNumberOfCells(); i1++) { volmesh_regions_cells->SetTuple1(i1,0); //reset } //store the labels std::ofstream file(outfile); for(vtkIdType i=0; i<labeldata.size(); i++) { BscEntry entry = labeldata[i]; file<<entry.id<<" "<< entry.pt1+1<<" "<< entry.pt2+1<<" "<< entry.pt3+1<<" "; if( entry.nvertices==4 ) file<<entry.pt4+1<<" "; file<<entry.tet_id+1<<LINEBREAK; if(volmeshout!=NULL) { volmesh_regions_cells->SetTuple1(entry.tet_id, entry.id); } } //store the labels 1 std::ofstream file1((std::string(outfile)+".1").c_str()); for(vtkIdType i=0; i<labeldata.size(); i++) { BscEntry entry = labeldata[i]; file1<<i+1<<" "<<entry.id<<endl; } if(volmeshout!=NULL) { volmesh->GetCellData()->AddArray(volmesh_regions_cells); if(vtkoutput_mesh) { vtkSmartPointer<vtkDataSetWriter> wrwr = vtkSmartPointer<vtkDataSetWriter>::New(); CommonTools::AssociateProgressFunction(wrwr); wrwr->SetFileTypeToBinary(); wrwr->SetFileName(volmeshout); wrwr->SetInputData(volmesh); wrwr->Update(); } else if(alyaoutput_mesh) { std::cout<<"Writing alya format"<<std::endl; CommonTools::SaveVolMeshBSC(volmesh, volmeshout, scale, correct_orientation); //add the boundary char boundary_file[256]; char boundary_elemtype_file[256]; sprintf(boundary_file, "%s.bound", volmeshout); sprintf(boundary_elemtype_file, "%s.bound_type", volmeshout); std::ofstream file(boundary_file); std::ofstream file_elemtype(boundary_elemtype_file); for(vtkIdType i=0; i<labeldata.size(); i++) { BscEntry entry = labeldata[i]; file<<i+1<<" "<< entry.pt1+1<<" "<< entry.pt2+1<<" "<< entry.pt3+1<<" "; if( entry.nvertices==4 ) file<<entry.pt4+1; file<<LINEBREAK; file_elemtype<<i+1<<" "<<entry.nvertices<<LINEBREAK; } } else //Write elmer mesh { std::cout<<"Writing elmer file"<<std::endl; std::string header_filename = "mesh.header"; std::ofstream header_file(header_filename.c_str()); header_file<<volmesh->GetNumberOfPoints()<<" "<<volmesh->GetNumberOfCells()<<" "<<labeldata.size()<<std::endl; header_file<<"2"<<std::endl; header_file<<"303 "<<labeldata.size()<<std::endl; header_file<<"504 "<<volmesh->GetNumberOfCells()<<std::endl; std::string node_filename = "mesh.nodes"; std::ofstream node_file(node_filename.c_str()); for(vtkIdType i=0; i<volmesh->GetNumberOfPoints(); i++) { double* pt = volmesh->GetPoint(i); node_file<<i+1<<" -1 "<<pt[0]<<" "<<pt[1]<<" "<<pt[2]<<std::endl; } std::string ele_filename = "mesh.elements"; std::ofstream ele_file(ele_filename.c_str()); for(vtkIdType i=0; i<volmesh->GetNumberOfCells(); i++) { vtkCell* cell = volmesh->GetCell(i); ele_file<<i+1<<" 1 504"; for(int k=0; k<cell->GetNumberOfPoints(); k++) ele_file<<" "<<cell->GetPointId(k)+1; ele_file<<std::endl; } std::string bound_filename = "mesh.boundary"; std::ofstream bound_file(bound_filename.c_str()); for(vtkIdType i=0; i<labeldata.size(); i++) { BscEntry entry = labeldata[i]; bound_file<<i+1<<" "<< entry.id<<" "<< entry.tet_id+1<<" 0 303 "<< entry.pt1+1<<" "<< entry.pt2+1<<" "<< entry.pt3+1; if( entry.nvertices==4 ) bound_file<<" "<<entry.pt4+1; bound_file<<std::endl; } } } return 0; }