CLAM-Development
1.1
|
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