SciDAVis  1.D4
IntervalAttribute.h
Go to the documentation of this file.
1 /***************************************************************************
2  File : IntervalAttribute.h
3  Project : SciDAVis
4  --------------------------------------------------------------------
5  Copyright : (C) 2007 by Knut Franke, Tilman Benkert
6  Email (use @ for *) : knut.franke*gmx.de, thzs*gmx.net
7  Description : A class representing an interval-based attribute
8 
9  ***************************************************************************/
10 
11 /***************************************************************************
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * *
18  * This program is distributed in the hope that it will be useful, *
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
21  * GNU General Public License for more details. *
22  * *
23  * You should have received a copy of the GNU General Public License *
24  * along with d_intervals program; if not, write to the Free Software *
25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
26  * Boston, MA 02110-1301 USA *
27  * *
28  ***************************************************************************/
29 
30 #ifndef INTERVALATTRIBUTE_H
31 #define INTERVALATTRIBUTE_H
32 
33 #include "Interval.h"
34 #include <QList>
35 
37 template<class T> class IntervalAttribute
38 {
39  public:
41  {
42  // first: subtract the new interval from all others
43  QList< Interval<int> > temp_list;
44  for(int c=0; c<d_intervals.size(); c++)
45  {
46  temp_list = Interval<int>::subtract(d_intervals.at(c), i);
47  if(temp_list.isEmpty())
48  {
49  d_intervals.removeAt(c);
50  d_values.removeAt(c--);
51  }
52  else
53  {
54  d_intervals.replace(c, temp_list.at(0));
55  if(temp_list.size()>1)
56  {
57  d_intervals.insert(c, temp_list.at(1));
58  d_values.insert(c, d_values.at(c));
59  }
60  }
61  }
62 
63  // second: try to merge the new interval with an old one
64  for(int c=0; c<d_intervals.size(); c++)
65  {
66  if( d_intervals.at(c).touches(i) &&
67  d_values.at(c) == value )
68  {
69  d_intervals.replace(c, Interval<int>::merge(d_intervals.at(c), i));
70  return;
71  }
72  }
73  // if it could not be merged, just append it
74  d_intervals.append(i);
75  d_values.append(value);
76  }
77 
78  // overloaded for convenience
79  void setValue(int row, T value)
80  {
81  setValue(Interval<int>(row, row), value);
82  }
83 
84  T value(int row) const
85  {
86  for(int c=d_intervals.size()-1; c>=0; c--)
87  {
88  if(d_intervals.at(c).contains(row))
89  return d_values.at(c);
90  }
91  return T();
92  }
93 
94  void insertRows(int before, int count)
95  {
96  QList< Interval<int> > temp_list;
97  // first: split all intervals that contain 'before'
98  for(int c=0; c<d_intervals.size(); c++)
99  {
100  if(d_intervals.at(c).contains(before))
101  {
102  temp_list = Interval<int>::split(d_intervals.at(c), before);
103  d_intervals.replace(c, temp_list.at(0));
104  if(temp_list.size()>1)
105  {
106  d_intervals.insert(c, temp_list.at(1));
107  d_values.insert(c, d_values.at(c));
108  c++;
109  }
110 
111  }
112  }
113  // second: translate all intervals that start at 'before' or later
114  for(int c=0; c<d_intervals.size(); c++)
115  {
116  if(d_intervals.at(c).start() >= before)
117  d_intervals[c].translate(count);
118  }
119 
120  }
121 
122  void removeRows(int first, int count)
123  {
124  QList< Interval<int> > temp_list;
125  Interval<int> i(first, first+count-1);
126  // first: remove the relevant rows from all intervals
127  for(int c=0; c<d_intervals.size(); c++)
128  {
129  temp_list = Interval<int>::subtract(d_intervals.at(c), i);
130  if(temp_list.isEmpty())
131  {
132  d_intervals.removeAt(c);
133  d_values.removeAt(c--);
134  }
135  else
136  {
137  d_intervals.replace(c, temp_list.at(0));
138  if(temp_list.size()>1)
139  {
140  d_intervals.insert(c, temp_list.at(1));
141  d_values.insert(c, d_values.at(c));
142  c++;
143  }
144  }
145  }
146  // second: translate all intervals that start at 'first+count' or later
147  for(int c=0; c<d_intervals.size(); c++)
148  {
149  if(d_intervals.at(c).start() >= first+count)
150  d_intervals[c].translate(-count);
151  }
152  // third: merge as many intervals as possible
153  QList<T> values_copy = d_values;
154  QList< Interval<int> > intervals_copy = d_intervals;
155  d_values.clear();
156  d_intervals.clear();
157  for(int c=0; c<intervals_copy.size(); c++)
158  {
159  i = intervals_copy.at(c);
160  T value = values_copy.at(c);
161  for(int cc=0; cc<d_intervals.size(); cc++)
162  {
163  if( d_intervals.at(cc).touches(i) &&
164  d_values.at(cc) == value )
165  {
166  d_intervals.replace(cc, Interval<int>::merge(d_intervals.at(cc),i));
167  return;
168  }
169  }
170  // if it could not be merged, just append it
171  d_intervals.append(i);
172  d_values.append(value);
173  }
174  }
175 
176  void clear() { d_values.clear(); d_intervals.clear(); }
177 
178  QList< Interval<int> > intervals() const { return d_intervals; }
179  QList<T> values() const { return d_values; }
181  {
182  d_intervals.clear();
183  d_values.clear();
184  foreach( Interval<int> iv, other.intervals())
185  d_intervals.append(iv);
186  foreach( T value, other.values())
187  d_values.append(value);
188  return *this;
189  }
190 
191  private:
192  QList<T> d_values;
193  QList< Interval<int> > d_intervals;
194 };
195 
197 template<> class IntervalAttribute<bool>
198 {
199  public:
203  {
204  d_intervals.clear();
205  foreach( Interval<int> iv, other.intervals())
206  d_intervals.append(iv);
207  return *this;
208  }
209 
210  void setValue(Interval<int> i, bool value=true)
211  {
212  if(value)
213  {
214  foreach(Interval<int> iv, d_intervals)
215  if(iv.contains(i))
216  return;
217 
219  } else { // unset
221  }
222  }
223 
224  void setValue(int row, bool value)
225  {
226  setValue(Interval<int>(row, row), value);
227  }
228 
229  bool isSet(int row) const
230  {
231  foreach(Interval<int> iv, d_intervals)
232  if(iv.contains(row))
233  return true;
234  return false;
235  }
236 
237  bool isSet(Interval<int> i) const
238  {
239  foreach(Interval<int> iv, d_intervals)
240  if(iv.contains(i))
241  return true;
242  return false;
243  }
244 
245  void insertRows(int before, int count)
246  {
247  QList< Interval<int> > temp_list;
248  int c;
249  // first: split all intervals that contain 'before'
250  for(c=0; c<d_intervals.size(); c++)
251  {
252  if(d_intervals.at(c).contains(before))
253  {
254  temp_list = Interval<int>::split(d_intervals.at(c), before);
255  d_intervals.replace(c, temp_list.at(0));
256  if(temp_list.size()>1)
257  d_intervals.insert(c++, temp_list.at(1));
258 
259  }
260  }
261  // second: translate all intervals that start at 'before' or later
262  for(c=0; c<d_intervals.size(); c++)
263  {
264  if(d_intervals.at(c).start() >= before)
265  d_intervals[c].translate(count);
266  }
267 
268  }
269 
270  void removeRows(int first, int count)
271  {
272  int c;
273  // first: remove the relevant rows from all intervals
275  // second: translate all intervals that start at 'first+count' or later
276  for(c=0; c<d_intervals.size(); c++)
277  {
278  if(d_intervals.at(c).start() >= first+count)
279  d_intervals[c].translate(-count);
280  }
281  // third: merge as many intervals as possible
282  for(c=d_intervals.size()-1; c>=0; c--)
283  {
284  Interval<int> iv = d_intervals.takeAt(c);
285  int size_before = d_intervals.size();
287  if(size_before == d_intervals.size()) // merge successful
288  c--;
289  }
290  }
291 
292  QList< Interval<int> > intervals() const { return d_intervals; }
293 
294  void clear() { d_intervals.clear(); }
295 
296  private:
297  QList< Interval<int> > d_intervals;
298 };
299 
300 #endif