23#ifndef __VCGLIB_CURVE_ON_SURF_H
24#define __VCGLIB_CURVE_ON_SURF_H
27#include<vcg/complex/complex.h>
28#include<vcg/simplex/face/topology.h>
29#include<vcg/complex/algorithms/update/topology.h>
30#include<vcg/complex/algorithms/update/color.h>
31#include<vcg/complex/algorithms/update/normal.h>
32#include<vcg/complex/algorithms/update/quality.h>
33#include<vcg/complex/algorithms/clean.h>
34#include<vcg/complex/append.h>
35#include<vcg/complex/algorithms/mesh_assert.h>
36#include<vcg/complex/algorithms/update/bounding.h>
37#include<vcg/complex/algorithms/vertex_interpolation.h>
38#include<vcg/complex/algorithms/point_sampling.h>
39#include <vcg/space/index/grid_static_ptr.h>
40#include <vcg/math/histogram.h>
41#include<vcg/space/distance3.h>
42#include <wrap/callback.h>
43#include <vcg/space/planar_polygon_tessellation.h>
118template <
class MeshType>
class CoMEmbed;
120template <
class MeshType>
124 typedef typename MeshType::ScalarType ScalarType;
125 typedef typename MeshType::CoordType CoordType;
126 typedef typename MeshType::VertexType VertexType;
127 typedef typename MeshType::VertexPointer VertexPointer;
128 typedef typename MeshType::VertexIterator VertexIterator;
129 typedef typename MeshType::EdgeIterator EdgeIterator;
130 typedef typename MeshType::EdgeType EdgeType;
131 typedef typename MeshType::FaceType FaceType;
132 typedef typename MeshType::FacePointer FacePointer;
133 typedef typename MeshType::FaceIterator FaceIterator;
134 typedef Segment3<ScalarType> Segment3Type;
135 typedef typename vcg::GridStaticPtr<FaceType, ScalarType> MeshGrid;
155 vcg::CallBackPos *
cb =
nullptr;
200 template <
class>
friend class CoMEmbed;
205 template <
class... Args>
206 void Progress(
int pos,
const char *fmt, Args... args)
214 template <
class... Args>
215 void Log(
const char *fmt, Args... args)
219 snprintf(msg,
sizeof(msg), fmt, args...);
220 par.
cb(progress, msg);
226 FaceType *Closest(
const CoordType &p, CoordType &closestP, ScalarType &closestDist)
231 snprintf(msg,
sizeof(msg),
"CoM: no face of the base mesh within %g (Param::gridBailout) of the point (%g, %g, %g); the curve is too far from the surface.",
232 double(
par.
gridBailout),
double(p[0]),
double(p[1]),
double(p[2]));
233 throw vcg::MissingPreconditionException(msg);
253 ScalarType closestDist;
255 return Closest(p, closestP, closestDist);
266 ScalarType closestDist;
268 FaceType *f = Closest(p, closestP, closestDist);
269 InterpolationParameters(*f, f->N(), closestP, ip);
283 in = f->V(0)->cN()*ip[0] + f->V(1)->cN()*ip[1] + f->V(2)->cN()*ip[2];
295 ScalarType closestDist;
296 return Closest(p, closestP, closestDist);
315 if(ip[i]>0.0 && ip[(i+1)%3]>0.0 && ip[(i+2)%3]==0.0 ) {
332 if(ip[i]==1.0 && ip[(i+1)%3]==0.0 && ip[(i+2)%3]==0.0 ) {
349 if(ip[i]==1.0 && ip[(i+1)%3]==0.0 && ip[(i+2)%3]==0.0 )
return fp->V(i);
376 std::vector<FaceType *> face(poly.vert.size());
377 std::vector<CoordType> ip(poly.vert.size()), raw(poly.vert.size());
378 std::map<VertexType *, std::vector<size_t>> onVertex;
379 for (
size_t i = 0; i < poly.vert.size(); ++i)
386 if (VertexPointer v =
FindVertexSnap(face[i], ip[i])) onVertex[v].push_back(i);
392 for (
auto &ov : onVertex)
394 if (ov.second.size() < 2)
continue;
395 std::sort(ov.second.begin(), ov.second.end(), [&](
size_t a,
size_t b) {
396 if (poly.vert[a].IsS() != poly.vert[b].IsS()) return poly.vert[a].IsS();
397 return Distance(poly.vert[a].cP(), ov.first->cP()) < Distance(poly.vert[b].cP(), ov.first->cP()); });
398 std::set<size_t> kept{ov.second[0]};
399 for (
bool grew =
true; grew; )
402 for (
size_t c : ov.second)
404 if (kept.count(c))
continue;
405 std::vector<VertexPointer> star;
406 edge::VVStarVE(&poly.vert[c], star);
407 for (VertexPointer w : star)
408 if (kept.count(tri::Index(poly, w))) { kept.insert(c); grew =
true;
break; }
411 for (
size_t c : ov.second)
413 if (kept.count(c) || poly.vert[c].IsS())
continue;
416 CoordType &q = ip[c];
418 const int k = (q[0] <= q[1] && q[0] <= q[2]) ? 0 : (q[1] <= q[2] ? 1 : 2);
419 const FaceType &f = *face[c];
420 const ScalarType len = Distance(f.cP((k + 1) % 3), f.cP((k + 2) % 3));
424 q[(k + 1) % 3] /= q[(k + 1) % 3] + q[(k + 2) % 3];
425 q[(k + 2) % 3] = 1 - q[(k + 1) % 3];
429 int vertSnapCnt=0, edgeSnapCnt=0;
430 for (
size_t i = 0; i < poly.vert.size(); ++i)
432 if (poly.vert[i].IsS())
continue;
434 for (
int k = 0; k < 3; ++k) zeros += ip[i][k] == 0;
435 if (zeros == 0)
continue;
436 const FaceType &f = *face[i];
437 poly.vert[i].P() = f.cP(0)*ip[i][0] + f.cP(1)*ip[i][1] + f.cP(2)*ip[i][2];
438 if (zeros == 2) vertSnapCnt++;
else edgeSnapCnt++;
441 Log(
"SnapPolyline %i vertices: snapped %i onto vertices and %i onto edges, %i kept off an occupied vertex, %i null edges collapsed",
442 poly.vn, vertSnapCnt, edgeSnapCnt, deniedCnt, dupCnt);
443 return vertSnapCnt==0 && edgeSnapCnt==0 && dupCnt==0;
467 const int deg = edge::VEDegree<EdgeType>(&v);
468 if (mode ==
AllVertices || deg != 2) v.SetS();
else v.ClearS();
484 std::map<CoordType, int> count;
485 for (
const VertexType &v : poly.vert)
if (!v.IsD()) ++count[v.cP()];
493 for (VertexType &v : poly.vert)
494 if (count[v.cP()] > 1 && edge::VEDegree<EdgeType>(&v) > 2) { v.SetS(); ++junctions; }
499 void SelectUniformlyDistributed(MeshType &poly,
int k)
502 ScalarType samplingRadius = tri::Stat<MeshType>::ComputeEdgeLengthSum(poly)/ScalarType(k);
504 for(
int i=0;i<tps.sampleVec.size();++i)
505 tps.sampleVec[i]->SetS();
524 void DecomposeNonManifoldPolyline(MeshType &poly,
bool singSplitFlag =
true)
527 std::vector<int> degreeVec(poly.vn, 0);
531 if(singSplitFlag) delta = 1;
534 for(VertexIterator vi=poly.vert.begin(); vi!=poly.vert.end();++vi)
536 std::vector<EdgeType *> starVec;
537 edge::VEStarVE(&*vi,starVec);
538 degreeVec[tri::Index(poly, *vi)] = starVec.size();
540 neededVert += starVec.size()-delta;
542 Log(
"DecomposeNonManifold Adding %i vert to a polyline of %i vert",neededVert,poly.vn);
545 for(
size_t i=0;i<degreeVec.size();++i)
549 std::vector<EdgeType *> edgeStarVec;
550 edge::VEStarVE(&(poly.vert[i]),edgeStarVec);
551 assert(edgeStarVec.size() == degreeVec[i]);
552 for(
size_t j=delta;j<edgeStarVec.size();++j)
554 EdgeType *ep = edgeStarVec[j];
556 if(tri::Index(poly,ep->V(0)) == i) ind = 0;
559 ep->V(ind) = &*firstVi;
560 ep->V(ind)->P() = poly.vert[i].P();
561 ep->V(ind)->N() = poly.vert[i].N();
566 assert(firstVi == poly.vert.end());
588 throw vcg::MissingPreconditionException(
"CoM: the base mesh has no faces.");
591 MeshAssert<MeshType>::FFTwoManifoldEdge(
base);
594 MeshAssert<MeshType>::NoZeroAreaFace(
base);
613 Log(
"SimplifyNullEdges: Collapsed %i zero-length edges",cnt);
629 for (
bool changed =
true; changed; )
632 for (
size_t i = 0; i < poly.edge.size(); ++i)
634 EdgeType &e = poly.edge[i];
635 if (e.IsD() || e.V(0)->cP() != e.V(1)->cP())
continue;
637 else edge::VEEdgeCollapseToVertex(poly, &e, e.V(1)->IsS() && !e.V(0)->IsS() ? 1 : 0);
646 void Simplify(MeshType &poly)
648 int startEn = poly.en;
649 Distribution<ScalarType> hist;
650 for(
int i =0; i<poly.en;++i)
651 hist.Add(edge::Length(poly.edge[i]));
655 for(
int i =0; i<poly.vn;++i)
657 std::vector<VertexPointer> starVecVp;
658 edge::VVStarVE(&(poly.vert[i]),starVecVp);
659 if ((starVecVp.size()==2) && (!poly.vert[i].IsS()))
661 ScalarType newSegLen = Distance(starVecVp[0]->P(), starVecVp[1]->P());
662 Segment3Type seg(starVecVp[0]->P(),starVecVp[1]->P());
664 CoordType closestPSeg;
665 SegmentPointDistance(seg,poly.vert[i].cP(),closestPSeg,segDist);
667 ScalarType maxSurfDist = MaxSegDist(starVecVp[0], starVecVp[1],fp,fn);
671 edge::VEEdgeCollapse(poly,&(poly.vert[i]));
676 tri::Allocator<MeshType>::CompactEveryVector(poly);
681 void EvaluateHausdorffDistance(MeshType &poly, Distribution<ScalarType> &dist)
684 tri::UpdateTopology<MeshType>::VertexEdge(poly);
686 for(
int i =0; i<poly.edge.size();++i)
688 CoordType farthestP, farthestN;
689 ScalarType maxDist = MaxSegDist(poly.edge[i].V(0),poly.edge[i].V(1), farthestP, farthestN, &dist);
690 poly.edge[i].V(0)->Q()+= maxDist;
691 poly.edge[i].V(1)->Q()+= maxDist;
693 for(
int i=0;i<poly.vn;++i)
695 ScalarType deg = edge::VEDegree<EdgeType>(&poly.vert[i]);
696 poly.vert[i].Q()/=deg;
724 static bool BarycentricSnap(CoordType &ip,
const FaceType &f, ScalarType barThr, ScalarType distThr)
728 const ScalarType area2 = DoubleArea(f);
730 for (
int i = 0; i < 3; ++i)
732 const ScalarType len = Distance(f.cP((i + 1) % 3), f.cP((i + 2) % 3));
733 zero[i] = ip[i] <= barThr && len > 0 && ip[i] * (area2 / len) <= distThr;
735 if (zero[0] && zero[1] && zero[2])
736 zero[ip[0] >= ip[1] && ip[0] >= ip[2] ? 0 : (ip[1] >= ip[2] ? 1 : 2)] =
false;
738 for (
int i = 0; i < 3; ++i) {
if (zero[i]) ip[i] = 0; sum += ip[i]; }
740 for (
int i = 0; i < 3; ++i)
if (!zero[i]) { ip[i] /= sum; last = i; }
743 for (
int i = 0; i < 3; ++i)
if (i != last) ip[last] -= ip[i];
744 return zero[0] || zero[1] || zero[2];
750 ScalarType MaxSegDist(VertexType *v0, VertexType *v1, CoordType &farthestPointOnSurf, CoordType &farthestN, Distribution<ScalarType> *distanceDistribution=0)
752 ScalarType maxSurfDist = 0;
753 const ScalarType sampleNum = 10;
754 for(ScalarType k = 1;k<sampleNum;++k)
757 CoordType closestPSurf;
758 CoordType samplePnt = (v0->P()*k +v1->P()*(sampleNum-k))/sampleNum;
759 FaceType *f = Closest(samplePnt, closestPSurf, surfDist);
760 if(distanceDistribution)
761 distanceDistribution->Add(surfDist);
762 if(surfDist > maxSurfDist)
764 maxSurfDist = surfDist;
765 farthestPointOnSurf = closestPSurf;
787 int startEdgeSize = poly.en;
788 for(
int i =0; i<startEdgeSize;++i)
790 EdgeType &ei = poly.edge[i];
793 CoordType farthestP, farthestN;
794 ScalarType maxDist = MaxSegDist(ei.V(0),ei.V(1),farthestP, farthestN);
797 edge::VEEdgeSplit(poly, &ei, farthestP, farthestN);
825 const int startEn = poly.en;
828 for (
size_t i = 0; i < poly.vert.size(); ++i) out.vert[i].ImportData(poly.vert[i]);
829 for (
size_t ei = 0; ei < poly.edge.size(); ++ei)
831 Progress(
int(100 * ei / poly.edge.size()),
"RefineCurveByBaseMesh: tracing segment %lu of %lu", (
unsigned long)ei + 1, (
unsigned long)poly.edge.size());
832 const size_t i0 = tri::Index(poly, poly.edge[ei].cV(0)), i1 = tri::Index(poly, poly.edge[ei].cV(1));
833 std::vector<CoordType> crossings;
834 TraceSegment(poly.vert[i0].cP(), poly.vert[i1].cP(), crossings);
836 for (
const CoordType &c : crossings)
839 out.vert[vi].ImportData(poly.vert[i0]);
840 out.vert[vi].P() = c;
841 out.vert[vi].ClearS();
843 e->V(0) = &out.vert[prev]; e->V(1) = &out.vert[vi];
847 e->V(0) = &out.vert[prev]; e->V(1) = &out.vert[i1];
859 auto faces = [&](
const CoordType &p) {
860 std::vector<FaceType *> fs;
861 for (
const auto &l : Locate(p)) fs.push_back(l.first);
862 std::sort(fs.begin(), fs.end());
865 for (VertexType &v : poly.vert)
867 if (v.IsD() || v.IsS() || edge::VEDegree<EdgeType>(&v) != 2)
continue;
868 std::vector<VertexPointer> nb;
869 edge::VVStarVE(&v, nb);
870 const std::vector<FaceType *> fv = faces(v.cP()), fa = faces(nb[0]->cP()), fb = faces(nb[1]->cP());
871 if (!std::includes(fa.begin(), fa.end(), fv.begin(), fv.end()) ||
872 !std::includes(fb.begin(), fb.end(), fv.begin(), fv.end()))
continue;
873 edge::VEEdgeCollapse(poly, &v);
878 Log(
"RefineCurveByBaseMesh %i en -> %i en, %i vertices inside faces dropped", startEn, poly.en, droppedCnt);
898 typedef std::vector<std::pair<FaceType *, CoordType>>
Location;
905 return LocationFrom(f, ip);
908 Location LocationFrom(FaceType *f,
const CoordType &ip)
const
911 int zeros = 0, one = -1, zero = -1;
912 for (
int i = 0; i < 3; ++i) {
if (ip[i] == 0) { ++zeros; zero = i; }
else one = i; }
915 const int e = (zero + 1) % 3;
916 FaceType *g = f->FFp(e);
918 CoordType ig(0, 0, 0);
919 for (
int j = 0; j < 3; ++j) {
920 if (g->V(j) == f->V(e)) ig[j] = ip[e];
921 if (g->V(j) == f->V((e + 1) % 3)) ig[j] = ip[(e + 1) % 3];
923 loc.push_back({g, ig});
928 VertexPointer v = f->V(one);
929 for (
size_t k = 0; k < loc.size(); ++k)
930 for (
int i = 0; i < 3; ++i) {
931 FaceType *h = loc[k].first;
932 if (h->V(i) != v && h->V((i + 1) % 3) != v)
continue;
933 FaceType *g = h->FFp(i);
935 for (
const auto &l : loc) seen |= l.first == g;
937 CoordType ig(0, 0, 0);
938 for (
int j = 0; j < 3; ++j)
if (g->V(j) == v) ig[j] = 1;
939 loc.push_back({g, ig});
953 const ScalarType tol2 = math::Sqr(
base.bbox.Diag() * ScalarType(1e-6));
954 auto same = [tol2](
const CoordType &a,
const CoordType &b) {
return SquaredDistance(a, b) <= tol2; };
955 for (
const auto &c : loc)
956 for (
int i = 0; i < 3; ++i)
958 if (!
face::IsBorder(*c.first, i) || c.second[(i + 2) % 3] != 0)
continue;
959 const CoordType &a = c.first->cP(i), &b = c.first->cP((i + 1) % 3);
960 for (
const FaceType &g :
base.face)
961 if (!g.IsD() && &g != c.first)
962 for (
int j = 0; j < 3; ++j)
963 if (
face::IsBorder(g, j) && ((same(g.cP(j), b) && same(g.cP((j + 1) % 3), a)) ||
964 (same(g.cP(j), a) && same(g.cP((j + 1) % 3), b))))
970 [[noreturn]]
static void ThrowCutSeam(
const CoordType &p)
973 std::snprintf(buf,
sizeof(buf),
"CoM: a curve crosses or touches a cut seam at (%g, %g, %g): the border there "
974 "has a coincident twin, so the surface is cut but not open. Embed all curves before cutting, "
975 "or weld the seam first.",
double(p[0]),
double(p[1]),
double(p[2]));
976 throw vcg::MissingPreconditionException(buf);
986 void TraceSegment(
const CoordType &p,
const CoordType &q, std::vector<CoordType> &crossings)
990 CoordType cutN = (q - p) ^ (cur[0].first->cN() + target[0].first->cN());
991 if (!(cutN.Norm() > 0))
992 throw vcg::MissingPreconditionException(
"CoM: could not trace a curve segment across the mesh.");
994 for (
int step = 0; ; ++step)
996 for (
const auto &c : cur)
for (
const auto &t : target)
997 if (c.first == t.first)
return;
1000 const CoordType pc = cur[0].first->cP(0) * cur[0].second[0] + cur[0].first->cP(1) * cur[0].second[1] + cur[0].first->cP(2) * cur[0].second[2];
1001 if (SquaredDistance(pc, q) <= math::Sqr(
base.bbox.Diag() * ScalarType(1e-6)))
1003 if (step > 4 *
int(
base.fn) + 16)
1004 throw vcg::MissingPreconditionException(
"CoM: could not trace a curve segment across the mesh.");
1012 FaceType *g =
nullptr;
1014 ScalarType bestInward = std::numeric_limits<ScalarType>::lowest();
1015 bool onBorder =
false;
1016 for (
const auto &c : cur)
1018 const FaceType &f = *c.first;
1019 for (
int i = 0; i < 3; ++i)
1022 for (
int i = 0; i < 3; ++i) sd[i] = cutN.dot(f.cP(i) - p);
1023 CoordType dir(sd[1] - sd[2], sd[2] - sd[0], sd[0] - sd[1]);
1024 const CoordType disp = f.cP(0) * dir[0] + f.cP(1) * dir[1] + f.cP(2) * dir[2];
1025 if (!(disp.Norm() > 0))
continue;
1026 dir /= (disp.dot(q - pc) < 0 ? -disp.Norm() : disp.Norm());
1027 const ScalarType tol = ScalarType(1e-6) * (std::abs(dir[0]) + std::abs(dir[1]) + std::abs(dir[2]));
1028 ScalarType inward = std::numeric_limits<ScalarType>::max();
1029 for (
int k = 0; k < 3; ++k)
if (c.second[k] == 0) inward = std::min(inward, dir[k]);
1030 if (inward > -tol) inward = std::max(inward, ScalarType(0));
1031 if (inward <= bestInward)
continue;
1032 for (
int k = 0; k < 3; ++k)
if (c.second[k] == 0 && dir[k] < 0) dir[k] = 0;
1033 bestInward = inward; g = c.first; bx = c.second; d = dir;
1036 throw vcg::MissingPreconditionException(
"CoM: could not trace a curve segment across the mesh.");
1037 if (bestInward < 0 && onBorder)
1041 std::snprintf(buf,
sizeof(buf),
"CoM: a curve segment leaves the surface across a border at (%g, %g, %g).",
1042 double(pc[0]),
double(pc[1]),
double(pc[2]));
1043 throw vcg::MissingPreconditionException(buf);
1047 ScalarType sExit = std::numeric_limits<ScalarType>::max();
1048 for (
int k = 0; k < 3; ++k)
1049 if (d[k] < 0 && bx[k] > 0 && bx[k] / -d[k] < sExit) { sExit = bx[k] / -d[k]; exitK = k; }
1051 throw vcg::MissingPreconditionException(
"CoM: could not trace a curve segment across the mesh.");
1052 CoordType b = bx + d * sExit;
1054 const ScalarType rest = b[(exitK + 1) % 3] + b[(exitK + 2) % 3];
1055 b[(exitK + 1) % 3] /= rest;
1056 b[(exitK + 2) % 3] = 1 - b[(exitK + 1) % 3];
1058 crossings.push_back(g->cP(0) * b[0] + g->cP(1) * b[1] + g->cP(2) * b[2]);
1059 cur = LocationFrom(g, b);
1072 std::vector<CoordType> operator()(
const MeshType &poly)
const {
1073 std::vector<CoordType> posVec(poly.vn, CoordType(0,0,0));
1074 std::vector<int> cntVec(poly.vn, 0);
1075 for(
int i=0; i<poly.en; ++i)
1076 for(
int j=0; j<2; ++j) {
1077 int vi = tri::Index(poly, poly.edge[i].V0(j));
1078 posVec[vi] += poly.edge[i].V1(j)->P();
1081 for(
int i=0; i<poly.vn; ++i)
1082 posVec[i] = (poly.vert[i].P() + posVec[i]) / ScalarType(cntVec[i]+1);
1109 ScalarType smoothBlend = 0.5;
1112 std::vector<CoordType> operator()(
const MeshType &poly)
const
1115 std::vector<CoordType> smoothPosVec(poly.vn, CoordType(0, 0, 0));
1116 std::vector<int> cntVec(poly.vn, 0);
1117 for (
int i = 0; i < poly.en; ++i)
1118 for (
int j = 0; j < 2; ++j)
1120 int vi = tri::Index(poly, poly.edge[i].V0(j));
1121 smoothPosVec[vi] += poly.edge[i].V1(j)->P();
1124 for (
int i = 0; i < poly.vn; ++i)
1125 smoothPosVec[i] = (poly.vert[i].P() + smoothPosVec[i]) / ScalarType(cntVec[i] + 1);
1128 std::vector<CoordType> fieldPosVec(poly.vn, CoordType(0, 0, 0));
1129 for (
const VertexType &v : poly.vert)
1133 ScalarType q = f->V(0)->Q() * ip[0] + f->V(1)->Q() * ip[1] + f->V(2)->Q() * ip[2];
1134 CoordType fieldDir = GradientScalarField(*f, f->V(0)->Q(),f->V(1)->Q(),f->V(2)->Q());
1136 fieldPosVec[tri::Index(poly, v)] = v.P() + fieldDir * scale * q;
1138 std::vector<CoordType> PosVec(poly.vn, CoordType(0, 0, 0));
1139 for (
int i = 0; i < poly.vn; ++i)
1140 PosVec[i] = (smoothPosVec[i] * smoothBlend + fieldPosVec[i] * (1.0 - smoothBlend));
1157 template<
typename PositionFunctor>
1158 void MoveAndProject(MeshType &poly,
int iterNum, ScalarType moveWeight, ScalarType projectWeight,
1159 PositionFunctor &desiredPos)
1161 tri::RequireCompactness(poly);
1163 if (poly.en == 0 ||
base.fn == 0)
1164 throw vcg::MissingPreconditionException(
"CoM: the curve and the base mesh must both be non-empty.");
1165 for(
int k=0;k<iterNum;++k)
1167 Progress(100*k/iterNum,
"MoveAndProject iteration %i of %i, %i vertices", k+1, iterNum, poly.vn);
1168 if(k==iterNum-1) projectWeight=1;
1169 std::vector<CoordType> desired = desiredPos(poly);
1171 for(
int i=0; i<poly.vn; ++i)
1172 if(!poly.vert[i].IsS())
1175 CoordType delta = desired[i] - poly.vert[i].P();
1176 ScalarType deltaLen = delta.Norm();
1179 desired[i] = poly.vert[i].P() + delta;
1182 CoordType newP = poly.vert[i].P()*(1.0-moveWeight) + desired[i]*moveWeight;
1186 poly.vert[i].P() = newP*(1.0-projectWeight) +closestP*projectWeight;
1187 poly.vert[i].N() = f->N();
1193 poly.vert[i].P() = closestP;
1194 poly.vert[i].N() = f->N();
1206 void SmoothProject(MeshType &poly,
int iterNum, ScalarType smoothWeight, ScalarType projectWeight)
1208 LaplacianFunctor lapFunct;
1209 MoveAndProject(poly, iterNum, smoothWeight, projectWeight, lapFunct);
1236template <
class MeshType>
1241 typedef typename MeshType::ScalarType ScalarType;
1242 typedef typename MeshType::CoordType CoordType;
1243 typedef typename MeshType::VertexType VertexType;
1244 typedef typename MeshType::VertexPointer VertexPointer;
1245 typedef typename MeshType::VertexIterator VertexIterator;
1246 typedef typename MeshType::EdgeIterator EdgeIterator;
1247 typedef typename MeshType::FaceType FaceType;
1248 typedef typename MeshType::FacePointer FacePointer;
1249 typedef typename MeshType::FaceIterator FaceIterator;
1282 for(EdgeIterator ei=poly.edge.begin(); ei!=poly.edge.end();++ei)
1298 FacePointer ff0,ff1;
1300 bool ret=face::FindSharedFaces<FaceType>(v0,v1,ff0,ff1,e0,e1);
1304 assert(ff0->V(e0)==v0 || ff0->V(e0)==v1);
1305 ff0->SetFaceEdgeS(e0);
1306 ff1->SetFaceEdgeS(e1);
1357 MeshType &m = com.
base;
1359 if (poly.vn == 0)
return;
1360 typedef std::pair<size_t, size_t> EdgeKey;
1361 auto key = [](
size_t a,
size_t b) {
return a < b ? EdgeKey(a, b) : EdgeKey(b, a); };
1364 enum { OnVertex, OnEdge, InFace };
1365 struct Loc {
int kind;
size_t vert; EdgeKey edge; ScalarType t;
size_t face[2];
int faceNum; CoordType ip; };
1366 std::vector<Loc> loc(poly.vert.size());
1367 for (
size_t ci = 0; ci < poly.vert.size(); ++ci)
1374 int z = -1, one = -1;
1375 for (
int i = 0; i < 3; ++i) {
if (l.ip[i] == 0) z = i;
if (l.ip[i] == 1) one = i; }
1376 l.face[0] = tri::Index(m, f); l.faceNum = 1;
1377 if (one >= 0) { l.kind = OnVertex; l.vert = tri::Index(m, f->V(one)); }
1381 const size_t a = tri::Index(m, f->V((z + 1) % 3)), b = tri::Index(m, f->V((z + 2) % 3));
1383 l.t = (a < b) ? l.ip[(z + 2) % 3] : l.ip[(z + 1) % 3];
1384 const int e = (z + 1) % 3;
1385 if (f->FFp(e) != f) { l.face[1] = tri::Index(m, f->FFp(e)); l.faceNum = 2; }
1387 else l.kind = InFace;
1393 const ScalarType tol = m.bbox.Diag() * ScalarType(1e-6);
1394 std::vector<size_t> meshV(poly.vert.size());
1395 std::map<EdgeKey, std::vector<std::pair<ScalarType, size_t>>> edgePoints;
1396 std::map<size_t, std::vector<std::pair<size_t, CoordType>>> facePoints;
1397 size_t newVertNum = 0;
1398 const size_t firstNewVert = m.vert.size();
1399 for (
size_t ci = 0; ci < poly.vert.size(); ++ci)
1401 const Loc &l = loc[ci];
1402 if (l.kind == OnVertex) { meshV[ci] = l.vert;
continue; }
1403 if (l.kind == OnEdge) {
1404 auto &pts = edgePoints[l.edge];
1405 const ScalarType len = Distance(m.vert[l.edge.first].cP(), m.vert[l.edge.second].cP());
1406 auto it = std::find_if(pts.begin(), pts.end(), [&](
const std::pair<ScalarType, size_t> &p) { return std::abs(p.first - l.t) * len <= tol; });
1407 if (it != pts.end()) { meshV[ci] = it->second;
continue; }
1408 meshV[ci] = firstNewVert + newVertNum++;
1409 pts.push_back({l.t, meshV[ci]});
1411 auto &pts = facePoints[l.face[0]];
1412 const FaceType &f = m.face[l.face[0]];
1413 const CoordType p = f.cP(0) * l.ip[0] + f.cP(1) * l.ip[1] + f.cP(2) * l.ip[2];
1414 auto it = std::find_if(pts.begin(), pts.end(), [&](
const std::pair<size_t, CoordType> &q) {
1415 return Distance(p, f.cP(0) * q.second[0] + f.cP(1) * q.second[1] + f.cP(2) * q.second[2]) <= tol; });
1416 if (it != pts.end()) { meshV[ci] = it->first;
continue; }
1417 meshV[ci] = firstNewVert + newVertNum++;
1418 pts.push_back({meshV[ci], l.ip});
1422 for (
size_t ci = 0; ci < poly.vert.size(); ++ci)
1424 const Loc &l = loc[ci];
1425 VertexType &nv = m.vert[meshV[ci]];
1426 if (l.kind == OnEdge && meshV[ci] >= firstNewVert) {
1427 const VertexType &va = m.vert[l.edge.first], &vb = m.vert[l.edge.second];
1428 nv.P() = va.cP() * (1 - l.t) + vb.cP() * l.t;
1429 VertexInterpolator<MeshType>::Lerp(m, nv, va, vb, l.t);
1430 }
else if (l.kind == InFace && meshV[ci] >= firstNewVert) {
1431 const FaceType &f = m.face[l.face[0]];
1432 nv.P() = f.cP(0) * l.ip[0] + f.cP(1) * l.ip[1] + f.cP(2) * l.ip[2];
1433 VertexInterpolator<MeshType>::Barycentric(m, nv, *f.cV(0), *f.cV(1), *f.cV(2), l.ip);
1436 for (
size_t ci = 0; ci < poly.vert.size(); ++ci) poly.vert[ci].P() = m.vert[meshV[ci]].cP();
1439 struct Segment {
size_t polyEdge, a, b; };
1440 std::map<size_t, std::vector<Segment>> faceSegments;
1441 std::vector<std::pair<Segment, EdgeKey>> edgeSegments;
1442 std::map<size_t, std::vector<size_t>> vertFaces;
1443 for (
size_t ci = 0; ci < poly.vert.size(); ++ci)
1444 if (loc[ci].kind == OnVertex) vertFaces[loc[ci].vert];
1445 if (!vertFaces.empty())
1446 for (
size_t fi = 0; fi < m.face.size(); ++fi)
if (!m.face[fi].IsD())
1447 for (
int i = 0; i < 3; ++i) {
1448 auto it = vertFaces.find(tri::Index(m, m.face[fi].V(i)));
1449 if (it != vertFaces.end()) it->second.push_back(fi);
1451 auto candidateFaces = [&](
size_t ci) {
1452 if (loc[ci].kind == OnVertex)
return vertFaces[loc[ci].vert];
1453 return std::vector<size_t>(loc[ci].face, loc[ci].face + loc[ci].faceNum);
1455 for (
size_t ei = 0; ei < poly.edge.size(); ++ei)
1457 const auto &e = poly.edge[ei];
1458 const size_t c0 = tri::Index(poly, e.cV(0)), c1 = tri::Index(poly, e.cV(1));
1459 if (meshV[c0] == meshV[c1])
continue;
1462 std::vector<size_t> f0 = candidateFaces(c0), f1 = candidateFaces(c1), common;
1463 std::sort(f0.begin(), f0.end()); std::sort(f1.begin(), f1.end());
1464 std::set_intersection(f0.begin(), f0.end(), f1.begin(), f1.end(), std::back_inserter(common));
1466 throw vcg::MissingPreconditionException(
"CoMEmbed: a curve segment does not lie in one face; call RefineCurveByBaseMesh first.");
1467 const Segment s{ei, meshV[c0], meshV[c1]};
1468 if (common.size() == 1) faceSegments[common[0]].push_back(s);
1470 const FaceType &f = m.face[common[0]];
1472 for (
int i = 0; i < 3; ++i)
1473 if (f.cFFp(i) == &m.face[common[1]]) ek = key(tri::Index(m, f.cV(i)), tri::Index(m, f.cV1(i)));
1474 edgeSegments.push_back({s, ek});
1478 std::set<size_t> touched;
1479 for (
const auto &fp : facePoints) touched.insert(fp.first);
1480 for (
const auto &fs : faceSegments) touched.insert(fs.first);
1481 for (
size_t fi = 0; fi < m.face.size(); ++fi)
if (!m.face[fi].IsD())
1482 for (
int i = 0; i < 3; ++i)
1483 if (edgePoints.count(key(tri::Index(m, m.face[fi].V(i)), tri::Index(m, m.face[fi].V1(i))))) touched.insert(fi);
1488 std::map<size_t, std::vector<size_t>> chains;
1489 std::vector<std::pair<size_t, CoordType>> crossingVerts;
1490 const size_t firstCrossingVert = m.vert.size();
1491 std::vector<std::pair<size_t, LocalTriangulation>> rebuilt;
1492 size_t newFaceNum = 0, done = 0;
1493 for (
size_t fi : touched)
1495 com.Progress(
int(100 * done / touched.size()),
"SplitMeshWithPolyline: rebuilding face %lu of %lu", (
unsigned long)done + 1, (
unsigned long)touched.size());
1497 LocalTriangulation lt;
1498 const FaceType &f = m.face[fi];
1499 lt.SetMetric(f.cP(1) - f.cP(0), f.cP(2) - f.cP(0));
1501 for (
int k = 0; k < 3; ++k) { corner[k] = tri::Index(m, f.cV(k)); lt.AddPoint(corner[k], k == 1, k == 2, (1 << k) | (1 << ((k + 2) % 3))); }
1502 lt.tris.push_back({{0, 1, 2}});
1503 for (
int k = 0; k < 3; ++k)
1505 auto it = edgePoints.find(key(corner[k], corner[(k + 1) % 3]));
1506 if (it == edgePoints.end())
continue;
1507 std::vector<std::pair<ScalarType, size_t>> pts;
1508 for (
const auto &p : it->second) pts.push_back({corner[k] < corner[(k + 1) % 3] ? p.first : 1 - p.first, p.second});
1509 std::sort(pts.begin(), pts.end());
1511 for (
const auto &p : pts)
1513 const ScalarType s = p.first;
1514 const ScalarType u = lt.pts[k].u * (1 - s) + lt.pts[(k + 1) % 3].u * s;
1515 const ScalarType v = lt.pts[k].v * (1 - s) + lt.pts[(k + 1) % 3].v * s;
1516 const int pi = lt.AddPoint(p.second, u, v, 1 << k);
1517 lt.SplitEdge(prev, (k + 1) % 3, pi);
1521 for (
const auto &p : facePoints[fi]) lt.InsertInterior(lt.AddPoint(p.first, p.second[1], p.second[2], 0));
1523 const std::vector<Segment> &segs = faceSegments[fi];
1524 auto pos3 = [&](
int i) {
return f.cP(0) * (1 - lt.pts[i].u - lt.pts[i].v) + f.cP(1) * lt.pts[i].u + f.cP(2) * lt.pts[i].v; };
1525 auto nearPoint = [&](
const CoordType &p) {
1526 for (
size_t i = 0; i < lt.pts.size(); ++i)
if (Distance(pos3(
int(i)), p) <= tol)
return int(i);
1530 for (
size_t i = 0; i < segs.size(); ++i)
1531 for (
size_t j = i + 1; j < segs.size(); ++j)
1533 const int p = lt.Local(segs[i].a), q = lt.Local(segs[i].b), a = lt.Local(segs[j].a), b = lt.Local(segs[j].b);
1534 if (!lt.Crosses(p, q, a, b))
continue;
1535 const long double op = lt.Orient(a, b, p), oq = lt.Orient(a, b, q);
1536 const ScalarType s = ScalarType(op / (op - oq));
1537 const ScalarType u = lt.pts[p].u + (lt.pts[q].u - lt.pts[p].u) * s, v = lt.pts[p].v + (lt.pts[q].v - lt.pts[p].v) * s;
1538 const CoordType x = f.cP(0) * (1 - u - v) + f.cP(1) * u + f.cP(2) * v;
1539 if (nearPoint(x) >= 0)
continue;
1540 crossingVerts.push_back({fi, CoordType(1 - u - v, u, v)});
1541 lt.InsertInterior(lt.AddPoint(firstCrossingVert + crossingVerts.size() - 1, u, v, 0));
1544 for (
const Segment &sg : segs)
1546 const int p = lt.Local(sg.a), q = lt.Local(sg.b);
1547 const Segment3<ScalarType> seg(pos3(p), pos3(q));
1548 std::vector<std::pair<ScalarType, int>> on;
1549 for (
size_t r = 0; r < lt.pts.size(); ++r)
1551 if (
int(r) == p ||
int(r) == q)
continue;
1552 CoordType closest; ScalarType dist;
1553 SegmentPointDistance(seg, pos3(
int(r)), closest, dist);
1554 const ScalarType t = (pos3(
int(r)) - seg.P0()) * (seg.P1() - seg.P0()) / seg.SquaredLength();
1555 if (dist <= tol && t > 0 && t < 1 && Distance(pos3(
int(r)), seg.P0()) > tol && Distance(pos3(
int(r)), seg.P1()) > tol)
1556 on.push_back({t,
int(r)});
1558 std::sort(on.begin(), on.end());
1560 for (
const auto &o : on) { lt.Recover(prev, o.second); prev = o.second; chains[sg.polyEdge].push_back(lt.pts[o.second].vert); }
1561 lt.Recover(prev, q);
1564 newFaceNum += lt.tris.size() - 1;
1565 rebuilt.push_back({fi, std::move(lt)});
1568 for (
const auto &es : edgeSegments)
1570 const Segment &sg = es.first;
1571 auto tOf = [&](
size_t v) -> ScalarType {
1572 if (v == es.second.first)
return 0;
1573 if (v == es.second.second)
return 1;
1574 for (
const auto &p : edgePoints[es.second])
if (p.second == v)
return p.first;
1577 const ScalarType ta = tOf(sg.a), tb = tOf(sg.b);
1578 std::vector<std::pair<ScalarType, size_t>> between;
1579 for (
const auto &p : edgePoints[es.second])
1580 if (p.second != sg.a && p.second != sg.b && (p.first - ta) * (p.first - tb) < 0)
1581 between.push_back({std::abs(p.first - ta), p.second});
1582 std::sort(between.begin(), between.end());
1583 for (
const auto &b : between) chains[sg.polyEdge].push_back(b.second);
1586 for (
size_t k = 0; k < crossingVerts.size(); ++k)
1588 const FaceType &f = m.face[crossingVerts[k].first];
1589 const CoordType &b = crossingVerts[k].second;
1590 VertexType &nv = m.vert[firstCrossingVert + k];
1591 nv.P() = f.cP(0) * b[0] + f.cP(1) * b[1] + f.cP(2) * b[2];
1592 VertexInterpolator<MeshType>::Barycentric(m, nv, *f.cV(0), *f.cV(1), *f.cV(2), b);
1596 const bool wedgeTex = tri::HasPerWedgeTexCoord(m);
1597 size_t nextFace = m.face.size();
1599 for (
auto &r : rebuilt)
1601 FaceType &f = m.face[r.first];
1602 typename FaceType::TexCoordType wt[3];
1603 bool faux[3], border[3], edgeSel[3];
1604 for (
int k = 0; k < 3; ++k) {
1605 if (wedgeTex) wt[k] = f.WT(k);
1606 faux[k] = f.IsF(k); border[k] = f.IsB(k); edgeSel[k] = f.IsFaceEdgeS(k);
1608 const LocalTriangulation < = r.second;
1609 for (
size_t ti = 0; ti < lt.tris.size(); ++ti)
1611 FaceType &g = (ti == 0) ? f : m.face[nextFace++];
1612 if (ti > 0) g.ImportData(f);
1613 for (
int i = 0; i < 3; ++i)
1615 const auto &a = lt.pts[lt.tris[ti][i]], &b = lt.pts[lt.tris[ti][(i + 1) % 3]];
1616 g.V(i) = &m.vert[a.vert];
1619 g.WT(i).P() = wt[0].P() * (1 - a.u - a.v) + wt[1].P() * a.u + wt[2].P() * a.v;
1623 const int shared = a.edges & b.edges;
1624 const int k = shared ? (shared & 1 ? 0 : (shared & 2 ? 1 : 2)) : -1;
1625 if (k >= 0 && faux[k]) g.SetF(i);
else g.ClearF(i);
1626 if (k >= 0 && border[k]) g.SetB(i);
else g.ClearB(i);
1627 if (k >= 0 && edgeSel[k]) g.SetFaceEdgeS(i);
else g.ClearFaceEdgeS(i);
1637 std::set<EdgeKey> curveEdges;
1638 const size_t oldEdgeNum = poly.edge.size();
1639 for (
size_t ei = 0; ei < oldEdgeNum; ++ei)
1641 if (poly.edge[ei].IsD())
continue;
1642 const size_t c0 = tri::Index(poly, poly.edge[ei].cV(0)), c1 = tri::Index(poly, poly.edge[ei].cV(1));
1643 size_t prev = c0, prevMV = meshV[c0];
1644 auto ch = chains.find(ei);
1645 if (ch != chains.end())
1646 for (
size_t mv : ch->second)
1649 poly.vert[vi].ImportData(poly.vert[c0]);
1650 poly.vert[vi].ClearS();
1651 poly.vert[vi].P() = m.vert[mv].cP();
1653 ne->V(0) = &poly.vert[prev]; ne->V(1) = &poly.vert[vi];
1654 curveEdges.insert(key(prevMV, mv));
1655 prev = vi; prevMV = mv;
1657 poly.edge[ei].V(0) = &poly.vert[prev];
1658 if (prevMV != meshV[c1]) curveEdges.insert(key(prevMV, meshV[c1]));
1660 for (FaceType &f : m.face)
if (!f.IsD())
1661 for (
int i = 0; i < 3; ++i)
1662 if (curveEdges.count(key(tri::Index(m, f.V0(i)), tri::Index(m, f.V1(i))))) f.SetFaceEdgeS(i);
1669 struct LocalTriangulation
1671 struct Point {
size_t vert; ScalarType u, v;
int edges; };
1672 std::vector<Point> pts;
1673 std::vector<std::array<int, 3>> tris;
1674 std::set<std::pair<int, int>> recovered;
1675 double g11 = 1, g12 = 0, g22 = 1;
1678 void SetMetric(
const CoordType &e1,
const CoordType &e2)
1680 g11 = e1.dot(e1); g12 = e1.dot(e2); g22 = e2.dot(e2);
1682 double Len2(
int a,
int b)
const
1684 const double du = double(pts[b].u) - pts[a].u, dv = double(pts[b].v) - pts[a].v;
1685 return du * du * g11 + 2 * du * dv * g12 + dv * dv * g22;
1688 int AddPoint(
size_t vert, ScalarType u, ScalarType v,
int edges)
1690 pts.push_back({vert, u, v, edges});
1691 return int(pts.size()) - 1;
1693 int Local(
size_t vert)
const
1695 for (
size_t i = 0; i < pts.size(); ++i)
if (pts[i].vert == vert)
return int(i);
1696 throw vcg::MissingPreconditionException(
"CoMEmbed: a curve segment ends outside the face it was assigned to.");
1703 long double Orient(
int a,
int b,
int c)
const
1705 if (pts[a].edges & pts[b].edges & pts[c].edges)
return 0;
1706 return planar_polygon_detail::Orient2D(Point2d(pts[a].u, pts[a].v), Point2d(pts[b].u, pts[b].v), Point2d(pts[c].u, pts[c].v));
1709 bool FindEdge(
int a,
int b,
size_t &ti,
int &i)
const
1711 for (ti = 0; ti < tris.size(); ++ti)
1712 for (i = 0; i < 3; ++i)
1713 if (tris[ti][i] == a && tris[ti][(i + 1) % 3] == b)
return true;
1717 void SplitEdge(
int a,
int b,
int p)
1719 for (
int side = 0; side < 2; ++side)
1722 if (!FindEdge(side ? b : a, side ? a : b, ti, i))
continue;
1723 const std::array<int, 3> t = tris[ti];
1724 tris[ti] = {{t[i], p, t[(i + 2) % 3]}};
1725 tris.push_back({{p, t[(i + 1) % 3], t[(i + 2) % 3]}});
1729 void InsertInterior(
int p)
1731 for (
size_t ti = 0; ti < tris.size(); ++ti)
1733 const std::array<int, 3> t = tris[ti];
1735 for (
int i = 0; i < 3; ++i) o[i] = Orient(t[i], t[(i + 1) % 3], p);
1736 if (o[0] < 0 || o[1] < 0 || o[2] < 0)
continue;
1737 int onEdge = -1, onCount = 0;
1738 for (
int i = 0; i < 3; ++i)
if (o[i] == 0) { onEdge = i; ++onCount; }
1740 throw vcg::MissingPreconditionException(
"CoMEmbed: two curve points coincide inside a face.");
1741 if (onEdge >= 0) { SplitEdge(t[onEdge], t[(onEdge + 1) % 3], p);
return; }
1742 tris[ti] = {{t[0], t[1], p}};
1743 tris.push_back({{t[1], t[2], p}});
1744 tris.push_back({{t[2], t[0], p}});
1747 throw vcg::MissingPreconditionException(
"CoMEmbed: a curve point is outside the face it was assigned to.");
1749 static int Sign(
long double o) {
return o > 0 ? 1 : (o < 0 ? -1 : 0); }
1751 bool Crosses(
int p,
int q,
int a,
int b)
const
1753 return Sign(Orient(p, q, a)) * Sign(Orient(p, q, b)) < 0 && Sign(Orient(a, b, p)) * Sign(Orient(a, b, q)) < 0;
1759 void Recover(
int p,
int q)
1761 std::deque<std::pair<int, int>> queue;
1762 for (
const auto &t : tris)
1763 for (
int i = 0; i < 3; ++i)
1765 const int a = t[i], b = t[(i + 1) % 3];
1766 if (a < b && Crosses(p, q, a, b)) {
1767 if (recovered.count({a, b}))
1768 throw vcg::MissingPreconditionException(
"CoMEmbed: two curve segments cross inside a face.");
1769 queue.push_back({a, b});
1773 while (!queue.empty())
1775 if (++guard > 100 * (tris.size() + 10) * (tris.size() + 10))
1776 throw vcg::MissingPreconditionException(
"CoMEmbed: could not recover a curve segment; curves may touch or cross.");
1777 const int a = queue.front().first, b = queue.front().second;
1779 size_t t1, t2;
int i1, i2;
1780 if (!FindEdge(a, b, t1, i1) || !FindEdge(b, a, t2, i2))
1781 throw vcg::MissingPreconditionException(
"CoMEmbed: a curve segment crosses the boundary of its face.");
1782 const int c = tris[t1][(i1 + 2) % 3], d = tris[t2][(i2 + 2) % 3];
1783 if (Orient(c, a, d) > 0 && Orient(d, b, c) > 0)
1785 tris[t1] = {{c, a, d}};
1786 tris[t2] = {{d, b, c}};
1787 if (Crosses(p, q, c, d)) queue.push_back({c, d});
1789 else queue.push_back({a, b});
1792 if (!FindEdge(p, q, ti, i) && !FindEdge(q, p, ti, i))
1793 throw vcg::MissingPreconditionException(
"CoMEmbed: could not recover a curve segment; it passes through another curve point.");
1794 recovered.insert({std::min(p, q), std::max(p, q)});
1800 std::vector<int> flat;
1801 for (
const auto &t : tris) flat.insert(flat.end(), t.begin(), t.end());
1802 FlipToConstrainedDelaunay(flat, recovered,
1803 [
this](
int a,
int b,
int c) {
return Orient(a, b, c); },
1804 [
this](
int a,
int b) {
return Len2(a, b); });
1805 for (
size_t i = 0; i < tris.size(); ++i) tris[i] = {{flat[3 * i], flat[3 * i + 1], flat[3 * i + 2]}};
Class to safely add and delete elements in a mesh.
Definition: allocate.h:97
static EdgeIterator AddEdges(MeshType &m, size_t n, PointerUpdater< EdgePointer > &pu)
Add n edges to the mesh. Function to add n edges to the mesh. The elements are added always to the en...
Definition: allocate.h:339
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:195
static FaceIterator AddFaces(MeshType &m, size_t n)
Function to add n faces to the mesh. First wrapper, with no parameters.
Definition: allocate.h:621
static void DeleteEdge(MeshType &m, EdgeType &e)
Definition: allocate.h:952
static void MeshCopy(MeshLeft &ml, ConstMeshRight &mr, bool selected=false, const bool adjFlag=false)
Copy the second mesh over the first one. The first mesh is destroyed. If requested only the selected ...
Definition: append.h:601
static int RemoveDuplicateVertex(MeshType &m, bool RemoveDegenerateFlag=true)
Definition: clean.h:206
static int RemoveDuplicateEdge(MeshType &m)
Definition: clean.h:361
A class for managing curves on a 2-manifold (Curve on Manifold - CoM).
Definition: curve_on_manifold.h:1238
static bool TagFaceEdgeSelWithPolyLine(CoMType &com, MeshType &poly, bool markFlag=true)
Tag face edges of the base mesh that coincide with polyline edges.
Definition: curve_on_manifold.h:1274
static void SplitMeshWithPolyline(CoMType &com, MeshType &poly)
Make the base mesh conform to the polyline: afterwards every polyline edge is an edge of the base mes...
Definition: curve_on_manifold.h:1355
Parameter class controlling the behavior of CoM algorithms.
Definition: curve_on_manifold.h:145
vcg::CallBackPos * cb
Receives progress and diagnostic messages (see wrap/callback.h)
Definition: curve_on_manifold.h:155
ScalarType surfDistThr
Max distance between surface and curve; used in simplify and refine.
Definition: curve_on_manifold.h:148
ScalarType maxMoveDelta
The maximum movement admitted during MoveAndProject (before projection)
Definition: curve_on_manifold.h:151
ScalarType barycentricSnapThr
Threshold for snapping barycentric coords to 0 or 1 (controls vertex/edge snapping)
Definition: curve_on_manifold.h:154
ScalarType gridBailout
The maximum distance bailout used in grid-based spatial queries.
Definition: curve_on_manifold.h:153
ScalarType maxSimpEdgeLen
Maximal admitted edge length (used in simplify: never make edges longer than this)
Definition: curve_on_manifold.h:150
void SetDefault(MeshType &m)
Set all parameters to reasonable defaults based on the mesh bounding box.
Definition: curve_on_manifold.h:161
ScalarType minRefEdgeLen
Minimal admitted edge length (used in refine: never make edges shorter than this)
Definition: curve_on_manifold.h:149
ScalarType maxSnapThr
The maximum distance a snap may move a polyline vertex (onto a mesh vertex or edge)
Definition: curve_on_manifold.h:152
void Dump() const
Print current parameter values to stdout.
Definition: curve_on_manifold.h:173
Param(MeshType &m)
Constructor with default parameter initialization based on mesh size.
Definition: curve_on_manifold.h:158
Definition: curve_on_manifold.h:122
std::vector< std::pair< FaceType *, CoordType > > Location
Definition: curve_on_manifold.h:898
ControlPoints
Which polyline vertices SetControlPoints() makes control points.
Definition: curve_on_manifold.h:448
@ EndsAndNodes
the ends (degree 1) and the junctions (degree > 2): each strand is free
Definition: curve_on_manifold.h:450
@ Selected
the vertices already selected, left as they are
Definition: curve_on_manifold.h:451
@ AllVertices
every vertex: the polyline is taken as it is, only projected and refined
Definition: curve_on_manifold.h:449
MeshType & base
Reference to the base triangulated surface mesh.
Definition: curve_on_manifold.h:188
void SimplifyNullEdges(MeshType &poly)
Remove duplicate/zero-length edges from a polyline.
Definition: curve_on_manifold.h:609
VertexPointer FindVertexSnap(FacePointer fp, CoordType &ip)
Find the vertex pointer for a vertex-snapped barycentric coordinate.
Definition: curve_on_manifold.h:346
FaceType * GetClosestFace(const CoordType &p)
Get the closest face to a query point.
Definition: curve_on_manifold.h:251
MeshGrid uniformGrid
Spatial acceleration structure for closest point queries.
Definition: curve_on_manifold.h:189
FaceType * GetClosestFaceIP(const CoordType &p, CoordType &ip)
Get the closest face and its barycentric coordinates.
Definition: curve_on_manifold.h:264
bool BarycentricSnap(CoordType &ip, const FaceType &f)
Snap the barycentric coordinates of a point of face f onto a vertex or an edge.
Definition: curve_on_manifold.h:718
void SetControlPoints(MeshType &poly, ControlPoints mode=EndsAndNodes)
Choose the control points of a polyline (stored as its vertex selection).
Definition: curve_on_manifold.h:462
void RefineCurveByBaseMesh(MeshType &poly)
Make every polyline segment lie inside one face or along one edge of the base mesh,...
Definition: curve_on_manifold.h:822
Param par
Parameters controlling algorithm behavior.
Definition: curve_on_manifold.h:190
CoM(MeshType &_m)
Definition: curve_on_manifold.h:195
FaceType * GetClosestFacePoint(const CoordType &p, CoordType &closestP)
Get the closest face and the closest point on it.
Definition: curve_on_manifold.h:293
bool RoundingSnap(CoordType &ip, const FaceType &f) const
Definition: curve_on_manifold.h:890
bool SnapPolyline(MeshType &poly)
SnapPolyline snaps the vertexes of a polyline onto the base mesh.
Definition: curve_on_manifold.h:371
bool OnCutSeam(const Location &loc) const
Definition: curve_on_manifold.h:951
int CollapseNullEdges(MeshType &poly)
Merge the two ends of every zero-length polyline edge.
Definition: curve_on_manifold.h:625
static bool BarycentricSnap(CoordType &ip, const FaceType &f, ScalarType barThr, ScalarType distThr)
BarycentricSnap() with explicit thresholds, e.g. rounding-level ones.
Definition: curve_on_manifold.h:724
void MoveAndProject(MeshType &poly, int iterNum, ScalarType moveWeight, ScalarType projectWeight, PositionFunctor &desiredPos)
MoveAndProject.
Definition: curve_on_manifold.h:1158
FaceType * GetClosestFaceIP(const CoordType &p, CoordType &ip, CoordType &in)
Get the closest face, barycentric coordinates, and normal.
Definition: curve_on_manifold.h:280
void RefineCurveByDistance(MeshType &poly)
RefineCurve.
Definition: curve_on_manifold.h:784
void TraceSegment(const CoordType &p, const CoordType &q, std::vector< CoordType > &crossings)
Definition: curve_on_manifold.h:986
int ConnectCrossings(MeshType &poly)
Make the points where strands meet into junctions (opt-in).
Definition: curve_on_manifold.h:482
void Init()
Initialize the CoM data structures for processing.
Definition: curve_on_manifold.h:585
bool IsSnappedVertex(CoordType &ip, int &vi)
Check if a barycentric coordinate is snapped to a vertex.
Definition: curve_on_manifold.h:329
bool IsSnappedEdge(CoordType &ip, int &ei)
Check if a barycentric coordinate is snapped to an edge.
Definition: curve_on_manifold.h:312
Main Class of the Sampling framework.
Definition: point_sampling.h:476
Definition: point_sampling.h:137
static void Box(ComputeMeshType &m)
Calculates the bounding box of the given mesh m.
Definition: bounding.h:45
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
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
bool IsBorder(FaceType const &f, const int j)
Definition: topology.h:55
Definition: curve_on_manifold.h:1671
LaplacianFunctor basic Laplacian smoothing functor.
Definition: curve_on_manifold.h:1071
QualityDistanceFieldFunctor quality field based smoothing functor.
Definition: curve_on_manifold.h:1105