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) {