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.
|
- |
|
326 |
|
325 |
\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,
|
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,
|
326 |
\begin{verbatim}
|
328 |
\begin{verbatim}
|
327 |
VertexID Manifold::split_edge(HalfEdgeID h);
|
329 |
VertexID Manifold::split_edge(HalfEdgeID h);
|
328 |
\end{verbatim}
|
330 |
\end{verbatim}
|
329 |
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
|
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
|
Line 335... |
Line 337... |
335 |
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}
|
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}
|
336 |
\begin{verbatim}
|
338 |
\begin{verbatim}
|
337 |
for(VertexIDIterator v = m.vertices_begin();
|
339 |
for(VertexIDIterator v = m.vertices_begin();
|
338 |
v != m.vertices_end(); ++v)
|
340 |
v != m.vertices_end(); ++v)
|
339 |
{
|
341 |
{
|
340 |
Vec3f p = mani.pos(*v);
|
342 |
Vec3d p = mani.pos(*v);
|
341 |
// Do something
|
343 |
// Do something
|
342 |
}
|
344 |
}
|
343 |
\end{verbatim}
|
345 |
\end{verbatim}
|
344 |
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.
|
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.
|
345 |
|
347 |
|
346 |
\subsection{Walker}
|
348 |
\subsection{Walker}
|
347 |
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}
|
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}
|
348 |
\begin{verbatim}
|
350 |
\begin{verbatim}
|
349 |
Vec3f p(0);
|
351 |
Vec3d p(0);
|
350 |
FaceIDIterator f = m.faces_begin();
|
352 |
FaceIDIterator f = m.faces_begin();
|
351 |
Walker w = m.walker(*f);
|
353 |
Walker w = m.walker(*f);
|
352 |
for(; !w.full_circle(); w = w.next()){
|
354 |
for(; !w.full_circle(); w = w.next()){
|
353 |
p += m.pos(w.vertex());
|
355 |
p += m.pos(w.vertex());
|
354 |
p /= w.no_steps();
|
356 |
p /= w.no_steps();
|
Line 363... |
Line 365... |
363 |
\texttt{prev} does the same as \texttt{circulate\_face\_cw} and \texttt{next} does the same as \\\texttt{circulate\_face\_ccw}. The longer names are indicative of the geometric operation while \texttt{prev} and \texttt{next} highlight the connection with the data structure. It is important to note that all of the functions which operate on \texttt{Walker} instances return a new \texttt{Walker} and do not alter the state of the current walker. Thus to walk around a face, we use \texttt{w = w.next()} as opposed to just \texttt{w.next()} in the for loop above.
|
365 |
\texttt{prev} does the same as \texttt{circulate\_face\_cw} and \texttt{next} does the same as \\\texttt{circulate\_face\_ccw}. The longer names are indicative of the geometric operation while \texttt{prev} and \texttt{next} highlight the connection with the data structure. It is important to note that all of the functions which operate on \texttt{Walker} instances return a new \texttt{Walker} and do not alter the state of the current walker. Thus to walk around a face, we use \texttt{w = w.next()} as opposed to just \texttt{w.next()} in the for loop above.
|
364 |
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.
|
365 |
|
367 |
|
366 |
\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
|
367 |
\begin{verbatim}
|
369 |
\begin{verbatim}
|
368 |
Vec3f p(0);
|
370 |
Vec3d p(0);
|
369 |
VertexIDIterator v = m.vertices_begin();
|
371 |
VertexIDIterator v = m.vertices_begin();
|
370 |
Walker w = m.walker(*v);
|
372 |
Walker w = m.walker(*v);
|
371 |
for(; !w.full_circle(); w = w.circulate_vertex_ccw()){
|
373 |
for(; !w.full_circle(); w = w.circulate_vertex_ccw()){
|
372 |
p += m.pos(w.vertex());
|
374 |
p += m.pos(w.vertex());
|
373 |
p /= w.no_steps();
|
375 |
p /= w.no_steps();
|
Line 388... |
Line 390... |
388 |
We could have combined two or all three of these concepts, but would have led to rather bloated datatypes.
|
390 |
We could have combined two or all three of these concepts, but would have led to rather bloated datatypes.
|
389 |
|
391 |
|
390 |
\subsection{Attributes}
|
392 |
\subsection{Attributes}
|
391 |
Given a \texttt{VertexID}, \texttt{v}, and a \texttt{Manifold}, \texttt{m}, we can obtain the geometric position of the vertex with the method call \texttt{m.pos(v)}. If is fairly important to note that a reference to the position is returned. Thus, we can assign the position of a vertex:
|
393 |
Given a \texttt{VertexID}, \texttt{v}, and a \texttt{Manifold}, \texttt{m}, we can obtain the geometric position of the vertex with the method call \texttt{m.pos(v)}. If is fairly important to note that a reference to the position is returned. Thus, we can assign the position of a vertex:
|
392 |
\begin{verbatim}
|
394 |
\begin{verbatim}
|
393 |
Vec3f p;
|
395 |
Vec3d p;
|
394 |
VertexID v;
|
396 |
VertexID v;
|
395 |
// ...
|
397 |
// ...
|
396 |
m.pos(v) = p;
|
398 |
m.pos(v) = p;
|
397 |
\end{verbatim}
|
399 |
\end{verbatim}
|
398 |
|
400 |
|