support closed loops

This commit is contained in:
Alec Jacobson
2020-04-11 20:21:19 -04:00
parent 4ab389d462
commit 4ca4f8b341
2 changed files with 22 additions and 8 deletions
+18 -7
View File
@@ -44,10 +44,18 @@ IGL_INLINE void igl::fit_cubic_bezier(
}
return t.normalized();
};
const Eigen::RowVectorXd tHat1 = tangent(0,+1);
const Eigen::RowVectorXd tHat2 = tangent(nPts-1,-1);
Eigen::RowVectorXd tHat1 = tangent(0,+1);
Eigen::RowVectorXd tHat2 = tangent(nPts-1,-1);
// If first and last points are identically equal, then consider closed
const bool closed = (d.row(0) - d.row(d.rows()-1)).squaredNorm() == 0;
// If closed loop make tangents match
if(closed)
{
tHat1 = (tHat1 - tHat2).eval().normalized();
tHat2 = -tHat1;
}
cubics.clear();
fit_cubic_bezier_substring(d,0,nPts-1,tHat1,tHat2,error,cubics);
fit_cubic_bezier_substring(d,0,nPts-1,tHat1,tHat2,error,closed,cubics);
};
IGL_INLINE void igl::fit_cubic_bezier_substring(
@@ -57,6 +65,7 @@ IGL_INLINE void igl::fit_cubic_bezier_substring(
const Eigen::RowVectorXd & tHat1,
const Eigen::RowVectorXd & tHat2,
const double error,
const bool force_split,
std::vector<Eigen::MatrixXd> & cubics)
{
// Helper functions
@@ -252,7 +261,7 @@ IGL_INLINE void igl::fit_cubic_bezier_substring(
int splitPoint;
double maxError = ComputeMaxError(d, first, last, bezCurve, u, splitPoint);
if (maxError < error)
if (!force_split && maxError < error)
{
cubics.push_back(bezCurve);
return;
@@ -272,7 +281,7 @@ IGL_INLINE void igl::fit_cubic_bezier_substring(
}
GenerateBezier(d, first, last, uPrime, tHat1, tHat2, bezCurve);
maxError = ComputeMaxError(d, first, last, bezCurve, uPrime, splitPoint);
if (maxError < error) {
if (!force_split && maxError < error) {
cubics.push_back(bezCurve);
return;
}
@@ -284,8 +293,10 @@ IGL_INLINE void igl::fit_cubic_bezier_substring(
const Eigen::RowVectorXd tHatCenter =
(d.row(splitPoint-1)-d.row(splitPoint+1)).normalized();
//foobar
fit_cubic_bezier_substring(d,first,splitPoint,tHat1,tHatCenter,error,cubics);
fit_cubic_bezier_substring(d,splitPoint,last,(-tHatCenter).eval(),tHat2,error,cubics);
fit_cubic_bezier_substring(
d,first,splitPoint,tHat1,tHatCenter,error,false,cubics);
fit_cubic_bezier_substring(
d,splitPoint,last,(-tHatCenter).eval(),tHat2,error,false,cubics);
}
+4 -1
View File
@@ -18,7 +18,8 @@ namespace igl
//
// Inputs:
// d #d by dim list of points along a curve to be fit with a cubic bezier
// spline (should probably be roughly uniformly spaced)
// spline (should probably be roughly uniformly spaced). If d(0)==d(end),
// then will treat as a closed curve.
// error maximum squared distance allowed
// Output:
// cubics #cubics list of 4 by dim lists of cubic control points
@@ -34,6 +35,7 @@ namespace igl
// tHat1 tangent to use at beginning of spline
// tHat2 tangent to use at end of spline
// error see above
// force_split whether to force a split (i.e., force a recursive call)
// cubics running list of cubics so far
// Outputs
// cubics running list of cubics so far (new cubics appended)
@@ -44,6 +46,7 @@ namespace igl
const Eigen::RowVectorXd & tHat1,
const Eigen::RowVectorXd & tHat2,
const double error,
const bool force_split,
std::vector<Eigen::MatrixXd> & cubics);
}