Mercurial > hg > svgui
comparison 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 |
comparison
equal
deleted
inserted
replaced
1183:57d192e26331 | 1324:13d9b422f7fe |
---|---|
68 } | 68 } |
69 | 69 |
70 Colour3DPlotLayer::~Colour3DPlotLayer() | 70 Colour3DPlotLayer::~Colour3DPlotLayer() |
71 { | 71 { |
72 invalidateRenderers(); | 72 invalidateRenderers(); |
73 if (m_peakCache) m_peakCache->aboutToDelete(); | |
73 delete m_peakCache; | 74 delete m_peakCache; |
74 } | 75 } |
75 | 76 |
76 ColourScaleType | 77 ColourScaleType |
77 Colour3DPlotLayer::convertToColourScale(int value) | 78 Colour3DPlotLayer::convertToColourScale(int value) |
104 Colour3DPlotLayer::convertToColumnNorm(int value) | 105 Colour3DPlotLayer::convertToColumnNorm(int value) |
105 { | 106 { |
106 switch (value) { | 107 switch (value) { |
107 default: | 108 default: |
108 case 0: return { ColumnNormalization::None, false }; | 109 case 0: return { ColumnNormalization::None, false }; |
109 case 1: return { ColumnNormalization::Max1, false }; | 110 case 1: return { ColumnNormalization::Range01, false }; |
110 case 2: return { ColumnNormalization::None, true }; // visible area | 111 case 2: return { ColumnNormalization::None, true }; // visible area |
111 case 3: return { ColumnNormalization::Hybrid, false }; | 112 case 3: return { ColumnNormalization::Hybrid, false }; |
112 } | 113 } |
113 } | 114 } |
114 | 115 |
116 Colour3DPlotLayer::convertFromColumnNorm(ColumnNormalization norm, bool visible) | 117 Colour3DPlotLayer::convertFromColumnNorm(ColumnNormalization norm, bool visible) |
117 { | 118 { |
118 if (visible) return 2; | 119 if (visible) return 2; |
119 switch (norm) { | 120 switch (norm) { |
120 case ColumnNormalization::None: return 0; | 121 case ColumnNormalization::None: return 0; |
121 case ColumnNormalization::Max1: return 1; | 122 case ColumnNormalization::Range01: return 1; |
122 case ColumnNormalization::Hybrid: return 3; | 123 case ColumnNormalization::Hybrid: return 3; |
123 | 124 |
124 case ColumnNormalization::Sum1: | 125 case ColumnNormalization::Sum1: |
126 case ColumnNormalization::Max1: | |
125 default: return 0; | 127 default: return 0; |
126 } | 128 } |
127 } | 129 } |
128 | 130 |
129 void | 131 void |
133 } | 135 } |
134 | 136 |
135 void | 137 void |
136 Colour3DPlotLayer::setModel(const DenseThreeDimensionalModel *model) | 138 Colour3DPlotLayer::setModel(const DenseThreeDimensionalModel *model) |
137 { | 139 { |
140 SVDEBUG << "Colour3DPlotLayer::setModel(" << model << ")" << endl; | |
141 | |
138 if (m_model == model) return; | 142 if (m_model == model) return; |
139 const DenseThreeDimensionalModel *oldModel = m_model; | 143 const DenseThreeDimensionalModel *oldModel = m_model; |
140 m_model = model; | 144 m_model = model; |
141 if (!m_model || !m_model->isOK()) return; | 145 if (!m_model || !m_model->isOK()) return; |
142 | 146 |
143 connectSignals(m_model); | 147 connectSignals(m_model); |
144 | 148 |
145 connect(m_model, SIGNAL(modelChanged()), this, SLOT(modelChanged())); | 149 connect(m_model, SIGNAL(modelChanged()), this, SLOT(modelChanged())); |
146 connect(m_model, SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)), | 150 connect(m_model, SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)), |
147 this, SLOT(modelChangedWithin(sv_frame_t, sv_frame_t))); | 151 this, SLOT(modelChangedWithin(sv_frame_t, sv_frame_t))); |
148 | 152 |
149 m_peakResolution = 256; | 153 m_peakResolution = 256; |
150 if (model->getResolution() > 512) { | 154 if (model->getResolution() > 512) { |
151 m_peakResolution = 16; | 155 m_peakResolution = 16; |
152 } else if (model->getResolution() > 128) { | 156 } else if (model->getResolution() > 128) { |
153 m_peakResolution = 64; | 157 m_peakResolution = 64; |
154 } else if (model->getResolution() > 2) { | 158 } else if (model->getResolution() > 2) { |
155 m_peakResolution = 128; | 159 m_peakResolution = 128; |
156 } | 160 } |
157 | 161 |
162 if (m_peakCache) m_peakCache->aboutToDelete(); | |
158 delete m_peakCache; | 163 delete m_peakCache; |
159 m_peakCache = 0; | 164 m_peakCache = 0; |
160 | 165 |
161 invalidateRenderers(); | 166 invalidateRenderers(); |
167 invalidateMagnitudes(); | |
162 | 168 |
163 emit modelReplaced(); | 169 emit modelReplaced(); |
164 emit sliceableModelReplaced(oldModel, model); | 170 emit sliceableModelReplaced(oldModel, model); |
165 } | 171 } |
166 | 172 |
167 void | 173 void |
168 Colour3DPlotLayer::cacheInvalid() | 174 Colour3DPlotLayer::cacheInvalid() |
169 { | 175 { |
170 invalidateRenderers(); | 176 invalidateRenderers(); |
177 invalidateMagnitudes(); | |
171 } | 178 } |
172 | 179 |
173 void | 180 void |
174 Colour3DPlotLayer::cacheInvalid(sv_frame_t /* startFrame */, | 181 Colour3DPlotLayer::cacheInvalid(sv_frame_t /* startFrame */, |
175 sv_frame_t /* endFrame */) | 182 sv_frame_t /* endFrame */) |
176 { | 183 { |
177 //!!! should do this only if the range is visible | 184 //!!! should do this only if the range is visible |
185 if (m_peakCache) m_peakCache->aboutToDelete(); | |
178 delete m_peakCache; | 186 delete m_peakCache; |
179 m_peakCache = 0; | 187 m_peakCache = 0; |
180 | 188 |
181 invalidateRenderers(); | 189 invalidateRenderers(); |
190 invalidateMagnitudes(); | |
182 } | 191 } |
183 | 192 |
184 void | 193 void |
185 Colour3DPlotLayer::invalidateRenderers() | 194 Colour3DPlotLayer::invalidateRenderers() |
186 { | 195 { |
187 for (ViewRendererMap::iterator i = m_renderers.begin(); | 196 for (ViewRendererMap::iterator i = m_renderers.begin(); |
188 i != m_renderers.end(); ++i) { | 197 i != m_renderers.end(); ++i) { |
189 delete i->second; | 198 delete i->second; |
190 } | 199 } |
191 m_renderers.clear(); | 200 m_renderers.clear(); |
201 } | |
202 | |
203 void | |
204 Colour3DPlotLayer::invalidateMagnitudes() | |
205 { | |
206 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT | |
207 cerr << "Colour3DPlotLayer::invalidateMagnitudes called" << endl; | |
208 #endif | |
209 m_viewMags.clear(); | |
192 } | 210 } |
193 | 211 |
194 Dense3DModelPeakCache * | 212 Dense3DModelPeakCache * |
195 Colour3DPlotLayer::getPeakCache() const | 213 Colour3DPlotLayer::getPeakCache() const |
196 { | 214 { |
273 { | 291 { |
274 if (name == "Gain") return RangeProperty; | 292 if (name == "Gain") return RangeProperty; |
275 if (name == "Invert Vertical Scale") return ToggleProperty; | 293 if (name == "Invert Vertical Scale") return ToggleProperty; |
276 if (name == "Opaque") return ToggleProperty; | 294 if (name == "Opaque") return ToggleProperty; |
277 if (name == "Smooth") return ToggleProperty; | 295 if (name == "Smooth") return ToggleProperty; |
296 if (name == "Colour") return ColourMapProperty; | |
278 return ValueProperty; | 297 return ValueProperty; |
279 } | 298 } |
280 | 299 |
281 QString | 300 QString |
282 Colour3DPlotLayer::getPropertyGroupName(const PropertyName &name) const | 301 Colour3DPlotLayer::getPropertyGroupName(const PropertyName &name) const |
303 if (!max) max = &garbage1; | 322 if (!max) max = &garbage1; |
304 if (!deflt) deflt = &garbage2; | 323 if (!deflt) deflt = &garbage2; |
305 | 324 |
306 if (name == "Gain") { | 325 if (name == "Gain") { |
307 | 326 |
308 *min = -50; | 327 *min = -50; |
309 *max = 50; | 328 *max = 50; |
310 | 329 |
311 *deflt = int(lrint(log10(1.0) * 20.0)); | 330 *deflt = int(lrint(log10(1.0) * 20.0)); |
312 if (*deflt < *min) *deflt = *min; | 331 if (*deflt < *min) *deflt = *min; |
313 if (*deflt > *max) *deflt = *max; | 332 if (*deflt > *max) *deflt = *max; |
314 | 333 |
315 val = int(lrint(log10(m_gain) * 20.0)); | 334 val = int(lrint(log10(m_gain) * 20.0)); |
316 if (val < *min) val = *min; | 335 if (val < *min) val = *min; |
317 if (val > *max) val = *max; | 336 if (val > *max) val = *max; |
318 | 337 |
319 } else if (name == "Colour Scale") { | 338 } else if (name == "Colour Scale") { |
320 | 339 |
321 // linear, log, +/-1, abs | 340 // linear, log, +/-1, abs |
322 *min = 0; | |
323 *max = 3; | |
324 *deflt = 0; | |
325 | |
326 val = convertFromColourScale(m_colourScale); | |
327 | |
328 } else if (name == "Colour") { | |
329 | |
330 *min = 0; | |
331 *max = ColourMapper::getColourMapCount() - 1; | |
332 *deflt = 0; | |
333 | |
334 val = m_colourMap; | |
335 | |
336 } else if (name == "Normalization") { | |
337 | |
338 *min = 0; | 341 *min = 0; |
339 *max = 3; | 342 *max = 3; |
340 *deflt = 0; | 343 *deflt = 0; |
341 | 344 |
345 val = convertFromColourScale(m_colourScale); | |
346 | |
347 } else if (name == "Colour") { | |
348 | |
349 *min = 0; | |
350 *max = ColourMapper::getColourMapCount() - 1; | |
351 *deflt = 0; | |
352 | |
353 val = m_colourMap; | |
354 | |
355 } else if (name == "Normalization") { | |
356 | |
357 *min = 0; | |
358 *max = 3; | |
359 *deflt = 0; | |
360 | |
342 val = convertFromColumnNorm(m_normalization, m_normalizeVisibleArea); | 361 val = convertFromColumnNorm(m_normalization, m_normalizeVisibleArea); |
343 | 362 |
344 } else if (name == "Invert Vertical Scale") { | 363 } else if (name == "Invert Vertical Scale") { |
345 | 364 |
346 *deflt = 0; | 365 *deflt = 0; |
347 val = (m_invertVertical ? 1 : 0); | 366 val = (m_invertVertical ? 1 : 0); |
348 | 367 |
349 } else if (name == "Bin Scale") { | 368 } else if (name == "Bin Scale") { |
350 | 369 |
351 *min = 0; | 370 *min = 0; |
352 *max = 1; | 371 *max = 1; |
353 *deflt = int(BinScale::Linear); | 372 *deflt = int(BinScale::Linear); |
354 val = (int)m_binScale; | 373 val = (int)m_binScale; |
355 | 374 |
356 } else if (name == "Opaque") { | 375 } else if (name == "Opaque") { |
357 | 376 |
358 *deflt = 0; | 377 *deflt = 0; |
359 val = (m_opaque ? 1 : 0); | 378 val = (m_opaque ? 1 : 0); |
360 | 379 |
361 } else if (name == "Smooth") { | 380 } else if (name == "Smooth") { |
362 | 381 |
363 *deflt = 0; | 382 *deflt = 0; |
364 val = (m_smooth ? 1 : 0); | 383 val = (m_smooth ? 1 : 0); |
365 | 384 |
366 } else { | 385 } else { |
367 val = Layer::getPropertyRangeAndValue(name, min, max, deflt); | 386 val = Layer::getPropertyRangeAndValue(name, min, max, deflt); |
368 } | 387 } |
369 | 388 |
370 return val; | 389 return val; |
371 } | 390 } |
372 | 391 |
373 QString | 392 QString |
374 Colour3DPlotLayer::getPropertyValueLabel(const PropertyName &name, | 393 Colour3DPlotLayer::getPropertyValueLabel(const PropertyName &name, |
375 int value) const | 394 int value) const |
376 { | 395 { |
377 if (name == "Colour") { | 396 if (name == "Colour") { |
378 return ColourMapper::getColourMapName(value); | 397 return ColourMapper::getColourMapName(value); |
379 } | 398 } |
380 if (name == "Colour Scale") { | 399 if (name == "Colour Scale") { |
381 switch (value) { | 400 switch (value) { |
382 default: | 401 default: |
383 case 0: return tr("Linear"); | 402 case 0: return tr("Linear"); |
384 case 1: return tr("Log"); | 403 case 1: return tr("Log"); |
385 case 2: return tr("+/-1"); | 404 case 2: return tr("+/-1"); |
386 case 3: return tr("Absolute"); | 405 case 3: return tr("Absolute"); |
387 } | 406 } |
388 } | 407 } |
389 if (name == "Normalization") { | 408 if (name == "Normalization") { |
390 return ""; // icon only | 409 switch(value) { |
410 default: | |
411 case 0: return tr("None"); | |
412 case 1: return tr("Col"); | |
413 case 2: return tr("View"); | |
414 case 3: return tr("Hybrid"); | |
415 } | |
416 // return ""; // icon only | |
391 } | 417 } |
392 if (name == "Bin Scale") { | 418 if (name == "Bin Scale") { |
393 switch (value) { | 419 switch (value) { |
394 default: | 420 default: |
395 case 0: return tr("Linear"); | 421 case 0: return tr("Linear"); |
396 case 1: return tr("Log"); | 422 case 1: return tr("Log"); |
397 } | 423 } |
398 } | 424 } |
399 return tr("<unknown>"); | 425 return tr("<unknown>"); |
400 } | 426 } |
401 | 427 |
402 QString | 428 QString |
426 | 452 |
427 void | 453 void |
428 Colour3DPlotLayer::setProperty(const PropertyName &name, int value) | 454 Colour3DPlotLayer::setProperty(const PropertyName &name, int value) |
429 { | 455 { |
430 if (name == "Gain") { | 456 if (name == "Gain") { |
431 setGain(float(pow(10, value/20.0))); | 457 setGain(float(pow(10, value/20.0))); |
432 } else if (name == "Colour Scale") { | 458 } else if (name == "Colour Scale") { |
433 setColourScale(convertToColourScale(value)); | 459 setColourScale(convertToColourScale(value)); |
434 } else if (name == "Colour") { | 460 } else if (name == "Colour") { |
435 setColourMap(value); | 461 setColourMap(value); |
436 } else if (name == "Invert Vertical Scale") { | 462 } else if (name == "Invert Vertical Scale") { |
437 setInvertVertical(value ? true : false); | 463 setInvertVertical(value ? true : false); |
438 } else if (name == "Opaque") { | 464 } else if (name == "Opaque") { |
439 setOpaque(value ? true : false); | 465 setOpaque(value ? true : false); |
440 } else if (name == "Smooth") { | 466 } else if (name == "Smooth") { |
441 setSmooth(value ? true : false); | 467 setSmooth(value ? true : false); |
442 } else if (name == "Bin Scale") { | 468 } else if (name == "Bin Scale") { |
443 switch (value) { | 469 switch (value) { |
444 default: | 470 default: |
445 case 0: setBinScale(BinScale::Linear); break; | 471 case 0: setBinScale(BinScale::Linear); break; |
446 case 1: setBinScale(BinScale::Log); break; | 472 case 1: setBinScale(BinScale::Log); break; |
447 } | 473 } |
448 } else if (name == "Normalization") { | 474 } else if (name == "Normalization") { |
449 auto n = convertToColumnNorm(value); | 475 auto n = convertToColumnNorm(value); |
450 setNormalization(n.first); | 476 setNormalization(n.first); |
451 setNormalizeVisibleArea(n.second); | 477 setNormalizeVisibleArea(n.second); |
452 } | 478 } |
453 } | 479 } |
454 | 480 |
455 void | 481 void |
456 Colour3DPlotLayer::setColourScale(ColourScaleType scale) | 482 Colour3DPlotLayer::setColourScale(ColourScaleType scale) |
457 { | 483 { |
484 m_colourScaleSet = true; // even if setting to the same thing | |
458 if (m_colourScale == scale) return; | 485 if (m_colourScale == scale) return; |
459 m_colourScale = scale; | 486 m_colourScale = scale; |
460 m_colourScaleSet = true; | |
461 invalidateRenderers(); | 487 invalidateRenderers(); |
462 emit layerParametersChanged(); | 488 emit layerParametersChanged(); |
463 } | 489 } |
464 | 490 |
465 void | 491 void |
521 void | 547 void |
522 Colour3DPlotLayer::setNormalizeVisibleArea(bool n) | 548 Colour3DPlotLayer::setNormalizeVisibleArea(bool n) |
523 { | 549 { |
524 if (m_normalizeVisibleArea == n) return; | 550 if (m_normalizeVisibleArea == n) return; |
525 | 551 |
552 invalidateRenderers(); | |
553 invalidateMagnitudes(); | |
526 m_normalizeVisibleArea = n; | 554 m_normalizeVisibleArea = n; |
527 invalidateRenderers(); | |
528 | 555 |
529 emit layerParametersChanged(); | 556 emit layerParametersChanged(); |
530 } | 557 } |
531 | 558 |
532 bool | 559 bool |
595 } | 622 } |
596 | 623 |
597 Layer::setLayerDormant(v, true); | 624 Layer::setLayerDormant(v, true); |
598 | 625 |
599 cacheInvalid(); | 626 cacheInvalid(); |
600 | 627 |
601 } else { | 628 } else { |
602 | 629 |
603 Layer::setLayerDormant(v, false); | 630 Layer::setLayerDormant(v, false); |
604 } | 631 } |
605 } | 632 } |
606 | 633 |
607 bool | 634 bool |
608 Colour3DPlotLayer::isLayerScrollable(const LayerGeometryProvider * /* v */) const | 635 Colour3DPlotLayer::isLayerScrollable(const LayerGeometryProvider * /* v */) const |
609 { | 636 { |
610 if (m_normalizeVisibleArea) { | |
611 return false; | |
612 } | |
613 //!!! ah hang on, if we're potentially rendering incrementally | |
614 //!!! they we can't be scrollable | |
615 return false; | 637 return false; |
616 // if (getRenderer(v)->willRenderOpaque(v)) { | |
617 // return true; | |
618 // } | |
619 // QPoint discard; | |
620 // return !v->shouldIlluminateLocalFeatures(this, discard); | |
621 } | 638 } |
622 | 639 |
623 bool | 640 bool |
624 Colour3DPlotLayer::getValueExtents(double &min, double &max, | 641 Colour3DPlotLayer::getValueExtents(double &min, double &max, |
625 bool &logarithmic, QString &unit) const | 642 bool &logarithmic, QString &unit) const |
627 if (!m_model) return false; | 644 if (!m_model) return false; |
628 | 645 |
629 min = 0; | 646 min = 0; |
630 max = double(m_model->getHeight()); | 647 max = double(m_model->getHeight()); |
631 | 648 |
632 logarithmic = false; | 649 logarithmic = (m_binScale == BinScale::Log); |
633 unit = ""; | 650 unit = ""; |
634 | 651 |
635 return true; | 652 return true; |
636 } | 653 } |
637 | 654 |
751 if (!m_model) return bin; | 768 if (!m_model) return bin; |
752 double mn = 0, mx = m_model->getHeight(); | 769 double mn = 0, mx = m_model->getHeight(); |
753 getDisplayExtents(mn, mx); | 770 getDisplayExtents(mn, mx); |
754 double h = v->getPaintHeight(); | 771 double h = v->getPaintHeight(); |
755 if (m_binScale == BinScale::Linear) { | 772 if (m_binScale == BinScale::Linear) { |
756 bin = mn + ((h - y) * (mx - mn)) / h; | 773 // Arrange that the first bin (mn) appears as the exact result |
774 // for the first pixel (which is pixel h-1) and the first | |
775 // out-of-range bin (mx) would appear as the exact result for | |
776 // the first out-of-range pixel (which would be pixel -1) | |
777 bin = mn + ((h - y - 1) * (mx - mn)) / h; | |
757 } else { | 778 } else { |
758 double logmin = mn + 1, logmax = mx + 1; | 779 double logmin = mn + 1, logmax = mx + 1; |
759 LogRange::mapRange(logmin, logmax); | 780 LogRange::mapRange(logmin, logmax); |
760 bin = LogRange::unmap(logmin + ((h - y) * (logmax - logmin)) / h) - 1; | 781 bin = LogRange::unmap(logmin + ((h - y - 1) * (logmax - logmin)) / h) - 1; |
761 } | 782 } |
762 return bin; | 783 return bin; |
763 } | 784 } |
764 | 785 |
765 QString | 786 QString |
812 QString binName = m_model->getBinName(sy); | 833 QString binName = m_model->getBinName(sy); |
813 if (binName == "") binName = QString("[%1]").arg(sy + 1); | 834 if (binName == "") binName = QString("[%1]").arg(sy + 1); |
814 else binName = QString("%1 [%2]").arg(binName).arg(sy + 1); | 835 else binName = QString("%1 [%2]").arg(binName).arg(sy + 1); |
815 | 836 |
816 QString text = tr("Time:\t%1 - %2\nBin:\t%3\nValue:\t%4") | 837 QString text = tr("Time:\t%1 - %2\nBin:\t%3\nValue:\t%4") |
817 .arg(RealTime::frame2RealTime(f0, m_model->getSampleRate()) | 838 .arg(RealTime::frame2RealTime(f0, m_model->getSampleRate()) |
818 .toText(true).c_str()) | 839 .toText(true).c_str()) |
819 .arg(RealTime::frame2RealTime(f1, m_model->getSampleRate()) | 840 .arg(RealTime::frame2RealTime(f1, m_model->getSampleRate()) |
820 .toText(true).c_str()) | 841 .toText(true).c_str()) |
821 .arg(binName) | 842 .arg(binName) |
822 .arg(value); | 843 .arg(value); |
823 | 844 |
824 return text; | 845 return text; |
825 } | 846 } |
826 | 847 |
827 int | 848 int |
840 QString sampleText = QString("[%1]").arg(m_model->getHeight()); | 861 QString sampleText = QString("[%1]").arg(m_model->getHeight()); |
841 int tw = paint.fontMetrics().width(sampleText); | 862 int tw = paint.fontMetrics().width(sampleText); |
842 bool another = false; | 863 bool another = false; |
843 | 864 |
844 for (int i = 0; i < m_model->getHeight(); ++i) { | 865 for (int i = 0; i < m_model->getHeight(); ++i) { |
845 if (m_model->getBinName(i).length() > sampleText.length()) { | 866 if (m_model->getBinName(i).length() > sampleText.length()) { |
846 sampleText = m_model->getBinName(i); | 867 sampleText = m_model->getBinName(i); |
847 another = true; | 868 another = true; |
848 } | 869 } |
849 } | 870 } |
850 if (another) { | 871 if (another) { |
851 tw = std::max(tw, paint.fontMetrics().width(sampleText)); | 872 tw = std::max(tw, paint.fontMetrics().width(sampleText)); |
852 } | 873 } |
853 | 874 |
854 return tw + 13 + getColourScaleWidth(paint); | 875 return tw + 13 + getColourScaleWidth(paint); |
855 } | 876 } |
856 | 877 |
946 } else { | 967 } else { |
947 continue; | 968 continue; |
948 } | 969 } |
949 } | 970 } |
950 } | 971 } |
951 | 972 |
952 py = y0; | 973 py = y0; |
953 | 974 |
954 if (i < symax) { | 975 if (i < symax) { |
955 paint.drawLine(cw, y0, w, y0); | 976 paint.drawLine(cw, y0, w, y0); |
956 } | 977 } |
971 } | 992 } |
972 | 993 |
973 paint.restore(); | 994 paint.restore(); |
974 } | 995 } |
975 | 996 |
976 DenseThreeDimensionalModel::Column | |
977 Colour3DPlotLayer::getColumn(int col) const | |
978 { | |
979 Profiler profiler("Colour3DPlotLayer::getColumn"); | |
980 | |
981 DenseThreeDimensionalModel::Column values = m_model->getColumn(col); | |
982 values.resize(m_model->getHeight(), 0.f); | |
983 if (m_normalization != ColumnNormalization::Max1 && | |
984 m_normalization != ColumnNormalization::Hybrid) { | |
985 return values; | |
986 } | |
987 | |
988 double colMax = 0.f, colMin = 0.f; | |
989 double min = 0.f, max = 0.f; | |
990 | |
991 int nv = int(values.size()); | |
992 | |
993 min = m_model->getMinimumLevel(); | |
994 max = m_model->getMaximumLevel(); | |
995 | |
996 for (int y = 0; y < nv; ++y) { | |
997 if (y == 0 || values.at(y) > colMax) colMax = values.at(y); | |
998 if (y == 0 || values.at(y) < colMin) colMin = values.at(y); | |
999 } | |
1000 if (colMin == colMax) colMax = colMin + 1; | |
1001 | |
1002 for (int y = 0; y < nv; ++y) { | |
1003 | |
1004 double value = values.at(y); | |
1005 double norm = (value - colMin) / (colMax - colMin); | |
1006 double newvalue = min + (max - min) * norm; | |
1007 | |
1008 if (value != newvalue) values[y] = float(newvalue); | |
1009 } | |
1010 | |
1011 if (m_normalization == ColumnNormalization::Hybrid | |
1012 && (colMax > 0.0)) { | |
1013 double logmax = log10(colMax); | |
1014 for (int y = 0; y < nv; ++y) { | |
1015 values[y] = float(values[y] * logmax); | |
1016 } | |
1017 } | |
1018 | |
1019 return values; | |
1020 } | |
1021 | |
1022 Colour3DPlotRenderer * | 997 Colour3DPlotRenderer * |
1023 Colour3DPlotLayer::getRenderer(const LayerGeometryProvider *v) const | 998 Colour3DPlotLayer::getRenderer(const LayerGeometryProvider *v) const |
1024 { | 999 { |
1025 if (m_renderers.find(v->getId()) == m_renderers.end()) { | 1000 int viewId = v->getId(); |
1001 | |
1002 if (m_renderers.find(viewId) == m_renderers.end()) { | |
1026 | 1003 |
1027 Colour3DPlotRenderer::Sources sources; | 1004 Colour3DPlotRenderer::Sources sources; |
1028 sources.verticalBinLayer = this; | 1005 sources.verticalBinLayer = this; |
1029 sources.fft = 0; | 1006 sources.fft = 0; |
1030 sources.source = m_model; | 1007 sources.source = m_model; |
1031 sources.peakCache = getPeakCache(); | 1008 sources.peakCaches.push_back(getPeakCache()); |
1032 | 1009 |
1033 ColourScale::Parameters cparams; | 1010 ColourScale::Parameters cparams; |
1034 cparams.colourMap = m_colourMap; | 1011 cparams.colourMap = m_colourMap; |
1035 cparams.scaleType = m_colourScale; | 1012 cparams.scaleType = m_colourScale; |
1036 cparams.gain = m_gain; | 1013 cparams.gain = m_gain; |
1037 | 1014 |
1038 if (m_normalization == ColumnNormalization::None) { | 1015 double minValue = 0.0; |
1039 cparams.minValue = m_model->getMinimumLevel(); | 1016 double maxValue = 1.0; |
1040 cparams.maxValue = m_model->getMaximumLevel(); | 1017 |
1018 if (m_normalizeVisibleArea && m_viewMags[viewId].isSet()) { | |
1019 minValue = m_viewMags[viewId].getMin(); | |
1020 maxValue = m_viewMags[viewId].getMax(); | |
1041 } else if (m_normalization == ColumnNormalization::Hybrid) { | 1021 } else if (m_normalization == ColumnNormalization::Hybrid) { |
1042 cparams.minValue = 0; | 1022 minValue = 0; |
1043 cparams.maxValue = log10(m_model->getMaximumLevel() + 1.0); | 1023 maxValue = log10(m_model->getMaximumLevel() + 1.0); |
1044 } | 1024 } else if (m_normalization == ColumnNormalization::None) { |
1045 | 1025 minValue = m_model->getMinimumLevel(); |
1046 if (cparams.maxValue <= cparams.minValue) { | 1026 maxValue = m_model->getMaximumLevel(); |
1047 cparams.maxValue = cparams.minValue + 0.1; | 1027 } |
1048 } | 1028 |
1029 SVDEBUG << "Colour3DPlotLayer: rebuilding renderer, value range is " | |
1030 << minValue << " -> " << maxValue << endl; | |
1049 | 1031 |
1032 if (maxValue <= minValue) { | |
1033 maxValue = minValue + 0.1f; | |
1034 } | |
1035 | |
1036 cparams.threshold = minValue; | |
1037 cparams.minValue = minValue; | |
1038 cparams.maxValue = maxValue; | |
1039 | |
1040 m_lastRenderedMags[viewId] = MagnitudeRange(float(minValue), | |
1041 float(maxValue)); | |
1042 | |
1050 Colour3DPlotRenderer::Parameters params; | 1043 Colour3DPlotRenderer::Parameters params; |
1051 params.colourScale = ColourScale(cparams); | 1044 params.colourScale = ColourScale(cparams); |
1052 params.normalization = m_normalization; | 1045 params.normalization = m_normalization; |
1053 params.binScale = m_binScale; | 1046 params.binScale = m_binScale; |
1054 params.alwaysOpaque = m_opaque; | 1047 params.alwaysOpaque = m_opaque; |
1055 params.invertVertical = m_invertVertical; | 1048 params.invertVertical = m_invertVertical; |
1056 params.interpolate = m_smooth; | 1049 params.interpolate = m_smooth; |
1057 | 1050 |
1058 m_renderers[v->getId()] = new Colour3DPlotRenderer(sources, params); | 1051 m_renderers[viewId] = new Colour3DPlotRenderer(sources, params); |
1059 } | 1052 } |
1060 | 1053 |
1061 return m_renderers[v->getId()]; | 1054 return m_renderers[viewId]; |
1062 } | 1055 } |
1063 | 1056 |
1064 void | 1057 void |
1065 Colour3DPlotLayer::paintWithRenderer(LayerGeometryProvider *v, | 1058 Colour3DPlotLayer::paintWithRenderer(LayerGeometryProvider *v, |
1066 QPainter &paint, QRect rect) const | 1059 QPainter &paint, QRect rect) const |
1069 | 1062 |
1070 Colour3DPlotRenderer::RenderResult result; | 1063 Colour3DPlotRenderer::RenderResult result; |
1071 MagnitudeRange magRange; | 1064 MagnitudeRange magRange; |
1072 int viewId = v->getId(); | 1065 int viewId = v->getId(); |
1073 | 1066 |
1074 if (!renderer->geometryChanged(v)) { | 1067 bool continuingPaint = !renderer->geometryChanged(v); |
1068 | |
1069 if (continuingPaint) { | |
1075 magRange = m_viewMags[viewId]; | 1070 magRange = m_viewMags[viewId]; |
1076 } | 1071 } |
1077 | 1072 |
1078 if (m_synchronous) { | 1073 if (m_synchronous) { |
1079 | 1074 |
1090 } | 1085 } |
1091 | 1086 |
1092 magRange.sample(result.range); | 1087 magRange.sample(result.range); |
1093 | 1088 |
1094 if (magRange.isSet()) { | 1089 if (magRange.isSet()) { |
1095 if (!(m_viewMags[viewId] == magRange)) { | 1090 if (m_viewMags[viewId] != magRange) { |
1096 m_viewMags[viewId] = magRange; | 1091 m_viewMags[viewId] = magRange; |
1097 //!!! now need to do the normalise-visible thing | 1092 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT |
1098 } | 1093 cerr << "mag range in this view has changed: " |
1099 } | 1094 << magRange.getMin() << " -> " << magRange.getMax() << endl; |
1100 | 1095 #endif |
1101 cerr << "mag range in this view: " | 1096 } |
1102 << m_viewMags[v->getId()].getMin() | 1097 } |
1103 << " -> " | 1098 |
1104 << m_viewMags[v->getId()].getMax() | 1099 if (!continuingPaint && m_normalizeVisibleArea && |
1105 << endl; | 1100 m_viewMags[viewId] != m_lastRenderedMags[viewId]) { |
1106 | 1101 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT |
1102 cerr << "mag range has changed from last rendered range: re-rendering" | |
1103 << endl; | |
1104 #endif | |
1105 delete m_renderers[viewId]; | |
1106 m_renderers.erase(viewId); | |
1107 v->updatePaintRect(v->getPaintRect()); | |
1108 } | |
1107 } | 1109 } |
1108 | 1110 |
1109 void | 1111 void |
1110 Colour3DPlotLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const | 1112 Colour3DPlotLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const |
1111 { | 1113 { |
1119 cerr << "Colour3DPlotLayer::paint(): m_model is " << m_model << ", zoom level is " << v->getZoomLevel() << ", rect is (" << rect.x() << "," << rect.y() << ") " << rect.width() << "x" << rect.height() << endl; | 1121 cerr << "Colour3DPlotLayer::paint(): m_model is " << m_model << ", zoom level is " << v->getZoomLevel() << ", rect is (" << rect.x() << "," << rect.y() << ") " << rect.width() << "x" << rect.height() << endl; |
1120 #endif | 1122 #endif |
1121 | 1123 |
1122 int completion = 0; | 1124 int completion = 0; |
1123 if (!m_model || !m_model->isOK() || !m_model->isReady(&completion)) { | 1125 if (!m_model || !m_model->isOK() || !m_model->isReady(&completion)) { |
1124 if (completion > 0) { | 1126 if (completion > 0) { |
1125 paint.fillRect(0, 10, v->getPaintWidth() * completion / 100, | 1127 paint.fillRect(0, 10, v->getPaintWidth() * completion / 100, |
1126 10, QColor(120, 120, 120)); | 1128 10, QColor(120, 120, 120)); |
1127 } | 1129 } |
1128 return; | 1130 return; |
1129 } | 1131 } |
1130 | 1132 |
1131 if (m_model->getWidth() == 0) { | 1133 if (m_model->getWidth() == 0) { |
1132 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT | 1134 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT |
1133 cerr << "Colour3DPlotLayer::paint(): model width == 0, " | 1135 cerr << "Colour3DPlotLayer::paint(): model width == 0, " |
1134 << "nothing to paint (yet)" << endl; | 1136 << "nothing to paint (yet)" << endl; |
1135 #endif | 1137 #endif |
1136 return; | 1138 return; |
1137 } | 1139 } |
1138 | 1140 |
1139 //!!!??? | |
1140 | |
1141 if (m_normalizeVisibleArea) { | |
1142 rect = v->getPaintRect(); | |
1143 } | |
1144 | |
1145 //!!! why is the setLayerDormant(false) found here in | |
1146 //!!! SpectrogramLayer not present in Colour3DPlotLayer? | |
1147 //!!! unnecessary? vestigial? forgotten? | |
1148 | |
1149 paintWithRenderer(v, paint, rect); | 1141 paintWithRenderer(v, paint, rect); |
1150 } | 1142 } |
1151 | 1143 |
1152 bool | 1144 bool |
1153 Colour3DPlotLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame, | 1145 Colour3DPlotLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame, |
1154 int &resolution, | 1146 int &resolution, |
1155 SnapType snap) const | 1147 SnapType snap) const |
1156 { | 1148 { |
1157 if (!m_model) { | 1149 if (!m_model) { |
1158 return Layer::snapToFeatureFrame(v, frame, resolution, snap); | 1150 return Layer::snapToFeatureFrame(v, frame, resolution, snap); |
1159 } | 1151 } |
1160 | 1152 |
1161 resolution = m_model->getResolution(); | 1153 resolution = m_model->getResolution(); |
1162 sv_frame_t left = (frame / resolution) * resolution; | 1154 sv_frame_t left = (frame / resolution) * resolution; |
1163 sv_frame_t right = left + resolution; | 1155 sv_frame_t right = left + resolution; |
1165 switch (snap) { | 1157 switch (snap) { |
1166 case SnapLeft: frame = left; break; | 1158 case SnapLeft: frame = left; break; |
1167 case SnapRight: frame = right; break; | 1159 case SnapRight: frame = right; break; |
1168 case SnapNearest: | 1160 case SnapNearest: |
1169 case SnapNeighbouring: | 1161 case SnapNeighbouring: |
1170 if (frame - left > right - frame) frame = right; | 1162 if (frame - left > right - frame) frame = right; |
1171 else frame = left; | 1163 else frame = left; |
1172 break; | 1164 break; |
1173 } | 1165 } |
1174 | 1166 |
1175 return true; | 1167 return true; |
1176 } | 1168 } |
1177 | 1169 |
1183 "colourScheme=\"%2\" " | 1175 "colourScheme=\"%2\" " |
1184 "minY=\"%3\" " | 1176 "minY=\"%3\" " |
1185 "maxY=\"%4\" " | 1177 "maxY=\"%4\" " |
1186 "invertVertical=\"%5\" " | 1178 "invertVertical=\"%5\" " |
1187 "opaque=\"%6\" %7") | 1179 "opaque=\"%6\" %7") |
1188 .arg(convertFromColourScale(m_colourScale)) | 1180 .arg(convertFromColourScale(m_colourScale)) |
1189 .arg(m_colourMap) | 1181 .arg(m_colourMap) |
1190 .arg(m_miny) | 1182 .arg(m_miny) |
1191 .arg(m_maxy) | 1183 .arg(m_maxy) |
1192 .arg(m_invertVertical ? "true" : "false") | 1184 .arg(m_invertVertical ? "true" : "false") |
1193 .arg(m_opaque ? "true" : "false") | 1185 .arg(m_opaque ? "true" : "false") |
1200 // normalization in future: write out the column normalization | 1192 // normalization in future: write out the column normalization |
1201 // type separately, and then whether we are normalizing visible | 1193 // type separately, and then whether we are normalizing visible |
1202 // area as well afterwards | 1194 // area as well afterwards |
1203 | 1195 |
1204 s += QString("columnNormalization=\"%1\" ") | 1196 s += QString("columnNormalization=\"%1\" ") |
1205 .arg(m_normalization == ColumnNormalization::Max1 ? "peak" : | 1197 .arg(m_normalization == ColumnNormalization::Range01 ? "peak" : |
1206 m_normalization == ColumnNormalization::Hybrid ? "hybrid" : "none"); | 1198 m_normalization == ColumnNormalization::Hybrid ? "hybrid" : "none"); |
1207 | 1199 |
1208 // Old-style normalization attribute, for backward compatibility | 1200 // Old-style normalization attribute, for backward compatibility |
1209 | 1201 |
1210 s += QString("normalizeColumns=\"%1\" ") | 1202 s += QString("normalizeColumns=\"%1\" ") |
1211 .arg(m_normalization == ColumnNormalization::Max1 ? "true" : "false"); | 1203 .arg(m_normalization == ColumnNormalization::Range01 ? "true" : "false"); |
1212 | 1204 |
1213 // And this applies to both old- and new-style attributes | 1205 // And this applies to both old- and new-style attributes |
1214 | 1206 |
1215 s += QString("normalizeVisibleArea=\"%1\" ") | 1207 s += QString("normalizeVisibleArea=\"%1\" ") |
1216 .arg(m_normalizeVisibleArea ? "true" : "false"); | 1208 .arg(m_normalizeVisibleArea ? "true" : "false"); |
1222 Colour3DPlotLayer::setProperties(const QXmlAttributes &attributes) | 1214 Colour3DPlotLayer::setProperties(const QXmlAttributes &attributes) |
1223 { | 1215 { |
1224 bool ok = false, alsoOk = false; | 1216 bool ok = false, alsoOk = false; |
1225 | 1217 |
1226 ColourScaleType colourScale = convertToColourScale | 1218 ColourScaleType colourScale = convertToColourScale |
1227 (attributes.value("colourScale").toInt(&ok)); | 1219 (attributes.value("scale").toInt(&ok)); |
1228 if (ok) setColourScale(colourScale); | 1220 if (ok) setColourScale(colourScale); |
1229 | 1221 |
1230 int colourMap = attributes.value("colourScheme").toInt(&ok); | 1222 int colourMap = attributes.value("colourScheme").toInt(&ok); |
1231 if (ok) setColourMap(colourMap); | 1223 if (ok) setColourMap(colourMap); |
1232 | 1224 |
1233 BinScale binScale = (BinScale) | 1225 BinScale binScale = (BinScale) |
1234 attributes.value("binScale").toInt(&ok); | 1226 attributes.value("binScale").toInt(&ok); |
1235 if (ok) setBinScale(binScale); | 1227 if (ok) setBinScale(binScale); |
1236 | 1228 |
1237 bool invertVertical = | 1229 bool invertVertical = |
1238 (attributes.value("invertVertical").trimmed() == "true"); | 1230 (attributes.value("invertVertical").trimmed() == "true"); |
1239 setInvertVertical(invertVertical); | 1231 setInvertVertical(invertVertical); |
1260 if (columnNormalization != "") { | 1252 if (columnNormalization != "") { |
1261 | 1253 |
1262 haveNewStyleNormalization = true; | 1254 haveNewStyleNormalization = true; |
1263 | 1255 |
1264 if (columnNormalization == "peak") { | 1256 if (columnNormalization == "peak") { |
1265 setNormalization(ColumnNormalization::Max1); | 1257 setNormalization(ColumnNormalization::Range01); |
1266 } else if (columnNormalization == "hybrid") { | 1258 } else if (columnNormalization == "hybrid") { |
1267 setNormalization(ColumnNormalization::Hybrid); | 1259 setNormalization(ColumnNormalization::Hybrid); |
1268 } else if (columnNormalization == "none") { | 1260 } else if (columnNormalization == "none") { |
1269 setNormalization(ColumnNormalization::None); | 1261 setNormalization(ColumnNormalization::None); |
1270 } else { | 1262 } else { |
1278 setNormalization(ColumnNormalization::None); | 1270 setNormalization(ColumnNormalization::None); |
1279 | 1271 |
1280 bool normalizeColumns = | 1272 bool normalizeColumns = |
1281 (attributes.value("normalizeColumns").trimmed() == "true"); | 1273 (attributes.value("normalizeColumns").trimmed() == "true"); |
1282 if (normalizeColumns) { | 1274 if (normalizeColumns) { |
1283 setNormalization(ColumnNormalization::Max1); | 1275 setNormalization(ColumnNormalization::Range01); |
1284 } | 1276 } |
1285 | 1277 |
1286 bool normalizeHybrid = | 1278 bool normalizeHybrid = |
1287 (attributes.value("normalizeHybrid").trimmed() == "true"); | 1279 (attributes.value("normalizeHybrid").trimmed() == "true"); |
1288 if (normalizeHybrid) { | 1280 if (normalizeHybrid) { |