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 )
158 for(
size_t i = 1; i <
size(); )
161 if( length( newLine.
back() - current ) > newSegmentLength )
163 newLine.
push_back( newLine.
back() + normalize( ( current - newLine.
back() ) * newSegmentLength ) );
171 current = (*this)[i];
173 while( length( newLine.
back() - current ) < newSegmentLength && i <
size() );
179 const WPosition pred = ( *this )[ i - 1 ];
181 WVector3d lineDirection = current - pred;
182 WAssert( lineDirection !=
WVector3d( 0.0, 0.0, 0.0 ),
"current should be diffrent from pred" );
184 double alpha = dot( lineDirection, lineDirection );
185 double beta = 2.0 * dot( lineDirection, o_c );
186 double gamma = dot( o_c, o_c ) - newSegmentLength * newSegmentLength;
188 std::pair< std::complex< double >, std::complex< double > > solution = solveRealQuadraticEquation( alpha, beta, gamma );
190 WAssert( std::imag( solution.first ) == 0.0 && std::imag( solution.second ) == 0.0,
"Imaginary solution detected." );
192 if( std::real( solution.first ) > 0.0 )
194 pointOfIntersection = pred + std::real( solution.first ) * ( ( *this )[i] - pred );
198 pointOfIntersection = pred + std::real( solution.second ) * ( ( *this )[i] - pred );
200 newLine.
push_back( pointOfIntersection );
206 int equalsDelta(
const WLine& line,
const WLine& other,
double delta )
208 size_t pts = ( std::min )( other.
size(), line.
size() );
210 bool sameLines =
true;
211 for( diffPos = 0; ( diffPos < pts ) && sameLines; ++diffPos )
213 for(
int x = 0; x < 3; ++x )
215 sameLines = sameLines && ( std::abs( line[diffPos][x] - other[diffPos][x] ) <= delta );
218 if( sameLines && ( line.
size() == other.
size() ) )
229 double maxSegmentLength(
const WLine& line )
236 for(
size_t i = 0; i < line.
size() - 1; ++i )
238 result = std::max( result, static_cast< double >( length( line[i] - line[i+1] ) ) );
245 const size_t numBasePoints = 4;
246 boost::array< WPosition, numBasePoints > m;
247 boost::array< WPosition, numBasePoints > n;
249 double distance = 0.0;
250 double inverseDistance = 0.0;
251 for(
size_t i = 0; i < numBasePoints; ++i )
253 m[i] = other.
at( ( other.
size() - 1 ) * static_cast< double >( i ) / ( numBasePoints - 1 ) );
254 n[i] =
at( (
size() - 1 ) * static_cast< double >( i ) / ( numBasePoints - 1 ) );
255 distance += length2( m[i] - n[i] );
256 inverseDistance += length2( m[i] -
at( (
size() - 1 ) * static_cast< double >( numBasePoints - 1 - i ) / ( numBasePoints - 1 ) ) );
258 distance /=
static_cast< double >( numBasePoints );
259 inverseDistance /=
static_cast< double >( numBasePoints );
261 if( inverseDistance < distance )