File indexing completed on 2024-05-12 15:27:00

0001 /***************************************************************************
0002     File                 : IntervalAttribute.h
0003     Project              : LabPlot
0004     --------------------------------------------------------------------
0005 
0006     Copyright            : (C) 2007 by Knut Franke (knut.franke@gmx.de)
0007     Copyright            : (C) 2007 by Tilman Benkert (thzs@gmx.net)
0008     Description          : A class representing an interval-based attribute
0009 
0010  ***************************************************************************/
0011 
0012 /***************************************************************************
0013  *                                                                         *
0014  *  This program is free software; you can redistribute it and/or modify   *
0015  *  it under the terms of the GNU General Public License as published by   *
0016  *  the Free Software Foundation; either version 2 of the License, or      *
0017  *  (at your option) any later version.                                    *
0018  *                                                                         *
0019  *  This program is distributed in the hope that it will be useful,        *
0020  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
0021  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
0022  *  GNU General Public License for more details.                           *
0023  *                                                                         *
0024  *   You should have received a copy of the GNU General Public License     *
0025  *   along with m_intervals program; if not, write to the Free Software    *
0026  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
0027  *   Boston, MA  02110-1301  USA                                           *
0028  *                                                                         *
0029  ***************************************************************************/
0030 
0031 #ifndef INTERVALATTRIBUTE_H
0032 #define INTERVALATTRIBUTE_H
0033 
0034 #include "Interval.h"
0035 #include <QVector>
0036 
0037 //! A class representing an interval-based attribute
0038 template<class T> class IntervalAttribute {
0039 public:
0040     void setValue(const Interval<int>& i, T value) {
0041         // first: subtract the new interval from all others
0042         QVector< Interval<int> > temp_list;
0043         for (int c = 0; c < m_intervals.size(); c++) {
0044             temp_list = Interval<int>::subtract(m_intervals.at(c), i);
0045             if (temp_list.isEmpty()) {
0046                 m_intervals.removeAt(c);
0047                 m_values.removeAt(c--);
0048             } else {
0049                 m_intervals.replace(c, temp_list.at(0));
0050                 if (temp_list.size() > 1) {
0051                     m_intervals.insert(c, temp_list.at(1));
0052                     m_values.insert(c, m_values.at(c));
0053                 }
0054             }
0055         }
0056 
0057         // second: try to merge the new interval with an old one
0058         for (int c = 0; c < m_intervals.size(); c++) {
0059             if (m_intervals.at(c).touches(i) && m_values.at(c) == value) {
0060                 m_intervals.replace(c, Interval<int>::merge(m_intervals.at(c), i));
0061                 return;
0062             }
0063         }
0064         // if it could not be merged, just append it
0065         m_intervals.append(i);
0066         m_values.append(value);
0067     }
0068 
0069     // overloaded for convenience
0070     void setValue(int row, T value)
0071     {
0072         setValue(Interval<int>(row, row), value);
0073     }
0074 
0075     T value(int row) const
0076     {
0077         for(int c=m_intervals.size()-1; c>=0; c--)
0078         {
0079             if(m_intervals.at(c).contains(row))
0080                 return m_values.at(c);
0081         }
0082         return T();
0083     }
0084 
0085     void insertRows(int before, int count)
0086     {
0087         QVector< Interval<int> > temp_list;
0088         // first: split all intervals that contain 'before'
0089         for(int c=0; c<m_intervals.size(); c++)
0090         {
0091             if(m_intervals.at(c).contains(before))
0092             {
0093                 temp_list = Interval<int>::split(m_intervals.at(c), before);
0094                 m_intervals.replace(c, temp_list.at(0));
0095                 if(temp_list.size()>1)
0096                 {
0097                     m_intervals.insert(c, temp_list.at(1));
0098                     m_values.insert(c, m_values.at(c));
0099                     c++;
0100                 }
0101 
0102             }
0103         }
0104         // second: translate all intervals that start at 'before' or later
0105         for(int c=0; c<m_intervals.size(); c++)
0106         {
0107             if(m_intervals.at(c).start() >= before)
0108                 m_intervals[c].translate(count);
0109         }
0110 
0111     }
0112 
0113     void removeRows(int first, int count)
0114     {
0115         QVector< Interval<int> > temp_list;
0116         Interval<int> i(first, first+count-1);
0117         // first: remove the relevant rows from all intervals
0118         for(int c=0; c<m_intervals.size(); c++)
0119         {
0120             temp_list = Interval<int>::subtract(m_intervals.at(c), i);
0121             if(temp_list.isEmpty())
0122             {
0123                 m_intervals.removeAt(c);
0124                 m_values.removeAt(c--);
0125             }
0126             else
0127             {
0128                 m_intervals.replace(c, temp_list.at(0));
0129                 if(temp_list.size()>1)
0130                 {
0131                     m_intervals.insert(c, temp_list.at(1));
0132                     m_values.insert(c, m_values.at(c));
0133                     c++;
0134                 }
0135             }
0136         }
0137         // second: translate all intervals that start at 'first+count' or later
0138         for(int c=0; c<m_intervals.size(); c++)
0139         {
0140             if(m_intervals.at(c).start() >= first+count)
0141                 m_intervals[c].translate(-count);
0142         }
0143         // third: merge as many intervals as possible
0144         QVector<T> values_copy = m_values;
0145         QVector< Interval<int> > intervals_copy = m_intervals;
0146         m_values.clear();
0147         m_intervals.clear();
0148         for(int c=0; c<intervals_copy.size(); c++)
0149         {
0150             i = intervals_copy.at(c);
0151             T value = values_copy.at(c);
0152             for(int cc=0; cc<m_intervals.size(); cc++)
0153             {
0154                 if( m_intervals.at(cc).touches(i) &&
0155                         m_values.at(cc) == value )
0156                 {
0157                     m_intervals.replace(cc, Interval<int>::merge(m_intervals.at(cc),i));
0158                     return;
0159                 }
0160             }
0161             // if it could not be merged, just append it
0162             m_intervals.append(i);
0163             m_values.append(value);
0164         }
0165     }
0166 
0167     void clear() { m_values.clear(); m_intervals.clear(); }
0168 
0169     QVector< Interval<int> > intervals() const { return m_intervals; }
0170     QVector<T> values() const { return m_values; }
0171 
0172 private:
0173     QVector<T> m_values;
0174     QVector< Interval<int> > m_intervals;
0175 };
0176 
0177 //! A class representing an interval-based attribute (bool version)
0178 template<> class IntervalAttribute<bool>
0179 {
0180     public:
0181         IntervalAttribute<bool>() {}
0182         IntervalAttribute<bool>(const QVector< Interval<int> >& intervals) : m_intervals(intervals) {}
0183 
0184         void setValue(const Interval<int>& i, bool value=true)
0185         {
0186             if(value)
0187             {
0188                 foreach(const Interval<int>& iv, m_intervals)
0189                     if(iv.contains(i))
0190                         return;
0191 
0192                 Interval<int>::mergeIntervalIntoList(&m_intervals, i);
0193             } else { // unset
0194                 Interval<int>::subtractIntervalFromList(&m_intervals, i);
0195             }
0196         }
0197 
0198         void setValue(int row, bool value)
0199         {
0200             setValue(Interval<int>(row, row), value);
0201         }
0202 
0203         bool isSet(int row) const
0204         {
0205             foreach(Interval<int> iv, m_intervals)
0206                 if(iv.contains(row))
0207                     return true;
0208             return false;
0209         }
0210 
0211         bool isSet(const Interval<int>& i) const
0212         {
0213             foreach(Interval<int> iv, m_intervals)
0214                 if(iv.contains(i))
0215                     return true;
0216             return false;
0217         }
0218 
0219         void insertRows(int before, int count)
0220         {
0221             QVector< Interval<int> > temp_list;
0222             int c;
0223             // first: split all intervals that contain 'before'
0224             for(c=0; c<m_intervals.size(); c++)
0225             {
0226                 if(m_intervals.at(c).contains(before))
0227                 {
0228                     temp_list = Interval<int>::split(m_intervals.at(c), before);
0229                     m_intervals.replace(c, temp_list.at(0));
0230                     if(temp_list.size()>1)
0231                         m_intervals.insert(c++, temp_list.at(1));
0232 
0233                 }
0234             }
0235             // second: translate all intervals that start at 'before' or later
0236             for(c=0; c<m_intervals.size(); c++)
0237             {
0238                 if(m_intervals.at(c).start() >= before)
0239                     m_intervals[c].translate(count);
0240             }
0241 
0242         }
0243 
0244         void removeRows(int first, int count)
0245         {
0246             int c;
0247             // first: remove the relevant rows from all intervals
0248             Interval<int>::subtractIntervalFromList(&m_intervals, Interval<int>(first, first+count-1));
0249             // second: translate all intervals that start at 'first+count' or later
0250             for(c=0; c<m_intervals.size(); c++)
0251             {
0252                 if(m_intervals.at(c).start() >= first+count)
0253                     m_intervals[c].translate(-count);
0254             }
0255             // third: merge as many intervals as possible
0256             for(c=m_intervals.size()-1; c>=0; c--)
0257             {
0258                 Interval<int> iv = m_intervals.takeAt(c);
0259                 int size_before = m_intervals.size();
0260                 Interval<int>::mergeIntervalIntoList(&m_intervals, iv);
0261                 if(size_before == m_intervals.size()) // merge successful
0262                     c--;
0263             }
0264         }
0265 
0266         QVector< Interval<int> > intervals() const { return m_intervals; }
0267 
0268         void clear() { m_intervals.clear(); }
0269 
0270     private:
0271         QVector< Interval<int> > m_intervals;
0272 };
0273 
0274 #endif