Programming tasks to Scientific Computing I
triangMesh.h
Go to the documentation of this file.
1 #ifndef __TRIANGMESH_H
2 #define __TRIANGMESH_H
3 
4 #include <aol.h>
5 
6 namespace shellFE
7 {
8 
9 template< typename DataTypeContainer, typename TriangleType >
11 {
12 public:
15  typedef typename DataTypeContainer::Point3DType Point3DType;
16  typedef typename DataTypeContainer::TangentVecType TangentVecType;
17  typedef typename DataTypeContainer::Indices3DType Indices3DType;
19  typedef typename DataTypeContainer::MaskType MaskType;
20 
21 protected:
22  std::vector< Point3DType > _vertexIterator;
23  std::vector< TriangleType > _triangIterator;
24  // ----
25  mutable std::vector< Indices3DType > _neighbour_;
26 
27 public:
30  : _vertexIterator(), _triangIterator()
31  {}
32 
33  TriangMesh(const string& fileName)
34  {
35  this->loadFromLegacyVTK ( fileName );
36  }
37 
38  virtual ~TriangMesh()
39  {}
40 
41 public:
42  int getNumVertices() const
43  {
44  return ( _vertexIterator.size() );
45  }
46  int getNumTriangs() const
47  {
48  return ( static_cast<int> ( _triangIterator.size() ) );
49  }
50 
52  int pushBackVertex(const Point3DType newVertex)
53  {
54  _vertexIterator.push_back(newVertex);
55  return getNumVertices() - 1;
56  }
57 
59  int pushBackTriang(const Indices3DType nodeIdx)
60  {
61  int globalIdx = getNumTriangs();
62  _triangIterator.push_back ( TriangleType( globalIdx, nodeIdx, _vertexIterator ) );
63  return globalIdx;
64  }
65 
66  const Point3DType& getVertex(const int num) const
67  {
68  return _vertexIterator[num];
69  }
70  void setVertex(const int num, const Point3DType Arg)
71  {
72  _vertexIterator[num] = Arg;
73  }
74 
76  int getNeighbour(const int elementID, const int acrossLocalEdge) const
77  {
78  return _neighbour_[elementID][acrossLocalEdge];
79  }
80 
82  void setNeighbour(const int elementID, const int acrossLocalEdge, const int value) const
83  {
84  _neighbour_[elementID][acrossLocalEdge] = value;
85  }
86 
87  const TriangleType& getTriang(const int num) const
88  {
89  return _triangIterator[num];
90  }
91 
94  TriangleType & getTriang(const int num)
95  {
96  return _triangIterator[num];
97  }
98 
99  void setTriang(const int num, const TriangleType Arg)
100  {
101  _triangIterator[num] = Arg;
102  }
103 
104  int getTriangNodeIdx(const int num, const int localNode) const
105  {
106  return _triangIterator[num].getGlobalNodeIdx(localNode);
107  }
108 
109  void setTriangNodeIdx(const int num, const int localNode, const int newIdx)
110  {
111  _triangIterator[num].setGlobalNodeIdx(localNode, newIdx );
112  }
113 
114  // refinement operations only update NodeIndex informations, hence have to update coords, edges of elements
116  {
117  for ( int elementIndex = 0; elementIndex < getNumTriangs(); ++elementIndex ) _triangIterator[elementIndex].updateNodesAndEdges( _vertexIterator );
118  }
119 
120  void print()
121  {
122  for ( int nodeIndex = 0; nodeIndex < getNumVertices(); ++nodeIndex ) {
123  cout << endl << "node = " << nodeIndex << endl;
124  }
125  for ( int elementIndex = 0; elementIndex < getNumTriangs(); ++elementIndex ) _triangIterator[elementIndex].print();
126  }
127 
128 public:
129 
131  void loadFromLegacyVTK(const string& filename)
132  {
133  /*std::ifstream vtkFile ( filename.c_str() ); */
134  std::ifstream vtkFile;
135  vtkFile.open ( filename.c_str() );
136  if ( vtkFile.fail() ) throw std::invalid_argument( aol::strprintf ( "Cannot open file. In File %s at line %d.", __FILE__, __LINE__ ).c_str() );
137  bool readVertices = false;
138  bool readFaces = false;
139  while ( !vtkFile.eof() ) {
140  char line[256];
141  vtkFile.getline ( line, 256 );
142  // first: expect vertices
143  if( !strncmp ( line, "POINTS ", strlen ( "POINTS " ) ) ) {
144  readVertices = true;
145  continue;
146  }
147  // second: expect triangles (i.e. starting with "3 " )
148  if( !strncmp ( line, "POLYGONS ", strlen ( "POLYGONS " ) ) ) {
149  readVertices = false;
150  readFaces = true;
151  continue;
152  }
153  // geometric information ends with the first line that does not start with "3 " anymore
154  if( readFaces && strncmp ( line, "3 ", strlen ( "3 " ) ) ) break;
155  // read in the vertex coordinates and add it to the mesh
156  if( readVertices ) {
157  Point3DType vertex;
158  char * substring = strtok ( line, " " );
159  for ( int i = 0; i < 3; i++ ) {
160  vertex[i] = atof( substring );
161  substring = strtok (NULL, " ");
162  }
163  pushBackVertex ( vertex );
164  }
165  // read in the face and add it to the mesh
166  if( readFaces ) {
167  Indices3DType triangle;
168  char * substring = strtok ( line, " " );
169  for ( int i = 0; i < 3; i++ ) {
170  substring = strtok (NULL, " ");
171  triangle[i] = atof( substring );
172  }
173  pushBackTriang( triangle );
174  }
175  }
176  vtkFile.close();
177  }
178 
179 
180  void makeNeighbour() const
181  {
182  int *n_to_t, *num_of_n, *start_of_n;
183  const int numNodes = getNumVertices();
184  const int numElements = getNumTriangs();
185 
186  if ( int(_neighbour_.size()) != numElements ) _neighbour_.resize ( numElements );
187 
188  n_to_t = new int[numElements*3];
189  num_of_n = new int[numNodes];
190  start_of_n = new int[numNodes+1];
191 
192  // iterate over all vertices and set num_of_n to zero, i.e. initialize
193  for ( int nodeIndex = 0; nodeIndex < numNodes; nodeIndex++ ) num_of_n[nodeIndex] = 0;
194 
195  // iterate over all triangles and all neighbours, i.e. 3, since every triangle has 3 neighbours for closed meshes
196  for ( int elementIndex = 0; elementIndex < numElements; elementIndex++ )
197  for ( int j = 0; j < 3; j++ ) {
198  num_of_n[getTriangNodeIdx ( elementIndex,j ) ]++;
199  setNeighbour ( elementIndex, j, -1 );
200  }
201 
202  // get Startindex for node
203  int nodeIdx = 0;
204  start_of_n[nodeIdx++] = 0;
205  while ( nodeIdx < numNodes ) {
206  start_of_n[nodeIdx] = start_of_n[nodeIdx-1] + num_of_n[nodeIdx-1];
207  nodeIdx++;
208  }
209  start_of_n[numNodes] = 3 * numElements;
210 
211  // initialize reference
212  for ( int elementIndex = 0; elementIndex < numElements*3; ++elementIndex ) n_to_t[elementIndex] = -1;
213 
214  // build reference
215  for ( int elementIndex = 0; elementIndex < numElements; elementIndex++ )
216  for ( int j = 0; j < 3; j++ ) {
217  int k = start_of_n[getTriangNodeIdx ( elementIndex,j ) ];
218  while ( n_to_t[k] > -1 ) k++;
219  n_to_t[k] = elementIndex;
220  }
221  // find neighbour
222  for ( int elementIndex = 0; elementIndex < numElements; elementIndex++ )
223  for ( int j = 0; j < 3; j++ ) {
224  int node1 = getTriangNodeIdx ( elementIndex, j );
225  int node2 = getTriangNodeIdx ( elementIndex, ( j + 1 ) % 3 );
226  int node3 = getTriangNodeIdx ( elementIndex, ( j + 2 ) % 3 );
227 
228  for ( int k = start_of_n[node1]; k < start_of_n[node1+1]; k++ ) {
229  int n = n_to_t[k]; // Tetraeder
230  if ( elementIndex < n ) // set neighborhood only once
231  for ( int l = 0; l < 3; l++ ) {
232  if ( node3 == getTriangNodeIdx ( n, l ) ) {
233  setNeighbour ( elementIndex, ( j + 1 ) % 3, n );
234  for ( int v = 0; v < 3; v++ )
235  if ( v != l && getTriangNodeIdx ( n, v ) != node1 ) setNeighbour ( n, v, elementIndex );
236  } else {
237  if ( node2 == getTriangNodeIdx ( n, l ) ) {
238  setNeighbour ( elementIndex, ( j + 2 ) % 3, n );
239  for ( int v = 0; v < 3; v++ )
240  if ( v != l && getTriangNodeIdx ( n, v ) != node1 ) setNeighbour ( n, v, elementIndex );
241  }
242  }
243  }
244  }
245  }
246 
247  delete[] n_to_t;
248  delete[] num_of_n;
249  delete[] start_of_n;
250  }
251 
253  {
254  if ( int(_neighbour_.size()) != this->getNumTriangs() )
255  makeNeighbour();
256  // true for all triangles T, whose neighboring triangles have already been oriented consistent with T
257  MaskType alreadyHandled( this->getNumTriangs() );
258  // true for all triangles who have already been dealt with or who are already waiting in queue
259  MaskType inQueue( this->getNumTriangs() );
260  // contains all triangles which are already oriented and whose neighbors will be dealt with next (may contain triangles twice for simplicity)
261  std::queue<int> activeTriangles;
262  activeTriangles.push( 0 );
263  inQueue[0] = true;
264  // the triangle whose neighbors are currently handled
265  int currentTriangle;
266  // while there are triangles left whose neighbors are not consistently oriented...
267  while( !activeTriangles.empty() ) {
268  currentTriangle = activeTriangles.front();
269  activeTriangles.pop();
270  // deal with all three neighbors of currentTriangle, i.e. orient them and add them to the list to deal with their neighbors
271  for ( int i = 0; i < 3; i++ ) {
272  int neighbor = getNeighbour( currentTriangle, i );
273  if ( neighbor >= 0 && neighbor < this->getNumTriangs() && !alreadyHandled[neighbor] ) {
274  // compute the nodes "currentTriangle" and "neighbor" have in common
275  int node1 = getTriangNodeIdx ( currentTriangle, ( i + 1 ) % 3 );
276  int node2 = getTriangNodeIdx ( currentTriangle, ( i + 2 ) % 3 );
277  // check whether common nodes occur in reversed order in "neighbor", if not, change order
278  int j = 0;
279  while ( getTriangNodeIdx ( neighbor, j ) != node2 )
280  j++;
281  if ( getTriangNodeIdx ( neighbor, ( j + 1 ) % 3 ) != node1 ) {
282  // change order of nodes
283  int exchangeCache = getTriangNodeIdx ( neighbor, ( j + 1 ) % 3 );
284  setTriangNodeIdx( neighbor, ( j + 1 ) % 3, getTriangNodeIdx ( neighbor, ( j + 2 ) % 3 ) );
285  setTriangNodeIdx( neighbor, ( j + 2 ) % 3, exchangeCache );
286  // change order of corresponding neighbours
287  exchangeCache = getNeighbour( neighbor, ( j + 1 ) % 3 );
288  setNeighbour( neighbor, ( j + 1 ) % 3, getNeighbour( neighbor, ( j + 2 ) % 3 ) );
289  setNeighbour( neighbor, ( j + 2 ) % 3, exchangeCache );
290  }
291  if ( !inQueue[neighbor] ) {
292  activeTriangles.push( neighbor );
293  inQueue[neighbor] = true;
294  }
295  }
296  }
297  alreadyHandled[currentTriangle] = true;
298  }
299  }
300 };
301 
302 
303 }//end namespace
304 
305 #endif
void updateAllTriangles()
Definition: triangMesh.h:115
void makeNeighbour() const
Definition: triangMesh.h:180
const TriangleType & getTriang(const int num) const
Definition: triangMesh.h:87
const Point3DType & getVertex(const int num) const
Definition: triangMesh.h:66
std::vector< TriangleType > _triangIterator
Definition: triangMesh.h:23
DataTypeContainer::MaskType MaskType
Definition: triangMesh.h:19
DataTypeContainer::Indices3DType Indices3DType
Definition: triangMesh.h:17
int pushBackTriang(const Indices3DType nodeIdx)
Insert new triangle and return global index.
Definition: triangMesh.h:59
int getNumVertices() const
Definition: triangMesh.h:42
int getNeighbour(const int elementID, const int acrossLocalEdge) const
Get neighbor on edge.
Definition: triangMesh.h:76
void loadFromLegacyVTK(const string &filename)
load from file in the .vtk file format. Currently only loads geometric information.
Definition: triangMesh.h:131
std::vector< Point3DType > _vertexIterator
Definition: triangMesh.h:22
int getNumTriangs() const
Definition: triangMesh.h:46
virtual ~TriangMesh()
Definition: triangMesh.h:38
void setTriangNodeIdx(const int num, const int localNode, const int newIdx)
Definition: triangMesh.h:109
TriangleType ElementType
Definition: triangMesh.h:13
TriangleType & getTriang(const int num)
Returns a triangle.
Definition: triangMesh.h:94
int pushBackVertex(const Point3DType newVertex)
Insert new vertex and return global index.
Definition: triangMesh.h:52
DataTypeContainer::VectorType VectorType
Definition: triangMesh.h:18
shellFE::ShellElementWithTangentSpaceAtVertex< DataTypeContainerShellFE > TriangleType
Definition: ex2.cpp:22
void setTriang(const int num, const TriangleType Arg)
Definition: triangMesh.h:99
int getTriangNodeIdx(const int num, const int localNode) const
Definition: triangMesh.h:104
double RealType
Definition: ex2.cpp:21
TriangMesh(const string &fileName)
Definition: triangMesh.h:33
void setNeighbour(const int elementID, const int acrossLocalEdge, const int value) const
Set neighbor on edge.
Definition: triangMesh.h:82
TriangMesh()
Create empty TriangMesh.
Definition: triangMesh.h:29
string strprintf(const char *format,...)
Give back formatted string, analogously to sprintf, but save the long way &#39;round with char arrays...
Definition: aol.cpp:5
DataTypeContainer::TangentVecType TangentVecType
Definition: triangMesh.h:16
void makeOrientationConsistent()
Definition: triangMesh.h:252
ConfiguratorType::VectorType VectorType
Definition: ex2.cpp:26
void setVertex(const int num, const Point3DType Arg)
Definition: triangMesh.h:70
DataTypeContainer::RealType RealType
Definition: triangMesh.h:14
std::vector< Indices3DType > _neighbour_
Definition: triangMesh.h:25
Triangle which has a tangent space at each node.
DataTypeContainer::Point3DType Point3DType
Definition: triangMesh.h:15