Mercurial > hg > svgui
comparison layer/TimeValueLayer.cpp @ 437:755243c67f59
* Add vertical zoom and pan to time-value layer.
Still some defects, particularly in logarithmic mode.
Now need to get this in note layer as well!
* Some fixes to log colouring in segmentation mode of time-value layer.
author | Chris Cannam |
---|---|
date | Fri, 24 Oct 2008 14:52:40 +0000 |
parents | 6324461340b1 |
children | 76cd1c89eb06 |
comparison
equal
deleted
inserted
replaced
436:1e0744b2cebe | 437:755243c67f59 |
---|---|
17 | 17 |
18 #include "data/model/Model.h" | 18 #include "data/model/Model.h" |
19 #include "base/RealTime.h" | 19 #include "base/RealTime.h" |
20 #include "base/Profiler.h" | 20 #include "base/Profiler.h" |
21 #include "base/LogRange.h" | 21 #include "base/LogRange.h" |
22 #include "base/RangeMapper.h" | |
22 #include "ColourDatabase.h" | 23 #include "ColourDatabase.h" |
23 #include "view/View.h" | 24 #include "view/View.h" |
24 | 25 |
25 #include "data/model/SparseTimeValueModel.h" | 26 #include "data/model/SparseTimeValueModel.h" |
26 #include "data/model/Labeller.h" | 27 #include "data/model/Labeller.h" |
49 m_originalPoint(0, 0.0, tr("New Point")), | 50 m_originalPoint(0, 0.0, tr("New Point")), |
50 m_editingPoint(0, 0.0, tr("New Point")), | 51 m_editingPoint(0, 0.0, tr("New Point")), |
51 m_editingCommand(0), | 52 m_editingCommand(0), |
52 m_colourMap(0), | 53 m_colourMap(0), |
53 m_plotStyle(PlotConnectedPoints), | 54 m_plotStyle(PlotConnectedPoints), |
54 m_verticalScale(AutoAlignScale) | 55 m_verticalScale(AutoAlignScale), |
56 m_scaleMinimum(0), | |
57 m_scaleMaximum(0) | |
55 { | 58 { |
56 | 59 |
57 } | 60 } |
58 | 61 |
59 void | 62 void |
258 bool | 261 bool |
259 TimeValueLayer::getDisplayExtents(float &min, float &max) const | 262 TimeValueLayer::getDisplayExtents(float &min, float &max) const |
260 { | 263 { |
261 if (!m_model || shouldAutoAlign()) return false; | 264 if (!m_model || shouldAutoAlign()) return false; |
262 | 265 |
263 min = m_model->getValueMinimum(); | 266 if (m_scaleMinimum == m_scaleMaximum) { |
264 max = m_model->getValueMaximum(); | 267 m_scaleMinimum = m_model->getValueMinimum(); |
268 m_scaleMaximum = m_model->getValueMaximum(); | |
269 } | |
270 | |
271 min = m_scaleMinimum; | |
272 max = m_scaleMaximum; | |
273 | |
274 // std::cerr << "TimeValueLayer::getDisplayExtents: min = " << min << ", max = " << max << std::endl; | |
275 | |
265 return true; | 276 return true; |
277 } | |
278 | |
279 bool | |
280 TimeValueLayer::setDisplayExtents(float min, float max) | |
281 { | |
282 if (!m_model) return false; | |
283 | |
284 if (min == max) { | |
285 if (min == 0.f) { | |
286 max = 1.f; | |
287 } else { | |
288 max = min * 1.0001; | |
289 } | |
290 } | |
291 | |
292 m_scaleMinimum = min; | |
293 m_scaleMaximum = max; | |
294 | |
295 std::cerr << "TimeValueLayer::setDisplayExtents: min = " << min << ", max = " << max << std::endl; | |
296 | |
297 emit layerParametersChanged(); | |
298 return true; | |
299 } | |
300 | |
301 int | |
302 TimeValueLayer::getVerticalZoomSteps(int &defaultStep) const | |
303 { | |
304 if (shouldAutoAlign()) return 0; | |
305 if (!m_model) return 0; | |
306 | |
307 defaultStep = 100; | |
308 return 100; | |
309 } | |
310 | |
311 int | |
312 TimeValueLayer::getCurrentVerticalZoomStep() const | |
313 { | |
314 if (shouldAutoAlign()) return 0; | |
315 if (!m_model) return 0; | |
316 | |
317 RangeMapper *mapper = getNewVerticalZoomRangeMapper(); | |
318 if (!mapper) return 0; | |
319 | |
320 float dmin, dmax; | |
321 getDisplayExtents(dmin, dmax); | |
322 | |
323 int nr = mapper->getPositionForValue(dmax - dmin); | |
324 /* | |
325 int n0 = mapper->getPositionForValue(dmax); | |
326 int n1 = mapper->getPositionForValue(dmin); | |
327 int nr = n1 - n0; | |
328 if (nr < 0) nr = -nr; | |
329 | |
330 std::cerr << "TimeValueLayer::getCurrentVerticalZoomStep: dmin = " << dmin << ", dmax = " << dmax << ", n0 = " << n0 << ", n1 = " << n1 << ", nr = " << nr << std::endl; | |
331 */ | |
332 delete mapper; | |
333 | |
334 return 100 - nr; | |
335 } | |
336 | |
337 void | |
338 TimeValueLayer::setVerticalZoomStep(int step) | |
339 { | |
340 if (shouldAutoAlign()) return; | |
341 if (!m_model) return; | |
342 | |
343 RangeMapper *mapper = getNewVerticalZoomRangeMapper(); | |
344 if (!mapper) return; | |
345 | |
346 float min, max; | |
347 bool logarithmic; | |
348 QString unit; | |
349 getValueExtents(min, max, logarithmic, unit); | |
350 | |
351 float dmin, dmax; | |
352 getDisplayExtents(dmin, dmax); | |
353 | |
354 float newdist = mapper->getValueForPosition(100 - step); | |
355 | |
356 float newmin, newmax; | |
357 | |
358 if (logarithmic) { | |
359 | |
360 // see SpectrogramLayer::setVerticalZoomStep | |
361 | |
362 newmax = (newdist + sqrtf(newdist*newdist + 4*dmin*dmax)) / 2; | |
363 newmin = newmax - newdist; | |
364 | |
365 // std::cerr << "newmin = " << newmin << ", newmax = " << newmax << std::endl; | |
366 | |
367 } else { | |
368 float dmid = (dmax + dmin) / 2; | |
369 newmin = dmid - newdist / 2; | |
370 newmax = dmid + newdist / 2; | |
371 } | |
372 | |
373 if (newmin < min) { | |
374 newmax += (min - newmin); | |
375 newmin = min; | |
376 } | |
377 if (newmax > max) { | |
378 newmax = max; | |
379 } | |
380 | |
381 std::cerr << "TimeValueLayer::setVerticalZoomStep: " << step << ": " << newmin << " -> " << newmax << " (range " << newdist << ")" << std::endl; | |
382 | |
383 setDisplayExtents(newmin, newmax); | |
384 } | |
385 | |
386 RangeMapper * | |
387 TimeValueLayer::getNewVerticalZoomRangeMapper() const | |
388 { | |
389 if (!m_model) return 0; | |
390 | |
391 RangeMapper *mapper; | |
392 | |
393 float min, max; | |
394 bool logarithmic; | |
395 QString unit; | |
396 getValueExtents(min, max, logarithmic, unit); | |
397 | |
398 if (min == max) return 0; | |
399 | |
400 if (logarithmic) { | |
401 mapper = new LogRangeMapper(0, 100, min, max, unit); | |
402 } else { | |
403 mapper = new LinearRangeMapper(0, 100, min, max, unit); | |
404 } | |
405 | |
406 return mapper; | |
266 } | 407 } |
267 | 408 |
268 SparseTimeValueModel::PointList | 409 SparseTimeValueModel::PointList |
269 TimeValueLayer::getLocalPoints(View *v, int x) const | 410 TimeValueLayer::getLocalPoints(View *v, int x) const |
270 { | 411 { |
444 min = -1.0; | 585 min = -1.0; |
445 max = 1.0; | 586 max = 1.0; |
446 | 587 |
447 } else { | 588 } else { |
448 | 589 |
449 min = m_model->getValueMinimum(); | 590 getDisplayExtents(min, max); |
450 max = m_model->getValueMaximum(); | |
451 | 591 |
452 if (m_verticalScale == LogScale) { | 592 if (m_verticalScale == LogScale) { |
453 LogRange::mapRange(min, max); | 593 LogRange::mapRange(min, max); |
454 log = true; | 594 log = true; |
455 } | 595 } |
487 getScaleExtents(v, min, max, logarithmic); | 627 getScaleExtents(v, min, max, logarithmic); |
488 | 628 |
489 float val = min + (float(h - y) * float(max - min)) / h; | 629 float val = min + (float(h - y) * float(max - min)) / h; |
490 | 630 |
491 if (logarithmic) { | 631 if (logarithmic) { |
492 val = powf(10.f, val); | 632 val = LogRange::map(val); |
493 } | 633 } |
494 | 634 |
495 return val; | 635 return val; |
496 } | 636 } |
497 | 637 |
512 | 652 |
513 if (min > max) std::swap(min, max); | 653 if (min > max) std::swap(min, max); |
514 if (max == min) max = min + 1; | 654 if (max == min) max = min + 1; |
515 | 655 |
516 if (log) { | 656 if (log) { |
517 LogRange::mapRange(min, max); | |
518 val = LogRange::map(val); | 657 val = LogRange::map(val); |
519 } | 658 } |
520 | 659 |
521 // std::cerr << "TimeValueLayer::getColourForValue: min " << min << ", max " | 660 // std::cerr << "TimeValueLayer::getColourForValue: min " << min << ", max " |
522 // << max << ", log " << log << ", value " << val << std::endl; | 661 // << max << ", log " << log << ", value " << val << std::endl; |
779 | 918 |
780 int h = v->height(); | 919 int h = v->height(); |
781 | 920 |
782 int n = 10; | 921 int n = 10; |
783 | 922 |
784 float max = m_model->getValueMaximum(); | 923 float min, max; |
785 float min = m_model->getValueMinimum(); | 924 bool logarithmic; |
925 getScaleExtents(v, min, max, logarithmic); | |
926 | |
927 if (m_plotStyle == PlotSegmentation) { | |
928 QString unit; | |
929 getValueExtents(min, max, logarithmic, unit); | |
930 if (logarithmic) { | |
931 LogRange::mapRange(min, max); | |
932 } | |
933 } | |
934 | |
786 float val = min; | 935 float val = min; |
787 float inc = (max - val) / n; | 936 float inc = (max - val) / n; |
788 | 937 |
789 char buffer[40]; | 938 char buffer[40]; |
790 | 939 |
805 | 954 |
806 if (m_plotStyle == PlotSegmentation) { | 955 if (m_plotStyle == PlotSegmentation) { |
807 paint.save(); | 956 paint.save(); |
808 for (int y = 0; y < boxh; ++y) { | 957 for (int y = 0; y < boxh; ++y) { |
809 float val = ((boxh - y) * (max - min)) / boxh + min; | 958 float val = ((boxh - y) * (max - min)) / boxh + min; |
810 paint.setPen(getColourForValue(v, val)); | 959 if (logarithmic) { |
960 paint.setPen(getColourForValue(v, LogRange::unmap(val))); | |
961 } else { | |
962 paint.setPen(getColourForValue(v, val)); | |
963 } | |
811 paint.drawLine(boxx + 1, y + boxy + 1, boxx + boxw, y + boxy + 1); | 964 paint.drawLine(boxx + 1, y + boxy + 1, boxx + boxw, y + boxy + 1); |
812 } | 965 } |
813 paint.restore(); | 966 paint.restore(); |
814 } | 967 } |
815 | 968 |
834 | 987 |
835 if (m_plotStyle == PlotSegmentation) { | 988 if (m_plotStyle == PlotSegmentation) { |
836 y = boxy + int(boxh - ((val - min) * boxh) / (max - min)); | 989 y = boxy + int(boxh - ((val - min) * boxh) / (max - min)); |
837 ty = y; | 990 ty = y; |
838 } else { | 991 } else { |
839 if (i == n-1) { | 992 if (i == n-1 && |
993 v->height() < paint.fontMetrics().height() * (n*2)) { | |
840 if (m_model->getScaleUnits() != "") drawText = false; | 994 if (m_model->getScaleUnits() != "") drawText = false; |
841 } | 995 } |
842 dispval = lrintf(val / round) * round; | 996 dispval = lrintf(val / round) * round; |
843 // std::cerr << "val = " << val << ", dispval = " << dispval << std::endl; | 997 // std::cerr << "val = " << val << ", dispval = " << dispval << std::endl; |
844 y = getYForValue(v, dispval); | 998 if (logarithmic) { |
999 y = getYForValue(v, LogRange::unmap(dispval)); | |
1000 } else { | |
1001 y = getYForValue(v, dispval); | |
1002 } | |
845 ty = y - paint.fontMetrics().height() + | 1003 ty = y - paint.fontMetrics().height() + |
846 paint.fontMetrics().ascent() + 2; | 1004 paint.fontMetrics().ascent() + 2; |
847 | 1005 |
848 if (prevy >= 0 && (prevy - y) < paint.fontMetrics().height()) { | 1006 if (prevy >= 0 && (prevy - y) < paint.fontMetrics().height()) { |
849 val += inc; | 1007 val += inc; |
850 continue; | 1008 continue; |
851 } | 1009 } |
852 } | 1010 } |
853 | 1011 |
854 sprintf(buffer, "%.*f", dp, dispval); | 1012 if (logarithmic) { |
1013 sprintf(buffer, "%.*g", dp < 2 ? 2 : dp, LogRange::unmap(dispval)); | |
1014 } else { | |
1015 sprintf(buffer, "%.*f", dp, dispval); | |
1016 } | |
855 QString label = QString(buffer); | 1017 QString label = QString(buffer); |
856 | 1018 |
857 if (m_plotStyle != PlotSegmentation) { | 1019 if (m_plotStyle != PlotSegmentation) { |
858 paint.drawLine(w - 5, y, w, y); | 1020 paint.drawLine(w - 5, y, w, y); |
859 } else { | 1021 } else { |