comparison layer/RegionLayer.cpp @ 542:5930f2b0b1d2

* some work on improving region editing -- incomplete
author Chris Cannam
date Mon, 03 Aug 2009 16:42:25 +0000
parents ac349afdb23f
children b73f486fc2e4
comparison
equal deleted inserted replaced
541:e233627a923e 542:5930f2b0b1d2
236 RegionLayer::recalcSpacing() 236 RegionLayer::recalcSpacing()
237 { 237 {
238 m_spacingMap.clear(); 238 m_spacingMap.clear();
239 if (!m_model) return; 239 if (!m_model) return;
240 240
241 std::cerr << "RegionLayer::recalcSpacing" << std::endl;
242
241 std::set<float> values; 243 std::set<float> values;
242 244
243 for (RegionModel::PointList::const_iterator i = m_model->getPoints().begin(); 245 for (RegionModel::PointList::const_iterator i = m_model->getPoints().begin();
244 i != m_model->getPoints().end(); ++i) { 246 i != m_model->getPoints().end(); ++i) {
245 values.insert(i->value); 247 values.insert(i->value);
248 std::cerr << "RegionLayer::recalcSpacing: value found: " << i->value << std::endl;
246 } 249 }
247 250
248 int n = 0; 251 int n = 0;
249 252
250 for (std::set<float>::const_iterator i = values.begin(); 253 for (std::set<float>::const_iterator i = values.begin();
251 i != values.end(); ++i) { 254 i != values.end(); ++i) {
252 m_spacingMap[*i] = n++; 255 m_spacingMap[*i] = n++;
256 std::cerr << "RegionLayer::recalcSpacing: " << *i << " -> " << m_spacingMap[*i] << std::endl;
253 } 257 }
254 } 258 }
255 259
256 bool 260 bool
257 RegionLayer::getValueExtents(float &min, float &max, 261 RegionLayer::getValueExtents(float &min, float &max,
491 if (!v->getValueExtents(queryUnits, min, max, log)) { 495 if (!v->getValueExtents(queryUnits, min, max, log)) {
492 496
493 min = m_model->getValueMinimum(); 497 min = m_model->getValueMinimum();
494 max = m_model->getValueMaximum(); 498 max = m_model->getValueMaximum();
495 499
496 std::cerr << "RegionLayer[" << this << "]::getScaleExtents: min = " << min << ", max = " << max << ", log = " << log << std::endl; 500 // std::cerr << "RegionLayer[" << this << "]::getScaleExtents: min = " << min << ", max = " << max << ", log = " << log << std::endl;
497 501
498 } else if (log) { 502 } else if (log) {
499 503
500 LogRange::mapRange(min, max); 504 LogRange::mapRange(min, max);
501 505
502 std::cerr << "RegionLayer[" << this << "]::getScaleExtents: min = " << min << ", max = " << max << ", log = " << log << std::endl; 506 // std::cerr << "RegionLayer[" << this << "]::getScaleExtents: min = " << min << ", max = " << max << ", log = " << log << std::endl;
503 507
504 } 508 }
505 509
506 } else if (m_verticalScale == EqualSpaced) { 510 } else if (m_verticalScale == EqualSpaced) {
507 511
509 SpacingMap::const_iterator i = m_spacingMap.begin(); 513 SpacingMap::const_iterator i = m_spacingMap.begin();
510 min = i->second; 514 min = i->second;
511 i = m_spacingMap.end(); 515 i = m_spacingMap.end();
512 --i; 516 --i;
513 max = i->second; 517 max = i->second;
514 std::cerr << "RegionLayer[" << this << "]::getScaleExtents: equal spaced; min = " << min << ", max = " << max << ", log = " << log << std::endl; 518 // std::cerr << "RegionLayer[" << this << "]::getScaleExtents: equal spaced; min = " << min << ", max = " << max << ", log = " << log << std::endl;
515 } 519 }
516 520
517 } else { 521 } else {
518 522
519 min = m_model->getValueMinimum(); 523 min = m_model->getValueMinimum();
524 log = true; 528 log = true;
525 } 529 }
526 } 530 }
527 531
528 if (max == min) max = min + 1.0; 532 if (max == min) max = min + 1.0;
533 }
534
535 int
536 RegionLayer::spacingIndexToY(View *v, int i) const
537 {
538 int h = v->height();
539 int n = m_spacingMap.size();
540 // this maps from i (spacing of the value from the spacing
541 // map) and n (number of region types) to y
542 int y = h - (((h * i) / n) + (h / (2 * n)));
543 return y;
544 }
545
546 float
547 RegionLayer::yToSpacingIndex(View *v, int y) const
548 {
549 // we return an inexact result here (float rather than int)
550 int h = v->height();
551 int n = m_spacingMap.size();
552 // from y = h - ((h * i) / n) + (h / (2 * n)) as above
553 float vh = ((h + (h / float(2 * n)) - y) * n) / h;
554 return vh;
529 } 555 }
530 556
531 int 557 int
532 RegionLayer::getYForValue(View *v, float val) const 558 RegionLayer::getYForValue(View *v, float val) const
533 { 559 {
540 if (m_spacingMap.empty()) return h/2; 566 if (m_spacingMap.empty()) return h/2;
541 567
542 SpacingMap::const_iterator i = m_spacingMap.lower_bound(val); 568 SpacingMap::const_iterator i = m_spacingMap.lower_bound(val);
543 //!!! what now, if i->first != v? 569 //!!! what now, if i->first != v?
544 570
545 int vh = i->second; 571 int y = spacingIndexToY(v, i->second);
546 572
547 SpacingMap::const_iterator j = m_spacingMap.end(); 573 std::cerr << "RegionLayer::getYForValue: value " << val << " -> i->second " << i->second << " -> y " << y << std::endl;
548 --j; 574 return y;
549 575
550 return h - (((h * vh) / (j->second + 1)) + (h / (2 * (j->second + 1))));
551 576
552 } else { 577 } else {
553 578
554 getScaleExtents(v, min, max, logarithmic); 579 getScaleExtents(v, min, max, logarithmic);
555 580
559 if (logarithmic) { 584 if (logarithmic) {
560 val = LogRange::map(val); 585 val = LogRange::map(val);
561 } 586 }
562 587
563 return int(h - ((val - min) * h) / (max - min)); 588 return int(h - ((val - min) * h) / (max - min));
589 }
590 }
591
592 float
593 RegionLayer::getValueForY(View *v, int y) const
594 {
595 float min = 0.0, max = 0.0;
596 bool logarithmic = false;
597 int h = v->height();
598
599 if (m_verticalScale == EqualSpaced) {
600
601 // if we're equal spaced, we probably want to snap to the
602 // nearest item when close to it, and give some notification
603 // that we're doing so
604
605 if (m_spacingMap.empty()) return 1.f;
606
607 // n is the number of distinct regions. if we are close to
608 // one of the m/n divisions in the y scale, we should snap to
609 // the value of the mth region.
610
611 float vh = yToSpacingIndex(v, y);
612
613 // spacings in the map are integral, so find the closest one,
614 // map it back to its y coordinate, and see how far we are
615 // from it
616
617 int n = m_spacingMap.size();
618 int ivh = lrintf(vh);
619 if (ivh < 0) ivh = 0;
620 if (ivh > n-1) ivh = n-1;
621 int iy = spacingIndexToY(v, ivh);
622
623 int dist = iy - y;
624 int gap = h / n; // between region lines
625
626 std::cerr << "getValueForY: y = " << y << ", n = " << n << ", vh = " << vh << ", iy = " << iy << ", dist = " << dist << ", gap = " << gap << std::endl;
627
628 SpacingMap::const_iterator i = m_spacingMap.begin();
629 while (i != m_spacingMap.end()) {
630 if (i->second == ivh) break;
631 ++i;
632 }
633 if (i == m_spacingMap.end()) i = m_spacingMap.begin();
634
635 float val = 0;
636
637 if (dist > -gap/3 && dist < gap/3) {
638 // snap
639 val = i->first;
640 std::cerr << "snapped to " << val << std::endl;
641 } else if (dist < 0) {
642 // bisect gap to prior
643 if (i == m_spacingMap.begin()) {
644 val = i->first - 1.f;
645 std::cerr << "extended down to " << val << std::endl;
646 } else {
647 SpacingMap::const_iterator j = i;
648 --j;
649 val = (i->first + j->first) / 2;
650 std::cerr << "bisected down to " << val << std::endl;
651 }
652 } else {
653 // bisect gap to following
654 SpacingMap::const_iterator j = i;
655 ++j;
656 if (j == m_spacingMap.end()) {
657 val = i->first + 1.f;
658 std::cerr << "extended up to " << val << std::endl;
659 } else {
660 val = (i->first + j->first) / 2;
661 std::cerr << "bisected up to " << val << std::endl;
662 }
663 }
664
665 return val;
666
667 } else {
668
669 getScaleExtents(v, min, max, logarithmic);
670
671 float val = min + (float(h - y) * float(max - min)) / h;
672
673 if (logarithmic) {
674 val = powf(10.f, val);
675 }
676
677 return val;
564 } 678 }
565 } 679 }
566 680
567 QColor 681 QColor
568 RegionLayer::getColourForValue(View *v, float val) const 682 RegionLayer::getColourForValue(View *v, float val) const
590 RegionLayer::getDefaultColourHint(bool darkbg, bool &impose) 704 RegionLayer::getDefaultColourHint(bool darkbg, bool &impose)
591 { 705 {
592 impose = false; 706 impose = false;
593 return ColourDatabase::getInstance()->getColourIndex 707 return ColourDatabase::getInstance()->getColourIndex
594 (QString(darkbg ? "Bright Blue" : "Blue")); 708 (QString(darkbg ? "Bright Blue" : "Blue"));
595 }
596
597 float
598 RegionLayer::getValueForY(View *v, int y) const
599 {
600 float min = 0.0, max = 0.0;
601 bool logarithmic = false;
602 int h = v->height();
603
604 getScaleExtents(v, min, max, logarithmic);
605
606 float val = min + (float(h - y) * float(max - min)) / h;
607
608 if (logarithmic) {
609 val = powf(10.f, val);
610 }
611
612 return val;
613 } 709 }
614 710
615 void 711 void
616 RegionLayer::paint(View *v, QPainter &paint, QRect rect) const 712 RegionLayer::paint(View *v, QPainter &paint, QRect rect) const
617 { 713 {
776 872
777 long frame = v->getFrameForX(e->x()); 873 long frame = v->getFrameForX(e->x());
778 if (frame < 0) frame = 0; 874 if (frame < 0) frame = 0;
779 frame = frame / m_model->getResolution() * m_model->getResolution(); 875 frame = frame / m_model->getResolution() * m_model->getResolution();
780 876
781 float newValue = getValueForY(v, e->y()); 877 float newValue = m_editingPoint.value;
878 if (m_verticalScale != EqualSpaced) newValue = getValueForY(v, e->y());
782 879
783 long newFrame = m_editingPoint.frame; 880 long newFrame = m_editingPoint.frame;
784 long newDuration = frame - newFrame; 881 long newDuration = frame - newFrame;
785 if (newDuration < 0) { 882 if (newDuration < 0) {
786 newFrame = frame; 883 newFrame = frame;