VCG Library
Loading...
Searching...
No Matches
curve_on_manifold.h
1/****************************************************************************
2* VCGLib o o *
3* Visual and Computer Graphics Library o o *
4* _ O _ *
5* Copyright(C) 2004-2016 \/)\/ *
6* Visual Computing Lab /\/| *
7* ISTI - Italian National Research Council | *
8* \ *
9* All rights reserved. *
10* *
11* This program is free software; you can redistribute it and/or modify *
12* it under the terms of the GNU General Public License as published by *
13* the Free Software Foundation; either version 2 of the License, or *
14* (at your option) any later version. *
15* *
16* This program is distributed in the hope that it will be useful, *
17* but WITHOUT ANY WARRANTY; without even the implied warranty of *
18* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
20* for more details. *
21* *
22****************************************************************************/
23#ifndef __VCGLIB_CURVE_ON_SURF_H
24#define __VCGLIB_CURVE_ON_SURF_H
25
26#include<vcg/complex/complex.h>
27#include<vcg/simplex/face/topology.h>
28#include<vcg/complex/algorithms/update/topology.h>
29#include<vcg/complex/algorithms/update/color.h>
30#include<vcg/complex/algorithms/update/normal.h>
31#include<vcg/complex/algorithms/update/quality.h>
32#include<vcg/complex/algorithms/clean.h>
33#include<vcg/complex/algorithms/refine.h>
34#include<vcg/complex/algorithms/create/platonic.h>
35#include<vcg/complex/algorithms/point_sampling.h>
36#include <vcg/space/index/grid_static_ptr.h>
37#include <vcg/space/index/kdtree/kdtree.h>
38#include <vcg/math/histogram.h>
39#include<vcg/space/distance3.h>
40#include <vcg/complex/algorithms/attribute_seam.h>
41#include <wrap/io_trimesh/export_ply.h>
42
43namespace vcg {
44namespace tri {
47
87template <class MeshType>
88class CoM
89{
90public:
91 typedef typename MeshType::ScalarType ScalarType;
92 typedef typename MeshType::CoordType CoordType;
93 typedef typename MeshType::VertexType VertexType;
94 typedef typename MeshType::VertexPointer VertexPointer;
95 typedef typename MeshType::VertexIterator VertexIterator;
96 typedef typename MeshType::EdgeIterator EdgeIterator;
97 typedef typename MeshType::EdgeType EdgeType;
98 typedef typename MeshType::FaceType FaceType;
99 typedef typename MeshType::FacePointer FacePointer;
100 typedef typename MeshType::FaceIterator FaceIterator;
102 typedef Segment3<ScalarType> Segment3Type;
103 typedef typename vcg::GridStaticPtr<FaceType, ScalarType> MeshGrid;
104 typedef typename vcg::GridStaticPtr<EdgeType, ScalarType> EdgeGrid;
105 typedef typename face::Pos<FaceType> PosType;
107
115 class Param
116 {
117 public:
118
119 ScalarType surfDistThr;
120 ScalarType minRefEdgeLen;
121 ScalarType maxSimpEdgeLen;
122 ScalarType maxSmoothDelta;
123 ScalarType maxSnapThr;
124 ScalarType gridBailout;
126
128 Param(MeshType &m) { SetDefault(m);}
129
131 void SetDefault(MeshType &m)
132 {
133 surfDistThr = m.bbox.Diag()/1000.0;
134 minRefEdgeLen = m.bbox.Diag()/16000.0;
135 maxSimpEdgeLen = m.bbox.Diag()/100.0;
136 maxSmoothDelta = m.bbox.Diag()/100.0;
137 maxSnapThr = m.bbox.Diag()/1000.0;
138 gridBailout = m.bbox.Diag()/20.0;
139 barycentricSnapThr = 0.05;
140 }
141
143 void Dump() const
144 {
145 printf("surfDistThr = %6.4f\n",surfDistThr );
146 printf("minRefEdgeLen = %6.4f\n",minRefEdgeLen );
147 printf("maxSimpEdgeLen = %6.4f\n",maxSimpEdgeLen );
148 printf("maxSmoothDelta = %6.4f\n",maxSmoothDelta);
149 }
150 };
151
152
153
154 // ============================================================================
155 // Data Members
156 // ============================================================================
157
158 MeshType &base;
159 MeshGrid uniformGrid;
161
163 CoM(MeshType &_m) :base(_m),par(_m){}
164
165 // ============================================================================
166 // Spatial Query Methods
167 // ============================================================================
168
174 FaceType *GetClosestFace(const CoordType &p)
175 {
176 ScalarType closestDist;
177 CoordType closestP;
178 return vcg::tri::GetClosestFaceBase(base,uniformGrid,p, this->par.gridBailout, closestDist, closestP);
179 }
180
187 FaceType *GetClosestFaceIP(const CoordType &p, CoordType &ip)
188 {
189 ScalarType closestDist;
190 CoordType closestP,closestN;
191 return vcg::tri::GetClosestFaceBase(base,uniformGrid,p, this->par.gridBailout, closestDist, closestP,closestN,ip);
192 }
193
201 FaceType *GetClosestFaceIP(const CoordType &p, CoordType &ip, CoordType &in)
202 {
203 ScalarType closestDist;
204 CoordType closestP;
205 return vcg::tri::GetClosestFaceBase(base,uniformGrid,p, this->par.gridBailout, closestDist, closestP,in,ip);
206 }
207
214 FaceType *GetClosestFacePoint(const CoordType &p, CoordType &closestP)
215 {
216 ScalarType closestDist;
217 return vcg::tri::GetClosestFaceBase(base,uniformGrid,p, this->par.gridBailout, closestDist, closestP);
218 }
219
220 // ============================================================================
221 // Barycentric Coordinate and Snapping Methods
222 // ============================================================================
223
235 bool IsWellSnapped(const CoordType &ip)
236 {
237 for(int i=0;i<3;++i)
238 if( (ip[i]< par.barycentricSnapThr && ip[i]!= 0.0) ||
239 (ip[i]> (1.0 - par.barycentricSnapThr) && ip[i]!= 1.0))
240 return false;
241 assert(ip[0]+ip[1]+ip[2] == 1.0);
242 return true;
243 }
244
254 bool IsSnappedEdge(CoordType &ip, int &ei)
255 {
256 for(int i=0;i<3;++i)
257 if(ip[i]>0.0 && ip[(i+1)%3]>0.0 && ip[(i+2)%3]==0.0 ) {
258 ei=i;
259 return true;
260 }
261 ei=-1;
262 return false;
263 }
264
271 bool IsSnappedVertex(CoordType &ip, int &vi)
272 {
273 for(int i=0;i<3;++i)
274 if(ip[i]==1.0 && ip[(i+1)%3]==0.0 && ip[(i+2)%3]==0.0 ) {
275 vi=i;
276 return true;
277 }
278 vi=-1;
279 return false;
280 }
281
288 VertexPointer FindVertexSnap(FacePointer fp, CoordType &ip)
289 {
290 for(int i=0;i<3;++i)
291 if(ip[i]==1.0 && ip[(i+1)%3]==0.0 && ip[(i+2)%3]==0.0 ) return fp->V(i);
292 return 0;
293 }
294
295 // ============================================================================
296 // Polyline Tagging and Mesh Cutting Methods
297 // ============================================================================
298
318bool TagFaceEdgeSelWithPolyLine(MeshType &poly,bool markFlag=true)
319{
320 if (markFlag)
322
325
326 for(EdgeIterator ei=poly.edge.begin(); ei!=poly.edge.end();++ei)
327 {
328 CoordType ip0,ip1;
329 FaceType *f0 = GetClosestFaceIP(ei->cP(0),ip0);
330 FaceType *f1 = GetClosestFaceIP(ei->cP(1),ip1);
331
332 if(BarycentricSnap(ip0) && BarycentricSnap(ip1))
333 {
334 VertexPointer v0 = FindVertexSnap(f0,ip0);
335 VertexPointer v1 = FindVertexSnap(f1,ip1);
336
337 if(v0==0 || v1==0)
338 return false;
339 if(v0==v1)
340 return false;
341
342 FacePointer ff0,ff1;
343 int e0,e1;
344 bool ret=face::FindSharedFaces<FaceType>(v0,v1,ff0,ff1,e0,e1);
345 if(ret)
346 {
347 assert(ret);
348 assert(ff0->V(e0)==v0 || ff0->V(e0)==v1);
349 ff0->SetFaceEdgeS(e0);
350 ff1->SetFaceEdgeS(e1);
351 } else {
352 return false;
353 }
354 }
355 else {
356 return false;
357 }
358 }
359 return true;
360}
361
370 ScalarType MinDistOnEdge(CoordType samplePnt, EdgeGrid &edgeGrid, MeshType &poly, CoordType &closestPoint)
371 {
372 ScalarType polyDist;
373 EdgeType *cep = vcg::tri::GetClosestEdgeBase(poly,edgeGrid,samplePnt,par.gridBailout,polyDist,closestPoint);
374 return polyDist;
375 }
376
388 static ScalarType MinDistOnEdge(VertexType *v0,VertexType *v1, EdgeGrid &edgeGrid, MeshType &poly, CoordType &closestPoint)
389 {
390 ScalarType minPolyDist = std::numeric_limits<ScalarType>::max();
391 const ScalarType sampleNum = 50;
392 const ScalarType maxDist = poly.bbox.Diag()/10.0;
393 for(ScalarType k = 0;k<sampleNum+1;++k)
394 {
395 ScalarType polyDist;
396 CoordType closestPPoly;
397 CoordType samplePnt = (v0->P()*k +v1->P()*(sampleNum-k))/sampleNum;
398
399 EdgeType *cep = vcg::tri::GetClosestEdgeBase(poly,edgeGrid,samplePnt,maxDist,polyDist,closestPPoly);
400
401 if(polyDist < minPolyDist)
402 {
403 minPolyDist = polyDist;
404 closestPoint = samplePnt;
405// closestPoint = closestPPoly;
406 }
407 }
408 return minPolyDist;
409 }
410
411 // ============================================================================
412 // Attribute Extraction and Comparison (for Seam Processing)
413 // ============================================================================
414
428 static inline void ExtractVertex(const MeshType & srcMesh, const FaceType & f, int whichWedge, const MeshType & dstMesh, VertexType & v)
429 {
430 (void)srcMesh;
431 (void)dstMesh;
432 // This is done to preserve every single perVertex property
433 // perVextex Texture Coordinate is instead obtained from perWedge one.
434 v.ImportData(*f.cV(whichWedge));
435 v.C() = f.cC();
436 }
437
451 static inline bool CompareVertex(const MeshType & m, const VertexType & vA, const VertexType & vB)
452 {
453 (void)m;
454
455 if(vA.C() == Color4b(Color4b::Red) && vB.C() == Color4b(Color4b::Blue) ) return false;
456 if(vA.C() == Color4b(Color4b::Blue) && vB.C() == Color4b(Color4b::Red) ) return false;
457 return true;
458 }
459
460 // ============================================================================
461 // Utility Functions
462 // ============================================================================
463
473 static CoordType QLerp(VertexType *v0, VertexType *v1)
474 {
475
476 ScalarType qSum = fabs(v0->Q())+fabs(v1->Q());
477 ScalarType w0 = (qSum - fabs(v0->Q()))/qSum;
478 ScalarType w1 = (qSum - fabs(v1->Q()))/qSum;
479 return v0->P()*w0 + v1->P()*w1;
480 }
481
482
495 bool SnapPolyline(MeshType &poly)
496 {
499 int vertSnapCnt=0;
500 int edgeSnapCnt=0;
501 int borderCnt=0,midCnt=0,nonmanifCnt=0;
502 for(VertexIterator vi=poly.vert.begin(); vi!=poly.vert.end();++vi)
503 {
504 CoordType ip;
505 FaceType *f = GetClosestFaceIP(vi->cP(),ip);
506 if(BarycentricSnap(ip))
507 {
508 if(ip[0]>0 && ip[1]>0) { vi->P() = f->P(0)*ip[0]+f->P(1)*ip[1]; edgeSnapCnt++; assert(ip[2]==0); vi->C()=Color4b::White;}
509 if(ip[0]>0 && ip[2]>0) { vi->P() = f->P(0)*ip[0]+f->P(2)*ip[2]; edgeSnapCnt++; assert(ip[1]==0); vi->C()=Color4b::White;}
510 if(ip[1]>0 && ip[2]>0) { vi->P() = f->P(1)*ip[1]+f->P(2)*ip[2]; edgeSnapCnt++; assert(ip[0]==0); vi->C()=Color4b::White;}
511
512 if(ip[0]==1.0) { vi->P() = f->P(0); vertSnapCnt++; assert(ip[1]==0 && ip[2]==0); vi->C()=Color4b::Black; }
513 if(ip[1]==1.0) { vi->P() = f->P(1); vertSnapCnt++; assert(ip[0]==0 && ip[2]==0); vi->C()=Color4b::Black;}
514 if(ip[2]==1.0) { vi->P() = f->P(2); vertSnapCnt++; assert(ip[0]==0 && ip[1]==0); vi->C()=Color4b::Black;}
515 }
516 else
517 {
518 int deg = edge::VEDegree<EdgeType>(&*vi);
519 if (deg > 2) { nonmanifCnt++; vi->C()=Color4b::Magenta; }
520 if (deg < 2) { borderCnt++; vi->C()=Color4b::Green;}
521 if (deg== 2) { midCnt++; vi->C()=Color4b::Blue;}
522 }
523 }
524 printf("SnapPolyline %i vertices: snapped %i onto vert and %i onto edges %i nonmanif, %i border, %i mid\n",
525 poly.vn, vertSnapCnt, edgeSnapCnt, nonmanifCnt,borderCnt,midCnt); fflush(stdout);
528 if(dupCnt) printf("SnapPolyline: Removed %i Duplicated vertices\n",dupCnt);
529
530 return vertSnapCnt==0 && edgeSnapCnt==0 && dupCnt==0;
531 }
532
533 void SelectBoundaryVertex(MeshType &poly)
534 {
537 ForEachVertex(poly, [&](VertexType &v){
538 if(edge::VEDegree<EdgeType>(&v)==1) v.SetS();
539 });
540 }
541
542 void SelectUniformlyDistributed(MeshType &poly, int k)
543 {
544 tri::TrivialPointerSampler<MeshType> tps;
545 ScalarType samplingRadius = tri::Stat<MeshType>::ComputeEdgeLengthSum(poly)/ScalarType(k);
546 tri::SurfaceSampling<MeshType, typename tri::TrivialPointerSampler<MeshType> >::EdgeMeshUniform(poly,tps,samplingRadius);
547 for(int i=0;i<tps.sampleVec.size();++i)
548 tps.sampleVec[i]->SetS();
549 }
550
551
552
553 /*
554 * Make an edge mesh 1-manifold by splitting all the
555 * vertexes that have more than two incident edges
556 *
557 * It performs the split in three steps.
558 * - First it collects and counts the vertices to be splitten.
559 * - Then it adds the vertices to the mesh and
560 * - lastly it updates the poly with the newly added vertices.
561 *
562 * singSplitFlag allows to ubersplit each singularity in a number of vertex of the same order of its degree.
563 * This is not really necessary but helps the management of sharp turns in the poly mesh.
564 * \todo add corner detection and split.
565 */
566
567 void DecomposeNonManifoldPolyline(MeshType &poly, bool singSplitFlag = true)
568 {
569 tri::Allocator<MeshType>::CompactEveryVector(poly);
570 std::vector<int> degreeVec(poly.vn, 0);
571 tri::UpdateTopology<MeshType>::VertexEdge(poly);
572 int neededVert=0;
573 int delta;
574 if(singSplitFlag) delta = 1;
575 else delta = 2;
576
577 for(VertexIterator vi=poly.vert.begin(); vi!=poly.vert.end();++vi)
578 {
579 std::vector<EdgeType *> starVec;
580 edge::VEStarVE(&*vi,starVec);
581 degreeVec[tri::Index(poly, *vi)] = starVec.size();
582 if(starVec.size()>2)
583 neededVert += starVec.size()-delta;
584 }
585 printf("DecomposeNonManifold Adding %i vert to a polyline of %i vert\n",neededVert,poly.vn);
586 VertexIterator firstVi = tri::Allocator<MeshType>::AddVertices(poly,neededVert);
587
588 for(size_t i=0;i<degreeVec.size();++i)
589 {
590 if(degreeVec[i]>2)
591 {
592 std::vector<EdgeType *> edgeStarVec;
593 edge::VEStarVE(&(poly.vert[i]),edgeStarVec);
594 assert(edgeStarVec.size() == degreeVec[i]);
595 for(size_t j=delta;j<edgeStarVec.size();++j)
596 {
597 EdgeType *ep = edgeStarVec[j];
598 int ind; // index of the vertex to be changed
599 if(tri::Index(poly,ep->V(0)) == i) ind = 0;
600 else ind = 1;
601
602 ep->V(ind) = &*firstVi;
603 ep->V(ind)->P() = poly.vert[i].P();
604 ep->V(ind)->N() = poly.vert[i].N();
605 ++firstVi;
606 }
607 }
608 }
609 assert(firstVi == poly.vert.end());
610 }
611
612 // ============================================================================
613 // Mesh Splitting and Refinement for Polyline Integration
614 // ============================================================================
615
644 void SplitMeshWithPolyline(MeshType &poly)
645 {
646 std::vector< std::pair<int,VertexPointer> > toSplitVec; // the index of the face to be split and the poly vertex to be used
647
648 for(VertexIterator vi=poly.vert.begin(); vi!=poly.vert.end();++vi)
649 {
650 CoordType ip;
651 FaceType *f = GetClosestFaceIP(vi->cP(),ip);
652 if(!BarycentricSnap(ip))
653 toSplitVec.push_back(std::make_pair(tri::Index(base,f),&*vi));
654 }
655 SimplifyNullEdges(poly);
656 printf("SplitMeshWithPolyline found %lu non snapped points\n",toSplitVec.size()); fflush(stdout);
657
658 FaceIterator newFi = tri::Allocator<MeshType>::AddFaces(base,toSplitVec.size()*2);
659 VertexIterator newVi = tri::Allocator<MeshType>::AddVertices(base,toSplitVec.size());
661
662 for(size_t i =0; i<toSplitVec.size();++i)
663 {
664 newVi->P() = toSplitVec[i].second->P();
665 newVi->C()=Color4b::Green;
666 face::TriSplit(&base.face[toSplitVec[i].first],&*(newFi++),&*(newFi++),&*(newVi++));
667 }
668 Init(); // need to reset everthing
669 SnapPolyline(poly);
670
671 // Second loop to perform the face-face Edge split **********************
672 // This loop must be iterated multiple times becouse it can happen that more than one polyline vertices falls on the same edge.
673 // So multiple splits must be done.
674 std::map<std::pair<CoordType,CoordType>, VertexPointer> edgeToSplitMap;
675 do
676 {
677 edgeToSplitMap.clear();
678 for(VertexIterator vi=poly.vert.begin(); vi!=poly.vert.end();++vi)
679 {
680 CoordType ip;
681 FaceType *f = GetClosestFaceIP(vi->cP(),ip);
682 if(!BarycentricSnap(ip)) { assert(0); }
683 for(int i=0;i<3;++i)
684 {
685 if((ip[i ]>0 && ip[i ]<1.0) &&
686 (ip[(i+1)%3]>0 && ip[(i+1)%3]<1.0) &&
687 ip[(i+2)%3]==0 )
688 {
689 CoordType p0=f->P0(i);
690 CoordType p1=f->P1(i);
691 if (p0>p1) std::swap(p0,p1);
692 if(edgeToSplitMap[std::make_pair(p0,p1)])
693 printf("Found an already used Edge %lu - %lu vert %lu!!!\n", tri::Index(base,f->V0(i)),tri::Index(base,f->V1(i)),tri::Index(poly,&*vi));
694 edgeToSplitMap[std::make_pair(p0,p1)]=&*vi;
695 }
696 }
697 }
698 printf("SplitMeshWithPolyline: Created a map of %lu edges to be split\n",edgeToSplitMap.size());
699 EdgePointPred ePred(edgeToSplitMap);
700 EdgePointSplit eSplit(edgeToSplitMap);
702 tri::RefineE(base,eSplit,ePred);
703 Init(); // need to reset everthing
704 } while(edgeToSplitMap.size()>0); // while there are edges to be split
705 }
706
707 // ============================================================================
708 // Initialization
709 // ============================================================================
710
723 void Init()
724 {
725 // Construction of the uniform grid
728 uniformGrid.Set(base.face.begin(), base.face.end());
729 }
730
731 // ============================================================================
732 // Simplification Methods
733 // ============================================================================
734
741 void SimplifyNullEdges(MeshType &poly)
742 {
744 if(cnt)
745 printf("SimplifyNullEdges: Removed %i Duplicated vertices\n",cnt);
746 }
747
748 void SimplifyMidEdge(MeshType &poly)
749 {
750 int startVn;
751 int midEdgeCollapseCnt=0;
753 do
754 {
755 startVn = poly.vn;
756 for(int ei =0; ei<poly.en; ++ei)
757 {
758 VertexType *v0=poly.edge[ei].V(0);
759 VertexType *v1=poly.edge[ei].V(1);
760 CoordType ip0,ip1;
761 FaceType *f0=GetClosestFaceIP(v0->P(),ip0);
762 FaceType *f1=GetClosestFaceIP(v1->P(),ip1);
763
764 bool snap0=BarycentricSnap(ip0);
765 bool snap1=BarycentricSnap(ip1);
766 int e0i,e1i;
767 bool e0 = IsSnappedEdge(ip0,e0i);
768 bool e1 = IsSnappedEdge(ip1,e1i);
769 if(e0 && e1)
770 if( ( f0 == f1 && e0i == e1i) ||
771 ( f0 == f1->FFp(e1i) && e0i == f1->FFi(e1i)) ||
772 (f0->FFp(e0i) == f1 && f0->FFi(e0i) == e1i) ||
773 (f0->FFp(e0i) == f1->FFp(e1i) && f0->FFi(e0i) == f1->FFi(e1i)) )
774 {
775 CoordType newp = (v0->P()+v1->P())/2.0;
776 v0->P()=newp;
777 v1->P()=newp;
778 midEdgeCollapseCnt++;
779 }
780 }
782 tri::Allocator<MeshType>::CompactEveryVector(poly);
783// printf("SimplifyMidEdge %5i -> %5i %i mid %i ve \n",startVn,poly.vn,midEdgeCollapseCnt);
784 } while(startVn>poly.vn);
785 }
786
795 void SimplifyMidFace(MeshType &poly)
796 {
797 int startVn= poly.vn;;
798 int midFaceCollapseCnt=0;
799 int vertexEdgeCollapseCnt=0;
800 int curVn;
801 do
802 {
804 curVn = poly.vn;
806 for(int i =0; i<poly.vn;++i)
807 {
808 std::vector<VertexPointer> starVecVp;
809 edge::VVStarVE(&(poly.vert[i]),starVecVp);
810 if( (starVecVp.size()==2) )
811 {
812 CoordType ipP, ipN, ipI;
813 FacePointer fpP = GetClosestFaceIP(starVecVp[0]->P(),ipP);
814 FacePointer fpN = GetClosestFaceIP(starVecVp[1]->P(),ipN);
815 FacePointer fpI = GetClosestFaceIP(poly.vert[i].P(), ipI);
816
817 bool snapP = (BarycentricSnap(ipP));
818 bool snapN = (BarycentricSnap(ipN));
819 bool snapI = (BarycentricSnap(ipI));
820 VertexPointer vertexSnapP = 0;
821 VertexPointer vertexSnapN = 0;
822 VertexPointer vertexSnapI = 0;
823 for(int j=0;j<3;++j)
824 {
825 if(ipP[j]==1.0) vertexSnapP=fpP->V(j);
826 if(ipN[j]==1.0) vertexSnapN=fpN->V(j);
827 if(ipI[j]==1.0) vertexSnapI=fpI->V(j);
828 }
829
830 bool collapseFlag=false;
831
832 if((!snapI && snapP && snapN) || // First case a vertex that is not snapped between two snapped vertexes
833 (!snapI && !snapP && fpI==fpP) || // Or a two vertex not snapped but on the same face
834 (!snapI && !snapN && fpI==fpN) )
835 {
836 collapseFlag=true;
837 midFaceCollapseCnt++;
838 }
839
840 else // case 2) a vertex snap and edge snap we have to check that the edge do not share the same vertex of the vertex snap
841 if(snapI && snapP && snapN && vertexSnapI==0 && (vertexSnapP!=0 || vertexSnapN!=0) )
842 {
843 for(int j=0;j<3;++j) {
844 if(ipI[j]!=0 && (fpI->V(j)==vertexSnapP || fpI->V(j)==vertexSnapN)) {
845 collapseFlag=true;
846 vertexEdgeCollapseCnt++;
847 }
848 }
849 }
850
851 if(collapseFlag)
852 edge::VEEdgeCollapse(poly,&(poly.vert[i]));
853 }
854 }
855 } while(curVn>poly.vn);
856 printf("SimplifyMidFace %5i -> %5i %i mid %i ve \n",startVn,poly.vn,midFaceCollapseCnt,vertexEdgeCollapseCnt);
857 }
858
859 void Simplify(MeshType &poly)
860 {
861 int startEn = poly.en;
862 Distribution<ScalarType> hist;
863 for(int i =0; i<poly.en;++i)
864 hist.Add(edge::Length(poly.edge[i]));
865
867
868 for(int i =0; i<poly.vn;++i)
869 {
870 std::vector<VertexPointer> starVecVp;
871 edge::VVStarVE(&(poly.vert[i]),starVecVp);
872 if ((starVecVp.size()==2) && (!poly.vert[i].IsS()))
873 {
874 ScalarType newSegLen = Distance(starVecVp[0]->P(), starVecVp[1]->P());
875 Segment3Type seg(starVecVp[0]->P(),starVecVp[1]->P());
876 ScalarType segDist;
877 CoordType closestPSeg;
878 SegmentPointDistance(seg,poly.vert[i].cP(),closestPSeg,segDist);
879 CoordType fp,fn;
880 ScalarType maxSurfDist = MaxSegDist(starVecVp[0], starVecVp[1],fp,fn);
881
882 if((maxSurfDist < par.surfDistThr) && (newSegLen < par.maxSimpEdgeLen) )
883 {
884 edge::VEEdgeCollapse(poly,&(poly.vert[i]));
885 }
886 }
887 }
889 tri::Allocator<MeshType>::CompactEveryVector(poly);
891// printf("Simplify %5i -> %5i (total len %5.2f)\n",startEn,poly.en,hist.Sum());
892 }
893
894 void EvaluateHausdorffDistance(MeshType &poly, Distribution<ScalarType> &dist)
895 {
896 dist.Clear();
897 tri::UpdateTopology<MeshType>::VertexEdge(poly);
899 for(int i =0; i<poly.edge.size();++i)
900 {
901 CoordType farthestP, farthestN;
902 ScalarType maxDist = MaxSegDist(poly.edge[i].V(0),poly.edge[i].V(1), farthestP, farthestN, &dist);
903 poly.edge[i].V(0)->Q()+= maxDist;
904 poly.edge[i].V(1)->Q()+= maxDist;
905 }
906 for(int i=0;i<poly.vn;++i)
907 {
908 ScalarType deg = edge::VEDegree<EdgeType>(&poly.vert[i]);
909 poly.vert[i].Q()/=deg;
910 }
912 }
913
914
948 bool BarycentricSnap(CoordType &ip)
949 {
950 for(int i=0;i<3;++i)
951 {
952 if(ip[i] <= par.barycentricSnapThr) ip[i]=0;
953 if(ip[i] >= 1.0-par.barycentricSnapThr) ip[i]=1;
954 }
955 ScalarType sum = ip[0]+ip[1]+ip[2];
956
957 for(int i=0;i<3;++i)
958 if(ip[i]!=1.0) ip[i]/=sum;
959
960 sum = ip[0]+ip[1]+ip[2];
961
962 if(sum!=1.0){
963 for(int i=0;i<3;++i)
964 if(ip[i]>0.0 && ip[i]<1.0) // if it is non snapped
965 ip[i]=1.0-(ip[(i+1)%3]+ip[(i+2)%3]);
966 }
967
968 sum = ip[0]+ip[1]+ip[2];
969 assert(sum ==1.0);
970 assert(IsWellSnapped(ip));
971 if(ip[0]==0 || ip[1]==0 || ip[2]==0) return true;
972 return false;
973 }
974
975
993 bool TestSplitSegWithMesh(VertexType *v0, VertexType *v1, CoordType &splitPt)
994 {
995 Segment3Type segPoly(v0->P(),v1->P());
996 const ScalarType sampleNum = 40;
997 CoordType ip0,ip1;
998
999 FaceType *f0=GetClosestFaceIP(v0->P(),ip0);
1000 FaceType *f1=GetClosestFaceIP(v1->P(),ip1);
1001 if(f0==f1) return false;
1002
1003 bool snap0=false,snap1=false; // true if the segment start/end on a edge/vert
1004
1005 Segment3Type seg0; // The two segments to be avoided
1006 Segment3Type seg1; // from which the current poly segment can start
1007 VertexPointer vertexSnap0 = 0;
1008 VertexPointer vertexSnap1 = 0;
1009 if(BarycentricSnap(ip0)) {
1010 snap0=true;
1011 for(int i=0;i<3;++i) {
1012 if(ip0[i]==1.0) vertexSnap0=f0->V(i);
1013 if(ip0[i]==0.0) seg0=Segment3Type(f0->P1(i),f0->P2(i));
1014 }
1015 }
1016 if(BarycentricSnap(ip1)) {
1017 snap1=true;
1018 for(int i=0;i<3;++i){
1019 if(ip1[i]==1.0) vertexSnap1=f1->V(i);
1020 if(ip1[i]==0.0) seg1=Segment3Type(f1->P1(i),f1->P2(i));
1021 }
1022 }
1023
1024 CoordType bestSplitPt(0,0,0);
1025 ScalarType bestDist = std::numeric_limits<ScalarType>::max();
1026 for(ScalarType k = 1;k<sampleNum;++k)
1027 {
1028 CoordType samplePnt = segPoly.Lerp(k/sampleNum);
1029 CoordType ip;
1030 FaceType *f=GetClosestFaceIP(samplePnt,ip);
1031// BarycentricEdgeSnap(ip);
1032 if(BarycentricSnap(ip))
1033 {
1034 VertexPointer vertexSnapI = 0;
1035 for(int i=0;i<3;++i)
1036 if(ip[i]==1.0) vertexSnapI=f->V(i);
1037 CoordType closestPt = f->P(0)*ip[0]+f->P(1)*ip[1]+f->P(2)*ip[2];
1038 if(Distance(samplePnt,closestPt) < bestDist )
1039 {
1040 ScalarType dist0=std::numeric_limits<ScalarType>::max();
1041 ScalarType dist1=std::numeric_limits<ScalarType>::max();
1042 CoordType closestSegPt;
1043 if(snap0) SegmentPointDistance(seg0,closestPt,closestSegPt,dist0);
1044 if(snap1) SegmentPointDistance(seg1,closestPt,closestSegPt,dist1);
1045 if( (!vertexSnapI && (dist0 > par.surfDistThr/1000 && dist1>par.surfDistThr/1000) ) ||
1046 ( vertexSnapI!=vertexSnap0 && vertexSnapI!=vertexSnap1) )
1047 {
1048 bestDist = Distance(samplePnt,closestPt);
1049 bestSplitPt = closestPt;
1050 }
1051 }
1052 }
1053 }
1054 if(bestDist < par.surfDistThr*100)
1055 {
1056 splitPt = bestSplitPt;
1057 return true;
1058 }
1059
1060 return false;
1061 }
1076 bool SnappedOnSameFace(FacePointer f0, CoordType i0, FacePointer f1, CoordType i1)
1077 {
1078 if(f0==f1) return true;
1079 int e0,e1;
1080 int v0,v1;
1081 bool e0Snap = IsSnappedEdge(i0,e0);
1082 bool e1Snap = IsSnappedEdge(i1,e1);
1083 bool v0Snap = IsSnappedVertex(i0,v0);
1084 bool v1Snap = IsSnappedVertex(i1,v1);
1085 FacePointer f0p=0; int e0p=-1; // When Edge snap the other face and the index of the snapped edge on the other face
1086 FacePointer f1p=0; int e1p=-1;
1087 assert((e0Snap != v0Snap) && (e1Snap != v1Snap));
1088 // For EdgeSnap compute the 'other' face stuff
1089 if(e0Snap){
1090 f0p = f0->FFp(e0); e0p=f0->FFi(e0); assert(f0p->FFp(e0p)==f0);
1091 }
1092 if(e1Snap){
1093 f1p = f1->FFp(e1); e1p=f1->FFi(e1); assert(f1p->FFp(e1p)==f1);
1094 }
1095
1096 if(e0Snap && e1Snap) {
1097 if(f0==f1p || f0p==f1p || f0p==f1 || f0==f1) return true;
1098 }
1099
1100 if(e0Snap && v1Snap) {
1101 assert(v1>=0 && v1<3 && v0==-1 && e1==-1);
1102 if(f0->V2(e0) ==f1->V(v1)) return true;
1103 if(f0p->V2(e0p)==f1->V(v1)) return true;
1104 }
1105
1106 if(e1Snap && v0Snap) {
1107 assert(v0>=0 && v0<3 && v1==-1 && e0==-1);
1108 if(f1->V2(e1) ==f0->V(v0)) return true;
1109 if(f1p->V2(e1p)==f0->V(v0)) return true;
1110 }
1111
1112 if(v1Snap && v0Snap) {
1113 PosType startPos(f0,f0->V(v0));
1114 PosType curPos=startPos;
1115 do
1116 {
1117 assert(curPos.V()==f0->V(v0));
1118 if(curPos.VFlip()==f1->V(v1)) return true;
1119 curPos.FlipE();
1120 curPos.FlipF();
1121 }
1122 while(curPos!=startPos);
1123 }
1124 return false;
1125 }
1126
1144 bool TestSplitSegWithMeshAdapt(VertexType *v0, VertexType *v1, CoordType &splitPt)
1145 {
1146 splitPt=(v0->P()+v1->P())/2.0;
1147
1148 CoordType ip0,ip1,ipm;
1149 FaceType *f0=GetClosestFaceIP(v0->P(),ip0);
1150 FaceType *f1=GetClosestFaceIP(v1->P(),ip1);
1151 FaceType *fm=GetClosestFaceIP(splitPt,ipm);
1152
1153 if(f0==f1) return false;
1154
1155 bool snap0=BarycentricSnap(ip0);
1156 bool snap1=BarycentricSnap(ip1);
1157 bool snapm=BarycentricSnap(ipm);
1158
1159 splitPt = fm->P(0)*ipm[0]+fm->P(1)*ipm[1]+fm->P(2)*ipm[2];
1160
1161 if(!snap0 && !snap1) {
1162 assert(f0!=f1);
1163 return true;
1164 }
1165 if(snap0 && snap1)
1166 {
1167 if(SnappedOnSameFace(f0,ip0,f1,ip1))
1168 return false;
1169 }
1170
1171 if(snap0) {
1172 int e0,v0;
1173 if (IsSnappedEdge(ip0,e0)) {
1174 if(f0->FFp(e0) == f1) return false;
1175 }
1176 if(IsSnappedVertex(ip0,v0)) {
1177 for(int i=0;i<3;++i)
1178 if(f1->V(i)==f0->V(v0)) return false;
1179 }
1180 }
1181 if(snap1) {
1182 int e1,v1;
1183 if (IsSnappedEdge(ip1,e1)) {
1184 if(f1->FFp(e1) == f0) return false;
1185 }
1186 if(IsSnappedVertex(ip1,v1)) {
1187 for(int i=0;i<3;++i)
1188 if(f0->V(i)==f1->V(v1)) return false;
1189 }
1190 }
1191
1192 return true;
1193 }
1194
1195
1196 bool TestSplitSegWithMeshAdaptOld(VertexType *v0, VertexType *v1, CoordType &splitPt)
1197 {
1198 Segment3Type segPoly(v0->P(),v1->P());
1199 const ScalarType sampleNum = 40;
1200 CoordType ip0,ip1;
1201 FaceType *f0=GetClosestFaceIP(v0->P(),ip0);
1202 FaceType *f1=GetClosestFaceIP(v1->P(),ip1);
1203 if(f0==f1) return false;
1204
1205 bool snap0=BarycentricSnap(ip0);
1206 bool snap1=BarycentricSnap(ip1);
1207
1208 if(!snap0 && !snap1) {
1209 assert(f0!=f1);
1210 splitPt=(v0->P()+v1->P())/2.0;
1211 return true;
1212 }
1213 if(snap0 && snap1)
1214 {
1215 if(SnappedOnSameFace(f0,ip0,f1,ip1))
1216 return false;
1217 }
1218
1219 if(snap0) {
1220 int e0,v0;
1221 if (IsSnappedEdge(ip0,e0)) {
1222 if(f0->FFp(e0) == f1) return false;
1223 }
1224 if(IsSnappedVertex(ip0,v0)) {
1225 for(int i=0;i<3;++i)
1226 if(f1->V(i)==f0->V(v0)) return false;
1227 }
1228 }
1229 splitPt=(v0->P()+v1->P())/2.0;
1230 return true;
1231 }
1232
1233 // Given a segment find the maximum distance from it to the original surface.
1234 // It is used to evaluate the Haustdorff distance of a Segment from the mesh.
1235 ScalarType MaxSegDist(VertexType *v0, VertexType *v1, CoordType &farthestPointOnSurf, CoordType &farthestN, Distribution<ScalarType> *dist=0)
1236 {
1237 ScalarType maxSurfDist = 0;
1238 const ScalarType sampleNum = 10;
1239 const ScalarType maxDist = base.bbox.Diag()/10.0;
1240 for(ScalarType k = 1;k<sampleNum;++k)
1241 {
1242 ScalarType surfDist;
1243 CoordType closestPSurf;
1244 CoordType samplePnt = (v0->P()*k +v1->P()*(sampleNum-k))/sampleNum;
1245 FaceType *f = vcg::tri::GetClosestFaceBase(base,uniformGrid,samplePnt,maxDist, surfDist, closestPSurf);
1246 if(dist)
1247 dist->Add(surfDist);
1248 assert(f);
1249 if(surfDist > maxSurfDist)
1250 {
1251 maxSurfDist = surfDist;
1252 farthestPointOnSurf = closestPSurf;
1253 farthestN = f->N();
1254 }
1255 }
1256 return maxSurfDist;
1257 }
1258
1259
1271 void RefineCurveByDistance(MeshType &poly)
1272 {
1274 int startEdgeSize = poly.en;
1275 for(int i =0; i<startEdgeSize;++i)
1276 {
1277 EdgeType &ei = poly.edge[i];
1278 if(edge::Length(ei)>par.minRefEdgeLen)
1279 {
1280 CoordType farthestP, farthestN;
1281 ScalarType maxDist = MaxSegDist(ei.V(0),ei.V(1),farthestP, farthestN);
1282 if(maxDist > par.surfDistThr)
1283 {
1284 edge::VEEdgeSplit(poly, &ei, farthestP, farthestN);
1285 }
1286 }
1287 }
1288// tri::Allocator<MeshType>::CompactEveryVector(poly);
1289// printf("Refine %i -> %i\n",startEdgeSize,poly.en);fflush(stdout);
1290 }
1291
1297 void RefineCurveByBaseMesh(MeshType &poly)
1298 {
1300 std::vector<int> edgeToRefineVec;
1301 for(int i=0; i<poly.en;++i)
1302 edgeToRefineVec.push_back(i);
1303 int startEn=poly.en;
1304 int iterCnt=0;
1305 while (!edgeToRefineVec.empty() && iterCnt<100) {
1306 iterCnt++;
1307 std::vector<int> edgeToRefineVecNext;
1308 for(int i=0; i<edgeToRefineVec.size();++i)
1309 {
1310 EdgeType &e = poly.edge[edgeToRefineVec[i]];
1311 CoordType splitPt;
1312 if(TestSplitSegWithMeshAdapt(e.V(0),e.V(1),splitPt))
1313 {
1314 edge::VEEdgeSplit(poly, &e, splitPt);
1315 edgeToRefineVecNext.push_back(edgeToRefineVec[i]);
1316 edgeToRefineVecNext.push_back(poly.en-1);
1317 }
1318 }
1320 swap(edgeToRefineVecNext,edgeToRefineVec);
1321 printf("RefineCurveByBaseMesh %i en -> %i en\n",startEn,poly.en); fflush(stdout);
1322 }
1323//
1324 SimplifyNullEdges(poly);
1325 SimplifyMidFace(poly);
1326 SimplifyMidEdge(poly);
1327 SnapPolyline(poly);
1328 printf("RefineCurveByBaseMesh %i en -> %i en\n",startEn,poly.en); fflush(stdout);
1329 }
1330
1331
1332
1347 void SmoothProject(MeshType &poly, int iterNum, ScalarType smoothWeight, ScalarType projectWeight)
1348 {
1349 tri::RequireCompactness(poly);
1351// printf("SmoothProject: Selected vert num %i\n",tri::UpdateSelection<MeshType>::VertexCount(poly));
1352 assert(poly.en>0 && base.fn>0);
1353 for(int k=0;k<iterNum;++k)
1354 {
1355 if(k==iterNum-1) projectWeight=1;
1356
1357 std::vector<CoordType> posVec(poly.vn,CoordType(0,0,0));
1358 std::vector<int> cntVec(poly.vn,0);
1359
1360 for(int i =0; i<poly.en;++i)
1361 {
1362 for(int j=0;j<2;++j)
1363 {
1364 int vertInd = tri::Index(poly,poly.edge[i].V0(j));
1365 posVec[vertInd] += poly.edge[i].V1(j)->P();
1366 cntVec[vertInd] += 1;
1367 }
1368 }
1369
1370 const ScalarType maxDist = base.bbox.Diag()/10.0;
1371 for(int i=0; i<poly.vn; ++i)
1372 if(!poly.vert[i].IsS())
1373 {
1374 CoordType smoothPos = (poly.vert[i].P() + posVec[i])/ScalarType(cntVec[i]+1);
1375
1376 CoordType newP = poly.vert[i].P()*(1.0-smoothWeight) + smoothPos *smoothWeight;
1377
1378// CoordType delta = newP - poly.vert[i].P();
1379// if(delta.Norm() > par.maxSmoothDelta)
1380// {
1381// newP = poly.vert[i].P() + ( delta / delta.Norm()) * maxDist*0.5;
1382// }
1383
1384 ScalarType minDist;
1385 CoordType closestP;
1386 FaceType *f = vcg::tri::GetClosestFaceBase(base,uniformGrid,newP,maxDist, minDist, closestP);
1387 assert(f);
1388 poly.vert[i].P() = newP*(1.0-projectWeight) +closestP*projectWeight;
1389 poly.vert[i].N() = f->N();
1390 }
1391
1392 // Refine(poly);
1394 RefineCurveByDistance(poly);
1396 Simplify(poly);
1398 int dupVertNum = Clean<MeshType>::RemoveDuplicateVertex(poly);
1399 if(dupVertNum) {
1400// printf("****REMOVED %i Duplicated\n",dupVertNum);
1403 }
1404 }
1405 }
1406
1407
1409{
1410public:
1411 std::map<std::pair<CoordType,CoordType>, VertexPointer> &edgeToPolyVertMap;
1412
1413 EdgePointPred(std::map<std::pair<CoordType,CoordType>, VertexPointer> &_edgeToPolyVertMap):edgeToPolyVertMap(_edgeToPolyVertMap){};
1414 bool operator()(face::Pos<FaceType> ep) const
1415 {
1416 CoordType p0 = ep.V()->P();
1417 CoordType p1 = ep.VFlip()->P();
1418 if (p0>p1) std::swap(p0,p1);
1419 return edgeToPolyVertMap.find(std::make_pair(p0,p1)) != edgeToPolyVertMap.end();
1420 }
1421};
1422
1424{
1425public:
1426 std::map<std::pair<CoordType,CoordType>, VertexPointer> &edgeToPolyVertMap;
1427
1428 EdgePointSplit(std::map<std::pair<CoordType,CoordType>, VertexPointer> &_edgeToPolyVertMap):edgeToPolyVertMap(_edgeToPolyVertMap){};
1429 void operator()(VertexType &nv, face::Pos<FaceType> ep)
1430 {
1431 CoordType p0 = ep.V()->P();
1432 CoordType p1 = ep.VFlip()->P();
1433 if (p0>p1) std::swap(p0,p1);
1434 VertexPointer vp=edgeToPolyVertMap[std::make_pair(p0,p1)];
1435 assert(vp);
1436 nv.P()=vp->P();
1437 return;
1438 }
1439 Color4b WedgeInterp(Color4b &c0, Color4b &c1)
1440 {
1441 Color4b cc;
1442 cc.lerp(c0,c1,0.5f);
1443 return Color4b::Red;
1444 }
1445 TexCoord2f WedgeInterp(TexCoord2f &t0, TexCoord2f &t1)
1446 {
1447 TexCoord2f tmp;
1448 assert(t0.n()== t1.n());
1449 tmp.n()=t0.n();
1450 tmp.t()=(t0.t()+t1.t())/2.0;
1451 return tmp;
1452 }
1453};
1454
1455};
1456
1457} // end namespace tri
1458} // end namespace vcg
1459
1460#endif // __VCGLIB_CURVE_ON_SURF_H
Definition: box3.h:42
Definition: color4.h:41
Class to safely add and delete elements in a mesh.
Definition: allocate.h:97
static VertexIterator AddVertices(MeshType &m, size_t n, PointerUpdater< VertexPointer > &pu)
Add n vertices to the mesh. Function to add n vertices to the mesh. The elements are added always to ...
Definition: allocate.h:189
static FaceIterator AddFaces(MeshType &m, size_t n)
Function to add n faces to the mesh. First wrapper, with no parameters.
Definition: allocate.h:615
static int RemoveDuplicateVertex(MeshType &m, bool RemoveDegenerateFlag=true)
Definition: clean.h:206
Definition: curve_on_manifold.h:1409
Parameter class controlling the behavior of CoM algorithms.
Definition: curve_on_manifold.h:116
ScalarType surfDistThr
Max distance between surface and curve; used in simplify and refine.
Definition: curve_on_manifold.h:119
ScalarType barycentricSnapThr
Threshold for snapping barycentric coords to 0 or 1 (controls vertex/edge snapping)
Definition: curve_on_manifold.h:125
ScalarType gridBailout
The maximum distance bailout used in grid-based spatial queries.
Definition: curve_on_manifold.h:124
ScalarType maxSimpEdgeLen
Maximal admitted edge length (used in simplify: never make edges longer than this)
Definition: curve_on_manifold.h:121
void SetDefault(MeshType &m)
Set all parameters to reasonable defaults based on the mesh bounding box.
Definition: curve_on_manifold.h:131
ScalarType minRefEdgeLen
Minimal admitted edge length (used in refine: never make edges shorter than this)
Definition: curve_on_manifold.h:120
ScalarType maxSnapThr
The maximum distance allowed when snapping a polyline vertex onto a mesh vertex (currently unused)
Definition: curve_on_manifold.h:123
void Dump() const
Print current parameter values to stdout.
Definition: curve_on_manifold.h:143
ScalarType maxSmoothDelta
The maximum movement admitted during smoothing (currently unused)
Definition: curve_on_manifold.h:122
Param(MeshType &m)
Constructor with default parameter initialization based on mesh size.
Definition: curve_on_manifold.h:128
A class for managing curves on a 2-manifold (Curve on Manifold - CoM).
Definition: curve_on_manifold.h:89
ScalarType MinDistOnEdge(CoordType samplePnt, EdgeGrid &edgeGrid, MeshType &poly, CoordType &closestPoint)
Find the minimum distance from a sample point to the polyline.
Definition: curve_on_manifold.h:370
MeshType & base
Reference to the base triangulated surface mesh.
Definition: curve_on_manifold.h:158
void SimplifyNullEdges(MeshType &poly)
Remove duplicate/zero-length edges from a polyline.
Definition: curve_on_manifold.h:741
VertexPointer FindVertexSnap(FacePointer fp, CoordType &ip)
Find the vertex pointer for a vertex-snapped barycentric coordinate.
Definition: curve_on_manifold.h:288
FaceType * GetClosestFace(const CoordType &p)
Get the closest face to a query point.
Definition: curve_on_manifold.h:174
MeshGrid uniformGrid
Spatial acceleration structure for closest point queries.
Definition: curve_on_manifold.h:159
FaceType * GetClosestFaceIP(const CoordType &p, CoordType &ip)
Get the closest face and its barycentric coordinates.
Definition: curve_on_manifold.h:187
void RefineCurveByBaseMesh(MeshType &poly)
RefineCurveByBaseMesh.
Definition: curve_on_manifold.h:1297
Param par
Parameters controlling algorithm behavior.
Definition: curve_on_manifold.h:160
bool TagFaceEdgeSelWithPolyLine(MeshType &poly, bool markFlag=true)
Tag face edges of the base mesh that coincide with polyline edges.
Definition: curve_on_manifold.h:318
void SimplifyMidFace(MeshType &poly)
SimplifyMidFace remove all the vertices that in the mid of a face and between two of the points snapp...
Definition: curve_on_manifold.h:795
CoM(MeshType &_m)
Constructor: initializes the CoM with a base mesh.
Definition: curve_on_manifold.h:163
FaceType * GetClosestFacePoint(const CoordType &p, CoordType &closestP)
Get the closest face and the closest point on it.
Definition: curve_on_manifold.h:214
bool SnapPolyline(MeshType &poly)
SnapPolyline snaps the vertexes of a polyline onto the base mesh.
Definition: curve_on_manifold.h:495
static CoordType QLerp(VertexType *v0, VertexType *v1)
Compute quality-weighted linear interpolation between two vertices.
Definition: curve_on_manifold.h:473
bool IsWellSnapped(const CoordType &ip)
Test if a barycentric coordinate is well snapped.
Definition: curve_on_manifold.h:235
bool SnappedOnSameFace(FacePointer f0, CoordType i0, FacePointer f1, CoordType i1)
SnappedOnSameFace Return true if the two points are snapped to a common face;.
Definition: curve_on_manifold.h:1076
bool TestSplitSegWithMeshAdapt(VertexType *v0, VertexType *v1, CoordType &splitPt)
TestSplitSegWithMesh Given a poly segment decide if it should be split along elements of base mesh.
Definition: curve_on_manifold.h:1144
FaceType * GetClosestFaceIP(const CoordType &p, CoordType &ip, CoordType &in)
Get the closest face, barycentric coordinates, and normal.
Definition: curve_on_manifold.h:201
void RefineCurveByDistance(MeshType &poly)
RefineCurve.
Definition: curve_on_manifold.h:1271
bool BarycentricSnap(CoordType &ip)
Snap barycentric coordinates to 0 or 1 if within threshold.
Definition: curve_on_manifold.h:948
void Init()
Initialize the CoM data structures for processing.
Definition: curve_on_manifold.h:723
void SmoothProject(MeshType &poly, int iterNum, ScalarType smoothWeight, ScalarType projectWeight)
SmoothProject.
Definition: curve_on_manifold.h:1347
bool TestSplitSegWithMesh(VertexType *v0, VertexType *v1, CoordType &splitPt)
TestSplitSegWithMesh Given a poly segment decide if it should be split along elements of base mesh.
Definition: curve_on_manifold.h:993
static bool CompareVertex(const MeshType &m, const VertexType &vA, const VertexType &vB)
Compare two vertices for seam compatibility.
Definition: curve_on_manifold.h:451
static void ExtractVertex(const MeshType &srcMesh, const FaceType &f, int whichWedge, const MeshType &dstMesh, VertexType &v)
Extract vertex attributes for seam processing.
Definition: curve_on_manifold.h:428
bool IsSnappedVertex(CoordType &ip, int &vi)
Check if a barycentric coordinate is snapped to a vertex.
Definition: curve_on_manifold.h:271
static ScalarType MinDistOnEdge(VertexType *v0, VertexType *v1, EdgeGrid &edgeGrid, MeshType &poly, CoordType &closestPoint)
Find the closest point on a mesh edge to the polyline (static version)
Definition: curve_on_manifold.h:388
bool IsSnappedEdge(CoordType &ip, int &ei)
Check if a barycentric coordinate is snapped to an edge.
Definition: curve_on_manifold.h:254
void SplitMeshWithPolyline(MeshType &poly)
Split the base mesh to make it conforming with the polyline.
Definition: curve_on_manifold.h:644
static int PerVertexConstant(MeshType &m, Color4b vs=Color4b::White, bool selected=false)
This function colors all (or the selected) the vertices of a mesh.
Definition: color.h:83
static void PerVertexQualityRamp(MeshType &m, ScalarType minq=0., ScalarType maxq=0., vcg::ColorMap cmap=vcg::ColorMap::RGB)
This function colores all the faces of a mesh with a hue color shade dependent on the quality.
Definition: color.h:222
Management, updating and computation of per-vertex and per-face flags (like border flags).
Definition: flag.h:44
static void PerFaceNormalized(ComputeMeshType &m)
Equivalent to PerFace() and NormalizePerFace()
Definition: normal.h:276
static void VertexConstant(MeshType &m, VertexQualityType q)
Definition: quality.h:67
static size_t VertexClear(MeshType &m)
This function clear the selection flag for all the vertices.
Definition: selection.h:237
Auxiliary data structure for computing face face adjacency information.
Definition: topology.h:149
Generation of per-vertex and per-face topological information.
Definition: topology.h:43
static void VertexFace(MeshType &m)
Update the Vertex-Face topological relation.
Definition: topology.h:467
static void FaceFace(MeshType &m)
Update the Face-Face topological relation by allowing to retrieve for each face what other faces shar...
Definition: topology.h:395
static void TestVertexEdge(MeshType &m)
Test correctness of VEtopology.
Definition: topology.h:584
void ForEachVertex(const MeshType &m, Callable action)
Definition: foreach.h:126
void TriSplit(FaceType *fToSplit, FaceType *newf0, FaceType *newf1, typename FaceType::VertexType *newVert)
Definition: topology.h:842
Definition: color4.h:30
Definition: curve_on_manifold.h:1424