annotate layer/Colour3DPlotLayer.cpp @ 789:9fd1bdf214dd tonioni

Play pointer: when user drags pane during playback such that the pointer is no longer visible, accept that and stop trying to track it until pointer naturally comes back within visible area
author Chris Cannam
date Thu, 12 Jun 2014 12:48:11 +0100
parents d7e8cefedbbc
children 1d526ba11a24
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@725 582 bool
Chris@725 583 Colour3DPlotLayer::getYScaleValue(const View *v, int y,
Chris@725 584 float &value, QString &unit) const
Chris@725 585 {
Chris@725 586 return false;//!!!
Chris@725 587 }
Chris@725 588
Chris@444 589 int
Chris@444 590 Colour3DPlotLayer::getVerticalZoomSteps(int &defaultStep) const
Chris@444 591 {
Chris@444 592 if (!m_model) return 0;
Chris@444 593
Chris@444 594 defaultStep = 0;
Chris@444 595 int h = m_model->getHeight();
Chris@444 596 return h;
Chris@444 597 }
Chris@444 598
Chris@444 599 int
Chris@444 600 Colour3DPlotLayer::getCurrentVerticalZoomStep() const
Chris@444 601 {
Chris@444 602 if (!m_model) return 0;
Chris@444 603
Chris@444 604 float min, max;
Chris@444 605 getDisplayExtents(min, max);
Chris@444 606 return m_model->getHeight() - lrintf(max - min);
Chris@444 607 }
Chris@444 608
Chris@444 609 void
Chris@444 610 Colour3DPlotLayer::setVerticalZoomStep(int step)
Chris@444 611 {
Chris@444 612 if (!m_model) return;
Chris@444 613
Chris@587 614 // SVDEBUG << "Colour3DPlotLayer::setVerticalZoomStep(" <<step <<"): before: miny = " << m_miny << ", maxy = " << m_maxy << endl;
Chris@444 615
Chris@444 616 int dist = m_model->getHeight() - step;
Chris@444 617 if (dist < 1) dist = 1;
Chris@444 618 float centre = m_miny + (float(m_maxy) - float(m_miny)) / 2.f;
Chris@444 619 m_miny = lrintf(centre - float(dist)/2);
Chris@444 620 if (m_miny < 0) m_miny = 0;
Chris@444 621 m_maxy = m_miny + dist;
Chris@444 622 if (m_maxy > m_model->getHeight()) m_maxy = m_model->getHeight();
Chris@444 623
Chris@587 624 // SVDEBUG << "Colour3DPlotLayer::setVerticalZoomStep(" <<step <<"): after: miny = " << m_miny << ", maxy = " << m_maxy << endl;
Chris@444 625
Chris@444 626 emit layerParametersChanged();
Chris@444 627 }
Chris@444 628
Chris@444 629 RangeMapper *
Chris@444 630 Colour3DPlotLayer::getNewVerticalZoomRangeMapper() const
Chris@444 631 {
Chris@444 632 if (!m_model) return 0;
Chris@444 633
Chris@444 634 return new LinearRangeMapper(0, m_model->getHeight(),
Chris@444 635 0, m_model->getHeight(), "");
Chris@444 636 }
Chris@444 637
Chris@532 638 float
Chris@532 639 Colour3DPlotLayer::getYForBin(View *v, float bin) const
Chris@532 640 {
Chris@532 641 float y = bin;
Chris@532 642 if (!m_model) return y;
Chris@532 643 float mn = 0, mx = m_model->getHeight();
Chris@532 644 getDisplayExtents(mn, mx);
Chris@532 645 float h = v->height();
Chris@532 646 if (m_binScale == LinearBinScale) {
Chris@532 647 y = h - (((bin - mn) * h) / (mx - mn));
Chris@532 648 } else {
Chris@532 649 float logmin = mn + 1, logmax = mx + 1;
Chris@532 650 LogRange::mapRange(logmin, logmax);
Chris@532 651 y = h - (((LogRange::map(bin + 1) - logmin) * h) / (logmax - logmin));
Chris@532 652 }
Chris@532 653 return y;
Chris@532 654 }
Chris@532 655
Chris@532 656 float
Chris@532 657 Colour3DPlotLayer::getBinForY(View *v, float y) const
Chris@532 658 {
Chris@532 659 float bin = y;
Chris@532 660 if (!m_model) return bin;
Chris@532 661 float mn = 0, mx = m_model->getHeight();
Chris@532 662 getDisplayExtents(mn, mx);
Chris@532 663 float h = v->height();
Chris@532 664 if (m_binScale == LinearBinScale) {
Chris@532 665 bin = mn + ((h - y) * (mx - mn)) / h;
Chris@532 666 } else {
Chris@532 667 float logmin = mn + 1, logmax = mx + 1;
Chris@532 668 LogRange::mapRange(logmin, logmax);
Chris@532 669 bin = LogRange::unmap(logmin + ((h - y) * (logmax - logmin)) / h) - 1;
Chris@532 670 }
Chris@532 671 return bin;
Chris@532 672 }
Chris@532 673
Chris@25 674 QString
Chris@44 675 Colour3DPlotLayer::getFeatureDescription(View *v, QPoint &pos) const
Chris@25 676 {
Chris@25 677 if (!m_model) return "";
Chris@25 678
Chris@25 679 int x = pos.x();
Chris@25 680 int y = pos.y();
Chris@25 681
Chris@25 682 size_t modelStart = m_model->getStartFrame();
Chris@130 683 size_t modelResolution = m_model->getResolution();
Chris@25 684
Chris@159 685 float srRatio =
Chris@159 686 float(v->getViewManager()->getMainModelSampleRate()) /
Chris@159 687 float(m_model->getSampleRate());
Chris@159 688
Chris@160 689 int sx0 = int((v->getFrameForX(x) / srRatio - long(modelStart)) /
Chris@160 690 long(modelResolution));
Chris@25 691
Chris@160 692 int f0 = sx0 * modelResolution;
Chris@160 693 int f1 = f0 + modelResolution;
Chris@160 694
Chris@447 695 int sh = m_model->getHeight();
Chris@447 696
Chris@447 697 int symin = m_miny;
Chris@447 698 int symax = m_maxy;
Chris@447 699 if (symax <= symin) {
Chris@447 700 symin = 0;
Chris@447 701 symax = sh;
Chris@447 702 }
Chris@447 703 if (symin < 0) symin = 0;
Chris@447 704 if (symax > sh) symax = sh;
Chris@447 705
Chris@534 706 // float binHeight = float(v->height()) / (symax - symin);
Chris@534 707 // int sy = int((v->height() - y) / binHeight) + symin;
Chris@534 708
Chris@534 709 int sy = getBinForY(v, y);
Chris@25 710
Chris@357 711 if (m_invertVertical) sy = m_model->getHeight() - sy - 1;
Chris@357 712
Chris@160 713 float value = m_model->getValueAt(sx0, sy);
Chris@159 714
Chris@682 715 // cerr << "bin value (" << sx0 << "," << sy << ") is " << value << endl;
Chris@25 716
Chris@25 717 QString binName = m_model->getBinName(sy);
Chris@25 718 if (binName == "") binName = QString("[%1]").arg(sy + 1);
Chris@25 719 else binName = QString("%1 [%2]").arg(binName).arg(sy + 1);
Chris@25 720
Chris@25 721 QString text = tr("Time:\t%1 - %2\nBin:\t%3\nValue:\t%4")
Chris@160 722 .arg(RealTime::frame2RealTime(f0, m_model->getSampleRate())
Chris@25 723 .toText(true).c_str())
Chris@160 724 .arg(RealTime::frame2RealTime(f1, m_model->getSampleRate())
Chris@25 725 .toText(true).c_str())
Chris@25 726 .arg(binName)
Chris@25 727 .arg(value);
Chris@25 728
Chris@25 729 return text;
Chris@25 730 }
Chris@25 731
Chris@25 732 int
Chris@248 733 Colour3DPlotLayer::getColourScaleWidth(QPainter &) const
Chris@159 734 {
Chris@159 735 int cw = 20;
Chris@159 736 return cw;
Chris@159 737 }
Chris@159 738
Chris@159 739 int
Chris@607 740 Colour3DPlotLayer::getVerticalScaleWidth(View *, bool, QPainter &paint) const
Chris@25 741 {
Chris@25 742 if (!m_model) return 0;
Chris@25 743
Chris@160 744 QString sampleText = QString("[%1]").arg(m_model->getHeight());
Chris@25 745 int tw = paint.fontMetrics().width(sampleText);
Chris@98 746 bool another = false;
Chris@25 747
Chris@160 748 for (size_t i = 0; i < m_model->getHeight(); ++i) {
Chris@25 749 if (m_model->getBinName(i).length() > sampleText.length()) {
Chris@25 750 sampleText = m_model->getBinName(i);
Chris@98 751 another = true;
Chris@25 752 }
Chris@25 753 }
Chris@98 754 if (another) {
Chris@25 755 tw = std::max(tw, paint.fontMetrics().width(sampleText));
Chris@25 756 }
Chris@25 757
Chris@159 758 return tw + 13 + getColourScaleWidth(paint);
Chris@25 759 }
Chris@25 760
Chris@25 761 void
Chris@607 762 Colour3DPlotLayer::paintVerticalScale(View *v, bool, QPainter &paint, QRect rect) const
Chris@25 763 {
Chris@25 764 if (!m_model) return;
Chris@25 765
Chris@25 766 int h = rect.height(), w = rect.width();
Chris@25 767
Chris@159 768 int cw = getColourScaleWidth(paint);
Chris@159 769
Chris@159 770 int ch = h - 20;
Chris@159 771 if (ch > 20 && m_cache) {
Chris@159 772
Chris@447 773 float min = m_model->getMinimumLevel();
Chris@447 774 float max = m_model->getMaximumLevel();
Chris@447 775
Chris@447 776 float mmin = min;
Chris@447 777 float mmax = max;
Chris@447 778
Chris@447 779 if (m_colourScale == LogScale) {
Chris@447 780 LogRange::mapRange(mmin, mmax);
Chris@447 781 } else if (m_colourScale == PlusMinusOneScale) {
Chris@447 782 mmin = -1.f;
Chris@447 783 mmax = 1.f;
Chris@509 784 } else if (m_colourScale == AbsoluteScale) {
Chris@509 785 if (mmin < 0) {
Chris@509 786 if (fabsf(mmin) > fabsf(mmax)) mmax = fabsf(mmin);
Chris@509 787 else mmax = fabsf(mmax);
Chris@509 788 mmin = 0;
Chris@509 789 } else {
Chris@509 790 mmin = fabsf(mmin);
Chris@509 791 mmax = fabsf(mmax);
Chris@509 792 }
Chris@447 793 }
Chris@447 794
Chris@447 795 if (max == min) max = min + 1.0;
Chris@465 796 if (mmax == mmin) mmax = mmin + 1.0;
Chris@447 797
Chris@287 798 paint.setPen(v->getForeground());
Chris@447 799 paint.drawRect(4, 10, cw - 8, ch+1);
Chris@159 800
Chris@446 801 for (int y = 0; y < ch; ++y) {
Chris@447 802 float value = ((max - min) * (ch - y - 1)) / ch + min;
Chris@447 803 if (m_colourScale == LogScale) {
Chris@447 804 value = LogRange::map(value);
Chris@447 805 }
Chris@447 806 int pixel = int(((value - mmin) * 256) / (mmax - mmin));
Chris@465 807 if (pixel >= 0 && pixel < 256) {
Chris@465 808 QRgb c = m_cache->color(pixel);
Chris@465 809 paint.setPen(QColor(qRed(c), qGreen(c), qBlue(c)));
Chris@465 810 paint.drawLine(5, 11 + y, cw - 5, 11 + y);
Chris@465 811 } else {
Chris@682 812 cerr << "WARNING: Colour3DPlotLayer::paintVerticalScale: value " << value << ", mmin " << mmin << ", mmax " << mmax << " leads to invalid pixel " << pixel << endl;
Chris@465 813 }
Chris@159 814 }
Chris@446 815
Chris@446 816 QString minstr = QString("%1").arg(min);
Chris@446 817 QString maxstr = QString("%1").arg(max);
Chris@446 818
Chris@446 819 paint.save();
Chris@446 820
Chris@446 821 QFont font = paint.font();
Chris@446 822 font.setPixelSize(10);
Chris@446 823 paint.setFont(font);
Chris@446 824
Chris@446 825 int msw = paint.fontMetrics().width(maxstr);
Chris@446 826
Chris@446 827 QMatrix m;
Chris@446 828 m.translate(cw - 6, ch + 10);
Chris@446 829 m.rotate(-90);
Chris@446 830
Chris@446 831 paint.setWorldMatrix(m);
Chris@446 832
Chris@446 833 v->drawVisibleText(paint, 2, 0, minstr, View::OutlinedText);
Chris@446 834
Chris@446 835 m.translate(ch - msw - 2, 0);
Chris@446 836 paint.setWorldMatrix(m);
Chris@446 837
Chris@446 838 v->drawVisibleText(paint, 0, 0, maxstr, View::OutlinedText);
Chris@446 839
Chris@446 840 paint.restore();
Chris@159 841 }
Chris@159 842
Chris@287 843 paint.setPen(v->getForeground());
Chris@159 844
Chris@445 845 int sh = m_model->getHeight();
Chris@445 846
Chris@445 847 int symin = m_miny;
Chris@445 848 int symax = m_maxy;
Chris@445 849 if (symax <= symin) {
Chris@445 850 symin = 0;
Chris@445 851 symax = sh;
Chris@445 852 }
Chris@445 853 if (symin < 0) symin = 0;
Chris@445 854 if (symax > sh) symax = sh;
Chris@445 855
Chris@532 856 paint.save();
Chris@456 857
Chris@533 858 int py = h;
Chris@25 859
Chris@534 860 for (size_t i = symin; i <= symax; ++i) {
Chris@98 861
Chris@532 862 int y0;
Chris@534 863
Chris@532 864 y0 = lrintf(getYForBin(v, i));
Chris@532 865 int h = py - y0;
Chris@532 866
Chris@532 867 if (i > symin) {
Chris@532 868 if (paint.fontMetrics().height() >= h) {
Chris@533 869 if (h >= 8) {
Chris@532 870 QFont tf = paint.font();
Chris@533 871 tf.setPixelSize(h-2);
Chris@532 872 paint.setFont(tf);
Chris@532 873 } else {
Chris@532 874 continue;
Chris@532 875 }
Chris@532 876 }
Chris@532 877 }
Chris@25 878
Chris@532 879 py = y0;
Chris@532 880
Chris@534 881 if (i < symax) {
Chris@534 882 paint.drawLine(cw, y0, w, y0);
Chris@534 883 }
Chris@25 884
Chris@532 885 if (i > symin) {
Chris@534 886
Chris@534 887 size_t idx = i - 1;
Chris@534 888 if (m_invertVertical) idx = m_model->getHeight() - idx - 1;
Chris@534 889
Chris@534 890 QString text = m_model->getBinName(idx);
Chris@534 891 if (text == "") text = QString("[%1]").arg(idx + 1);
Chris@534 892
Chris@534 893 int ty = y0 + (h/2) - (paint.fontMetrics().height()/2) +
Chris@534 894 paint.fontMetrics().ascent() + 1;
Chris@534 895
Chris@534 896 paint.drawText(cw + 5, ty, text);
Chris@457 897 }
Chris@25 898 }
Chris@456 899
Chris@456 900 paint.restore();
Chris@25 901 }
Chris@25 902
Chris@467 903 DenseThreeDimensionalModel::Column
Chris@467 904 Colour3DPlotLayer::getColumn(size_t col) const
Chris@197 905 {
Chris@467 906 DenseThreeDimensionalModel::Column values = m_model->getColumn(col);
Chris@468 907 while (values.size() < m_model->getHeight()) values.push_back(0.f);
Chris@719 908 if (!m_normalizeColumns && !m_normalizeHybrid) return values;
Chris@461 909
Chris@224 910 float colMax = 0.f, colMin = 0.f;
Chris@461 911 float min = 0.f, max = 0.f;
Chris@197 912
Chris@461 913 min = m_model->getMinimumLevel();
Chris@461 914 max = m_model->getMaximumLevel();
Chris@461 915
Chris@461 916 for (size_t y = 0; y < values.size(); ++y) {
Chris@467 917 if (y == 0 || values.at(y) > colMax) colMax = values.at(y);
Chris@467 918 if (y == 0 || values.at(y) < colMin) colMin = values.at(y);
Chris@197 919 }
Chris@461 920 if (colMin == colMax) colMax = colMin + 1;
Chris@197 921
Chris@197 922 for (size_t y = 0; y < values.size(); ++y) {
Chris@461 923
Chris@467 924 float value = values.at(y);
Chris@461 925 float norm = (value - colMin) / (colMax - colMin);
Chris@467 926 float newvalue = min + (max - min) * norm;
Chris@197 927
Chris@467 928 if (value != newvalue) values[y] = newvalue;
Chris@468 929 }
Chris@468 930
Chris@719 931 if (m_normalizeHybrid && (colMax > 0.0)) {
Chris@719 932 float logmax = log10(colMax);
Chris@719 933 for (size_t y = 0; y < values.size(); ++y) {
Chris@719 934 values[y] *= logmax;
Chris@719 935 }
Chris@719 936 }
Chris@719 937
Chris@468 938 return values;
Chris@197 939 }
Chris@197 940
Chris@197 941 void
Chris@197 942 Colour3DPlotLayer::fillCache(size_t firstBin, size_t lastBin) const
Chris@197 943 {
Chris@466 944 Profiler profiler("Colour3DPlotLayer::fillCache");
Chris@476 945
Chris@197 946 size_t modelStart = m_model->getStartFrame();
Chris@197 947 size_t modelEnd = m_model->getEndFrame();
Chris@197 948 size_t modelResolution = m_model->getResolution();
Chris@197 949
Chris@519 950 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@587 951 SVDEBUG << "Colour3DPlotLayer::fillCache: " << firstBin << " -> " << lastBin << endl;
Chris@519 952 #endif
Chris@197 953
Chris@461 954 size_t modelStartBin = modelStart / modelResolution;
Chris@461 955 size_t modelEndBin = modelEnd / modelResolution;
Chris@461 956
Chris@461 957 size_t cacheWidth = modelEndBin - modelStartBin + 1;
Chris@471 958 if (lastBin > modelEndBin) cacheWidth = lastBin - modelStartBin + 1;
Chris@461 959 size_t cacheHeight = m_model->getHeight();
Chris@461 960
Chris@461 961 if (m_cache && (m_cache->height() != int(cacheHeight))) {
Chris@742 962 // height has changed: delete everything rather than resizing
Chris@461 963 delete m_cache;
Chris@469 964 delete m_peaksCache;
Chris@461 965 m_cache = 0;
Chris@469 966 m_peaksCache = 0;
Chris@461 967 }
Chris@461 968
Chris@461 969 if (m_cache && (m_cache->width() != int(cacheWidth))) {
Chris@742 970 // width has changed and we have an existing cache: resize it
Chris@469 971 QImage *newCache =
Chris@469 972 new QImage(m_cache->copy(0, 0, cacheWidth, cacheHeight));
Chris@461 973 delete m_cache;
Chris@461 974 m_cache = newCache;
Chris@469 975 if (m_peaksCache) {
Chris@469 976 QImage *newPeaksCache =
Chris@469 977 new QImage(m_peaksCache->copy
Chris@742 978 (0, 0, cacheWidth / m_peakResolution + 1, cacheHeight));
Chris@469 979 delete m_peaksCache;
Chris@469 980 m_peaksCache = newPeaksCache;
Chris@469 981 }
Chris@197 982 }
Chris@197 983
Chris@461 984 if (!m_cache) {
Chris@469 985 m_cache = new QImage
Chris@469 986 (cacheWidth, cacheHeight, QImage::Format_Indexed8);
Chris@616 987 // No longer exists in Qt5: m_cache->setNumColors(256);
Chris@514 988 m_cache->fill(0);
Chris@474 989 if (!m_normalizeVisibleArea) {
Chris@469 990 m_peaksCache = new QImage
Chris@469 991 (cacheWidth / m_peakResolution + 1, cacheHeight,
Chris@469 992 QImage::Format_Indexed8);
Chris@616 993 // No longer exists in Qt5: m_peaksCache->setNumColors(256);
Chris@514 994 m_peaksCache->fill(0);
Chris@469 995 } else if (m_peaksCache) {
Chris@469 996 delete m_peaksCache;
Chris@469 997 m_peaksCache = 0;
Chris@469 998 }
Chris@461 999 m_cacheValidStart = 0;
Chris@461 1000 m_cacheValidEnd = 0;
Chris@197 1001 }
Chris@197 1002
Chris@742 1003 // cerr << "cache size = " << m_cache->width() << "x" << m_cache->height()
Chris@742 1004 // << " peaks cache size = " << m_peaksCache->width() << "x" << m_peaksCache->height() << endl;
Chris@742 1005
Chris@461 1006 if (m_cacheValidStart <= firstBin && m_cacheValidEnd >= lastBin) {
Chris@519 1007 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@682 1008 cerr << "Cache is valid in this region already" << endl;
Chris@519 1009 #endif
Chris@461 1010 return;
Chris@461 1011 }
Chris@461 1012
Chris@461 1013 size_t fillStart = firstBin;
Chris@461 1014 size_t fillEnd = lastBin;
Chris@197 1015
Chris@461 1016 if (fillStart < modelStartBin) fillStart = modelStartBin;
Chris@461 1017 if (fillStart > modelEndBin) fillStart = modelEndBin;
Chris@461 1018 if (fillEnd < modelStartBin) fillEnd = modelStartBin;
Chris@461 1019 if (fillEnd > modelEndBin) fillEnd = modelEndBin;
Chris@197 1020
Chris@461 1021 bool normalizeVisible = (m_normalizeVisibleArea && !m_normalizeColumns);
Chris@197 1022
Chris@461 1023 if (!normalizeVisible && (m_cacheValidStart < m_cacheValidEnd)) {
Chris@461 1024
Chris@461 1025 if (m_cacheValidEnd < fillStart) {
Chris@461 1026 fillStart = m_cacheValidEnd + 1;
Chris@461 1027 }
Chris@461 1028 if (m_cacheValidStart > fillEnd) {
Chris@461 1029 fillEnd = m_cacheValidStart - 1;
Chris@461 1030 }
Chris@461 1031
Chris@461 1032 m_cacheValidStart = std::min(fillStart, m_cacheValidStart);
Chris@461 1033 m_cacheValidEnd = std::max(fillEnd, m_cacheValidEnd);
Chris@461 1034
Chris@461 1035 } else {
Chris@461 1036
Chris@461 1037 // the only valid area, ever, is the currently visible one
Chris@461 1038
Chris@461 1039 m_cacheValidStart = fillStart;
Chris@461 1040 m_cacheValidEnd = fillEnd;
Chris@461 1041 }
Chris@461 1042
Chris@519 1043 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@682 1044 cerr << "Cache size " << cacheWidth << "x" << cacheHeight << " will be valid from " << m_cacheValidStart << " to " << m_cacheValidEnd << endl;
Chris@519 1045 #endif
Chris@461 1046
Chris@197 1047 DenseThreeDimensionalModel::Column values;
Chris@197 1048
Chris@197 1049 float min = m_model->getMinimumLevel();
Chris@197 1050 float max = m_model->getMaximumLevel();
Chris@197 1051
Chris@197 1052 if (m_colourScale == LogScale) {
Chris@197 1053 LogRange::mapRange(min, max);
Chris@197 1054 } else if (m_colourScale == PlusMinusOneScale) {
Chris@197 1055 min = -1.f;
Chris@197 1056 max = 1.f;
Chris@509 1057 } else if (m_colourScale == AbsoluteScale) {
Chris@509 1058 if (min < 0) {
Chris@509 1059 if (fabsf(min) > fabsf(max)) max = fabsf(min);
Chris@509 1060 else max = fabsf(max);
Chris@509 1061 min = 0;
Chris@509 1062 } else {
Chris@509 1063 min = fabsf(min);
Chris@509 1064 max = fabsf(max);
Chris@509 1065 }
Chris@197 1066 }
Chris@197 1067
Chris@197 1068 if (max == min) max = min + 1.0;
Chris@197 1069
Chris@197 1070 ColourMapper mapper(m_colourMap, 0.f, 255.f);
Chris@197 1071
Chris@197 1072 for (int index = 0; index < 256; ++index) {
Chris@197 1073 QColor colour = mapper.map(index);
Chris@469 1074 m_cache->setColor
Chris@469 1075 (index, qRgb(colour.red(), colour.green(), colour.blue()));
Chris@469 1076 if (m_peaksCache) {
Chris@469 1077 m_peaksCache->setColor
Chris@469 1078 (index, qRgb(colour.red(), colour.green(), colour.blue()));
Chris@469 1079 }
Chris@197 1080 }
Chris@197 1081
Chris@224 1082 float visibleMax = 0.f, visibleMin = 0.f;
Chris@197 1083
Chris@461 1084 if (normalizeVisible) {
Chris@197 1085
Chris@461 1086 for (size_t c = fillStart; c <= fillEnd; ++c) {
Chris@197 1087
Chris@467 1088 values = getColumn(c);
Chris@197 1089
Chris@224 1090 float colMax = 0.f, colMin = 0.f;
Chris@197 1091
Chris@461 1092 for (size_t y = 0; y < cacheHeight; ++y) {
Chris@197 1093 if (y >= values.size()) break;
Chris@197 1094 if (y == 0 || values[y] > colMax) colMax = values[y];
Chris@224 1095 if (y == 0 || values[y] < colMin) colMin = values[y];
Chris@197 1096 }
Chris@197 1097
Chris@461 1098 if (c == fillStart || colMax > visibleMax) visibleMax = colMax;
Chris@461 1099 if (c == fillStart || colMin < visibleMin) visibleMin = colMin;
Chris@461 1100 }
Chris@461 1101
Chris@461 1102 if (m_colourScale == LogScale) {
Chris@461 1103 visibleMin = LogRange::map(visibleMin);
Chris@461 1104 visibleMax = LogRange::map(visibleMax);
Chris@461 1105 if (visibleMin > visibleMax) std::swap(visibleMin, visibleMax);
Chris@509 1106 } else if (m_colourScale == AbsoluteScale) {
Chris@509 1107 if (visibleMin < 0) {
Chris@509 1108 if (fabsf(visibleMin) > fabsf(visibleMax)) visibleMax = fabsf(visibleMin);
Chris@509 1109 else visibleMax = fabsf(visibleMax);
Chris@509 1110 visibleMin = 0;
Chris@509 1111 } else {
Chris@509 1112 visibleMin = fabsf(visibleMin);
Chris@509 1113 visibleMax = fabsf(visibleMax);
Chris@509 1114 }
Chris@197 1115 }
Chris@197 1116 }
Chris@197 1117
Chris@224 1118 if (visibleMin == visibleMax) visibleMax = visibleMin + 1;
Chris@224 1119
Chris@469 1120 int *peaks = 0;
Chris@469 1121 if (m_peaksCache) {
Chris@469 1122 peaks = new int[cacheHeight];
Chris@469 1123 for (int y = 0; y < cacheHeight; ++y) {
Chris@469 1124 peaks[y] = 0;
Chris@469 1125 }
Chris@469 1126 }
Chris@469 1127
Chris@461 1128 for (size_t c = fillStart; c <= fillEnd; ++c) {
Chris@197 1129
Chris@467 1130 values = getColumn(c);
Chris@197 1131
Chris@742 1132 if (c >= m_cache->width()) {
Chris@742 1133 cerr << "ERROR: column " << c << " >= cache width "
Chris@742 1134 << m_cache->width() << endl;
Chris@742 1135 continue;
Chris@742 1136 }
Chris@742 1137
Chris@461 1138 for (size_t y = 0; y < cacheHeight; ++y) {
Chris@197 1139
Chris@197 1140 float value = min;
Chris@197 1141 if (y < values.size()) {
Chris@469 1142 value = values.at(y);
Chris@197 1143 }
Chris@224 1144
Chris@534 1145 value = value * m_gain;
Chris@534 1146
Chris@224 1147 if (m_colourScale == LogScale) {
Chris@224 1148 value = LogRange::map(value);
Chris@509 1149 } else if (m_colourScale == AbsoluteScale) {
Chris@509 1150 value = fabsf(value);
Chris@197 1151 }
Chris@461 1152
Chris@461 1153 if (normalizeVisible) {
Chris@461 1154 float norm = (value - visibleMin) / (visibleMax - visibleMin);
Chris@461 1155 value = min + (max - min) * norm;
Chris@461 1156 }
Chris@197 1157
Chris@197 1158 int pixel = int(((value - min) * 256) / (max - min));
Chris@197 1159 if (pixel < 0) pixel = 0;
Chris@197 1160 if (pixel > 255) pixel = 255;
Chris@469 1161 if (peaks && (pixel > peaks[y])) peaks[y] = pixel;
Chris@197 1162
Chris@357 1163 if (m_invertVertical) {
Chris@461 1164 m_cache->setPixel(c, cacheHeight - y - 1, pixel);
Chris@357 1165 } else {
Chris@742 1166 if (y >= m_cache->height()) {
Chris@742 1167 cerr << "ERROR: row " << y << " >= cache height " << m_cache->height() << endl;
Chris@742 1168 } else {
Chris@742 1169 m_cache->setPixel(c, y, pixel);
Chris@742 1170 }
Chris@357 1171 }
Chris@197 1172 }
Chris@469 1173
Chris@469 1174 if (peaks) {
Chris@469 1175 size_t notch = (c % m_peakResolution);
Chris@469 1176 if (notch == m_peakResolution-1 || c == fillEnd) {
Chris@469 1177 size_t pc = c / m_peakResolution;
Chris@742 1178 if (pc >= m_peaksCache->width()) {
Chris@742 1179 cerr << "ERROR: peak column " << pc
Chris@742 1180 << " (from col " << c << ") >= peaks cache width "
Chris@742 1181 << m_peaksCache->width() << endl;
Chris@742 1182 continue;
Chris@742 1183 }
Chris@469 1184 for (size_t y = 0; y < cacheHeight; ++y) {
Chris@469 1185 if (m_invertVertical) {
Chris@469 1186 m_peaksCache->setPixel(pc, cacheHeight - y - 1, peaks[y]);
Chris@469 1187 } else {
Chris@742 1188 if (y >= m_peaksCache->height()) {
Chris@742 1189 cerr << "ERROR: row " << y
Chris@742 1190 << " >= peaks cache height "
Chris@742 1191 << m_peaksCache->height() << endl;
Chris@742 1192 } else {
Chris@742 1193 m_peaksCache->setPixel(pc, y, peaks[y]);
Chris@742 1194 }
Chris@469 1195 }
Chris@469 1196 }
Chris@469 1197 for (int y = 0; y < cacheHeight; ++y) {
Chris@469 1198 peaks[y] = 0;
Chris@469 1199 }
Chris@469 1200 }
Chris@469 1201 }
Chris@197 1202 }
Chris@469 1203
Chris@469 1204 delete[] peaks;
Chris@197 1205 }
Chris@197 1206
Chris@197 1207 void
Chris@44 1208 Colour3DPlotLayer::paint(View *v, QPainter &paint, QRect rect) const
Chris@0 1209 {
Chris@514 1210 /*
Chris@443 1211 if (m_model) {
Chris@587 1212 SVDEBUG << "Colour3DPlotLayer::paint: model says shouldUseLogValueScale = " << m_model->shouldUseLogValueScale() << endl;
Chris@443 1213 }
Chris@514 1214 */
Chris@466 1215 Profiler profiler("Colour3DPlotLayer::paint");
Chris@125 1216 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@587 1217 SVDEBUG << "Colour3DPlotLayer::paint(): m_model is " << m_model << ", zoom level is " << v->getZoomLevel() << endl;
Chris@125 1218 #endif
Chris@0 1219
Chris@0 1220 int completion = 0;
Chris@0 1221 if (!m_model || !m_model->isOK() || !m_model->isReady(&completion)) {
Chris@0 1222 if (completion > 0) {
Chris@44 1223 paint.fillRect(0, 10, v->width() * completion / 100,
Chris@0 1224 10, QColor(120, 120, 120));
Chris@0 1225 }
Chris@0 1226 return;
Chris@0 1227 }
Chris@0 1228
Chris@197 1229 if (m_normalizeVisibleArea && !m_normalizeColumns) rect = v->rect();
Chris@197 1230
Chris@0 1231 size_t modelStart = m_model->getStartFrame();
Chris@0 1232 size_t modelEnd = m_model->getEndFrame();
Chris@130 1233 size_t modelResolution = m_model->getResolution();
Chris@0 1234
Chris@197 1235 // The cache is from the model's start frame to the model's end
Chris@197 1236 // frame at the model's window increment frames per pixel. We
Chris@197 1237 // want to draw from our start frame + x0 * zoomLevel to our start
Chris@197 1238 // frame + x1 * zoomLevel at zoomLevel frames per pixel.
Chris@12 1239
Chris@197 1240 // We have quite different paint mechanisms for rendering "large"
Chris@197 1241 // bins (more than one bin per pixel in both directions) and
Chris@197 1242 // "small". This is "large"; see paintDense below for "small".
Chris@12 1243
Chris@197 1244 int x0 = rect.left();
Chris@197 1245 int x1 = rect.right() + 1;
Chris@12 1246
Chris@197 1247 int h = v->height();
Chris@0 1248
Chris@197 1249 float srRatio =
Chris@197 1250 float(v->getViewManager()->getMainModelSampleRate()) /
Chris@197 1251 float(m_model->getSampleRate());
Chris@0 1252
Chris@197 1253 int sx0 = int((v->getFrameForX(x0) / srRatio - long(modelStart))
Chris@197 1254 / long(modelResolution));
Chris@197 1255 int sx1 = int((v->getFrameForX(x1) / srRatio - long(modelStart))
Chris@197 1256 / long(modelResolution));
Chris@197 1257 int sh = m_model->getHeight();
Chris@159 1258
Chris@444 1259 int symin = m_miny;
Chris@444 1260 int symax = m_maxy;
Chris@444 1261 if (symax <= symin) {
Chris@444 1262 symin = 0;
Chris@444 1263 symax = sh;
Chris@444 1264 }
Chris@444 1265 if (symin < 0) symin = 0;
Chris@444 1266 if (symax > sh) symax = sh;
Chris@444 1267
Chris@197 1268 if (sx0 > 0) --sx0;
Chris@197 1269 fillCache(sx0 < 0 ? 0 : sx0,
Chris@197 1270 sx1 < 0 ? 0 : sx1);
Chris@0 1271
Chris@351 1272 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@587 1273 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 1274 #endif
Chris@351 1275
Chris@465 1276 if (m_opaque ||
Chris@535 1277 m_smooth ||
Chris@465 1278 int(m_model->getHeight()) >= v->height() ||
Chris@466 1279 ((modelResolution * srRatio) / v->getZoomLevel()) < 2) {
Chris@347 1280 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@587 1281 SVDEBUG << "calling paintDense" << endl;
Chris@347 1282 #endif
Chris@98 1283 paintDense(v, paint, rect);
Chris@98 1284 return;
Chris@98 1285 }
Chris@98 1286
Chris@125 1287 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@587 1288 SVDEBUG << "Colour3DPlotLayer::paint: w " << x1-x0 << ", h " << h << ", sx0 " << sx0 << ", sx1 " << sx1 << ", sw " << sx1-sx0 << ", sh " << sh << endl;
Chris@682 1289 cerr << "Colour3DPlotLayer: sample rate is " << m_model->getSampleRate() << ", resolution " << m_model->getResolution() << endl;
Chris@125 1290 #endif
Chris@0 1291
Chris@25 1292 QPoint illuminatePos;
Chris@44 1293 bool illuminate = v->shouldIlluminateLocalFeatures(this, illuminatePos);
Chris@54 1294 char labelbuf[10];
Chris@25 1295
Chris@197 1296 for (int sx = sx0; sx <= sx1; ++sx) {
Chris@0 1297
Chris@130 1298 int fx = sx * int(modelResolution);
Chris@0 1299
Chris@351 1300 if (fx + int(modelResolution) <= int(modelStart) ||
Chris@0 1301 fx > int(modelEnd)) continue;
Chris@0 1302
Chris@248 1303 int rx0 = v->getXForFrame(int((fx + int(modelStart)) * srRatio));
Chris@248 1304 int rx1 = v->getXForFrame(int((fx + int(modelStart) + int(modelResolution) + 1) * srRatio));
Chris@54 1305
Chris@159 1306 int rw = rx1 - rx0;
Chris@159 1307 if (rw < 1) rw = 1;
Chris@54 1308
Chris@159 1309 bool showLabel = (rw > 10 &&
Chris@159 1310 paint.fontMetrics().width("0.000000") < rw - 3 &&
Chris@54 1311 paint.fontMetrics().height() < (h / sh));
Chris@98 1312
Chris@444 1313 for (int sy = symin; sy < symax; ++sy) {
Chris@0 1314
Chris@534 1315 int ry0 = getYForBin(v, sy);
Chris@534 1316 int ry1 = getYForBin(v, sy + 1);
Chris@534 1317 QRect r(rx0, ry1, rw, ry0 - ry1);
Chris@534 1318
Chris@0 1319 QRgb pixel = qRgb(255, 255, 255);
Chris@461 1320 if (sx >= 0 && sx < m_cache->width() &&
Chris@0 1321 sy >= 0 && sy < m_cache->height()) {
Chris@461 1322 pixel = m_cache->pixel(sx, sy);
Chris@0 1323 }
Chris@0 1324
Chris@159 1325 if (rw == 1) {
Chris@159 1326 paint.setPen(pixel);
Chris@159 1327 paint.setBrush(Qt::NoBrush);
Chris@159 1328 paint.drawLine(r.x(), r.y(), r.x(), r.y() + r.height() - 1);
Chris@159 1329 continue;
Chris@159 1330 }
Chris@159 1331
Chris@0 1332 QColor pen(255, 255, 255, 80);
Chris@0 1333 QColor brush(pixel);
Chris@159 1334
Chris@159 1335 if (rw > 3 && r.height() > 3) {
Chris@159 1336 brush.setAlpha(160);
Chris@159 1337 }
Chris@159 1338
Chris@0 1339 paint.setPen(Qt::NoPen);
Chris@0 1340 paint.setBrush(brush);
Chris@0 1341
Chris@25 1342 if (illuminate) {
Chris@25 1343 if (r.contains(illuminatePos)) {
Chris@287 1344 paint.setPen(v->getForeground());
Chris@25 1345 }
Chris@25 1346 }
Chris@76 1347
Chris@125 1348 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
Chris@682 1349 // cerr << "rect " << r.x() << "," << r.y() << " "
Chris@682 1350 // << r.width() << "x" << r.height() << endl;
Chris@125 1351 #endif
Chris@25 1352
Chris@25 1353 paint.drawRect(r);
Chris@0 1354
Chris@54 1355 if (showLabel) {
Chris@461 1356 if (sx >= 0 && sx < m_cache->width() &&
Chris@54 1357 sy >= 0 && sy < m_cache->height()) {
Chris@461 1358 float value = m_model->getValueAt(sx, sy);
Chris@54 1359 sprintf(labelbuf, "%06f", value);
Chris@54 1360 QString text(labelbuf);
Chris@287 1361 paint.setPen(v->getBackground());
Chris@54 1362 paint.drawText(rx0 + 2,
Chris@54 1363 ry0 - h / sh - 1 + 2 + paint.fontMetrics().ascent(),
Chris@54 1364 text);
Chris@0 1365 }
Chris@0 1366 }
Chris@0 1367 }
Chris@0 1368 }
Chris@98 1369 }
Chris@0 1370
Chris@98 1371 void
Chris@98 1372 Colour3DPlotLayer::paintDense(View *v, QPainter &paint, QRect rect) const
Chris@98 1373 {
Chris@466 1374 Profiler profiler("Colour3DPlotLayer::paintDense");
Chris@463 1375 if (!m_cache) return;
Chris@463 1376
Chris@466 1377 float modelStart = m_model->getStartFrame();
Chris@466 1378 float modelResolution = m_model->getResolution();
Chris@0 1379
Chris@469 1380 int mmsr = v->getViewManager()->getMainModelSampleRate();
Chris@469 1381 int msr = m_model->getSampleRate();
Chris@469 1382 float srRatio = float(mmsr) / float(msr);
Chris@159 1383
Chris@98 1384 int x0 = rect.left();
Chris@98 1385 int x1 = rect.right() + 1;
Chris@0 1386
Chris@470 1387 const int w = x1 - x0; // const so it can be used as array size below
Chris@471 1388 int h = v->height(); // we always paint full height
Chris@160 1389 int sh = m_model->getHeight();
Chris@98 1390
Chris@444 1391 int symin = m_miny;
Chris@444 1392 int symax = m_maxy;
Chris@444 1393 if (symax <= symin) {
Chris@444 1394 symin = 0;
Chris@444 1395 symax = sh;
Chris@444 1396 }
Chris@444 1397 if (symin < 0) symin = 0;
Chris@444 1398 if (symax > sh) symax = sh;
Chris@444 1399
Chris@466 1400 QImage img(w, h, QImage::Format_Indexed8);
Chris@466 1401 img.setColorTable(m_cache->colorTable());
Chris@98 1402
Chris@466 1403 uchar *peaks = new uchar[w];
Chris@466 1404 memset(peaks, 0, w);
Chris@98 1405
Chris@469 1406 int zoomLevel = v->getZoomLevel();
Chris@469 1407
Chris@469 1408 QImage *source = m_cache;
Chris@474 1409
Chris@679 1410 SVDEBUG << "modelResolution " << modelResolution << ", srRatio "
Chris@474 1411 << srRatio << ", m_peakResolution " << m_peakResolution
Chris@474 1412 << ", zoomLevel " << zoomLevel << ", result "
Chris@474 1413 << ((modelResolution * srRatio * m_peakResolution) / zoomLevel)
Chris@679 1414 << endl;
Chris@474 1415
Chris@474 1416 if (m_peaksCache) {
Chris@474 1417 if (((modelResolution * srRatio * m_peakResolution) / zoomLevel) < 1) {
Chris@587 1418 SVDEBUG << "using peaks cache" << endl;
Chris@474 1419 source = m_peaksCache;
Chris@474 1420 modelResolution *= m_peakResolution;
Chris@474 1421 } else {
Chris@679 1422 SVDEBUG << "not using peaks cache" << endl;
Chris@474 1423 }
Chris@469 1424 } else {
Chris@679 1425 SVDEBUG << "have no peaks cache" << endl;
Chris@469 1426 }
Chris@469 1427
Chris@466 1428 int psy1i = -1;
Chris@469 1429 int sw = source->width();
Chris@470 1430
Chris@470 1431 long xf = -1;
Chris@470 1432 long nxf = v->getFrameForX(x0);
Chris@470 1433
Chris@535 1434 float epsilon = 0.000001;
Chris@535 1435
Chris@545 1436 #ifdef __GNUC__
Chris@535 1437 float sxa[w * 2];
Chris@545 1438 #else
Chris@545 1439 float *sxa = (float *)alloca(w * 2 * sizeof(float));
Chris@545 1440 #endif
Chris@470 1441 for (int x = 0; x < w; ++x) {
Chris@470 1442
Chris@470 1443 xf = nxf;
Chris@470 1444 nxf = xf + zoomLevel;
Chris@470 1445
Chris@470 1446 float sx0 = (float(xf) / srRatio - modelStart) / modelResolution;
Chris@470 1447 float sx1 = (float(nxf) / srRatio - modelStart) / modelResolution;
Chris@470 1448
Chris@535 1449 sxa[x*2] = sx0;
Chris@535 1450 sxa[x*2 + 1] = sx1;
Chris@470 1451 }
Chris@466 1452
Chris@532 1453 float logmin = symin+1, logmax = symax+1;
Chris@532 1454 LogRange::mapRange(logmin, logmax);
Chris@532 1455
Chris@535 1456 if (m_smooth) {
Chris@535 1457
Chris@535 1458 for (int y = 0; y < h; ++y) {
Chris@466 1459
Chris@535 1460 float sy = getBinForY(v, y) - 0.5;
Chris@535 1461 int syi = int(sy + epsilon);
Chris@535 1462 if (syi < 0 || syi >= source->height()) continue;
Chris@531 1463
Chris@535 1464 uchar *targetLine = img.scanLine(y);
Chris@535 1465 uchar *sourceLine = source->scanLine(syi);
Chris@535 1466 uchar *nextSource;
Chris@535 1467 if (syi + 1 < source->height()) {
Chris@535 1468 nextSource = source->scanLine(syi + 1);
Chris@535 1469 } else {
Chris@535 1470 nextSource = sourceLine;
Chris@535 1471 }
Chris@466 1472
Chris@466 1473 for (int x = 0; x < w; ++x) {
Chris@98 1474
Chris@535 1475 targetLine[x] = 0;
Chris@474 1476
Chris@535 1477 float sx0 = sxa[x*2];
Chris@537 1478 if (sx0 < 0) continue;
Chris@535 1479 int sx0i = int(sx0 + epsilon);
Chris@474 1480 if (sx0i >= sw) break;
Chris@98 1481
Chris@535 1482 float a, b, value;
Chris@535 1483
Chris@535 1484 float sx1 = sxa[x*2+1];
Chris@535 1485 if (sx1 > sx0 + 1.f) {
Chris@535 1486 int sx1i = int(sx1);
Chris@535 1487 bool have = false;
Chris@535 1488 for (int sx = sx0i; sx <= sx1i; ++sx) {
Chris@535 1489 if (sx < 0 || sx >= sw) continue;
Chris@535 1490 if (!have) {
Chris@535 1491 a = float(sourceLine[sx]);
Chris@535 1492 b = float(nextSource[sx]);
Chris@535 1493 have = true;
Chris@535 1494 } else {
Chris@535 1495 a = std::max(a, float(sourceLine[sx]));
Chris@535 1496 b = std::max(b, float(nextSource[sx]));
Chris@535 1497 }
Chris@535 1498 }
Chris@535 1499 float yprop = sy - syi;
Chris@535 1500 value = (a * (1.f - yprop) + b * yprop);
Chris@535 1501 } else {
Chris@535 1502 a = float(sourceLine[sx0i]);
Chris@535 1503 b = float(nextSource[sx0i]);
Chris@535 1504 float yprop = sy - syi;
Chris@535 1505 value = (a * (1.f - yprop) + b * yprop);
Chris@535 1506 int oi = sx0i + 1;
Chris@535 1507 float xprop = sx0 - sx0i;
Chris@535 1508 xprop -= 0.5;
Chris@535 1509 if (xprop < 0) {
Chris@535 1510 oi = sx0i - 1;
Chris@535 1511 xprop = -xprop;
Chris@535 1512 }
Chris@535 1513 if (oi < 0 || oi >= sw) oi = sx0i;
Chris@535 1514 a = float(sourceLine[oi]);
Chris@535 1515 b = float(nextSource[oi]);
Chris@535 1516 value = (value * (1.f - xprop) +
Chris@535 1517 (a * (1.f - yprop) + b * yprop) * xprop);
Chris@98 1518 }
Chris@535 1519
Chris@535 1520 int vi = lrintf(value);
Chris@535 1521 if (vi > 255) vi = 255;
Chris@535 1522 if (vi < 0) vi = 0;
Chris@535 1523 targetLine[x] = uchar(vi);
Chris@98 1524 }
Chris@466 1525 }
Chris@535 1526 } else {
Chris@535 1527
Chris@535 1528 for (int y = 0; y < h; ++y) {
Chris@535 1529
Chris@535 1530 float sy0, sy1;
Chris@535 1531
Chris@535 1532 sy0 = getBinForY(v, y + 1);
Chris@535 1533 sy1 = getBinForY(v, y);
Chris@535 1534
Chris@535 1535 int sy0i = int(sy0 + epsilon);
Chris@535 1536 int sy1i = int(sy1);
Chris@535 1537
Chris@535 1538 uchar *targetLine = img.scanLine(y);
Chris@535 1539
Chris@535 1540 if (sy0i == sy1i && sy0i == psy1i) { // same source scan line as just computed
Chris@535 1541 goto copy;
Chris@535 1542 }
Chris@535 1543
Chris@535 1544 for (int x = 0; x < w; ++x) {
Chris@535 1545 peaks[x] = 0;
Chris@535 1546 }
Chris@466 1547
Chris@535 1548 for (int sy = sy0i; sy <= sy1i; ++sy) {
Chris@535 1549
Chris@535 1550 if (sy < 0 || sy >= source->height()) continue;
Chris@535 1551
Chris@535 1552 uchar *sourceLine = source->scanLine(sy);
Chris@535 1553
Chris@535 1554 for (int x = 0; x < w; ++x) {
Chris@535 1555
Chris@537 1556 float sx1 = sxa[x*2 + 1];
Chris@537 1557 if (sx1 < 0) continue;
Chris@537 1558 int sx1i = int(sx1);
Chris@535 1559
Chris@537 1560 float sx0 = sxa[x*2];
Chris@537 1561 if (sx0 < 0) continue;
Chris@537 1562 int sx0i = int(sx0 + epsilon);
Chris@535 1563 if (sx0i >= sw) break;
Chris@535 1564
Chris@535 1565 uchar peak = 0;
Chris@535 1566 for (int sx = sx0i; sx <= sx1i; ++sx) {
Chris@535 1567 if (sx < 0 || sx >= sw) continue;
Chris@535 1568 if (sourceLine[sx] > peak) peak = sourceLine[sx];
Chris@535 1569 }
Chris@535 1570 peaks[x] = peak;
Chris@535 1571 }
Chris@535 1572 }
Chris@535 1573
Chris@535 1574 copy:
Chris@535 1575 for (int x = 0; x < w; ++x) {
Chris@535 1576 targetLine[x] = peaks[x];
Chris@535 1577 }
Chris@98 1578 }
Chris@0 1579 }
Chris@0 1580
Chris@469 1581 delete[] peaks;
Chris@469 1582
Chris@98 1583 paint.drawImage(x0, 0, img);
Chris@0 1584 }
Chris@0 1585
Chris@28 1586 bool
Chris@44 1587 Colour3DPlotLayer::snapToFeatureFrame(View *v, int &frame,
Chris@28 1588 size_t &resolution,
Chris@28 1589 SnapType snap) const
Chris@24 1590 {
Chris@24 1591 if (!m_model) {
Chris@44 1592 return Layer::snapToFeatureFrame(v, frame, resolution, snap);
Chris@24 1593 }
Chris@24 1594
Chris@130 1595 resolution = m_model->getResolution();
Chris@28 1596 int left = (frame / resolution) * resolution;
Chris@28 1597 int right = left + resolution;
Chris@28 1598
Chris@28 1599 switch (snap) {
Chris@28 1600 case SnapLeft: frame = left; break;
Chris@28 1601 case SnapRight: frame = right; break;
Chris@28 1602 case SnapNearest:
Chris@28 1603 case SnapNeighbouring:
Chris@28 1604 if (frame - left > right - frame) frame = right;
Chris@28 1605 else frame = left;
Chris@28 1606 break;
Chris@28 1607 }
Chris@24 1608
Chris@28 1609 return true;
Chris@24 1610 }
Chris@24 1611
Chris@316 1612 void
Chris@316 1613 Colour3DPlotLayer::toXml(QTextStream &stream,
Chris@316 1614 QString indent, QString extraAttributes) const
Chris@197 1615 {
Chris@316 1616 QString s = QString("scale=\"%1\" "
Chris@316 1617 "colourScheme=\"%2\" "
Chris@316 1618 "normalizeColumns=\"%3\" "
Chris@445 1619 "normalizeVisibleArea=\"%4\" "
Chris@445 1620 "minY=\"%5\" "
Chris@465 1621 "maxY=\"%6\" "
Chris@465 1622 "invertVertical=\"%7\" "
Chris@535 1623 "opaque=\"%8\" %9")
Chris@197 1624 .arg((int)m_colourScale)
Chris@197 1625 .arg(m_colourMap)
Chris@197 1626 .arg(m_normalizeColumns ? "true" : "false")
Chris@445 1627 .arg(m_normalizeVisibleArea ? "true" : "false")
Chris@445 1628 .arg(m_miny)
Chris@465 1629 .arg(m_maxy)
Chris@465 1630 .arg(m_invertVertical ? "true" : "false")
Chris@534 1631 .arg(m_opaque ? "true" : "false")
Chris@536 1632 .arg(QString("binScale=\"%1\" smooth=\"%2\" gain=\"%3\" ")
Chris@535 1633 .arg((int)m_binScale)
Chris@536 1634 .arg(m_smooth ? "true" : "false")
Chris@536 1635 .arg(m_gain));
Chris@535 1636
Chris@316 1637 Layer::toXml(stream, indent, extraAttributes + " " + s);
Chris@197 1638 }
Chris@197 1639
Chris@197 1640 void
Chris@197 1641 Colour3DPlotLayer::setProperties(const QXmlAttributes &attributes)
Chris@197 1642 {
Chris@445 1643 bool ok = false, alsoOk = false;
Chris@197 1644
Chris@197 1645 ColourScale scale = (ColourScale)attributes.value("scale").toInt(&ok);
Chris@197 1646 if (ok) setColourScale(scale);
Chris@197 1647
Chris@197 1648 int colourMap = attributes.value("colourScheme").toInt(&ok);
Chris@197 1649 if (ok) setColourMap(colourMap);
Chris@197 1650
Chris@534 1651 BinScale binscale = (BinScale)attributes.value("binScale").toInt(&ok);
Chris@534 1652 if (ok) setBinScale(binscale);
Chris@534 1653
Chris@197 1654 bool normalizeColumns =
Chris@197 1655 (attributes.value("normalizeColumns").trimmed() == "true");
Chris@197 1656 setNormalizeColumns(normalizeColumns);
Chris@197 1657
Chris@197 1658 bool normalizeVisibleArea =
Chris@197 1659 (attributes.value("normalizeVisibleArea").trimmed() == "true");
Chris@197 1660 setNormalizeVisibleArea(normalizeVisibleArea);
Chris@445 1661
Chris@465 1662 bool invertVertical =
Chris@465 1663 (attributes.value("invertVertical").trimmed() == "true");
Chris@465 1664 setInvertVertical(invertVertical);
Chris@465 1665
Chris@465 1666 bool opaque =
Chris@465 1667 (attributes.value("opaque").trimmed() == "true");
Chris@535 1668 setOpaque(opaque);
Chris@535 1669
Chris@535 1670 bool smooth =
Chris@535 1671 (attributes.value("smooth").trimmed() == "true");
Chris@535 1672 setSmooth(smooth);
Chris@465 1673
Chris@536 1674 float gain = attributes.value("gain").toFloat(&ok);
Chris@536 1675 if (ok) setGain(gain);
Chris@536 1676
Chris@445 1677 float min = attributes.value("minY").toFloat(&ok);
Chris@445 1678 float max = attributes.value("maxY").toFloat(&alsoOk);
Chris@445 1679 if (ok && alsoOk) setDisplayExtents(min, max);
Chris@197 1680 }
Chris@197 1681