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