1 /*
2  This Source Code Form is subject to the terms of the Mozilla Public
3  License, v. 2.0. If a copy of the MPL was not distributed with this
4  file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 */
6 
7 #ifndef _VITELOTTE_VG_MESH_
8 #define _VITELOTTE_VG_MESH_
9 
10 
11 #include <cassert>
12 #include <climits>
13 #include <limits>
14 #include <vector>
15 #include <map>
16 
17 #include <Eigen/Core>
18 
19 #include "../../common/surface_mesh/surfaceMesh.h"
20 #include "../../common/gl_utils/color.h"
21 
22 #include "bezierPath.h"
23 
24 
25 namespace Vitelotte
26 {
27 
28 
29 using PatateCommon::ColorSpace;
30 
31 
32 enum
33 {
34     Dynamic = Eigen::Dynamic
35 };
36 
37 
38 #define PATATE_VG_MESH_HALFEDGE_ATTR_FLAG(_index) (1 << _index)
39 #define PATATE_VG_MESH_VERTEX_ATTR_FLAG(_index) (1 << (16 + _index))
40 
41 
42 /**
43  * \brief A mesh with data suitable for representing complex color gradients,
44  * among other.
45  *
46  * For more details about VGMesh, see the [user manual](vitelotte_user_manual_vg_mesh_page).
47  */
48 template < typename _Scalar, int _Dims=2, int _Coeffs=4 >
49 class VGMesh: public PatateCommon::SurfaceMesh
50 {
51 public:
52     typedef _Scalar Scalar;
53 
54     enum {
55         DimsAtCompileTime = _Dims,
56         CoeffsAtCompileTime = _Coeffs
57     };
58 
59     typedef VGMesh<Scalar, DimsAtCompileTime, CoeffsAtCompileTime> Self;
60 
61     typedef Eigen::Matrix<Scalar, DimsAtCompileTime, 1> Vector;
62     typedef Eigen::Matrix<Scalar, CoeffsAtCompileTime, 1> Value;
63     typedef Eigen::Matrix<Scalar, CoeffsAtCompileTime, DimsAtCompileTime> Gradient;
64 
65     typedef BezierSegment<Vector> CurvedEdge;
66 
67 protected:
68     typedef Eigen::Matrix<Scalar, DimsAtCompileTime, Eigen::Dynamic> VectorMatrix;
69     typedef Eigen::Matrix<Scalar, CoeffsAtCompileTime, Eigen::Dynamic> NodeMatrix;
70 
71 public:
72     typedef typename VectorMatrix::ColXpr VectorXpr;
73     typedef typename VectorMatrix::ConstColXpr ConstVectorXpr;
74     typedef typename NodeMatrix::ColXpr ValueXpr;
75     typedef typename NodeMatrix::ConstColXpr ConstValueXpr;
76     typedef typename Value::ConstantReturnType UnconstrainedNodeType;
77 
78     struct Node : public BaseHandle
79     {
BaseHandleNode80         explicit Node(int _idx = -1) : BaseHandle(_idx) {}
81         std::ostream& operator<<(std::ostream& os) const { return os << 'n' << idx(); }
82     };
83 
84     enum HalfedgeAttribute
85     {
86         TO_VERTEX_VALUE,
87         FROM_VERTEX_VALUE,
88         EDGE_VALUE,
89         EDGE_GRADIENT,
90 
91         HALFEDGE_ATTRIB_COUNT
92     };
93 
94     // TODO: Unused now. Use it or remove it ?
95     enum VertexAttribute
96     {
97         VERTEX_POSITION,
98         VERTEX_GRADIENT_CONSTRAINT,
99 
100         VERTEX_ATTRIB_COUNT
101     };
102 
103     enum
104     {
105         // Nodes
106         TO_VERTEX_VALUE_FLAG    = PATATE_VG_MESH_HALFEDGE_ATTR_FLAG(TO_VERTEX_VALUE),
107         FROM_VERTEX_VALUE_FLAG  = PATATE_VG_MESH_HALFEDGE_ATTR_FLAG(FROM_VERTEX_VALUE),
108         EDGE_VALUE_FLAG         = PATATE_VG_MESH_HALFEDGE_ATTR_FLAG(EDGE_VALUE),
109         EDGE_GRADIENT_FLAG      = PATATE_VG_MESH_HALFEDGE_ATTR_FLAG(EDGE_GRADIENT),
110 
111         // Other
112         VERTEX_GRADIENT_CONSTRAINT_FLAG =
113                 PATATE_VG_MESH_VERTEX_ATTR_FLAG(VERTEX_GRADIENT_CONSTRAINT),
114 
115         // Aggregates
116         LINEAR_FLAGS = TO_VERTEX_VALUE_FLAG | FROM_VERTEX_VALUE_FLAG,
117         QUADRATIC_FLAGS = LINEAR_FLAGS | EDGE_VALUE_FLAG,
118 
119         MORLEY_FLAGS = LINEAR_FLAGS | EDGE_GRADIENT_FLAG,
120         FV_FLAGS = QUADRATIC_FLAGS | EDGE_GRADIENT_FLAG | VERTEX_GRADIENT_CONSTRAINT_FLAG
121     };
122 
123 public:
124     /// this class iterates linearly over all nodes
125     /// \sa nodesBegin(), nodesEnd()
126     class NodeIterator
127     {
128     public:
129 
130         /// Default constructor
hnd_(n)131         NodeIterator(Node n=Node(), const Self* m=NULL) : hnd_(n), mesh_(m)
132         {
133             if(mesh_ && mesh_->garbage())
134             {
135                 while(mesh_->isValid(hnd_) && mesh_->isDeleted(hnd_))
136                 {
137                     hnd_ = Node(hnd_.idx() + 1);
138                 }
139             }
140         }
141 
142         /// get the node the iterator refers to
143         Node operator*()  const { return  hnd_; }
144 
145         /// are two iterators equal?
146         bool operator==(const NodeIterator& rhs) const
147         {
148             return (hnd_==rhs.hnd_);
149         }
150 
151         /// are two iterators different?
152         bool operator!=(const NodeIterator& rhs) const
153         {
154             return !operator==(rhs);
155         }
156 
157         /// pre-increment iterator
158         NodeIterator& operator++()
159         {
160             hnd_ = Node(hnd_.idx() + 1);
161             assert(mesh_);
162             while(mesh_->garbage() && mesh_->isValid(hnd_) && mesh_->isDeleted(hnd_))
163             {
164                 hnd_ = Node(hnd_.idx() + 1);
165             }
166             return *this;
167         }
168 
169         /// pre-decrement iterator
170         NodeIterator& operator--()
171         {
172             --hnd_.idx_;
173             assert(mesh_);
174             while (mesh_->garbage() && mesh_->isValid(hnd_) && mesh_->isDeleted(hnd_)) --hnd_.idx_;
175             return *this;
176         }
177 
178     private:
179         Node  hnd_;
180         const Self* mesh_;
181     };
182 
183     /// Node property of type T
184     /// \sa VertexProperty, HalfedgeProperty, EdgeProperty, FaceProperty
185     template <class T> class NodeProperty : public PatateCommon::Property<T>
186     {
187     public:
188 
189         /// default constructor
NodeProperty()190         explicit NodeProperty() {}
NodeProperty(PatateCommon::Property<T> p)191         explicit NodeProperty(PatateCommon::Property<T> p)
192             : PatateCommon::Property<T>(p) {}
193 
194         /// access the data stored for vertex \c v
195         typename PatateCommon::Property<T>::Reference operator[](Node n)
196         {
197             return PatateCommon::Property<T>::operator[](n.idx());
198         }
199 
200         /// access the data stored for vertex \c v
201         typename PatateCommon::Property<T>::ConstReference operator[](Node n) const
202         {
203             return PatateCommon::Property<T>::operator[](n.idx());
204         }
205     };
206 
207 public:
208 
209     /// \name Constructor, derstructor, assignement
210     /// \{
211 
212     /// \brief Create a VGMesh with `attirbutes` flags activated.
213     explicit VGMesh(unsigned attributes = 0);
214     explicit VGMesh(unsigned nDims, unsigned nCoeffs, unsigned attributes=0);
~VGMesh()215     virtual ~VGMesh() {}
216 
217     VGMesh(const Self& other);
218 
219     VGMesh& operator=(const Self& rhs);
220     VGMesh& assign(const Self& rhs);
221 
222     /// \}
223 
224 
225     /// \name Mesh and general
226     /// \{
227 
nDims()228     inline unsigned nDims() const { return m_positions.rows(); }
nCoeffs()229     inline unsigned nCoeffs() const { return m_nodes.rows(); }
230 
231     void setNDims(unsigned nDims);
232 
233 protected:
positionsCapacity()234     inline unsigned positionsCapacity() const { return m_positions.cols(); }
235 
236 public:
237 
238     /**
239      * \brief Set the number of coefficients to nCoeffs.
240      *
241      * If this mesh has a fixed number of coefficients, nCoeffs must match it.
242      *
243      * If this function is used to increase the number of coefficients of a
244      * non-empty mesh, be aware that the new coefficients will be
245      * uninitialized. In other words, value() will return partially initialized
246      * vectors.
247      */
248     void setNCoeffs(unsigned nCoeffs);
249 
250     inline void reserve(unsigned nvertices, unsigned nedges, unsigned nfaces,
251                         unsigned nnodes);
252     inline void clear();
253     void garbageCollection(unsigned flags = 0);
254     void releaseGCIndexMaps();
255 
256     using PatateCommon::SurfaceMesh::gcMap;
gcMap(Node n)257     inline Node gcMap(Node n) const
258     {
259         assert(n.isValid() && n.idx() < int(m_gcNodeMap.size()));
260         return m_gcNodeMap[n.idx()];
261     }
262 
263     template <typename Derived>
264     inline Vertex addVertex(const Eigen::DenseBase<Derived>& pos);
265 
position(Vertex v)266     inline ConstVectorXpr position(Vertex v) const
267     { assert(unsigned(v.idx()) < verticesSize()); return m_positions.col(v.idx()); }
268 
position(Vertex v)269     inline VectorXpr position(Vertex v)
270     { assert(unsigned(v.idx()) < verticesSize()); return m_positions.col(v.idx()); }
271 
272     using PatateCommon::SurfaceMesh::isValid;
273     inline bool isValid(Node n) const;
274 
colorSpace()275     inline ColorSpace colorSpace() const {
276         return m_colorSpace;
277     }
278 
setColorSpace(ColorSpace colorSpace)279     inline void setColorSpace(ColorSpace colorSpace) {
280         m_colorSpace = colorSpace;
281     }
282 
isCurved(Edge e)283     inline bool isCurved(Edge e) const {
284         return m_curvedEdges.find(e) != m_curvedEdges.end();
285     }
286 
isCurved(Halfedge h)287     inline bool isCurved(Halfedge h) const {
288         return isCurved(edge(h));
289     }
290 
edgeCurve(Edge e)291     inline const CurvedEdge& edgeCurve(Edge e) const {
292         return m_curvedEdges.at(e);
293     }
294 
edgeCurve(Halfedge h)295     inline CurvedEdge edgeCurve(Halfedge h) const {
296         return halfedgeOrientation(h)?
297                     edgeCurve(edge(h)).getBackward():
298                     edgeCurve(edge(h));
299     }
300 
setEdgeCurve(Edge e,const CurvedEdge & curve)301     inline void setEdgeCurve(Edge e, const CurvedEdge& curve) {
302         m_curvedEdges[e] = curve;
303     }
304 
setEdgeCurve(Halfedge h,const CurvedEdge & curve)305     inline void setEdgeCurve(Halfedge h, const CurvedEdge& curve) {
306         if(halfedgeOrientation(h)) setEdgeCurve(edge(h), curve.getBackward());
307         else                       setEdgeCurve(edge(h), curve);
308     }
309 
310     /**
311      * \brief Return a boolean such that opposite halfedges give a different
312      * result.
313      *
314      * In practice, return `fromVertex(h).idx() > toVertex(h).idx()`. This
315      * make the method easily predictable.
316      */
halfedgeOrientation(Halfedge h)317     inline bool halfedgeOrientation(Halfedge h) const {
318         // It is possible to use h.idx() % 2 for a similar result, but it makes
319         // the halfedge orientation hard to predict.
320         return fromVertex(h).idx() > toVertex(h).idx();
321     }
322 
323     template <class T> NodeProperty<T> addNodeProperty(const std::string& name, const T t=T())
324     {
325         return NodeProperty<T>(m_nprops.add<T>(name, t));
326     }
327 
getNodeProperty(const std::string & name)328     template <class T> NodeProperty<T> getNodeProperty(const std::string& name) const
329     {
330         return NodeProperty<T>(m_nprops.get<T>(name));
331     }
332 
333     template <class T> NodeProperty<T> nodeProperty(const std::string& name, const T t=T())
334     {
335         return NodeProperty<T>(m_nprops.getOrAdd<T>(name, t));
336     }
337 
removeNodeProperty(NodeProperty<T> & p)338     template <class T> void removeNodeProperty(NodeProperty<T>& p)
339     {
340         m_nprops.remove(p);
341     }
342 
getNodePropertyType(const std::string & name)343     const std::type_info& getNodePropertyType(const std::string& name)
344     {
345         return m_nprops.getType(name);
346     }
347 
nodeProperties()348     std::vector<std::string> nodeProperties() const
349     {
350         return m_nprops.properties();
351     }
352 
353     /// \}
354 
355 
356     /// \name Attributes
357     /// \{
358 
359     /// \brief Return active attribute flags ored together.
getAttributes()360     unsigned getAttributes() const { return m_attributes; }
361 
362     /**
363      * \brief Set the active attributes to `attributes`.
364      *
365      * Attributes that are removed will release corresponding memory and
366      * new attributes will be set to their default value. Attibute that stay
367      * active won't be modified.
368      *
369      * \param attributes Attributes flags ORed together.
370      */
371     void setAttributes(unsigned attributes);
372 
hasAttribute(HalfedgeAttribute attr)373     inline bool hasAttribute(HalfedgeAttribute attr) const
374         { assert(attr < HALFEDGE_ATTRIB_COUNT); return m_attributes & (1 << attr); }
hasToVertexValue()375     inline bool hasToVertexValue() const { return m_attributes & TO_VERTEX_VALUE_FLAG; }
hasFromVertexValue()376     inline bool hasFromVertexValue() const { return m_attributes & FROM_VERTEX_VALUE_FLAG; }
hasEdgeValue()377     inline bool hasEdgeValue() const { return m_attributes & EDGE_VALUE_FLAG; }
hasEdgeGradient()378     inline bool hasEdgeGradient() const { return m_attributes & EDGE_GRADIENT_FLAG; }
hasVertexGradientConstraint()379     inline bool hasVertexGradientConstraint() const
380         { return m_attributes & VERTEX_GRADIENT_CONSTRAINT_FLAG; }
381 
toVertexValueNode(Halfedge h)382     inline Node toVertexValueNode(Halfedge h) const
383         { return halfedgeNode(h, TO_VERTEX_VALUE); }
toVertexValueNode(Halfedge h)384     inline Node& toVertexValueNode(Halfedge h)
385         { return halfedgeNode(h, TO_VERTEX_VALUE); }
386 
fromVertexValueNode(Halfedge h)387     inline Node fromVertexValueNode(Halfedge h) const
388         { return halfedgeNode(h, FROM_VERTEX_VALUE); }
fromVertexValueNode(Halfedge h)389     inline Node& fromVertexValueNode(Halfedge h)
390         { return halfedgeNode(h, FROM_VERTEX_VALUE); }
391 
edgeValueNode(Halfedge h)392     inline Node edgeValueNode(Halfedge h) const
393         { return halfedgeNode(h, EDGE_VALUE); }
edgeValueNode(Halfedge h)394     inline Node& edgeValueNode(Halfedge h)
395         { return halfedgeNode(h, EDGE_VALUE); }
396 
edgeGradientNode(Halfedge h)397     inline Node edgeGradientNode(Halfedge h) const
398         { return halfedgeNode(h, EDGE_GRADIENT); }
edgeGradientNode(Halfedge h)399     inline Node& edgeGradientNode(Halfedge h)
400         { return halfedgeNode(h, EDGE_GRADIENT); }
401 
402     HalfedgeAttribute oppositeAttribute(HalfedgeAttribute attr) const;
403 
404     inline Node halfedgeNode(Halfedge h, HalfedgeAttribute attr) const;
405     inline Node& halfedgeNode(Halfedge h, HalfedgeAttribute attr);
406 
407     inline Node halfedgeOppositeNode(Halfedge h, HalfedgeAttribute attr) const;
408     inline Node& halfedgeOppositeNode(Halfedge h, HalfedgeAttribute attr);
409 
410     /// \}
411 
412 
413     /// \name Point gradient constraints
414     /// \{
415 
isGradientConstraint(Vertex v)416     inline bool isGradientConstraint(Vertex v) const
417         { assert(hasVertexGradientConstraint()); return m_vertexGradientConstraints.count(v); }
gradientConstraint(Vertex v)418     inline Gradient& gradientConstraint(Vertex v)
419         { assert(hasVertexGradientConstraint()); return m_vertexGradientConstraints.at(v); }
gradientConstraint(Vertex v)420     inline const Gradient& gradientConstraint(Vertex v) const
421         { assert(hasVertexGradientConstraint()); return m_vertexGradientConstraints.at(v); }
422     inline void setGradientConstraint(Vertex v, const Gradient& grad);
423     inline void removeGradientConstraint(Vertex v);
424 
nVertexGradientConstraints()425     inline int nVertexGradientConstraints() const
426         { assert(hasVertexGradientConstraint()); return m_vertexGradientConstraints.size(); }
427     inline unsigned nVertexGradientConstraints(Halfedge h) const;
428     inline unsigned nVertexGradientConstraints(Face f) const;
429 
430     /// \}
431 
432 
433     /// \name Low-level nodes manipulation
434     /// \{
435 
nodesSize()436     inline unsigned nodesSize() const { return m_nprops.size(); }
437     /// \brief Return the number of nodes.
nNodes()438     inline unsigned nNodes() const { return nodesSize() - m_deletedNodes; }
439 
440 protected:
nodesCapacity()441     inline unsigned nodesCapacity() const { return m_nodes.cols(); }
442 
443 public:
444     using PatateCommon::SurfaceMesh::isDeleted;
isDeleted(Node n)445     inline bool isDeleted(Node n) const { return m_ndeleted[n]; }
446 
447     /// \brief Mark unused node as deleted, but does not free memory.
448     /// \sa garbageCollection()
449     void deleteUnusedNodes();
450 
nodesBegin()451     NodeIterator nodesBegin() const { return NodeIterator(Node(0),           this); }
nodesEnd()452     NodeIterator nodesEnd()   const { return NodeIterator(Node(nodesSize()), this); }
453 
454     /**
455      * \brief Add and return a node with value `value` or an unknown node
456      * if no parameter is provided.
457      */
addNode()458     inline Node addNode() { return addNode(unconstrainedValue()); }
459     template <typename Derived>
460     inline Node addNode(const Eigen::DenseBase<Derived>& value);
461 
462     /// \brief Read only access to the value of `node`.
value(Node node)463     inline ConstValueXpr value(Node node) const
464     { assert(unsigned(node.idx()) < nodesSize()); return m_nodes.col(node.idx()); }
465 
466     /// \brief Read-write access to the value of `node`.
value(Node node)467     inline ValueXpr value(Node node)
468     { assert(unsigned(node.idx()) < nodesSize()); return m_nodes.col(node.idx()); }
469 
unconstrainedValue()470     inline UnconstrainedNodeType unconstrainedValue() const
471     { return Value::Constant(nCoeffs(), std::numeric_limits<Scalar>::quiet_NaN()); }
472 
473     /// \brief Return true iff `node` is a constraint.
isConstraint(Node node)474     inline bool isConstraint(Node node) const
475     { return isValid(node) && !std::isnan(value(node)[0]); }
476 
477     /**
478      * \brief Return true if the mesh has unknown nodes.
479      * \par Complexity
480      * This function operates in \f$O(n)\f$ with \f$n\f$ the number of nodes.
481      */
482     inline bool hasUnknowns() const;
483     inline unsigned nUnknowns() const;
484 
485     /// \}
486 
487 
488     /// \name High-level nodes manipulation
489     /// \{
490 
491     /**
492      * \brief Set nodes of all the halfedges inbetween halfedges `from` and
493      * `to` (in counter-clockwise direction) to `node`.
494      *
495      * \pre `from` and `to` mush have the same source vertex.
496      */
497     void setVertexNodes(Node node, Halfedge from, Halfedge to);
498 
499     /**
500      * \brief Similar to VGMesh::setVertexNode, but for singularities.
501      *
502      * set nodes for a singularity starting with value `fromNode` in the
503      * direction of halfedge `from` to value `toNode` in the direction of
504      * halfedge `to`.
505      *
506      * \pre The mesh must have the VertexFromValue attribute active.
507      * \pre `from` and `to` mush have the same source vertex.
508      * \pre `fromNode` and `toNode` mush be constraints.
509      */
510     void setSingularity(Node fromNode, Node toNode, Halfedge from, Halfedge to);
511 
512     /**
513      * \brief Simplify constraints when possible.
514      *
515      * This method operate in two steps:
516      * 1. Simplify each pair of opposite nodes (see
517      *    VGMesh::simplifyOppositeNodes()).
518      * 2. Go around each vertex and try to simplfy them.
519      *
520      * After processing, the resulting mesh will use less nodes than the
521      * original if simplifications where possible, but still produce the same
522      * final result after finalization and solving. It may be usefull to make
523      * the solver slightly faster or to diminish file size.
524      *
525      * One typically wish to call VGMesh::deleteUnusedNodes() and
526      * VGMesh::garbageCollection after this function to effectively remove
527      * unused nodes.
528      *
529      * \note Currently, this method only work locally. This mean for instance
530      * that it won't merge all constraint nodes with the same value if they are
531      * not on the same primitive.
532      *
533      * \warning This method does not support non-local unknown node, ie.
534      * unknown node used on different primitive of the mesh to achieve special
535      * effects like color "teleportation". Using it in such case may lead to
536      * unexpected results.
537      */
538     void simplifyConstraints();
539 
540     void simplifyVertexArcConstraints(Halfedge from, Halfedge to);
541     void simplifyEdgeConstraints(Edge e);
542 
543     /**
544      * \brief Replace `n0` and `n1` by a single node on an invalid node if
545      * possible.
546      *
547      * This is mainly an helper funciton for VGMesh::simplifyConstraints().
548      *
549      * \warning This method does not support non-local unknown node, ie.
550      * unknown node used on different primitive of the mesh to achieve special
551      * effects like color "teleportation". Using it in such case may lead to
552      * unexpected results.
553      */
554     void simplifyOppositeNodes(Node& n0, Node& n1,
555                                bool b0 = false, bool b1 = false) const;
556 
557     /**
558      * /brief Finalize a mesh with invalid node so that it can be send to a
559      * Solver.
560      *
561      * \todo create a tutorial page about this an link it from here.
562      *
563      * \warning This method does not support non-local unknown node, ie.
564      * unknown node used on different primitive of the mesh to achieve special
565      * effects like color "teleportation". Using it in such case may lead to
566      * unexpected results.
567      */
568     void finalize();
569 
570     void finalizeVertexArc(Halfedge from, Halfedge to);
571     void finalizeEdge(Edge e);
572 
573     /// \}
574     ///
575 
576 
577     /// \name Quadratic patches
578     /// \{
579 
580     /// \brief Return true if the target vertex of `h` is singular.
581     inline bool isSingular(Halfedge h) const;
582 
583     /// \brief Return the number of singular vertex around `f`.
584     inline unsigned nSingulars(Face f) const;
585 
586     /**
587      * \brief Return the number of singular faces in the mesh.
588      *
589      * \par Complexity
590      * This method opperates in \f$O(n)\f$ with \f$n\f$ the number of
591      * halfedges.
592      */
593     inline unsigned nSingularFaces() const;
594 
595     /// \}
596 
597 
598 protected:
599     // FIXME: Would likely be better to use a hash map, but this is only
600     // available in C++11...
601     typedef std::pair<Vertex, Gradient> VertexGradientPair;
602     typedef std::map<Vertex, Gradient, std::less<Vertex>,
603                      Eigen::aligned_allocator<VertexGradientPair> > VertexGradientMap;
604 
605     typedef std::pair<Edge, CurvedEdge> EdgeCurvePair;
606     typedef std::map<Edge, CurvedEdge, std::less<Edge>,
607                      Eigen::aligned_allocator<EdgeCurvePair> >  CurvedEdgesMap;
608 
609 protected:
610     /// \name Removed topological operations
611     /// \{
612 
triangulate()613     inline void triangulate() { assert(false); }
triangulate(Face)614     inline void triangulate(Face /*f*/) { assert(false); }
615 
isCollapseOk(Halfedge)616     inline bool isCollapseOk(Halfedge /*h*/) { assert(false); return false; }
collapse(Halfedge)617     inline void collapse(Halfedge /*h*/) { assert(false); }
618 
split(Face,Vertex)619     inline void split(Face /*f*/, Vertex /*v*/) { assert(false); }
split(Edge,Vertex)620     inline void split(Edge /*e*/, Vertex /*v*/) { assert(false); }
621 
insertVertex(Edge,Vertex)622     inline Halfedge insertVertex(Edge /*e*/, Vertex /*v*/)
623         { assert(false); return Halfedge(); }
insertVertex(Halfedge,Vertex)624     inline Halfedge insertVertex(Halfedge /*h*/, Vertex /*v*/)
625         { assert(false); return Halfedge(); }
626 
insertEdge(Halfedge,Halfedge)627     inline Halfedge insertEdge(Halfedge /*h0*/, Halfedge /*h1*/)
628         { assert(false); return Halfedge(); }
629 
isFlipOk(Edge)630     inline bool isFlipOk(Edge /*e*/) const { assert(false); return false; }
flip(Edge)631     inline void flip(Edge /*e*/) { assert(false); }
632 
633     /// \}
634 
635     /// \name Helper methods
636     /// \{
637 
638     void copyVGMeshMembers(const Self& rhs);
639     void findConstrainedEdgesSimplify(Vertex vx,
640                                       std::vector<Halfedge>& consEdges);
641     void resizePositionsMatrix(unsigned rows, unsigned cols);
642     void resizeNodesMatrix(unsigned rows, unsigned cols);
643 
644     /// \}
645 
646 protected:
647     static const char* _halfedgeAttrName[HALFEDGE_ATTRIB_COUNT];
648 
649 protected:
650     unsigned m_attributes;
651     ColorSpace m_colorSpace;
652 
653     PatateCommon::PropertyContainer m_nprops;
654 
655     VectorMatrix m_positions;
656     VertexGradientMap m_vertexGradientConstraints;
657     CurvedEdgesMap m_curvedEdges;
658 
659     HalfedgeProperty<Node> m_halfedgeAttributes[HALFEDGE_ATTRIB_COUNT];
660 
661     unsigned m_deletedNodes;
662     NodeMatrix m_nodes;
663     NodeProperty<bool> m_ndeleted;
664     std::vector<Node> m_gcNodeMap;
665 
666 };
667 
668 } // namespace Vitelotte
669 
670 
671 #include "vgMesh.hpp"
672 
673 
674 #endif // VGMESH_H
675 
676