ContiguousSegmentation.hxx

Go to the documentation of this file.
00001 #ifndef ContiguousSegmentation_hxx
00002 #define ContiguousSegmentation_hxx
00003 
00004 #include "Segmentation.hxx"
00005 
00006 namespace CLAM
00007 {
00008         class ContiguousSegmentation : public Segmentation
00009         {
00010         public:
00011                 class InsertedOutOfBounds : public std::exception
00012                 {
00013                         public:
00014                         const char * what() const throw () { return "Segmentation point inserted out of limits";}
00015                 };
00016                 typedef std::vector<double> TimePositions;
00017         public:
00018                 ContiguousSegmentation(double maxPosition=0)
00019                         : Segmentation(maxPosition)
00020                 {
00021                         _onsets.push_back(0);
00022                         _offsets.push_back(maxPosition);
00023                         _selection.push_back(false);
00024 
00025                 }
00026 
00027                 ContiguousSegmentation(double maxPosition, const TData * begin, const TData * end)
00028                         : Segmentation(maxPosition)
00029                 {
00030                         _onsets.push_back(0);
00031                         _offsets.push_back(maxPosition);
00032                         _selection.push_back(false);
00033                         takeArray(begin, end);
00034                 }
00035                 ~ContiguousSegmentation()
00036                 {
00037                 }
00038 
00042                 void takeArray(const TData * begin, const TData * end)
00043                 {                       
00044                         for (const TData * it=begin; it!=end; it++)
00045                                 insert(*it);
00046                 }
00047                 
00051                 unsigned insert(double timePosition)
00052                 {
00053                         if (timePosition<=0.0) throw InsertedOutOfBounds();
00054                         TimePositions::iterator insertPoint = 
00055                                 std::lower_bound(_offsets.begin(), _offsets.end(), timePosition);
00056                         if (insertPoint == _offsets.end()) throw InsertedOutOfBounds();
00057                         //if (insertPoint == _offsets.end()) return insertPoint - _offsets.begin();
00058                         // 'position' must be computed before the insertion to not invalidate iterators.
00059                         unsigned position = insertPoint - _offsets.begin() +1;
00060                         _offsets.insert(insertPoint, timePosition);
00061                         _onsets.insert(_onsets.begin()+position, _offsets[position-1]);
00062                         _selection.insert(_selection.begin()+position, false);
00063                         if (position<=_current) _current++;
00064                         return position;
00065                 }
00069                 void maxPosition(double maxPosition)
00070                 {
00071                         Segmentation::maxPosition(maxPosition);
00072                         _offsets.back()=maxPosition;
00073                 }
00074                 
00081                 void remove(unsigned segment)
00082                 {
00083                         if (_offsets.size()==1) return;
00084                         unsigned offsetToRemove = segment? segment-1 : 0;
00085                         _offsets.erase(_offsets.begin()+offsetToRemove);
00086                         _onsets.erase(_onsets.begin()+segment);
00087                         _selection.erase(_selection.begin()+segment);
00088                         if (_current!=0 && segment<=_current) _current--;
00089                         if (segment==0) _onsets[0]=0;
00090                 }
00097                 unsigned pickOffset(double timePosition, double tolerance) const
00098                 {
00099                         return pickPosition(_offsets, timePosition, tolerance);
00100                 }
00107                 unsigned pickOnset(double timePosition, double tolerance) const
00108                 {
00109                         return pickPosition(_onsets, timePosition, tolerance);
00110                 }
00114                 unsigned pickSegmentBody(double timePosition) const
00115                 {
00116                         if (timePosition<0) return _offsets.size();
00117                         TimePositions::const_iterator lowerBound =
00118                                 std::lower_bound(_offsets.begin(), _offsets.end(), timePosition);
00119                         return lowerBound - _offsets.begin();
00120                 }
00126                 void dragOnset(unsigned segment, double newTimePosition)
00127                 {
00128                         // first onset cannot be moved on Contiguous mode
00129                         if (segment==0) return;
00130                         // The onset is attached to the previous offset
00131                         dragOffset(segment-1, newTimePosition);
00132                 }
00138                 void dragOffset(unsigned segment, double newTimePosition)
00139                 {
00140                         if (segment==_offsets.size()) return; // Invalid segment
00141                         if (segment==_offsets.size()-1) return; // Last offset, cannot be moved
00142 
00143                         // Limit movement on the left to the onset
00144                         if (newTimePosition<_onsets[segment])
00145                                 newTimePosition = _onsets[segment];
00146                         // Limit movement on the right to the next offset
00147                         if (newTimePosition>_offsets[segment+1])
00148                                 newTimePosition = _offsets[segment+1];
00149 
00150                         // The offset and the next onset change together
00151                         _offsets[segment]=newTimePosition;
00152                         _onsets[segment+1]=newTimePosition;
00153                 }
00157                 void fillArray(DataArray& segmentation) const
00158                 {
00159                         unsigned nSegments= _onsets.size();
00160                         segmentation.Resize(nSegments-1);
00161                         segmentation.SetSize(nSegments-1);
00162                         for(unsigned i=1; i<nSegments; i++)
00163                                 segmentation[i-1]=_onsets[i];
00164                 }
00165                 const char * GetClassName() const { return "ContiguousSegmentation"; }
00166 
00167         private:
00175                 unsigned pickPosition(const TimePositions & positions, double timePosition, double tolerance) const
00176                 {
00177                         TimePositions::const_iterator lowerBound = 
00178                                 std::lower_bound(positions.begin(), positions.end(), timePosition-tolerance);
00179                         TimePositions::const_iterator upperBound = 
00180                                 std::upper_bound(lowerBound, positions.end(), timePosition+tolerance);
00181 
00182                         if (lowerBound==upperBound) return positions.size(); // None found
00183         
00184                         // Pick the closest in range
00185                         unsigned lowerSegment = lowerBound - positions.begin();
00186                         unsigned upperSegment = upperBound - positions.begin();
00187                         double lastDifference = std::fabs(timePosition-positions[lowerSegment]);
00188                         for (unsigned i=lowerSegment; i<upperSegment; i++)
00189                         {
00190                                 double newDifference = std::fabs(timePosition-positions[i]);
00191                                 if (newDifference>lastDifference) break;
00192                                 lastDifference = newDifference;
00193                                 lowerSegment = i;
00194                         }
00195                         return lowerSegment;
00196                 }
00197         };
00198 
00199 }
00200 
00201 
00202 
00203 #endif//ContiguousSegmentation_hxx
00204 
Generated by  doxygen 1.6.3