Mercurial > hg > svgui
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; |