32 #include <boost/array.hpp>
34 #include "../exceptions/WOutOfBounds.h"
35 #include "../WAssert.h"
36 #include "../WLimits.h"
37 #include "../WStringUtils.h"
39 #include "WPolynomialEquationSolvers.h"
40 #include "linearAlgebra/WPosition.h"
41 #include "linearAlgebra/WVectorFixed.h"
57 throw WOutOfBounds( std::string(
"There is no midpoint for an empty line." ) );
59 return line[( line.
size() - 1 ) / 2];
67 double pathLength(
const WLine& line )
71 for(
size_t i = 1; i < line.
size(); ++i )
73 len += length( line[i - 1] - line[i] );
82 if(
size() != numPoints &&
size() > 1 && numPoints > 0 )
84 const double pathL = pathLength( *
this );
85 double newSegmentLength = pathL / ( numPoints - 1 );
86 const double delta = newSegmentLength * 1.0e-10;
87 double remainingLength = 0.0;
89 for(
size_t i = 0; i < (
size() - 1 ); ++i )
91 remainingLength += length(
at( i ) -
at( i + 1 ) );
92 while( ( remainingLength > newSegmentLength ) || std::abs( remainingLength - newSegmentLength ) < delta )
94 remainingLength -= newSegmentLength;
98 WPosition newPoint =
at( i + 1 ) + remainingLength * normalize(
at( i ) -
at( i + 1 ) );
110 else if(
size() == 1 &&
size() < numPoints )
112 for(
size_t i = 0; i < numPoints; ++i )
117 if(
size() != numPoints )
137 for(
size_t i = 1; i <
size(); ++i )
166 while( k <
size() && length( newLine.
back() -
at( k ) ) < newSegmentLength )
176 newLine.
push_back( newLine.
back() + normalize(
at( k ) - newLine.
back() ) * newSegmentLength );
183 WVector3d lineDirection = current - pred;
184 WAssert( lineDirection !=
WVector3d( 0.0, 0.0, 0.0 ),
"current should be diffrent from pred" );
186 double alpha = dot( lineDirection, lineDirection );
187 double beta = 2.0 * dot( lineDirection, o_c );
188 double gamma = dot( o_c, o_c ) - newSegmentLength * newSegmentLength;
190 std::pair< std::complex< double >, std::complex< double > > solution = solveRealQuadraticEquation( alpha, beta, gamma );
192 WAssert( std::imag( solution.first ) == 0.0 && std::imag( solution.second ) == 0.0,
"Imaginary solution detected." );
194 if( std::real( solution.first ) > 0.0 )
196 pointOfIntersection = pred + std::real( solution.first ) * ( current - pred );
200 pointOfIntersection = pred + std::real( solution.second ) * ( current - pred );
202 newLine.
push_back( pointOfIntersection );
228 while( k <
size() && length( newLine.
back() -
at( k ) ) < newSegmentLength )
233 if( length( newLine.
back() -
at( k - 1 ) ) > 0.001 )
240 newLine.
push_back( newLine.
back() + normalize(
at( k ) - newLine.
back() ) * newSegmentLength );
247 WVector3d lineDirection = current - pred;
248 WAssert( lineDirection !=
WVector3d( 0.0, 0.0, 0.0 ),
"current should be diffrent from pred" );
250 double alpha = dot( lineDirection, lineDirection );
251 double beta = 2.0 * dot( lineDirection, o_c );
252 double gamma = dot( o_c, o_c ) - newSegmentLength * newSegmentLength;
254 std::pair< std::complex< double >, std::complex< double > > solution = solveRealQuadraticEquation( alpha, beta, gamma );
256 WAssert( std::imag( solution.first ) == 0.0 && std::imag( solution.second ) == 0.0,
"Imaginary solution detected." );
258 if( std::real( solution.first ) > 0.0 )
260 pointOfIntersection = pred + std::real( solution.first ) * ( current - pred );
264 pointOfIntersection = pred + std::real( solution.second ) * ( current - pred );
266 newLine.
push_back( pointOfIntersection );
273 int equalsDelta(
const WLine& line,
const WLine& other,
double delta )
275 size_t pts = ( std::min )( other.
size(), line.
size() );
277 bool sameLines =
true;
278 for( diffPos = 0; ( diffPos < pts ) && sameLines; ++diffPos )
280 for(
int x = 0; x < 3; ++x )
282 sameLines = sameLines && ( std::abs( line[diffPos][x] - other[diffPos][x] ) <= delta );
285 if( sameLines && ( line.
size() == other.
size() ) )
296 double maxSegmentLength(
const WLine& line )
303 for(
size_t i = 0; i < line.
size() - 1; ++i )
305 result = std::max( result,
static_cast< double >( length( line[i] - line[i+1] ) ) );
312 const size_t numBasePoints = 4;
313 boost::array< WPosition, numBasePoints > m;
314 boost::array< WPosition, numBasePoints > n;
316 double distance = 0.0;
317 double inverseDistance = 0.0;
318 for(
size_t i = 0; i < numBasePoints; ++i )
320 m[i] = other.
at( ( other.
size() - 1 ) *
static_cast< double >( i ) / ( numBasePoints - 1 ) );
321 n[i] =
at( (
size() - 1 ) *
static_cast< double >( i ) / ( numBasePoints - 1 ) );
322 distance += length2( m[i] - n[i] );
323 inverseDistance += length2( m[i] -
at( (
size() - 1 ) *
static_cast< double >( numBasePoints - 1 - i ) / ( numBasePoints - 1 ) ) );
325 distance /=
static_cast< double >( numBasePoints );
326 inverseDistance /=
static_cast< double >( numBasePoints );
328 if( inverseDistance < distance )
void expandBy(const WBoundingBoxImpl< VT > &bb)
Expands this bounding box to include the given bounding box.
A line is an ordered sequence of WPositions.
void resampleByNumberOfPoints(size_t numPoints)
Resample this line so it has a number of given points afterwards.
void unifyDirectionBy(const WLine &other)
Put the line into reverse ordering if the reverse ordering would have a similar direction to the give...
void resampleBySegmentLengthKeepShortFibers(double newSegmentLength)
Resample this line so there are only segements of the given length.
void reverseOrder()
Reverses the order of the points.
void removeAdjacentDuplicates()
Collapse samplepoints which are equal and neighboured.
void resampleBySegmentLength(double newSegementLength)
Resample this line so there are only segements of the given length.
WLine()
Creates an empty line.
This is taken from OpenSceneGraph <osg/MixinVector> but copy and pasted in order to reduce dependency...
void reserve(size_type new_capacity)
Wrapper around std::vector member function.
WMixinVector & operator=(const vector_type &other)
Assignment operator for the appropriate vector type.
size_type size() const
Wrapper around std::vector member function.
void push_back(const value_type &value)
Wrapper around std::vector member function.
const_reference back() const
Wrapper around std::vector member function.
bool empty() const
Wrapper around std::vector member function.
const_reference front() const
Wrapper around std::vector member function.
const_iterator end() const
Wrapper around std::vector member function.
const_iterator begin() const
Wrapper around std::vector member function.
const_reference at(size_type index) const
Wrapper around std::vector member function.
vector_type::const_iterator const_iterator
Compares to std::vector type.
Indicates invalid element access of a container.
This only is a 3d double vector.
const double DBL_EPS
Smallest double such: 1.0 + DBL_EPS == 1.0 is still true.