Mercurial > hg > svgui
diff 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 |
line wrap: on
line diff
--- a/layer/RegionLayer.cpp Mon Aug 03 12:55:00 2009 +0000 +++ b/layer/RegionLayer.cpp Mon Aug 03 16:42:25 2009 +0000 @@ -238,11 +238,14 @@ m_spacingMap.clear(); if (!m_model) return; + std::cerr << "RegionLayer::recalcSpacing" << std::endl; + std::set<float> values; for (RegionModel::PointList::const_iterator i = m_model->getPoints().begin(); i != m_model->getPoints().end(); ++i) { values.insert(i->value); + std::cerr << "RegionLayer::recalcSpacing: value found: " << i->value << std::endl; } int n = 0; @@ -250,6 +253,7 @@ for (std::set<float>::const_iterator i = values.begin(); i != values.end(); ++i) { m_spacingMap[*i] = n++; + std::cerr << "RegionLayer::recalcSpacing: " << *i << " -> " << m_spacingMap[*i] << std::endl; } } @@ -493,13 +497,13 @@ min = m_model->getValueMinimum(); max = m_model->getValueMaximum(); - std::cerr << "RegionLayer[" << this << "]::getScaleExtents: min = " << min << ", max = " << max << ", log = " << log << std::endl; +// std::cerr << "RegionLayer[" << this << "]::getScaleExtents: min = " << min << ", max = " << max << ", log = " << log << std::endl; } else if (log) { LogRange::mapRange(min, max); - std::cerr << "RegionLayer[" << this << "]::getScaleExtents: min = " << min << ", max = " << max << ", log = " << log << std::endl; +// std::cerr << "RegionLayer[" << this << "]::getScaleExtents: min = " << min << ", max = " << max << ", log = " << log << std::endl; } @@ -511,7 +515,7 @@ i = m_spacingMap.end(); --i; max = i->second; - std::cerr << "RegionLayer[" << this << "]::getScaleExtents: equal spaced; min = " << min << ", max = " << max << ", log = " << log << std::endl; +// std::cerr << "RegionLayer[" << this << "]::getScaleExtents: equal spaced; min = " << min << ", max = " << max << ", log = " << log << std::endl; } } else { @@ -529,6 +533,28 @@ } int +RegionLayer::spacingIndexToY(View *v, int i) const +{ + int h = v->height(); + int n = m_spacingMap.size(); + // this maps from i (spacing of the value from the spacing + // map) and n (number of region types) to y + int y = h - (((h * i) / n) + (h / (2 * n))); + return y; +} + +float +RegionLayer::yToSpacingIndex(View *v, int y) const +{ + // we return an inexact result here (float rather than int) + int h = v->height(); + int n = m_spacingMap.size(); + // from y = h - ((h * i) / n) + (h / (2 * n)) as above + float vh = ((h + (h / float(2 * n)) - y) * n) / h; + return vh; +} + +int RegionLayer::getYForValue(View *v, float val) const { float min = 0.0, max = 0.0; @@ -542,12 +568,11 @@ SpacingMap::const_iterator i = m_spacingMap.lower_bound(val); //!!! what now, if i->first != v? - int vh = i->second; + int y = spacingIndexToY(v, i->second); - SpacingMap::const_iterator j = m_spacingMap.end(); - --j; + std::cerr << "RegionLayer::getYForValue: value " << val << " -> i->second " << i->second << " -> y " << y << std::endl; + return y; - return h - (((h * vh) / (j->second + 1)) + (h / (2 * (j->second + 1)))); } else { @@ -564,6 +589,95 @@ } } +float +RegionLayer::getValueForY(View *v, int y) const +{ + float min = 0.0, max = 0.0; + bool logarithmic = false; + int h = v->height(); + + if (m_verticalScale == EqualSpaced) { + + // if we're equal spaced, we probably want to snap to the + // nearest item when close to it, and give some notification + // that we're doing so + + if (m_spacingMap.empty()) return 1.f; + + // n is the number of distinct regions. if we are close to + // one of the m/n divisions in the y scale, we should snap to + // the value of the mth region. + + float vh = yToSpacingIndex(v, y); + + // spacings in the map are integral, so find the closest one, + // map it back to its y coordinate, and see how far we are + // from it + + int n = m_spacingMap.size(); + int ivh = lrintf(vh); + if (ivh < 0) ivh = 0; + if (ivh > n-1) ivh = n-1; + int iy = spacingIndexToY(v, ivh); + + int dist = iy - y; + int gap = h / n; // between region lines + + std::cerr << "getValueForY: y = " << y << ", n = " << n << ", vh = " << vh << ", iy = " << iy << ", dist = " << dist << ", gap = " << gap << std::endl; + + SpacingMap::const_iterator i = m_spacingMap.begin(); + while (i != m_spacingMap.end()) { + if (i->second == ivh) break; + ++i; + } + if (i == m_spacingMap.end()) i = m_spacingMap.begin(); + + float val = 0; + + if (dist > -gap/3 && dist < gap/3) { + // snap + val = i->first; + std::cerr << "snapped to " << val << std::endl; + } else if (dist < 0) { + // bisect gap to prior + if (i == m_spacingMap.begin()) { + val = i->first - 1.f; + std::cerr << "extended down to " << val << std::endl; + } else { + SpacingMap::const_iterator j = i; + --j; + val = (i->first + j->first) / 2; + std::cerr << "bisected down to " << val << std::endl; + } + } else { + // bisect gap to following + SpacingMap::const_iterator j = i; + ++j; + if (j == m_spacingMap.end()) { + val = i->first + 1.f; + std::cerr << "extended up to " << val << std::endl; + } else { + val = (i->first + j->first) / 2; + std::cerr << "bisected up to " << val << std::endl; + } + } + + return val; + + } else { + + getScaleExtents(v, min, max, logarithmic); + + float val = min + (float(h - y) * float(max - min)) / h; + + if (logarithmic) { + val = powf(10.f, val); + } + + return val; + } +} + QColor RegionLayer::getColourForValue(View *v, float val) const { @@ -594,24 +708,6 @@ (QString(darkbg ? "Bright Blue" : "Blue")); } -float -RegionLayer::getValueForY(View *v, int y) const -{ - float min = 0.0, max = 0.0; - bool logarithmic = false; - int h = v->height(); - - getScaleExtents(v, min, max, logarithmic); - - float val = min + (float(h - y) * float(max - min)) / h; - - if (logarithmic) { - val = powf(10.f, val); - } - - return val; -} - void RegionLayer::paint(View *v, QPainter &paint, QRect rect) const { @@ -778,7 +874,8 @@ if (frame < 0) frame = 0; frame = frame / m_model->getResolution() * m_model->getResolution(); - float newValue = getValueForY(v, e->y()); + float newValue = m_editingPoint.value; + if (m_verticalScale != EqualSpaced) newValue = getValueForY(v, e->y()); long newFrame = m_editingPoint.frame; long newDuration = frame - newFrame;