G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
gsMesh.hpp
Go to the documentation of this file.
1
14#pragma once
15
16#include <gsCore/gsBasis.h>
19
20namespace gismo
21{
22
23template<class T>
24gsMesh<T>::~gsMesh()
25{
26 //gsInfo << "delete gsMesh\n";
27 freeAll(m_vertex);
28 freeAll(m_face);
29}
30
31template<class T>
32gsMesh<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
122template<class T>
123typename 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
132template<class T>
133typename 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
142template<class T>
143void gsMesh<T>::addEdge(VertexHandle v0, VertexHandle v1)
144{
145 m_edge.push_back( Edge(v0,v1) );
146}
147
148
149template<class T>
150void 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
161template<class T>
162void gsMesh<T>::addEdge(gsVector<T> const & u0,
163 gsVector<T> const & u1 )
164{
165 addEdge( addVertex(u0), addVertex(u1) );
166}
167
168
169template<class T>
170typename 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
179template<class T>
180typename 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
190template<class T>
191typename 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
201template<class T>
202typename 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
217template<class T>
218typename 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
227template<class T>
228typename 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
237template<class T>
238std::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
249template <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
319template<class T>
320gsMesh<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
328template <class T>
329void 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
347template <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 basis represents a family of scalar basis functions defined over a common parameter domain.
Definition gsBasis.h:79
A matrix with arbitrary coefficient type and fixed or dynamic size.
Definition gsMatrix.h:41
Class Representing a triangle mesh with 3D vertices.
Definition gsMesh.h:32
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
void addLine(gsMatrix< T > const &points)
Definition gsMesh.hpp:329
A fixed-size, statically allocated 3D vector.
Definition gsVector.h:219
A vector with arbitrary coefficient type and fixed or dynamic size.
Definition gsVector.h:37
gsVertex class that represents a 3D vertex for a gsMesh.
Definition gsVertex.h:27
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
Provides declaration of Basis abstract interface.
Provides combinatorial unitilies.
#define index_t
Definition gsConfig.h:32
#define gsDebug
Definition gsDebug.h:61
#define GISMO_ASSERT(cond, message)
Definition gsDebug.h:89
Provides declaration of DomainIterator abstract interface.
The G+Smo namespace, containing all definitions for the library.
void freeAll(It begin, It end)
Frees all pointers in the range [begin end)
Definition gsMemory.h:312