annotate layer/Colour3DPlotLayer.cpp @ 561:aced8ec09bc8

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