Subversion Repositories gelsvn

Rev

Rev 630 | Rev 635 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 630 Rev 633
Line 320... Line 320...
320
\begin{verbatim}
320
\begin{verbatim}
321
VertexID vid;
321
VertexID vid;
322
// ... obtain a vertex ID
322
// ... obtain a vertex ID
323
vec3d p = m.pos(vid);
323
vec3d p = m.pos(vid);
324
\end{verbatim}
324
\end{verbatim}
325
Note that m.pos(vid) returns a reference to the vertex identified by vid, so we can also assign the vertex position simply using m.pos(vid) = p.
325
Note that m.pos(vid) returns a reference to the vertex identified by vid, so we can also assign the vertex position simply using 
-
 
326
\begin{verbatim}
-
 
327
m.pos(vid) = p;
326
 
328
\end{verbatim}
327
\texttt{VertexID}, \texttt{FaceID}, and \texttt{HalfEdgeID} are simply indices which we use to refer to entities in the mesh. These types are used to communicate with the \texttt{Manifold} class. For instance to get the position of a vertex, but many other functions -- both inside and outside the \texttt{Manifold} class take one of the ID types as argument. For instance,
329
\texttt{VertexID}, \texttt{FaceID}, and \texttt{HalfEdgeID} are simply indices which we use to refer to entities in the mesh. These types are used to communicate with the \texttt{Manifold} class. For instance to get the position of a vertex, but many other functions -- both inside and outside the \texttt{Manifold} class take one of the ID types as argument. For instance,
328
\begin{verbatim}
330
\begin{verbatim}
329
VertexID Manifold::split_edge(HalfEdgeID h);
331
VertexID Manifold::split_edge(HalfEdgeID h);
330
\end{verbatim}
332
\end{verbatim}
331
splits an edge and returns a \texttt{VertexID} for the introduced vertex. For functions outside the class, we need to also give the \texttt{Manifold} as an argument since an ID does not tell the function which mesh we are referring to. For example
333
splits an edge and returns a \texttt{VertexID} for the introduced vertex. For functions outside the class, we need to also give the \texttt{Manifold} as an argument since an ID does not tell the function which mesh we are referring to. For example
332
\begin{verbatim}
334
\begin{verbatim}
333
bool boundary(const Manifold& m, HalfEdgeID h);
335
bool boundary(const Manifold& m, HalfEdgeID h);
334
\end{verbatim}
336
\end{verbatim}
335
returns true if the halfedge identified by \texttt{h} is a boundary edge in \texttt{m}.
337
returns true if the halfedge identified by \texttt{h} is a boundary edge in \texttt{m}.
336
 
338
 
337
We might somewhere have stored the \texttt{VertexID}, but frequently we simply iterate through our vertices. In other words, we loop over all vertices. Such a loop requires another type, namely the \texttt{VertexIDIterator}
339
A very frequent operation is that we need to iterate over all the vertices in a mesh. This is done as follows:
338
\begin{verbatim}
340
\begin{verbatim}
339
for(VertexIDIterator v = m.vertices_begin(); 
341
for(VertexID v : m.vertices())
340
     v != m.vertices_end(); ++v)
-
 
341
{
342
{
342
  Vec3d p = mani.pos(*v);
343
   Vec3d p = m.pos(v);
343
  // Do something
344
   // Do something with the position
344
}
345
}
345
\end{verbatim}
346
\end{verbatim}
346
An ID iterator is only useful for iterating over elements in the mesh. However, from the iterator we can obtain the ID by using the dereference operator \texttt{*} as shown above. We also have \texttt{HalfEdgeID}, \texttt{HalfEdgeIDIterator}, \texttt{FaceID}, and \texttt{FaceIDIterator}. Thus, similar code could have been used to iterate over halfedges or faces. Clearly, iterating over elements is just the beginning. The iterators expose how the mesh entities are stored in the \texttt{Manifold} but not how they relate geometrically to one another. 
347
Since we also have ID types for faces and half edges, similar code could have been used to iterate over these entities. As a note: there are also specific iterator classes (e.g. \texttt{VertexIDIterator}) which can be used to iterate with old fashioned for loops. However, the syntax is far more cumbersome, so we suggest you stick with the range based for loops as  shown above.
347
 
-
 
348
\subsection{Walker}
348
\subsection{Walker}
-
 
349
To loop over all vertices is one way of traversing the mesh. It ensures that we visit all vertices, but it does not relate to the connectivity of the mesh. 
349
To traverse the mesh in a geometric fashion, we use the \texttt{Walker}. A \texttt{Walker} simply encapsulates an ID for a given \texttt{HalfEdge} and a pointer to the data structure which stores the mesh. Thus, to compute the centroid for a given face, we can use a \texttt{Walker}
350
To traverse the mesh in a way that respects connectivity, we use the \texttt{Walker} class. A \texttt{Walker} always points to a specific halfedge, but unlike a \texttt{HalfEdgeID}, it can be used to move from edge to edge. For instance, to compute the centroid for a given face, we can use the following code:
350
\begin{verbatim}
351
\begin{verbatim}
351
Vec3d p(0);
352
Vec3d p(0);
352
FaceIDIterator f = m.faces_begin();
353
FaceID f = *m.faces_begin();
353
Walker w = m.walker(*f);
-
 
354
for(; !w.full_circle(); w = w.next()){
354
for(Walker w = m.walker(f); !w.full_circle(); w = w.next())
355
  p += m.pos(w.vertex()); 
355
  p += m.pos(w.vertex()); 
356
p /= w.no_steps();
356
p /= w.no_steps();
357
\end{verbatim}
357
\end{verbatim}
358
The code above computes the centroid for the first face in the mesh. The benefit of the walker is that it allows us to move from a halfedge to all connected halfedges. The simple traversal functions are \texttt{next}, \texttt{prev}, and \texttt{opp}:
358
The code above computes the centroid for the first face in the mesh. It does so by jumping from edge to edge until it has come full circle. For each jump, we add the vertex pointed to by the halfedge to \texttt{p}. The benefit of the \texttt{Walker} is that it allows us to move from a halfedge to all connected halfedges. The simple traversal functions are \texttt{next}, \texttt{prev}, and \texttt{opp}:
359
\begin{verbatim}
359
\begin{verbatim}
360
Walker w;
360
Walker w;
361
w = w.next(); 
361
w = w.next(); 
362
w = w.prev();
362
w = w.prev();
363
w = w.opp();
363
w = w.opp();
Line 366... Line 366...
366
That might seem inconvenient but it is more flexible since we can obtain, say, a nearby vertex just by concatenating some traversal functions. For instance \texttt{w.next().opp().next().vertex()} returns an ID to a vertex nearby  -- without changing \texttt{w}. The sequence \texttt{w.next().opp().next()} creates three anonymous walkers. If, on the other hand, the functions used for walking updated the state of  \texttt{w}, we would have needed to first make a named copy of \texttt{w} before updating its state, so that we could get back to the original state.
366
That might seem inconvenient but it is more flexible since we can obtain, say, a nearby vertex just by concatenating some traversal functions. For instance \texttt{w.next().opp().next().vertex()} returns an ID to a vertex nearby  -- without changing \texttt{w}. The sequence \texttt{w.next().opp().next()} creates three anonymous walkers. If, on the other hand, the functions used for walking updated the state of  \texttt{w}, we would have needed to first make a named copy of \texttt{w} before updating its state, so that we could get back to the original state.
367
 
367
 
368
\texttt{Walker} can be used to circulate around both faces and vertices. Below, we use vertex circulation to compute the average of the neighbors of a vertex
368
\texttt{Walker} can be used to circulate around both faces and vertices. Below, we use vertex circulation to compute the average of the neighbors of a vertex
369
\begin{verbatim}
369
\begin{verbatim}
370
Vec3d p(0);
370
Vec3d p(0);
371
VertexIDIterator v = m.vertices_begin();
371
VertexID v = *m.vertices_begin();
372
Walker w = m.walker(*v);
372
for(Walker w = m.walker(v);!w.full_circle(); 
373
for(; !w.full_circle(); w = w.circulate_vertex_ccw()){
373
     w = w.circulate_vertex_ccw()){
374
  p += m.pos(w.vertex()); 
374
  p += m.pos(w.vertex()); 
375
p /= w.no_steps();
375
p /= w.no_steps();
376
\end{verbatim}
376
\end{verbatim}
377
 
377
 
378
The \texttt{full\_circle()} function tests whether the walker has returned to the original halfedge whence it was created. We can also call  \texttt{no\_steps() } which returns the number of steps taken. In this regard, vertex circulation is considered atomic - even though \texttt{w.circulate\_vertex\_ccw()} is the same as  \texttt{w.prev().opp()}.
378
Again, the \texttt{full\_circle()} function tests whether the walker has returned to the original halfedge whence it was created. We can also call  \texttt{no\_steps() } which returns the number of steps taken. In this regard, a step of vertex circulation is considered atomic - even though \texttt{w.circulate\_vertex\_ccw()} is the same as  \texttt{w.prev().opp()}.
379
 
379
 
380
From a walker we can easily obtain any of the mesh entities that the halfedge it refers to are incident upon. For instance \texttt{vertex()} returns the \texttt{VertexID} of the vertex which the halfedge points to, \texttt{face()} gives us the \texttt{FaceID} of the incident face and \texttt{halfedge()} simply returns the \texttt{HalfEdgeID}.
380
From a walker we can easily obtain any of the mesh entities that the halfedge it refers to are incident upon. For instance \texttt{vertex()} returns the \texttt{VertexID} of the vertex which the halfedge points to, \texttt{face()} gives us the \texttt{FaceID} of the incident face and \texttt{halfedge()} simply returns the \texttt{HalfEdgeID}. There is one more option for circulation. The following code does precisely the same as the code above, i.e. it computes the average of the neighboring vertices.
-
 
381
\begin{verbatim}
-
 
382
        Vec3d p(0);
-
 
383
        int n = circulate_vertex_ccw(m, v, 
-
 
384
                   [&](VertexID v){ p += m.pos(v); });
-
 
385
        return p / n;
-
 
386
\end{verbatim}
-
 
387
Here the function \texttt{circulate\_vertex\_ccw} takes three arguments. The \texttt{Manifold}, \texttt{m}, and the vertex, \texttt{v}, around which we circulate, and, finally, a function that accepts a \texttt{VertexID}. This function gets called for every vertex adjacent to \texttt{v}. In this example, the function is given as a so called \textit{lambda} function. This allows us to write things compactly and to have the body of the function where it is needed. We could also have passed a function which accepts a \texttt{FaceID} or a \texttt{HalfEdgeID} or a \texttt{Walker}. Thus, we can visit incident faces and edges during circulation if that is what we need, and if we need go get some entity other than adjacent vertices, edges, or faces, we can use the \texttt{Walker} option which is the most generic.
381
 
388
 
382
To summarize there are three datatypes that we use to refer to mesh entitites.
389
To summarize there are three datatypes that we use to refer to mesh entitites.
383
\begin{itemize}
390
\begin{itemize}
384
\item IDs \texttt{VertexID}, \texttt{HalfEdgeID}, and \texttt{FaceID} are simply indices. These types are what we use when calling functions that take arguments which refer to mesh entities. 
391
\item IDs \texttt{VertexID}, \texttt{HalfEdgeID}, and \texttt{FaceID} are simply indices. These types are what we use when calling functions that take arguments which refer to mesh entities. 
385
\item ID iterators \texttt{VertexIDIterator}, \texttt{HalfEdgeIDIterator}, and\\ \texttt{FaceIDIterator} as their names imply can be used to iterate over the entities of a mesh. As such they reflect how the mesh is stored in memory. Dereferencing an ID iterator will give an ID. 
392
\item ID iterators \texttt{VertexIDIterator}, \texttt{HalfEdgeIDIterator}, and\\ \texttt{FaceIDIterator} as their names imply can be used to iterate over the entities of a mesh. As such they reflect how the mesh is stored in memory. Dereferencing an ID iterator will give an ID.