G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsMesh.hpp
Go to the documentation of this file.
1 
14 #pragma once
15 
16 #include <gsCore/gsBasis.h>
19 
20 namespace gismo
21 {
22 
23 template<class T>
24 gsMesh<T>::~gsMesh()
25 {
26  //gsInfo << "delete gsMesh\n";
27  freeAll(m_vertex);
28  freeAll(m_face);
29 }
30 
31 template<class T>
32 gsMesh<T>::gsMesh(const gsBasis<T> & basis, int midPts)
33 : MeshElement()
34 {
35  const unsigned d = basis.dim();
36 
37  typedef typename gsMesh<T>::VertexHandle vtx;
38  typename gsBasis<T>::domainIter domIter = basis.makeDomainIterator();
39 
40  // variables for iterating over a cube (element is a cube)
44 
45  // maps integer representation of a vertex into pointer to the
46  // vertex coordinates
47  std::vector<vtx> map(1ULL<<d);
48 
49  // neighbour[i] are integer representations of certain neighbours of
50  // vertex i (i counts in lexicographics order over all vertices)
51  std::vector<std::vector<unsigned> > neighbour(1ULL<<d,
52  std::vector<unsigned>() );
53 
54  cur.setZero(d);
55  int counter = 0;
56  do
57  {
58  // set neighbour
59  for (unsigned dim = 0; dim < d; dim++)
60  {
61  if (cur(dim) == 0)
62  {
63  const unsigned tmp = counter | (1<< dim) ;
64  neighbour[counter].push_back(tmp);
65  }
66  }
67  counter++;
68 
69  } while (nextCubePoint<gsVector<unsigned> >(cur, zeros, ones));
70 
71  gsVector<T> vv(d);
72 
73  for (; domIter->good(); domIter->next())
74  {
75  const gsVector<T>& low = domIter->lowerCorner();
76  const gsVector<T>& upp = domIter->upperCorner();
77  const T vol = domIter->volume();
78 
79  vv.setZero();
80  cur.setZero();
81  counter = 0;
82 
83  // Add points to the mesh.
84  do
85  {
86  // Get the appropriate coordinate of a point.
87  for (unsigned dim = 0; dim < d; dim++)
88  {
89  vv(dim) = ( cur(dim) ? upp(dim) : low(dim) );
90  }
91 
92  vtx v = addVertex(vv);
93  v->data = vol;
94  map[counter++] = v;
95 
96  } while (nextCubePoint<gsVector<unsigned> >(cur, zeros, ones));
97 
98 
99  // Add edges to the mesh (connect points).
100  for (size_t index = 0; index != neighbour.size(); index++)
101  {
102  const std::vector<unsigned> & v = neighbour[index];
103 
104  for (size_t ngh = 0; ngh != v.size(); ngh++)
105  {
106  // Add more vertices for better physical resolution.
107  addLine( map[index], map[v[ngh]], midPts );
108  //addEdge( map[index], map[v[ngh]] );
109  }
110  }
111 
112  // idea: instead of edges add the faces to the mesh
113  // addFace( mesh.vertex.back(),
114  // *(vertex.end()-3),
115  // *(vertex.end()-4),
116  // *(vertex.end()-2)
117  // );
118  }
119 }
120 
121 
122 template<class T>
123 typename gsMesh<T>::VertexHandle gsMesh<T>::addVertex(scalar_t const& x, scalar_t const& y, scalar_t const& z)
124 {
125  VertexHandle v = this->makeVertex(x,y,z);
126  v->setId(m_vertex.size());
127  m_vertex.push_back(v );
128  return v;
129 }
130 
131 
132 template<class T>
133 typename gsMesh<T>::VertexHandle gsMesh<T>::addVertex(gsVector<T> const & u)
134 {
135  VertexHandle v = this->makeVertex(u);
136  v->setId(m_vertex.size());
137  m_vertex.push_back(v);
138  return v;
139 }
140 
141 
142 template<class T>
143 void gsMesh<T>::addEdge(VertexHandle v0, VertexHandle v1)
144 {
145  m_edge.push_back( Edge(v0,v1) );
146 }
147 
148 
149 template<class T>
150 void gsMesh<T>::addEdge(int const vind0, int const vind1)
151 {
152  GISMO_ASSERT( (size_t)vind0 < numVertices(), "Invalid vertex index "
153  << vind0 << "(numVertices="<< numVertices() <<").");
154  GISMO_ASSERT( (size_t)vind1 < numVertices(), "Invalid vertex index "
155  << vind1 << "(numVertices="<< numVertices() <<").");
156 
157  addEdge(m_vertex[vind0], m_vertex[vind1]);
158 }
159 
160 
161 template<class T>
162 void gsMesh<T>::addEdge(gsVector<T> const & u0,
163  gsVector<T> const & u1 )
164 {
165  addEdge( addVertex(u0), addVertex(u1) );
166 }
167 
168 
169 template<class T>
170 typename gsMesh<T>::FaceHandle gsMesh<T>::addFace(std::vector<VertexHandle> const & vert)
171 {
172  FaceHandle f = this->makeFace( vert );
173  f->setId(m_face.size());
174  m_face.push_back(f);
175  return f;
176 }
177 
178 
179 template<class T>
180 typename gsMesh<T>::FaceHandle gsMesh<T>::addFace(VertexHandle const & v0, VertexHandle const & v1,
181  VertexHandle const & v2)
182 {
183  FaceHandle f = this->makeFace( v0, v1, v2 );
184  f->setId(m_face.size());
185  m_face.push_back(f);
186  return f;
187 }
188 
189 
190 template<class T>
191 typename gsMesh<T>::FaceHandle gsMesh<T>::addFace(VertexHandle const & v0, VertexHandle const & v1,
192  VertexHandle const & v2, VertexHandle const & v3)
193 {
194  FaceHandle f = this->makeFace( v0,v1,v2,v3 );
195  f->setId(m_face.size());
196  m_face.push_back(f);
197  return f;
198 }
199 
200 
201 template<class T>
202 typename gsMesh<T>::FaceHandle gsMesh<T>::addFace(std::vector<int> const & vert)
203 {
204  std::vector<VertexHandle> pvert; //(vert.size() );
205  pvert.reserve(vert.size());
206  for ( std::vector<int>::const_iterator it = vert.begin();
207  it!= vert.end(); ++it )
208  pvert.push_back( m_vertex[*it] );
209 
210  FaceHandle f = this->makeFace( pvert );
211  f->setId(m_face.size());
212  m_face.push_back(f);
213  return f;
214 }
215 
216 
217 template<class T>
218 typename gsMesh<T>::FaceHandle gsMesh<T>::addFace(const int v0, const int v1, const int v2)
219 {
220  FaceHandle f = this->makeFace( m_vertex[v0],m_vertex[v1],m_vertex[v2] );
221  f->setId(m_face.size());
222  m_face.push_back(f);
223  return f;
224 }
225 
226 
227 template<class T>
228 typename gsMesh<T>::FaceHandle gsMesh<T>::addFace(const int v0, const int v1, const int v2, const int v3)
229 {
230  FaceHandle f = this->makeFace( m_vertex[v0],m_vertex[v1],m_vertex[v2],m_vertex[v3] );
231  f->setId(m_face.size());
232  m_face.push_back(f);
233  return f;
234 }
235 
236 
237 template<class T>
238 std::ostream &gsMesh<T>::print(std::ostream &os) const
239 {
240  os<<"gsMesh with "<<numVertices()<<" vertices, "<<numEdges()<<
241  " edges and "<<numFaces()<<" faces.\n";
242 // for ( typename std::vector<FaceHandle>::const_iterator
243 // it = face.begin(); it!= face.end(); ++it)
244 // os<<" "<< **it ;
245  return os;
246 }
247 
248 
249 template <class T>
251 {
252  gsDebug << "Cleaning the gsMesh\n";
253 
254  // This function looks for duplicated vertex coordinates. For each
255  // vector, it chooses a unique vertex having that vector, then makes
256  // sure that the source and target of every edge is one of the chosen
257  // vertices. The old way was more efficient but did not work for
258  // non-manifold solids.
259 
260  /*gsDebug << "std::vector<> vertex before cleanMesh\n";
261  for (size_t i = 0; i < m_vertex.size(); ++i)
262  {
263  gsDebug << i << ": " << m_vertex[i] << " id: " << m_vertex[i]->getId() << " " << *m_vertex[i];
264  }
265  gsDebug << "----------------------------------------\n";*/
266 
267  // build up the unique map
268  std::vector<size_t> uniquemap;
269  uniquemap.reserve(m_vertex.size());
270  for(size_t i = 0; i < m_vertex.size(); i++)
271  {
272  size_t buddy = i;
273  for(size_t j = 0; j < i; j++)
274  {
275  if(*(m_vertex[i]) == *(m_vertex[j])) // overload compares coords
276  {
277  buddy = j;
278  break;
279  }
280  }
281  uniquemap.push_back(buddy);
282  }
283 
284  for(size_t i = 0; i != m_face.size(); i++)
285  {
286  for (size_t j = 0; j != m_face[i]->vertices.size(); j++)
287  {
288  m_face[i]->vertices[j] = m_vertex[uniquemap[m_face[i]->vertices[j]->getId()]];
289  }
290  }
291 
292  for(size_t i = 0; i < m_edge.size(); i++)
293  {
294  m_edge[i].source = m_vertex[uniquemap[m_edge[i].source->getId()]];
295  m_edge[i].target = m_vertex[uniquemap[m_edge[i].target->getId()]];
296  }
297 
298  std::set<size_t> uniqueset(uniquemap.begin(), uniquemap.end()); // O(n*log(n))
299  std::vector<VertexHandle> uvertex;
300  uvertex.reserve(uniqueset.size());
301  for(size_t i = 0; i < uniquemap.size(); i++) { // O(n)
302  if(uniqueset.find(i) != uniqueset.end()) // O(log(m)), n >> m
303  {
304  // re-number vertices id by new sequence - should we not do?
305  m_vertex[i]->setId(uvertex.size());
306  uvertex.push_back(m_vertex[i]);
307  }
308  else
309  {
310  delete m_vertex[i];
311  m_vertex[i] = nullptr;
312  }
313  } // O(n*log(n)+O(n)*O(log(m)) ==> O(n*log(n))
314  m_vertex.swap(uvertex);
315 
316  return *this;
317 }
318 
319 template<class T>
320 gsMesh<T>& gsMesh<T>::reserve(size_t vertex, size_t face, size_t edge)
321 {
322  m_vertex.reserve(vertex);
323  m_face.reserve(face);
324  m_edge.reserve(edge);
325  return *this;
326 }
327 
328 template <class T>
329 void gsMesh<T>::addLine(gsMatrix<T> const & points)
330  {
331  const index_t cols = points.cols();
332  if ( cols < 2 ) return;
333 
334  const bool zzero = ( points.rows()==2 );
335 
336  VertexHandle v1,
337  v0 = addVertex( points(0,0), points(1,0), zzero ? (T)0 : points(2,0) );
338 
339  for ( index_t i = 1; i<cols; ++i)
340  {
341  v1 = addVertex( points(0, i), points(1, i), zzero ? (T)0 : points(2,0) );
342  addEdge(v0 , v1);
343  v0 = v1;
344  }
345  }
346 
347 template <class T>
349 {
350  const gsVector3d<T> & start = *dynamic_cast<gsVector3d<T>* >(v0);
351  const T h = (*v1 - start).norm() / (T)(midPts + 1);
352  const gsVector3d<T> step = (*v1 - start).normalized();
353 
354  VertexHandle last = v0;
355  VertexHandle next;
356  for ( int i = 0; i<midPts; ++i )
357  {
358  next = addVertex(start + (T)(i+1)*h*step);
359  addEdge(last, next);
360  last = next;
361  }
362  addEdge(last, v1);
363 }
364 
365 
366 //template <class T>
367 //gsSolid<T> *
368 //gsMesh<T>::meshToSolid(int kvOuterPoints, int kvAdditionalInnerPoints, bool addInner,
369 // bool plot,std::string name,int meshPoints, T wE, T wI,int closeBoundary,
370 // std::vector<std::vector<VertexHandle> > iPoints,
371 // std::vector<std::vector<VertexHandle> > oPoints,
372 // std::vector< std::vector<std::vector<VertexHandle> > > innerBdrys,
373 // std::vector< std::vector<Vertex> > innerBdrysMassP,
374 // std::vector<std::vector<bool> > oPointsConvexFlag)
375 // {
376 // gsSolid<T> * s1 = new gsSolid<T>();
377 // this->toSolid(*s1,iPoints,oPoints,innerBdrys,innerBdrysMassP,oPointsConvexFlag,kvOuterPoints,kvAdditionalInnerPoints,plot,name,meshPoints,addInner,wE,wI,closeBoundary);
378 // return s1;
379 // }
380 
381 };// namespace gismo
A fixed-size, statically allocated 3D vector.
Definition: gsVector.h:218
bool nextCubePoint(Vec &cur, const Vec &end)
Iterate in lexigographic order through the points of the integer lattice contained in the cube [0...
Definition: gsCombinatorics.h:327
#define gsDebug
Definition: gsDebug.h:61
Provides declaration of Basis abstract interface.
#define index_t
Definition: gsConfig.h:32
Provides combinatorial unitilies.
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
Class Representing a triangle mesh with 3D vertices.
Definition: gsMesh.h:31
gsMesh & cleanMesh()
reorders the vertices of all faces of an .stl mesh, such that only 1 vertex is used instead of #(adja...
Definition: gsMesh.hpp:250
Provides declaration of DomainIterator abstract interface.
void freeAll(It begin, It end)
Frees all pointers in the range [begin end)
Definition: gsMemory.h:312
void addLine(gsMatrix< T > const &points)
Definition: gsMesh.hpp:329
virtual domainIter makeDomainIterator() const
Create a domain iterator for the computational mesh of this basis, that points to the first element o...
Definition: gsBasis.hpp:493
A basis represents a family of scalar basis functions defined over a common parameter domain...
Definition: gsBasis.h:78
gsVertex class that represents a 3D vertex for a gsMesh.
Definition: gsVertex.h:26