00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <sofa/helper/io/MeshTopologyLoader.h>
00028 #include <sofa/helper/io/Mesh.h>
00029 #include <sofa/helper/system/FileRepository.h>
00030 #include <sofa/defaulttype/Vec.h>
00031
00032 #include <iostream>
00033 #include <vector>
00034 #include <string>
00035 #include <cstring>
00036
00037 #include <set>
00038
00039 namespace sofa
00040 {
00041
00042 namespace helper
00043 {
00044
00045 namespace io
00046 {
00047
00048 using namespace sofa::defaulttype;
00049
00050 static void skipToEOL(FILE* f)
00051 {
00052 int ch;
00053 while ((ch = fgetc(f)) != EOF && ch != '\n') ;
00054 }
00055
00056 static bool readLine(char* buf, int size, FILE* f)
00057 {
00058 buf[0] = '\0';
00059 if (fgets(buf, size, f) == NULL)
00060 return false;
00061 if ((int)strlen(buf)==size-1 && buf[size-1] != '\n')
00062 skipToEOL(f);
00063 return true;
00064 }
00065
00066 bool MeshTopologyLoader::loadObj(const char *filename)
00067 {
00068 helper::io::Mesh* mesh = helper::io::Mesh::Create(filename);
00069 if (mesh==NULL)
00070 return false;
00071
00072 setNbPoints(mesh->getVertices().size());
00073 for (unsigned int i=0; i<mesh->getVertices().size(); i++)
00074 {
00075 addPoint((double)mesh->getVertices()[i][0],
00076 (double)mesh->getVertices()[i][1],
00077 (double)mesh->getVertices()[i][2]);
00078 }
00079
00080 const vector< vector < vector <int> > > & facets = mesh->getFacets();
00081 for (unsigned int i=0; i<facets.size(); i++)
00082 {
00083 const vector<int>& facet = facets[i][0];
00084 if (facet.size()==2)
00085 {
00086 if (facet[0]<facet[1])
00087 addLine(facet[0],facet[1]);
00088 else
00089 addLine(facet[1],facet[0]);
00090 }
00091 else if (facet.size()==4)
00092 {
00093 addQuad(facet[0],facet[1],facet[2],facet[3]);
00094 }
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 else
00105 {
00106 for (unsigned int j=2; j<facet.size(); j++)
00107 addTriangle(facet[0],facet[j-1],facet[j]);
00108 }
00109
00110 std::set< std::pair<int,int> > edges;
00111
00112 if (facet.size()>2)
00113 {
00114 for (unsigned int j=0; j<facet.size(); j++)
00115 {
00116 int i1 = facet[j];
00117 int i2 = facet[(j+1)%facet.size()];
00118 if (edges.count(std::make_pair(i1,i2))!=0)
00119 {
00120
00121 }
00122 else if (edges.count(std::make_pair(i2,i1))==0)
00123 {
00124 if (i1>i2)
00125 addLine(i1,i2);
00126 else
00127 addLine(i2,i1);
00128 edges.insert(std::make_pair(i1,i2));
00129 }
00130 }
00131 }
00132 }
00133
00134 delete mesh;
00135 return true;
00136 }
00137
00138 bool MeshTopologyLoader::loadGmsh(FILE *file, const int gmshFormat)
00139 {
00140 char cmd[1024];
00141 int npoints = 0;
00142 int nlines = 0;
00143 int ntris = 0;
00144 int nquads = 0;
00145 int ntetras = 0;
00146 int ncubes = 0;
00147
00148
00149 fscanf(file, "%d\n", &npoints);
00150 setNbPoints(npoints);
00151 std::vector<int> pmap;
00152 for (int i=0; i<npoints; ++i)
00153 {
00154 int index = i;
00155 double x,y,z;
00156 fscanf(file, "%d %lf %lf %lf\n", &index, &x, &y, &z);
00157 addPoint(x, y, z);
00158 if ((int)pmap.size() <= index) pmap.resize(index+1);
00159 pmap[index] = i;
00160
00161 }
00162
00163 readLine(cmd, sizeof(cmd), file);
00164
00165 if (strncmp(cmd,"$ENDNOD",7) && strncmp(cmd,"$EndNodes",9))
00166 {
00167 std::cerr << "'$ENDNOD' or '$EndNodes' expected, found '" << cmd << "'" << std::endl;
00168 fclose(file);
00169 return false;
00170 }
00171
00172 readLine(cmd, sizeof(cmd), file);
00173
00174 if (strncmp(cmd,"$ELM",4) && strncmp(cmd,"$Elements",9))
00175 {
00176 std::cerr << "'$ELM' or '$Elements' expected, found '" << cmd << "'" << std::endl;
00177 fclose(file);
00178 return false;
00179 }
00180
00181 int nelems = 0;
00182 fscanf(file, "%d\n", &nelems);
00183 for (int i=0; i<nelems; ++i)
00184 {
00185 int index, etype, rphys, relem, nnodes, ntags, tag;
00186 if (gmshFormat==1)
00187 {
00188
00189
00190 fscanf(file, "%d %d %d %d %d", &index, &etype, &rphys, &relem, &nnodes);
00191 }
00192 else if (gmshFormat == 2)
00193 {
00194
00195
00196 fscanf(file, "%d %d %d", &index, &etype, &ntags);
00197 for (int t=0; t<ntags; t++)
00198 fscanf(file, "%d", &tag);
00199
00200 switch (etype)
00201 {
00202 case 1:
00203 nnodes = 2;
00204 break;
00205 case 2:
00206 nnodes = 3;
00207 break;
00208 case 3:
00209 nnodes = 4;
00210 break;
00211 case 4:
00212 nnodes = 4;
00213 break;
00214 case 5:
00215 nnodes = 8;
00216 break;
00217 default:
00218 std::cerr << "Elements of type 1, 2, 3, 4, 5, or 6 expected. Element of type " << etype << " found." << std::endl;
00219
00220
00221 nnodes = 0;
00222 }
00223 }
00224
00225 std::vector<int> nodes;
00226 nodes.resize(nnodes);
00227 for (int n=0; n<nnodes; ++n)
00228 {
00229 int t = 0;
00230 fscanf(file, "%d",&t);
00231 nodes[n] = (((unsigned int)t)<pmap.size())?pmap[t]:0;
00232
00233 }
00234 switch (etype)
00235 {
00236 case 1:
00237 addLine(nodes[0], nodes[1]);
00238 ++nlines;
00239 break;
00240 case 2:
00241 addTriangle(nodes[0], nodes[1], nodes[2]);
00242
00243 ++ntris;
00244 break;
00245 case 3:
00246 addQuad(nodes[0], nodes[1], nodes[2], nodes[3]);
00247 ++nquads;
00248 break;
00249 case 4:
00250 addTetra(nodes[0], nodes[1], nodes[2], nodes[3]);
00251 ++ntetras;
00252 break;
00253 case 5:
00254 addCube(nodes[0], nodes[1], nodes[2], nodes[3],nodes[4], nodes[5], nodes[6], nodes[7]);
00255 ++ncubes;
00256 break;
00257 }
00258 skipToEOL(file);
00259 }
00260 readLine(cmd, sizeof(cmd), file);
00261 if (strncmp(cmd,"$ENDELM",7) && strncmp(cmd,"$EndElements",12))
00262 {
00263 std::cerr << "'$ENDELM' or '$EndElements' expected, found '" << cmd << "'" << std::endl;
00264 fclose(file);
00265 return false;
00266 }
00267 else
00268 {
00269
00270 }
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280 return true;
00281 }
00282
00283 bool MeshTopologyLoader::loadXsp(FILE *file, bool vector_spring)
00284 {
00285 char cmd[1024];
00286 int npoints = 0;
00287 int nlines = 0;
00288
00289
00290
00291
00292
00293 int totalNumMasses;
00294 int totalNumSprings;
00295
00296
00297
00298
00299 if (fscanf(file, "%s", cmd) != EOF && !strcmp(cmd,"numm"))
00300 {
00301 fscanf(file, "%d", &totalNumMasses);
00302 setNbPoints(totalNumMasses);
00303 npoints=totalNumMasses;
00304 }
00305
00306 if (fscanf(file, "%s", cmd) != EOF && !strcmp(cmd,"nums"))
00307 {
00308 fscanf(file, "%d", &totalNumSprings);
00309 setNbLines(totalNumSprings);
00310 nlines=totalNumSprings;
00311
00312 }
00313
00314
00315
00316 while (fscanf(file, "%s", cmd) != EOF)
00317 {
00318 if (!strcmp(cmd,"mass"))
00319 {
00320 int index;
00321 char location;
00322 double px,py,pz,vx,vy,vz,mass=0.0,elastic=0.0;
00323 bool fixed=false;
00324 fscanf(file, "%d %c %lf %lf %lf %lf %lf %lf %lf %lf\n",
00325 &index, &location,
00326 &px, &py, &pz, &vx, &vy, &vz,
00327 &mass, &elastic);
00328
00329 if (mass < 0)
00330 {
00331
00332 mass = -mass;
00333 fixed = true;
00334 }
00335 addPoint(px,py,pz);
00336 }
00337 else if (!strcmp(cmd,"lspg"))
00338 {
00339 int index;
00340 int m1,m2;
00341 double ks=0.0,kd=0.0,initpos=-1;
00342 double restx=0.0,resty=0.0,restz=0.0;
00343 if (vector_spring)
00344 fscanf(file, "%d %d %d %lf %lf %lf %lf %lf %lf\n",
00345 &index,&m1,&m2,&ks,&kd,&initpos, &restx,&resty,&restz);
00346 else
00347 fscanf(file, "%d %d %d %lf %lf %lf\n",
00348 &index,&m1,&m2,&ks,&kd,&initpos);
00349 --m1;
00350 --m2;
00351
00352 addLine(m1,m2);
00353 }
00354 else if (!strcmp(cmd,"grav"))
00355 {
00356 double gx,gy,gz;
00357 fscanf(file, "%lf %lf %lf\n", &gx, &gy, &gz);
00358 }
00359 else if (!strcmp(cmd,"visc"))
00360 {
00361 double viscosity;
00362 fscanf(file, "%lf\n", &viscosity);
00363 }
00364 else if (!strcmp(cmd,"step"))
00365 {
00366
00367 skipToEOL(file);
00368 }
00369 else if (!strcmp(cmd,"frce"))
00370 {
00371 skipToEOL(file);
00372 }
00373 else if (cmd[0] == '#')
00374 {
00375 skipToEOL(file);
00376 }
00377 else
00378 {
00379 printf("Unknown MassSpring keyword: %s\n", cmd);
00380 skipToEOL(file);
00381 return false;
00382 }
00383 }
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393 return true;
00394 }
00395
00396 bool MeshTopologyLoader::loadMesh(FILE *file)
00397 {
00398 char cmd[1024];
00399 int npoints = 0;
00400 int nlines = 0;
00401 int ntris = 0;
00402 int nquads = 0;
00403 int ntetras = 0;
00404 int ncubes = 0;
00405
00406
00407 while (fscanf(file, "%s", cmd) != EOF)
00408 {
00409 if (!strcmp(cmd,"line"))
00410 {
00411 int p1,p2;
00412 fscanf(file, "%d %d\n",
00413 &p1, &p2);
00414 addLine(p1, p2);
00415 ++nlines;
00416 }
00417 else if (!strcmp(cmd,"triangle"))
00418 {
00419 int p1,p2,p3;
00420 fscanf(file, "%d %d %d\n",
00421 &p1, &p2, &p3);
00422 addTriangle(p1, p2, p3);
00423 ++ntris;
00424 }
00425 else if (!strcmp(cmd,"quad"))
00426 {
00427 int p1,p2,p3,p4;
00428 fscanf(file, "%d %d %d %d\n",
00429 &p1, &p2, &p3, &p4);
00430 addQuad(p1, p2, p3, p4);
00431 ++nquads;
00432 }
00433 else if (!strcmp(cmd,"tetra"))
00434 {
00435 int p1,p2,p3,p4;
00436 fscanf(file, "%d %d %d %d\n",
00437 &p1, &p2, &p3, &p4);
00438 addTetra(p1, p2, p3, p4);
00439 ++ntetras;
00440 }
00441 else if (!strcmp(cmd,"cube"))
00442 {
00443 int p1,p2,p3,p4,p5,p6,p7,p8;
00444 fscanf(file, "%d %d %d %d %d %d %d %d\n",
00445 &p1, &p2, &p3, &p4, &p5, &p6, &p7, &p8);
00446 addCube(p1, p2, p3, p4, p5, p6, p7, p8);
00447 ++ncubes;
00448 }
00449 else if (!strcmp(cmd,"point"))
00450 {
00451 double px,py,pz;
00452 fscanf(file, "%lf %lf %lf\n",
00453 &px, &py, &pz);
00454 addPoint(px, py, pz);
00455 ++npoints;
00456 }
00457 else if (!strcmp(cmd,"v"))
00458 {
00459 double px,py,pz;
00460 fscanf(file, "%lf %lf %lf\n",
00461 &px, &py, &pz);
00462 addPoint(px, py, pz);
00463 ++npoints;
00464 }
00465 else if (!strcmp(cmd,"f"))
00466 {
00467 int p1,p2,p3,p4=0;
00468 fscanf(file, "%d %d %d %d\n",
00469 &p1, &p2, &p3, &p4);
00470 if (p4)
00471 {
00472 addQuad(p1-1, p2-1, p3-1, p4-1);
00473 ++nquads;
00474 }
00475 else
00476 {
00477 addTriangle(p1-1, p2-1, p3-1);
00478 ++ntris;
00479 }
00480 }
00481 else if (!strcmp(cmd,"mass"))
00482 {
00483 int index;
00484 char location;
00485 double px,py,pz,vx,vy,vz,mass=0.0,elastic=0.0;
00486 fscanf(file, "%d %c %lf %lf %lf %lf %lf %lf %lf %lf\n",
00487 &index, &location,
00488 &px, &py, &pz, &vx, &vy, &vz,
00489 &mass, &elastic);
00490 addPoint(px, py, pz);
00491 ++npoints;
00492 }
00493 else if (!strcmp(cmd,"lspg"))
00494 {
00495 int index;
00496 int m1,m2;
00497 double ks=0.0,kd=0.0,initpos=-1;
00498 fscanf(file, "%d %d %d %lf %lf %lf\n", &index,
00499 &m1,&m2,&ks,&kd,&initpos);
00500 --m1;
00501 --m2;
00502 addLine(m1,m2);
00503 ++nlines;
00504 }
00505 else if (cmd[0] == '#')
00506 {
00507 skipToEOL(file);
00508 }
00509 else
00510 {
00511 printf("Unknown Mesh keyword: %s\n", cmd);
00512 skipToEOL(file);
00513 return false;
00514 }
00515 }
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525 return true;
00526 }
00527
00528 bool MeshTopologyLoader::loadMeshFile(const char *filename)
00529 {
00530 FILE* file;
00531 char cmd[1024];
00532 bool fileLoaded = false;
00533
00534 if ((file = fopen(filename, "r")) == NULL)
00535 {
00536 std::cout << "ERROR: cannot read file '" << filename << "'. Exiting..." << std::endl;
00537 return false;
00538 }
00539
00540
00541 if (!readLine(cmd, sizeof(cmd), file))
00542 {
00543 fclose(file);
00544 return false;
00545 }
00546
00547
00548
00549 int gmshFormat = 0;
00550 if (!strncmp(cmd,"$MeshFormat",11))
00551 {
00552 gmshFormat = 2;
00553
00554 readLine(cmd, sizeof(cmd), file);
00555 readLine(cmd, sizeof(cmd), file);
00556 if (strncmp(cmd,"$EndMeshFormat",14))
00557 {
00558 fclose(file);
00559 return false;
00560 }
00561 else
00562 readLine(cmd, sizeof(cmd), file);
00563 }
00564 else
00565 {
00566 gmshFormat = 1;
00567
00568 }
00569
00570 if (!strncmp(cmd,"$NOD",4) || !strncmp(cmd,"$Nodes",6))
00571 {
00572 fileLoaded = loadGmsh(file, gmshFormat);
00573 }
00574 else if (!strncmp(cmd,"Xsp",3))
00575 {
00576 float version = 0.0f;
00577 sscanf(cmd, "Xsp %f", &version);
00578
00579 if (version == 3.0)
00580 fileLoaded = loadXsp(file, false);
00581 else if (version == 4.0)
00582 fileLoaded = loadXsp(file, true);
00583 }
00584 else
00585 {
00586 fileLoaded = loadMesh(file);
00587 }
00588
00589 fclose(file);
00590 return fileLoaded;
00591 }
00592
00593 bool MeshTopologyLoader::load(const char *filename)
00594 {
00595 std::string fname(filename);
00596 if (!sofa::helper::system::DataRepository.findFile(fname))
00597 {
00598 printf("Cannot find file: %s \n", filename);
00599 return false;
00600 }
00601
00602 bool fileLoaded;
00603
00604 if ((strlen(filename)>4 && !strcmp(filename+strlen(filename)-4,".obj"))
00605 || (strlen(filename)>6 && !strcmp(filename+strlen(filename)-6,".trian")))
00606 {
00607 fileLoaded = loadObj(fname.c_str());
00608 }
00609 else
00610 fileLoaded = loadMeshFile(fname.c_str());
00611
00612 if(!fileLoaded)
00613 printf("Error loading mesh file: %s \n", fname.c_str());
00614
00615 return fileLoaded;
00616 }
00617
00618 }
00619
00620 }
00621
00622 }
00623