| 122 | } |
| 123 | |
| 124 | PolylineProjectionResult3Arg findMaxProjectionOnPolyline( const VertCoords& points, const Polyline3& polyline, |
| 125 | const VertBitSet* pointsRegion, AffineXf3f* xf, float loDistLimitSq ) |
| 126 | { |
| 127 | MR_TIMER; |
| 128 | std::atomic<float> currMaxDistSq{ loDistLimitSq }; |
| 129 | auto pv = parallel_reduce( tbb::blocked_range( 0_v, points.endId() ), MaxArg<float, VertId>{}, |
| 130 | [&] ( const auto & range, MaxArg<float, VertId> curr ) |
| 131 | { |
| 132 | for ( VertId v = range.begin(); v < range.end(); ++v ) |
| 133 | { |
| 134 | if ( !contains( pointsRegion, v ) ) |
| 135 | continue; |
| 136 | auto myLoDistLimitSq = currMaxDistSq.load( std::memory_order_relaxed ); |
| 137 | auto myRes = findProjectionOnPolyline( points[v], polyline, FLT_MAX, xf, myLoDistLimitSq ); |
| 138 | while ( myRes.distSq > myLoDistLimitSq && !currMaxDistSq.compare_exchange_strong( myLoDistLimitSq, myRes.distSq, std::memory_order_relaxed ) ) |
| 139 | {} |
| 140 | assert( myRes.distSq <= currMaxDistSq ); |
| 141 | curr.include( myRes.distSq, v ); |
| 142 | } |
| 143 | return curr; |
| 144 | }, |
| 145 | [] ( MaxArg<float, VertId> a, const MaxArg<float, VertId> & b ) { a.include( b ); return a; } |
| 146 | ); |
| 147 | PolylineProjectionResult3Arg res; |
| 148 | if ( pv.arg ) |
| 149 | { |
| 150 | res.pointId = pv.arg; |
| 151 | assert( pv.val <= currMaxDistSq ); // it can be less only if the closest distance for all points was smaller than given loDistLimitSq |
| 152 | static_cast<PolylineProjectionResult3&>( res ) = findProjectionOnPolyline( points[res.pointId], polyline, FLT_MAX, xf, currMaxDistSq ); |
| 153 | } |
| 154 | return res; |
| 155 | } |
| 156 | |
| 157 | PolylineProjectionResult3 findProjectionOnPolyline( const Line3f& ln, const Polyline3& polyline, |
| 158 | float upDistLimitSq, AffineXf3f* xf, float loDistLimitSq ) |