annotate layer/Colour3DPlotLayer.cpp @ 1127:9fb8dfd7ce4c spectrogram-minor-refactor

Fix threshold in spectrogram -- it wasn't working in the last release. There is a new protocol for this. Formerly the threshold parameter had a range from -50dB to 0 with the default at -50, and -50 treated internally as "no threshold". However, there was a hardcoded, hidden internal threshold for spectrogram colour mapping at -80dB with anything below this being rounded to zero. Now the threshold parameter has range -81 to -1 with the default at -80, -81 is treated internally as "no threshold", and there is no hidden internal threshold. So the default behaviour is the same as before, an effective -80dB threshold, but it is now possible to change this in both directions. Sessions reloaded from prior versions may look slightly different because, if the session says there should be no threshold, there will now actually be no threshold instead of having the hidden internal one. Still need to do something in the UI to make it apparent that the -81dB setting removes the threshold entirely. This is at least no worse than the previous, also obscured, magic -50dB setting.
author Chris Cannam
date Mon, 01 Aug 2016 16:21:01 +0100
parents 343887ac6766
children ee98d587cd1a
rev   line source
Chris@58 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@59 4 Sonic Visualiser
Chris@59 5 An audio file viewer and annotation editor.
Chris@59 6 Centre for Digital Music, Queen Mary, University of London.
Chris@182 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@0 8
Chris@59 9 This program is free software; you can redistribute it and/or
Chris@59 10 modify it under the terms of the GNU General Public License as
Chris@59 11 published by the Free Software Foundation; either version 2 of the
Chris@59 12 License, or (at your option) any later version. See the file
Chris@59 13 COPYING included with this distribution for more information.
Chris@0 14 */
Chris@0 15
Chris@0 16 #include "Colour3DPlotLayer.h"
Chris@0 17
Chris@0 18 #include "base/Profiler.h"
Chris@197 19 #include "base/LogRange.h"
Chris@444 20 #include "base/RangeMapper.h"
Chris@1077 21
Chris@376 22 #include "ColourMapper.h"
Chris@1077 23 #include "LayerGeometryProvider.h"
Chris@1078 24 #include "PaintAssistant.h"
Chris@1077 25
Chris@1100 26 #include "data/model/Dense3DModelPeakCache.h"
Chris@1100 27
Chris@1077 28 #include "view/ViewManager.h"
Chris@0 29
Chris@0 30 #include <QPainter>
Chris@0 31 #include <QImage>
Chris@0 32 #include <QRect>
Chris@316 33 #include <QTextStream>
Chris@1018 34 #include <QSettings>
Chris@0 35
Chris@0 36 #include <iostream>
Chris@0 37
Chris@0 38 #include <cassert>
Chris@0 39
Chris@545 40 #ifndef __GNUC__
Chris@545 41 #include <alloca.h>
Chris@545 42 #endif
Chris@545 43
Chris@903 44 using std::vector;
Chris@903 45
Chris@353 46 //#define DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 1
Chris@125 47
Chris@0 48
Chris@44 49 Colour3DPlotLayer::Colour3DPlotLayer() :
Chris@0 50 m_model(0),
Chris@1105 51 m_colourScale(ColourScaleType::Linear),
Chris@461 52 m_colourScaleSet(false),
Chris@197 53 m_colourMap(0),
Chris@534 54 m_gain(1.0),
Chris@1103 55 m_binScale(BinScale::Linear),
Chris@1104 56 m_normalization(ColumnNormalization::None),
Chris@1104 57 m_normalizeVisibleArea(false),
Chris@444 58 m_invertVertical(false),
Chris@465 59 m_opaque(false),
Chris@535 60 m_smooth(false),
Chris@805 61 m_peakResolution(256),
Chris@444 62 m_miny(0),
Chris@1100 63 m_maxy(0),
Chris@1101 64 m_synchronous(false),
Chris@1100 65 m_peakCache(0),
Chris@1100 66 m_peakCacheDivisor(8)
Chris@0 67 {
Chris@1018 68 QSettings settings;
Chris@1018 69 settings.beginGroup("Preferences");
Chris@1018 70 setColourMap(settings.value("colour-3d-plot-colour", ColourMapper::Green).toInt());
Chris@1018 71 settings.endGroup();
Chris@0 72 }
Chris@0 73
Chris@0 74 Colour3DPlotLayer::~Colour3DPlotLayer()
Chris@0 75 {
Chris@1107 76 invalidateRenderers();
Chris@1100 77 delete m_peakCache;
Chris@0 78 }
Chris@0 79
Chris@1105 80 ColourScaleType
Chris@1104 81 Colour3DPlotLayer::convertToColourScale(int value)
Chris@1104 82 {
Chris@1104 83 switch (value) {
Chris@1104 84 default:
Chris@1105 85 case 0: return ColourScaleType::Linear;
Chris@1105 86 case 1: return ColourScaleType::Log;
Chris@1105 87 case 2: return ColourScaleType::PlusMinusOne;
Chris@1105 88 case 3: return ColourScaleType::Absolute;
Chris@1104 89 }
Chris@1104 90 }
Chris@1104 91
Chris@1104 92 int
Chris@1105 93 Colour3DPlotLayer::convertFromColourScale(ColourScaleType scale)
Chris@1104 94 {
Chris@1104 95 switch (scale) {
Chris@1105 96 case ColourScaleType::Linear: return 0;
Chris@1105 97 case ColourScaleType::Log: return 1;
Chris@1105 98 case ColourScaleType::PlusMinusOne: return 2;
Chris@1105 99 case ColourScaleType::Absolute: return 3;
Chris@1104 100
Chris@1105 101 case ColourScaleType::Meter:
Chris@1105 102 case ColourScaleType::Phase:
Chris@1104 103 default: return 0;
Chris@1104 104 }
Chris@1104 105 }
Chris@1104 106
Chris@1104 107 std::pair<ColumnNormalization, bool>
Chris@1104 108 Colour3DPlotLayer::convertToColumnNorm(int value)
Chris@1104 109 {
Chris@1104 110 switch (value) {
Chris@1104 111 default:
Chris@1104 112 case 0: return { ColumnNormalization::None, false };
Chris@1104 113 case 1: return { ColumnNormalization::Max1, false };
Chris@1104 114 case 2: return { ColumnNormalization::None, true }; // visible area
Chris@1104 115 case 3: return { ColumnNormalization::Hybrid, false };
Chris@1104 116 }
Chris@1104 117 }
Chris@1104 118
Chris@1104 119 int
Chris@1104 120 Colour3DPlotLayer::convertFromColumnNorm(ColumnNormalization norm, bool visible)
Chris@1104 121 {
Chris@1104 122 if (visible) return 2;
Chris@1104 123 switch (norm) {
Chris@1104 124 case ColumnNormalization::None: return 0;
Chris@1104 125 case ColumnNormalization::Max1: return 1;
Chris@1104 126 case ColumnNormalization::Hybrid: return 3;
Chris@1104 127
Chris@1104 128 case ColumnNormalization::Sum1:
Chris@1104 129 default: return 0;
Chris@1104 130 }
Chris@1104 131 }
Chris@1104 132
Chris@0 133 void
Chris@1101 134 Colour3DPlotLayer::setSynchronousPainting(bool synchronous)
Chris@1101 135 {
Chris@1101 136 m_synchronous = synchronous;
Chris@1101 137 }
Chris@1101 138
Chris@1101 139 void
Chris@0 140 Colour3DPlotLayer::setModel(const DenseThreeDimensionalModel *model)
Chris@0 141 {
Chris@193 142 if (m_model == model) return;
Chris@193 143 const DenseThreeDimensionalModel *oldModel = m_model;
Chris@0 144 m_model = model;
Chris@0 145 if (!m_model || !m_model->isOK()) return;
Chris@0 146
Chris@320 147 connectSignals(m_model);
Chris@0 148
Chris@461 149 connect(m_model, SIGNAL(modelChanged()), this, SLOT(modelChanged()));
Chris@908 150 connect(m_model, SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)),
Chris@908 151 this, SLOT(modelChangedWithin(sv_frame_t, sv_frame_t)));
Chris@0 152
Chris@474 153 m_peakResolution = 256;
Chris@474 154 if (model->getResolution() > 512) {
Chris@474 155 m_peakResolution = 16;
Chris@474 156 } else if (model->getResolution() > 128) {
Chris@474 157 m_peakResolution = 64;
Chris@474 158 } else if (model->getResolution() > 2) {
Chris@474 159 m_peakResolution = 128;
Chris@474 160 }
Chris@1100 161
Chris@1100 162 delete m_peakCache;
Chris@1100 163 m_peakCache = 0;
Chris@1100 164
Chris@1107 165 invalidateRenderers();
Chris@474 166
Chris@0 167 emit modelReplaced();
Chris@193 168 emit sliceableModelReplaced(oldModel, model);
Chris@0 169 }
Chris@0 170
Chris@0 171 void
Chris@0 172 Colour3DPlotLayer::cacheInvalid()
Chris@0 173 {
Chris@1107 174 invalidateRenderers();
Chris@1107 175 }
Chris@1102 176
Chris@1107 177 void
Chris@1107 178 Colour3DPlotLayer::cacheInvalid(sv_frame_t /* startFrame */,
Chris@1107 179 sv_frame_t /* endFrame */)
Chris@1107 180 {
Chris@1107 181 //!!! should do this only if the range is visible
Chris@1107 182 delete m_peakCache;
Chris@1108 183 m_peakCache = 0;
Chris@1108 184
Chris@1107 185 invalidateRenderers();
Chris@1107 186 }
Chris@1107 187
Chris@1107 188 void
Chris@1107 189 Colour3DPlotLayer::invalidateRenderers()
Chris@1107 190 {
Chris@1102 191 for (ViewRendererMap::iterator i = m_renderers.begin();
Chris@1102 192 i != m_renderers.end(); ++i) {
Chris@1102 193 delete i->second;
Chris@1102 194 }
Chris@1102 195 m_renderers.clear();
Chris@0 196 }
Chris@0 197
Chris@1100 198 Dense3DModelPeakCache *
Chris@1100 199 Colour3DPlotLayer::getPeakCache() const
Chris@1100 200 {
Chris@1100 201 if (!m_peakCache) {
Chris@1100 202 m_peakCache = new Dense3DModelPeakCache(m_model, m_peakCacheDivisor);
Chris@1100 203 }
Chris@1100 204 return m_peakCache;
Chris@1100 205 }
Chris@1100 206
Chris@461 207 void
Chris@461 208 Colour3DPlotLayer::modelChanged()
Chris@461 209 {
Chris@1105 210 if (!m_colourScaleSet && m_colourScale == ColourScaleType::Linear) {
Chris@461 211 if (m_model) {
Chris@461 212 if (m_model->shouldUseLogValueScale()) {
Chris@1105 213 setColourScale(ColourScaleType::Log);
Chris@461 214 } else {
Chris@461 215 m_colourScaleSet = true;
Chris@461 216 }
Chris@461 217 }
Chris@461 218 }
Chris@0 219 cacheInvalid();
Chris@0 220 }
Chris@0 221
Chris@461 222 void
Chris@908 223 Colour3DPlotLayer::modelChangedWithin(sv_frame_t startFrame, sv_frame_t endFrame)
Chris@461 224 {
Chris@1105 225 if (!m_colourScaleSet && m_colourScale == ColourScaleType::Linear) {
Chris@461 226 if (m_model && m_model->getWidth() > 50) {
Chris@461 227 if (m_model->shouldUseLogValueScale()) {
Chris@1105 228 setColourScale(ColourScaleType::Log);
Chris@461 229 } else {
Chris@461 230 m_colourScaleSet = true;
Chris@461 231 }
Chris@461 232 }
Chris@461 233 }
Chris@461 234 cacheInvalid(startFrame, endFrame);
Chris@461 235 }
Chris@461 236
Chris@159 237 Layer::PropertyList
Chris@159 238 Colour3DPlotLayer::getProperties() const
Chris@159 239 {
Chris@159 240 PropertyList list;
Chris@197 241 list.push_back("Colour");
Chris@159 242 list.push_back("Colour Scale");
Chris@1104 243 list.push_back("Normalization");
Chris@534 244 list.push_back("Gain");
Chris@531 245 list.push_back("Bin Scale");
Chris@357 246 list.push_back("Invert Vertical Scale");
Chris@465 247 list.push_back("Opaque");
Chris@535 248 list.push_back("Smooth");
Chris@159 249 return list;
Chris@159 250 }
Chris@159 251
Chris@159 252 QString
Chris@159 253 Colour3DPlotLayer::getPropertyLabel(const PropertyName &name) const
Chris@159 254 {
Chris@197 255 if (name == "Colour") return tr("Colour");
Chris@197 256 if (name == "Colour Scale") return tr("Scale");
Chris@1104 257 if (name == "Normalization") return tr("Normalization");
Chris@357 258 if (name == "Invert Vertical Scale") return tr("Invert Vertical Scale");
Chris@534 259 if (name == "Gain") return tr("Gain");
Chris@465 260 if (name == "Opaque") return tr("Always Opaque");
Chris@535 261 if (name == "Smooth") return tr("Smooth");
Chris@531 262 if (name == "Bin Scale") return tr("Bin Scale");
Chris@159 263 return "";
Chris@159 264 }
Chris@159 265
Chris@346 266 QString
Chris@346 267 Colour3DPlotLayer::getPropertyIconName(const PropertyName &name) const
Chris@346 268 {
Chris@357 269 if (name == "Invert Vertical Scale") return "invert-vertical";
Chris@465 270 if (name == "Opaque") return "opaque";
Chris@535 271 if (name == "Smooth") return "smooth";
Chris@346 272 return "";
Chris@346 273 }
Chris@346 274
Chris@159 275 Layer::PropertyType
Chris@159 276 Colour3DPlotLayer::getPropertyType(const PropertyName &name) const
Chris@159 277 {
Chris@534 278 if (name == "Gain") return RangeProperty;
Chris@357 279 if (name == "Invert Vertical Scale") return ToggleProperty;
Chris@465 280 if (name == "Opaque") return ToggleProperty;
Chris@535 281 if (name == "Smooth") return ToggleProperty;
Chris@159 282 return ValueProperty;
Chris@159 283 }
Chris@159 284
Chris@159 285 QString
Chris@159 286 Colour3DPlotLayer::getPropertyGroupName(const PropertyName &name) const
Chris@159 287 {
Chris@1104 288 if (name == "Normalization" ||
Chris@1104 289 name == "Colour Scale" ||
Chris@534 290 name == "Gain") return tr("Scale");
Chris@531 291 if (name == "Bin Scale" ||
Chris@531 292 name == "Invert Vertical Scale") return tr("Bins");
Chris@465 293 if (name == "Opaque" ||
Chris@535 294 name == "Smooth" ||
Chris@465 295 name == "Colour") return tr("Colour");
Chris@159 296 return QString();
Chris@159 297 }
Chris@159 298
Chris@159 299 int
Chris@159 300 Colour3DPlotLayer::getPropertyRangeAndValue(const PropertyName &name,
Chris@216 301 int *min, int *max, int *deflt) const
Chris@159 302 {
Chris@216 303 int val = 0;
Chris@159 304
Chris@216 305 int garbage0, garbage1, garbage2;
Chris@159 306 if (!min) min = &garbage0;
Chris@159 307 if (!max) max = &garbage1;
Chris@216 308 if (!deflt) deflt = &garbage2;
Chris@159 309
Chris@534 310 if (name == "Gain") {
Chris@534 311
Chris@534 312 *min = -50;
Chris@534 313 *max = 50;
Chris@534 314
Chris@902 315 *deflt = int(lrint(log10(1.0) * 20.0));
Chris@534 316 if (*deflt < *min) *deflt = *min;
Chris@534 317 if (*deflt > *max) *deflt = *max;
Chris@534 318
Chris@902 319 val = int(lrint(log10(m_gain) * 20.0));
Chris@534 320 if (val < *min) val = *min;
Chris@534 321 if (val > *max) val = *max;
Chris@534 322
Chris@534 323 } else if (name == "Colour Scale") {
Chris@159 324
Chris@1099 325 // linear, log, +/-1, abs
Chris@159 326 *min = 0;
Chris@509 327 *max = 3;
Chris@1099 328 *deflt = 0;
Chris@159 329
Chris@1104 330 val = convertFromColourScale(m_colourScale);
Chris@159 331
Chris@197 332 } else if (name == "Colour") {
Chris@197 333
Chris@197 334 *min = 0;
Chris@197 335 *max = ColourMapper::getColourMapCount() - 1;
Chris@216 336 *deflt = 0;
Chris@197 337
Chris@216 338 val = m_colourMap;
Chris@197 339
Chris@1099 340 } else if (name == "Normalization") {
Chris@197 341
Chris@1099 342 *min = 0;
Chris@1099 343 *max = 3;
Chris@1104 344 *deflt = 0;
Chris@1104 345
Chris@1104 346 val = convertFromColumnNorm(m_normalization, m_normalizeVisibleArea);
Chris@197 347
Chris@357 348 } else if (name == "Invert Vertical Scale") {
Chris@357 349
Chris@357 350 *deflt = 0;
Chris@357 351 val = (m_invertVertical ? 1 : 0);
Chris@357 352
Chris@531 353 } else if (name == "Bin Scale") {
Chris@531 354
Chris@531 355 *min = 0;
Chris@531 356 *max = 1;
Chris@1103 357 *deflt = int(BinScale::Linear);
Chris@531 358 val = (int)m_binScale;
Chris@531 359
Chris@465 360 } else if (name == "Opaque") {
Chris@465 361
Chris@465 362 *deflt = 0;
Chris@465 363 val = (m_opaque ? 1 : 0);
Chris@465 364
Chris@535 365 } else if (name == "Smooth") {
Chris@535 366
Chris@535 367 *deflt = 0;
Chris@535 368 val = (m_smooth ? 1 : 0);
Chris@535 369
Chris@159 370 } else {
Chris@216 371 val = Layer::getPropertyRangeAndValue(name, min, max, deflt);
Chris@159 372 }
Chris@159 373
Chris@216 374 return val;
Chris@159 375 }
Chris@159 376
Chris@159 377 QString
Chris@159 378 Colour3DPlotLayer::getPropertyValueLabel(const PropertyName &name,
Chris@159 379 int value) const
Chris@159 380 {
Chris@197 381 if (name == "Colour") {
Chris@197 382 return ColourMapper::getColourMapName(value);
Chris@197 383 }
Chris@159 384 if (name == "Colour Scale") {
Chris@159 385 switch (value) {
Chris@159 386 default:
Chris@198 387 case 0: return tr("Linear");
Chris@198 388 case 1: return tr("Log");
Chris@198 389 case 2: return tr("+/-1");
Chris@509 390 case 3: return tr("Absolute");
Chris@159 391 }
Chris@159 392 }
Chris@1099 393 if (name == "Normalization") {
Chris@1099 394 return ""; // icon only
Chris@1099 395 }
Chris@531 396 if (name == "Bin Scale") {
Chris@531 397 switch (value) {
Chris@531 398 default:
Chris@531 399 case 0: return tr("Linear");
Chris@531 400 case 1: return tr("Log");
Chris@531 401 }
Chris@531 402 }
Chris@159 403 return tr("<unknown>");
Chris@159 404 }
Chris@159 405
Chris@1099 406 QString
Chris@1099 407 Colour3DPlotLayer::getPropertyValueIconName(const PropertyName &name,
Chris@1099 408 int value) const
Chris@1099 409 {
Chris@1099 410 if (name == "Normalization") {
Chris@1099 411 switch(value) {
Chris@1099 412 default:
Chris@1099 413 case 0: return "normalise-none";
Chris@1099 414 case 1: return "normalise-columns";
Chris@1099 415 case 2: return "normalise";
Chris@1099 416 case 3: return "normalise-hybrid";
Chris@1099 417 }
Chris@1099 418 }
Chris@1099 419 return "";
Chris@1099 420 }
Chris@1099 421
Chris@534 422 RangeMapper *
Chris@534 423 Colour3DPlotLayer::getNewPropertyRangeMapper(const PropertyName &name) const
Chris@534 424 {
Chris@534 425 if (name == "Gain") {
Chris@534 426 return new LinearRangeMapper(-50, 50, -25, 25, tr("dB"));
Chris@534 427 }
Chris@534 428 return 0;
Chris@534 429 }
Chris@534 430
Chris@159 431 void
Chris@159 432 Colour3DPlotLayer::setProperty(const PropertyName &name, int value)
Chris@159 433 {
Chris@534 434 if (name == "Gain") {
Chris@902 435 setGain(float(pow(10, value/20.0)));
Chris@534 436 } else if (name == "Colour Scale") {
Chris@1104 437 setColourScale(convertToColourScale(value));
Chris@197 438 } else if (name == "Colour") {
Chris@197 439 setColourMap(value);
Chris@357 440 } else if (name == "Invert Vertical Scale") {
Chris@357 441 setInvertVertical(value ? true : false);
Chris@465 442 } else if (name == "Opaque") {
Chris@465 443 setOpaque(value ? true : false);
Chris@535 444 } else if (name == "Smooth") {
Chris@535 445 setSmooth(value ? true : false);
Chris@531 446 } else if (name == "Bin Scale") {
Chris@531 447 switch (value) {
Chris@531 448 default:
Chris@1103 449 case 0: setBinScale(BinScale::Linear); break;
Chris@1103 450 case 1: setBinScale(BinScale::Log); break;
Chris@531 451 }
Chris@1099 452 } else if (name == "Normalization") {
Chris@1104 453 auto n = convertToColumnNorm(value);
Chris@1104 454 setNormalization(n.first);
Chris@1104 455 setNormalizeVisibleArea(n.second);
Chris@159 456 }
Chris@159 457 }
Chris@159 458
Chris@159 459 void
Chris@1105 460 Colour3DPlotLayer::setColourScale(ColourScaleType scale)
Chris@159 461 {
Chris@159 462 if (m_colourScale == scale) return;
Chris@159 463 m_colourScale = scale;
Chris@461 464 m_colourScaleSet = true;
Chris@1107 465 invalidateRenderers();
Chris@159 466 emit layerParametersChanged();
Chris@159 467 }
Chris@159 468
Chris@197 469 void
Chris@197 470 Colour3DPlotLayer::setColourMap(int map)
Chris@197 471 {
Chris@197 472 if (m_colourMap == map) return;
Chris@197 473 m_colourMap = map;
Chris@1107 474 invalidateRenderers();
Chris@197 475 emit layerParametersChanged();
Chris@197 476 }
Chris@197 477
Chris@197 478 void
Chris@534 479 Colour3DPlotLayer::setGain(float gain)
Chris@534 480 {
Chris@534 481 if (m_gain == gain) return;
Chris@534 482 m_gain = gain;
Chris@1107 483 invalidateRenderers();
Chris@534 484 emit layerParametersChanged();
Chris@534 485 }
Chris@534 486
Chris@534 487 float
Chris@534 488 Colour3DPlotLayer::getGain() const
Chris@534 489 {
Chris@534 490 return m_gain;
Chris@534 491 }
Chris@534 492
Chris@534 493 void
Chris@1103 494 Colour3DPlotLayer::setBinScale(BinScale binScale)
Chris@531 495 {
Chris@531 496 if (m_binScale == binScale) return;
Chris@531 497 m_binScale = binScale;
Chris@1107 498 invalidateRenderers();
Chris@531 499 emit layerParametersChanged();
Chris@531 500 }
Chris@531 501
Chris@1103 502 BinScale
Chris@531 503 Colour3DPlotLayer::getBinScale() const
Chris@531 504 {
Chris@531 505 return m_binScale;
Chris@531 506 }
Chris@531 507
Chris@531 508 void
Chris@1104 509 Colour3DPlotLayer::setNormalization(ColumnNormalization n)
Chris@197 510 {
Chris@1099 511 if (m_normalization == n) return;
Chris@1099 512
Chris@1099 513 m_normalization = n;
Chris@1107 514 invalidateRenderers();
Chris@1099 515
Chris@197 516 emit layerParametersChanged();
Chris@197 517 }
Chris@197 518
Chris@1104 519 ColumnNormalization
Chris@1099 520 Colour3DPlotLayer::getNormalization() const
Chris@197 521 {
Chris@1099 522 return m_normalization;
Chris@197 523 }
Chris@197 524
Chris@357 525 void
Chris@1104 526 Colour3DPlotLayer::setNormalizeVisibleArea(bool n)
Chris@1104 527 {
Chris@1104 528 if (m_normalizeVisibleArea == n) return;
Chris@1104 529
Chris@1104 530 m_normalizeVisibleArea = n;
Chris@1107 531 invalidateRenderers();
Chris@1104 532
Chris@1104 533 emit layerParametersChanged();
Chris@1104 534 }
Chris@1104 535
Chris@1104 536 bool
Chris@1104 537 Colour3DPlotLayer::getNormalizeVisibleArea() const
Chris@1104 538 {
Chris@1104 539 return m_normalizeVisibleArea;
Chris@1104 540 }
Chris@1104 541
Chris@1104 542 void
Chris@357 543 Colour3DPlotLayer::setInvertVertical(bool n)
Chris@357 544 {
Chris@357 545 if (m_invertVertical == n) return;
Chris@357 546 m_invertVertical = n;
Chris@1107 547 invalidateRenderers();
Chris@357 548 emit layerParametersChanged();
Chris@357 549 }
Chris@357 550
Chris@465 551 void
Chris@465 552 Colour3DPlotLayer::setOpaque(bool n)
Chris@465 553 {
Chris@465 554 if (m_opaque == n) return;
Chris@465 555 m_opaque = n;
Chris@1107 556 invalidateRenderers();
Chris@465 557 emit layerParametersChanged();
Chris@465 558 }
Chris@465 559
Chris@535 560 void
Chris@535 561 Colour3DPlotLayer::setSmooth(bool n)
Chris@535 562 {
Chris@535 563 if (m_smooth == n) return;
Chris@535 564 m_smooth = n;
Chris@1107 565 invalidateRenderers();
Chris@535 566 emit layerParametersChanged();
Chris@535 567 }
Chris@535 568
Chris@357 569 bool
Chris@357 570 Colour3DPlotLayer::getInvertVertical() const
Chris@357 571 {
Chris@357 572 return m_invertVertical;
Chris@357 573 }
Chris@357 574
Chris@25 575 bool
Chris@465 576 Colour3DPlotLayer::getOpaque() const
Chris@465 577 {
Chris@465 578 return m_opaque;
Chris@465 579 }
Chris@465 580
Chris@535 581 bool
Chris@535 582 Colour3DPlotLayer::getSmooth() const
Chris@535 583 {
Chris@535 584 return m_smooth;
Chris@535 585 }
Chris@535 586
Chris@475 587 void
Chris@916 588 Colour3DPlotLayer::setLayerDormant(const LayerGeometryProvider *v, bool dormant)
Chris@475 589 {
Chris@475 590 if (dormant) {
Chris@475 591
Chris@475 592 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@812 593 cerr << "Colour3DPlotLayer::setLayerDormant(" << dormant << ")"
Chris@585 594 << endl;
Chris@475 595 #endif
Chris@475 596
Chris@475 597 if (isLayerDormant(v)) {
Chris@475 598 return;
Chris@475 599 }
Chris@475 600
Chris@475 601 Layer::setLayerDormant(v, true);
Chris@475 602
Chris@475 603 cacheInvalid();
Chris@475 604
Chris@475 605 } else {
Chris@475 606
Chris@475 607 Layer::setLayerDormant(v, false);
Chris@475 608 }
Chris@475 609 }
Chris@475 610
Chris@465 611 bool
Chris@1121 612 Colour3DPlotLayer::isLayerScrollable(const LayerGeometryProvider */* v */) const
Chris@25 613 {
Chris@1104 614 if (m_normalizeVisibleArea) {
Chris@812 615 return false;
Chris@812 616 }
Chris@1121 617 //!!! ah hang on, if we're potentially rendering incrementally
Chris@1121 618 //!!! they we can't be scrollable
Chris@1121 619 return false;
Chris@1121 620 // if (getRenderer(v)->willRenderOpaque(v)) {
Chris@1121 621 // return true;
Chris@1121 622 // }
Chris@1121 623 // QPoint discard;
Chris@1121 624 // return !v->shouldIlluminateLocalFeatures(this, discard);
Chris@25 625 }
Chris@25 626
Chris@444 627 bool
Chris@904 628 Colour3DPlotLayer::getValueExtents(double &min, double &max,
Chris@444 629 bool &logarithmic, QString &unit) const
Chris@444 630 {
Chris@444 631 if (!m_model) return false;
Chris@444 632
Chris@444 633 min = 0;
Chris@904 634 max = double(m_model->getHeight());
Chris@444 635
Chris@444 636 logarithmic = false;
Chris@444 637 unit = "";
Chris@444 638
Chris@444 639 return true;
Chris@444 640 }
Chris@444 641
Chris@444 642 bool
Chris@904 643 Colour3DPlotLayer::getDisplayExtents(double &min, double &max) const
Chris@444 644 {
Chris@444 645 if (!m_model) return false;
Chris@444 646
Chris@904 647 double hmax = double(m_model->getHeight());
Chris@902 648
Chris@904 649 min = m_miny;
Chris@904 650 max = m_maxy;
Chris@444 651 if (max <= min) {
Chris@444 652 min = 0;
Chris@902 653 max = hmax;
Chris@444 654 }
Chris@444 655 if (min < 0) min = 0;
Chris@902 656 if (max > hmax) max = hmax;
Chris@444 657
Chris@444 658 return true;
Chris@444 659 }
Chris@444 660
Chris@444 661 bool
Chris@904 662 Colour3DPlotLayer::setDisplayExtents(double min, double max)
Chris@444 663 {
Chris@444 664 if (!m_model) return false;
Chris@444 665
Chris@904 666 m_miny = int(lrint(min));
Chris@904 667 m_maxy = int(lrint(max));
Chris@444 668
Chris@444 669 emit layerParametersChanged();
Chris@444 670 return true;
Chris@444 671 }
Chris@444 672
Chris@725 673 bool
Chris@916 674 Colour3DPlotLayer::getYScaleValue(const LayerGeometryProvider *, int,
Chris@904 675 double &, QString &) const
Chris@725 676 {
Chris@725 677 return false;//!!!
Chris@725 678 }
Chris@725 679
Chris@444 680 int
Chris@444 681 Colour3DPlotLayer::getVerticalZoomSteps(int &defaultStep) const
Chris@444 682 {
Chris@444 683 if (!m_model) return 0;
Chris@444 684
Chris@444 685 defaultStep = 0;
Chris@444 686 int h = m_model->getHeight();
Chris@444 687 return h;
Chris@444 688 }
Chris@444 689
Chris@444 690 int
Chris@444 691 Colour3DPlotLayer::getCurrentVerticalZoomStep() const
Chris@444 692 {
Chris@444 693 if (!m_model) return 0;
Chris@444 694
Chris@904 695 double min, max;
Chris@444 696 getDisplayExtents(min, max);
Chris@904 697 return m_model->getHeight() - int(lrint(max - min));
Chris@444 698 }
Chris@444 699
Chris@444 700 void
Chris@444 701 Colour3DPlotLayer::setVerticalZoomStep(int step)
Chris@444 702 {
Chris@444 703 if (!m_model) return;
Chris@444 704
Chris@587 705 // SVDEBUG << "Colour3DPlotLayer::setVerticalZoomStep(" <<step <<"): before: miny = " << m_miny << ", maxy = " << m_maxy << endl;
Chris@444 706
Chris@444 707 int dist = m_model->getHeight() - step;
Chris@444 708 if (dist < 1) dist = 1;
Chris@904 709 double centre = m_miny + (m_maxy - m_miny) / 2.0;
Chris@904 710 m_miny = int(lrint(centre - dist/2.0));
Chris@444 711 if (m_miny < 0) m_miny = 0;
Chris@444 712 m_maxy = m_miny + dist;
Chris@444 713 if (m_maxy > m_model->getHeight()) m_maxy = m_model->getHeight();
Chris@444 714
Chris@587 715 // SVDEBUG << "Colour3DPlotLayer::setVerticalZoomStep(" <<step <<"): after: miny = " << m_miny << ", maxy = " << m_maxy << endl;
Chris@444 716
Chris@444 717 emit layerParametersChanged();
Chris@444 718 }
Chris@444 719
Chris@444 720 RangeMapper *
Chris@444 721 Colour3DPlotLayer::getNewVerticalZoomRangeMapper() const
Chris@444 722 {
Chris@444 723 if (!m_model) return 0;
Chris@444 724
Chris@444 725 return new LinearRangeMapper(0, m_model->getHeight(),
Chris@444 726 0, m_model->getHeight(), "");
Chris@444 727 }
Chris@444 728
Chris@904 729 double
Chris@1113 730 Colour3DPlotLayer::getYForBin(const LayerGeometryProvider *v, double bin) const
Chris@532 731 {
Chris@904 732 double y = bin;
Chris@532 733 if (!m_model) return y;
Chris@904 734 double mn = 0, mx = m_model->getHeight();
Chris@532 735 getDisplayExtents(mn, mx);
Chris@916 736 double h = v->getPaintHeight();
Chris@1103 737 if (m_binScale == BinScale::Linear) {
Chris@532 738 y = h - (((bin - mn) * h) / (mx - mn));
Chris@532 739 } else {
Chris@904 740 double logmin = mn + 1, logmax = mx + 1;
Chris@532 741 LogRange::mapRange(logmin, logmax);
Chris@532 742 y = h - (((LogRange::map(bin + 1) - logmin) * h) / (logmax - logmin));
Chris@532 743 }
Chris@532 744 return y;
Chris@532 745 }
Chris@532 746
Chris@904 747 double
Chris@1113 748 Colour3DPlotLayer::getBinForY(const LayerGeometryProvider *v, double y) const
Chris@532 749 {
Chris@904 750 double bin = y;
Chris@532 751 if (!m_model) return bin;
Chris@904 752 double mn = 0, mx = m_model->getHeight();
Chris@532 753 getDisplayExtents(mn, mx);
Chris@916 754 double h = v->getPaintHeight();
Chris@1103 755 if (m_binScale == BinScale::Linear) {
Chris@532 756 bin = mn + ((h - y) * (mx - mn)) / h;
Chris@532 757 } else {
Chris@904 758 double logmin = mn + 1, logmax = mx + 1;
Chris@532 759 LogRange::mapRange(logmin, logmax);
Chris@532 760 bin = LogRange::unmap(logmin + ((h - y) * (logmax - logmin)) / h) - 1;
Chris@532 761 }
Chris@532 762 return bin;
Chris@532 763 }
Chris@532 764
Chris@25 765 QString
Chris@916 766 Colour3DPlotLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &pos) const
Chris@25 767 {
Chris@25 768 if (!m_model) return "";
Chris@25 769
Chris@25 770 int x = pos.x();
Chris@25 771 int y = pos.y();
Chris@25 772
Chris@902 773 sv_frame_t modelStart = m_model->getStartFrame();
Chris@805 774 int modelResolution = m_model->getResolution();
Chris@25 775
Chris@902 776 double srRatio =
Chris@902 777 v->getViewManager()->getMainModelSampleRate() /
Chris@902 778 m_model->getSampleRate();
Chris@159 779
Chris@902 780 int sx0 = int((double(v->getFrameForX(x)) / srRatio - double(modelStart)) /
Chris@812 781 modelResolution);
Chris@25 782
Chris@160 783 int f0 = sx0 * modelResolution;
Chris@160 784 int f1 = f0 + modelResolution;
Chris@160 785
Chris@447 786 int sh = m_model->getHeight();
Chris@447 787
Chris@447 788 int symin = m_miny;
Chris@447 789 int symax = m_maxy;
Chris@447 790 if (symax <= symin) {
Chris@447 791 symin = 0;
Chris@447 792 symax = sh;
Chris@447 793 }
Chris@447 794 if (symin < 0) symin = 0;
Chris@447 795 if (symax > sh) symax = sh;
Chris@447 796
Chris@916 797 // double binHeight = double(v->getPaintHeight()) / (symax - symin);
Chris@916 798 // int sy = int((v->getPaintHeight() - y) / binHeight) + symin;
Chris@534 799
Chris@903 800 int sy = getIBinForY(v, y);
Chris@25 801
Chris@812 802 if (sy < 0 || sy >= m_model->getHeight()) {
Chris@812 803 return "";
Chris@812 804 }
Chris@812 805
Chris@357 806 if (m_invertVertical) sy = m_model->getHeight() - sy - 1;
Chris@357 807
Chris@160 808 float value = m_model->getValueAt(sx0, sy);
Chris@159 809
Chris@682 810 // cerr << "bin value (" << sx0 << "," << sy << ") is " << value << endl;
Chris@25 811
Chris@25 812 QString binName = m_model->getBinName(sy);
Chris@25 813 if (binName == "") binName = QString("[%1]").arg(sy + 1);
Chris@25 814 else binName = QString("%1 [%2]").arg(binName).arg(sy + 1);
Chris@25 815
Chris@25 816 QString text = tr("Time:\t%1 - %2\nBin:\t%3\nValue:\t%4")
Chris@160 817 .arg(RealTime::frame2RealTime(f0, m_model->getSampleRate())
Chris@25 818 .toText(true).c_str())
Chris@160 819 .arg(RealTime::frame2RealTime(f1, m_model->getSampleRate())
Chris@25 820 .toText(true).c_str())
Chris@25 821 .arg(binName)
Chris@25 822 .arg(value);
Chris@25 823
Chris@25 824 return text;
Chris@25 825 }
Chris@25 826
Chris@25 827 int
Chris@969 828 Colour3DPlotLayer::getColourScaleWidth(QPainter &p) const
Chris@159 829 {
Chris@969 830 // Font is rotated
Chris@969 831 int cw = p.fontMetrics().height();
Chris@159 832 return cw;
Chris@159 833 }
Chris@159 834
Chris@159 835 int
Chris@916 836 Colour3DPlotLayer::getVerticalScaleWidth(LayerGeometryProvider *, bool, QPainter &paint) const
Chris@25 837 {
Chris@25 838 if (!m_model) return 0;
Chris@25 839
Chris@160 840 QString sampleText = QString("[%1]").arg(m_model->getHeight());
Chris@25 841 int tw = paint.fontMetrics().width(sampleText);
Chris@98 842 bool another = false;
Chris@25 843
Chris@805 844 for (int i = 0; i < m_model->getHeight(); ++i) {
Chris@25 845 if (m_model->getBinName(i).length() > sampleText.length()) {
Chris@25 846 sampleText = m_model->getBinName(i);
Chris@98 847 another = true;
Chris@25 848 }
Chris@25 849 }
Chris@98 850 if (another) {
Chris@25 851 tw = std::max(tw, paint.fontMetrics().width(sampleText));
Chris@25 852 }
Chris@25 853
Chris@159 854 return tw + 13 + getColourScaleWidth(paint);
Chris@25 855 }
Chris@25 856
Chris@25 857 void
Chris@916 858 Colour3DPlotLayer::paintVerticalScale(LayerGeometryProvider *v, bool, QPainter &paint, QRect rect) const
Chris@25 859 {
Chris@25 860 if (!m_model) return;
Chris@25 861
Chris@25 862 int h = rect.height(), w = rect.width();
Chris@25 863
Chris@159 864 int cw = getColourScaleWidth(paint);
Chris@159 865
Chris@159 866 int ch = h - 20;
Chris@1107 867 if (ch > 20) {
Chris@159 868
Chris@904 869 double min = m_model->getMinimumLevel();
Chris@904 870 double max = m_model->getMaximumLevel();
Chris@447 871
Chris@904 872 double mmin = min;
Chris@904 873 double mmax = max;
Chris@447 874
Chris@1105 875 if (m_colourScale == ColourScaleType::Log) {
Chris@447 876 LogRange::mapRange(mmin, mmax);
Chris@1105 877 } else if (m_colourScale == ColourScaleType::PlusMinusOne) {
Chris@447 878 mmin = -1.f;
Chris@447 879 mmax = 1.f;
Chris@1105 880 } else if (m_colourScale == ColourScaleType::Absolute) {
Chris@509 881 if (mmin < 0) {
Chris@904 882 if (fabs(mmin) > fabs(mmax)) mmax = fabs(mmin);
Chris@904 883 else mmax = fabs(mmax);
Chris@509 884 mmin = 0;
Chris@509 885 } else {
Chris@904 886 mmin = fabs(mmin);
Chris@904 887 mmax = fabs(mmax);
Chris@509 888 }
Chris@447 889 }
Chris@447 890
Chris@902 891 if (max == min) max = min + 1.f;
Chris@902 892 if (mmax == mmin) mmax = mmin + 1.f;
Chris@447 893
Chris@287 894 paint.setPen(v->getForeground());
Chris@447 895 paint.drawRect(4, 10, cw - 8, ch+1);
Chris@159 896
Chris@446 897 for (int y = 0; y < ch; ++y) {
Chris@904 898 double value = ((max - min) * (double(ch-y) - 1.0)) / double(ch) + min;
Chris@1105 899 if (m_colourScale == ColourScaleType::Log) {
Chris@447 900 value = LogRange::map(value);
Chris@447 901 }
Chris@447 902 int pixel = int(((value - mmin) * 256) / (mmax - mmin));
Chris@465 903 if (pixel >= 0 && pixel < 256) {
Chris@1107 904 //!!! replace this
Chris@1107 905 // QRgb c = m_cache->color(pixel);
Chris@1107 906 // paint.setPen(QColor(qRed(c), qGreen(c), qBlue(c)));
Chris@465 907 paint.drawLine(5, 11 + y, cw - 5, 11 + y);
Chris@465 908 } else {
Chris@682 909 cerr << "WARNING: Colour3DPlotLayer::paintVerticalScale: value " << value << ", mmin " << mmin << ", mmax " << mmax << " leads to invalid pixel " << pixel << endl;
Chris@465 910 }
Chris@159 911 }
Chris@446 912
Chris@446 913 QString minstr = QString("%1").arg(min);
Chris@446 914 QString maxstr = QString("%1").arg(max);
Chris@446 915
Chris@446 916 paint.save();
Chris@446 917
Chris@446 918 QFont font = paint.font();
Chris@1053 919 if (font.pixelSize() > 0) {
Chris@1053 920 int newSize = int(font.pixelSize() * 0.65);
Chris@1053 921 if (newSize < 6) newSize = 6;
Chris@1053 922 font.setPixelSize(newSize);
Chris@1053 923 paint.setFont(font);
Chris@1053 924 }
Chris@446 925
Chris@446 926 int msw = paint.fontMetrics().width(maxstr);
Chris@446 927
Chris@446 928 QMatrix m;
Chris@446 929 m.translate(cw - 6, ch + 10);
Chris@446 930 m.rotate(-90);
Chris@446 931
Chris@446 932 paint.setWorldMatrix(m);
Chris@446 933
Chris@1078 934 PaintAssistant::drawVisibleText(v, paint, 2, 0, minstr, PaintAssistant::OutlinedText);
Chris@446 935
Chris@446 936 m.translate(ch - msw - 2, 0);
Chris@446 937 paint.setWorldMatrix(m);
Chris@446 938
Chris@1078 939 PaintAssistant::drawVisibleText(v, paint, 0, 0, maxstr, PaintAssistant::OutlinedText);
Chris@446 940
Chris@446 941 paint.restore();
Chris@159 942 }
Chris@159 943
Chris@287 944 paint.setPen(v->getForeground());
Chris@159 945
Chris@445 946 int sh = m_model->getHeight();
Chris@445 947
Chris@445 948 int symin = m_miny;
Chris@445 949 int symax = m_maxy;
Chris@445 950 if (symax <= symin) {
Chris@445 951 symin = 0;
Chris@445 952 symax = sh;
Chris@445 953 }
Chris@445 954 if (symin < 0) symin = 0;
Chris@445 955 if (symax > sh) symax = sh;
Chris@445 956
Chris@532 957 paint.save();
Chris@456 958
Chris@533 959 int py = h;
Chris@25 960
Chris@969 961 int defaultFontHeight = paint.fontMetrics().height();
Chris@969 962
Chris@805 963 for (int i = symin; i <= symax; ++i) {
Chris@98 964
Chris@532 965 int y0;
Chris@534 966
Chris@903 967 y0 = getIYForBin(v, i);
Chris@532 968 int h = py - y0;
Chris@532 969
Chris@532 970 if (i > symin) {
Chris@532 971 if (paint.fontMetrics().height() >= h) {
Chris@969 972 if (h >= defaultFontHeight * 0.8) {
Chris@532 973 QFont tf = paint.font();
Chris@973 974 tf.setPixelSize(int(h * 0.8));
Chris@532 975 paint.setFont(tf);
Chris@532 976 } else {
Chris@532 977 continue;
Chris@532 978 }
Chris@532 979 }
Chris@532 980 }
Chris@25 981
Chris@532 982 py = y0;
Chris@532 983
Chris@534 984 if (i < symax) {
Chris@534 985 paint.drawLine(cw, y0, w, y0);
Chris@534 986 }
Chris@25 987
Chris@532 988 if (i > symin) {
Chris@534 989
Chris@805 990 int idx = i - 1;
Chris@534 991 if (m_invertVertical) idx = m_model->getHeight() - idx - 1;
Chris@534 992
Chris@534 993 QString text = m_model->getBinName(idx);
Chris@534 994 if (text == "") text = QString("[%1]").arg(idx + 1);
Chris@534 995
Chris@534 996 int ty = y0 + (h/2) - (paint.fontMetrics().height()/2) +
Chris@534 997 paint.fontMetrics().ascent() + 1;
Chris@534 998
Chris@534 999 paint.drawText(cw + 5, ty, text);
Chris@457 1000 }
Chris@25 1001 }
Chris@456 1002
Chris@456 1003 paint.restore();
Chris@25 1004 }
Chris@25 1005
Chris@467 1006 DenseThreeDimensionalModel::Column
Chris@805 1007 Colour3DPlotLayer::getColumn(int col) const
Chris@197 1008 {
Chris@812 1009 Profiler profiler("Colour3DPlotLayer::getColumn");
Chris@812 1010
Chris@467 1011 DenseThreeDimensionalModel::Column values = m_model->getColumn(col);
Chris@1019 1012 values.resize(m_model->getHeight(), 0.f);
Chris@1104 1013 if (m_normalization != ColumnNormalization::Max1 &&
Chris@1104 1014 m_normalization != ColumnNormalization::Hybrid) {
Chris@1099 1015 return values;
Chris@1099 1016 }
Chris@461 1017
Chris@904 1018 double colMax = 0.f, colMin = 0.f;
Chris@904 1019 double min = 0.f, max = 0.f;
Chris@197 1020
Chris@1019 1021 int nv = int(values.size());
Chris@1019 1022
Chris@461 1023 min = m_model->getMinimumLevel();
Chris@461 1024 max = m_model->getMaximumLevel();
Chris@461 1025
Chris@1019 1026 for (int y = 0; y < nv; ++y) {
Chris@467 1027 if (y == 0 || values.at(y) > colMax) colMax = values.at(y);
Chris@467 1028 if (y == 0 || values.at(y) < colMin) colMin = values.at(y);
Chris@197 1029 }
Chris@461 1030 if (colMin == colMax) colMax = colMin + 1;
Chris@197 1031
Chris@1019 1032 for (int y = 0; y < nv; ++y) {
Chris@461 1033
Chris@904 1034 double value = values.at(y);
Chris@904 1035 double norm = (value - colMin) / (colMax - colMin);
Chris@904 1036 double newvalue = min + (max - min) * norm;
Chris@197 1037
Chris@904 1038 if (value != newvalue) values[y] = float(newvalue);
Chris@468 1039 }
Chris@468 1040
Chris@1104 1041 if (m_normalization == ColumnNormalization::Hybrid
Chris@1099 1042 && (colMax > 0.0)) {
Chris@904 1043 double logmax = log10(colMax);
Chris@1019 1044 for (int y = 0; y < nv; ++y) {
Chris@904 1045 values[y] = float(values[y] * logmax);
Chris@719 1046 }
Chris@719 1047 }
Chris@719 1048
Chris@468 1049 return values;
Chris@197 1050 }
Chris@1114 1051
Chris@1100 1052 Colour3DPlotRenderer *
Chris@1113 1053 Colour3DPlotLayer::getRenderer(const LayerGeometryProvider *v) const
Chris@1100 1054 {
Chris@1100 1055 if (m_renderers.find(v->getId()) == m_renderers.end()) {
Chris@1100 1056
Chris@1100 1057 Colour3DPlotRenderer::Sources sources;
Chris@1100 1058 sources.verticalBinLayer = this;
Chris@1100 1059 sources.fft = 0;
Chris@1100 1060 sources.source = m_model;
Chris@1100 1061 sources.peaks = getPeakCache();
Chris@1100 1062
Chris@1100 1063 ColourScale::Parameters cparams;
Chris@1100 1064 cparams.colourMap = m_colourMap;
Chris@1100 1065 cparams.scale = m_colourScale;
Chris@1100 1066 cparams.gain = m_gain;
Chris@1100 1067
Chris@1100 1068 Colour3DPlotRenderer::Parameters params;
Chris@1100 1069 params.colourScale = ColourScale(cparams);
Chris@1100 1070 params.normalization = m_normalization;
Chris@1100 1071 params.binScale = m_binScale;
Chris@1100 1072 params.alwaysOpaque = m_opaque;
Chris@1100 1073 params.invertVertical = m_invertVertical;
Chris@1100 1074 params.interpolate = m_smooth;
Chris@1100 1075
Chris@1100 1076 m_renderers[v->getId()] = new Colour3DPlotRenderer(sources, params);
Chris@1100 1077 }
Chris@1100 1078
Chris@1100 1079 return m_renderers[v->getId()];
Chris@1100 1080 }
Chris@1100 1081
Chris@197 1082 void
Chris@1107 1083 Colour3DPlotLayer::paintWithRenderer(LayerGeometryProvider *v,
Chris@1107 1084 QPainter &paint, QRect rect) const
Chris@1101 1085 {
Chris@1101 1086 Colour3DPlotRenderer *renderer = getRenderer(v);
Chris@1101 1087
Chris@1121 1088 Colour3DPlotRenderer::RenderResult result;
Chris@1123 1089 MagnitudeRange magRange;
Chris@1123 1090 int viewId = v->getId();
Chris@1123 1091
Chris@1123 1092 if (!renderer->geometryChanged(v)) {
Chris@1123 1093 magRange = m_viewMags[viewId];
Chris@1123 1094 }
Chris@1121 1095
Chris@1101 1096 if (m_synchronous) {
Chris@1121 1097
Chris@1121 1098 result = renderer->render(v, paint, rect);
Chris@1121 1099
Chris@1121 1100 } else {
Chris@1121 1101
Chris@1121 1102 result = renderer->renderTimeConstrained(v, paint, rect);
Chris@1121 1103
Chris@1121 1104 QRect uncached = renderer->getLargestUncachedRect(v);
Chris@1121 1105 if (uncached.width() > 0) {
Chris@1121 1106 v->updatePaintRect(uncached);
Chris@1121 1107 }
Chris@1101 1108 }
Chris@1121 1109
Chris@1123 1110 magRange.sample(result.range);
Chris@1101 1111
Chris@1123 1112 if (magRange.isSet()) {
Chris@1123 1113 if (!(m_viewMags[viewId] == magRange)) {
Chris@1123 1114 m_viewMags[viewId] = magRange;
Chris@1123 1115 //!!! now need to do the normalise-visible thing
Chris@1123 1116 }
Chris@1123 1117 }
Chris@1101 1118
Chris@1121 1119 cerr << "mag range in this view: "
Chris@1121 1120 << m_viewMags[v->getId()].getMin()
Chris@1121 1121 << " -> "
Chris@1121 1122 << m_viewMags[v->getId()].getMax()
Chris@1121 1123 << endl;
Chris@1121 1124
Chris@1101 1125 }
Chris@1101 1126
Chris@1101 1127 void
Chris@916 1128 Colour3DPlotLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const
Chris@0 1129 {
Chris@514 1130 /*
Chris@443 1131 if (m_model) {
Chris@587 1132 SVDEBUG << "Colour3DPlotLayer::paint: model says shouldUseLogValueScale = " << m_model->shouldUseLogValueScale() << endl;
Chris@443 1133 }
Chris@514 1134 */
Chris@466 1135 Profiler profiler("Colour3DPlotLayer::paint");
Chris@125 1136 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@812 1137 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;
Chris@125 1138 #endif
Chris@0 1139
Chris@0 1140 int completion = 0;
Chris@0 1141 if (!m_model || !m_model->isOK() || !m_model->isReady(&completion)) {
Chris@0 1142 if (completion > 0) {
Chris@916 1143 paint.fillRect(0, 10, v->getPaintWidth() * completion / 100,
Chris@0 1144 10, QColor(120, 120, 120));
Chris@0 1145 }
Chris@0 1146 return;
Chris@0 1147 }
Chris@0 1148
Chris@1053 1149 if (m_model->getWidth() == 0) {
Chris@1053 1150 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@1053 1151 cerr << "Colour3DPlotLayer::paint(): model width == 0, "
Chris@1053 1152 << "nothing to paint (yet)" << endl;
Chris@1053 1153 #endif
Chris@1053 1154 return;
Chris@1053 1155 }
Chris@1101 1156
Chris@1101 1157 //!!!???
Chris@1053 1158
Chris@1104 1159 if (m_normalizeVisibleArea) {
Chris@1099 1160 rect = v->getPaintRect();
Chris@1099 1161 }
Chris@197 1162
Chris@1107 1163 //!!! why is the setLayerDormant(false) found here in
Chris@1107 1164 //!!! SpectrogramLayer not present in Colour3DPlotLayer?
Chris@1107 1165 //!!! unnecessary? vestigial? forgotten?
Chris@1107 1166
Chris@1107 1167 paintWithRenderer(v, paint, rect);
Chris@1107 1168 }
Chris@1107 1169
Chris@28 1170 bool
Chris@916 1171 Colour3DPlotLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame,
Chris@805 1172 int &resolution,
Chris@28 1173 SnapType snap) const
Chris@24 1174 {
Chris@24 1175 if (!m_model) {
Chris@44 1176 return Layer::snapToFeatureFrame(v, frame, resolution, snap);
Chris@24 1177 }
Chris@24 1178
Chris@130 1179 resolution = m_model->getResolution();
Chris@904 1180 sv_frame_t left = (frame / resolution) * resolution;
Chris@904 1181 sv_frame_t right = left + resolution;
Chris@28 1182
Chris@28 1183 switch (snap) {
Chris@28 1184 case SnapLeft: frame = left; break;
Chris@28 1185 case SnapRight: frame = right; break;
Chris@28 1186 case SnapNearest:
Chris@28 1187 case SnapNeighbouring:
Chris@28 1188 if (frame - left > right - frame) frame = right;
Chris@28 1189 else frame = left;
Chris@28 1190 break;
Chris@28 1191 }
Chris@24 1192
Chris@28 1193 return true;
Chris@24 1194 }
Chris@24 1195
Chris@316 1196 void
Chris@316 1197 Colour3DPlotLayer::toXml(QTextStream &stream,
Chris@316 1198 QString indent, QString extraAttributes) const
Chris@197 1199 {
Chris@316 1200 QString s = QString("scale=\"%1\" "
Chris@316 1201 "colourScheme=\"%2\" "
Chris@1099 1202 "minY=\"%3\" "
Chris@1099 1203 "maxY=\"%4\" "
Chris@1099 1204 "invertVertical=\"%5\" "
Chris@1099 1205 "opaque=\"%6\" %7")
Chris@1104 1206 .arg(convertFromColourScale(m_colourScale))
Chris@197 1207 .arg(m_colourMap)
Chris@445 1208 .arg(m_miny)
Chris@465 1209 .arg(m_maxy)
Chris@465 1210 .arg(m_invertVertical ? "true" : "false")
Chris@534 1211 .arg(m_opaque ? "true" : "false")
Chris@536 1212 .arg(QString("binScale=\"%1\" smooth=\"%2\" gain=\"%3\" ")
Chris@1103 1213 .arg(int(m_binScale))
Chris@536 1214 .arg(m_smooth ? "true" : "false")
Chris@536 1215 .arg(m_gain));
Chris@535 1216
Chris@1099 1217 // New-style normalization attributes, allowing for more types of
Chris@1099 1218 // normalization in future: write out the column normalization
Chris@1099 1219 // type separately, and then whether we are normalizing visible
Chris@1099 1220 // area as well afterwards
Chris@1099 1221
Chris@1099 1222 s += QString("columnNormalization=\"%1\" ")
Chris@1104 1223 .arg(m_normalization == ColumnNormalization::Max1 ? "peak" :
Chris@1104 1224 m_normalization == ColumnNormalization::Hybrid ? "hybrid" : "none");
Chris@1099 1225
Chris@1099 1226 // Old-style normalization attribute, for backward compatibility
Chris@1099 1227
Chris@1099 1228 s += QString("normalizeColumns=\"%1\" ")
Chris@1104 1229 .arg(m_normalization == ColumnNormalization::Max1 ? "true" : "false");
Chris@1099 1230
Chris@1099 1231 // And this applies to both old- and new-style attributes
Chris@1099 1232
Chris@1099 1233 s += QString("normalizeVisibleArea=\"%1\" ")
Chris@1104 1234 .arg(m_normalizeVisibleArea ? "true" : "false");
Chris@1099 1235
Chris@316 1236 Layer::toXml(stream, indent, extraAttributes + " " + s);
Chris@197 1237 }
Chris@197 1238
Chris@197 1239 void
Chris@197 1240 Colour3DPlotLayer::setProperties(const QXmlAttributes &attributes)
Chris@197 1241 {
Chris@445 1242 bool ok = false, alsoOk = false;
Chris@197 1243
Chris@1105 1244 ColourScaleType colourScale = convertToColourScale
Chris@1099 1245 (attributes.value("colourScale").toInt(&ok));
Chris@1099 1246 if (ok) setColourScale(colourScale);
Chris@197 1247
Chris@197 1248 int colourMap = attributes.value("colourScheme").toInt(&ok);
Chris@197 1249 if (ok) setColourMap(colourMap);
Chris@197 1250
Chris@1103 1251 BinScale binScale = (BinScale)
Chris@1099 1252 attributes.value("binScale").toInt(&ok);
Chris@1099 1253 if (ok) setBinScale(binScale);
Chris@445 1254
Chris@465 1255 bool invertVertical =
Chris@465 1256 (attributes.value("invertVertical").trimmed() == "true");
Chris@465 1257 setInvertVertical(invertVertical);
Chris@465 1258
Chris@465 1259 bool opaque =
Chris@465 1260 (attributes.value("opaque").trimmed() == "true");
Chris@535 1261 setOpaque(opaque);
Chris@535 1262
Chris@535 1263 bool smooth =
Chris@535 1264 (attributes.value("smooth").trimmed() == "true");
Chris@535 1265 setSmooth(smooth);
Chris@465 1266
Chris@536 1267 float gain = attributes.value("gain").toFloat(&ok);
Chris@536 1268 if (ok) setGain(gain);
Chris@536 1269
Chris@445 1270 float min = attributes.value("minY").toFloat(&ok);
Chris@445 1271 float max = attributes.value("maxY").toFloat(&alsoOk);
Chris@445 1272 if (ok && alsoOk) setDisplayExtents(min, max);
Chris@1099 1273
Chris@1099 1274 bool haveNewStyleNormalization = false;
Chris@1099 1275
Chris@1099 1276 QString columnNormalization = attributes.value("columnNormalization");
Chris@1099 1277
Chris@1099 1278 if (columnNormalization != "") {
Chris@1099 1279
Chris@1099 1280 haveNewStyleNormalization = true;
Chris@1099 1281
Chris@1099 1282 if (columnNormalization == "peak") {
Chris@1104 1283 setNormalization(ColumnNormalization::Max1);
Chris@1099 1284 } else if (columnNormalization == "hybrid") {
Chris@1104 1285 setNormalization(ColumnNormalization::Hybrid);
Chris@1099 1286 } else if (columnNormalization == "none") {
Chris@1104 1287 setNormalization(ColumnNormalization::None);
Chris@1099 1288 } else {
Chris@1099 1289 cerr << "NOTE: Unknown or unsupported columnNormalization attribute \""
Chris@1099 1290 << columnNormalization << "\"" << endl;
Chris@1099 1291 }
Chris@1099 1292 }
Chris@1099 1293
Chris@1099 1294 if (!haveNewStyleNormalization) {
Chris@1099 1295
Chris@1104 1296 setNormalization(ColumnNormalization::None);
Chris@1104 1297
Chris@1099 1298 bool normalizeColumns =
Chris@1099 1299 (attributes.value("normalizeColumns").trimmed() == "true");
Chris@1099 1300 if (normalizeColumns) {
Chris@1104 1301 setNormalization(ColumnNormalization::Max1);
Chris@1099 1302 }
Chris@1099 1303
Chris@1099 1304 bool normalizeHybrid =
Chris@1099 1305 (attributes.value("normalizeHybrid").trimmed() == "true");
Chris@1099 1306 if (normalizeHybrid) {
Chris@1104 1307 setNormalization(ColumnNormalization::Hybrid);
Chris@1099 1308 }
Chris@1099 1309 }
Chris@1099 1310
Chris@1099 1311 bool normalizeVisibleArea =
Chris@1099 1312 (attributes.value("normalizeVisibleArea").trimmed() == "true");
Chris@1104 1313 setNormalizeVisibleArea(normalizeVisibleArea);
Chris@1099 1314
Chris@1099 1315 //!!! todo: check save/reload scaling, compare with
Chris@1099 1316 //!!! SpectrogramLayer, compare with prior SV versions, compare
Chris@1099 1317 //!!! with Tony v1 and v2 and their save files
Chris@197 1318 }
Chris@197 1319