1 // Gmsh - Copyright (C) 1997-2021 C. Geuzaine, J.-F. Remacle
2 //
3 // See the LICENSE.txt file in the Gmsh root directory for license information.
4 // Please report all issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
5 
6 #include <stdio.h>
7 #include <string>
8 #include "GModel.h"
9 #include "MTriangle.h"
10 #include "MQuadrangle.h"
11 #include "OS.h"
12 #include "discreteFace.h"
13 
readOFF(const std::string & name)14 int GModel::readOFF(const std::string &name)
15 {
16   FILE *fp = Fopen(name.c_str(), "r");
17   if(!fp) {
18     Msg::Error("Unable to open file '%s'", name.c_str());
19     return 0;
20   }
21 
22   int numVertices, numFaces, numEdges;
23   if(fscanf(fp, "OFF %d %d %d", &numVertices, &numFaces, &numEdges) != 3) {
24     Msg::Error("Invalid OFF header");
25     return 0;
26   }
27 
28   if(!numVertices || !numFaces) {
29     Msg::Info("Empty OFF mesh");
30     return 1;
31   }
32 
33   GFace *gf = new discreteFace(this, getMaxElementaryNumber(2) + 1);
34   add(gf);
35 
36   std::vector<MVertex*> vertices(numVertices);
37   for(int i = 0; i < numVertices; i++) {
38     double x, y, z;
39     if(fscanf(fp, "%lf %lf %lf", &x, &y, &z) != 3) {
40       Msg::Error("Could not read vertex");
41       return 0;
42     }
43     vertices[i] = new MVertex(x, y, z, gf);
44   }
45 
46   for(int i = 0; i < numFaces; i++) {
47     int n;
48     if(fscanf(fp, "%d", &n) != 1) {
49       Msg::Error("Could not read face");
50     }
51     int v[4] = {-1, -1, -1, -1};
52     if(n == 3) {
53       if(fscanf(fp, "%d %d %d", &v[0], &v[1], &v[2]) != 3) {
54         Msg::Error("Could not read face");
55         return 0;
56       }
57       gf->triangles.push_back(new MTriangle(vertices[v[0]], vertices[v[1]],
58                                             vertices[v[2]]));
59     }
60     else if(n == 4) {
61       if(fscanf(fp, "%d %d %d %d", &v[0], &v[1], &v[2], &v[3]) != 4) {
62         Msg::Error("Could not read face");
63         return 0;
64       }
65       gf->quadrangles.push_back(new MQuadrangle(vertices[v[0]], vertices[v[1]],
66                                                 vertices[v[2]], vertices[v[3]]));
67     }
68     else{
69       char buffer[4096];
70       if(!fgets(buffer, sizeof(buffer), fp))
71         Msg::Error("Could not read line");
72       Msg::Warning("Ignoring %d-node face", n);
73       continue;
74     }
75   }
76 
77   _associateEntityWithMeshVertices();
78   _storeVerticesInEntities(vertices); // will delete unused vertices
79   fclose(fp);
80   return 1;
81 }
82 
writeOFF(const std::string & name,bool saveAll,double scalingFactor)83 int GModel::writeOFF(const std::string &name, bool saveAll, double scalingFactor)
84 {
85   FILE *fp = Fopen(name.c_str(), "w");
86   if(!fp) {
87     Msg::Error("Unable to open file '%s'", name.c_str());
88     return 0;
89   }
90 
91   if(noPhysicalGroups()) saveAll = true;
92   int numVertices = indexMeshVertices(saveAll);
93   int numFaces = 0;
94   for(auto it = faces.begin(); it != faces.end(); ++it) {
95     GFace *gf = *it;
96     if(saveAll || gf->physicals.size())
97       numFaces += gf->getNumMeshElements();
98   }
99 
100   fprintf(fp, "OFF %d %d 0\n", numVertices, numFaces);
101 
102   std::vector<GEntity *> entities;
103   getEntities(entities);
104   for(std::size_t i = 0; i < entities.size(); i++)
105     for(std::size_t j = 0; j < entities[i]->mesh_vertices.size(); j++)
106       entities[i]->mesh_vertices[j]->writeOFF(fp, scalingFactor);
107 
108   for(auto it = faces.begin(); it != faces.end(); ++it) {
109     GFace *gf = *it;
110     if(saveAll || gf->physicals.size()) {
111       for(std::size_t i = 0; i < gf->triangles.size(); i++)
112         fprintf(fp, "3 %d %d %d\n",
113                 (int)gf->triangles[i]->getVertex(0)->getIndex() - 1,
114                 (int)gf->triangles[i]->getVertex(1)->getIndex() - 1,
115                 (int)gf->triangles[i]->getVertex(2)->getIndex() - 1);
116       for(std::size_t i = 0; i < gf->quadrangles.size(); i++)
117         fprintf(fp, "4 %d %d %d %d\n",
118                 (int)gf->triangles[i]->getVertex(0)->getIndex() - 1,
119                 (int)gf->triangles[i]->getVertex(1)->getIndex() - 1,
120                 (int)gf->triangles[i]->getVertex(2)->getIndex() - 1,
121                 (int)gf->triangles[i]->getVertex(3)->getIndex() - 1);
122     }
123   }
124 
125   fclose(fp);
126   return 1;
127 }
128