DiscontinuousSegmentation.hxx
Go to the documentation of this file.00001 #ifndef DiscontinuousSegmentation_hxx
00002 #define DiscontinuousSegmentation_hxx
00003
00004 #include "Segmentation.hxx"
00005
00006 namespace CLAM
00007 {
00008 class DiscontinuousSegmentation : 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 class OffsetMissing : public std::exception
00017 {
00018 public:
00019 const char * what() const throw () { return "Odd number of segmentation points, every segment beggining must be followed by its ending";}
00020 };
00021 class MissplacedOnset : public std::exception
00022 {
00023 std::string _message;
00024 public:
00025 MissplacedOnset(unsigned missplacedOnset,
00026 double previousOffsetPosition,
00027 double intendedOnsetPosition)
00028 {
00029 std::ostringstream os;
00030 os << "Segment " << missplacedOnset
00031 << " starts at " << intendedOnsetPosition
00032 << " overlapping previous segment which ends at " << previousOffsetPosition;
00033 _message = os.str();
00034 }
00035 virtual ~MissplacedOnset() throw () {}
00036 const char * what() const throw () { return _message.c_str(); }
00037 };
00038 class MissplacedOffset : public std::exception
00039 {
00040 std::string _message;
00041 public:
00042 MissplacedOffset(unsigned missplacedOffset,
00043 double onsetPosition,
00044 double offsetPosition)
00045 {
00046 std::ostringstream os;
00047 os << "Segment " << missplacedOffset
00048 << " starts at " << onsetPosition
00049 << " but ends before that, at " << offsetPosition;
00050 _message = os.str();
00051 }
00052 virtual ~MissplacedOffset() throw () {}
00053 const char * what() const throw () { return _message.c_str(); }
00054 };
00055 typedef std::vector<double> TimePositions;
00056 public:
00057 DiscontinuousSegmentation(double maxPosition=0)
00058 : Segmentation(maxPosition)
00059 {
00060 }
00067 DiscontinuousSegmentation(double maxPosition, const TData * begin, const TData * end)
00068 : Segmentation(maxPosition)
00069 {
00070 takeArray(begin, end);
00071 }
00075 void takeArray(const TData * begin, const TData * end)
00076 {
00077 double previousOffset=0.0;
00078 unsigned i=0;
00079 for (const TData* it=begin; it!=end; i++)
00080 {
00081 double onset = *it++;
00082 std::cout << onset << " " << std::flush;
00083 if (onset<previousOffset) throw MissplacedOnset(i,previousOffset,onset);
00084 if (it==end) throw OffsetMissing();
00085 double offset = *it++;
00086 std::cout << offset << " " << std::flush;
00087 if (offset<onset) throw MissplacedOffset(i, onset, offset);
00088 if (offset>_maxPosition) throw InsertedOutOfBounds();
00089 _onsets.push_back(onset);
00090 _offsets.push_back(offset);
00091 _labels.push_back("");
00092 _selection.push_back(false);
00093 previousOffset=offset;
00094 }
00095 }
00099 unsigned insert(double timePosition)
00100 {
00101 if (timePosition<0.0) throw InsertedOutOfBounds();
00102 if (timePosition>_maxPosition) throw InsertedOutOfBounds();
00103 TimePositions::iterator nextOffset =
00104 std::lower_bound(_offsets.begin(), _offsets.end(), timePosition);
00105 if (nextOffset == _offsets.end())
00106 {
00107 _onsets.push_back(timePosition);
00108 _offsets.push_back(_maxPosition);
00109 _labels.push_back("");
00110 _selection.push_back(false);
00111 return _onsets.size()-1;
00112 }
00113
00114 unsigned nextOffsetPosition = nextOffset - _offsets.begin();
00115 if (_onsets[nextOffsetPosition]<=timePosition)
00116 {
00117 _offsets.insert(nextOffset, timePosition);
00118 _onsets.insert(_onsets.begin()+nextOffsetPosition+1, timePosition);
00119 _labels.insert(_labels.begin()+nextOffsetPosition+1, "");
00120 _selection.insert(_selection.begin()+nextOffsetPosition+1, false);
00121 if (nextOffsetPosition<_current) _current++;
00122 return nextOffsetPosition+1;
00123 }
00124 else
00125 {
00126 _offsets.insert(nextOffset, _onsets[nextOffsetPosition]);
00127 _onsets.insert(_onsets.begin()+nextOffsetPosition, timePosition);
00128 _labels.insert(_labels.begin()+nextOffsetPosition, "");
00129 _selection.insert(_selection.begin()+nextOffsetPosition, false);
00130 if (_current>=nextOffsetPosition) _current++;
00131 return nextOffsetPosition;
00132 }
00133
00134 }
00138 unsigned insert(double timePosition, std::string label)
00139 {
00140 unsigned segment = insert(timePosition);
00141 setLabel(segment, label);
00142 return segment;
00143 }
00150 void remove(unsigned segment)
00151 {
00152 _offsets.erase(_offsets.begin()+segment);
00153 _onsets.erase(_onsets.begin()+segment);
00154 _labels.erase(_labels.begin()+segment);
00155 _selection.erase(_selection.begin()+segment);
00156 if (_current!=0 && segment<=_current) _current--;
00157 }
00164 unsigned pickOffset(double timePosition, double tolerance) const
00165 {
00166 return pickPosition(_offsets, timePosition, tolerance);
00167 }
00174 unsigned pickOnset(double timePosition, double tolerance) const
00175 {
00176 return pickPosition(_onsets, timePosition, tolerance);
00177 }
00181 unsigned pickSegmentBody(double timePosition) const
00182 {
00183 if (timePosition<0) return _offsets.size();
00184 TimePositions::const_iterator lowerBound =
00185 std::lower_bound(_offsets.begin(), _offsets.end(), timePosition);
00186 unsigned index = lowerBound-_offsets.begin();
00187 if (index==_offsets.size()) return index;
00188 if (_onsets[index]>timePosition) return _offsets.size();
00189 return index;
00190 }
00196 void dragOnset(unsigned segment, double newTimePosition)
00197 {
00198
00199 if (segment>=_onsets.size()) return;
00200
00201
00202 double leftBound = segment ? _offsets[segment-1] : 0;
00203 if (newTimePosition<leftBound)
00204 newTimePosition=leftBound;
00205
00206 double rigthBound = _offsets[segment];
00207 if (newTimePosition>rigthBound)
00208 newTimePosition=rigthBound;
00209
00210
00211 _onsets[segment]=newTimePosition;
00212 }
00218 void dragOffset(unsigned segment, double newTimePosition)
00219 {
00220 if (segment>=_offsets.size()) return;
00221
00222
00223 double rigthBound = segment+1==_offsets.size()? _maxPosition : _onsets[segment+1];
00224 if (newTimePosition>rigthBound)
00225 newTimePosition=rigthBound;
00226
00227 double leftBound = _onsets[segment];
00228 if (newTimePosition<leftBound)
00229 newTimePosition=leftBound;
00230
00231
00232 _offsets[segment]=newTimePosition;
00233 }
00237 void fillArray(DataArray& segmentation) const
00238 {
00239 unsigned nSegments = _onsets.size();
00240 segmentation.Resize(nSegments*2);
00241 segmentation.SetSize(nSegments*2);
00242 for (unsigned i=0; i<nSegments; i++)
00243 {
00244 segmentation[i*2] = _onsets[i];
00245 segmentation[i*2+1] = _offsets[i];
00246 }
00247 }
00248
00249 const char * GetClassName() const { return "DiscontinuousSegmentation"; }
00250
00251
00252 private:
00260 unsigned pickPosition(const TimePositions & positions, double timePosition, double tolerance) const
00261 {
00262 TimePositions::const_iterator lowerBound =
00263 std::lower_bound(positions.begin(), positions.end(), timePosition-tolerance);
00264 TimePositions::const_iterator upperBound =
00265 std::upper_bound(lowerBound, positions.end(), timePosition+tolerance);
00266
00267 if (lowerBound==upperBound) return positions.size();
00268
00269
00270 unsigned lowerSegment = lowerBound - positions.begin();
00271 unsigned upperSegment = upperBound - positions.begin();
00272 double lastDifference = std::fabs(timePosition-positions[lowerSegment]);
00273 for (unsigned i=lowerSegment; i<upperSegment; i++)
00274 {
00275 double newDifference = std::fabs(timePosition-positions[i]);
00276 if (newDifference>lastDifference) break;
00277 lastDifference = newDifference;
00278 lowerSegment = i;
00279 }
00280 return lowerSegment;
00281 }
00282 };
00283
00284 }
00285
00286
00287
00288 #endif//DiscontinuousSegmentation_hxx
00289