annotate layer/Colour3DPlotLayer.cpp @ 738:d26545a2a02d tonioni

Rather than undrawing the bottom bit of the dial, don't draw it in the first place (necessary on shaded background)
author Chris Cannam
date Thu, 06 Mar 2014 13:52:33 +0000
parents 67e6d518ac27
children c27a3604fe6f
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@128 18 #include "view/View.h"
Chris@0 19 #include "base/Profiler.h"
Chris@197 20 #include "base/LogRange.h"
Chris@444 21 #include "base/RangeMapper.h"
Chris@376 22 #include "ColourMapper.h"
Chris@0 23
Chris@0 24 #include <QPainter>
Chris@0 25 #include <QImage>
Chris@0 26 #include <QRect>
Chris@316 27 #include <QTextStream>
Chris@0 28
Chris@0 29 #include <iostream>
Chris@0 30
Chris@0 31 #include <cassert>
Chris@0 32
Chris@545 33 #ifndef __GNUC__
Chris@545 34 #include <alloca.h>
Chris@545 35 #endif
Chris@545 36
Chris@353 37 //#define DEBUG_COLOUR_3D_PLOT_LAYER_PAINT 1
Chris@125 38
Chris@0 39
Chris@44 40 Colour3DPlotLayer::Colour3DPlotLayer() :
Chris@0 41 m_model(0),
Chris@159 42 m_cache(0),
Chris@469 43 m_peaksCache(0),
Chris@474 44 m_peakResolution(256),
Chris@461 45 m_cacheValidStart(0),
Chris@461 46 m_cacheValidEnd(0),
Chris@197 47 m_colourScale(LinearScale),
Chris@461 48 m_colourScaleSet(false),
Chris@197 49 m_colourMap(0),
Chris@534 50 m_gain(1.0),
Chris@531 51 m_binScale(LinearBinScale),
Chris@197 52 m_normalizeColumns(false),
Chris@357 53 m_normalizeVisibleArea(false),
Chris@719 54 m_normalizeHybrid(false),
Chris@444 55 m_invertVertical(false),
Chris@465 56 m_opaque(false),
Chris@535 57 m_smooth(false),
Chris@444 58 m_miny(0),
Chris@444 59 m_maxy(0)
Chris@0 60 {
Chris@44 61
Chris@0 62 }
Chris@0 63
Chris@0 64 Colour3DPlotLayer::~Colour3DPlotLayer()
Chris@0 65 {
Chris@461 66 delete m_cache;
Chris@469 67 delete m_peaksCache;
Chris@0 68 }
Chris@0 69
Chris@0 70 void
Chris@0 71 Colour3DPlotLayer::setModel(const DenseThreeDimensionalModel *model)
Chris@0 72 {
Chris@193 73 if (m_model == model) return;
Chris@193 74 const DenseThreeDimensionalModel *oldModel = m_model;
Chris@0 75 m_model = model;
Chris@0 76 if (!m_model || !m_model->isOK()) return;
Chris@0 77
Chris@320 78 connectSignals(m_model);
Chris@0 79
Chris@461 80 connect(m_model, SIGNAL(modelChanged()), this, SLOT(modelChanged()));
Chris@0 81 connect(m_model, SIGNAL(modelChanged(size_t, size_t)),
Chris@461 82 this, SLOT(modelChanged(size_t, size_t)));
Chris@0 83
Chris@474 84 m_peakResolution = 256;
Chris@474 85 if (model->getResolution() > 512) {
Chris@474 86 m_peakResolution = 16;
Chris@474 87 } else if (model->getResolution() > 128) {
Chris@474 88 m_peakResolution = 64;
Chris@474 89 } else if (model->getResolution() > 2) {
Chris@474 90 m_peakResolution = 128;
Chris@474 91 }
Chris@474 92 cacheInvalid();
Chris@474 93
Chris@0 94 emit modelReplaced();
Chris@193 95 emit sliceableModelReplaced(oldModel, model);
Chris@0 96 }
Chris@0 97
Chris@0 98 void
Chris@0 99 Colour3DPlotLayer::cacheInvalid()
Chris@0 100 {
Chris@469 101 delete m_cache;
Chris@469 102 delete m_peaksCache;
Chris@0 103 m_cache = 0;
Chris@469 104 m_peaksCache = 0;
Chris@461 105 m_cacheValidStart = 0;
Chris@461 106 m_cacheValidEnd = 0;
Chris@0 107 }
Chris@0 108
Chris@0 109 void
Chris@461 110 Colour3DPlotLayer::cacheInvalid(size_t startFrame, size_t endFrame)
Chris@0 111 {
Chris@461 112 if (!m_cache) return;
Chris@461 113
Chris@461 114 size_t modelResolution = m_model->getResolution();
Chris@461 115 size_t start = startFrame / modelResolution;
Chris@461 116 size_t end = endFrame / modelResolution + 1;
Chris@461 117 if (m_cacheValidStart < end) m_cacheValidStart = end;
Chris@461 118 if (m_cacheValidEnd > start) m_cacheValidEnd = start;
Chris@461 119 if (m_cacheValidStart > m_cacheValidEnd) m_cacheValidEnd = m_cacheValidStart;
Chris@461 120 }
Chris@461 121
Chris@461 122 void
Chris@461 123 Colour3DPlotLayer::modelChanged()
Chris@461 124 {
Chris@461 125 if (!m_colourScaleSet && m_colourScale == LinearScale) {
Chris@461 126 if (m_model) {
Chris@461 127 if (m_model->shouldUseLogValueScale()) {
Chris@461 128 setColourScale(LogScale);
Chris@461 129 } else {
Chris@461 130 m_colourScaleSet = true;
Chris@461 131 }
Chris@461 132 }
Chris@461 133 }
Chris@0 134 cacheInvalid();
Chris@0 135 }
Chris@0 136
Chris@461 137 void
Chris@461 138 Colour3DPlotLayer::modelChanged(size_t startFrame, size_t endFrame)
Chris@461 139 {
Chris@461 140 if (!m_colourScaleSet && m_colourScale == LinearScale) {
Chris@461 141 if (m_model && m_model->getWidth() > 50) {
Chris@461 142 if (m_model->shouldUseLogValueScale()) {
Chris@461 143 setColourScale(LogScale);
Chris@461 144 } else {
Chris@461 145 m_colourScaleSet = true;
Chris@461 146 }
Chris@461 147 }
Chris@461 148 }
Chris@461 149 cacheInvalid(startFrame, endFrame);
Chris@461 150 }
Chris@461 151
Chris@159 152 Layer::PropertyList
Chris@159 153 Colour3DPlotLayer::getProperties() const
Chris@159 154 {
Chris@159 155 PropertyList list;
Chris@197 156 list.push_back("Colour");
Chris@159 157 list.push_back("Colour Scale");
Chris@197 158 list.push_back("Normalize Columns");
Chris@197 159 list.push_back("Normalize Visible Area");
Chris@534 160 list.push_back("Gain");
Chris@531 161 list.push_back("Bin Scale");
Chris@357 162 list.push_back("Invert Vertical Scale");
Chris@465 163 list.push_back("Opaque");
Chris@535 164 list.push_back("Smooth");
Chris@159 165 return list;
Chris@159 166 }
Chris@159 167
Chris@159 168 QString
Chris@159 169 Colour3DPlotLayer::getPropertyLabel(const PropertyName &name) const
Chris@159 170 {
Chris@197 171 if (name == "Colour") return tr("Colour");
Chris@197 172 if (name == "Colour Scale") return tr("Scale");
Chris@197 173 if (name == "Normalize Columns") return tr("Normalize Columns");
Chris@197 174 if (name == "Normalize Visible Area") return tr("Normalize Visible Area");
Chris@357 175 if (name == "Invert Vertical Scale") return tr("Invert Vertical Scale");
Chris@534 176 if (name == "Gain") return tr("Gain");
Chris@465 177 if (name == "Opaque") return tr("Always Opaque");
Chris@535 178 if (name == "Smooth") return tr("Smooth");
Chris@531 179 if (name == "Bin Scale") return tr("Bin Scale");
Chris@159 180 return "";
Chris@159 181 }
Chris@159 182
Chris@346 183 QString
Chris@346 184 Colour3DPlotLayer::getPropertyIconName(const PropertyName &name) const
Chris@346 185 {
Chris@346 186 if (name == "Normalize Columns") return "normalise-columns";
Chris@346 187 if (name == "Normalize Visible Area") return "normalise";
Chris@357 188 if (name == "Invert Vertical Scale") return "invert-vertical";
Chris@465 189 if (name == "Opaque") return "opaque";
Chris@535 190 if (name == "Smooth") return "smooth";
Chris@346 191 return "";
Chris@346 192 }
Chris@346 193
Chris@159 194 Layer::PropertyType
Chris@159 195 Colour3DPlotLayer::getPropertyType(const PropertyName &name) const
Chris@159 196 {
Chris@534 197 if (name == "Gain") return RangeProperty;
Chris@197 198 if (name == "Normalize Columns") return ToggleProperty;
Chris@197 199 if (name == "Normalize Visible Area") return ToggleProperty;
Chris@357 200 if (name == "Invert Vertical Scale") return ToggleProperty;
Chris@465 201 if (name == "Opaque") return ToggleProperty;
Chris@535 202 if (name == "Smooth") return ToggleProperty;
Chris@159 203 return ValueProperty;
Chris@159 204 }
Chris@159 205
Chris@159 206 QString
Chris@159 207 Colour3DPlotLayer::getPropertyGroupName(const PropertyName &name) const
Chris@159 208 {
Chris@197 209 if (name == "Normalize Columns" ||
Chris@197 210 name == "Normalize Visible Area" ||
Chris@534 211 name == "Colour Scale" ||
Chris@534 212 name == "Gain") return tr("Scale");
Chris@531 213 if (name == "Bin Scale" ||
Chris@531 214 name == "Invert Vertical Scale") return tr("Bins");
Chris@465 215 if (name == "Opaque" ||
Chris@535 216 name == "Smooth" ||
Chris@465 217 name == "Colour") return tr("Colour");
Chris@159 218 return QString();
Chris@159 219 }
Chris@159 220
Chris@159 221 int
Chris@159 222 Colour3DPlotLayer::getPropertyRangeAndValue(const PropertyName &name,
Chris@216 223 int *min, int *max, int *deflt) const
Chris@159 224 {
Chris@216 225 int val = 0;
Chris@159 226
Chris@216 227 int garbage0, garbage1, garbage2;
Chris@159 228 if (!min) min = &garbage0;
Chris@159 229 if (!max) max = &garbage1;
Chris@216 230 if (!deflt) deflt = &garbage2;
Chris@159 231
Chris@534 232 if (name == "Gain") {
Chris@534 233
Chris@534 234 *min = -50;
Chris@534 235 *max = 50;
Chris@534 236
Chris@534 237 *deflt = lrintf(log10(1.f) * 20.0);;
Chris@534 238 if (*deflt < *min) *deflt = *min;
Chris@534 239 if (*deflt > *max) *deflt = *max;
Chris@534 240
Chris@534 241 val = lrintf(log10(m_gain) * 20.0);
Chris@534 242 if (val < *min) val = *min;
Chris@534 243 if (val > *max) val = *max;
Chris@534 244
Chris@534 245 } else if (name == "Colour Scale") {
Chris@159 246
Chris@159 247 *min = 0;
Chris@509 248 *max = 3;
Chris@216 249 *deflt = (int)LinearScale;
Chris@159 250
Chris@216 251 val = (int)m_colourScale;
Chris@159 252
Chris@197 253 } else if (name == "Colour") {
Chris@197 254
Chris@197 255 *min = 0;
Chris@197 256 *max = ColourMapper::getColourMapCount() - 1;
Chris@216 257 *deflt = 0;
Chris@197 258
Chris@216 259 val = m_colourMap;
Chris@197 260
Chris@197 261 } else if (name == "Normalize Columns") {
Chris@197 262
Chris@216 263 *deflt = 0;
Chris@216 264 val = (m_normalizeColumns ? 1 : 0);
Chris@197 265
Chris@197 266 } else if (name == "Normalize Visible Area") {
Chris@197 267
Chris@216 268 *deflt = 0;
Chris@216 269 val = (m_normalizeVisibleArea ? 1 : 0);
Chris@197 270
Chris@357 271 } else if (name == "Invert Vertical Scale") {
Chris@357 272
Chris@357 273 *deflt = 0;
Chris@357 274 val = (m_invertVertical ? 1 : 0);
Chris@357 275
Chris@531 276 } else if (name == "Bin Scale") {
Chris@531 277
Chris@531 278 *min = 0;
Chris@531 279 *max = 1;
Chris@531 280 *deflt = int(LinearBinScale);
Chris@531 281 val = (int)m_binScale;
Chris@531 282
Chris@465 283 } else if (name == "Opaque") {
Chris@465 284
Chris@465 285 *deflt = 0;
Chris@465 286 val = (m_opaque ? 1 : 0);
Chris@465 287
Chris@535 288 } else if (name == "Smooth") {
Chris@535 289
Chris@535 290 *deflt = 0;
Chris@535 291 val = (m_smooth ? 1 : 0);
Chris@535 292
Chris@159 293 } else {
Chris@216 294 val = Layer::getPropertyRangeAndValue(name, min, max, deflt);
Chris@159 295 }
Chris@159 296
Chris@216 297 return val;
Chris@159 298 }
Chris@159 299
Chris@159 300 QString
Chris@159 301 Colour3DPlotLayer::getPropertyValueLabel(const PropertyName &name,
Chris@159 302 int value) const
Chris@159 303 {
Chris@197 304 if (name == "Colour") {
Chris@197 305 return ColourMapper::getColourMapName(value);
Chris@197 306 }
Chris@159 307 if (name == "Colour Scale") {
Chris@159 308 switch (value) {
Chris@159 309 default:
Chris@198 310 case 0: return tr("Linear");
Chris@198 311 case 1: return tr("Log");
Chris@198 312 case 2: return tr("+/-1");
Chris@509 313 case 3: return tr("Absolute");
Chris@159 314 }
Chris@159 315 }
Chris@531 316 if (name == "Bin Scale") {
Chris@531 317 switch (value) {
Chris@531 318 default:
Chris@531 319 case 0: return tr("Linear");
Chris@531 320 case 1: return tr("Log");
Chris@531 321 }
Chris@531 322 }
Chris@159 323 return tr("<unknown>");
Chris@159 324 }
Chris@159 325
Chris@534 326 RangeMapper *
Chris@534 327 Colour3DPlotLayer::getNewPropertyRangeMapper(const PropertyName &name) const
Chris@534 328 {
Chris@534 329 if (name == "Gain") {
Chris@534 330 return new LinearRangeMapper(-50, 50, -25, 25, tr("dB"));
Chris@534 331 }
Chris@534 332 return 0;
Chris@534 333 }
Chris@534 334
Chris@159 335 void
Chris@159 336 Colour3DPlotLayer::setProperty(const PropertyName &name, int value)
Chris@159 337 {
Chris@534 338 if (name == "Gain") {
Chris@534 339 setGain(pow(10, float(value)/20.0));
Chris@534 340 } else if (name == "Colour Scale") {
Chris@159 341 switch (value) {
Chris@159 342 default:
Chris@159 343 case 0: setColourScale(LinearScale); break;
Chris@197 344 case 1: setColourScale(LogScale); break;
Chris@197 345 case 2: setColourScale(PlusMinusOneScale); break;
Chris@509 346 case 3: setColourScale(AbsoluteScale); break;
Chris@159 347 }
Chris@197 348 } else if (name == "Colour") {
Chris@197 349 setColourMap(value);
Chris@197 350 } else if (name == "Normalize Columns") {
Chris@197 351 setNormalizeColumns(value ? true : false);
Chris@197 352 } else if (name == "Normalize Visible Area") {
Chris@197 353 setNormalizeVisibleArea(value ? true : false);
Chris@357 354 } else if (name == "Invert Vertical Scale") {
Chris@357 355 setInvertVertical(value ? true : false);
Chris@465 356 } else if (name == "Opaque") {
Chris@465 357 setOpaque(value ? true : false);
Chris@535 358 } else if (name == "Smooth") {
Chris@535 359 setSmooth(value ? true : false);
Chris@531 360 } else if (name == "Bin Scale") {
Chris@531 361 switch (value) {
Chris@531 362 default:
Chris@531 363 case 0: setBinScale(LinearBinScale); break;
Chris@531 364 case 1: setBinScale(LogBinScale); break;
Chris@531 365 }
Chris@159 366 }
Chris@159 367 }
Chris@159 368
Chris@159 369 void
Chris@159 370 Colour3DPlotLayer::setColourScale(ColourScale scale)
Chris@159 371 {
Chris@159 372 if (m_colourScale == scale) return;
Chris@159 373 m_colourScale = scale;
Chris@461 374 m_colourScaleSet = true;
Chris@159 375 cacheInvalid();
Chris@159 376 emit layerParametersChanged();
Chris@159 377 }
Chris@159 378
Chris@197 379 void
Chris@197 380 Colour3DPlotLayer::setColourMap(int map)
Chris@197 381 {
Chris@197 382 if (m_colourMap == map) return;
Chris@197 383 m_colourMap = map;
Chris@197 384 cacheInvalid();
Chris@197 385 emit layerParametersChanged();
Chris@197 386 }
Chris@197 387
Chris@197 388 void
Chris@534 389 Colour3DPlotLayer::setGain(float gain)
Chris@534 390 {
Chris@534 391 if (m_gain == gain) return;
Chris@534 392 m_gain = gain;
Chris@534 393 cacheInvalid();
Chris@534 394 emit layerParametersChanged();
Chris@534 395 }
Chris@534 396
Chris@534 397 float
Chris@534 398 Colour3DPlotLayer::getGain() const
Chris@534 399 {
Chris@534 400 return m_gain;
Chris@534 401 }
Chris@534 402
Chris@534 403 void
Chris@531 404 Colour3DPlotLayer::setBinScale(BinScale binScale)
Chris@531 405 {
Chris@531 406 if (m_binScale == binScale) return;
Chris@531 407 m_binScale = binScale;
Chris@531 408 cacheInvalid();
Chris@531 409 emit layerParametersChanged();
Chris@531 410 }
Chris@531 411
Chris@531 412 Colour3DPlotLayer::BinScale
Chris@531 413 Colour3DPlotLayer::getBinScale() const
Chris@531 414 {
Chris@531 415 return m_binScale;
Chris@531 416 }
Chris@531 417
Chris@531 418 void
Chris@197 419 Colour3DPlotLayer::setNormalizeColumns(bool n)
Chris@197 420 {
Chris@197 421 if (m_normalizeColumns == n) return;
Chris@197 422 m_normalizeColumns = n;
Chris@197 423 cacheInvalid();
Chris@197 424 emit layerParametersChanged();
Chris@197 425 }
Chris@197 426
Chris@197 427 bool
Chris@197 428 Colour3DPlotLayer::getNormalizeColumns() const
Chris@197 429 {
Chris@197 430 return m_normalizeColumns;
Chris@197 431 }
Chris@197 432
Chris@197 433 void
Chris@719 434 Colour3DPlotLayer::setNormalizeHybrid(bool n)
Chris@719 435 {
Chris@719 436 if (m_normalizeHybrid == n) return;
Chris@719 437 m_normalizeHybrid = n;
Chris@719 438 cacheInvalid();
Chris@719 439 emit layerParametersChanged();
Chris@719 440 }
Chris@719 441
Chris@719 442 bool
Chris@719 443 Colour3DPlotLayer::getNormalizeHybrid() const
Chris@719 444 {
Chris@719 445 return m_normalizeHybrid;
Chris@719 446 }
Chris@719 447
Chris@719 448 void
Chris@197 449 Colour3DPlotLayer::setNormalizeVisibleArea(bool n)
Chris@197 450 {
Chris@197 451 if (m_normalizeVisibleArea == n) return;
Chris@197 452 m_normalizeVisibleArea = n;
Chris@197 453 cacheInvalid();
Chris@197 454 emit layerParametersChanged();
Chris@197 455 }
Chris@197 456
Chris@197 457 bool
Chris@197 458 Colour3DPlotLayer::getNormalizeVisibleArea() const
Chris@197 459 {
Chris@197 460 return m_normalizeVisibleArea;
Chris@197 461 }
Chris@197 462
Chris@357 463 void
Chris@357 464 Colour3DPlotLayer::setInvertVertical(bool n)
Chris@357 465 {
Chris@357 466 if (m_invertVertical == n) return;
Chris@357 467 m_invertVertical = n;
Chris@357 468 cacheInvalid();
Chris@357 469 emit layerParametersChanged();
Chris@357 470 }
Chris@357 471
Chris@465 472 void
Chris@465 473 Colour3DPlotLayer::setOpaque(bool n)
Chris@465 474 {
Chris@465 475 if (m_opaque == n) return;
Chris@465 476 m_opaque = n;
Chris@465 477 emit layerParametersChanged();
Chris@465 478 }
Chris@465 479
Chris@535 480 void
Chris@535 481 Colour3DPlotLayer::setSmooth(bool n)
Chris@535 482 {
Chris@535 483 if (m_smooth == n) return;
Chris@535 484 m_smooth = n;
Chris@535 485 emit layerParametersChanged();
Chris@535 486 }
Chris@535 487
Chris@357 488 bool
Chris@357 489 Colour3DPlotLayer::getInvertVertical() const
Chris@357 490 {
Chris@357 491 return m_invertVertical;
Chris@357 492 }
Chris@357 493
Chris@25 494 bool
Chris@465 495 Colour3DPlotLayer::getOpaque() const
Chris@465 496 {
Chris@465 497 return m_opaque;
Chris@465 498 }
Chris@465 499
Chris@535 500 bool
Chris@535 501 Colour3DPlotLayer::getSmooth() const
Chris@535 502 {
Chris@535 503 return m_smooth;
Chris@535 504 }
Chris@535 505
Chris@475 506 void
Chris@475 507 Colour3DPlotLayer::setLayerDormant(const View *v, bool dormant)
Chris@475 508 {
Chris@475 509 if (dormant) {
Chris@475 510
Chris@475 511 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@587 512 SVDEBUG << "Colour3DPlotLayer::setLayerDormant(" << dormant << ")"
Chris@585 513 << endl;
Chris@475 514 #endif
Chris@475 515
Chris@475 516 if (isLayerDormant(v)) {
Chris@475 517 return;
Chris@475 518 }
Chris@475 519
Chris@475 520 Layer::setLayerDormant(v, true);
Chris@475 521
Chris@475 522 cacheInvalid();
Chris@475 523
Chris@475 524 } else {
Chris@475 525
Chris@475 526 Layer::setLayerDormant(v, false);
Chris@475 527 }
Chris@475 528 }
Chris@475 529
Chris@465 530 bool
Chris@44 531 Colour3DPlotLayer::isLayerScrollable(const View *v) const
Chris@25 532 {
Chris@197 533 if (m_normalizeVisibleArea) return false;
Chris@25 534 QPoint discard;
Chris@44 535 return !v->shouldIlluminateLocalFeatures(this, discard);
Chris@25 536 }
Chris@25 537
Chris@444 538 bool
Chris@444 539 Colour3DPlotLayer::getValueExtents(float &min, float &max,
Chris@444 540 bool &logarithmic, QString &unit) const
Chris@444 541 {
Chris@444 542 if (!m_model) return false;
Chris@444 543
Chris@444 544 min = 0;
Chris@444 545 max = m_model->getHeight();
Chris@444 546
Chris@444 547 logarithmic = false;
Chris@444 548 unit = "";
Chris@444 549
Chris@444 550 return true;
Chris@444 551 }
Chris@444 552
Chris@444 553 bool
Chris@444 554 Colour3DPlotLayer::getDisplayExtents(float &min, float &max) const
Chris@444 555 {
Chris@444 556 if (!m_model) return false;
Chris@444 557
Chris@444 558 min = m_miny;
Chris@444 559 max = m_maxy;
Chris@444 560 if (max <= min) {
Chris@444 561 min = 0;
Chris@444 562 max = m_model->getHeight();
Chris@444 563 }
Chris@444 564 if (min < 0) min = 0;
Chris@444 565 if (max > m_model->getHeight()) max = m_model->getHeight();
Chris@444 566
Chris@444 567 return true;
Chris@444 568 }
Chris@444 569
Chris@444 570 bool
Chris@444 571 Colour3DPlotLayer::setDisplayExtents(float min, float max)
Chris@444 572 {
Chris@444 573 if (!m_model) return false;
Chris@444 574
Chris@444 575 m_miny = lrintf(min);
Chris@444 576 m_maxy = lrintf(max);
Chris@444 577
Chris@444 578 emit layerParametersChanged();
Chris@444 579 return true;
Chris@444 580 }
Chris@444 581
Chris@444 582 int
Chris@444 583 Colour3DPlotLayer::getVerticalZoomSteps(int &defaultStep) const
Chris@444 584 {
Chris@444 585 if (!m_model) return 0;
Chris@444 586
Chris@444 587 defaultStep = 0;
Chris@444 588 int h = m_model->getHeight();
Chris@444 589 return h;
Chris@444 590 }
Chris@444 591
Chris@444 592 int
Chris@444 593 Colour3DPlotLayer::getCurrentVerticalZoomStep() const
Chris@444 594 {
Chris@444 595 if (!m_model) return 0;
Chris@444 596
Chris@444 597 float min, max;
Chris@444 598 getDisplayExtents(min, max);
Chris@444 599 return m_model->getHeight() - lrintf(max - min);
Chris@444 600 }
Chris@444 601
Chris@444 602 void
Chris@444 603 Colour3DPlotLayer::setVerticalZoomStep(int step)
Chris@444 604 {
Chris@444 605 if (!m_model) return;
Chris@444 606
Chris@587 607 // SVDEBUG << "Colour3DPlotLayer::setVerticalZoomStep(" <<step <<"): before: miny = " << m_miny << ", maxy = " << m_maxy << endl;
Chris@444 608
Chris@444 609 int dist = m_model->getHeight() - step;
Chris@444 610 if (dist < 1) dist = 1;
Chris@444 611 float centre = m_miny + (float(m_maxy) - float(m_miny)) / 2.f;
Chris@444 612 m_miny = lrintf(centre - float(dist)/2);
Chris@444 613 if (m_miny < 0) m_miny = 0;
Chris@444 614 m_maxy = m_miny + dist;
Chris@444 615 if (m_maxy > m_model->getHeight()) m_maxy = m_model->getHeight();
Chris@444 616
Chris@587 617 // SVDEBUG << "Colour3DPlotLayer::setVerticalZoomStep(" <<step <<"): after: miny = " << m_miny << ", maxy = " << m_maxy << endl;
Chris@444 618
Chris@444 619 emit layerParametersChanged();
Chris@444 620 }
Chris@444 621
Chris@444 622 RangeMapper *
Chris@444 623 Colour3DPlotLayer::getNewVerticalZoomRangeMapper() const
Chris@444 624 {
Chris@444 625 if (!m_model) return 0;
Chris@444 626
Chris@444 627 return new LinearRangeMapper(0, m_model->getHeight(),
Chris@444 628 0, m_model->getHeight(), "");
Chris@444 629 }
Chris@444 630
Chris@532 631 float
Chris@532 632 Colour3DPlotLayer::getYForBin(View *v, float bin) const
Chris@532 633 {
Chris@532 634 float y = bin;
Chris@532 635 if (!m_model) return y;
Chris@532 636 float mn = 0, mx = m_model->getHeight();
Chris@532 637 getDisplayExtents(mn, mx);
Chris@532 638 float h = v->height();
Chris@532 639 if (m_binScale == LinearBinScale) {
Chris@532 640 y = h - (((bin - mn) * h) / (mx - mn));
Chris@532 641 } else {
Chris@532 642 float logmin = mn + 1, logmax = mx + 1;
Chris@532 643 LogRange::mapRange(logmin, logmax);
Chris@532 644 y = h - (((LogRange::map(bin + 1) - logmin) * h) / (logmax - logmin));
Chris@532 645 }
Chris@532 646 return y;
Chris@532 647 }
Chris@532 648
Chris@532 649 float
Chris@532 650 Colour3DPlotLayer::getBinForY(View *v, float y) const
Chris@532 651 {
Chris@532 652 float bin = y;
Chris@532 653 if (!m_model) return bin;
Chris@532 654 float mn = 0, mx = m_model->getHeight();
Chris@532 655 getDisplayExtents(mn, mx);
Chris@532 656 float h = v->height();
Chris@532 657 if (m_binScale == LinearBinScale) {
Chris@532 658 bin = mn + ((h - y) * (mx - mn)) / h;
Chris@532 659 } else {
Chris@532 660 float logmin = mn + 1, logmax = mx + 1;
Chris@532 661 LogRange::mapRange(logmin, logmax);
Chris@532 662 bin = LogRange::unmap(logmin + ((h - y) * (logmax - logmin)) / h) - 1;
Chris@532 663 }
Chris@532 664 return bin;
Chris@532 665 }
Chris@532 666
Chris@25 667 QString
Chris@44 668 Colour3DPlotLayer::getFeatureDescription(View *v, QPoint &pos) const
Chris@25 669 {
Chris@25 670 if (!m_model) return "";
Chris@25 671
Chris@25 672 int x = pos.x();
Chris@25 673 int y = pos.y();
Chris@25 674
Chris@25 675 size_t modelStart = m_model->getStartFrame();
Chris@130 676 size_t modelResolution = m_model->getResolution();
Chris@25 677
Chris@159 678 float srRatio =
Chris@159 679 float(v->getViewManager()->getMainModelSampleRate()) /
Chris@159 680 float(m_model->getSampleRate());
Chris@159 681
Chris@160 682 int sx0 = int((v->getFrameForX(x) / srRatio - long(modelStart)) /
Chris@160 683 long(modelResolution));
Chris@25 684
Chris@160 685 int f0 = sx0 * modelResolution;
Chris@160 686 int f1 = f0 + modelResolution;
Chris@160 687
Chris@447 688 int sh = m_model->getHeight();
Chris@447 689
Chris@447 690 int symin = m_miny;
Chris@447 691 int symax = m_maxy;
Chris@447 692 if (symax <= symin) {
Chris@447 693 symin = 0;
Chris@447 694 symax = sh;
Chris@447 695 }
Chris@447 696 if (symin < 0) symin = 0;
Chris@447 697 if (symax > sh) symax = sh;
Chris@447 698
Chris@534 699 // float binHeight = float(v->height()) / (symax - symin);
Chris@534 700 // int sy = int((v->height() - y) / binHeight) + symin;
Chris@534 701
Chris@534 702 int sy = getBinForY(v, y);
Chris@25 703
Chris@357 704 if (m_invertVertical) sy = m_model->getHeight() - sy - 1;
Chris@357 705
Chris@160 706 float value = m_model->getValueAt(sx0, sy);
Chris@159 707
Chris@682 708 // cerr << "bin value (" << sx0 << "," << sy << ") is " << value << endl;
Chris@25 709
Chris@25 710 QString binName = m_model->getBinName(sy);
Chris@25 711 if (binName == "") binName = QString("[%1]").arg(sy + 1);
Chris@25 712 else binName = QString("%1 [%2]").arg(binName).arg(sy + 1);
Chris@25 713
Chris@25 714 QString text = tr("Time:\t%1 - %2\nBin:\t%3\nValue:\t%4")
Chris@160 715 .arg(RealTime::frame2RealTime(f0, m_model->getSampleRate())
Chris@25 716 .toText(true).c_str())
Chris@160 717 .arg(RealTime::frame2RealTime(f1, m_model->getSampleRate())
Chris@25 718 .toText(true).c_str())
Chris@25 719 .arg(binName)
Chris@25 720 .arg(value);
Chris@25 721
Chris@25 722 return text;
Chris@25 723 }
Chris@25 724
Chris@25 725 int
Chris@248 726 Colour3DPlotLayer::getColourScaleWidth(QPainter &) const
Chris@159 727 {
Chris@159 728 int cw = 20;
Chris@159 729 return cw;
Chris@159 730 }
Chris@159 731
Chris@159 732 int
Chris@607 733 Colour3DPlotLayer::getVerticalScaleWidth(View *, bool, QPainter &paint) const
Chris@25 734 {
Chris@25 735 if (!m_model) return 0;
Chris@25 736
Chris@160 737 QString sampleText = QString("[%1]").arg(m_model->getHeight());
Chris@25 738 int tw = paint.fontMetrics().width(sampleText);
Chris@98 739 bool another = false;
Chris@25 740
Chris@160 741 for (size_t i = 0; i < m_model->getHeight(); ++i) {
Chris@25 742 if (m_model->getBinName(i).length() > sampleText.length()) {
Chris@25 743 sampleText = m_model->getBinName(i);
Chris@98 744 another = true;
Chris@25 745 }
Chris@25 746 }
Chris@98 747 if (another) {
Chris@25 748 tw = std::max(tw, paint.fontMetrics().width(sampleText));
Chris@25 749 }
Chris@25 750
Chris@159 751 return tw + 13 + getColourScaleWidth(paint);
Chris@25 752 }
Chris@25 753
Chris@25 754 void
Chris@607 755 Colour3DPlotLayer::paintVerticalScale(View *v, bool, QPainter &paint, QRect rect) const
Chris@25 756 {
Chris@25 757 if (!m_model) return;
Chris@25 758
Chris@25 759 int h = rect.height(), w = rect.width();
Chris@25 760
Chris@159 761 int cw = getColourScaleWidth(paint);
Chris@159 762
Chris@159 763 int ch = h - 20;
Chris@159 764 if (ch > 20 && m_cache) {
Chris@159 765
Chris@447 766 float min = m_model->getMinimumLevel();
Chris@447 767 float max = m_model->getMaximumLevel();
Chris@447 768
Chris@447 769 float mmin = min;
Chris@447 770 float mmax = max;
Chris@447 771
Chris@447 772 if (m_colourScale == LogScale) {
Chris@447 773 LogRange::mapRange(mmin, mmax);
Chris@447 774 } else if (m_colourScale == PlusMinusOneScale) {
Chris@447 775 mmin = -1.f;
Chris@447 776 mmax = 1.f;
Chris@509 777 } else if (m_colourScale == AbsoluteScale) {
Chris@509 778 if (mmin < 0) {
Chris@509 779 if (fabsf(mmin) > fabsf(mmax)) mmax = fabsf(mmin);
Chris@509 780 else mmax = fabsf(mmax);
Chris@509 781 mmin = 0;
Chris@509 782 } else {
Chris@509 783 mmin = fabsf(mmin);
Chris@509 784 mmax = fabsf(mmax);
Chris@509 785 }
Chris@447 786 }
Chris@447 787
Chris@447 788 if (max == min) max = min + 1.0;
Chris@465 789 if (mmax == mmin) mmax = mmin + 1.0;
Chris@447 790
Chris@287 791 paint.setPen(v->getForeground());
Chris@447 792 paint.drawRect(4, 10, cw - 8, ch+1);
Chris@159 793
Chris@446 794 for (int y = 0; y < ch; ++y) {
Chris@447 795 float value = ((max - min) * (ch - y - 1)) / ch + min;
Chris@447 796 if (m_colourScale == LogScale) {
Chris@447 797 value = LogRange::map(value);
Chris@447 798 }
Chris@447 799 int pixel = int(((value - mmin) * 256) / (mmax - mmin));
Chris@465 800 if (pixel >= 0 && pixel < 256) {
Chris@465 801 QRgb c = m_cache->color(pixel);
Chris@465 802 paint.setPen(QColor(qRed(c), qGreen(c), qBlue(c)));
Chris@465 803 paint.drawLine(5, 11 + y, cw - 5, 11 + y);
Chris@465 804 } else {
Chris@682 805 cerr << "WARNING: Colour3DPlotLayer::paintVerticalScale: value " << value << ", mmin " << mmin << ", mmax " << mmax << " leads to invalid pixel " << pixel << endl;
Chris@465 806 }
Chris@159 807 }
Chris@446 808
Chris@446 809 QString minstr = QString("%1").arg(min);
Chris@446 810 QString maxstr = QString("%1").arg(max);
Chris@446 811
Chris@446 812 paint.save();
Chris@446 813
Chris@446 814 QFont font = paint.font();
Chris@446 815 font.setPixelSize(10);
Chris@446 816 paint.setFont(font);
Chris@446 817
Chris@446 818 int msw = paint.fontMetrics().width(maxstr);
Chris@446 819
Chris@446 820 QMatrix m;
Chris@446 821 m.translate(cw - 6, ch + 10);
Chris@446 822 m.rotate(-90);
Chris@446 823
Chris@446 824 paint.setWorldMatrix(m);
Chris@446 825
Chris@446 826 v->drawVisibleText(paint, 2, 0, minstr, View::OutlinedText);
Chris@446 827
Chris@446 828 m.translate(ch - msw - 2, 0);
Chris@446 829 paint.setWorldMatrix(m);
Chris@446 830
Chris@446 831 v->drawVisibleText(paint, 0, 0, maxstr, View::OutlinedText);
Chris@446 832
Chris@446 833 paint.restore();
Chris@159 834 }
Chris@159 835
Chris@287 836 paint.setPen(v->getForeground());
Chris@159 837
Chris@445 838 int sh = m_model->getHeight();
Chris@445 839
Chris@445 840 int symin = m_miny;
Chris@445 841 int symax = m_maxy;
Chris@445 842 if (symax <= symin) {
Chris@445 843 symin = 0;
Chris@445 844 symax = sh;
Chris@445 845 }
Chris@445 846 if (symin < 0) symin = 0;
Chris@445 847 if (symax > sh) symax = sh;
Chris@445 848
Chris@532 849 paint.save();
Chris@456 850
Chris@533 851 int py = h;
Chris@25 852
Chris@534 853 for (size_t i = symin; i <= symax; ++i) {
Chris@98 854
Chris@532 855 int y0;
Chris@534 856
Chris@532 857 y0 = lrintf(getYForBin(v, i));
Chris@532 858 int h = py - y0;
Chris@532 859
Chris@532 860 if (i > symin) {
Chris@532 861 if (paint.fontMetrics().height() >= h) {
Chris@533 862 if (h >= 8) {
Chris@532 863 QFont tf = paint.font();
Chris@533 864 tf.setPixelSize(h-2);
Chris@532 865 paint.setFont(tf);
Chris@532 866 } else {
Chris@532 867 continue;
Chris@532 868 }
Chris@532 869 }
Chris@532 870 }
Chris@25 871
Chris@532 872 py = y0;
Chris@532 873
Chris@534 874 if (i < symax) {
Chris@534 875 paint.drawLine(cw, y0, w, y0);
Chris@534 876 }
Chris@25 877
Chris@532 878 if (i > symin) {
Chris@534 879
Chris@534 880 size_t idx = i - 1;
Chris@534 881 if (m_invertVertical) idx = m_model->getHeight() - idx - 1;
Chris@534 882
Chris@534 883 QString text = m_model->getBinName(idx);
Chris@534 884 if (text == "") text = QString("[%1]").arg(idx + 1);
Chris@534 885
Chris@534 886 int ty = y0 + (h/2) - (paint.fontMetrics().height()/2) +
Chris@534 887 paint.fontMetrics().ascent() + 1;
Chris@534 888
Chris@534 889 paint.drawText(cw + 5, ty, text);
Chris@457 890 }
Chris@25 891 }
Chris@456 892
Chris@456 893 paint.restore();
Chris@25 894 }
Chris@25 895
Chris@467 896 DenseThreeDimensionalModel::Column
Chris@467 897 Colour3DPlotLayer::getColumn(size_t col) const
Chris@197 898 {
Chris@467 899 DenseThreeDimensionalModel::Column values = m_model->getColumn(col);
Chris@468 900 while (values.size() < m_model->getHeight()) values.push_back(0.f);
Chris@719 901 if (!m_normalizeColumns && !m_normalizeHybrid) return values;
Chris@461 902
Chris@224 903 float colMax = 0.f, colMin = 0.f;
Chris@461 904 float min = 0.f, max = 0.f;
Chris@197 905
Chris@461 906 min = m_model->getMinimumLevel();
Chris@461 907 max = m_model->getMaximumLevel();
Chris@461 908
Chris@461 909 for (size_t y = 0; y < values.size(); ++y) {
Chris@467 910 if (y == 0 || values.at(y) > colMax) colMax = values.at(y);
Chris@467 911 if (y == 0 || values.at(y) < colMin) colMin = values.at(y);
Chris@197 912 }
Chris@461 913 if (colMin == colMax) colMax = colMin + 1;
Chris@197 914
Chris@197 915 for (size_t y = 0; y < values.size(); ++y) {
Chris@461 916
Chris@467 917 float value = values.at(y);
Chris@461 918 float norm = (value - colMin) / (colMax - colMin);
Chris@467 919 float newvalue = min + (max - min) * norm;
Chris@197 920
Chris@467 921 if (value != newvalue) values[y] = newvalue;
Chris@468 922 }
Chris@468 923
Chris@719 924 if (m_normalizeHybrid && (colMax > 0.0)) {
Chris@719 925 float logmax = log10(colMax);
Chris@719 926 for (size_t y = 0; y < values.size(); ++y) {
Chris@719 927 values[y] *= logmax;
Chris@719 928 }
Chris@719 929 }
Chris@719 930
Chris@468 931 return values;
Chris@197 932 }
Chris@197 933
Chris@197 934 void
Chris@197 935 Colour3DPlotLayer::fillCache(size_t firstBin, size_t lastBin) const
Chris@197 936 {
Chris@466 937 Profiler profiler("Colour3DPlotLayer::fillCache");
Chris@476 938
Chris@197 939 size_t modelStart = m_model->getStartFrame();
Chris@197 940 size_t modelEnd = m_model->getEndFrame();
Chris@197 941 size_t modelResolution = m_model->getResolution();
Chris@197 942
Chris@519 943 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@587 944 SVDEBUG << "Colour3DPlotLayer::fillCache: " << firstBin << " -> " << lastBin << endl;
Chris@519 945 #endif
Chris@197 946
Chris@461 947 size_t modelStartBin = modelStart / modelResolution;
Chris@461 948 size_t modelEndBin = modelEnd / modelResolution;
Chris@461 949
Chris@461 950 size_t cacheWidth = modelEndBin - modelStartBin + 1;
Chris@471 951 if (lastBin > modelEndBin) cacheWidth = lastBin - modelStartBin + 1;
Chris@461 952 size_t cacheHeight = m_model->getHeight();
Chris@461 953
Chris@461 954 if (m_cache && (m_cache->height() != int(cacheHeight))) {
Chris@461 955 delete m_cache;
Chris@469 956 delete m_peaksCache;
Chris@461 957 m_cache = 0;
Chris@469 958 m_peaksCache = 0;
Chris@461 959 }
Chris@461 960
Chris@461 961 if (m_cache && (m_cache->width() != int(cacheWidth))) {
Chris@469 962 QImage *newCache =
Chris@469 963 new QImage(m_cache->copy(0, 0, cacheWidth, cacheHeight));
Chris@461 964 delete m_cache;
Chris@461 965 m_cache = newCache;
Chris@469 966 if (m_peaksCache) {
Chris@469 967 QImage *newPeaksCache =
Chris@469 968 new QImage(m_peaksCache->copy
Chris@469 969 (0, 0, cacheWidth / m_peakResolution, cacheHeight));
Chris@469 970 delete m_peaksCache;
Chris@469 971 m_peaksCache = newPeaksCache;
Chris@469 972 }
Chris@197 973 }
Chris@197 974
Chris@461 975 if (!m_cache) {
Chris@469 976 m_cache = new QImage
Chris@469 977 (cacheWidth, cacheHeight, QImage::Format_Indexed8);
Chris@616 978 // No longer exists in Qt5: m_cache->setNumColors(256);
Chris@514 979 m_cache->fill(0);
Chris@474 980 if (!m_normalizeVisibleArea) {
Chris@469 981 m_peaksCache = new QImage
Chris@469 982 (cacheWidth / m_peakResolution + 1, cacheHeight,
Chris@469 983 QImage::Format_Indexed8);
Chris@616 984 // No longer exists in Qt5: m_peaksCache->setNumColors(256);
Chris@514 985 m_peaksCache->fill(0);
Chris@469 986 } else if (m_peaksCache) {
Chris@469 987 delete m_peaksCache;
Chris@469 988 m_peaksCache = 0;
Chris@469 989 }
Chris@461 990 m_cacheValidStart = 0;
Chris@461 991 m_cacheValidEnd = 0;
Chris@197 992 }
Chris@197 993
Chris@461 994 if (m_cacheValidStart <= firstBin && m_cacheValidEnd >= lastBin) {
Chris@519 995 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@682 996 cerr << "Cache is valid in this region already" << endl;
Chris@519 997 #endif
Chris@461 998 return;
Chris@461 999 }
Chris@461 1000
Chris@461 1001 size_t fillStart = firstBin;
Chris@461 1002 size_t fillEnd = lastBin;
Chris@197 1003
Chris@461 1004 if (fillStart < modelStartBin) fillStart = modelStartBin;
Chris@461 1005 if (fillStart > modelEndBin) fillStart = modelEndBin;
Chris@461 1006 if (fillEnd < modelStartBin) fillEnd = modelStartBin;
Chris@461 1007 if (fillEnd > modelEndBin) fillEnd = modelEndBin;
Chris@197 1008
Chris@461 1009 bool normalizeVisible = (m_normalizeVisibleArea && !m_normalizeColumns);
Chris@197 1010
Chris@461 1011 if (!normalizeVisible && (m_cacheValidStart < m_cacheValidEnd)) {
Chris@461 1012
Chris@461 1013 if (m_cacheValidEnd < fillStart) {
Chris@461 1014 fillStart = m_cacheValidEnd + 1;
Chris@461 1015 }
Chris@461 1016 if (m_cacheValidStart > fillEnd) {
Chris@461 1017 fillEnd = m_cacheValidStart - 1;
Chris@461 1018 }
Chris@461 1019
Chris@461 1020 m_cacheValidStart = std::min(fillStart, m_cacheValidStart);
Chris@461 1021 m_cacheValidEnd = std::max(fillEnd, m_cacheValidEnd);
Chris@461 1022
Chris@461 1023 } else {
Chris@461 1024
Chris@461 1025 // the only valid area, ever, is the currently visible one
Chris@461 1026
Chris@461 1027 m_cacheValidStart = fillStart;
Chris@461 1028 m_cacheValidEnd = fillEnd;
Chris@461 1029 }
Chris@461 1030
Chris@519 1031 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@682 1032 cerr << "Cache size " << cacheWidth << "x" << cacheHeight << " will be valid from " << m_cacheValidStart << " to " << m_cacheValidEnd << endl;
Chris@519 1033 #endif
Chris@461 1034
Chris@197 1035 DenseThreeDimensionalModel::Column values;
Chris@197 1036
Chris@197 1037 float min = m_model->getMinimumLevel();
Chris@197 1038 float max = m_model->getMaximumLevel();
Chris@197 1039
Chris@197 1040 if (m_colourScale == LogScale) {
Chris@197 1041 LogRange::mapRange(min, max);
Chris@197 1042 } else if (m_colourScale == PlusMinusOneScale) {
Chris@197 1043 min = -1.f;
Chris@197 1044 max = 1.f;
Chris@509 1045 } else if (m_colourScale == AbsoluteScale) {
Chris@509 1046 if (min < 0) {
Chris@509 1047 if (fabsf(min) > fabsf(max)) max = fabsf(min);
Chris@509 1048 else max = fabsf(max);
Chris@509 1049 min = 0;
Chris@509 1050 } else {
Chris@509 1051 min = fabsf(min);
Chris@509 1052 max = fabsf(max);
Chris@509 1053 }
Chris@197 1054 }
Chris@197 1055
Chris@197 1056 if (max == min) max = min + 1.0;
Chris@197 1057
Chris@197 1058 ColourMapper mapper(m_colourMap, 0.f, 255.f);
Chris@197 1059
Chris@197 1060 for (int index = 0; index < 256; ++index) {
Chris@197 1061 QColor colour = mapper.map(index);
Chris@469 1062 m_cache->setColor
Chris@469 1063 (index, qRgb(colour.red(), colour.green(), colour.blue()));
Chris@469 1064 if (m_peaksCache) {
Chris@469 1065 m_peaksCache->setColor
Chris@469 1066 (index, qRgb(colour.red(), colour.green(), colour.blue()));
Chris@469 1067 }
Chris@197 1068 }
Chris@197 1069
Chris@224 1070 float visibleMax = 0.f, visibleMin = 0.f;
Chris@197 1071
Chris@461 1072 if (normalizeVisible) {
Chris@197 1073
Chris@461 1074 for (size_t c = fillStart; c <= fillEnd; ++c) {
Chris@197 1075
Chris@467 1076 values = getColumn(c);
Chris@197 1077
Chris@224 1078 float colMax = 0.f, colMin = 0.f;
Chris@197 1079
Chris@461 1080 for (size_t y = 0; y < cacheHeight; ++y) {
Chris@197 1081 if (y >= values.size()) break;
Chris@197 1082 if (y == 0 || values[y] > colMax) colMax = values[y];
Chris@224 1083 if (y == 0 || values[y] < colMin) colMin = values[y];
Chris@197 1084 }
Chris@197 1085
Chris@461 1086 if (c == fillStart || colMax > visibleMax) visibleMax = colMax;
Chris@461 1087 if (c == fillStart || colMin < visibleMin) visibleMin = colMin;
Chris@461 1088 }
Chris@461 1089
Chris@461 1090 if (m_colourScale == LogScale) {
Chris@461 1091 visibleMin = LogRange::map(visibleMin);
Chris@461 1092 visibleMax = LogRange::map(visibleMax);
Chris@461 1093 if (visibleMin > visibleMax) std::swap(visibleMin, visibleMax);
Chris@509 1094 } else if (m_colourScale == AbsoluteScale) {
Chris@509 1095 if (visibleMin < 0) {
Chris@509 1096 if (fabsf(visibleMin) > fabsf(visibleMax)) visibleMax = fabsf(visibleMin);
Chris@509 1097 else visibleMax = fabsf(visibleMax);
Chris@509 1098 visibleMin = 0;
Chris@509 1099 } else {
Chris@509 1100 visibleMin = fabsf(visibleMin);
Chris@509 1101 visibleMax = fabsf(visibleMax);
Chris@509 1102 }
Chris@197 1103 }
Chris@197 1104 }
Chris@197 1105
Chris@224 1106 if (visibleMin == visibleMax) visibleMax = visibleMin + 1;
Chris@224 1107
Chris@469 1108 int *peaks = 0;
Chris@469 1109 if (m_peaksCache) {
Chris@469 1110 peaks = new int[cacheHeight];
Chris@469 1111 for (int y = 0; y < cacheHeight; ++y) {
Chris@469 1112 peaks[y] = 0;
Chris@469 1113 }
Chris@469 1114 }
Chris@469 1115
Chris@461 1116 for (size_t c = fillStart; c <= fillEnd; ++c) {
Chris@197 1117
Chris@467 1118 values = getColumn(c);
Chris@197 1119
Chris@461 1120 for (size_t y = 0; y < cacheHeight; ++y) {
Chris@197 1121
Chris@197 1122 float value = min;
Chris@197 1123 if (y < values.size()) {
Chris@469 1124 value = values.at(y);
Chris@197 1125 }
Chris@224 1126
Chris@534 1127 value = value * m_gain;
Chris@534 1128
Chris@224 1129 if (m_colourScale == LogScale) {
Chris@224 1130 value = LogRange::map(value);
Chris@509 1131 } else if (m_colourScale == AbsoluteScale) {
Chris@509 1132 value = fabsf(value);
Chris@197 1133 }
Chris@461 1134
Chris@461 1135 if (normalizeVisible) {
Chris@461 1136 float norm = (value - visibleMin) / (visibleMax - visibleMin);
Chris@461 1137 value = min + (max - min) * norm;
Chris@461 1138 }
Chris@197 1139
Chris@197 1140 int pixel = int(((value - min) * 256) / (max - min));
Chris@197 1141 if (pixel < 0) pixel = 0;
Chris@197 1142 if (pixel > 255) pixel = 255;
Chris@469 1143 if (peaks && (pixel > peaks[y])) peaks[y] = pixel;
Chris@197 1144
Chris@357 1145 if (m_invertVertical) {
Chris@461 1146 m_cache->setPixel(c, cacheHeight - y - 1, pixel);
Chris@357 1147 } else {
Chris@461 1148 m_cache->setPixel(c, y, pixel);
Chris@357 1149 }
Chris@197 1150 }
Chris@469 1151
Chris@469 1152 if (peaks) {
Chris@469 1153 size_t notch = (c % m_peakResolution);
Chris@469 1154 if (notch == m_peakResolution-1 || c == fillEnd) {
Chris@469 1155 size_t pc = c / m_peakResolution;
Chris@469 1156 for (size_t y = 0; y < cacheHeight; ++y) {
Chris@469 1157 if (m_invertVertical) {
Chris@469 1158 m_peaksCache->setPixel(pc, cacheHeight - y - 1, peaks[y]);
Chris@469 1159 } else {
Chris@469 1160 m_peaksCache->setPixel(pc, y, peaks[y]);
Chris@469 1161 }
Chris@469 1162 }
Chris@469 1163 for (int y = 0; y < cacheHeight; ++y) {
Chris@469 1164 peaks[y] = 0;
Chris@469 1165 }
Chris@469 1166 }
Chris@469 1167 }
Chris@197 1168 }
Chris@469 1169
Chris@469 1170 delete[] peaks;
Chris@197 1171 }
Chris@197 1172
Chris@197 1173 void
Chris@44 1174 Colour3DPlotLayer::paint(View *v, QPainter &paint, QRect rect) const
Chris@0 1175 {
Chris@514 1176 /*
Chris@443 1177 if (m_model) {
Chris@587 1178 SVDEBUG << "Colour3DPlotLayer::paint: model says shouldUseLogValueScale = " << m_model->shouldUseLogValueScale() << endl;
Chris@443 1179 }
Chris@514 1180 */
Chris@466 1181 Profiler profiler("Colour3DPlotLayer::paint");
Chris@125 1182 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@587 1183 SVDEBUG << "Colour3DPlotLayer::paint(): m_model is " << m_model << ", zoom level is " << v->getZoomLevel() << endl;
Chris@125 1184 #endif
Chris@0 1185
Chris@0 1186 int completion = 0;
Chris@0 1187 if (!m_model || !m_model->isOK() || !m_model->isReady(&completion)) {
Chris@0 1188 if (completion > 0) {
Chris@44 1189 paint.fillRect(0, 10, v->width() * completion / 100,
Chris@0 1190 10, QColor(120, 120, 120));
Chris@0 1191 }
Chris@0 1192 return;
Chris@0 1193 }
Chris@0 1194
Chris@197 1195 if (m_normalizeVisibleArea && !m_normalizeColumns) rect = v->rect();
Chris@197 1196
Chris@0 1197 size_t modelStart = m_model->getStartFrame();
Chris@0 1198 size_t modelEnd = m_model->getEndFrame();
Chris@130 1199 size_t modelResolution = m_model->getResolution();
Chris@0 1200
Chris@197 1201 // The cache is from the model's start frame to the model's end
Chris@197 1202 // frame at the model's window increment frames per pixel. We
Chris@197 1203 // want to draw from our start frame + x0 * zoomLevel to our start
Chris@197 1204 // frame + x1 * zoomLevel at zoomLevel frames per pixel.
Chris@12 1205
Chris@197 1206 // We have quite different paint mechanisms for rendering "large"
Chris@197 1207 // bins (more than one bin per pixel in both directions) and
Chris@197 1208 // "small". This is "large"; see paintDense below for "small".
Chris@12 1209
Chris@197 1210 int x0 = rect.left();
Chris@197 1211 int x1 = rect.right() + 1;
Chris@12 1212
Chris@197 1213 int h = v->height();
Chris@0 1214
Chris@197 1215 float srRatio =
Chris@197 1216 float(v->getViewManager()->getMainModelSampleRate()) /
Chris@197 1217 float(m_model->getSampleRate());
Chris@0 1218
Chris@197 1219 int sx0 = int((v->getFrameForX(x0) / srRatio - long(modelStart))
Chris@197 1220 / long(modelResolution));
Chris@197 1221 int sx1 = int((v->getFrameForX(x1) / srRatio - long(modelStart))
Chris@197 1222 / long(modelResolution));
Chris@197 1223 int sh = m_model->getHeight();
Chris@159 1224
Chris@444 1225 int symin = m_miny;
Chris@444 1226 int symax = m_maxy;
Chris@444 1227 if (symax <= symin) {
Chris@444 1228 symin = 0;
Chris@444 1229 symax = sh;
Chris@444 1230 }
Chris@444 1231 if (symin < 0) symin = 0;
Chris@444 1232 if (symax > sh) symax = sh;
Chris@444 1233
Chris@197 1234 if (sx0 > 0) --sx0;
Chris@197 1235 fillCache(sx0 < 0 ? 0 : sx0,
Chris@197 1236 sx1 < 0 ? 0 : sx1);
Chris@0 1237
Chris@351 1238 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@587 1239 SVDEBUG << "Colour3DPlotLayer::paint: height = "<< m_model->getHeight() << ", modelStart = " << modelStart << ", resolution = " << modelResolution << ", model rate = " << m_model->getSampleRate() << " (zoom level = " << v->getZoomLevel() << ", srRatio = " << srRatio << ")" << endl;
Chris@351 1240 #endif
Chris@351 1241
Chris@465 1242 if (m_opaque ||
Chris@535 1243 m_smooth ||
Chris@465 1244 int(m_model->getHeight()) >= v->height() ||
Chris@466 1245 ((modelResolution * srRatio) / v->getZoomLevel()) < 2) {
Chris@347 1246 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@587 1247 SVDEBUG << "calling paintDense" << endl;
Chris@347 1248 #endif
Chris@98 1249 paintDense(v, paint, rect);
Chris@98 1250 return;
Chris@98 1251 }
Chris@98 1252
Chris@125 1253 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@587 1254 SVDEBUG << "Colour3DPlotLayer::paint: w " << x1-x0 << ", h " << h << ", sx0 " << sx0 << ", sx1 " << sx1 << ", sw " << sx1-sx0 << ", sh " << sh << endl;
Chris@682 1255 cerr << "Colour3DPlotLayer: sample rate is " << m_model->getSampleRate() << ", resolution " << m_model->getResolution() << endl;
Chris@125 1256 #endif
Chris@0 1257
Chris@25 1258 QPoint illuminatePos;
Chris@44 1259 bool illuminate = v->shouldIlluminateLocalFeatures(this, illuminatePos);
Chris@54 1260 char labelbuf[10];
Chris@25 1261
Chris@197 1262 for (int sx = sx0; sx <= sx1; ++sx) {
Chris@0 1263
Chris@130 1264 int fx = sx * int(modelResolution);
Chris@0 1265
Chris@351 1266 if (fx + int(modelResolution) <= int(modelStart) ||
Chris@0 1267 fx > int(modelEnd)) continue;
Chris@0 1268
Chris@248 1269 int rx0 = v->getXForFrame(int((fx + int(modelStart)) * srRatio));
Chris@248 1270 int rx1 = v->getXForFrame(int((fx + int(modelStart) + int(modelResolution) + 1) * srRatio));
Chris@54 1271
Chris@159 1272 int rw = rx1 - rx0;
Chris@159 1273 if (rw < 1) rw = 1;
Chris@54 1274
Chris@159 1275 bool showLabel = (rw > 10 &&
Chris@159 1276 paint.fontMetrics().width("0.000000") < rw - 3 &&
Chris@54 1277 paint.fontMetrics().height() < (h / sh));
Chris@98 1278
Chris@444 1279 for (int sy = symin; sy < symax; ++sy) {
Chris@0 1280
Chris@534 1281 int ry0 = getYForBin(v, sy);
Chris@534 1282 int ry1 = getYForBin(v, sy + 1);
Chris@534 1283 QRect r(rx0, ry1, rw, ry0 - ry1);
Chris@534 1284
Chris@0 1285 QRgb pixel = qRgb(255, 255, 255);
Chris@461 1286 if (sx >= 0 && sx < m_cache->width() &&
Chris@0 1287 sy >= 0 && sy < m_cache->height()) {
Chris@461 1288 pixel = m_cache->pixel(sx, sy);
Chris@0 1289 }
Chris@0 1290
Chris@159 1291 if (rw == 1) {
Chris@159 1292 paint.setPen(pixel);
Chris@159 1293 paint.setBrush(Qt::NoBrush);
Chris@159 1294 paint.drawLine(r.x(), r.y(), r.x(), r.y() + r.height() - 1);
Chris@159 1295 continue;
Chris@159 1296 }
Chris@159 1297
Chris@0 1298 QColor pen(255, 255, 255, 80);
Chris@0 1299 QColor brush(pixel);
Chris@159 1300
Chris@159 1301 if (rw > 3 && r.height() > 3) {
Chris@159 1302 brush.setAlpha(160);
Chris@159 1303 }
Chris@159 1304
Chris@0 1305 paint.setPen(Qt::NoPen);
Chris@0 1306 paint.setBrush(brush);
Chris@0 1307
Chris@25 1308 if (illuminate) {
Chris@25 1309 if (r.contains(illuminatePos)) {
Chris@287 1310 paint.setPen(v->getForeground());
Chris@25 1311 }
Chris@25 1312 }
Chris@76 1313
Chris@125 1314 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@682 1315 // cerr << "rect " << r.x() << "," << r.y() << " "
Chris@682 1316 // << r.width() << "x" << r.height() << endl;
Chris@125 1317 #endif
Chris@25 1318
Chris@25 1319 paint.drawRect(r);
Chris@0 1320
Chris@54 1321 if (showLabel) {
Chris@461 1322 if (sx >= 0 && sx < m_cache->width() &&
Chris@54 1323 sy >= 0 && sy < m_cache->height()) {
Chris@461 1324 float value = m_model->getValueAt(sx, sy);
Chris@54 1325 sprintf(labelbuf, "%06f", value);
Chris@54 1326 QString text(labelbuf);
Chris@287 1327 paint.setPen(v->getBackground());
Chris@54 1328 paint.drawText(rx0 + 2,
Chris@54 1329 ry0 - h / sh - 1 + 2 + paint.fontMetrics().ascent(),
Chris@54 1330 text);
Chris@0 1331 }
Chris@0 1332 }
Chris@0 1333 }
Chris@0 1334 }
Chris@98 1335 }
Chris@0 1336
Chris@98 1337 void
Chris@98 1338 Colour3DPlotLayer::paintDense(View *v, QPainter &paint, QRect rect) const
Chris@98 1339 {
Chris@466 1340 Profiler profiler("Colour3DPlotLayer::paintDense");
Chris@463 1341 if (!m_cache) return;
Chris@463 1342
Chris@466 1343 float modelStart = m_model->getStartFrame();
Chris@466 1344 float modelResolution = m_model->getResolution();
Chris@0 1345
Chris@469 1346 int mmsr = v->getViewManager()->getMainModelSampleRate();
Chris@469 1347 int msr = m_model->getSampleRate();
Chris@469 1348 float srRatio = float(mmsr) / float(msr);
Chris@159 1349
Chris@98 1350 int x0 = rect.left();
Chris@98 1351 int x1 = rect.right() + 1;
Chris@0 1352
Chris@470 1353 const int w = x1 - x0; // const so it can be used as array size below
Chris@471 1354 int h = v->height(); // we always paint full height
Chris@160 1355 int sh = m_model->getHeight();
Chris@98 1356
Chris@444 1357 int symin = m_miny;
Chris@444 1358 int symax = m_maxy;
Chris@444 1359 if (symax <= symin) {
Chris@444 1360 symin = 0;
Chris@444 1361 symax = sh;
Chris@444 1362 }
Chris@444 1363 if (symin < 0) symin = 0;
Chris@444 1364 if (symax > sh) symax = sh;
Chris@444 1365
Chris@466 1366 QImage img(w, h, QImage::Format_Indexed8);
Chris@466 1367 img.setColorTable(m_cache->colorTable());
Chris@98 1368
Chris@466 1369 uchar *peaks = new uchar[w];
Chris@466 1370 memset(peaks, 0, w);
Chris@98 1371
Chris@469 1372 int zoomLevel = v->getZoomLevel();
Chris@469 1373
Chris@469 1374 QImage *source = m_cache;
Chris@474 1375
Chris@679 1376 SVDEBUG << "modelResolution " << modelResolution << ", srRatio "
Chris@474 1377 << srRatio << ", m_peakResolution " << m_peakResolution
Chris@474 1378 << ", zoomLevel " << zoomLevel << ", result "
Chris@474 1379 << ((modelResolution * srRatio * m_peakResolution) / zoomLevel)
Chris@679 1380 << endl;
Chris@474 1381
Chris@474 1382 if (m_peaksCache) {
Chris@474 1383 if (((modelResolution * srRatio * m_peakResolution) / zoomLevel) < 1) {
Chris@587 1384 SVDEBUG << "using peaks cache" << endl;
Chris@474 1385 source = m_peaksCache;
Chris@474 1386 modelResolution *= m_peakResolution;
Chris@474 1387 } else {
Chris@679 1388 SVDEBUG << "not using peaks cache" << endl;
Chris@474 1389 }
Chris@469 1390 } else {
Chris@679 1391 SVDEBUG << "have no peaks cache" << endl;
Chris@469 1392 }
Chris@469 1393
Chris@466 1394 int psy1i = -1;
Chris@469 1395 int sw = source->width();
Chris@470 1396
Chris@470 1397 long xf = -1;
Chris@470 1398 long nxf = v->getFrameForX(x0);
Chris@470 1399
Chris@535 1400 float epsilon = 0.000001;
Chris@535 1401
Chris@545 1402 #ifdef __GNUC__
Chris@535 1403 float sxa[w * 2];
Chris@545 1404 #else
Chris@545 1405 float *sxa = (float *)alloca(w * 2 * sizeof(float));
Chris@545 1406 #endif
Chris@470 1407 for (int x = 0; x < w; ++x) {
Chris@470 1408
Chris@470 1409 xf = nxf;
Chris@470 1410 nxf = xf + zoomLevel;
Chris@470 1411
Chris@470 1412 float sx0 = (float(xf) / srRatio - modelStart) / modelResolution;
Chris@470 1413 float sx1 = (float(nxf) / srRatio - modelStart) / modelResolution;
Chris@470 1414
Chris@535 1415 sxa[x*2] = sx0;
Chris@535 1416 sxa[x*2 + 1] = sx1;
Chris@470 1417 }
Chris@466 1418
Chris@532 1419 float logmin = symin+1, logmax = symax+1;
Chris@532 1420 LogRange::mapRange(logmin, logmax);
Chris@532 1421
Chris@535 1422 if (m_smooth) {
Chris@535 1423
Chris@535 1424 for (int y = 0; y < h; ++y) {
Chris@466 1425
Chris@535 1426 float sy = getBinForY(v, y) - 0.5;
Chris@535 1427 int syi = int(sy + epsilon);
Chris@535 1428 if (syi < 0 || syi >= source->height()) continue;
Chris@531 1429
Chris@535 1430 uchar *targetLine = img.scanLine(y);
Chris@535 1431 uchar *sourceLine = source->scanLine(syi);
Chris@535 1432 uchar *nextSource;
Chris@535 1433 if (syi + 1 < source->height()) {
Chris@535 1434 nextSource = source->scanLine(syi + 1);
Chris@535 1435 } else {
Chris@535 1436 nextSource = sourceLine;
Chris@535 1437 }
Chris@466 1438
Chris@466 1439 for (int x = 0; x < w; ++x) {
Chris@98 1440
Chris@535 1441 targetLine[x] = 0;
Chris@474 1442
Chris@535 1443 float sx0 = sxa[x*2];
Chris@537 1444 if (sx0 < 0) continue;
Chris@535 1445 int sx0i = int(sx0 + epsilon);
Chris@474 1446 if (sx0i >= sw) break;
Chris@98 1447
Chris@535 1448 float a, b, value;
Chris@535 1449
Chris@535 1450 float sx1 = sxa[x*2+1];
Chris@535 1451 if (sx1 > sx0 + 1.f) {
Chris@535 1452 int sx1i = int(sx1);
Chris@535 1453 bool have = false;
Chris@535 1454 for (int sx = sx0i; sx <= sx1i; ++sx) {
Chris@535 1455 if (sx < 0 || sx >= sw) continue;
Chris@535 1456 if (!have) {
Chris@535 1457 a = float(sourceLine[sx]);
Chris@535 1458 b = float(nextSource[sx]);
Chris@535 1459 have = true;
Chris@535 1460 } else {
Chris@535 1461 a = std::max(a, float(sourceLine[sx]));
Chris@535 1462 b = std::max(b, float(nextSource[sx]));
Chris@535 1463 }
Chris@535 1464 }
Chris@535 1465 float yprop = sy - syi;
Chris@535 1466 value = (a * (1.f - yprop) + b * yprop);
Chris@535 1467 } else {
Chris@535 1468 a = float(sourceLine[sx0i]);
Chris@535 1469 b = float(nextSource[sx0i]);
Chris@535 1470 float yprop = sy - syi;
Chris@535 1471 value = (a * (1.f - yprop) + b * yprop);
Chris@535 1472 int oi = sx0i + 1;
Chris@535 1473 float xprop = sx0 - sx0i;
Chris@535 1474 xprop -= 0.5;
Chris@535 1475 if (xprop < 0) {
Chris@535 1476 oi = sx0i - 1;
Chris@535 1477 xprop = -xprop;
Chris@535 1478 }
Chris@535 1479 if (oi < 0 || oi >= sw) oi = sx0i;
Chris@535 1480 a = float(sourceLine[oi]);
Chris@535 1481 b = float(nextSource[oi]);
Chris@535 1482 value = (value * (1.f - xprop) +
Chris@535 1483 (a * (1.f - yprop) + b * yprop) * xprop);
Chris@98 1484 }
Chris@535 1485
Chris@535 1486 int vi = lrintf(value);
Chris@535 1487 if (vi > 255) vi = 255;
Chris@535 1488 if (vi < 0) vi = 0;
Chris@535 1489 targetLine[x] = uchar(vi);
Chris@98 1490 }
Chris@466 1491 }
Chris@535 1492 } else {
Chris@535 1493
Chris@535 1494 for (int y = 0; y < h; ++y) {
Chris@535 1495
Chris@535 1496 float sy0, sy1;
Chris@535 1497
Chris@535 1498 sy0 = getBinForY(v, y + 1);
Chris@535 1499 sy1 = getBinForY(v, y);
Chris@535 1500
Chris@535 1501 int sy0i = int(sy0 + epsilon);
Chris@535 1502 int sy1i = int(sy1);
Chris@535 1503
Chris@535 1504 uchar *targetLine = img.scanLine(y);
Chris@535 1505
Chris@535 1506 if (sy0i == sy1i && sy0i == psy1i) { // same source scan line as just computed
Chris@535 1507 goto copy;
Chris@535 1508 }
Chris@535 1509
Chris@535 1510 for (int x = 0; x < w; ++x) {
Chris@535 1511 peaks[x] = 0;
Chris@535 1512 }
Chris@466 1513
Chris@535 1514 for (int sy = sy0i; sy <= sy1i; ++sy) {
Chris@535 1515
Chris@535 1516 if (sy < 0 || sy >= source->height()) continue;
Chris@535 1517
Chris@535 1518 uchar *sourceLine = source->scanLine(sy);
Chris@535 1519
Chris@535 1520 for (int x = 0; x < w; ++x) {
Chris@535 1521
Chris@537 1522 float sx1 = sxa[x*2 + 1];
Chris@537 1523 if (sx1 < 0) continue;
Chris@537 1524 int sx1i = int(sx1);
Chris@535 1525
Chris@537 1526 float sx0 = sxa[x*2];
Chris@537 1527 if (sx0 < 0) continue;
Chris@537 1528 int sx0i = int(sx0 + epsilon);
Chris@535 1529 if (sx0i >= sw) break;
Chris@535 1530
Chris@535 1531 uchar peak = 0;
Chris@535 1532 for (int sx = sx0i; sx <= sx1i; ++sx) {
Chris@535 1533 if (sx < 0 || sx >= sw) continue;
Chris@535 1534 if (sourceLine[sx] > peak) peak = sourceLine[sx];
Chris@535 1535 }
Chris@535 1536 peaks[x] = peak;
Chris@535 1537 }
Chris@535 1538 }
Chris@535 1539
Chris@535 1540 copy:
Chris@535 1541 for (int x = 0; x < w; ++x) {
Chris@535 1542 targetLine[x] = peaks[x];
Chris@535 1543 }
Chris@98 1544 }
Chris@0 1545 }
Chris@0 1546
Chris@469 1547 delete[] peaks;
Chris@469 1548
Chris@98 1549 paint.drawImage(x0, 0, img);
Chris@0 1550 }
Chris@0 1551
Chris@28 1552 bool
Chris@44 1553 Colour3DPlotLayer::snapToFeatureFrame(View *v, int &frame,
Chris@28 1554 size_t &resolution,
Chris@28 1555 SnapType snap) const
Chris@24 1556 {
Chris@24 1557 if (!m_model) {
Chris@44 1558 return Layer::snapToFeatureFrame(v, frame, resolution, snap);
Chris@24 1559 }
Chris@24 1560
Chris@130 1561 resolution = m_model->getResolution();
Chris@28 1562 int left = (frame / resolution) * resolution;
Chris@28 1563 int right = left + resolution;
Chris@28 1564
Chris@28 1565 switch (snap) {
Chris@28 1566 case SnapLeft: frame = left; break;
Chris@28 1567 case SnapRight: frame = right; break;
Chris@28 1568 case SnapNearest:
Chris@28 1569 case SnapNeighbouring:
Chris@28 1570 if (frame - left > right - frame) frame = right;
Chris@28 1571 else frame = left;
Chris@28 1572 break;
Chris@28 1573 }
Chris@24 1574
Chris@28 1575 return true;
Chris@24 1576 }
Chris@24 1577
Chris@316 1578 void
Chris@316 1579 Colour3DPlotLayer::toXml(QTextStream &stream,
Chris@316 1580 QString indent, QString extraAttributes) const
Chris@197 1581 {
Chris@316 1582 QString s = QString("scale=\"%1\" "
Chris@316 1583 "colourScheme=\"%2\" "
Chris@316 1584 "normalizeColumns=\"%3\" "
Chris@445 1585 "normalizeVisibleArea=\"%4\" "
Chris@445 1586 "minY=\"%5\" "
Chris@465 1587 "maxY=\"%6\" "
Chris@465 1588 "invertVertical=\"%7\" "
Chris@535 1589 "opaque=\"%8\" %9")
Chris@197 1590 .arg((int)m_colourScale)
Chris@197 1591 .arg(m_colourMap)
Chris@197 1592 .arg(m_normalizeColumns ? "true" : "false")
Chris@445 1593 .arg(m_normalizeVisibleArea ? "true" : "false")
Chris@445 1594 .arg(m_miny)
Chris@465 1595 .arg(m_maxy)
Chris@465 1596 .arg(m_invertVertical ? "true" : "false")
Chris@534 1597 .arg(m_opaque ? "true" : "false")
Chris@536 1598 .arg(QString("binScale=\"%1\" smooth=\"%2\" gain=\"%3\" ")
Chris@535 1599 .arg((int)m_binScale)
Chris@536 1600 .arg(m_smooth ? "true" : "false")
Chris@536 1601 .arg(m_gain));
Chris@535 1602
Chris@316 1603 Layer::toXml(stream, indent, extraAttributes + " " + s);
Chris@197 1604 }
Chris@197 1605
Chris@197 1606 void
Chris@197 1607 Colour3DPlotLayer::setProperties(const QXmlAttributes &attributes)
Chris@197 1608 {
Chris@445 1609 bool ok = false, alsoOk = false;
Chris@197 1610
Chris@197 1611 ColourScale scale = (ColourScale)attributes.value("scale").toInt(&ok);
Chris@197 1612 if (ok) setColourScale(scale);
Chris@197 1613
Chris@197 1614 int colourMap = attributes.value("colourScheme").toInt(&ok);
Chris@197 1615 if (ok) setColourMap(colourMap);
Chris@197 1616
Chris@534 1617 BinScale binscale = (BinScale)attributes.value("binScale").toInt(&ok);
Chris@534 1618 if (ok) setBinScale(binscale);
Chris@534 1619
Chris@197 1620 bool normalizeColumns =
Chris@197 1621 (attributes.value("normalizeColumns").trimmed() == "true");
Chris@197 1622 setNormalizeColumns(normalizeColumns);
Chris@197 1623
Chris@197 1624 bool normalizeVisibleArea =
Chris@197 1625 (attributes.value("normalizeVisibleArea").trimmed() == "true");
Chris@197 1626 setNormalizeVisibleArea(normalizeVisibleArea);
Chris@445 1627
Chris@465 1628 bool invertVertical =
Chris@465 1629 (attributes.value("invertVertical").trimmed() == "true");
Chris@465 1630 setInvertVertical(invertVertical);
Chris@465 1631
Chris@465 1632 bool opaque =
Chris@465 1633 (attributes.value("opaque").trimmed() == "true");
Chris@535 1634 setOpaque(opaque);
Chris@535 1635
Chris@535 1636 bool smooth =
Chris@535 1637 (attributes.value("smooth").trimmed() == "true");
Chris@535 1638 setSmooth(smooth);
Chris@465 1639
Chris@536 1640 float gain = attributes.value("gain").toFloat(&ok);
Chris@536 1641 if (ok) setGain(gain);
Chris@536 1642
Chris@445 1643 float min = attributes.value("minY").toFloat(&ok);
Chris@445 1644 float max = attributes.value("maxY").toFloat(&alsoOk);
Chris@445 1645 if (ok && alsoOk) setDisplayExtents(min, max);
Chris@197 1646 }
Chris@197 1647