comparison layer/TimeInstantLayer.cpp @ 28:202d1dca67d2

* Rationalise the local feature identification API in Layer subclasses * Add segmentation mode to TimeInstantLayer
author Chris Cannam
date Mon, 06 Feb 2006 17:24:52 +0000
parents dcdb21b62dbb
children 78515b1e29eb
comparison
equal deleted inserted replaced
27:38fe0ea9e46e 28:202d1dca67d2
25 Layer(w), 25 Layer(w),
26 m_model(0), 26 m_model(0),
27 m_editing(false), 27 m_editing(false),
28 m_editingPoint(0, tr("New Point")), 28 m_editingPoint(0, tr("New Point")),
29 m_editingCommand(0), 29 m_editingCommand(0),
30 m_colour(QColor(200, 50, 255)) 30 m_colour(QColor(200, 50, 255)),
31 m_plotStyle(PlotInstants)
31 { 32 {
32 m_view->addLayer(this); 33 m_view->addLayer(this);
33 } 34 }
34 35
35 void 36 void
53 Layer::PropertyList 54 Layer::PropertyList
54 TimeInstantLayer::getProperties() const 55 TimeInstantLayer::getProperties() const
55 { 56 {
56 PropertyList list; 57 PropertyList list;
57 list.push_back(tr("Colour")); 58 list.push_back(tr("Colour"));
59 list.push_back(tr("Plot Type"));
58 return list; 60 return list;
59 } 61 }
60 62
61 Layer::PropertyType 63 Layer::PropertyType
62 TimeInstantLayer::getPropertyType(const PropertyName &) const 64 TimeInstantLayer::getPropertyType(const PropertyName &) const
79 else if (m_colour == Qt::darkRed) deft = 1; 81 else if (m_colour == Qt::darkRed) deft = 1;
80 else if (m_colour == Qt::darkBlue) deft = 2; 82 else if (m_colour == Qt::darkBlue) deft = 2;
81 else if (m_colour == Qt::darkGreen) deft = 3; 83 else if (m_colour == Qt::darkGreen) deft = 3;
82 else if (m_colour == QColor(200, 50, 255)) deft = 4; 84 else if (m_colour == QColor(200, 50, 255)) deft = 4;
83 else if (m_colour == QColor(255, 150, 50)) deft = 5; 85 else if (m_colour == QColor(255, 150, 50)) deft = 5;
86
87 } else if (name == tr("Plot Type")) {
88
89 if (min) *min = 0;
90 if (max) *max = 1;
91
92 deft = int(m_plotStyle);
84 93
85 } else { 94 } else {
86 95
87 deft = Layer::getPropertyRangeAndValue(name, min, max); 96 deft = Layer::getPropertyRangeAndValue(name, min, max);
88 } 97 }
102 case 2: return tr("Blue"); 111 case 2: return tr("Blue");
103 case 3: return tr("Green"); 112 case 3: return tr("Green");
104 case 4: return tr("Purple"); 113 case 4: return tr("Purple");
105 case 5: return tr("Orange"); 114 case 5: return tr("Orange");
106 } 115 }
116 } else if (name == tr("Plot Type")) {
117 switch (value) {
118 default:
119 case 0: return tr("Instants");
120 case 1: return tr("Segmentation");
121 }
107 } 122 }
108 return tr("<unknown>"); 123 return tr("<unknown>");
109 } 124 }
110 125
111 void 126 void
119 case 2: setBaseColour(Qt::darkBlue); break; 134 case 2: setBaseColour(Qt::darkBlue); break;
120 case 3: setBaseColour(Qt::darkGreen); break; 135 case 3: setBaseColour(Qt::darkGreen); break;
121 case 4: setBaseColour(QColor(200, 50, 255)); break; 136 case 4: setBaseColour(QColor(200, 50, 255)); break;
122 case 5: setBaseColour(QColor(255, 150, 50)); break; 137 case 5: setBaseColour(QColor(255, 150, 50)); break;
123 } 138 }
139 } else if (name == tr("Plot Type")) {
140 setPlotStyle(PlotStyle(value));
124 } 141 }
125 } 142 }
126 143
127 void 144 void
128 TimeInstantLayer::setBaseColour(QColor colour) 145 TimeInstantLayer::setBaseColour(QColor colour)
130 if (m_colour == colour) return; 147 if (m_colour == colour) return;
131 m_colour = colour; 148 m_colour = colour;
132 emit layerParametersChanged(); 149 emit layerParametersChanged();
133 } 150 }
134 151
152 void
153 TimeInstantLayer::setPlotStyle(PlotStyle style)
154 {
155 if (m_plotStyle == style) return;
156 m_plotStyle = style;
157 emit layerParametersChanged();
158 }
159
135 bool 160 bool
136 TimeInstantLayer::isLayerScrollable() const 161 TimeInstantLayer::isLayerScrollable() const
137 { 162 {
138 QPoint discard; 163 QPoint discard;
139 return !m_view->shouldIlluminateLocalFeatures(this, discard); 164 return !m_view->shouldIlluminateLocalFeatures(this, discard);
140 } 165 }
141 166
142 SparseOneDimensionalModel::PointList 167 SparseOneDimensionalModel::PointList
143 TimeInstantLayer::getLocalPoints(int x) const 168 TimeInstantLayer::getLocalPoints(int x) const
144 { 169 {
170 // Return a set of points that all have the same frame number, the
171 // nearest to the given x coordinate, and that are within a
172 // certain fuzz distance of that x coordinate.
173
145 if (!m_model) return SparseOneDimensionalModel::PointList(); 174 if (!m_model) return SparseOneDimensionalModel::PointList();
146 175
147 long frame = getFrameForX(x); 176 long frame = getFrameForX(x);
148 177
149 SparseOneDimensionalModel::PointList onPoints = 178 SparseOneDimensionalModel::PointList onPoints =
168 } else if (nextPoints.begin()->frame - frame < 197 } else if (nextPoints.begin()->frame - frame <
169 frame - prevPoints.begin()->frame) { 198 frame - prevPoints.begin()->frame) {
170 usePoints = nextPoints; 199 usePoints = nextPoints;
171 } 200 }
172 201
202 if (!usePoints.empty()) {
203 int fuzz = 2;
204 int px = getXForFrame(usePoints.begin()->frame);
205 if ((px > x && px - x > fuzz) ||
206 (px < x && x - px > fuzz + 1)) {
207 usePoints.clear();
208 }
209 }
210
173 return usePoints; 211 return usePoints;
174 } 212 }
175 213
176 QString 214 QString
177 TimeInstantLayer::getFeatureDescription(QPoint &pos) const 215 TimeInstantLayer::getFeatureDescription(QPoint &pos) const
207 245
208 pos = QPoint(getXForFrame(useFrame), pos.y()); 246 pos = QPoint(getXForFrame(useFrame), pos.y());
209 return text; 247 return text;
210 } 248 }
211 249
212 int 250 bool
213 TimeInstantLayer::getNearestFeatureFrame(int frame, 251 TimeInstantLayer::snapToFeatureFrame(int &frame,
214 size_t &resolution, 252 size_t &resolution,
215 bool snapRight) const 253 SnapType snap) const
216 { 254 {
217 if (!m_model) { 255 if (!m_model) {
218 return Layer::getNearestFeatureFrame(frame, resolution, snapRight); 256 return Layer::snapToFeatureFrame(frame, resolution, snap);
219 } 257 }
220 258
221 resolution = m_model->getResolution(); 259 resolution = m_model->getResolution();
222 SparseOneDimensionalModel::PointList points(m_model->getPoints(frame, frame)); 260 SparseOneDimensionalModel::PointList points;
223 261
224 int returnFrame = frame; 262 if (snap == SnapNeighbouring) {
263
264 points = getLocalPoints(getXForFrame(frame));
265 if (points.empty()) return false;
266 frame = points.begin()->frame;
267 return true;
268 }
269
270 points = m_model->getPoints(frame, frame);
271 int snapped = frame;
272 bool found = false;
225 273
226 for (SparseOneDimensionalModel::PointList::const_iterator i = points.begin(); 274 for (SparseOneDimensionalModel::PointList::const_iterator i = points.begin();
227 i != points.end(); ++i) { 275 i != points.end(); ++i) {
228 276
229 if (snapRight) { 277 if (snap == SnapRight) {
230 if (i->frame > frame) { 278
231 returnFrame = i->frame; 279 if (i->frame >= frame) {
280 snapped = i->frame;
281 found = true;
232 break; 282 break;
233 } 283 }
234 } else { 284
285 } else if (snap == SnapLeft) {
286
235 if (i->frame <= frame) { 287 if (i->frame <= frame) {
236 returnFrame = i->frame; 288 snapped = i->frame;
237 } 289 found = true; // don't break, as the next may be better
238 } 290 } else {
239 } 291 break;
240 292 }
241 return returnFrame; 293
294 } else { // nearest
295
296 SparseOneDimensionalModel::PointList::const_iterator j = i;
297 ++j;
298
299 if (j == points.end()) {
300
301 snapped = i->frame;
302 found = true;
303 break;
304
305 } else if (j->frame >= frame) {
306
307 if (j->frame - frame < frame - i->frame) {
308 snapped = j->frame;
309 } else {
310 snapped = i->frame;
311 }
312 found = true;
313 break;
314 }
315 }
316 }
317
318 frame = snapped;
319 return found;
242 } 320 }
243 321
244 void 322 void
245 TimeInstantLayer::paint(QPainter &paint, QRect rect) const 323 TimeInstantLayer::paint(QPainter &paint, QRect rect) const
246 { 324 {
253 long frame0 = getFrameForX(x0); 331 long frame0 = getFrameForX(x0);
254 long frame1 = getFrameForX(x1); 332 long frame1 = getFrameForX(x1);
255 333
256 SparseOneDimensionalModel::PointList points(m_model->getPoints 334 SparseOneDimensionalModel::PointList points(m_model->getPoints
257 (frame0, frame1)); 335 (frame0, frame1));
336
337 bool odd = false;
338 if (m_plotStyle == PlotSegmentation && !points.empty()) {
339 int index = m_model->getIndexOf(*points.begin());
340 odd = ((index % 2) == 1);
341 }
258 342
259 paint.setPen(m_colour); 343 paint.setPen(m_colour);
260 344
261 QColor brushColour(m_colour); 345 QColor brushColour(m_colour);
262 brushColour.setAlpha(100); 346 brushColour.setAlpha(100);
263 paint.setBrush(brushColour); 347 paint.setBrush(brushColour);
348
349 QColor oddBrushColour(brushColour);
350 if (m_plotStyle == PlotSegmentation) {
351 if (m_colour == Qt::black) {
352 oddBrushColour = Qt::gray;
353 } else if (m_colour == Qt::darkRed) {
354 oddBrushColour = Qt::red;
355 } else if (m_colour == Qt::darkBlue) {
356 oddBrushColour = Qt::blue;
357 } else if (m_colour == Qt::darkGreen) {
358 oddBrushColour = Qt::green;
359 } else {
360 oddBrushColour = oddBrushColour.light(150);
361 }
362 oddBrushColour.setAlpha(100);
363 }
264 364
265 // std::cerr << "TimeInstantLayer::paint: resolution is " 365 // std::cerr << "TimeInstantLayer::paint: resolution is "
266 // << m_model->getResolution() << " frames" << std::endl; 366 // << m_model->getResolution() << " frames" << std::endl;
267 367
268 QPoint localPos; 368 QPoint localPos;
303 paint.setPen(Qt::black); //!!! 403 paint.setPen(Qt::black); //!!!
304 } else { 404 } else {
305 paint.setPen(brushColour); 405 paint.setPen(brushColour);
306 } 406 }
307 407
308 if (iw > 1) { 408 if (m_plotStyle == PlotInstants) {
309 paint.drawRect(x, 0, iw - 1, m_view->height() - 1); 409 if (iw > 1) {
410 paint.drawRect(x, 0, iw - 1, m_view->height() - 1);
411 } else {
412 paint.drawLine(x, 0, x, m_view->height() - 1);
413 }
310 } else { 414 } else {
311 paint.drawLine(x, 0, x, m_view->height() - 1); 415
312 } 416 if (odd) paint.setBrush(oddBrushColour);
417 else paint.setBrush(brushColour);
418
419 int nx;
420
421 if (j != points.end()) {
422 const SparseOneDimensionalModel::Point &q(*j);
423 nx = getXForFrame(q.frame);
424 } else {
425 nx = getXForFrame(m_model->getEndFrame());
426 }
427
428 if (nx >= x) {
429
430 if (illuminateFrame != p.frame &&
431 (nx < x + 5 || x >= m_view->width() - 1)) {
432 paint.setPen(Qt::NoPen);
433 }
434
435 paint.drawRect(x, -1, nx - x, m_view->height() + 1);
436 }
437
438 odd = !odd;
439 }
440
313 paint.setPen(m_colour); 441 paint.setPen(m_colour);
314 442
315 if (p.label != "") { 443 if (p.label != "") {
316 444
317 // only draw if there's enough room from here to the next point 445 // only draw if there's enough room from here to the next point
446 574
447 QString 575 QString
448 TimeInstantLayer::toXmlString(QString indent, QString extraAttributes) const 576 TimeInstantLayer::toXmlString(QString indent, QString extraAttributes) const
449 { 577 {
450 return Layer::toXmlString(indent, extraAttributes + 578 return Layer::toXmlString(indent, extraAttributes +
451 QString(" colour=\"%1\"").arg(encodeColour(m_colour))); 579 QString(" colour=\"%1\" plotStyle=\"%2\"")
580 .arg(encodeColour(m_colour)).arg(m_plotStyle));
452 } 581 }
453 582
454 void 583 void
455 TimeInstantLayer::setProperties(const QXmlAttributes &attributes) 584 TimeInstantLayer::setProperties(const QXmlAttributes &attributes)
456 { 585 {
459 QColor colour(colourSpec); 588 QColor colour(colourSpec);
460 if (colour.isValid()) { 589 if (colour.isValid()) {
461 setBaseColour(QColor(colourSpec)); 590 setBaseColour(QColor(colourSpec));
462 } 591 }
463 } 592 }
593
594 bool ok;
595 PlotStyle style = (PlotStyle)
596 attributes.value("plotStyle").toInt(&ok);
597 if (ok) setPlotStyle(style);
464 } 598 }
465 599
466 #ifdef INCLUDE_MOCFILES 600 #ifdef INCLUDE_MOCFILES
467 #include "TimeInstantLayer.moc.cpp" 601 #include "TimeInstantLayer.moc.cpp"
468 #endif 602 #endif