00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <list>
00026 #include <vector>
00027
00028 #include <boost/shared_ptr.hpp>
00029
00030 #include "../../common/math/WMath.h"
00031 #include "../../common/math/WPlane.h"
00032 #include "../../common/WLimits.h"
00033 #include "../../common/WTransferable.h"
00034 #include "../WDataSetFiberVector.h"
00035 #include "WFiberCluster.h"
00036
00037
00038
00039
00040
00041
00042
00043 boost::shared_ptr< WPrototyped > WFiberCluster::m_prototype = boost::shared_ptr< WPrototyped >();
00044
00045
00046 WFiberCluster::WFiberCluster()
00047 : WTransferable(),
00048 m_centerLineCreationLock( new boost::shared_mutex() ),
00049 m_longestLineCreationLock( new boost::shared_mutex() )
00050 {
00051 }
00052
00053 WFiberCluster::WFiberCluster( size_t index )
00054 : WTransferable(),
00055 m_centerLineCreationLock( new boost::shared_mutex() ),
00056 m_longestLineCreationLock( new boost::shared_mutex() )
00057 {
00058 m_memberIndices.push_back( index );
00059 }
00060
00061 WFiberCluster::WFiberCluster( const WFiberCluster& other )
00062 : WTransferable( other ),
00063 m_memberIndices( other.m_memberIndices ),
00064 m_fibs( other.m_fibs ),
00065 m_color( other.m_color ),
00066 m_centerLineCreationLock( new boost::shared_mutex() ),
00067
00068 m_longestLineCreationLock( new boost::shared_mutex() ),
00069 m_centerLine(),
00070 m_longestLine()
00071 {
00072
00073 if( other.m_centerLine )
00074 {
00075 m_centerLine = boost::shared_ptr< WFiber >( new WFiber( *other.m_centerLine.get() ) );
00076 }
00077 if( other.m_longestLine )
00078 {
00079 m_longestLine = boost::shared_ptr< WFiber >( new WFiber( *other.m_longestLine.get() ) );
00080 }
00081 }
00082
00083 WFiberCluster::~WFiberCluster()
00084 {
00085 delete m_centerLineCreationLock;
00086 delete m_longestLineCreationLock;
00087 }
00088
00089 void WFiberCluster::merge( WFiberCluster& other )
00090 {
00091 std::list< size_t >::const_iterator cit = other.m_memberIndices.begin();
00092 for( ; cit != other.m_memberIndices.end(); ++cit)
00093 {
00094 m_memberIndices.push_back( *cit );
00095 }
00096
00097 other.m_centerLine.reset();
00098 other.m_longestLine.reset();
00099 other.clear();
00100 }
00101
00102
00103
00104 void WFiberCluster::setDataSetReference( boost::shared_ptr< const WDataSetFiberVector > fibs )
00105 {
00106 m_fibs = fibs;
00107 }
00108
00109 boost::shared_ptr< const WDataSetFiberVector > WFiberCluster::getDataSetReference() const
00110 {
00111 return m_fibs;
00112 }
00113
00114
00115
00116
00117
00118 boost::shared_ptr< WPrototyped > WFiberCluster::getPrototype()
00119 {
00120 if( !m_prototype )
00121 {
00122 m_prototype = boost::shared_ptr< WPrototyped >( new WFiberCluster() );
00123 }
00124 return m_prototype;
00125 }
00126
00127
00128 void WFiberCluster::generateCenterLine() const
00129 {
00130
00131 boost::unique_lock< boost::shared_mutex > lock = boost::unique_lock< boost::shared_mutex >( *m_centerLineCreationLock );
00132
00133 if( m_centerLine )
00134 {
00135 lock.unlock();
00136 return;
00137 }
00138
00139
00140 boost::shared_ptr< WDataSetFiberVector > fibs( new WDataSetFiberVector() );
00141 size_t avgFiberSize = 0;
00142 for( std::list< size_t >::const_iterator cit = m_memberIndices.begin(); cit != m_memberIndices.end(); ++cit )
00143 {
00144 fibs->push_back( m_fibs->at( *cit ) );
00145 avgFiberSize += fibs->back().size();
00146 }
00147 avgFiberSize /= fibs->size();
00148
00149 unifyDirection( fibs );
00150
00151 for( WDataSetFiberVector::iterator cit = fibs->begin(); cit != fibs->end(); ++cit )
00152 {
00153 cit->resampleByNumberOfPoints( avgFiberSize );
00154 }
00155
00156 m_centerLine = boost::shared_ptr< WFiber >( new WFiber() );
00157 m_centerLine->reserve( avgFiberSize );
00158 for( size_t i = 0; i < avgFiberSize; ++i )
00159 {
00160 WPosition avgPosition( 0, 0, 0 );
00161 for( WDataSetFiberVector::const_iterator cit = fibs->begin(); cit != fibs->end(); ++cit )
00162 {
00163 avgPosition += cit->at( i );
00164 }
00165 avgPosition /= static_cast< double >( fibs->size() );
00166 m_centerLine->push_back( avgPosition );
00167 }
00168
00169 elongateCenterLine();
00170 lock.unlock();
00171 }
00172
00173 void WFiberCluster::generateLongestLine() const
00174 {
00175
00176 boost::unique_lock< boost::shared_mutex > lock = boost::unique_lock< boost::shared_mutex >( *m_longestLineCreationLock );
00177
00178 if( m_longestLine )
00179 {
00180 lock.unlock();
00181 return;
00182 }
00183
00184 m_longestLine = boost::shared_ptr< WFiber >( new WFiber() );
00185
00186
00187 if( m_fibs->size() == 0 )
00188 {
00189 return;
00190 }
00191
00192 size_t longest = 0;
00193 size_t longestID = 0;
00194 for( size_t cit = 0; cit < m_fibs->size(); ++cit )
00195 {
00196 if( m_fibs->at( cit ).size() > longest )
00197 {
00198 longest = m_fibs->at( cit ).size();
00199 longestID = cit;
00200 }
00201 }
00202
00203 for( WFiber::const_iterator cit = m_fibs->at( longestID ).begin(); cit != m_fibs->at( longestID ).end(); ++cit )
00204 {
00205 m_longestLine->push_back( *cit );
00206 }
00207
00208 lock.unlock();
00209 }
00210
00211 void WFiberCluster::elongateCenterLine() const
00212 {
00213
00214 assert( m_centerLine->size() > 1 );
00215 WFiber cL( *m_centerLine );
00216 WPlane p( cL[0] - cL[1], cL[0] + ( cL[0] - cL[1] ) );
00217 boost::shared_ptr< WPosition > cutPoint( new WPosition( 0, 0, 0 ) );
00218 bool intersectionFound = true;
00219
00220
00221 boost::shared_ptr< WDataSetFiberVector > fibs( new WDataSetFiberVector() );
00222 for( std::list< size_t >::const_iterator cit = m_memberIndices.begin(); cit != m_memberIndices.end(); ++cit )
00223 {
00224 fibs->push_back( m_fibs->at( *cit ) );
00225 }
00226
00227 while( intersectionFound )
00228 {
00229 intersectionFound = false;
00230 size_t intersectingFibers = 0;
00231
00232 for( WDataSetFiberVector::iterator cit = fibs->begin(); cit != fibs->end(); )
00233 {
00234 if( intersectPlaneLineNearCP( p, *cit, cutPoint ) )
00235 {
00236 if( length( *cutPoint - p.getPosition() ) < 20 )
00237 {
00238
00239 intersectingFibers++;
00240 intersectionFound = true;
00241 ++cit;
00242 }
00243 else
00244 {
00245 cit = fibs->erase( cit );
00246 }
00247 }
00248 else
00249 {
00250 cit = fibs->erase( cit );
00251 }
00252 }
00253 if( intersectingFibers > 10 )
00254 {
00255 cL.insert( cL.begin(), cL[0] + ( cL[0] - cL[1] ) );
00256 p.resetPosition( cL[0] + ( cL[0] - cL[1] ) );
00257
00258
00259
00260
00261
00262
00263 }
00264 else
00265 {
00266 break;
00267 }
00268 }
00269
00270 boost::shared_ptr< WDataSetFiberVector > fobs( new WDataSetFiberVector() );
00271 for( std::list< size_t >::const_iterator cit = m_memberIndices.begin(); cit != m_memberIndices.end(); ++cit )
00272 {
00273 fobs->push_back( m_fibs->at( *cit ) );
00274 }
00275
00276
00277
00278 WPlane q( cL.back() - cL[ cL.size() - 2 ], cL.back() + ( cL.back() - cL[ cL.size() - 2 ] ) );
00279 intersectionFound = true;
00280 while( intersectionFound )
00281 {
00282 intersectionFound = false;
00283 size_t intersectingFibers = 0;
00284
00285 for( WDataSetFiberVector::iterator cit = fobs->begin(); cit != fobs->end(); )
00286 {
00287 if( intersectPlaneLineNearCP( q, *cit, cutPoint ) )
00288 {
00289 if( length( *cutPoint - q.getPosition() ) < 20 )
00290 {
00291
00292 intersectingFibers++;
00293 intersectionFound = true;
00294 ++cit;
00295 }
00296 else
00297 {
00298 cit = fobs->erase( cit );
00299 }
00300 }
00301 else
00302 {
00303 cit = fobs->erase( cit );
00304 }
00305 }
00306 if( intersectingFibers > 10 )
00307 {
00308 cL.push_back( cL.back() + ( cL.back() - cL[ cL.size() - 2 ] ) );
00309 q.resetPosition( cL.back() + ( cL.back() - cL[ cL.size() - 2 ] ) );
00310
00311
00312
00313
00314
00315
00316 }
00317 else
00318 {
00319 break;
00320 }
00321 }
00322 *m_centerLine = cL;
00323 }
00324
00325 void WFiberCluster::unifyDirection( boost::shared_ptr< WDataSetFiberVector > fibs ) const
00326 {
00327 if( fibs->size() < 2 )
00328 {
00329 return;
00330 }
00331
00332 assert( !( fibs->at( 0 ).empty() ) && "WFiberCluster.unifyDirection: Empty fiber processed.. aborting" );
00333
00334
00335 const WFiber& firstFib = fibs->front();
00336 const WPosition start = firstFib.front();
00337 const WPosition m1 = firstFib.at( firstFib.size() * 1.0 / 3.0 );
00338 const WPosition m2 = firstFib.at( firstFib.size() * 2.0 / 3.0 );
00339 const WPosition end = firstFib.back();
00340
00341 for( WDataSetFiberVector::iterator cit = fibs->begin() + 1; cit != fibs->end(); ++cit )
00342 {
00343 const WFiber& other = *cit;
00344 double distance = length2( start - other.front() ) +
00345 length2( m1 - other.at( other.size() * 1.0 / 3.0 ) ) +
00346 length2( m2 - other.at( other.size() * 2.0 / 3.0 ) ) +
00347 length2( end - other.back() );
00348 double inverseDistance = length2( start - other.back() ) +
00349 length2( m1 - other.at( other.size() * 2.0 / 3.0 ) ) +
00350 length2( m2 - other.at( other.size() * 1.0 / 3.0 ) ) +
00351 length2( end - other.front() );
00352 distance /= 4.0;
00353 inverseDistance /= 4.0;
00354 if( inverseDistance < distance )
00355 {
00356 cit->reverseOrder();
00357 }
00358 }
00359 }
00360
00361 boost::shared_ptr< WFiber > WFiberCluster::getCenterLine() const
00362 {
00363 if( !m_centerLine )
00364 {
00365 generateCenterLine();
00366 }
00367 return m_centerLine;
00368 }
00369
00370 boost::shared_ptr< WFiber > WFiberCluster::getLongestLine() const
00371 {
00372 if( !m_longestLine )
00373 {
00374 generateLongestLine();
00375 }
00376 return m_longestLine;
00377 }
00378
00379 WBoundingBox WFiberCluster::getBoundingBox() const
00380 {
00381 WBoundingBox result;
00382 for( std::list< size_t >::const_iterator cit = m_memberIndices.begin(); cit != m_memberIndices.end(); ++cit )
00383 {
00384 result.expandBy( computeBoundingBox( m_fibs->at( *cit ) ) );
00385 }
00386 return result;
00387 }