From 2971da18bf0a2d17dc0b4f903689f4739147d65a Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Fri, 8 Oct 2004 02:41:56 +0000
Subject: [PATCH] A small utility that reads a Gmsh mesh file and makes the
 numbering dense (without gaps in the node/element number sequences)

---
 utils/misc/mshdensify.cpp | 267 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 267 insertions(+)
 create mode 100644 utils/misc/mshdensify.cpp

diff --git a/utils/misc/mshdensify.cpp b/utils/misc/mshdensify.cpp
new file mode 100644
index 0000000000..b6c971c360
--- /dev/null
+++ b/utils/misc/mshdensify.cpp
@@ -0,0 +1,267 @@
+// $Id: mshdensify.cpp,v 1.1 2004-10-08 02:41:56 geuzaine Exp $
+//
+// Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+// USA.
+// 
+// Please report all bugs and problems to <gmsh@geuz.org>.
+
+// A small utility that reads a Gmsh mesh file and makes the numbering
+// dense (without gaps in the node/element number sequences)
+
+#include <stdio.h>
+#include <strings.h>
+#include <vector>
+#include <map>
+
+using namespace std;
+
+int getNumNodes(int type)
+{
+  switch (type) {
+  case 15: return 1;              // point
+  case 1 : return 2;              // line 1
+  case 8 : return 2 + 1;          // line 2
+  case 2 : return 3;              // triangle 1
+  case 9 : return 3 + 3;          // triangle 2
+  case 3 : return 4;              // quadrangle 1
+  case 10: return 4 + 4 + 1;      // quadrangle 2
+  case 4 : return 4;              // tetrahedron 1
+  case 11: return 4 + 6;          // tetrahedron 2
+  case 5 : return 8;              // hexahedron 1
+  case 12: return 8 + 12 + 6 + 1; // hexahedron 2 
+  case 6 : return 6;              // prism 1
+  case 13: return 6 + 9 + 3;      // prism 2
+  case 7 : return 5;              // pyramid 1
+  case 14: return 5 + 8 + 1;      // pyramid 2
+  default: return 0;
+  }
+}
+
+class node{
+ private:
+  int _num;
+  double _x, _y, _z;
+ public:
+  node(double x, double y, double z) 
+    : _num(0), _x(x), _y(y), _z(z) {}
+  void setNum(int num){ _num = num; }
+  int getNum(){ return _num; }
+  void print(double version){
+    fprintf(stdout, "%d %.16g %.16g %.16g\n", _num, _x, _y, _z);
+  }
+};
+
+class element{
+ private:
+  int _num, _type, _physical, _elementary, _partition;
+  vector<node*> _nodes;
+ public:
+  element(int type, int physical, int elementary, int partition) 
+    : _num(0), _type(type), _physical(physical), _elementary(elementary),
+      _partition(partition) {}
+  void setNum(int num){ _num = num; }
+  void addNode(node *n){ _nodes.push_back(n); }
+  void print(double version){
+    if(version == 2.0)
+      fprintf(stdout, "%d %d 3 %d %d %d", _num, _type, _physical, 
+	      _elementary, _partition);
+    else
+      fprintf(stdout, "%d %d %d %d %d", _num, _type, _physical,
+	      _elementary, (int)_nodes.size());
+    for(unsigned int i = 0; i < _nodes.size(); i++)
+      fprintf(stdout, " %d", _nodes[i]->getNum());
+    fprintf(stdout, "\n");
+  }
+};
+
+double readMesh(char *fileName, map<int, node*> &nodes, vector<element*> &elements)
+{
+  FILE *fp = fopen(fileName, "r");
+
+  if(!fp){
+    fprintf(stderr, "Error: Unable to open file '%s'\n", fileName);
+    exit(1);
+  }
+
+  double version = 1.0;
+
+  while(1) {
+    char str[256];
+    do {
+      fgets(str, sizeof(str), fp);
+      if(feof(fp))
+        break;
+    } while(str[0] != '$');
+    
+    if(feof(fp))
+      break;
+
+    if(!strncmp(&str[1], "MeshFormat", 10)) {
+      int format, size;
+      fscanf(fp, "%lf %d %d\n", &version, &format, &size);
+      if(version != 2.0){
+	fprintf(stderr, "Error: Wrong msh file version %g\n", version);
+	exit(1);
+      }
+      if(format){
+        fprintf(stderr, "Error: Unknown data format for mesh\n");
+        exit(1);
+      }
+    }
+    else if(!strncmp(&str[1], "NOD", 3) ||
+	    !strncmp(&str[1], "NOE", 3) ||
+	    !strncmp(&str[1], "Nodes", 5)) {
+      int numNodes;
+      fscanf(fp, "%d", &numNodes);
+      for(int i = 0; i < numNodes; i++) {
+	int num;
+	double x, y, z;
+        fscanf(fp, "%d %lf %lf %lf", &num, &x, &y, &z);
+	if(nodes.count(num)){
+	  fprintf(stderr, "Error: node %d already exists\n", num);
+	  exit(1);
+	}
+	else{
+	  node *n = new node(x, y, z);
+	  nodes[num] = n;
+	}
+      }
+    }
+    else if(!strncmp(&str[1], "ELM", 3) ||
+	    !strncmp(&str[1], "Elements", 8)) {
+      int numElements;
+      fscanf(fp, "%d", &numElements);
+      for(int i = 0; i < numElements; i++) {
+	int num, type, physical, elementary, partition = 0, numNodes, numTags;
+	if(version <= 1.0){
+	  fscanf(fp, "%d %d %d %d %d",
+		 &num, &type, &physical, &elementary, &numNodes);
+	  int numNodesCheck = getNumNodes(type);
+	  if(!numNodesCheck){
+	    fprintf(stderr, "Error: Unknown type %d for element %d\n", type, num); 
+	    exit(1);
+	  }
+	  if(numNodes != numNodesCheck){
+	    fprintf(stderr, "Error: Wrong number of nodes for element %d\n", num);
+	    exit(1);
+	  }
+	}
+	else{
+	  fscanf(fp, "%d %d %d", &num, &type, &numTags);
+	  elementary = physical = partition = 1;
+	  for(int j = 0; j < numTags; j++){
+	    int tag;
+	    fscanf(fp, "%d", &tag);	    
+	    if(j == 0)
+	      physical = tag;
+	    else if(j == 1)
+	      elementary = tag;
+	    else if(j == 2)
+	      partition = tag;
+	    // ignore any other tags for now
+	  }
+	  numNodes = getNumNodes(type);
+	  if(!numNodes){
+	    fprintf(stderr, "Error: Unknown type %d for element %d\n", type, num); 
+	    exit(1);
+	  }
+	}
+	element *e = new element(type, elementary, physical, partition);
+        for(int j = 0; j < numNodes; j++){
+	  int numNode;
+          fscanf(fp, "%d", &numNode);
+	  if(nodes.count(numNode)){
+	    e->addNode(nodes[numNode]);
+	  }
+	  else{
+            fprintf(stderr, "Error: Unknown vertex %d in element %d\n", numNode,  num);
+	    exit(1);
+	  }
+	}
+	elements.push_back(e);
+      }
+    }
+
+    do {
+      fgets(str, sizeof(str), fp);
+      if(feof(fp)){
+        fprintf(stderr, "Error: Prematured end of mesh file\n");
+	exit(1);
+      }
+    } while(str[0] != '$');
+    
+  }
+
+  fclose(fp);
+
+  return version;
+}
+
+void printMesh(double version, map<int, node*> nodes, vector<element*> elements)
+{
+  map<int, node*>::const_iterator it = nodes.begin();
+  map<int, node*>::const_iterator ite = nodes.end();
+
+  if(version == 2.0){
+    fprintf(stdout, "$MeshFormat\n");
+    fprintf(stdout, "2.0 0 %d\n", sizeof(double));
+    fprintf(stdout, "$EndMeshFormat\n");
+    fprintf(stdout, "$Nodes\n");
+  }
+  else
+    fprintf(stdout, "$NOD\n");
+  fprintf(stdout, "%d\n", (int)nodes.size());
+
+  int index = 1;
+  for(;it!=ite;++it){
+    it->second->setNum(index++);
+    it->second->print(version);
+  }
+
+  if(version == 2.0){
+    fprintf(stdout, "$EndNodes\n");
+    fprintf(stdout, "$Elements\n");
+  }
+  else{
+    fprintf(stdout, "$ENDNOD\n");
+    fprintf(stdout, "$ELM\n");
+  }
+  fprintf(stdout, "%d\n", (int)elements.size());
+
+  for(unsigned int i = 0; i < elements.size(); i++){
+    elements[i]->setNum(i+1);
+    elements[i]->print(version);
+  }
+
+  if(version == 2.0)
+    fprintf(stdout, "$EndElements\n");
+  else
+    fprintf(stdout, "$ENDELM\n");
+}
+
+int main(int argc, char **argv)
+{
+  if(argc != 2){
+    fprintf(stderr, "Usage: %s file\n", argv[0]);
+    exit(1);
+  }
+
+  map<int, node*> nodes;
+  vector<element*> elements;
+  double version = readMesh(argv[1], nodes, elements);
+  printMesh(version, nodes, elements);
+}
-- 
GitLab