Mercurial > hg > svgui
diff layer/Colour3DPlotLayer.cpp @ 1324:13d9b422f7fe zoom
Merge from default branch
author | Chris Cannam |
---|---|
date | Mon, 17 Sep 2018 13:51:31 +0100 |
parents | a34a2a25907c |
children | d79e21855aef |
line wrap: on
line diff
--- a/layer/Colour3DPlotLayer.cpp Mon Dec 12 15:18:52 2016 +0000 +++ b/layer/Colour3DPlotLayer.cpp Mon Sep 17 13:51:31 2018 +0100 @@ -70,6 +70,7 @@ Colour3DPlotLayer::~Colour3DPlotLayer() { invalidateRenderers(); + if (m_peakCache) m_peakCache->aboutToDelete(); delete m_peakCache; } @@ -106,7 +107,7 @@ switch (value) { default: case 0: return { ColumnNormalization::None, false }; - case 1: return { ColumnNormalization::Max1, false }; + case 1: return { ColumnNormalization::Range01, false }; case 2: return { ColumnNormalization::None, true }; // visible area case 3: return { ColumnNormalization::Hybrid, false }; } @@ -118,10 +119,11 @@ if (visible) return 2; switch (norm) { case ColumnNormalization::None: return 0; - case ColumnNormalization::Max1: return 1; + case ColumnNormalization::Range01: return 1; case ColumnNormalization::Hybrid: return 3; case ColumnNormalization::Sum1: + case ColumnNormalization::Max1: default: return 0; } } @@ -135,6 +137,8 @@ void Colour3DPlotLayer::setModel(const DenseThreeDimensionalModel *model) { + SVDEBUG << "Colour3DPlotLayer::setModel(" << model << ")" << endl; + if (m_model == model) return; const DenseThreeDimensionalModel *oldModel = m_model; m_model = model; @@ -144,7 +148,7 @@ connect(m_model, SIGNAL(modelChanged()), this, SLOT(modelChanged())); connect(m_model, SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)), - this, SLOT(modelChangedWithin(sv_frame_t, sv_frame_t))); + this, SLOT(modelChangedWithin(sv_frame_t, sv_frame_t))); m_peakResolution = 256; if (model->getResolution() > 512) { @@ -155,10 +159,12 @@ m_peakResolution = 128; } + if (m_peakCache) m_peakCache->aboutToDelete(); delete m_peakCache; m_peakCache = 0; invalidateRenderers(); + invalidateMagnitudes(); emit modelReplaced(); emit sliceableModelReplaced(oldModel, model); @@ -168,6 +174,7 @@ Colour3DPlotLayer::cacheInvalid() { invalidateRenderers(); + invalidateMagnitudes(); } void @@ -175,10 +182,12 @@ sv_frame_t /* endFrame */) { //!!! should do this only if the range is visible + if (m_peakCache) m_peakCache->aboutToDelete(); delete m_peakCache; m_peakCache = 0; invalidateRenderers(); + invalidateMagnitudes(); } void @@ -191,6 +200,15 @@ m_renderers.clear(); } +void +Colour3DPlotLayer::invalidateMagnitudes() +{ +#ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT + cerr << "Colour3DPlotLayer::invalidateMagnitudes called" << endl; +#endif + m_viewMags.clear(); +} + Dense3DModelPeakCache * Colour3DPlotLayer::getPeakCache() const { @@ -275,6 +293,7 @@ if (name == "Invert Vertical Scale") return ToggleProperty; if (name == "Opaque") return ToggleProperty; if (name == "Smooth") return ToggleProperty; + if (name == "Colour") return ColourMapProperty; return ValueProperty; } @@ -305,36 +324,36 @@ if (name == "Gain") { - *min = -50; - *max = 50; + *min = -50; + *max = 50; *deflt = int(lrint(log10(1.0) * 20.0)); - if (*deflt < *min) *deflt = *min; - if (*deflt > *max) *deflt = *max; + if (*deflt < *min) *deflt = *min; + if (*deflt > *max) *deflt = *max; - val = int(lrint(log10(m_gain) * 20.0)); - if (val < *min) val = *min; - if (val > *max) val = *max; + val = int(lrint(log10(m_gain) * 20.0)); + if (val < *min) val = *min; + if (val > *max) val = *max; } else if (name == "Colour Scale") { // linear, log, +/-1, abs - *min = 0; - *max = 3; + *min = 0; + *max = 3; *deflt = 0; - val = convertFromColourScale(m_colourScale); + val = convertFromColourScale(m_colourScale); } else if (name == "Colour") { - *min = 0; - *max = ColourMapper::getColourMapCount() - 1; + *min = 0; + *max = ColourMapper::getColourMapCount() - 1; *deflt = 0; - val = m_colourMap; + val = m_colourMap; } else if (name == "Normalization") { - + *min = 0; *max = 3; *deflt = 0; @@ -342,29 +361,29 @@ val = convertFromColumnNorm(m_normalization, m_normalizeVisibleArea); } else if (name == "Invert Vertical Scale") { - + *deflt = 0; - val = (m_invertVertical ? 1 : 0); + val = (m_invertVertical ? 1 : 0); } else if (name == "Bin Scale") { - *min = 0; - *max = 1; + *min = 0; + *max = 1; *deflt = int(BinScale::Linear); - val = (int)m_binScale; + val = (int)m_binScale; } else if (name == "Opaque") { - + *deflt = 0; - val = (m_opaque ? 1 : 0); + val = (m_opaque ? 1 : 0); } else if (name == "Smooth") { - + *deflt = 0; - val = (m_smooth ? 1 : 0); + val = (m_smooth ? 1 : 0); } else { - val = Layer::getPropertyRangeAndValue(name, min, max, deflt); + val = Layer::getPropertyRangeAndValue(name, min, max, deflt); } return val; @@ -372,29 +391,36 @@ QString Colour3DPlotLayer::getPropertyValueLabel(const PropertyName &name, - int value) const + int value) const { if (name == "Colour") { return ColourMapper::getColourMapName(value); } if (name == "Colour Scale") { - switch (value) { - default: - case 0: return tr("Linear"); - case 1: return tr("Log"); - case 2: return tr("+/-1"); - case 3: return tr("Absolute"); - } + switch (value) { + default: + case 0: return tr("Linear"); + case 1: return tr("Log"); + case 2: return tr("+/-1"); + case 3: return tr("Absolute"); + } } if (name == "Normalization") { - return ""; // icon only + switch(value) { + default: + case 0: return tr("None"); + case 1: return tr("Col"); + case 2: return tr("View"); + case 3: return tr("Hybrid"); + } +// return ""; // icon only } if (name == "Bin Scale") { - switch (value) { - default: - case 0: return tr("Linear"); - case 1: return tr("Log"); - } + switch (value) { + default: + case 0: return tr("Linear"); + case 1: return tr("Log"); + } } return tr("<unknown>"); } @@ -428,23 +454,23 @@ Colour3DPlotLayer::setProperty(const PropertyName &name, int value) { if (name == "Gain") { - setGain(float(pow(10, value/20.0))); + setGain(float(pow(10, value/20.0))); } else if (name == "Colour Scale") { setColourScale(convertToColourScale(value)); } else if (name == "Colour") { setColourMap(value); } else if (name == "Invert Vertical Scale") { - setInvertVertical(value ? true : false); + setInvertVertical(value ? true : false); } else if (name == "Opaque") { - setOpaque(value ? true : false); + setOpaque(value ? true : false); } else if (name == "Smooth") { - setSmooth(value ? true : false); + setSmooth(value ? true : false); } else if (name == "Bin Scale") { - switch (value) { - default: - case 0: setBinScale(BinScale::Linear); break; - case 1: setBinScale(BinScale::Log); break; - } + switch (value) { + default: + case 0: setBinScale(BinScale::Linear); break; + case 1: setBinScale(BinScale::Log); break; + } } else if (name == "Normalization") { auto n = convertToColumnNorm(value); setNormalization(n.first); @@ -455,9 +481,9 @@ void Colour3DPlotLayer::setColourScale(ColourScaleType scale) { + m_colourScaleSet = true; // even if setting to the same thing if (m_colourScale == scale) return; m_colourScale = scale; - m_colourScaleSet = true; invalidateRenderers(); emit layerParametersChanged(); } @@ -523,8 +549,9 @@ { if (m_normalizeVisibleArea == n) return; + invalidateRenderers(); + invalidateMagnitudes(); m_normalizeVisibleArea = n; - invalidateRenderers(); emit layerParametersChanged(); } @@ -597,7 +624,7 @@ Layer::setLayerDormant(v, true); cacheInvalid(); - + } else { Layer::setLayerDormant(v, false); @@ -607,17 +634,7 @@ bool Colour3DPlotLayer::isLayerScrollable(const LayerGeometryProvider * /* v */) const { - if (m_normalizeVisibleArea) { - return false; - } - //!!! ah hang on, if we're potentially rendering incrementally - //!!! they we can't be scrollable return false; -// if (getRenderer(v)->willRenderOpaque(v)) { -// return true; -// } -// QPoint discard; -// return !v->shouldIlluminateLocalFeatures(this, discard); } bool @@ -629,7 +646,7 @@ min = 0; max = double(m_model->getHeight()); - logarithmic = false; + logarithmic = (m_binScale == BinScale::Log); unit = ""; return true; @@ -753,11 +770,15 @@ getDisplayExtents(mn, mx); double h = v->getPaintHeight(); if (m_binScale == BinScale::Linear) { - bin = mn + ((h - y) * (mx - mn)) / h; + // Arrange that the first bin (mn) appears as the exact result + // for the first pixel (which is pixel h-1) and the first + // out-of-range bin (mx) would appear as the exact result for + // the first out-of-range pixel (which would be pixel -1) + bin = mn + ((h - y - 1) * (mx - mn)) / h; } else { double logmin = mn + 1, logmax = mx + 1; LogRange::mapRange(logmin, logmax); - bin = LogRange::unmap(logmin + ((h - y) * (logmax - logmin)) / h) - 1; + bin = LogRange::unmap(logmin + ((h - y - 1) * (logmax - logmin)) / h) - 1; } return bin; } @@ -814,12 +835,12 @@ else binName = QString("%1 [%2]").arg(binName).arg(sy + 1); QString text = tr("Time:\t%1 - %2\nBin:\t%3\nValue:\t%4") - .arg(RealTime::frame2RealTime(f0, m_model->getSampleRate()) - .toText(true).c_str()) - .arg(RealTime::frame2RealTime(f1, m_model->getSampleRate()) - .toText(true).c_str()) - .arg(binName) - .arg(value); + .arg(RealTime::frame2RealTime(f0, m_model->getSampleRate()) + .toText(true).c_str()) + .arg(RealTime::frame2RealTime(f1, m_model->getSampleRate()) + .toText(true).c_str()) + .arg(binName) + .arg(value); return text; } @@ -842,13 +863,13 @@ bool another = false; for (int i = 0; i < m_model->getHeight(); ++i) { - if (m_model->getBinName(i).length() > sampleText.length()) { - sampleText = m_model->getBinName(i); + if (m_model->getBinName(i).length() > sampleText.length()) { + sampleText = m_model->getBinName(i); another = true; - } + } } if (another) { - tw = std::max(tw, paint.fontMetrics().width(sampleText)); + tw = std::max(tw, paint.fontMetrics().width(sampleText)); } return tw + 13 + getColourScaleWidth(paint); @@ -948,7 +969,7 @@ } } } - + py = y0; if (i < symax) { @@ -973,80 +994,52 @@ paint.restore(); } -DenseThreeDimensionalModel::Column -Colour3DPlotLayer::getColumn(int col) const -{ - Profiler profiler("Colour3DPlotLayer::getColumn"); - - DenseThreeDimensionalModel::Column values = m_model->getColumn(col); - values.resize(m_model->getHeight(), 0.f); - if (m_normalization != ColumnNormalization::Max1 && - m_normalization != ColumnNormalization::Hybrid) { - return values; - } - - double colMax = 0.f, colMin = 0.f; - double min = 0.f, max = 0.f; - - int nv = int(values.size()); - - min = m_model->getMinimumLevel(); - max = m_model->getMaximumLevel(); - - for (int y = 0; y < nv; ++y) { - if (y == 0 || values.at(y) > colMax) colMax = values.at(y); - if (y == 0 || values.at(y) < colMin) colMin = values.at(y); - } - if (colMin == colMax) colMax = colMin + 1; - - for (int y = 0; y < nv; ++y) { - - double value = values.at(y); - double norm = (value - colMin) / (colMax - colMin); - double newvalue = min + (max - min) * norm; - - if (value != newvalue) values[y] = float(newvalue); - } - - if (m_normalization == ColumnNormalization::Hybrid - && (colMax > 0.0)) { - double logmax = log10(colMax); - for (int y = 0; y < nv; ++y) { - values[y] = float(values[y] * logmax); - } - } - - return values; -} - Colour3DPlotRenderer * Colour3DPlotLayer::getRenderer(const LayerGeometryProvider *v) const { - if (m_renderers.find(v->getId()) == m_renderers.end()) { + int viewId = v->getId(); + + if (m_renderers.find(viewId) == m_renderers.end()) { Colour3DPlotRenderer::Sources sources; sources.verticalBinLayer = this; sources.fft = 0; sources.source = m_model; - sources.peakCache = getPeakCache(); + sources.peakCaches.push_back(getPeakCache()); ColourScale::Parameters cparams; cparams.colourMap = m_colourMap; cparams.scaleType = m_colourScale; cparams.gain = m_gain; - if (m_normalization == ColumnNormalization::None) { - cparams.minValue = m_model->getMinimumLevel(); - cparams.maxValue = m_model->getMaximumLevel(); + double minValue = 0.0; + double maxValue = 1.0; + + if (m_normalizeVisibleArea && m_viewMags[viewId].isSet()) { + minValue = m_viewMags[viewId].getMin(); + maxValue = m_viewMags[viewId].getMax(); } else if (m_normalization == ColumnNormalization::Hybrid) { - cparams.minValue = 0; - cparams.maxValue = log10(m_model->getMaximumLevel() + 1.0); + minValue = 0; + maxValue = log10(m_model->getMaximumLevel() + 1.0); + } else if (m_normalization == ColumnNormalization::None) { + minValue = m_model->getMinimumLevel(); + maxValue = m_model->getMaximumLevel(); } - if (cparams.maxValue <= cparams.minValue) { - cparams.maxValue = cparams.minValue + 0.1; + SVDEBUG << "Colour3DPlotLayer: rebuilding renderer, value range is " + << minValue << " -> " << maxValue << endl; + + if (maxValue <= minValue) { + maxValue = minValue + 0.1f; } + + cparams.threshold = minValue; + cparams.minValue = minValue; + cparams.maxValue = maxValue; + m_lastRenderedMags[viewId] = MagnitudeRange(float(minValue), + float(maxValue)); + Colour3DPlotRenderer::Parameters params; params.colourScale = ColourScale(cparams); params.normalization = m_normalization; @@ -1055,10 +1048,10 @@ params.invertVertical = m_invertVertical; params.interpolate = m_smooth; - m_renderers[v->getId()] = new Colour3DPlotRenderer(sources, params); + m_renderers[viewId] = new Colour3DPlotRenderer(sources, params); } - return m_renderers[v->getId()]; + return m_renderers[viewId]; } void @@ -1071,7 +1064,9 @@ MagnitudeRange magRange; int viewId = v->getId(); - if (!renderer->geometryChanged(v)) { + bool continuingPaint = !renderer->geometryChanged(v); + + if (continuingPaint) { magRange = m_viewMags[viewId]; } @@ -1092,18 +1087,25 @@ magRange.sample(result.range); if (magRange.isSet()) { - if (!(m_viewMags[viewId] == magRange)) { + if (m_viewMags[viewId] != magRange) { m_viewMags[viewId] = magRange; - //!!! now need to do the normalise-visible thing +#ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT + cerr << "mag range in this view has changed: " + << magRange.getMin() << " -> " << magRange.getMax() << endl; +#endif } } - cerr << "mag range in this view: " - << m_viewMags[v->getId()].getMin() - << " -> " - << m_viewMags[v->getId()].getMax() - << endl; - + if (!continuingPaint && m_normalizeVisibleArea && + m_viewMags[viewId] != m_lastRenderedMags[viewId]) { +#ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT + cerr << "mag range has changed from last rendered range: re-rendering" + << endl; +#endif + delete m_renderers[viewId]; + m_renderers.erase(viewId); + v->updatePaintRect(v->getPaintRect()); + } } void @@ -1121,11 +1123,11 @@ int completion = 0; if (!m_model || !m_model->isOK() || !m_model->isReady(&completion)) { - if (completion > 0) { - paint.fillRect(0, 10, v->getPaintWidth() * completion / 100, - 10, QColor(120, 120, 120)); - } - return; + if (completion > 0) { + paint.fillRect(0, 10, v->getPaintWidth() * completion / 100, + 10, QColor(120, 120, 120)); + } + return; } if (m_model->getWidth() == 0) { @@ -1136,26 +1138,16 @@ return; } - //!!!??? - - if (m_normalizeVisibleArea) { - rect = v->getPaintRect(); - } - - //!!! why is the setLayerDormant(false) found here in - //!!! SpectrogramLayer not present in Colour3DPlotLayer? - //!!! unnecessary? vestigial? forgotten? - paintWithRenderer(v, paint, rect); } bool Colour3DPlotLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame, - int &resolution, - SnapType snap) const + int &resolution, + SnapType snap) const { if (!m_model) { - return Layer::snapToFeatureFrame(v, frame, resolution, snap); + return Layer::snapToFeatureFrame(v, frame, resolution, snap); } resolution = m_model->getResolution(); @@ -1167,9 +1159,9 @@ case SnapRight: frame = right; break; case SnapNearest: case SnapNeighbouring: - if (frame - left > right - frame) frame = right; - else frame = left; - break; + if (frame - left > right - frame) frame = right; + else frame = left; + break; } return true; @@ -1185,7 +1177,7 @@ "maxY=\"%4\" " "invertVertical=\"%5\" " "opaque=\"%6\" %7") - .arg(convertFromColourScale(m_colourScale)) + .arg(convertFromColourScale(m_colourScale)) .arg(m_colourMap) .arg(m_miny) .arg(m_maxy) @@ -1202,13 +1194,13 @@ // area as well afterwards s += QString("columnNormalization=\"%1\" ") - .arg(m_normalization == ColumnNormalization::Max1 ? "peak" : + .arg(m_normalization == ColumnNormalization::Range01 ? "peak" : m_normalization == ColumnNormalization::Hybrid ? "hybrid" : "none"); // Old-style normalization attribute, for backward compatibility s += QString("normalizeColumns=\"%1\" ") - .arg(m_normalization == ColumnNormalization::Max1 ? "true" : "false"); + .arg(m_normalization == ColumnNormalization::Range01 ? "true" : "false"); // And this applies to both old- and new-style attributes @@ -1224,14 +1216,14 @@ bool ok = false, alsoOk = false; ColourScaleType colourScale = convertToColourScale - (attributes.value("colourScale").toInt(&ok)); + (attributes.value("scale").toInt(&ok)); if (ok) setColourScale(colourScale); int colourMap = attributes.value("colourScheme").toInt(&ok); if (ok) setColourMap(colourMap); BinScale binScale = (BinScale) - attributes.value("binScale").toInt(&ok); + attributes.value("binScale").toInt(&ok); if (ok) setBinScale(binScale); bool invertVertical = @@ -1262,7 +1254,7 @@ haveNewStyleNormalization = true; if (columnNormalization == "peak") { - setNormalization(ColumnNormalization::Max1); + setNormalization(ColumnNormalization::Range01); } else if (columnNormalization == "hybrid") { setNormalization(ColumnNormalization::Hybrid); } else if (columnNormalization == "none") { @@ -1280,7 +1272,7 @@ bool normalizeColumns = (attributes.value("normalizeColumns").trimmed() == "true"); if (normalizeColumns) { - setNormalization(ColumnNormalization::Max1); + setNormalization(ColumnNormalization::Range01); } bool normalizeHybrid =