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 maxMoveDelta;
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 maxMoveDelta = 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("maxMoveDelta = %6.4f\n",maxMoveDelta);
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
320bool TagFaceEdgeSelWithPolyLine(MeshType &poly,bool markFlag=true)
321{
322 if (markFlag)
324
327
328 for(EdgeIterator ei=poly.edge.begin(); ei!=poly.edge.end();++ei)
329 {
330 CoordType ip0,ip1;
331 FaceType *f0 = GetClosestFaceIP(ei->cP(0),ip0);
332 FaceType *f1 = GetClosestFaceIP(ei->cP(1),ip1);
333
334 if(BarycentricSnap(ip0) && BarycentricSnap(ip1))
335 {
336 VertexPointer v0 = FindVertexSnap(f0,ip0);
337 VertexPointer v1 = FindVertexSnap(f1,ip1);
338
339 if(v0==0 || v1==0)
340 return false;
341 if(v0==v1)
342 return false;
343
344 FacePointer ff0,ff1;
345 int e0,e1;
346 bool ret=face::FindSharedFaces<FaceType>(v0,v1,ff0,ff1,e0,e1);
347 if(ret)
348 {
349 assert(ret);
350 assert(ff0->V(e0)==v0 || ff0->V(e0)==v1);
351 ff0->SetFaceEdgeS(e0);
352 ff1->SetFaceEdgeS(e1);
353 } else {
354 return false;
355 }
356 }
357 else {
358 return false;
359 }
360 }
361 return true;
362}
363
372 ScalarType MinDistOnEdge(CoordType samplePnt, EdgeGrid &edgeGrid, MeshType &poly, CoordType &closestPoint)
373 {
374 ScalarType polyDist;
375 EdgeType *cep = vcg::tri::GetClosestEdgeBase(poly,edgeGrid,samplePnt,par.gridBailout,polyDist,closestPoint);
376 return polyDist;
377 }
378
390 static ScalarType MinDistOnEdge(VertexType *v0,VertexType *v1, EdgeGrid &edgeGrid, MeshType &poly, CoordType &closestPoint)
391 {
392 ScalarType minPolyDist = std::numeric_limits<ScalarType>::max();
393 const ScalarType sampleNum = 50;
394 const ScalarType maxDist = poly.bbox.Diag()/10.0;
395 for(ScalarType k = 0;k<sampleNum+1;++k)
396 {
397 ScalarType polyDist;
398 CoordType closestPPoly;
399 CoordType samplePnt = (v0->P()*k +v1->P()*(sampleNum-k))/sampleNum;
400
401 EdgeType *cep = vcg::tri::GetClosestEdgeBase(poly,edgeGrid,samplePnt,maxDist,polyDist,closestPPoly);
402
403 if(polyDist < minPolyDist)
404 {
405 minPolyDist = polyDist;
406 closestPoint = samplePnt;
407// closestPoint = closestPPoly;
408 }
409 }
410 return minPolyDist;
411 }
412
413 // ============================================================================
414 // Attribute Extraction and Comparison (for Seam Processing)
415 // ============================================================================
416
430 static inline void ExtractVertex(const MeshType & srcMesh, const FaceType & f, int whichWedge, const MeshType & dstMesh, VertexType & v)
431 {
432 (void)srcMesh;
433 (void)dstMesh;
434 // This is done to preserve every single perVertex property
435 // perVextex Texture Coordinate is instead obtained from perWedge one.
436 v.ImportData(*f.cV(whichWedge));
437 v.C() = f.cC();
438 }
439
453 static inline bool CompareVertex(const MeshType & m, const VertexType & vA, const VertexType & vB)
454 {
455 (void)m;
456
457 if(vA.C() == Color4b(Color4b::Red) && vB.C() == Color4b(Color4b::Blue) ) return false;
458 if(vA.C() == Color4b(Color4b::Blue) && vB.C() == Color4b(Color4b::Red) ) return false;
459 return true;
460 }
461
462 // ============================================================================
463 // Utility Functions
464 // ============================================================================
465
475 static CoordType QLerp(VertexType *v0, VertexType *v1)
476 {
477
478 ScalarType qSum = fabs(v0->Q())+fabs(v1->Q());
479 ScalarType w0 = (qSum - fabs(v0->Q()))/qSum;
480 ScalarType w1 = (qSum - fabs(v1->Q()))/qSum;
481 return v0->P()*w0 + v1->P()*w1;
482 }
483
484
497 bool SnapPolyline(MeshType &poly)
498 {
501 int vertSnapCnt=0;
502 int edgeSnapCnt=0;
503 int borderCnt=0,midCnt=0,nonmanifCnt=0;
504 for(VertexIterator vi=poly.vert.begin(); vi!=poly.vert.end();++vi)
505 {
506 CoordType ip;
507 FaceType *f = GetClosestFaceIP(vi->cP(),ip);
508 if(BarycentricSnap(ip))
509 {
510 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;}
511 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;}
512 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;}
513
514 if(ip[0]==1.0) { vi->P() = f->P(0); vertSnapCnt++; assert(ip[1]==0 && ip[2]==0); vi->C()=Color4b::Black; }
515 if(ip[1]==1.0) { vi->P() = f->P(1); vertSnapCnt++; assert(ip[0]==0 && ip[2]==0); vi->C()=Color4b::Black;}
516 if(ip[2]==1.0) { vi->P() = f->P(2); vertSnapCnt++; assert(ip[0]==0 && ip[1]==0); vi->C()=Color4b::Black;}
517 }
518 else
519 {
520 int deg = edge::VEDegree<EdgeType>(&*vi);
521 if (deg > 2) { nonmanifCnt++; vi->C()=Color4b::Magenta; }
522 if (deg < 2) { borderCnt++; vi->C()=Color4b::Green;}
523 if (deg== 2) { midCnt++; vi->C()=Color4b::Blue;}
524 }
525 }
526 printf("SnapPolyline %i vertices: snapped %i onto vert and %i onto edges %i nonmanif, %i border, %i mid\n",
527 poly.vn, vertSnapCnt, edgeSnapCnt, nonmanifCnt,borderCnt,midCnt); fflush(stdout);
530 if(dupCnt) printf("SnapPolyline: Removed %i Duplicated vertices\n",dupCnt);
531
532 return vertSnapCnt==0 && edgeSnapCnt==0 && dupCnt==0;
533 }
534
535 void SelectBoundaryVertex(MeshType &poly)
536 {
539 ForEachVertex(poly, [&](VertexType &v){
540 if(edge::VEDegree<EdgeType>(&v)==1) v.SetS();
541 });
542 }
543
544 void SelectUniformlyDistributed(MeshType &poly, int k)
545 {
546 tri::TrivialPointerSampler<MeshType> tps;
547 ScalarType samplingRadius = tri::Stat<MeshType>::ComputeEdgeLengthSum(poly)/ScalarType(k);
548 tri::SurfaceSampling<MeshType, typename tri::TrivialPointerSampler<MeshType> >::EdgeMeshUniform(poly,tps,samplingRadius);
549 for(int i=0;i<tps.sampleVec.size();++i)
550 tps.sampleVec[i]->SetS();
551 }
552
553
554
555 /*
556 * Make an edge mesh 1-manifold by splitting all the
557 * vertexes that have more than two incident edges
558 *
559 * It performs the split in three steps.
560 * - First it collects and counts the vertices to be splitten.
561 * - Then it adds the vertices to the mesh and
562 * - lastly it updates the poly with the newly added vertices.
563 *
564 * singSplitFlag allows to ubersplit each singularity in a number of vertex of the same order of its degree.
565 * This is not really necessary but helps the management of sharp turns in the poly mesh.
566 * \todo add corner detection and split.
567 */
568
569 void DecomposeNonManifoldPolyline(MeshType &poly, bool singSplitFlag = true)
570 {
571 tri::Allocator<MeshType>::CompactEveryVector(poly);
572 std::vector<int> degreeVec(poly.vn, 0);
573 tri::UpdateTopology<MeshType>::VertexEdge(poly);
574 int neededVert=0;
575 int delta;
576 if(singSplitFlag) delta = 1;
577 else delta = 2;
578
579 for(VertexIterator vi=poly.vert.begin(); vi!=poly.vert.end();++vi)
580 {
581 std::vector<EdgeType *> starVec;
582 edge::VEStarVE(&*vi,starVec);
583 degreeVec[tri::Index(poly, *vi)] = starVec.size();
584 if(starVec.size()>2)
585 neededVert += starVec.size()-delta;
586 }
587 printf("DecomposeNonManifold Adding %i vert to a polyline of %i vert\n",neededVert,poly.vn);
588 VertexIterator firstVi = tri::Allocator<MeshType>::AddVertices(poly,neededVert);
589
590 for(size_t i=0;i<degreeVec.size();++i)
591 {
592 if(degreeVec[i]>2)
593 {
594 std::vector<EdgeType *> edgeStarVec;
595 edge::VEStarVE(&(poly.vert[i]),edgeStarVec);
596 assert(edgeStarVec.size() == degreeVec[i]);
597 for(size_t j=delta;j<edgeStarVec.size();++j)
598 {
599 EdgeType *ep = edgeStarVec[j];
600 int ind; // index of the vertex to be changed
601 if(tri::Index(poly,ep->V(0)) == i) ind = 0;
602 else ind = 1;
603
604 ep->V(ind) = &*firstVi;
605 ep->V(ind)->P() = poly.vert[i].P();
606 ep->V(ind)->N() = poly.vert[i].N();
607 ++firstVi;
608 }
609 }
610 }
611 assert(firstVi == poly.vert.end());
612 }
613
614 // ============================================================================
615 // Mesh Splitting and Refinement for Polyline Integration
616 // ============================================================================
617
649 void SplitMeshWithPolyline(MeshType &poly)
650 {
651 std::vector< std::pair<int,VertexPointer> > toSplitVec; // the index of the face to be split and the poly vertex to be used
652
653 for(VertexIterator vi=poly.vert.begin(); vi!=poly.vert.end();++vi)
654 {
655 CoordType ip;
656 FaceType *f = GetClosestFaceIP(vi->cP(),ip);
657 if(!BarycentricSnap(ip))
658 toSplitVec.push_back(std::make_pair(tri::Index(base,f),&*vi));
659 }
660 SimplifyNullEdges(poly);
661 printf("SplitMeshWithPolyline found %lu non snapped points\n",toSplitVec.size()); fflush(stdout);
662
663 FaceIterator newFi = tri::Allocator<MeshType>::AddFaces(base,toSplitVec.size()*2);
664 VertexIterator newVi = tri::Allocator<MeshType>::AddVertices(base,toSplitVec.size());
666
667 for(size_t i =0; i<toSplitVec.size();++i)
668 {
669 newVi->P() = toSplitVec[i].second->P();
670 newVi->C()=Color4b::Green;
671 face::TriSplit(&base.face[toSplitVec[i].first],&*(newFi++),&*(newFi++),&*(newVi++));
672 }
673 Init(); // need to reset everthing
674 SnapPolyline(poly);
675
676 // Second loop to perform the face-face Edge split **********************
677 // This loop must be iterated multiple times becouse it can happen that more than one polyline vertices falls on the same edge.
678 // So multiple splits must be done.
679 std::map<std::pair<CoordType,CoordType>, VertexPointer> edgeToSplitMap;
680 do
681 {
682 edgeToSplitMap.clear();
683 for(VertexIterator vi=poly.vert.begin(); vi!=poly.vert.end();++vi)
684 {
685 CoordType ip;
686 FaceType *f = GetClosestFaceIP(vi->cP(),ip);
687 if(!BarycentricSnap(ip)) { assert(0); }
688 for(int i=0;i<3;++i)
689 {
690 if((ip[i ]>0 && ip[i ]<1.0) &&
691 (ip[(i+1)%3]>0 && ip[(i+1)%3]<1.0) &&
692 ip[(i+2)%3]==0 )
693 {
694 CoordType p0=f->P0(i);
695 CoordType p1=f->P1(i);
696 if (p0>p1) std::swap(p0,p1);
697 if(edgeToSplitMap[std::make_pair(p0,p1)])
698 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));
699 edgeToSplitMap[std::make_pair(p0,p1)]=&*vi;
700 }
701 }
702 }
703 printf("SplitMeshWithPolyline: Created a map of %lu edges to be split\n",edgeToSplitMap.size());
704 EdgePointPred ePred(edgeToSplitMap);
705 EdgePointSplit eSplit(edgeToSplitMap);
707 tri::RefineE(base,eSplit,ePred);
708 Init(); // need to reset everthing
709 } while(edgeToSplitMap.size()>0); // while there are edges to be split
710 }
711
712 // ============================================================================
713 // Initialization
714 // ============================================================================
715
728 void Init()
729 {
730 // Construction of the uniform grid
733 uniformGrid.Set(base.face.begin(), base.face.end());
734 }
735
736 // ============================================================================
737 // Simplification Methods
738 // ============================================================================
739
746 void SimplifyNullEdges(MeshType &poly)
747 {
749 if(cnt)
750 printf("SimplifyNullEdges: Removed %i Duplicated vertices\n",cnt);
751 }
752
753 void SimplifyMidEdge(MeshType &poly)
754 {
755 int startVn;
756 int midEdgeCollapseCnt=0;
758 do
759 {
760 startVn = poly.vn;
761 for(int ei =0; ei<poly.en; ++ei)
762 {
763 VertexType *v0=poly.edge[ei].V(0);
764 VertexType *v1=poly.edge[ei].V(1);
765 CoordType ip0,ip1;
766 FaceType *f0=GetClosestFaceIP(v0->P(),ip0);
767 FaceType *f1=GetClosestFaceIP(v1->P(),ip1);
768
769 bool snap0=BarycentricSnap(ip0);
770 bool snap1=BarycentricSnap(ip1);
771 int e0i,e1i;
772 bool e0 = IsSnappedEdge(ip0,e0i);
773 bool e1 = IsSnappedEdge(ip1,e1i);
774 if(e0 && e1)
775 if( ( f0 == f1 && e0i == e1i) ||
776 ( f0 == f1->FFp(e1i) && e0i == f1->FFi(e1i)) ||
777 (f0->FFp(e0i) == f1 && f0->FFi(e0i) == e1i) ||
778 (f0->FFp(e0i) == f1->FFp(e1i) && f0->FFi(e0i) == f1->FFi(e1i)) )
779 {
780 CoordType newp = (v0->P()+v1->P())/2.0;
781 v0->P()=newp;
782 v1->P()=newp;
783 midEdgeCollapseCnt++;
784 }
785 }
787 tri::Allocator<MeshType>::CompactEveryVector(poly);
788// printf("SimplifyMidEdge %5i -> %5i %i mid %i ve \n",startVn,poly.vn,midEdgeCollapseCnt);
789 } while(startVn>poly.vn);
790 }
791
800 void SimplifyMidFace(MeshType &poly)
801 {
802 int startVn= poly.vn;;
803 int midFaceCollapseCnt=0;
804 int vertexEdgeCollapseCnt=0;
805 int curVn;
806 do
807 {
809 curVn = poly.vn;
811 for(int i =0; i<poly.vn;++i)
812 {
813 std::vector<VertexPointer> starVecVp;
814 edge::VVStarVE(&(poly.vert[i]),starVecVp);
815 if( (starVecVp.size()==2) )
816 {
817 CoordType ipP, ipN, ipI;
818 FacePointer fpP = GetClosestFaceIP(starVecVp[0]->P(),ipP);
819 FacePointer fpN = GetClosestFaceIP(starVecVp[1]->P(),ipN);
820 FacePointer fpI = GetClosestFaceIP(poly.vert[i].P(), ipI);
821
822 bool snapP = (BarycentricSnap(ipP));
823 bool snapN = (BarycentricSnap(ipN));
824 bool snapI = (BarycentricSnap(ipI));
825 VertexPointer vertexSnapP = 0;
826 VertexPointer vertexSnapN = 0;
827 VertexPointer vertexSnapI = 0;
828 for(int j=0;j<3;++j)
829 {
830 if(ipP[j]==1.0) vertexSnapP=fpP->V(j);
831 if(ipN[j]==1.0) vertexSnapN=fpN->V(j);
832 if(ipI[j]==1.0) vertexSnapI=fpI->V(j);
833 }
834
835 bool collapseFlag=false;
836
837 if((!snapI && snapP && snapN) || // First case a vertex that is not snapped between two snapped vertexes
838 (!snapI && !snapP && fpI==fpP) || // Or a two vertex not snapped but on the same face
839 (!snapI && !snapN && fpI==fpN) )
840 {
841 collapseFlag=true;
842 midFaceCollapseCnt++;
843 }
844
845 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
846 if(snapI && snapP && snapN && vertexSnapI==0 && (vertexSnapP!=0 || vertexSnapN!=0) )
847 {
848 for(int j=0;j<3;++j) {
849 if(ipI[j]!=0 && (fpI->V(j)==vertexSnapP || fpI->V(j)==vertexSnapN)) {
850 collapseFlag=true;
851 vertexEdgeCollapseCnt++;
852 }
853 }
854 }
855
856 if(collapseFlag)
857 edge::VEEdgeCollapse(poly,&(poly.vert[i]));
858 }
859 }
860 } while(curVn>poly.vn);
861 printf("SimplifyMidFace %5i -> %5i %i mid %i ve \n",startVn,poly.vn,midFaceCollapseCnt,vertexEdgeCollapseCnt);
862 }
863
864 void Simplify(MeshType &poly)
865 {
866 int startEn = poly.en;
867 Distribution<ScalarType> hist;
868 for(int i =0; i<poly.en;++i)
869 hist.Add(edge::Length(poly.edge[i]));
870
872
873 for(int i =0; i<poly.vn;++i)
874 {
875 std::vector<VertexPointer> starVecVp;
876 edge::VVStarVE(&(poly.vert[i]),starVecVp);
877 if ((starVecVp.size()==2) && (!poly.vert[i].IsS()))
878 {
879 ScalarType newSegLen = Distance(starVecVp[0]->P(), starVecVp[1]->P());
880 Segment3Type seg(starVecVp[0]->P(),starVecVp[1]->P());
881 ScalarType segDist;
882 CoordType closestPSeg;
883 SegmentPointDistance(seg,poly.vert[i].cP(),closestPSeg,segDist);
884 CoordType fp,fn;
885 ScalarType maxSurfDist = MaxSegDist(starVecVp[0], starVecVp[1],fp,fn);
886
887 if((maxSurfDist < par.surfDistThr) && (newSegLen < par.maxSimpEdgeLen) )
888 {
889 edge::VEEdgeCollapse(poly,&(poly.vert[i]));
890 }
891 }
892 }
894 tri::Allocator<MeshType>::CompactEveryVector(poly);
896// printf("Simplify %5i -> %5i (total len %5.2f)\n",startEn,poly.en,hist.Sum());
897 }
898
899 void EvaluateHausdorffDistance(MeshType &poly, Distribution<ScalarType> &dist)
900 {
901 dist.Clear();
902 tri::UpdateTopology<MeshType>::VertexEdge(poly);
904 for(int i =0; i<poly.edge.size();++i)
905 {
906 CoordType farthestP, farthestN;
907 ScalarType maxDist = MaxSegDist(poly.edge[i].V(0),poly.edge[i].V(1), farthestP, farthestN, &dist);
908 poly.edge[i].V(0)->Q()+= maxDist;
909 poly.edge[i].V(1)->Q()+= maxDist;
910 }
911 for(int i=0;i<poly.vn;++i)
912 {
913 ScalarType deg = edge::VEDegree<EdgeType>(&poly.vert[i]);
914 poly.vert[i].Q()/=deg;
915 }
917 }
918
919
953 bool BarycentricSnap(CoordType &ip)
954 {
955 for(int i=0;i<3;++i)
956 {
957 if(ip[i] <= par.barycentricSnapThr) ip[i]=0;
958 if(ip[i] >= 1.0-par.barycentricSnapThr) ip[i]=1;
959 }
960 ScalarType sum = ip[0]+ip[1]+ip[2];
961
962 for(int i=0;i<3;++i)
963 if(ip[i]!=1.0) ip[i]/=sum;
964
965 sum = ip[0]+ip[1]+ip[2];
966
967 if(sum!=1.0){
968 for(int i=0;i<3;++i)
969 if(ip[i]>0.0 && ip[i]<1.0) // if it is non snapped
970 ip[i]=1.0-(ip[(i+1)%3]+ip[(i+2)%3]);
971 }
972
973 sum = ip[0]+ip[1]+ip[2];
974 assert(sum ==1.0);
975 assert(IsWellSnapped(ip));
976 if(ip[0]==0 || ip[1]==0 || ip[2]==0) return true;
977 return false;
978 }
979
980
998 bool TestSplitSegWithMesh(VertexType *v0, VertexType *v1, CoordType &splitPt)
999 {
1000 Segment3Type segPoly(v0->P(),v1->P());
1001 const ScalarType sampleNum = 40;
1002 CoordType ip0,ip1;
1003
1004 FaceType *f0=GetClosestFaceIP(v0->P(),ip0);
1005 FaceType *f1=GetClosestFaceIP(v1->P(),ip1);
1006 if(f0==f1) return false;
1007
1008 bool snap0=false,snap1=false; // true if the segment start/end on a edge/vert
1009
1010 Segment3Type seg0; // The two segments to be avoided
1011 Segment3Type seg1; // from which the current poly segment can start
1012 VertexPointer vertexSnap0 = 0;
1013 VertexPointer vertexSnap1 = 0;
1014 if(BarycentricSnap(ip0)) {
1015 snap0=true;
1016 for(int i=0;i<3;++i) {
1017 if(ip0[i]==1.0) vertexSnap0=f0->V(i);
1018 if(ip0[i]==0.0) seg0=Segment3Type(f0->P1(i),f0->P2(i));
1019 }
1020 }
1021 if(BarycentricSnap(ip1)) {
1022 snap1=true;
1023 for(int i=0;i<3;++i){
1024 if(ip1[i]==1.0) vertexSnap1=f1->V(i);
1025 if(ip1[i]==0.0) seg1=Segment3Type(f1->P1(i),f1->P2(i));
1026 }
1027 }
1028
1029 CoordType bestSplitPt(0,0,0);
1030 ScalarType bestDist = std::numeric_limits<ScalarType>::max();
1031 for(ScalarType k = 1;k<sampleNum;++k)
1032 {
1033 CoordType samplePnt = segPoly.Lerp(k/sampleNum);
1034 CoordType ip;
1035 FaceType *f=GetClosestFaceIP(samplePnt,ip);
1036// BarycentricEdgeSnap(ip);
1037 if(BarycentricSnap(ip))
1038 {
1039 VertexPointer vertexSnapI = 0;
1040 for(int i=0;i<3;++i)
1041 if(ip[i]==1.0) vertexSnapI=f->V(i);
1042 CoordType closestPt = f->P(0)*ip[0]+f->P(1)*ip[1]+f->P(2)*ip[2];
1043 if(Distance(samplePnt,closestPt) < bestDist )
1044 {
1045 ScalarType dist0=std::numeric_limits<ScalarType>::max();
1046 ScalarType dist1=std::numeric_limits<ScalarType>::max();
1047 CoordType closestSegPt;
1048 if(snap0) SegmentPointDistance(seg0,closestPt,closestSegPt,dist0);
1049 if(snap1) SegmentPointDistance(seg1,closestPt,closestSegPt,dist1);
1050 if( (!vertexSnapI && (dist0 > par.surfDistThr/1000 && dist1>par.surfDistThr/1000) ) ||
1051 ( vertexSnapI!=vertexSnap0 && vertexSnapI!=vertexSnap1) )
1052 {
1053 bestDist = Distance(samplePnt,closestPt);
1054 bestSplitPt = closestPt;
1055 }
1056 }
1057 }
1058 }
1059 if(bestDist < par.surfDistThr*100)
1060 {
1061 splitPt = bestSplitPt;
1062 return true;
1063 }
1064
1065 return false;
1066 }
1081 bool SnappedOnSameFace(FacePointer f0, CoordType i0, FacePointer f1, CoordType i1)
1082 {
1083 if(f0==f1) return true;
1084 int e0,e1;
1085 int v0,v1;
1086 bool e0Snap = IsSnappedEdge(i0,e0);
1087 bool e1Snap = IsSnappedEdge(i1,e1);
1088 bool v0Snap = IsSnappedVertex(i0,v0);
1089 bool v1Snap = IsSnappedVertex(i1,v1);
1090 FacePointer f0p=0; int e0p=-1; // When Edge snap the other face and the index of the snapped edge on the other face
1091 FacePointer f1p=0; int e1p=-1;
1092 assert((e0Snap != v0Snap) && (e1Snap != v1Snap));
1093 // For EdgeSnap compute the 'other' face stuff
1094 if(e0Snap){
1095 f0p = f0->FFp(e0); e0p=f0->FFi(e0); assert(f0p->FFp(e0p)==f0);
1096 }
1097 if(e1Snap){
1098 f1p = f1->FFp(e1); e1p=f1->FFi(e1); assert(f1p->FFp(e1p)==f1);
1099 }
1100
1101 if(e0Snap && e1Snap) {
1102 if(f0==f1p || f0p==f1p || f0p==f1 || f0==f1) return true;
1103 }
1104
1105 if(e0Snap && v1Snap) {
1106 assert(v1>=0 && v1<3 && v0==-1 && e1==-1);
1107 if(f0->V2(e0) ==f1->V(v1)) return true;
1108 if(f0p->V2(e0p)==f1->V(v1)) return true;
1109 }
1110
1111 if(e1Snap && v0Snap) {
1112 assert(v0>=0 && v0<3 && v1==-1 && e0==-1);
1113 if(f1->V2(e1) ==f0->V(v0)) return true;
1114 if(f1p->V2(e1p)==f0->V(v0)) return true;
1115 }
1116
1117 if(v1Snap && v0Snap) {
1118 PosType startPos(f0,f0->V(v0));
1119 PosType curPos=startPos;
1120 do
1121 {
1122 assert(curPos.V()==f0->V(v0));
1123 if(curPos.VFlip()==f1->V(v1)) return true;
1124 curPos.FlipE();
1125 curPos.FlipF();
1126 }
1127 while(curPos!=startPos);
1128 }
1129 return false;
1130 }
1131
1149 bool TestSplitSegWithMeshAdapt(VertexType *v0, VertexType *v1, CoordType &splitPt)
1150 {
1151 splitPt=(v0->P()+v1->P())/2.0;
1152
1153 CoordType ip0,ip1,ipm;
1154 FaceType *f0=GetClosestFaceIP(v0->P(),ip0);
1155 FaceType *f1=GetClosestFaceIP(v1->P(),ip1);
1156 FaceType *fm=GetClosestFaceIP(splitPt,ipm);
1157
1158 if(f0==f1) return false;
1159
1160 bool snap0=BarycentricSnap(ip0);
1161 bool snap1=BarycentricSnap(ip1);
1162 bool snapm=BarycentricSnap(ipm);
1163
1164 splitPt = fm->P(0)*ipm[0]+fm->P(1)*ipm[1]+fm->P(2)*ipm[2];
1165
1166 if(!snap0 && !snap1) {
1167 assert(f0!=f1);
1168 return true;
1169 }
1170 if(snap0 && snap1)
1171 {
1172 if(SnappedOnSameFace(f0,ip0,f1,ip1))
1173 return false;
1174 }
1175
1176 if(snap0) {
1177 int e0,v0;
1178 if (IsSnappedEdge(ip0,e0)) {
1179 if(f0->FFp(e0) == f1) return false;
1180 }
1181 if(IsSnappedVertex(ip0,v0)) {
1182 for(int i=0;i<3;++i)
1183 if(f1->V(i)==f0->V(v0)) return false;
1184 }
1185 }
1186 if(snap1) {
1187 int e1,v1;
1188 if (IsSnappedEdge(ip1,e1)) {
1189 if(f1->FFp(e1) == f0) return false;
1190 }
1191 if(IsSnappedVertex(ip1,v1)) {
1192 for(int i=0;i<3;++i)
1193 if(f0->V(i)==f1->V(v1)) return false;
1194 }
1195 }
1196
1197 return true;
1198 }
1199
1200
1201 bool TestSplitSegWithMeshAdaptOld(VertexType *v0, VertexType *v1, CoordType &splitPt)
1202 {
1203 Segment3Type segPoly(v0->P(),v1->P());
1204 const ScalarType sampleNum = 40;
1205 CoordType ip0,ip1;
1206 FaceType *f0=GetClosestFaceIP(v0->P(),ip0);
1207 FaceType *f1=GetClosestFaceIP(v1->P(),ip1);
1208 if(f0==f1) return false;
1209
1210 bool snap0=BarycentricSnap(ip0);
1211 bool snap1=BarycentricSnap(ip1);
1212
1213 if(!snap0 && !snap1) {
1214 assert(f0!=f1);
1215 splitPt=(v0->P()+v1->P())/2.0;
1216 return true;
1217 }
1218 if(snap0 && snap1)
1219 {
1220 if(SnappedOnSameFace(f0,ip0,f1,ip1))
1221 return false;
1222 }
1223
1224 if(snap0) {
1225 int e0,v0;
1226 if (IsSnappedEdge(ip0,e0)) {
1227 if(f0->FFp(e0) == f1) return false;
1228 }
1229 if(IsSnappedVertex(ip0,v0)) {
1230 for(int i=0;i<3;++i)
1231 if(f1->V(i)==f0->V(v0)) return false;
1232 }
1233 }
1234 splitPt=(v0->P()+v1->P())/2.0;
1235 return true;
1236 }
1237
1238 // Given a segment find the maximum distance from it to the original surface.
1239 // It is used to evaluate the Haustdorff distance of a Segment from the mesh.
1240 ScalarType MaxSegDist(VertexType *v0, VertexType *v1, CoordType &farthestPointOnSurf, CoordType &farthestN, Distribution<ScalarType> *distanceDistribution=0)
1241 {
1242 ScalarType maxSurfDist = 0;
1243 const ScalarType sampleNum = 10;
1244 for(ScalarType k = 1;k<sampleNum;++k)
1245 {
1246 ScalarType surfDist;
1247 CoordType closestPSurf;
1248 CoordType samplePnt = (v0->P()*k +v1->P()*(sampleNum-k))/sampleNum;
1249 FaceType *f = vcg::tri::GetClosestFaceBase(base,uniformGrid,samplePnt,par.gridBailout, surfDist, closestPSurf);
1250 if(distanceDistribution)
1251 distanceDistribution->Add(surfDist);
1252 assert(f);
1253 if(surfDist > maxSurfDist)
1254 {
1255 maxSurfDist = surfDist;
1256 farthestPointOnSurf = closestPSurf;
1257 farthestN = f->N();
1258 }
1259 }
1260 return maxSurfDist;
1261 }
1262
1263
1275 void RefineCurveByDistance(MeshType &poly)
1276 {
1278 int startEdgeSize = poly.en;
1279 for(int i =0; i<startEdgeSize;++i)
1280 {
1281 EdgeType &ei = poly.edge[i];
1282 if(edge::Length(ei)>par.minRefEdgeLen)
1283 {
1284 CoordType farthestP, farthestN;
1285 ScalarType maxDist = MaxSegDist(ei.V(0),ei.V(1),farthestP, farthestN);
1286 if(maxDist > par.surfDistThr)
1287 {
1288 edge::VEEdgeSplit(poly, &ei, farthestP, farthestN);
1289 }
1290 }
1291 }
1292// tri::Allocator<MeshType>::CompactEveryVector(poly);
1293// printf("Refine %i -> %i\n",startEdgeSize,poly.en);fflush(stdout);
1294 }
1295
1301 void RefineCurveByBaseMesh(MeshType &poly)
1302 {
1304 std::vector<int> edgeToRefineVec;
1305 for(int i=0; i<poly.en;++i)
1306 edgeToRefineVec.push_back(i);
1307 int startEn=poly.en;
1308 int iterCnt=0;
1309 while (!edgeToRefineVec.empty() && iterCnt<100) {
1310 iterCnt++;
1311 std::vector<int> edgeToRefineVecNext;
1312 for(int i=0; i<edgeToRefineVec.size();++i)
1313 {
1314 EdgeType &e = poly.edge[edgeToRefineVec[i]];
1315 CoordType splitPt;
1316 if(TestSplitSegWithMeshAdapt(e.V(0),e.V(1),splitPt))
1317 {
1318 edge::VEEdgeSplit(poly, &e, splitPt);
1319 edgeToRefineVecNext.push_back(edgeToRefineVec[i]);
1320 edgeToRefineVecNext.push_back(poly.en-1);
1321 }
1322 }
1324 swap(edgeToRefineVecNext,edgeToRefineVec);
1325 printf("RefineCurveByBaseMesh %i en -> %i en\n",startEn,poly.en); fflush(stdout);
1326 }
1327//
1328 SimplifyNullEdges(poly);
1329 SimplifyMidFace(poly);
1330 SimplifyMidEdge(poly);
1331 SnapPolyline(poly);
1332 printf("RefineCurveByBaseMesh %i en -> %i en\n",startEn,poly.en); fflush(stdout);
1333 }
1334
1335
1344 std::vector<CoordType> operator()(const MeshType &poly) const {
1345 std::vector<CoordType> posVec(poly.vn, CoordType(0,0,0));
1346 std::vector<int> cntVec(poly.vn, 0);
1347 for(int i=0; i<poly.en; ++i)
1348 for(int j=0; j<2; ++j) {
1349 int vi = tri::Index(poly, poly.edge[i].V0(j));
1350 posVec[vi] += poly.edge[i].V1(j)->P();
1351 cntVec[vi] += 1;
1352 }
1353 for(int i=0; i<poly.vn; ++i)
1354 posVec[i] = (poly.vert[i].P() + posVec[i]) / ScalarType(cntVec[i]+1);
1355 return posVec;
1356 }
1357 };
1358
1377 {
1378
1379 CoM<MeshType> &com;
1380 ScalarType scale;
1381 ScalarType smoothBlend = 0.5;
1382 QualityDistanceFieldFunctor(CoM<MeshType> &_com, ScalarType _scale=0, ScalarType _smoothBlend = 0.5) : com(_com), scale(_scale), smoothBlend(_smoothBlend) {};
1383
1384 std::vector<CoordType> operator()(const MeshType &poly) const
1385 {
1386 // Step 1: Compute smoothed position using Laplacian smoothing
1387 std::vector<CoordType> smoothPosVec(poly.vn, CoordType(0, 0, 0));
1388 std::vector<int> cntVec(poly.vn, 0);
1389 for (int i = 0; i < poly.en; ++i)
1390 for (int j = 0; j < 2; ++j)
1391 {
1392 int vi = tri::Index(poly, poly.edge[i].V0(j));
1393 smoothPosVec[vi] += poly.edge[i].V1(j)->P();
1394 cntVec[vi] += 1;
1395 }
1396 for (int i = 0; i < poly.vn; ++i)
1397 smoothPosVec[i] = (poly.vert[i].P() + smoothPosVec[i]) / ScalarType(cntVec[i] + 1);
1398
1399 // Step 2: Compute field-based position using the gradient of the quality field and moving toward zero
1400 std::vector<CoordType> fieldPosVec(poly.vn, CoordType(0, 0, 0));
1401 for (const VertexType &v : poly.vert)
1402 {
1403 CoordType ip;
1404 FacePointer f = com.GetClosestFaceIP(v.P(),ip);
1405 if(!f) {
1406 printf("Fail to get closest face for vertex at position (%f, %f, %f)\n", v.P().X(), v.P().Y(), v.P().Z()); fflush(stdout);
1407 }
1408 else {
1409 ScalarType q = f->V(0)->Q() * ip[0] + f->V(1)->Q() * ip[1] + f->V(2)->Q() * ip[2];
1410 CoordType fieldDir = GradientScalarField(*f, f->V(0)->Q(),f->V(1)->Q(),f->V(2)->Q());
1411
1412 fieldPosVec[tri::Index(poly, v)] = v.P() + fieldDir * scale * q; // Move towards higher quality (lower distance)
1413 }
1414 }
1415 std::vector<CoordType> PosVec(poly.vn, CoordType(0, 0, 0));
1416 for (int i = 0; i < poly.vn; ++i)
1417 PosVec[i] = (smoothPosVec[i] * smoothBlend + fieldPosVec[i] * (1.0 - smoothBlend));
1418
1419 return PosVec;
1420 }
1421 };
1422
1434 template<typename PositionFunctor>
1435 void MoveAndProject(MeshType &poly, int iterNum, ScalarType moveWeight, ScalarType projectWeight,
1436 PositionFunctor &desiredPos)
1437 {
1438 tri::RequireCompactness(poly);
1440 assert(poly.en>0 && base.fn>0);
1441 for(int k=0;k<iterNum;++k)
1442 {
1443 if(k==iterNum-1) projectWeight=1;
1444 std::vector<CoordType> desired = desiredPos(poly);
1445
1446 for(int i=0; i<poly.vn; ++i)
1447 if(!poly.vert[i].IsS())
1448 {
1449 // Clamp the movement towards the desired position by maxMoveDist
1450 CoordType delta = desired[i] - poly.vert[i].P();
1451 ScalarType deltaLen = delta.Norm();
1452 if(deltaLen > par.maxMoveDelta) {
1453 delta *= (par.maxMoveDelta / deltaLen);
1454 desired[i] = poly.vert[i].P() + delta;
1455 }
1456
1457 CoordType newP = poly.vert[i].P()*(1.0-moveWeight) + desired[i]*moveWeight;
1458
1459 CoordType closestP;
1460 FaceType *f = GetClosestFacePoint(newP, closestP);
1461 assert(f);
1462 poly.vert[i].P() = newP*(1.0-projectWeight) +closestP*projectWeight;
1463 poly.vert[i].N() = f->N();
1464 }
1465
1467 RefineCurveByDistance(poly);
1469 Simplify(poly);
1471 int dupVertNum = Clean<MeshType>::RemoveDuplicateVertex(poly);
1472 if(dupVertNum) {
1475 }
1476 }
1477 }
1478
1479 void SmoothProject(MeshType &poly, int iterNum, ScalarType smoothWeight, ScalarType projectWeight)
1480 {
1481 LaplacianFunctor lapFunct;
1482 MoveAndProject(poly, iterNum, smoothWeight, projectWeight, lapFunct);
1483 }
1484
1485
1487{
1488public:
1489 std::map<std::pair<CoordType,CoordType>, VertexPointer> &edgeToPolyVertMap;
1490
1491 EdgePointPred(std::map<std::pair<CoordType,CoordType>, VertexPointer> &_edgeToPolyVertMap):edgeToPolyVertMap(_edgeToPolyVertMap){};
1492 bool operator()(face::Pos<FaceType> ep) const
1493 {
1494 CoordType p0 = ep.V()->P();
1495 CoordType p1 = ep.VFlip()->P();
1496 if (p0>p1) std::swap(p0,p1);
1497 return edgeToPolyVertMap.find(std::make_pair(p0,p1)) != edgeToPolyVertMap.end();
1498 }
1499};
1500
1502{
1503public:
1504 std::map<std::pair<CoordType,CoordType>, VertexPointer> &edgeToPolyVertMap;
1505
1506 EdgePointSplit(std::map<std::pair<CoordType,CoordType>, VertexPointer> &_edgeToPolyVertMap):edgeToPolyVertMap(_edgeToPolyVertMap){};
1507 void operator()(VertexType &nv, face::Pos<FaceType> ep)
1508 {
1509 CoordType p0 = ep.V()->P();
1510 CoordType p1 = ep.VFlip()->P();
1511 if (p0>p1) std::swap(p0,p1);
1512 VertexPointer vp=edgeToPolyVertMap[std::make_pair(p0,p1)];
1513 assert(vp);
1514 nv.P()=vp->P();
1515 return;
1516 }
1517 Color4b WedgeInterp(Color4b &c0, Color4b &c1)
1518 {
1519 Color4b cc;
1520 cc.lerp(c0,c1,0.5f);
1521 return Color4b::Red;
1522 }
1523 TexCoord2f WedgeInterp(TexCoord2f &t0, TexCoord2f &t1)
1524 {
1525 TexCoord2f tmp;
1526 assert(t0.n()== t1.n());
1527 tmp.n()=t0.n();
1528 tmp.t()=(t0.t()+t1.t())/2.0;
1529 return tmp;
1530 }
1531};
1532
1533};
1534
1535} // end namespace tri
1536} // end namespace vcg
1537
1538#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:1487
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 maxMoveDelta
The maximum movement admitted during MoveAndProject (before projection)
Definition: curve_on_manifold.h:122
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
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:372
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:746
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:1301
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:320
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:800
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:497
static CoordType QLerp(VertexType *v0, VertexType *v1)
Compute quality-weighted linear interpolation between two vertices.
Definition: curve_on_manifold.h:475
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:1081
void MoveAndProject(MeshType &poly, int iterNum, ScalarType moveWeight, ScalarType projectWeight, PositionFunctor &desiredPos)
MoveAndProject.
Definition: curve_on_manifold.h:1435
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:1149
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:1275
bool BarycentricSnap(CoordType &ip)
Snap barycentric coordinates to 0 or 1 if within threshold.
Definition: curve_on_manifold.h:953
void Init()
Initialize the CoM data structures for processing.
Definition: curve_on_manifold.h:728
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:998
static bool CompareVertex(const MeshType &m, const VertexType &vA, const VertexType &vB)
Compare two vertices for seam compatibility.
Definition: curve_on_manifold.h:453
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:430
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:390
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:649
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:1502
LaplacianFunctor basic Laplacian smoothing functor.
Definition: curve_on_manifold.h:1343
QualityDistanceFieldFunctor quality field based smoothing functor.
Definition: curve_on_manifold.h:1377