2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU Lesser General Public License as
4 * published by the Free Software Foundation, either version 3 of the
5 * License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 * @file LambdaMST3D.ih
19 * @author Kacper Pluta (\c kacper.pluta@esiee.fr )
20 * Laboratoire d'Informatique Gaspard-Monge - LIGM, France
24 * This file is part of the DGtal library.
30 template < typename TSpace, typename TSegmentation, typename Functor, typename DSSFilter >
32 LambdaMST3DEstimator< TSpace, TSegmentation, Functor, DSSFilter >::LambdaMST3DEstimator() : myBegin(), myEnd(), dssSegments ( 0 ), myFunctor() {}
35 template < typename TSpace, typename TSegmentation, typename Functor, typename DSSFilter >
38 LambdaMST3DEstimator< TSpace, TSegmentation, Functor, DSSFilter >::init ( ConstIterator itb, ConstIterator ite )
44 template < typename TSpace, typename TSegmentation, typename Functor, typename DSSFilter >
47 LambdaMST3DEstimator< TSpace, TSegmentation, Functor, DSSFilter >::attach ( Alias<TSegmentation> segmentComputer )
49 dssSegments = &segmentComputer;
52 template < typename TSpace, typename TSegmentation, typename Functor, typename DSSFilter >
55 LambdaMST3DEstimator< TSpace, TSegmentation, Functor, DSSFilter >::isValid () const
57 return ( dssSegments != 0 );
61 template < typename TSpace, typename TSegmentation, typename Functor, typename DSSFilter >
64 LambdaMST3DEstimator< TSpace, TSegmentation, Functor, DSSFilter >::getDSSFilter ( )
69 template < typename TSpace, typename TSegmentation, typename Functor, typename DSSFilter >
71 typename LambdaMST3DEstimator< TSpace, TSegmentation, Functor, DSSFilter >::Value
72 LambdaMST3DEstimator< TSpace, TSegmentation, Functor, DSSFilter >::treatOrphan ( OrphanDSSIterator begin, OrphanDSSIterator end,
75 Value tangent, prev, partial;
76 for ( auto it = begin ; it != end; ++it )
78 // the returned type is signed but dssLen should never be negative
79 const auto dssLen = std::distance ( it->begin(), it->end() ) + 1;
81 const auto pos = myDSSFilter. position ( *it, p );
82 partial = myFunctor ( *it, pos, dssLen );
83 if ( prev.first.cosineSimilarity ( partial.first ) > M_PI_2 )
84 partial.first = -partial.first;
91 template < typename TSpace, typename TSegmentation, typename Functor, typename DSSFilter >
92 template < typename DSSesIterator, typename OrphanIterator >
95 LambdaMST3DEstimator< TSpace, TSegmentation, Functor, DSSFilter >::treatOrphans ( DSSesIterator begin,
97 OrphanIterator obegin,
99 std::multimap < Point, Value > & outValues )
101 for ( auto DSS = begin; DSS != end; ++DSS )
103 for ( auto orphan = obegin; orphan != oend; ++orphan )
105 if ( ! DSS->isInDSS ( *orphan ) && myDSSFilter.admissibility ( *DSS, *orphan ) )
107 // the returned type is signed but dssLen should never be negative
108 const auto dssLen = std::distance ( DSS->begin ( ), DSS->end ( ) ) + 1;
109 const auto pos = myDSSFilter. position ( *DSS, *orphan );
110 outValues.insert ( std::make_pair ( *orphan, myFunctor ( *DSS, pos, dssLen ) ) );
117 template < typename TSpace, typename TSegmentation, typename Functor, typename DSSFilter >
119 typename LambdaMST3DEstimator< TSpace, TSegmentation, Functor, DSSFilter >::RealVector
120 LambdaMST3DEstimator< TSpace, TSegmentation, Functor, DSSFilter >::eval( const Point & p )
122 assert ( isValid() );
123 std::vector < SegmentComputer > admissibleDSS;
124 bool isOrphan = true;
125 typename TSegmentation::SegmentComputerIterator DSS = dssSegments->begin();
126 typename TSegmentation::SegmentComputerIterator lastDSS = dssSegments->end();
127 Value tangent, partial, prev;
129 for ( ; DSS != lastDSS; ++DSS )
131 if ( myDSSFilter ( *DSS ) )
134 // collect DSSes that may need to be required to ensure coverage if the only covering DSS was filtered out
135 if ( isOrphan && ! DSS->isInDSS ( p ) && myDSSFilter.admissibility ( *DSS, p ) )
136 admissibleDSS.push_back ( *DSS );
138 if ( DSS->isInDSS ( p ) )
140 // the returned type is signed but dssLen should never be negative
141 const auto dssLen = std::distance ( DSS.begin(), DSS.end() ) + 1;
143 // the returned type is signed but pos should never be negative
144 const auto pos = std::distance ( DSS.begin(), std::find ( DSS.begin ( ), DSS.end ( ), p ) ) + 1;
145 partial = myFunctor ( *DSS, pos, dssLen );
146 if ( partial.first.norm() > 0. && prev.first.norm() > 0. && prev.first.cosineSimilarity ( partial.first ) > M_PI_2 )
147 partial.first = -partial.first;
153 if ( isOrphan && admissibleDSS.size ( ) > 0 )
154 tangent = treatOrphan ( admissibleDSS.cbegin ( ), admissibleDSS.cend ( ), p );
155 else if ( isOrphan && admissibleDSS.size ( ) == 0 )
156 throw std::runtime_error ( "The DSS filter is not well constructed! The point is not DSS covered!" );
158 if ( tangent.second != 0. )
159 return tangent.first / tangent.second;
161 return tangent.first;
164 template < typename TSpace, typename TSegmentation, typename Functor, typename DSSFilter >
165 template < typename OutputIterator >
168 LambdaMST3DEstimator< TSpace, TSegmentation, Functor, DSSFilter >::eval ( ConstIterator itb, ConstIterator ite,
169 OutputIterator result )
171 assert ( myBegin != myEnd && isValid() && myBegin <= itb && ite <= myEnd && itb != ite );
172 std::multimap < Point, Value > outValues;
173 dssSegments->setSubRange ( itb, ite );
174 typename TSegmentation::SegmentComputerIterator DSS = dssSegments->begin();
175 typename TSegmentation::SegmentComputerIterator lastDSS = dssSegments->end();
176 std::vector< Point > orphans;
178 for(; DSS != lastDSS; ++DSS)
180 // coolect potential orphans
181 if ( myDSSFilter ( *DSS ) )
183 for ( const auto & point : *DSS )
184 if ( std::find ( orphans.cbegin ( ), orphans.cend ( ), point ) == orphans.cend ( ) )
185 orphans.push_back ( point );
189 auto dssLen = std::distance ( DSS.begin(), DSS.end() );
190 for ( unsigned int indexOfPointInDSS = 0; indexOfPointInDSS < dssLen; indexOfPointInDSS++ )
192 outValues.insert ( std::make_pair ( *(DSS.begin ( ) + indexOfPointInDSS),
193 myFunctor ( *DSS, indexOfPointInDSS + 1, dssLen + 1 ) ) );
194 // if a point is covered then it is not an orphan
195 auto orphan = std::find ( orphans.begin ( ), orphans.end ( ), *(DSS.begin ( ) + indexOfPointInDSS) );
196 if ( orphan != orphans.end ( ) )
197 orphans.erase ( orphan );
200 if ( ! orphans.empty ( ) )
201 treatOrphans ( dssSegments->begin ( ), dssSegments->end ( ), orphans.cbegin ( ), orphans.cend ( ), outValues );
202 accumulate< OutputIterator >( outValues, itb, ite, result );
206 template < typename TSpace, typename TSegmentation, typename Functor, typename DSSFilter >
207 template <typename OutputIterator>
210 LambdaMST3DEstimator< TSpace, TSegmentation, Functor, DSSFilter >::accumulate ( std::multimap < Point, Value > & outValues,
211 ConstIterator itb, ConstIterator ite,
212 OutputIterator & result )
214 Value prev = outValues.lower_bound( *itb )->second;
215 Value accum_prev = outValues.lower_bound( *itb )->second;
216 for ( ConstIterator itt = itb; itt != ite; ++itt )
218 typename std::multimap< Point, Value >::const_iterator it = outValues.lower_bound ( *itt );
219 typename std::multimap< Point, Value >::const_iterator it2 = outValues.upper_bound ( *itt );
221 for (; it != it2; it++ )
223 Value partial = it->second;
224 if ( partial.first.norm() > 0. && prev.first.norm() > 0. && prev.first.cosineSimilarity ( partial.first ) > M_PI_2 )
225 partial.first = -partial.first;
229 outValues.erase ( *itt );
230 // avoid tangent flapping
231 if ( accum_prev.first.norm() > 0. && tangent.first.norm() > 0. && accum_prev.first.cosineSimilarity ( tangent.first ) > M_PI_2 )
232 tangent.first = -tangent.first;
233 accum_prev = tangent;
234 if ( tangent.second != 0 )
235 *result++ = ( tangent.first / tangent.second );
237 *result++ = tangent.first;