Skip to content

Commit

Permalink
Factored out arc length calculation into a single common place
Browse files Browse the repository at this point in the history
  • Loading branch information
Elliott Mahler committed Jan 19, 2017
1 parent 52e16d6 commit d852fca
Show file tree
Hide file tree
Showing 21 changed files with 253 additions and 483 deletions.
2 changes: 1 addition & 1 deletion SplineDemo.pro
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ HEADERS += \
spline_library/utils/linearalgebra.h \
spline_library/utils/nanoflann.hpp \
spline_library/utils/splinesample_adaptor.h \
spline_library/utils/spline_setup.h \
spline_library/basis/generic_b_spline.h \
spline_library/basis/looping_generic_b_spline.h \
spline_library/basis/generic_b_spline_common.h \
Expand All @@ -51,6 +50,7 @@ HEADERS += \
spline_library/hermite/cubic/looping_uniform_cr_spline.h \
spline_library/utils/calculus.h \
spline_library/vector.h
spline_library/utils/spline_common.h

FORMS += \
demo/settingswidget.ui \
Expand Down
9 changes: 5 additions & 4 deletions spline_library/basis/generic_b_spline.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#pragma once

#include "../spline.h"
#include "../utils/spline_setup.h"
#include "../utils/spline_common.h"

#include "generic_b_spline_common.h"

Expand All @@ -21,15 +21,16 @@ class GenericBSpline final : public Spline<InterpolationType, floating_t>
typename Spline<InterpolationType,floating_t>::InterpolatedPTC getCurvature(floating_t t) const override { return common.getCurvature(t); }
typename Spline<InterpolationType,floating_t>::InterpolatedPTCW getWiggle(floating_t t) const override { return common.getWiggle(t); }

floating_t arcLength(floating_t a, floating_t b) const override { if(a > b) std::swap(a,b); return common.getLength(a,b); }
floating_t totalLength(void) const override { return common.getTotalLength(); }
floating_t arcLength(floating_t a, floating_t b) const override { if(a > b) std::swap(a,b); return SplineCommon::arcLength(*this,a,b); }
floating_t totalLength(void) const override { return SplineCommon::totalLength(*this); }

floating_t getT(int index) const override { return indexToT.at(index); }
floating_t getMaxT(void) const override { return maxT; }

bool isLooping(void) const override { return false; }

size_t segmentCount(void) const override { return common.segmentCount(); }
size_t segmentForT(floating_t t) const override { return common.segmentForT(t); }
floating_t segmentT(size_t segmentIndex) const override { return common.segmentT(segmentIndex); }
floating_t segmentArcLength(size_t segmentIndex, floating_t a, floating_t b) const override { return common.segmentLength(segmentIndex, a, b); }

Expand Down Expand Up @@ -58,7 +59,7 @@ GenericBSpline<InterpolationType,floating_t>::GenericBSpline(const std::vector<I
int padding = degree - 1;

//compute the T values for each point
indexToT = SplineSetup::computeTValuesWithOuterPadding(points, 0.0f, padding);
indexToT = SplineCommon::computeTValuesWithOuterPadding(points, 0.0f, padding);
maxT = indexToT[size - degree];

//for purposes of actual interpolation, we don't need the negative indexes found in indexToT
Expand Down
78 changes: 19 additions & 59 deletions spline_library/basis/generic_b_spline_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#include <vector>

#include "../utils/spline_setup.h"
#include "../utils/spline_common.h"

template<class InterpolationType, typename floating_t>
class GenericBSplineCommon
Expand All @@ -17,14 +17,28 @@ class GenericBSplineCommon
{
return positions.size() - splineDegree;
}

inline size_t segmentForT(floating_t t) const
{
size_t segmentIndex = SplineCommon::getIndexForT(knots, t) - (splineDegree - 1);
if(segmentIndex > segmentCount() - 1)
{
return segmentCount() - 1;
}
else
{
return segmentIndex;
}
}

inline floating_t segmentT(size_t segmentIndex) const
{
return knots[segmentIndex + splineDegree - 1];
}

inline InterpolationType getPosition(floating_t globalT) const
{
size_t startIndex = SplineSetup::getIndexForT(knots, globalT);
size_t startIndex = SplineCommon::getIndexForT(knots, globalT);
if(startIndex >= positions.size() - 2)
{
startIndex = positions.size() - 2;
Expand All @@ -35,7 +49,7 @@ class GenericBSplineCommon

inline typename Spline<InterpolationType,floating_t>::InterpolatedPT getTangent(floating_t globalT) const
{
size_t startIndex = SplineSetup::getIndexForT(knots, globalT);
size_t startIndex = SplineCommon::getIndexForT(knots, globalT);
if(startIndex >= positions.size() - 2)
{
startIndex = positions.size() - 2;
Expand All @@ -49,7 +63,7 @@ class GenericBSplineCommon

inline typename Spline<InterpolationType,floating_t>::InterpolatedPTC getCurvature(floating_t globalT) const
{
size_t startIndex = SplineSetup::getIndexForT(knots, globalT);
size_t startIndex = SplineCommon::getIndexForT(knots, globalT);
if(startIndex >= positions.size() - 2)
{
startIndex = positions.size() - 2;
Expand All @@ -64,7 +78,7 @@ class GenericBSplineCommon

inline typename Spline<InterpolationType,floating_t>::InterpolatedPTCW getWiggle(floating_t globalT) const
{
size_t startIndex = SplineSetup::getIndexForT(knots, globalT);
size_t startIndex = SplineCommon::getIndexForT(knots, globalT);
if(startIndex >= positions.size() - 2)
{
startIndex = positions.size() - 2;
Expand All @@ -78,60 +92,6 @@ class GenericBSplineCommon
);
}

inline floating_t getLength(floating_t a, floating_t b) const
{
//get the knot indices for the beginning and end
size_t aIndex = SplineSetup::getIndexForT(knots, a);
size_t bIndex = SplineSetup::getIndexForT(knots, b);

if(aIndex > positions.size() - 2)
aIndex = positions.size() - 2;
if(bIndex > positions.size() - 2)
bIndex = positions.size() - 2;

//if a and b occur inside the same segment, compute the length within that segment
//but excude cases where a > b, because that means we need to wrap around
if(aIndex == bIndex && a <= b) {
return computeSegmentLength(aIndex, a, b);
}
else {
//a and b occur in different segments, so compute one length for every segment
floating_t result{0};

//first segment
result += computeSegmentLength(aIndex, a, knots[aIndex + 1]);

//last segment
result += computeSegmentLength(bIndex, knots[bIndex], b);

//if b index is less than a index, that means the user wants to wrap around the end of the spline and back to the beginning
//if so, add the number of points in the spline to bIndex, and we'll use mod to make sure it stays in range
size_t numSegments = positions.size() - splineDegree;
if(bIndex <= aIndex)
bIndex += numSegments;

//middle segments
auto padding = splineDegree - 1;
for(size_t i = aIndex + 1; i < bIndex; i++) {
size_t wrappedIndex = (i - padding)%numSegments + padding;
result += computeSegmentLength(wrappedIndex, knots[wrappedIndex], knots[wrappedIndex + 1]);
}

return result;
}
}

inline floating_t getTotalLength(void) const
{
floating_t result{0};

for(size_t segmentIndex = 0; segmentIndex < segmentCount(); segmentIndex++) {
auto index = segmentIndex + splineDegree - 1;
result += computeSegmentLength(index, knots[index], knots[index + 1]);
}
return result;
}

inline floating_t segmentLength(size_t segmentIndex, floating_t a, floating_t b) const {

auto innerIndex = segmentIndex + splineDegree - 1;
Expand Down
21 changes: 11 additions & 10 deletions spline_library/basis/looping_generic_b_spline.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#pragma once

#include "../spline.h"
#include "../utils/spline_setup.h"
#include "../utils/spline_common.h"
#include "generic_b_spline_common.h"

#include <unordered_map>
Expand All @@ -21,14 +21,15 @@ class LoopingGenericBSpline final : public Spline<InterpolationType, floating_t>
typename Spline<InterpolationType,floating_t>::InterpolatedPTCW getWiggle(floating_t x) const override;

floating_t arcLength(floating_t a, floating_t b) const override;
floating_t totalLength(void) const override { return common.getTotalLength(); }
floating_t totalLength(void) const override { return SplineCommon::totalLength(*this); }

floating_t getT(int index) const override { return indexToT.at(index); }
floating_t getMaxT(void) const override { return maxT; }

bool isLooping(void) const override { return true; }

size_t segmentCount(void) const override { return common.segmentCount(); }
size_t segmentForT(floating_t t) const override { return common.segmentForT(t); }
floating_t segmentT(size_t segmentIndex) const override { return common.segmentT(segmentIndex); }
floating_t segmentArcLength(size_t segmentIndex, floating_t a, floating_t b) const override { return common.segmentLength(segmentIndex, a, b); }

Expand All @@ -52,7 +53,7 @@ LoopingGenericBSpline<InterpolationType,floating_t>::LoopingGenericBSpline(const
int padding = degree - 1;

//compute the T values for each point
indexToT = SplineSetup::computeLoopingTValues(points, 0.0f, padding);
indexToT = SplineCommon::computeLoopingTValues(points, 0.0f, padding);
maxT = indexToT[size];

//we need enough space to repeat the last 'degree' elements
Expand Down Expand Up @@ -84,39 +85,39 @@ LoopingGenericBSpline<InterpolationType,floating_t>::LoopingGenericBSpline(const
template<class InterpolationType, typename floating_t>
InterpolationType LoopingGenericBSpline<InterpolationType,floating_t>::getPosition(floating_t globalT) const
{
floating_t wrappedT = SplineSetup::wrapGlobalT(globalT, maxT);
floating_t wrappedT = SplineCommon::wrapGlobalT(globalT, maxT);
return common.getPosition(wrappedT);
}

template<class InterpolationType, typename floating_t>
typename Spline<InterpolationType,floating_t>::InterpolatedPT
LoopingGenericBSpline<InterpolationType,floating_t>::getTangent(floating_t globalT) const
{
floating_t wrappedT = SplineSetup::wrapGlobalT(globalT, maxT);
floating_t wrappedT = SplineCommon::wrapGlobalT(globalT, maxT);
return common.getTangent(wrappedT);
}

template<class InterpolationType, typename floating_t>
typename Spline<InterpolationType,floating_t>::InterpolatedPTC
LoopingGenericBSpline<InterpolationType,floating_t>::getCurvature(floating_t globalT) const
{
floating_t wrappedT = SplineSetup::wrapGlobalT(globalT, maxT);
floating_t wrappedT = SplineCommon::wrapGlobalT(globalT, maxT);
return common.getCurvature(wrappedT);
}

template<class InterpolationType, typename floating_t>
typename Spline<InterpolationType,floating_t>::InterpolatedPTCW
LoopingGenericBSpline<InterpolationType,floating_t>::getWiggle(floating_t globalT) const
{
floating_t wrappedT = SplineSetup::wrapGlobalT(globalT, maxT);
floating_t wrappedT = SplineCommon::wrapGlobalT(globalT, maxT);
return common.getWiggle(wrappedT);
}

template<class InterpolationType, typename floating_t>
floating_t LoopingGenericBSpline<InterpolationType,floating_t>::arcLength(floating_t a, floating_t b) const
{
floating_t wrappedA = SplineSetup::wrapGlobalT(a, maxT);
floating_t wrappedB = SplineSetup::wrapGlobalT(b, maxT);
floating_t wrappedA = SplineCommon::wrapGlobalT(a, maxT);
floating_t wrappedB = SplineCommon::wrapGlobalT(b, maxT);

return common.getLength(wrappedA, wrappedB);
return SplineCommon::arcLength(*this, wrappedA, wrappedB);
}
19 changes: 10 additions & 9 deletions spline_library/basis/looping_uniform_cubic_bspline.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include "../spline.h"
#include "uniform_cubic_bspline_common.h"

#include "../utils/spline_setup.h"
#include "../utils/spline_common.h"

template<class InterpolationType, typename floating_t=float>
class LoopingUniformCubicBSpline final : public Spline<InterpolationType, floating_t>
Expand All @@ -19,14 +19,15 @@ class LoopingUniformCubicBSpline final : public Spline<InterpolationType, floati
typename Spline<InterpolationType,floating_t>::InterpolatedPTCW getWiggle(floating_t x) const override;

floating_t arcLength(floating_t a, floating_t b) const override;
floating_t totalLength(void) const override { return common.getTotalLength(); }
floating_t totalLength(void) const override { return SplineCommon::totalLength(*this); }

floating_t getT(int index) const override { return index; }
floating_t getMaxT(void) const override { return maxT; }

bool isLooping(void) const override { return true; }

size_t segmentCount(void) const override { return common.segmentCount(); }
size_t segmentForT(floating_t t) const override { return common.segmentForT(t); }
floating_t segmentT(size_t segmentIndex) const override { return segmentIndex; }
floating_t segmentArcLength(size_t segmentIndex, floating_t a, floating_t b) const override { return common.segmentLength(segmentIndex, a, b); }

Expand Down Expand Up @@ -63,39 +64,39 @@ LoopingUniformCubicBSpline<InterpolationType,floating_t>::LoopingUniformCubicBSp
template<class InterpolationType, typename floating_t>
InterpolationType LoopingUniformCubicBSpline<InterpolationType,floating_t>::getPosition(floating_t globalT) const
{
floating_t wrappedT = SplineSetup::wrapGlobalT(globalT, maxT);
floating_t wrappedT = SplineCommon::wrapGlobalT(globalT, maxT);
return common.getPosition(wrappedT);
}

template<class InterpolationType, typename floating_t>
typename Spline<InterpolationType,floating_t>::InterpolatedPT
LoopingUniformCubicBSpline<InterpolationType,floating_t>::getTangent(floating_t globalT) const
{
floating_t wrappedT = SplineSetup::wrapGlobalT(globalT, maxT);
floating_t wrappedT = SplineCommon::wrapGlobalT(globalT, maxT);
return common.getTangent(wrappedT);
}

template<class InterpolationType, typename floating_t>
typename Spline<InterpolationType,floating_t>::InterpolatedPTC
LoopingUniformCubicBSpline<InterpolationType,floating_t>::getCurvature(floating_t globalT) const
{
floating_t wrappedT = SplineSetup::wrapGlobalT(globalT, maxT);
floating_t wrappedT = SplineCommon::wrapGlobalT(globalT, maxT);
return common.getCurvature(wrappedT);
}

template<class InterpolationType, typename floating_t>
typename Spline<InterpolationType,floating_t>::InterpolatedPTCW
LoopingUniformCubicBSpline<InterpolationType,floating_t>::getWiggle(floating_t globalT) const
{
floating_t wrappedT = SplineSetup::wrapGlobalT(globalT, maxT);
floating_t wrappedT = SplineCommon::wrapGlobalT(globalT, maxT);
return common.getWiggle(wrappedT);
}

template<class InterpolationType, typename floating_t>
floating_t LoopingUniformCubicBSpline<InterpolationType,floating_t>::arcLength(floating_t a, floating_t b) const
{
floating_t wrappedA = SplineSetup::wrapGlobalT(a, maxT);
floating_t wrappedB = SplineSetup::wrapGlobalT(b, maxT);
floating_t wrappedA = SplineCommon::wrapGlobalT(a, maxT);
floating_t wrappedB = SplineCommon::wrapGlobalT(b, maxT);

return common.getLength(wrappedA, wrappedB);
return SplineCommon::arcLength(*this, wrappedA, wrappedB);
}
7 changes: 4 additions & 3 deletions spline_library/basis/uniform_cubic_bspline.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include "../spline.h"
#include "uniform_cubic_bspline_common.h"

#include "../utils/spline_setup.h"
#include "../utils/spline_common.h"

#include <cassert>

Expand All @@ -21,15 +21,16 @@ class UniformCubicBSpline final : public Spline<InterpolationType, floating_t>
typename Spline<InterpolationType,floating_t>::InterpolatedPTC getCurvature(floating_t t) const override { return common.getCurvature(t); }
typename Spline<InterpolationType,floating_t>::InterpolatedPTCW getWiggle(floating_t t) const override { return common.getWiggle(t); }

floating_t arcLength(floating_t a, floating_t b) const override { if(a > b) std::swap(a,b); return common.getLength(a,b); }
floating_t totalLength(void) const override { return common.getTotalLength(); }
floating_t arcLength(floating_t a, floating_t b) const override { if(a > b) std::swap(a,b); return SplineCommon::arcLength(*this,a,b); }
floating_t totalLength(void) const override { return SplineCommon::totalLength(*this); }

floating_t getT(int index) const override { return index - 1; }
floating_t getMaxT(void) const override { return maxT; }

bool isLooping(void) const override { return false; }

size_t segmentCount(void) const override { return common.segmentCount(); }
size_t segmentForT(floating_t t) const override { return common.segmentForT(t); }
floating_t segmentT(size_t segmentIndex) const override { return segmentIndex; }
floating_t segmentArcLength(size_t segmentIndex, floating_t a, floating_t b) const override { return common.segmentLength(segmentIndex, a, b); }

Expand Down
Loading

0 comments on commit d852fca

Please sign in to comment.