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
00058
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
00129 if (segment==0) return;
00130
00131 dragOffset(segment-1, newTimePosition);
00132 }
00138 void dragOffset(unsigned segment, double newTimePosition)
00139 {
00140 if (segment==_offsets.size()) return;
00141 if (segment==_offsets.size()-1) return;
00142
00143
00144 if (newTimePosition<_onsets[segment])
00145 newTimePosition = _onsets[segment];
00146
00147 if (newTimePosition>_offsets[segment+1])
00148 newTimePosition = _offsets[segment+1];
00149
00150
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();
00183
00184
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