CLAM-Development
1.1
|
00001 #ifndef UnsizedSegmentation_hxx 00002 #define UnsizedSegmentation_hxx 00003 00004 #include "Segmentation.hxx" 00005 00006 namespace CLAM 00007 { 00008 class UnsizedSegmentation : 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 UnsizedSegmentation() 00019 : Segmentation(0) 00020 { 00021 } 00022 UnsizedSegmentation(double maxPosition) 00023 : Segmentation(maxPosition) 00024 { 00025 } 00026 00027 UnsizedSegmentation(double maxPosition, const TData * begin, const TData * end) 00028 : Segmentation(maxPosition) 00029 { 00030 takeArray(begin, end); 00031 } 00035 void takeArray(const TData * begin, const TData * end) 00036 { 00037 for (const TData * it=begin; it!=end; it++) 00038 insert(*it); 00039 } 00040 ~UnsizedSegmentation() 00041 { 00042 } 00046 unsigned insert(double timePosition) 00047 { 00048 if (timePosition<0.0) throw InsertedOutOfBounds(); 00049 if (timePosition>=maxPosition()) throw InsertedOutOfBounds(); 00050 TimePositions::iterator insertPoint = 00051 std::lower_bound(_offsets.begin(), _offsets.end(), timePosition); 00052 if (insertPoint==_offsets.end()) 00053 { 00054 _offsets.push_back(timePosition); 00055 _onsets.push_back(timePosition); 00056 _selection.push_back(false); 00057 return _offsets.size()-1; 00058 } 00059 unsigned position = insertPoint - _offsets.begin(); 00060 _offsets.insert(insertPoint, timePosition); 00061 _onsets.insert(_onsets.begin()+position, timePosition); 00062 _selection.insert(_selection.begin()+position, false); 00063 if (position<=_current) _current++; 00064 return position; 00065 } 00072 void remove(unsigned segment) 00073 { 00074 _offsets.erase(_offsets.begin()+segment); 00075 _onsets.erase(_onsets.begin()+segment); 00076 _selection.erase(_selection.begin()+segment); 00077 if (_current!=0 && segment<=_current) _current--; 00078 } 00085 unsigned pickOffset(double timePosition, double tolerance) const 00086 { 00087 return pickPosition(_offsets, timePosition, tolerance); 00088 } 00095 unsigned pickOnset(double timePosition, double tolerance) const 00096 { 00097 return pickPosition(_onsets, timePosition, tolerance); 00098 } 00102 unsigned pickSegmentBody(double timePosition) const 00103 { 00104 if (timePosition<0) return _offsets.size(); 00105 TimePositions::const_iterator upperBound = 00106 std::lower_bound(_offsets.begin(), _offsets.end(), timePosition); 00107 if (upperBound == _offsets.begin()) return 0; 00108 if (timePosition - *(upperBound-1) > *upperBound - timePosition) return upperBound - _offsets.begin(); 00109 return upperBound - _offsets.begin()-1; 00110 } 00116 void dragOnset(unsigned segment, double newTimePosition) 00117 { 00118 // The onset is attached to the offset 00119 dragOffset(segment, newTimePosition); 00120 } 00126 void dragOffset(unsigned segment, double newTimePosition) 00127 { 00128 if (segment==_offsets.size()) return; // Invalid segment 00129 00130 // Limit movement on the left to the onset 00131 double leftLimit = segment!=0 ? 00132 _onsets[segment-1] : 0.0; 00133 double rightLimit = segment+1<_offsets.size()? 00134 _onsets[segment+1] : maxPosition(); 00135 if (newTimePosition<leftLimit) 00136 newTimePosition = leftLimit; 00137 // Limit movement on the right to the next offset 00138 if (newTimePosition>rightLimit) 00139 newTimePosition = rightLimit; 00140 00141 // The offset and the onset change together 00142 _offsets[segment]=newTimePosition; 00143 _onsets[segment]=newTimePosition; 00144 } 00148 void fillArray(DataArray& segmentation) const 00149 { 00150 unsigned nSegments = _onsets.size(); 00151 segmentation.Resize(nSegments); 00152 segmentation.SetSize(nSegments); 00153 for (unsigned i=0; i<nSegments; i++) 00154 segmentation[i]=_onsets[i]; 00155 } 00156 00157 const char * GetClassName() const { return "UnsizedSegmentation"; } 00158 00159 private: 00167 unsigned pickPosition(const TimePositions & positions, double timePosition, double tolerance) const 00168 { 00169 TimePositions::const_iterator lowerBound = 00170 std::lower_bound(positions.begin(), positions.end(), timePosition-tolerance); 00171 TimePositions::const_iterator upperBound = 00172 std::upper_bound(lowerBound, positions.end(), timePosition+tolerance); 00173 00174 if (lowerBound==upperBound) return positions.size(); // None found 00175 00176 // Pick the closest in range 00177 unsigned lowerSegment = lowerBound - positions.begin(); 00178 unsigned upperSegment = upperBound - positions.begin(); 00179 double lastDifference = std::fabs(timePosition-positions[lowerSegment]); 00180 for (unsigned i=lowerSegment; i<upperSegment; i++) 00181 { 00182 double newDifference = std::fabs(timePosition-positions[i]); 00183 if (newDifference>lastDifference) break; 00184 lastDifference = newDifference; 00185 lowerSegment = i; 00186 } 00187 return lowerSegment; 00188 } 00189 }; 00190 00191 } 00192 00193 00194 00195 #endif//UnsizedSegmentation_hxx 00196