Mercurial > hg > svgui
comparison layer/Colour3DPlotLayer.cpp @ 1324:13d9b422f7fe zoom
Merge from default branch
| author | Chris Cannam |
|---|---|
| date | Mon, 17 Sep 2018 13:51:31 +0100 |
| parents | a34a2a25907c |
| children | d79e21855aef |
comparison
equal
deleted
inserted
replaced
| 1183:57d192e26331 | 1324:13d9b422f7fe |
|---|---|
| 68 } | 68 } |
| 69 | 69 |
| 70 Colour3DPlotLayer::~Colour3DPlotLayer() | 70 Colour3DPlotLayer::~Colour3DPlotLayer() |
| 71 { | 71 { |
| 72 invalidateRenderers(); | 72 invalidateRenderers(); |
| 73 if (m_peakCache) m_peakCache->aboutToDelete(); | |
| 73 delete m_peakCache; | 74 delete m_peakCache; |
| 74 } | 75 } |
| 75 | 76 |
| 76 ColourScaleType | 77 ColourScaleType |
| 77 Colour3DPlotLayer::convertToColourScale(int value) | 78 Colour3DPlotLayer::convertToColourScale(int value) |
| 104 Colour3DPlotLayer::convertToColumnNorm(int value) | 105 Colour3DPlotLayer::convertToColumnNorm(int value) |
| 105 { | 106 { |
| 106 switch (value) { | 107 switch (value) { |
| 107 default: | 108 default: |
| 108 case 0: return { ColumnNormalization::None, false }; | 109 case 0: return { ColumnNormalization::None, false }; |
| 109 case 1: return { ColumnNormalization::Max1, false }; | 110 case 1: return { ColumnNormalization::Range01, false }; |
| 110 case 2: return { ColumnNormalization::None, true }; // visible area | 111 case 2: return { ColumnNormalization::None, true }; // visible area |
| 111 case 3: return { ColumnNormalization::Hybrid, false }; | 112 case 3: return { ColumnNormalization::Hybrid, false }; |
| 112 } | 113 } |
| 113 } | 114 } |
| 114 | 115 |
| 116 Colour3DPlotLayer::convertFromColumnNorm(ColumnNormalization norm, bool visible) | 117 Colour3DPlotLayer::convertFromColumnNorm(ColumnNormalization norm, bool visible) |
| 117 { | 118 { |
| 118 if (visible) return 2; | 119 if (visible) return 2; |
| 119 switch (norm) { | 120 switch (norm) { |
| 120 case ColumnNormalization::None: return 0; | 121 case ColumnNormalization::None: return 0; |
| 121 case ColumnNormalization::Max1: return 1; | 122 case ColumnNormalization::Range01: return 1; |
| 122 case ColumnNormalization::Hybrid: return 3; | 123 case ColumnNormalization::Hybrid: return 3; |
| 123 | 124 |
| 124 case ColumnNormalization::Sum1: | 125 case ColumnNormalization::Sum1: |
| 126 case ColumnNormalization::Max1: | |
| 125 default: return 0; | 127 default: return 0; |
| 126 } | 128 } |
| 127 } | 129 } |
| 128 | 130 |
| 129 void | 131 void |
| 133 } | 135 } |
| 134 | 136 |
| 135 void | 137 void |
| 136 Colour3DPlotLayer::setModel(const DenseThreeDimensionalModel *model) | 138 Colour3DPlotLayer::setModel(const DenseThreeDimensionalModel *model) |
| 137 { | 139 { |
| 140 SVDEBUG << "Colour3DPlotLayer::setModel(" << model << ")" << endl; | |
| 141 | |
| 138 if (m_model == model) return; | 142 if (m_model == model) return; |
| 139 const DenseThreeDimensionalModel *oldModel = m_model; | 143 const DenseThreeDimensionalModel *oldModel = m_model; |
| 140 m_model = model; | 144 m_model = model; |
| 141 if (!m_model || !m_model->isOK()) return; | 145 if (!m_model || !m_model->isOK()) return; |
| 142 | 146 |
| 143 connectSignals(m_model); | 147 connectSignals(m_model); |
| 144 | 148 |
| 145 connect(m_model, SIGNAL(modelChanged()), this, SLOT(modelChanged())); | 149 connect(m_model, SIGNAL(modelChanged()), this, SLOT(modelChanged())); |
| 146 connect(m_model, SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)), | 150 connect(m_model, SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)), |
| 147 this, SLOT(modelChangedWithin(sv_frame_t, sv_frame_t))); | 151 this, SLOT(modelChangedWithin(sv_frame_t, sv_frame_t))); |
| 148 | 152 |
| 149 m_peakResolution = 256; | 153 m_peakResolution = 256; |
| 150 if (model->getResolution() > 512) { | 154 if (model->getResolution() > 512) { |
| 151 m_peakResolution = 16; | 155 m_peakResolution = 16; |
| 152 } else if (model->getResolution() > 128) { | 156 } else if (model->getResolution() > 128) { |
| 153 m_peakResolution = 64; | 157 m_peakResolution = 64; |
| 154 } else if (model->getResolution() > 2) { | 158 } else if (model->getResolution() > 2) { |
| 155 m_peakResolution = 128; | 159 m_peakResolution = 128; |
| 156 } | 160 } |
| 157 | 161 |
| 162 if (m_peakCache) m_peakCache->aboutToDelete(); | |
| 158 delete m_peakCache; | 163 delete m_peakCache; |
| 159 m_peakCache = 0; | 164 m_peakCache = 0; |
| 160 | 165 |
| 161 invalidateRenderers(); | 166 invalidateRenderers(); |
| 167 invalidateMagnitudes(); | |
| 162 | 168 |
| 163 emit modelReplaced(); | 169 emit modelReplaced(); |
| 164 emit sliceableModelReplaced(oldModel, model); | 170 emit sliceableModelReplaced(oldModel, model); |
| 165 } | 171 } |
| 166 | 172 |
| 167 void | 173 void |
| 168 Colour3DPlotLayer::cacheInvalid() | 174 Colour3DPlotLayer::cacheInvalid() |
| 169 { | 175 { |
| 170 invalidateRenderers(); | 176 invalidateRenderers(); |
| 177 invalidateMagnitudes(); | |
| 171 } | 178 } |
| 172 | 179 |
| 173 void | 180 void |
| 174 Colour3DPlotLayer::cacheInvalid(sv_frame_t /* startFrame */, | 181 Colour3DPlotLayer::cacheInvalid(sv_frame_t /* startFrame */, |
| 175 sv_frame_t /* endFrame */) | 182 sv_frame_t /* endFrame */) |
| 176 { | 183 { |
| 177 //!!! should do this only if the range is visible | 184 //!!! should do this only if the range is visible |
| 185 if (m_peakCache) m_peakCache->aboutToDelete(); | |
| 178 delete m_peakCache; | 186 delete m_peakCache; |
| 179 m_peakCache = 0; | 187 m_peakCache = 0; |
| 180 | 188 |
| 181 invalidateRenderers(); | 189 invalidateRenderers(); |
| 190 invalidateMagnitudes(); | |
| 182 } | 191 } |
| 183 | 192 |
| 184 void | 193 void |
| 185 Colour3DPlotLayer::invalidateRenderers() | 194 Colour3DPlotLayer::invalidateRenderers() |
| 186 { | 195 { |
| 187 for (ViewRendererMap::iterator i = m_renderers.begin(); | 196 for (ViewRendererMap::iterator i = m_renderers.begin(); |
| 188 i != m_renderers.end(); ++i) { | 197 i != m_renderers.end(); ++i) { |
| 189 delete i->second; | 198 delete i->second; |
| 190 } | 199 } |
| 191 m_renderers.clear(); | 200 m_renderers.clear(); |
| 201 } | |
| 202 | |
| 203 void | |
| 204 Colour3DPlotLayer::invalidateMagnitudes() | |
| 205 { | |
| 206 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT | |
| 207 cerr << "Colour3DPlotLayer::invalidateMagnitudes called" << endl; | |
| 208 #endif | |
| 209 m_viewMags.clear(); | |
| 192 } | 210 } |
| 193 | 211 |
| 194 Dense3DModelPeakCache * | 212 Dense3DModelPeakCache * |
| 195 Colour3DPlotLayer::getPeakCache() const | 213 Colour3DPlotLayer::getPeakCache() const |
| 196 { | 214 { |
| 273 { | 291 { |
| 274 if (name == "Gain") return RangeProperty; | 292 if (name == "Gain") return RangeProperty; |
| 275 if (name == "Invert Vertical Scale") return ToggleProperty; | 293 if (name == "Invert Vertical Scale") return ToggleProperty; |
| 276 if (name == "Opaque") return ToggleProperty; | 294 if (name == "Opaque") return ToggleProperty; |
| 277 if (name == "Smooth") return ToggleProperty; | 295 if (name == "Smooth") return ToggleProperty; |
| 296 if (name == "Colour") return ColourMapProperty; | |
| 278 return ValueProperty; | 297 return ValueProperty; |
| 279 } | 298 } |
| 280 | 299 |
| 281 QString | 300 QString |
| 282 Colour3DPlotLayer::getPropertyGroupName(const PropertyName &name) const | 301 Colour3DPlotLayer::getPropertyGroupName(const PropertyName &name) const |
| 303 if (!max) max = &garbage1; | 322 if (!max) max = &garbage1; |
| 304 if (!deflt) deflt = &garbage2; | 323 if (!deflt) deflt = &garbage2; |
| 305 | 324 |
| 306 if (name == "Gain") { | 325 if (name == "Gain") { |
| 307 | 326 |
| 308 *min = -50; | 327 *min = -50; |
| 309 *max = 50; | 328 *max = 50; |
| 310 | 329 |
| 311 *deflt = int(lrint(log10(1.0) * 20.0)); | 330 *deflt = int(lrint(log10(1.0) * 20.0)); |
| 312 if (*deflt < *min) *deflt = *min; | 331 if (*deflt < *min) *deflt = *min; |
| 313 if (*deflt > *max) *deflt = *max; | 332 if (*deflt > *max) *deflt = *max; |
| 314 | 333 |
| 315 val = int(lrint(log10(m_gain) * 20.0)); | 334 val = int(lrint(log10(m_gain) * 20.0)); |
| 316 if (val < *min) val = *min; | 335 if (val < *min) val = *min; |
| 317 if (val > *max) val = *max; | 336 if (val > *max) val = *max; |
| 318 | 337 |
| 319 } else if (name == "Colour Scale") { | 338 } else if (name == "Colour Scale") { |
| 320 | 339 |
| 321 // linear, log, +/-1, abs | 340 // linear, log, +/-1, abs |
| 322 *min = 0; | |
| 323 *max = 3; | |
| 324 *deflt = 0; | |
| 325 | |
| 326 val = convertFromColourScale(m_colourScale); | |
| 327 | |
| 328 } else if (name == "Colour") { | |
| 329 | |
| 330 *min = 0; | |
| 331 *max = ColourMapper::getColourMapCount() - 1; | |
| 332 *deflt = 0; | |
| 333 | |
| 334 val = m_colourMap; | |
| 335 | |
| 336 } else if (name == "Normalization") { | |
| 337 | |
| 338 *min = 0; | 341 *min = 0; |
| 339 *max = 3; | 342 *max = 3; |
| 340 *deflt = 0; | 343 *deflt = 0; |
| 341 | 344 |
| 345 val = convertFromColourScale(m_colourScale); | |
| 346 | |
| 347 } else if (name == "Colour") { | |
| 348 | |
| 349 *min = 0; | |
| 350 *max = ColourMapper::getColourMapCount() - 1; | |
| 351 *deflt = 0; | |
| 352 | |
| 353 val = m_colourMap; | |
| 354 | |
| 355 } else if (name == "Normalization") { | |
| 356 | |
| 357 *min = 0; | |
| 358 *max = 3; | |
| 359 *deflt = 0; | |
| 360 | |
| 342 val = convertFromColumnNorm(m_normalization, m_normalizeVisibleArea); | 361 val = convertFromColumnNorm(m_normalization, m_normalizeVisibleArea); |
| 343 | 362 |
| 344 } else if (name == "Invert Vertical Scale") { | 363 } else if (name == "Invert Vertical Scale") { |
| 345 | 364 |
| 346 *deflt = 0; | 365 *deflt = 0; |
| 347 val = (m_invertVertical ? 1 : 0); | 366 val = (m_invertVertical ? 1 : 0); |
| 348 | 367 |
| 349 } else if (name == "Bin Scale") { | 368 } else if (name == "Bin Scale") { |
| 350 | 369 |
| 351 *min = 0; | 370 *min = 0; |
| 352 *max = 1; | 371 *max = 1; |
| 353 *deflt = int(BinScale::Linear); | 372 *deflt = int(BinScale::Linear); |
| 354 val = (int)m_binScale; | 373 val = (int)m_binScale; |
| 355 | 374 |
| 356 } else if (name == "Opaque") { | 375 } else if (name == "Opaque") { |
| 357 | 376 |
| 358 *deflt = 0; | 377 *deflt = 0; |
| 359 val = (m_opaque ? 1 : 0); | 378 val = (m_opaque ? 1 : 0); |
| 360 | 379 |
| 361 } else if (name == "Smooth") { | 380 } else if (name == "Smooth") { |
| 362 | 381 |
| 363 *deflt = 0; | 382 *deflt = 0; |
| 364 val = (m_smooth ? 1 : 0); | 383 val = (m_smooth ? 1 : 0); |
| 365 | 384 |
| 366 } else { | 385 } else { |
| 367 val = Layer::getPropertyRangeAndValue(name, min, max, deflt); | 386 val = Layer::getPropertyRangeAndValue(name, min, max, deflt); |
| 368 } | 387 } |
| 369 | 388 |
| 370 return val; | 389 return val; |
| 371 } | 390 } |
| 372 | 391 |
| 373 QString | 392 QString |
| 374 Colour3DPlotLayer::getPropertyValueLabel(const PropertyName &name, | 393 Colour3DPlotLayer::getPropertyValueLabel(const PropertyName &name, |
| 375 int value) const | 394 int value) const |
| 376 { | 395 { |
| 377 if (name == "Colour") { | 396 if (name == "Colour") { |
| 378 return ColourMapper::getColourMapName(value); | 397 return ColourMapper::getColourMapName(value); |
| 379 } | 398 } |
| 380 if (name == "Colour Scale") { | 399 if (name == "Colour Scale") { |
| 381 switch (value) { | 400 switch (value) { |
| 382 default: | 401 default: |
| 383 case 0: return tr("Linear"); | 402 case 0: return tr("Linear"); |
| 384 case 1: return tr("Log"); | 403 case 1: return tr("Log"); |
| 385 case 2: return tr("+/-1"); | 404 case 2: return tr("+/-1"); |
| 386 case 3: return tr("Absolute"); | 405 case 3: return tr("Absolute"); |
| 387 } | 406 } |
| 388 } | 407 } |
| 389 if (name == "Normalization") { | 408 if (name == "Normalization") { |
| 390 return ""; // icon only | 409 switch(value) { |
| 410 default: | |
| 411 case 0: return tr("None"); | |
| 412 case 1: return tr("Col"); | |
| 413 case 2: return tr("View"); | |
| 414 case 3: return tr("Hybrid"); | |
| 415 } | |
| 416 // return ""; // icon only | |
| 391 } | 417 } |
| 392 if (name == "Bin Scale") { | 418 if (name == "Bin Scale") { |
| 393 switch (value) { | 419 switch (value) { |
| 394 default: | 420 default: |
| 395 case 0: return tr("Linear"); | 421 case 0: return tr("Linear"); |
| 396 case 1: return tr("Log"); | 422 case 1: return tr("Log"); |
| 397 } | 423 } |
| 398 } | 424 } |
| 399 return tr("<unknown>"); | 425 return tr("<unknown>"); |
| 400 } | 426 } |
| 401 | 427 |
| 402 QString | 428 QString |
| 426 | 452 |
| 427 void | 453 void |
| 428 Colour3DPlotLayer::setProperty(const PropertyName &name, int value) | 454 Colour3DPlotLayer::setProperty(const PropertyName &name, int value) |
| 429 { | 455 { |
| 430 if (name == "Gain") { | 456 if (name == "Gain") { |
| 431 setGain(float(pow(10, value/20.0))); | 457 setGain(float(pow(10, value/20.0))); |
| 432 } else if (name == "Colour Scale") { | 458 } else if (name == "Colour Scale") { |
| 433 setColourScale(convertToColourScale(value)); | 459 setColourScale(convertToColourScale(value)); |
| 434 } else if (name == "Colour") { | 460 } else if (name == "Colour") { |
| 435 setColourMap(value); | 461 setColourMap(value); |
| 436 } else if (name == "Invert Vertical Scale") { | 462 } else if (name == "Invert Vertical Scale") { |
| 437 setInvertVertical(value ? true : false); | 463 setInvertVertical(value ? true : false); |
| 438 } else if (name == "Opaque") { | 464 } else if (name == "Opaque") { |
| 439 setOpaque(value ? true : false); | 465 setOpaque(value ? true : false); |
| 440 } else if (name == "Smooth") { | 466 } else if (name == "Smooth") { |
| 441 setSmooth(value ? true : false); | 467 setSmooth(value ? true : false); |
| 442 } else if (name == "Bin Scale") { | 468 } else if (name == "Bin Scale") { |
| 443 switch (value) { | 469 switch (value) { |
| 444 default: | 470 default: |
| 445 case 0: setBinScale(BinScale::Linear); break; | 471 case 0: setBinScale(BinScale::Linear); break; |
| 446 case 1: setBinScale(BinScale::Log); break; | 472 case 1: setBinScale(BinScale::Log); break; |
| 447 } | 473 } |
| 448 } else if (name == "Normalization") { | 474 } else if (name == "Normalization") { |
| 449 auto n = convertToColumnNorm(value); | 475 auto n = convertToColumnNorm(value); |
| 450 setNormalization(n.first); | 476 setNormalization(n.first); |
| 451 setNormalizeVisibleArea(n.second); | 477 setNormalizeVisibleArea(n.second); |
| 452 } | 478 } |
| 453 } | 479 } |
| 454 | 480 |
| 455 void | 481 void |
| 456 Colour3DPlotLayer::setColourScale(ColourScaleType scale) | 482 Colour3DPlotLayer::setColourScale(ColourScaleType scale) |
| 457 { | 483 { |
| 484 m_colourScaleSet = true; // even if setting to the same thing | |
| 458 if (m_colourScale == scale) return; | 485 if (m_colourScale == scale) return; |
| 459 m_colourScale = scale; | 486 m_colourScale = scale; |
| 460 m_colourScaleSet = true; | |
| 461 invalidateRenderers(); | 487 invalidateRenderers(); |
| 462 emit layerParametersChanged(); | 488 emit layerParametersChanged(); |
| 463 } | 489 } |
| 464 | 490 |
| 465 void | 491 void |
| 521 void | 547 void |
| 522 Colour3DPlotLayer::setNormalizeVisibleArea(bool n) | 548 Colour3DPlotLayer::setNormalizeVisibleArea(bool n) |
| 523 { | 549 { |
| 524 if (m_normalizeVisibleArea == n) return; | 550 if (m_normalizeVisibleArea == n) return; |
| 525 | 551 |
| 552 invalidateRenderers(); | |
| 553 invalidateMagnitudes(); | |
| 526 m_normalizeVisibleArea = n; | 554 m_normalizeVisibleArea = n; |
| 527 invalidateRenderers(); | |
| 528 | 555 |
| 529 emit layerParametersChanged(); | 556 emit layerParametersChanged(); |
| 530 } | 557 } |
| 531 | 558 |
| 532 bool | 559 bool |
| 595 } | 622 } |
| 596 | 623 |
| 597 Layer::setLayerDormant(v, true); | 624 Layer::setLayerDormant(v, true); |
| 598 | 625 |
| 599 cacheInvalid(); | 626 cacheInvalid(); |
| 600 | 627 |
| 601 } else { | 628 } else { |
| 602 | 629 |
| 603 Layer::setLayerDormant(v, false); | 630 Layer::setLayerDormant(v, false); |
| 604 } | 631 } |
| 605 } | 632 } |
| 606 | 633 |
| 607 bool | 634 bool |
| 608 Colour3DPlotLayer::isLayerScrollable(const LayerGeometryProvider * /* v */) const | 635 Colour3DPlotLayer::isLayerScrollable(const LayerGeometryProvider * /* v */) const |
| 609 { | 636 { |
| 610 if (m_normalizeVisibleArea) { | |
| 611 return false; | |
| 612 } | |
| 613 //!!! ah hang on, if we're potentially rendering incrementally | |
| 614 //!!! they we can't be scrollable | |
| 615 return false; | 637 return false; |
| 616 // if (getRenderer(v)->willRenderOpaque(v)) { | |
| 617 // return true; | |
| 618 // } | |
| 619 // QPoint discard; | |
| 620 // return !v->shouldIlluminateLocalFeatures(this, discard); | |
| 621 } | 638 } |
| 622 | 639 |
| 623 bool | 640 bool |
| 624 Colour3DPlotLayer::getValueExtents(double &min, double &max, | 641 Colour3DPlotLayer::getValueExtents(double &min, double &max, |
| 625 bool &logarithmic, QString &unit) const | 642 bool &logarithmic, QString &unit) const |
| 627 if (!m_model) return false; | 644 if (!m_model) return false; |
| 628 | 645 |
| 629 min = 0; | 646 min = 0; |
| 630 max = double(m_model->getHeight()); | 647 max = double(m_model->getHeight()); |
| 631 | 648 |
| 632 logarithmic = false; | 649 logarithmic = (m_binScale == BinScale::Log); |
| 633 unit = ""; | 650 unit = ""; |
| 634 | 651 |
| 635 return true; | 652 return true; |
| 636 } | 653 } |
| 637 | 654 |
| 751 if (!m_model) return bin; | 768 if (!m_model) return bin; |
| 752 double mn = 0, mx = m_model->getHeight(); | 769 double mn = 0, mx = m_model->getHeight(); |
| 753 getDisplayExtents(mn, mx); | 770 getDisplayExtents(mn, mx); |
| 754 double h = v->getPaintHeight(); | 771 double h = v->getPaintHeight(); |
| 755 if (m_binScale == BinScale::Linear) { | 772 if (m_binScale == BinScale::Linear) { |
| 756 bin = mn + ((h - y) * (mx - mn)) / h; | 773 // Arrange that the first bin (mn) appears as the exact result |
| 774 // for the first pixel (which is pixel h-1) and the first | |
| 775 // out-of-range bin (mx) would appear as the exact result for | |
| 776 // the first out-of-range pixel (which would be pixel -1) | |
| 777 bin = mn + ((h - y - 1) * (mx - mn)) / h; | |
| 757 } else { | 778 } else { |
| 758 double logmin = mn + 1, logmax = mx + 1; | 779 double logmin = mn + 1, logmax = mx + 1; |
| 759 LogRange::mapRange(logmin, logmax); | 780 LogRange::mapRange(logmin, logmax); |
| 760 bin = LogRange::unmap(logmin + ((h - y) * (logmax - logmin)) / h) - 1; | 781 bin = LogRange::unmap(logmin + ((h - y - 1) * (logmax - logmin)) / h) - 1; |
| 761 } | 782 } |
| 762 return bin; | 783 return bin; |
| 763 } | 784 } |
| 764 | 785 |
| 765 QString | 786 QString |
| 812 QString binName = m_model->getBinName(sy); | 833 QString binName = m_model->getBinName(sy); |
| 813 if (binName == "") binName = QString("[%1]").arg(sy + 1); | 834 if (binName == "") binName = QString("[%1]").arg(sy + 1); |
| 814 else binName = QString("%1 [%2]").arg(binName).arg(sy + 1); | 835 else binName = QString("%1 [%2]").arg(binName).arg(sy + 1); |
| 815 | 836 |
| 816 QString text = tr("Time:\t%1 - %2\nBin:\t%3\nValue:\t%4") | 837 QString text = tr("Time:\t%1 - %2\nBin:\t%3\nValue:\t%4") |
| 817 .arg(RealTime::frame2RealTime(f0, m_model->getSampleRate()) | 838 .arg(RealTime::frame2RealTime(f0, m_model->getSampleRate()) |
| 818 .toText(true).c_str()) | 839 .toText(true).c_str()) |
| 819 .arg(RealTime::frame2RealTime(f1, m_model->getSampleRate()) | 840 .arg(RealTime::frame2RealTime(f1, m_model->getSampleRate()) |
| 820 .toText(true).c_str()) | 841 .toText(true).c_str()) |
| 821 .arg(binName) | 842 .arg(binName) |
| 822 .arg(value); | 843 .arg(value); |
| 823 | 844 |
| 824 return text; | 845 return text; |
| 825 } | 846 } |
| 826 | 847 |
| 827 int | 848 int |
| 840 QString sampleText = QString("[%1]").arg(m_model->getHeight()); | 861 QString sampleText = QString("[%1]").arg(m_model->getHeight()); |
| 841 int tw = paint.fontMetrics().width(sampleText); | 862 int tw = paint.fontMetrics().width(sampleText); |
| 842 bool another = false; | 863 bool another = false; |
| 843 | 864 |
| 844 for (int i = 0; i < m_model->getHeight(); ++i) { | 865 for (int i = 0; i < m_model->getHeight(); ++i) { |
| 845 if (m_model->getBinName(i).length() > sampleText.length()) { | 866 if (m_model->getBinName(i).length() > sampleText.length()) { |
| 846 sampleText = m_model->getBinName(i); | 867 sampleText = m_model->getBinName(i); |
| 847 another = true; | 868 another = true; |
| 848 } | 869 } |
| 849 } | 870 } |
| 850 if (another) { | 871 if (another) { |
| 851 tw = std::max(tw, paint.fontMetrics().width(sampleText)); | 872 tw = std::max(tw, paint.fontMetrics().width(sampleText)); |
| 852 } | 873 } |
| 853 | 874 |
| 854 return tw + 13 + getColourScaleWidth(paint); | 875 return tw + 13 + getColourScaleWidth(paint); |
| 855 } | 876 } |
| 856 | 877 |
| 946 } else { | 967 } else { |
| 947 continue; | 968 continue; |
| 948 } | 969 } |
| 949 } | 970 } |
| 950 } | 971 } |
| 951 | 972 |
| 952 py = y0; | 973 py = y0; |
| 953 | 974 |
| 954 if (i < symax) { | 975 if (i < symax) { |
| 955 paint.drawLine(cw, y0, w, y0); | 976 paint.drawLine(cw, y0, w, y0); |
| 956 } | 977 } |
| 971 } | 992 } |
| 972 | 993 |
| 973 paint.restore(); | 994 paint.restore(); |
| 974 } | 995 } |
| 975 | 996 |
| 976 DenseThreeDimensionalModel::Column | |
| 977 Colour3DPlotLayer::getColumn(int col) const | |
| 978 { | |
| 979 Profiler profiler("Colour3DPlotLayer::getColumn"); | |
| 980 | |
| 981 DenseThreeDimensionalModel::Column values = m_model->getColumn(col); | |
| 982 values.resize(m_model->getHeight(), 0.f); | |
| 983 if (m_normalization != ColumnNormalization::Max1 && | |
| 984 m_normalization != ColumnNormalization::Hybrid) { | |
| 985 return values; | |
| 986 } | |
| 987 | |
| 988 double colMax = 0.f, colMin = 0.f; | |
| 989 double min = 0.f, max = 0.f; | |
| 990 | |
| 991 int nv = int(values.size()); | |
| 992 | |
| 993 min = m_model->getMinimumLevel(); | |
| 994 max = m_model->getMaximumLevel(); | |
| 995 | |
| 996 for (int y = 0; y < nv; ++y) { | |
| 997 if (y == 0 || values.at(y) > colMax) colMax = values.at(y); | |
| 998 if (y == 0 || values.at(y) < colMin) colMin = values.at(y); | |
| 999 } | |
| 1000 if (colMin == colMax) colMax = colMin + 1; | |
| 1001 | |
| 1002 for (int y = 0; y < nv; ++y) { | |
| 1003 | |
| 1004 double value = values.at(y); | |
| 1005 double norm = (value - colMin) / (colMax - colMin); | |
| 1006 double newvalue = min + (max - min) * norm; | |
| 1007 | |
| 1008 if (value != newvalue) values[y] = float(newvalue); | |
| 1009 } | |
| 1010 | |
| 1011 if (m_normalization == ColumnNormalization::Hybrid | |
| 1012 && (colMax > 0.0)) { | |
| 1013 double logmax = log10(colMax); | |
| 1014 for (int y = 0; y < nv; ++y) { | |
| 1015 values[y] = float(values[y] * logmax); | |
| 1016 } | |
| 1017 } | |
| 1018 | |
| 1019 return values; | |
| 1020 } | |
| 1021 | |
| 1022 Colour3DPlotRenderer * | 997 Colour3DPlotRenderer * |
| 1023 Colour3DPlotLayer::getRenderer(const LayerGeometryProvider *v) const | 998 Colour3DPlotLayer::getRenderer(const LayerGeometryProvider *v) const |
| 1024 { | 999 { |
| 1025 if (m_renderers.find(v->getId()) == m_renderers.end()) { | 1000 int viewId = v->getId(); |
| 1001 | |
| 1002 if (m_renderers.find(viewId) == m_renderers.end()) { | |
| 1026 | 1003 |
| 1027 Colour3DPlotRenderer::Sources sources; | 1004 Colour3DPlotRenderer::Sources sources; |
| 1028 sources.verticalBinLayer = this; | 1005 sources.verticalBinLayer = this; |
| 1029 sources.fft = 0; | 1006 sources.fft = 0; |
| 1030 sources.source = m_model; | 1007 sources.source = m_model; |
| 1031 sources.peakCache = getPeakCache(); | 1008 sources.peakCaches.push_back(getPeakCache()); |
| 1032 | 1009 |
| 1033 ColourScale::Parameters cparams; | 1010 ColourScale::Parameters cparams; |
| 1034 cparams.colourMap = m_colourMap; | 1011 cparams.colourMap = m_colourMap; |
| 1035 cparams.scaleType = m_colourScale; | 1012 cparams.scaleType = m_colourScale; |
| 1036 cparams.gain = m_gain; | 1013 cparams.gain = m_gain; |
| 1037 | 1014 |
| 1038 if (m_normalization == ColumnNormalization::None) { | 1015 double minValue = 0.0; |
| 1039 cparams.minValue = m_model->getMinimumLevel(); | 1016 double maxValue = 1.0; |
| 1040 cparams.maxValue = m_model->getMaximumLevel(); | 1017 |
| 1018 if (m_normalizeVisibleArea && m_viewMags[viewId].isSet()) { | |
| 1019 minValue = m_viewMags[viewId].getMin(); | |
| 1020 maxValue = m_viewMags[viewId].getMax(); | |
| 1041 } else if (m_normalization == ColumnNormalization::Hybrid) { | 1021 } else if (m_normalization == ColumnNormalization::Hybrid) { |
| 1042 cparams.minValue = 0; | 1022 minValue = 0; |
| 1043 cparams.maxValue = log10(m_model->getMaximumLevel() + 1.0); | 1023 maxValue = log10(m_model->getMaximumLevel() + 1.0); |
| 1044 } | 1024 } else if (m_normalization == ColumnNormalization::None) { |
| 1045 | 1025 minValue = m_model->getMinimumLevel(); |
| 1046 if (cparams.maxValue <= cparams.minValue) { | 1026 maxValue = m_model->getMaximumLevel(); |
| 1047 cparams.maxValue = cparams.minValue + 0.1; | 1027 } |
| 1048 } | 1028 |
| 1029 SVDEBUG << "Colour3DPlotLayer: rebuilding renderer, value range is " | |
| 1030 << minValue << " -> " << maxValue << endl; | |
| 1049 | 1031 |
| 1032 if (maxValue <= minValue) { | |
| 1033 maxValue = minValue + 0.1f; | |
| 1034 } | |
| 1035 | |
| 1036 cparams.threshold = minValue; | |
| 1037 cparams.minValue = minValue; | |
| 1038 cparams.maxValue = maxValue; | |
| 1039 | |
| 1040 m_lastRenderedMags[viewId] = MagnitudeRange(float(minValue), | |
| 1041 float(maxValue)); | |
| 1042 | |
| 1050 Colour3DPlotRenderer::Parameters params; | 1043 Colour3DPlotRenderer::Parameters params; |
| 1051 params.colourScale = ColourScale(cparams); | 1044 params.colourScale = ColourScale(cparams); |
| 1052 params.normalization = m_normalization; | 1045 params.normalization = m_normalization; |
| 1053 params.binScale = m_binScale; | 1046 params.binScale = m_binScale; |
| 1054 params.alwaysOpaque = m_opaque; | 1047 params.alwaysOpaque = m_opaque; |
| 1055 params.invertVertical = m_invertVertical; | 1048 params.invertVertical = m_invertVertical; |
| 1056 params.interpolate = m_smooth; | 1049 params.interpolate = m_smooth; |
| 1057 | 1050 |
| 1058 m_renderers[v->getId()] = new Colour3DPlotRenderer(sources, params); | 1051 m_renderers[viewId] = new Colour3DPlotRenderer(sources, params); |
| 1059 } | 1052 } |
| 1060 | 1053 |
| 1061 return m_renderers[v->getId()]; | 1054 return m_renderers[viewId]; |
| 1062 } | 1055 } |
| 1063 | 1056 |
| 1064 void | 1057 void |
| 1065 Colour3DPlotLayer::paintWithRenderer(LayerGeometryProvider *v, | 1058 Colour3DPlotLayer::paintWithRenderer(LayerGeometryProvider *v, |
| 1066 QPainter &paint, QRect rect) const | 1059 QPainter &paint, QRect rect) const |
| 1069 | 1062 |
| 1070 Colour3DPlotRenderer::RenderResult result; | 1063 Colour3DPlotRenderer::RenderResult result; |
| 1071 MagnitudeRange magRange; | 1064 MagnitudeRange magRange; |
| 1072 int viewId = v->getId(); | 1065 int viewId = v->getId(); |
| 1073 | 1066 |
| 1074 if (!renderer->geometryChanged(v)) { | 1067 bool continuingPaint = !renderer->geometryChanged(v); |
| 1068 | |
| 1069 if (continuingPaint) { | |
| 1075 magRange = m_viewMags[viewId]; | 1070 magRange = m_viewMags[viewId]; |
| 1076 } | 1071 } |
| 1077 | 1072 |
| 1078 if (m_synchronous) { | 1073 if (m_synchronous) { |
| 1079 | 1074 |
| 1090 } | 1085 } |
| 1091 | 1086 |
| 1092 magRange.sample(result.range); | 1087 magRange.sample(result.range); |
| 1093 | 1088 |
| 1094 if (magRange.isSet()) { | 1089 if (magRange.isSet()) { |
| 1095 if (!(m_viewMags[viewId] == magRange)) { | 1090 if (m_viewMags[viewId] != magRange) { |
| 1096 m_viewMags[viewId] = magRange; | 1091 m_viewMags[viewId] = magRange; |
| 1097 //!!! now need to do the normalise-visible thing | 1092 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT |
| 1098 } | 1093 cerr << "mag range in this view has changed: " |
| 1099 } | 1094 << magRange.getMin() << " -> " << magRange.getMax() << endl; |
| 1100 | 1095 #endif |
| 1101 cerr << "mag range in this view: " | 1096 } |
| 1102 << m_viewMags[v->getId()].getMin() | 1097 } |
| 1103 << " -> " | 1098 |
| 1104 << m_viewMags[v->getId()].getMax() | 1099 if (!continuingPaint && m_normalizeVisibleArea && |
| 1105 << endl; | 1100 m_viewMags[viewId] != m_lastRenderedMags[viewId]) { |
| 1106 | 1101 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT |
| 1102 cerr << "mag range has changed from last rendered range: re-rendering" | |
| 1103 << endl; | |
| 1104 #endif | |
| 1105 delete m_renderers[viewId]; | |
| 1106 m_renderers.erase(viewId); | |
| 1107 v->updatePaintRect(v->getPaintRect()); | |
| 1108 } | |
| 1107 } | 1109 } |
| 1108 | 1110 |
| 1109 void | 1111 void |
| 1110 Colour3DPlotLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const | 1112 Colour3DPlotLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const |
| 1111 { | 1113 { |
| 1119 cerr << "Colour3DPlotLayer::paint(): m_model is " << m_model << ", zoom level is " << v->getZoomLevel() << ", rect is (" << rect.x() << "," << rect.y() << ") " << rect.width() << "x" << rect.height() << endl; | 1121 cerr << "Colour3DPlotLayer::paint(): m_model is " << m_model << ", zoom level is " << v->getZoomLevel() << ", rect is (" << rect.x() << "," << rect.y() << ") " << rect.width() << "x" << rect.height() << endl; |
| 1120 #endif | 1122 #endif |
| 1121 | 1123 |
| 1122 int completion = 0; | 1124 int completion = 0; |
| 1123 if (!m_model || !m_model->isOK() || !m_model->isReady(&completion)) { | 1125 if (!m_model || !m_model->isOK() || !m_model->isReady(&completion)) { |
| 1124 if (completion > 0) { | 1126 if (completion > 0) { |
| 1125 paint.fillRect(0, 10, v->getPaintWidth() * completion / 100, | 1127 paint.fillRect(0, 10, v->getPaintWidth() * completion / 100, |
| 1126 10, QColor(120, 120, 120)); | 1128 10, QColor(120, 120, 120)); |
| 1127 } | 1129 } |
| 1128 return; | 1130 return; |
| 1129 } | 1131 } |
| 1130 | 1132 |
| 1131 if (m_model->getWidth() == 0) { | 1133 if (m_model->getWidth() == 0) { |
| 1132 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT | 1134 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT |
| 1133 cerr << "Colour3DPlotLayer::paint(): model width == 0, " | 1135 cerr << "Colour3DPlotLayer::paint(): model width == 0, " |
| 1134 << "nothing to paint (yet)" << endl; | 1136 << "nothing to paint (yet)" << endl; |
| 1135 #endif | 1137 #endif |
| 1136 return; | 1138 return; |
| 1137 } | 1139 } |
| 1138 | 1140 |
| 1139 //!!!??? | |
| 1140 | |
| 1141 if (m_normalizeVisibleArea) { | |
| 1142 rect = v->getPaintRect(); | |
| 1143 } | |
| 1144 | |
| 1145 //!!! why is the setLayerDormant(false) found here in | |
| 1146 //!!! SpectrogramLayer not present in Colour3DPlotLayer? | |
| 1147 //!!! unnecessary? vestigial? forgotten? | |
| 1148 | |
| 1149 paintWithRenderer(v, paint, rect); | 1141 paintWithRenderer(v, paint, rect); |
| 1150 } | 1142 } |
| 1151 | 1143 |
| 1152 bool | 1144 bool |
| 1153 Colour3DPlotLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame, | 1145 Colour3DPlotLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame, |
| 1154 int &resolution, | 1146 int &resolution, |
| 1155 SnapType snap) const | 1147 SnapType snap) const |
| 1156 { | 1148 { |
| 1157 if (!m_model) { | 1149 if (!m_model) { |
| 1158 return Layer::snapToFeatureFrame(v, frame, resolution, snap); | 1150 return Layer::snapToFeatureFrame(v, frame, resolution, snap); |
| 1159 } | 1151 } |
| 1160 | 1152 |
| 1161 resolution = m_model->getResolution(); | 1153 resolution = m_model->getResolution(); |
| 1162 sv_frame_t left = (frame / resolution) * resolution; | 1154 sv_frame_t left = (frame / resolution) * resolution; |
| 1163 sv_frame_t right = left + resolution; | 1155 sv_frame_t right = left + resolution; |
| 1165 switch (snap) { | 1157 switch (snap) { |
| 1166 case SnapLeft: frame = left; break; | 1158 case SnapLeft: frame = left; break; |
| 1167 case SnapRight: frame = right; break; | 1159 case SnapRight: frame = right; break; |
| 1168 case SnapNearest: | 1160 case SnapNearest: |
| 1169 case SnapNeighbouring: | 1161 case SnapNeighbouring: |
| 1170 if (frame - left > right - frame) frame = right; | 1162 if (frame - left > right - frame) frame = right; |
| 1171 else frame = left; | 1163 else frame = left; |
| 1172 break; | 1164 break; |
| 1173 } | 1165 } |
| 1174 | 1166 |
| 1175 return true; | 1167 return true; |
| 1176 } | 1168 } |
| 1177 | 1169 |
| 1183 "colourScheme=\"%2\" " | 1175 "colourScheme=\"%2\" " |
| 1184 "minY=\"%3\" " | 1176 "minY=\"%3\" " |
| 1185 "maxY=\"%4\" " | 1177 "maxY=\"%4\" " |
| 1186 "invertVertical=\"%5\" " | 1178 "invertVertical=\"%5\" " |
| 1187 "opaque=\"%6\" %7") | 1179 "opaque=\"%6\" %7") |
| 1188 .arg(convertFromColourScale(m_colourScale)) | 1180 .arg(convertFromColourScale(m_colourScale)) |
| 1189 .arg(m_colourMap) | 1181 .arg(m_colourMap) |
| 1190 .arg(m_miny) | 1182 .arg(m_miny) |
| 1191 .arg(m_maxy) | 1183 .arg(m_maxy) |
| 1192 .arg(m_invertVertical ? "true" : "false") | 1184 .arg(m_invertVertical ? "true" : "false") |
| 1193 .arg(m_opaque ? "true" : "false") | 1185 .arg(m_opaque ? "true" : "false") |
| 1200 // normalization in future: write out the column normalization | 1192 // normalization in future: write out the column normalization |
| 1201 // type separately, and then whether we are normalizing visible | 1193 // type separately, and then whether we are normalizing visible |
| 1202 // area as well afterwards | 1194 // area as well afterwards |
| 1203 | 1195 |
| 1204 s += QString("columnNormalization=\"%1\" ") | 1196 s += QString("columnNormalization=\"%1\" ") |
| 1205 .arg(m_normalization == ColumnNormalization::Max1 ? "peak" : | 1197 .arg(m_normalization == ColumnNormalization::Range01 ? "peak" : |
| 1206 m_normalization == ColumnNormalization::Hybrid ? "hybrid" : "none"); | 1198 m_normalization == ColumnNormalization::Hybrid ? "hybrid" : "none"); |
| 1207 | 1199 |
| 1208 // Old-style normalization attribute, for backward compatibility | 1200 // Old-style normalization attribute, for backward compatibility |
| 1209 | 1201 |
| 1210 s += QString("normalizeColumns=\"%1\" ") | 1202 s += QString("normalizeColumns=\"%1\" ") |
| 1211 .arg(m_normalization == ColumnNormalization::Max1 ? "true" : "false"); | 1203 .arg(m_normalization == ColumnNormalization::Range01 ? "true" : "false"); |
| 1212 | 1204 |
| 1213 // And this applies to both old- and new-style attributes | 1205 // And this applies to both old- and new-style attributes |
| 1214 | 1206 |
| 1215 s += QString("normalizeVisibleArea=\"%1\" ") | 1207 s += QString("normalizeVisibleArea=\"%1\" ") |
| 1216 .arg(m_normalizeVisibleArea ? "true" : "false"); | 1208 .arg(m_normalizeVisibleArea ? "true" : "false"); |
| 1222 Colour3DPlotLayer::setProperties(const QXmlAttributes &attributes) | 1214 Colour3DPlotLayer::setProperties(const QXmlAttributes &attributes) |
| 1223 { | 1215 { |
| 1224 bool ok = false, alsoOk = false; | 1216 bool ok = false, alsoOk = false; |
| 1225 | 1217 |
| 1226 ColourScaleType colourScale = convertToColourScale | 1218 ColourScaleType colourScale = convertToColourScale |
| 1227 (attributes.value("colourScale").toInt(&ok)); | 1219 (attributes.value("scale").toInt(&ok)); |
| 1228 if (ok) setColourScale(colourScale); | 1220 if (ok) setColourScale(colourScale); |
| 1229 | 1221 |
| 1230 int colourMap = attributes.value("colourScheme").toInt(&ok); | 1222 int colourMap = attributes.value("colourScheme").toInt(&ok); |
| 1231 if (ok) setColourMap(colourMap); | 1223 if (ok) setColourMap(colourMap); |
| 1232 | 1224 |
| 1233 BinScale binScale = (BinScale) | 1225 BinScale binScale = (BinScale) |
| 1234 attributes.value("binScale").toInt(&ok); | 1226 attributes.value("binScale").toInt(&ok); |
| 1235 if (ok) setBinScale(binScale); | 1227 if (ok) setBinScale(binScale); |
| 1236 | 1228 |
| 1237 bool invertVertical = | 1229 bool invertVertical = |
| 1238 (attributes.value("invertVertical").trimmed() == "true"); | 1230 (attributes.value("invertVertical").trimmed() == "true"); |
| 1239 setInvertVertical(invertVertical); | 1231 setInvertVertical(invertVertical); |
| 1260 if (columnNormalization != "") { | 1252 if (columnNormalization != "") { |
| 1261 | 1253 |
| 1262 haveNewStyleNormalization = true; | 1254 haveNewStyleNormalization = true; |
| 1263 | 1255 |
| 1264 if (columnNormalization == "peak") { | 1256 if (columnNormalization == "peak") { |
| 1265 setNormalization(ColumnNormalization::Max1); | 1257 setNormalization(ColumnNormalization::Range01); |
| 1266 } else if (columnNormalization == "hybrid") { | 1258 } else if (columnNormalization == "hybrid") { |
| 1267 setNormalization(ColumnNormalization::Hybrid); | 1259 setNormalization(ColumnNormalization::Hybrid); |
| 1268 } else if (columnNormalization == "none") { | 1260 } else if (columnNormalization == "none") { |
| 1269 setNormalization(ColumnNormalization::None); | 1261 setNormalization(ColumnNormalization::None); |
| 1270 } else { | 1262 } else { |
| 1278 setNormalization(ColumnNormalization::None); | 1270 setNormalization(ColumnNormalization::None); |
| 1279 | 1271 |
| 1280 bool normalizeColumns = | 1272 bool normalizeColumns = |
| 1281 (attributes.value("normalizeColumns").trimmed() == "true"); | 1273 (attributes.value("normalizeColumns").trimmed() == "true"); |
| 1282 if (normalizeColumns) { | 1274 if (normalizeColumns) { |
| 1283 setNormalization(ColumnNormalization::Max1); | 1275 setNormalization(ColumnNormalization::Range01); |
| 1284 } | 1276 } |
| 1285 | 1277 |
| 1286 bool normalizeHybrid = | 1278 bool normalizeHybrid = |
| 1287 (attributes.value("normalizeHybrid").trimmed() == "true"); | 1279 (attributes.value("normalizeHybrid").trimmed() == "true"); |
| 1288 if (normalizeHybrid) { | 1280 if (normalizeHybrid) { |
