annotate layer/Colour3DPlotLayer.cpp @ 1160:a429b2acb45d 3.0-integration

Make SVDEBUG always write to a log file -- formerly this was disabled in NDEBUG builds. I think there's little use to that, it just means that we keep adding more cerr debug output because we aren't getting the log we need. And SVDEBUG logging is not usually used in tight loops, I don't think the performance overhead is too serious. Also update the About box.
author Chris Cannam
date Thu, 03 Nov 2016 14:57:00 +0000
parents 0edfed2c8482
children ab169938832a
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@159 278 return ValueProperty;
Chris@159 279 }
Chris@159 280
Chris@159 281 QString
Chris@159 282 Colour3DPlotLayer::getPropertyGroupName(const PropertyName &name) const
Chris@159 283 {
Chris@1104 284 if (name == "Normalization" ||
Chris@1104 285 name == "Colour Scale" ||
Chris@534 286 name == "Gain") return tr("Scale");
Chris@531 287 if (name == "Bin Scale" ||
Chris@531 288 name == "Invert Vertical Scale") return tr("Bins");
Chris@465 289 if (name == "Opaque" ||
Chris@535 290 name == "Smooth" ||
Chris@465 291 name == "Colour") return tr("Colour");
Chris@159 292 return QString();
Chris@159 293 }
Chris@159 294
Chris@159 295 int
Chris@159 296 Colour3DPlotLayer::getPropertyRangeAndValue(const PropertyName &name,
Chris@216 297 int *min, int *max, int *deflt) const
Chris@159 298 {
Chris@216 299 int val = 0;
Chris@159 300
Chris@216 301 int garbage0, garbage1, garbage2;
Chris@159 302 if (!min) min = &garbage0;
Chris@159 303 if (!max) max = &garbage1;
Chris@216 304 if (!deflt) deflt = &garbage2;
Chris@159 305
Chris@534 306 if (name == "Gain") {
Chris@534 307
Chris@534 308 *min = -50;
Chris@534 309 *max = 50;
Chris@534 310
Chris@902 311 *deflt = int(lrint(log10(1.0) * 20.0));
Chris@534 312 if (*deflt < *min) *deflt = *min;
Chris@534 313 if (*deflt > *max) *deflt = *max;
Chris@534 314
Chris@902 315 val = int(lrint(log10(m_gain) * 20.0));
Chris@534 316 if (val < *min) val = *min;
Chris@534 317 if (val > *max) val = *max;
Chris@534 318
Chris@534 319 } else if (name == "Colour Scale") {
Chris@159 320
Chris@1099 321 // linear, log, +/-1, abs
Chris@159 322 *min = 0;
Chris@509 323 *max = 3;
Chris@1099 324 *deflt = 0;
Chris@159 325
Chris@1104 326 val = convertFromColourScale(m_colourScale);
Chris@159 327
Chris@197 328 } else if (name == "Colour") {
Chris@197 329
Chris@197 330 *min = 0;
Chris@197 331 *max = ColourMapper::getColourMapCount() - 1;
Chris@216 332 *deflt = 0;
Chris@197 333
Chris@216 334 val = m_colourMap;
Chris@197 335
Chris@1099 336 } else if (name == "Normalization") {
Chris@197 337
Chris@1099 338 *min = 0;
Chris@1099 339 *max = 3;
Chris@1104 340 *deflt = 0;
Chris@1104 341
Chris@1104 342 val = convertFromColumnNorm(m_normalization, m_normalizeVisibleArea);
Chris@197 343
Chris@357 344 } else if (name == "Invert Vertical Scale") {
Chris@357 345
Chris@357 346 *deflt = 0;
Chris@357 347 val = (m_invertVertical ? 1 : 0);
Chris@357 348
Chris@531 349 } else if (name == "Bin Scale") {
Chris@531 350
Chris@531 351 *min = 0;
Chris@531 352 *max = 1;
Chris@1103 353 *deflt = int(BinScale::Linear);
Chris@531 354 val = (int)m_binScale;
Chris@531 355
Chris@465 356 } else if (name == "Opaque") {
Chris@465 357
Chris@465 358 *deflt = 0;
Chris@465 359 val = (m_opaque ? 1 : 0);
Chris@465 360
Chris@535 361 } else if (name == "Smooth") {
Chris@535 362
Chris@535 363 *deflt = 0;
Chris@535 364 val = (m_smooth ? 1 : 0);
Chris@535 365
Chris@159 366 } else {
Chris@216 367 val = Layer::getPropertyRangeAndValue(name, min, max, deflt);
Chris@159 368 }
Chris@159 369
Chris@216 370 return val;
Chris@159 371 }
Chris@159 372
Chris@159 373 QString
Chris@159 374 Colour3DPlotLayer::getPropertyValueLabel(const PropertyName &name,
Chris@159 375 int value) const
Chris@159 376 {
Chris@197 377 if (name == "Colour") {
Chris@197 378 return ColourMapper::getColourMapName(value);
Chris@197 379 }
Chris@159 380 if (name == "Colour Scale") {
Chris@159 381 switch (value) {
Chris@159 382 default:
Chris@198 383 case 0: return tr("Linear");
Chris@198 384 case 1: return tr("Log");
Chris@198 385 case 2: return tr("+/-1");
Chris@509 386 case 3: return tr("Absolute");
Chris@159 387 }
Chris@159 388 }
Chris@1099 389 if (name == "Normalization") {
Chris@1099 390 return ""; // icon only
Chris@1099 391 }
Chris@531 392 if (name == "Bin Scale") {
Chris@531 393 switch (value) {
Chris@531 394 default:
Chris@531 395 case 0: return tr("Linear");
Chris@531 396 case 1: return tr("Log");
Chris@531 397 }
Chris@531 398 }
Chris@159 399 return tr("<unknown>");
Chris@159 400 }
Chris@159 401
Chris@1099 402 QString
Chris@1099 403 Colour3DPlotLayer::getPropertyValueIconName(const PropertyName &name,
Chris@1099 404 int value) const
Chris@1099 405 {
Chris@1099 406 if (name == "Normalization") {
Chris@1099 407 switch(value) {
Chris@1099 408 default:
Chris@1099 409 case 0: return "normalise-none";
Chris@1099 410 case 1: return "normalise-columns";
Chris@1099 411 case 2: return "normalise";
Chris@1099 412 case 3: return "normalise-hybrid";
Chris@1099 413 }
Chris@1099 414 }
Chris@1099 415 return "";
Chris@1099 416 }
Chris@1099 417
Chris@534 418 RangeMapper *
Chris@534 419 Colour3DPlotLayer::getNewPropertyRangeMapper(const PropertyName &name) const
Chris@534 420 {
Chris@534 421 if (name == "Gain") {
Chris@534 422 return new LinearRangeMapper(-50, 50, -25, 25, tr("dB"));
Chris@534 423 }
Chris@534 424 return 0;
Chris@534 425 }
Chris@534 426
Chris@159 427 void
Chris@159 428 Colour3DPlotLayer::setProperty(const PropertyName &name, int value)
Chris@159 429 {
Chris@534 430 if (name == "Gain") {
Chris@902 431 setGain(float(pow(10, value/20.0)));
Chris@534 432 } else if (name == "Colour Scale") {
Chris@1104 433 setColourScale(convertToColourScale(value));
Chris@197 434 } else if (name == "Colour") {
Chris@197 435 setColourMap(value);
Chris@357 436 } else if (name == "Invert Vertical Scale") {
Chris@357 437 setInvertVertical(value ? true : false);
Chris@465 438 } else if (name == "Opaque") {
Chris@465 439 setOpaque(value ? true : false);
Chris@535 440 } else if (name == "Smooth") {
Chris@535 441 setSmooth(value ? true : false);
Chris@531 442 } else if (name == "Bin Scale") {
Chris@531 443 switch (value) {
Chris@531 444 default:
Chris@1103 445 case 0: setBinScale(BinScale::Linear); break;
Chris@1103 446 case 1: setBinScale(BinScale::Log); break;
Chris@531 447 }
Chris@1099 448 } else if (name == "Normalization") {
Chris@1104 449 auto n = convertToColumnNorm(value);
Chris@1104 450 setNormalization(n.first);
Chris@1104 451 setNormalizeVisibleArea(n.second);
Chris@159 452 }
Chris@159 453 }
Chris@159 454
Chris@159 455 void
Chris@1105 456 Colour3DPlotLayer::setColourScale(ColourScaleType scale)
Chris@159 457 {
Chris@159 458 if (m_colourScale == scale) return;
Chris@159 459 m_colourScale = scale;
Chris@461 460 m_colourScaleSet = true;
Chris@1107 461 invalidateRenderers();
Chris@159 462 emit layerParametersChanged();
Chris@159 463 }
Chris@159 464
Chris@197 465 void
Chris@197 466 Colour3DPlotLayer::setColourMap(int map)
Chris@197 467 {
Chris@197 468 if (m_colourMap == map) return;
Chris@197 469 m_colourMap = map;
Chris@1107 470 invalidateRenderers();
Chris@197 471 emit layerParametersChanged();
Chris@197 472 }
Chris@197 473
Chris@197 474 void
Chris@534 475 Colour3DPlotLayer::setGain(float gain)
Chris@534 476 {
Chris@534 477 if (m_gain == gain) return;
Chris@534 478 m_gain = gain;
Chris@1107 479 invalidateRenderers();
Chris@534 480 emit layerParametersChanged();
Chris@534 481 }
Chris@534 482
Chris@534 483 float
Chris@534 484 Colour3DPlotLayer::getGain() const
Chris@534 485 {
Chris@534 486 return m_gain;
Chris@534 487 }
Chris@534 488
Chris@534 489 void
Chris@1103 490 Colour3DPlotLayer::setBinScale(BinScale binScale)
Chris@531 491 {
Chris@531 492 if (m_binScale == binScale) return;
Chris@531 493 m_binScale = binScale;
Chris@1107 494 invalidateRenderers();
Chris@531 495 emit layerParametersChanged();
Chris@531 496 }
Chris@531 497
Chris@1103 498 BinScale
Chris@531 499 Colour3DPlotLayer::getBinScale() const
Chris@531 500 {
Chris@531 501 return m_binScale;
Chris@531 502 }
Chris@531 503
Chris@531 504 void
Chris@1104 505 Colour3DPlotLayer::setNormalization(ColumnNormalization n)
Chris@197 506 {
Chris@1099 507 if (m_normalization == n) return;
Chris@1099 508
Chris@1099 509 m_normalization = n;
Chris@1107 510 invalidateRenderers();
Chris@1099 511
Chris@197 512 emit layerParametersChanged();
Chris@197 513 }
Chris@197 514
Chris@1104 515 ColumnNormalization
Chris@1099 516 Colour3DPlotLayer::getNormalization() const
Chris@197 517 {
Chris@1099 518 return m_normalization;
Chris@197 519 }
Chris@197 520
Chris@357 521 void
Chris@1104 522 Colour3DPlotLayer::setNormalizeVisibleArea(bool n)
Chris@1104 523 {
Chris@1104 524 if (m_normalizeVisibleArea == n) return;
Chris@1104 525
Chris@1104 526 m_normalizeVisibleArea = n;
Chris@1107 527 invalidateRenderers();
Chris@1104 528
Chris@1104 529 emit layerParametersChanged();
Chris@1104 530 }
Chris@1104 531
Chris@1104 532 bool
Chris@1104 533 Colour3DPlotLayer::getNormalizeVisibleArea() const
Chris@1104 534 {
Chris@1104 535 return m_normalizeVisibleArea;
Chris@1104 536 }
Chris@1104 537
Chris@1104 538 void
Chris@357 539 Colour3DPlotLayer::setInvertVertical(bool n)
Chris@357 540 {
Chris@357 541 if (m_invertVertical == n) return;
Chris@357 542 m_invertVertical = n;
Chris@1107 543 invalidateRenderers();
Chris@357 544 emit layerParametersChanged();
Chris@357 545 }
Chris@357 546
Chris@465 547 void
Chris@465 548 Colour3DPlotLayer::setOpaque(bool n)
Chris@465 549 {
Chris@465 550 if (m_opaque == n) return;
Chris@465 551 m_opaque = n;
Chris@1107 552 invalidateRenderers();
Chris@465 553 emit layerParametersChanged();
Chris@465 554 }
Chris@465 555
Chris@535 556 void
Chris@535 557 Colour3DPlotLayer::setSmooth(bool n)
Chris@535 558 {
Chris@535 559 if (m_smooth == n) return;
Chris@535 560 m_smooth = n;
Chris@1107 561 invalidateRenderers();
Chris@535 562 emit layerParametersChanged();
Chris@535 563 }
Chris@535 564
Chris@357 565 bool
Chris@357 566 Colour3DPlotLayer::getInvertVertical() const
Chris@357 567 {
Chris@357 568 return m_invertVertical;
Chris@357 569 }
Chris@357 570
Chris@25 571 bool
Chris@465 572 Colour3DPlotLayer::getOpaque() const
Chris@465 573 {
Chris@465 574 return m_opaque;
Chris@465 575 }
Chris@465 576
Chris@535 577 bool
Chris@535 578 Colour3DPlotLayer::getSmooth() const
Chris@535 579 {
Chris@535 580 return m_smooth;
Chris@535 581 }
Chris@535 582
Chris@475 583 void
Chris@916 584 Colour3DPlotLayer::setLayerDormant(const LayerGeometryProvider *v, bool dormant)
Chris@475 585 {
Chris@475 586 if (dormant) {
Chris@475 587
Chris@475 588 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@812 589 cerr << "Colour3DPlotLayer::setLayerDormant(" << dormant << ")"
Chris@585 590 << endl;
Chris@475 591 #endif
Chris@475 592
Chris@475 593 if (isLayerDormant(v)) {
Chris@475 594 return;
Chris@475 595 }
Chris@475 596
Chris@475 597 Layer::setLayerDormant(v, true);
Chris@475 598
Chris@475 599 cacheInvalid();
Chris@475 600
Chris@475 601 } else {
Chris@475 602
Chris@475 603 Layer::setLayerDormant(v, false);
Chris@475 604 }
Chris@475 605 }
Chris@475 606
Chris@465 607 bool
Chris@1150 608 Colour3DPlotLayer::isLayerScrollable(const LayerGeometryProvider * /* v */) const
Chris@25 609 {
Chris@1104 610 if (m_normalizeVisibleArea) {
Chris@812 611 return false;
Chris@812 612 }
Chris@1121 613 //!!! ah hang on, if we're potentially rendering incrementally
Chris@1121 614 //!!! they we can't be scrollable
Chris@1121 615 return false;
Chris@1121 616 // if (getRenderer(v)->willRenderOpaque(v)) {
Chris@1121 617 // return true;
Chris@1121 618 // }
Chris@1121 619 // QPoint discard;
Chris@1121 620 // return !v->shouldIlluminateLocalFeatures(this, discard);
Chris@25 621 }
Chris@25 622
Chris@444 623 bool
Chris@904 624 Colour3DPlotLayer::getValueExtents(double &min, double &max,
Chris@444 625 bool &logarithmic, QString &unit) const
Chris@444 626 {
Chris@444 627 if (!m_model) return false;
Chris@444 628
Chris@444 629 min = 0;
Chris@904 630 max = double(m_model->getHeight());
Chris@444 631
Chris@444 632 logarithmic = false;
Chris@444 633 unit = "";
Chris@444 634
Chris@444 635 return true;
Chris@444 636 }
Chris@444 637
Chris@444 638 bool
Chris@904 639 Colour3DPlotLayer::getDisplayExtents(double &min, double &max) const
Chris@444 640 {
Chris@444 641 if (!m_model) return false;
Chris@444 642
Chris@904 643 double hmax = double(m_model->getHeight());
Chris@902 644
Chris@904 645 min = m_miny;
Chris@904 646 max = m_maxy;
Chris@444 647 if (max <= min) {
Chris@444 648 min = 0;
Chris@902 649 max = hmax;
Chris@444 650 }
Chris@444 651 if (min < 0) min = 0;
Chris@902 652 if (max > hmax) max = hmax;
Chris@444 653
Chris@444 654 return true;
Chris@444 655 }
Chris@444 656
Chris@444 657 bool
Chris@904 658 Colour3DPlotLayer::setDisplayExtents(double min, double max)
Chris@444 659 {
Chris@444 660 if (!m_model) return false;
Chris@444 661
Chris@904 662 m_miny = int(lrint(min));
Chris@904 663 m_maxy = int(lrint(max));
Chris@444 664
Chris@1133 665 invalidateRenderers();
Chris@1133 666
Chris@444 667 emit layerParametersChanged();
Chris@444 668 return true;
Chris@444 669 }
Chris@444 670
Chris@725 671 bool
Chris@916 672 Colour3DPlotLayer::getYScaleValue(const LayerGeometryProvider *, int,
Chris@904 673 double &, QString &) const
Chris@725 674 {
Chris@725 675 return false;//!!!
Chris@725 676 }
Chris@725 677
Chris@444 678 int
Chris@444 679 Colour3DPlotLayer::getVerticalZoomSteps(int &defaultStep) const
Chris@444 680 {
Chris@444 681 if (!m_model) return 0;
Chris@444 682
Chris@444 683 defaultStep = 0;
Chris@444 684 int h = m_model->getHeight();
Chris@444 685 return h;
Chris@444 686 }
Chris@444 687
Chris@444 688 int
Chris@444 689 Colour3DPlotLayer::getCurrentVerticalZoomStep() const
Chris@444 690 {
Chris@444 691 if (!m_model) return 0;
Chris@444 692
Chris@904 693 double min, max;
Chris@444 694 getDisplayExtents(min, max);
Chris@904 695 return m_model->getHeight() - int(lrint(max - min));
Chris@444 696 }
Chris@444 697
Chris@444 698 void
Chris@444 699 Colour3DPlotLayer::setVerticalZoomStep(int step)
Chris@444 700 {
Chris@444 701 if (!m_model) return;
Chris@444 702
Chris@587 703 // SVDEBUG << "Colour3DPlotLayer::setVerticalZoomStep(" <<step <<"): before: miny = " << m_miny << ", maxy = " << m_maxy << endl;
Chris@444 704
Chris@444 705 int dist = m_model->getHeight() - step;
Chris@444 706 if (dist < 1) dist = 1;
Chris@904 707 double centre = m_miny + (m_maxy - m_miny) / 2.0;
Chris@904 708 m_miny = int(lrint(centre - dist/2.0));
Chris@444 709 if (m_miny < 0) m_miny = 0;
Chris@444 710 m_maxy = m_miny + dist;
Chris@444 711 if (m_maxy > m_model->getHeight()) m_maxy = m_model->getHeight();
Chris@444 712
Chris@1133 713 invalidateRenderers();
Chris@1133 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@1131 869 double min = m_viewMags[v->getId()].getMin();
Chris@1131 870 double max = m_viewMags[v->getId()].getMax();
Chris@447 871
Chris@1131 872 if (max <= min) max = min + 0.1;
Chris@447 873
Chris@287 874 paint.setPen(v->getForeground());
Chris@447 875 paint.drawRect(4, 10, cw - 8, ch+1);
Chris@159 876
Chris@446 877 for (int y = 0; y < ch; ++y) {
Chris@904 878 double value = ((max - min) * (double(ch-y) - 1.0)) / double(ch) + min;
Chris@1131 879 paint.setPen(getRenderer(v)->getColour(value));
Chris@1131 880 paint.drawLine(5, 11 + y, cw - 5, 11 + y);
Chris@159 881 }
Chris@446 882
Chris@446 883 QString minstr = QString("%1").arg(min);
Chris@446 884 QString maxstr = QString("%1").arg(max);
Chris@446 885
Chris@446 886 paint.save();
Chris@446 887
Chris@446 888 QFont font = paint.font();
Chris@1053 889 if (font.pixelSize() > 0) {
Chris@1053 890 int newSize = int(font.pixelSize() * 0.65);
Chris@1053 891 if (newSize < 6) newSize = 6;
Chris@1053 892 font.setPixelSize(newSize);
Chris@1053 893 paint.setFont(font);
Chris@1053 894 }
Chris@446 895
Chris@446 896 int msw = paint.fontMetrics().width(maxstr);
Chris@446 897
Chris@446 898 QMatrix m;
Chris@446 899 m.translate(cw - 6, ch + 10);
Chris@446 900 m.rotate(-90);
Chris@446 901
Chris@446 902 paint.setWorldMatrix(m);
Chris@446 903
Chris@1078 904 PaintAssistant::drawVisibleText(v, paint, 2, 0, minstr, PaintAssistant::OutlinedText);
Chris@446 905
Chris@446 906 m.translate(ch - msw - 2, 0);
Chris@446 907 paint.setWorldMatrix(m);
Chris@446 908
Chris@1078 909 PaintAssistant::drawVisibleText(v, paint, 0, 0, maxstr, PaintAssistant::OutlinedText);
Chris@446 910
Chris@446 911 paint.restore();
Chris@159 912 }
Chris@159 913
Chris@287 914 paint.setPen(v->getForeground());
Chris@159 915
Chris@445 916 int sh = m_model->getHeight();
Chris@445 917
Chris@445 918 int symin = m_miny;
Chris@445 919 int symax = m_maxy;
Chris@445 920 if (symax <= symin) {
Chris@445 921 symin = 0;
Chris@445 922 symax = sh;
Chris@445 923 }
Chris@445 924 if (symin < 0) symin = 0;
Chris@445 925 if (symax > sh) symax = sh;
Chris@445 926
Chris@532 927 paint.save();
Chris@456 928
Chris@533 929 int py = h;
Chris@25 930
Chris@969 931 int defaultFontHeight = paint.fontMetrics().height();
Chris@969 932
Chris@805 933 for (int i = symin; i <= symax; ++i) {
Chris@98 934
Chris@532 935 int y0;
Chris@534 936
Chris@903 937 y0 = getIYForBin(v, i);
Chris@532 938 int h = py - y0;
Chris@532 939
Chris@532 940 if (i > symin) {
Chris@532 941 if (paint.fontMetrics().height() >= h) {
Chris@969 942 if (h >= defaultFontHeight * 0.8) {
Chris@532 943 QFont tf = paint.font();
Chris@973 944 tf.setPixelSize(int(h * 0.8));
Chris@532 945 paint.setFont(tf);
Chris@532 946 } else {
Chris@532 947 continue;
Chris@532 948 }
Chris@532 949 }
Chris@532 950 }
Chris@25 951
Chris@532 952 py = y0;
Chris@532 953
Chris@534 954 if (i < symax) {
Chris@534 955 paint.drawLine(cw, y0, w, y0);
Chris@534 956 }
Chris@25 957
Chris@532 958 if (i > symin) {
Chris@534 959
Chris@805 960 int idx = i - 1;
Chris@534 961 if (m_invertVertical) idx = m_model->getHeight() - idx - 1;
Chris@534 962
Chris@534 963 QString text = m_model->getBinName(idx);
Chris@534 964 if (text == "") text = QString("[%1]").arg(idx + 1);
Chris@534 965
Chris@534 966 int ty = y0 + (h/2) - (paint.fontMetrics().height()/2) +
Chris@534 967 paint.fontMetrics().ascent() + 1;
Chris@534 968
Chris@534 969 paint.drawText(cw + 5, ty, text);
Chris@457 970 }
Chris@25 971 }
Chris@456 972
Chris@456 973 paint.restore();
Chris@25 974 }
Chris@25 975
Chris@467 976 DenseThreeDimensionalModel::Column
Chris@805 977 Colour3DPlotLayer::getColumn(int col) const
Chris@197 978 {
Chris@812 979 Profiler profiler("Colour3DPlotLayer::getColumn");
Chris@812 980
Chris@467 981 DenseThreeDimensionalModel::Column values = m_model->getColumn(col);
Chris@1019 982 values.resize(m_model->getHeight(), 0.f);
Chris@1104 983 if (m_normalization != ColumnNormalization::Max1 &&
Chris@1104 984 m_normalization != ColumnNormalization::Hybrid) {
Chris@1099 985 return values;
Chris@1099 986 }
Chris@461 987
Chris@904 988 double colMax = 0.f, colMin = 0.f;
Chris@904 989 double min = 0.f, max = 0.f;
Chris@197 990
Chris@1019 991 int nv = int(values.size());
Chris@1019 992
Chris@461 993 min = m_model->getMinimumLevel();
Chris@461 994 max = m_model->getMaximumLevel();
Chris@461 995
Chris@1019 996 for (int y = 0; y < nv; ++y) {
Chris@467 997 if (y == 0 || values.at(y) > colMax) colMax = values.at(y);
Chris@467 998 if (y == 0 || values.at(y) < colMin) colMin = values.at(y);
Chris@197 999 }
Chris@461 1000 if (colMin == colMax) colMax = colMin + 1;
Chris@197 1001
Chris@1019 1002 for (int y = 0; y < nv; ++y) {
Chris@461 1003
Chris@904 1004 double value = values.at(y);
Chris@904 1005 double norm = (value - colMin) / (colMax - colMin);
Chris@904 1006 double newvalue = min + (max - min) * norm;
Chris@197 1007
Chris@904 1008 if (value != newvalue) values[y] = float(newvalue);
Chris@468 1009 }
Chris@468 1010
Chris@1104 1011 if (m_normalization == ColumnNormalization::Hybrid
Chris@1099 1012 && (colMax > 0.0)) {
Chris@904 1013 double logmax = log10(colMax);
Chris@1019 1014 for (int y = 0; y < nv; ++y) {
Chris@904 1015 values[y] = float(values[y] * logmax);
Chris@719 1016 }
Chris@719 1017 }
Chris@719 1018
Chris@468 1019 return values;
Chris@197 1020 }
Chris@1114 1021
Chris@1100 1022 Colour3DPlotRenderer *
Chris@1113 1023 Colour3DPlotLayer::getRenderer(const LayerGeometryProvider *v) const
Chris@1100 1024 {
Chris@1100 1025 if (m_renderers.find(v->getId()) == m_renderers.end()) {
Chris@1100 1026
Chris@1100 1027 Colour3DPlotRenderer::Sources sources;
Chris@1100 1028 sources.verticalBinLayer = this;
Chris@1100 1029 sources.fft = 0;
Chris@1100 1030 sources.source = m_model;
Chris@1100 1031 sources.peaks = getPeakCache();
Chris@1100 1032
Chris@1100 1033 ColourScale::Parameters cparams;
Chris@1100 1034 cparams.colourMap = m_colourMap;
Chris@1137 1035 cparams.scaleType = m_colourScale;
Chris@1100 1036 cparams.gain = m_gain;
Chris@1100 1037
Chris@1131 1038 if (m_normalization == ColumnNormalization::None) {
Chris@1131 1039 cparams.minValue = m_model->getMinimumLevel();
Chris@1131 1040 cparams.maxValue = m_model->getMaximumLevel();
Chris@1131 1041 } else if (m_normalization == ColumnNormalization::Hybrid) {
Chris@1131 1042 cparams.minValue = 0;
Chris@1131 1043 cparams.maxValue = log10(m_model->getMaximumLevel() + 1.0);
Chris@1131 1044 }
Chris@1131 1045
Chris@1131 1046 if (cparams.maxValue <= cparams.minValue) {
Chris@1131 1047 cparams.maxValue = cparams.minValue + 0.1;
Chris@1131 1048 }
Chris@1131 1049
Chris@1100 1050 Colour3DPlotRenderer::Parameters params;
Chris@1100 1051 params.colourScale = ColourScale(cparams);
Chris@1100 1052 params.normalization = m_normalization;
Chris@1100 1053 params.binScale = m_binScale;
Chris@1100 1054 params.alwaysOpaque = m_opaque;
Chris@1100 1055 params.invertVertical = m_invertVertical;
Chris@1100 1056 params.interpolate = m_smooth;
Chris@1100 1057
Chris@1100 1058 m_renderers[v->getId()] = new Colour3DPlotRenderer(sources, params);
Chris@1100 1059 }
Chris@1100 1060
Chris@1100 1061 return m_renderers[v->getId()];
Chris@1100 1062 }
Chris@1100 1063
Chris@197 1064 void
Chris@1107 1065 Colour3DPlotLayer::paintWithRenderer(LayerGeometryProvider *v,
Chris@1107 1066 QPainter &paint, QRect rect) const
Chris@1101 1067 {
Chris@1101 1068 Colour3DPlotRenderer *renderer = getRenderer(v);
Chris@1101 1069
Chris@1121 1070 Colour3DPlotRenderer::RenderResult result;
Chris@1123 1071 MagnitudeRange magRange;
Chris@1123 1072 int viewId = v->getId();
Chris@1123 1073
Chris@1123 1074 if (!renderer->geometryChanged(v)) {
Chris@1123 1075 magRange = m_viewMags[viewId];
Chris@1123 1076 }
Chris@1121 1077
Chris@1101 1078 if (m_synchronous) {
Chris@1121 1079
Chris@1121 1080 result = renderer->render(v, paint, rect);
Chris@1121 1081
Chris@1121 1082 } else {
Chris@1121 1083
Chris@1121 1084 result = renderer->renderTimeConstrained(v, paint, rect);
Chris@1121 1085
Chris@1121 1086 QRect uncached = renderer->getLargestUncachedRect(v);
Chris@1121 1087 if (uncached.width() > 0) {
Chris@1121 1088 v->updatePaintRect(uncached);
Chris@1121 1089 }
Chris@1101 1090 }
Chris@1121 1091
Chris@1123 1092 magRange.sample(result.range);
Chris@1101 1093
Chris@1123 1094 if (magRange.isSet()) {
Chris@1123 1095 if (!(m_viewMags[viewId] == magRange)) {
Chris@1123 1096 m_viewMags[viewId] = magRange;
Chris@1123 1097 //!!! now need to do the normalise-visible thing
Chris@1123 1098 }
Chris@1123 1099 }
Chris@1101 1100
Chris@1121 1101 cerr << "mag range in this view: "
Chris@1121 1102 << m_viewMags[v->getId()].getMin()
Chris@1121 1103 << " -> "
Chris@1121 1104 << m_viewMags[v->getId()].getMax()
Chris@1121 1105 << endl;
Chris@1121 1106
Chris@1101 1107 }
Chris@1101 1108
Chris@1101 1109 void
Chris@916 1110 Colour3DPlotLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const
Chris@0 1111 {
Chris@514 1112 /*
Chris@443 1113 if (m_model) {
Chris@587 1114 SVDEBUG << "Colour3DPlotLayer::paint: model says shouldUseLogValueScale = " << m_model->shouldUseLogValueScale() << endl;
Chris@443 1115 }
Chris@514 1116 */
Chris@466 1117 Profiler profiler("Colour3DPlotLayer::paint");
Chris@125 1118 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@812 1119 cerr << "Colour3DPlotLayer::paint(): m_model is " << m_model << ", zoom level is " << v->getZoomLevel() << ", rect is (" << rect.x() << "," << rect.y() << ") " << rect.width() << "x" << rect.height() << endl;
Chris@125 1120 #endif
Chris@0 1121
Chris@0 1122 int completion = 0;
Chris@0 1123 if (!m_model || !m_model->isOK() || !m_model->isReady(&completion)) {
Chris@0 1124 if (completion > 0) {
Chris@916 1125 paint.fillRect(0, 10, v->getPaintWidth() * completion / 100,
Chris@0 1126 10, QColor(120, 120, 120));
Chris@0 1127 }
Chris@0 1128 return;
Chris@0 1129 }
Chris@0 1130
Chris@1053 1131 if (m_model->getWidth() == 0) {
Chris@1053 1132 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@1053 1133 cerr << "Colour3DPlotLayer::paint(): model width == 0, "
Chris@1053 1134 << "nothing to paint (yet)" << endl;
Chris@1053 1135 #endif
Chris@1053 1136 return;
Chris@1053 1137 }
Chris@1101 1138
Chris@1101 1139 //!!!???
Chris@1053 1140
Chris@1104 1141 if (m_normalizeVisibleArea) {
Chris@1099 1142 rect = v->getPaintRect();
Chris@1099 1143 }
Chris@197 1144
Chris@1107 1145 //!!! why is the setLayerDormant(false) found here in
Chris@1107 1146 //!!! SpectrogramLayer not present in Colour3DPlotLayer?
Chris@1107 1147 //!!! unnecessary? vestigial? forgotten?
Chris@1107 1148
Chris@1107 1149 paintWithRenderer(v, paint, rect);
Chris@1107 1150 }
Chris@1107 1151
Chris@28 1152 bool
Chris@916 1153 Colour3DPlotLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame,
Chris@805 1154 int &resolution,
Chris@28 1155 SnapType snap) const
Chris@24 1156 {
Chris@24 1157 if (!m_model) {
Chris@44 1158 return Layer::snapToFeatureFrame(v, frame, resolution, snap);
Chris@24 1159 }
Chris@24 1160
Chris@130 1161 resolution = m_model->getResolution();
Chris@904 1162 sv_frame_t left = (frame / resolution) * resolution;
Chris@904 1163 sv_frame_t right = left + resolution;
Chris@28 1164
Chris@28 1165 switch (snap) {
Chris@28 1166 case SnapLeft: frame = left; break;
Chris@28 1167 case SnapRight: frame = right; break;
Chris@28 1168 case SnapNearest:
Chris@28 1169 case SnapNeighbouring:
Chris@28 1170 if (frame - left > right - frame) frame = right;
Chris@28 1171 else frame = left;
Chris@28 1172 break;
Chris@28 1173 }
Chris@24 1174
Chris@28 1175 return true;
Chris@24 1176 }
Chris@24 1177
Chris@316 1178 void
Chris@316 1179 Colour3DPlotLayer::toXml(QTextStream &stream,
Chris@316 1180 QString indent, QString extraAttributes) const
Chris@197 1181 {
Chris@316 1182 QString s = QString("scale=\"%1\" "
Chris@316 1183 "colourScheme=\"%2\" "
Chris@1099 1184 "minY=\"%3\" "
Chris@1099 1185 "maxY=\"%4\" "
Chris@1099 1186 "invertVertical=\"%5\" "
Chris@1099 1187 "opaque=\"%6\" %7")
Chris@1104 1188 .arg(convertFromColourScale(m_colourScale))
Chris@197 1189 .arg(m_colourMap)
Chris@445 1190 .arg(m_miny)
Chris@465 1191 .arg(m_maxy)
Chris@465 1192 .arg(m_invertVertical ? "true" : "false")
Chris@534 1193 .arg(m_opaque ? "true" : "false")
Chris@536 1194 .arg(QString("binScale=\"%1\" smooth=\"%2\" gain=\"%3\" ")
Chris@1103 1195 .arg(int(m_binScale))
Chris@536 1196 .arg(m_smooth ? "true" : "false")
Chris@536 1197 .arg(m_gain));
Chris@535 1198
Chris@1099 1199 // New-style normalization attributes, allowing for more types of
Chris@1099 1200 // normalization in future: write out the column normalization
Chris@1099 1201 // type separately, and then whether we are normalizing visible
Chris@1099 1202 // area as well afterwards
Chris@1099 1203
Chris@1099 1204 s += QString("columnNormalization=\"%1\" ")
Chris@1104 1205 .arg(m_normalization == ColumnNormalization::Max1 ? "peak" :
Chris@1104 1206 m_normalization == ColumnNormalization::Hybrid ? "hybrid" : "none");
Chris@1099 1207
Chris@1099 1208 // Old-style normalization attribute, for backward compatibility
Chris@1099 1209
Chris@1099 1210 s += QString("normalizeColumns=\"%1\" ")
Chris@1104 1211 .arg(m_normalization == ColumnNormalization::Max1 ? "true" : "false");
Chris@1099 1212
Chris@1099 1213 // And this applies to both old- and new-style attributes
Chris@1099 1214
Chris@1099 1215 s += QString("normalizeVisibleArea=\"%1\" ")
Chris@1104 1216 .arg(m_normalizeVisibleArea ? "true" : "false");
Chris@1099 1217
Chris@316 1218 Layer::toXml(stream, indent, extraAttributes + " " + s);
Chris@197 1219 }
Chris@197 1220
Chris@197 1221 void
Chris@197 1222 Colour3DPlotLayer::setProperties(const QXmlAttributes &attributes)
Chris@197 1223 {
Chris@445 1224 bool ok = false, alsoOk = false;
Chris@197 1225
Chris@1105 1226 ColourScaleType colourScale = convertToColourScale
Chris@1099 1227 (attributes.value("colourScale").toInt(&ok));
Chris@1099 1228 if (ok) setColourScale(colourScale);
Chris@197 1229
Chris@197 1230 int colourMap = attributes.value("colourScheme").toInt(&ok);
Chris@197 1231 if (ok) setColourMap(colourMap);
Chris@197 1232
Chris@1103 1233 BinScale binScale = (BinScale)
Chris@1099 1234 attributes.value("binScale").toInt(&ok);
Chris@1099 1235 if (ok) setBinScale(binScale);
Chris@445 1236
Chris@465 1237 bool invertVertical =
Chris@465 1238 (attributes.value("invertVertical").trimmed() == "true");
Chris@465 1239 setInvertVertical(invertVertical);
Chris@465 1240
Chris@465 1241 bool opaque =
Chris@465 1242 (attributes.value("opaque").trimmed() == "true");
Chris@535 1243 setOpaque(opaque);
Chris@535 1244
Chris@535 1245 bool smooth =
Chris@535 1246 (attributes.value("smooth").trimmed() == "true");
Chris@535 1247 setSmooth(smooth);
Chris@465 1248
Chris@536 1249 float gain = attributes.value("gain").toFloat(&ok);
Chris@536 1250 if (ok) setGain(gain);
Chris@536 1251
Chris@445 1252 float min = attributes.value("minY").toFloat(&ok);
Chris@445 1253 float max = attributes.value("maxY").toFloat(&alsoOk);
Chris@445 1254 if (ok && alsoOk) setDisplayExtents(min, max);
Chris@1099 1255
Chris@1099 1256 bool haveNewStyleNormalization = false;
Chris@1099 1257
Chris@1099 1258 QString columnNormalization = attributes.value("columnNormalization");
Chris@1099 1259
Chris@1099 1260 if (columnNormalization != "") {
Chris@1099 1261
Chris@1099 1262 haveNewStyleNormalization = true;
Chris@1099 1263
Chris@1099 1264 if (columnNormalization == "peak") {
Chris@1104 1265 setNormalization(ColumnNormalization::Max1);
Chris@1099 1266 } else if (columnNormalization == "hybrid") {
Chris@1104 1267 setNormalization(ColumnNormalization::Hybrid);
Chris@1099 1268 } else if (columnNormalization == "none") {
Chris@1104 1269 setNormalization(ColumnNormalization::None);
Chris@1099 1270 } else {
Chris@1099 1271 cerr << "NOTE: Unknown or unsupported columnNormalization attribute \""
Chris@1099 1272 << columnNormalization << "\"" << endl;
Chris@1099 1273 }
Chris@1099 1274 }
Chris@1099 1275
Chris@1099 1276 if (!haveNewStyleNormalization) {
Chris@1099 1277
Chris@1104 1278 setNormalization(ColumnNormalization::None);
Chris@1104 1279
Chris@1099 1280 bool normalizeColumns =
Chris@1099 1281 (attributes.value("normalizeColumns").trimmed() == "true");
Chris@1099 1282 if (normalizeColumns) {
Chris@1104 1283 setNormalization(ColumnNormalization::Max1);
Chris@1099 1284 }
Chris@1099 1285
Chris@1099 1286 bool normalizeHybrid =
Chris@1099 1287 (attributes.value("normalizeHybrid").trimmed() == "true");
Chris@1099 1288 if (normalizeHybrid) {
Chris@1104 1289 setNormalization(ColumnNormalization::Hybrid);
Chris@1099 1290 }
Chris@1099 1291 }
Chris@1099 1292
Chris@1099 1293 bool normalizeVisibleArea =
Chris@1099 1294 (attributes.value("normalizeVisibleArea").trimmed() == "true");
Chris@1104 1295 setNormalizeVisibleArea(normalizeVisibleArea);
Chris@1099 1296
Chris@1099 1297 //!!! todo: check save/reload scaling, compare with
Chris@1099 1298 //!!! SpectrogramLayer, compare with prior SV versions, compare
Chris@1099 1299 //!!! with Tony v1 and v2 and their save files
Chris@197 1300 }
Chris@197 1301