annotate layer/Colour3DPlotLayer.cpp @ 1198:69ff93e0c624 levelpanwidget

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