UnsizedSegmentation.hxx

Go to the documentation of this file.
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 
Generated by  doxygen 1.6.3