Permalink
Browse files

Merge topic 'itkParametricPathOscillation'

706a6bf BUG: itkPolyLineParametricPath infinite loop for degenerate paths
  • Loading branch information...
hjmjohnson authored and kwrobot committed Mar 29, 2013
2 parents 78fbbdf + 706a6bf commit 86a4aac1384ec55fc62cf92b2c8c943599cd2084
@@ -119,6 +119,17 @@ class ITK_EXPORT PolyLineParametricPath:public
/** Return the container of Vertices as a const object. */
itkGetModifiableObjectMacro(VertexList, VertexListType);
+ /** This function overrides the superclass IncrementInput and calculates
+ * the next pixel along the path to visit by using the instantaneous
+ * partial derivatives to calculate the timestep needed to move along the
+ * path by one pixel */
+ virtual OffsetType IncrementInput(InputType & input) const;
+
+ /** This function overrides the superclass EvaluateDerivative and instead
+ * calculates the instantaneous derivative of input by taking the index
+ * of the previous and next integral timepoints and subtracting them */
+ virtual VectorType EvaluateDerivative(const InputType & input) const;
+
protected:
PolyLineParametricPath();
~PolyLineParametricPath(){}
@@ -36,7 +36,7 @@ PolyLineParametricPath< VDimension >
}
const VertexType vertex0 = static_cast<const VertexListType*>(this->m_VertexList)->ElementAt( int(input) );
- const VertexType vertex1 = static_cast<const VertexListType*>(this->m_VertexList)->ElementAt( int(input + 1.0) );
+ const VertexType vertex1 = static_cast<const VertexListType*>(this->m_VertexList)->ElementAt( int(input) + 1 );
const double fractionOfLineSegment = input - int(input);
@@ -53,12 +53,108 @@ PolyLineParametricPath< VDimension >
return output;
}
-//template<unsigned int VDimension>
-//typename PolyLineParametricPath<VDimension>::VectorType
-//PolyLineParametricPath<VDimension>
-//::EvaluateDerivative(const InputType & input) const
-//{
-//}
+template<unsigned int VDimension>
+typename PolyLineParametricPath<VDimension>::VectorType
+PolyLineParametricPath<VDimension>
+::EvaluateDerivative(const InputType & input) const
+{
+ //Get next integral time-point
+ const InputType nextTimepoint = std::min(std::floor(input + 1.0), this->EndOfInput());
+
+ //Get previous integral time-point
+ const InputType previousTimepoint = nextTimepoint - 1.0;
+
+ //Calculate the continuous index for both points
+ const ContinuousIndexType nextIndex = this->Evaluate(nextTimepoint);
+ const ContinuousIndexType prevIndex = this->Evaluate(previousTimepoint);
+
+ //For some reason, there's no way to convert ContinuousIndexType to VectorType
+ VectorType partialDerivatives;
+ for (unsigned int i = 0; i < VDimension; ++i)
+ {
+ partialDerivatives[i] = nextIndex[i] - prevIndex[i];
+ }
+
+ return partialDerivatives;
+}
+
+template<unsigned int VDimension>
+typename PolyLineParametricPath<VDimension>::OffsetType
+PolyLineParametricPath<VDimension>
+::IncrementInput(InputType & input) const
+{
+ //Save this input index since we will use it to calculate the offset
+ const OutputType originalIndex = this->EvaluateToIndex(input);
+
+ InputType potentialTimestep = itk::NumericTraits< InputType >::ZeroValue();
+ bool timeStepSmallEnough = false;
+ while (!timeStepSmallEnough)
+ {
+ if (input == this->EndOfInput())
+ {
+ return this->GetZeroOffset();
+ }
+
+ //Check to make sure we aren't already at a place with an offset of 1 pixel
+ const OutputType potentialIndex = this->EvaluateToIndex(input);
+ //For some reason, there's no way to convert OutputType to OffsetType
+ OffsetType offset;
+ for (unsigned int i = 0; i < VDimension; ++i)
+ {
+ offset[i] = potentialIndex[i] - originalIndex[i];
+ }
+
+ if (offset != this->GetZeroOffset())
+ {
+ return offset;
+ }
+ //Get the derivative at the current input
+ VectorType partialDerivatives = this->EvaluateDerivative(input);
+
+ //Find the largest of all the partial derivatives
+ unsigned int maxPartialDerivativeIndex = 0;
+ for (unsigned int i = 1; i < VDimension; ++i)
+ {
+ if (std::abs(partialDerivatives[i]) > std::abs(partialDerivatives[maxPartialDerivativeIndex]))
+ {
+ maxPartialDerivativeIndex = i;
+ }
+ }
+
+ //Calculate the timestep required to effect a 1 pixel change
+ potentialTimestep = 1.0/std::abs(partialDerivatives[maxPartialDerivativeIndex]);
+
+ //Check to make sure the timestep doesn't put the input past the next integral timestep
+ //(since the derivatives can change)
+ if (input + potentialTimestep > std::floor(input + 1.0))
+ {
+ input = std::floor(input + 1.0); //Set the input to the next integral time-step
+ }
+ else
+ {
+ timeStepSmallEnough = true;
+ }
+ }
+
+ //Finalize the potential timestep into THE timestep
+ const InputType timestep = potentialTimestep;
+
+ //Get the index at the next timestep so we can calculate the offset
+ const OutputType nextIndex = this->EvaluateToIndex(input + timestep);
+
+ //For some reason, there's no way to convert OutputType to OffsetType
+ OffsetType offset;
+ for (unsigned int i = 0; i < VDimension; ++i)
+ {
+ offset[i] = nextIndex[i] - originalIndex[i];
+ }
+
+ //Update input timestep
+ input += timestep;
+
+ //Return the offset
+ return offset;
+}
template< unsigned int VDimension >
PolyLineParametricPath< VDimension >
@@ -84,6 +84,35 @@ int itkPolyLineParametricPathTest(int, char* [])
offset = path->IncrementInput( input );
std::cout << "Incrementing the input from 0.5 to " << input << ": " << offset << std::endl;
+ //Test a degenerate path
+ std::cout << "Generating degenerate path" << std::endl;
+ PathType::Pointer path2 = PathType::New();
+
+ //Add a bunch of points closely spaced together
+ for (double k = 0; k < 10; k+=0.1)
+ {
+ v.Fill(k);
+ path2->AddVertex(v);
+ }
+
+ //Add a point that is very far away from the first points
+ v.Fill(100);
+ path2->AddVertex(v);
+ PathType::InputType path2Input = path2->StartOfInput();
+
+ PathType::OffsetType zeroOffset;
+ zeroOffset.Fill(0);
+
+ std::cout << "Starting degenerate path test" << std::endl;
+ while (true)
+ {
+ offset = path2->IncrementInput(path2Input);
+ if (offset == zeroOffset)
+ {
+ break;
+ }
+ }
+
if (passed)
{
std::cout << "PolyLineParametricPath tests passed" << std::endl;
@@ -1 +1 @@
-e28ea77794e99f1da041ac67fa55e7ed
+b79c0a553750ed6fce228b23df79f7d8

0 comments on commit 86a4aac

Please sign in to comment.