Mercurial > hg > svgui
comparison layer/Colour3DPlotLayer.cpp @ 197:6b023411087b
* Work on harmonising colour and scale ranges between types of layer
* Add normalize options to colour 3d plot layer
author | Chris Cannam |
---|---|
date | Thu, 01 Feb 2007 14:31:28 +0000 |
parents | 57c2350a8c40 |
children | c2ed5014d4ff |
comparison
equal
deleted
inserted
replaced
196:22c99c8aa1e0 | 197:6b023411087b |
---|---|
15 | 15 |
16 #include "Colour3DPlotLayer.h" | 16 #include "Colour3DPlotLayer.h" |
17 | 17 |
18 #include "view/View.h" | 18 #include "view/View.h" |
19 #include "base/Profiler.h" | 19 #include "base/Profiler.h" |
20 #include "base/LogRange.h" | |
21 #include "ColourMapper.h" | |
20 | 22 |
21 #include <QPainter> | 23 #include <QPainter> |
22 #include <QImage> | 24 #include <QImage> |
23 #include <QRect> | 25 #include <QRect> |
24 | 26 |
30 | 32 |
31 | 33 |
32 Colour3DPlotLayer::Colour3DPlotLayer() : | 34 Colour3DPlotLayer::Colour3DPlotLayer() : |
33 m_model(0), | 35 m_model(0), |
34 m_cache(0), | 36 m_cache(0), |
35 m_colourScale(LinearScale) | 37 m_cacheStart(0), |
38 m_colourScale(LinearScale), | |
39 m_colourMap(0), | |
40 m_normalizeColumns(false), | |
41 m_normalizeVisibleArea(false) | |
36 { | 42 { |
37 | 43 |
38 } | 44 } |
39 | 45 |
40 Colour3DPlotLayer::~Colour3DPlotLayer() | 46 Colour3DPlotLayer::~Colour3DPlotLayer() |
79 | 85 |
80 Layer::PropertyList | 86 Layer::PropertyList |
81 Colour3DPlotLayer::getProperties() const | 87 Colour3DPlotLayer::getProperties() const |
82 { | 88 { |
83 PropertyList list; | 89 PropertyList list; |
90 list.push_back("Colour"); | |
84 list.push_back("Colour Scale"); | 91 list.push_back("Colour Scale"); |
92 list.push_back("Normalize Columns"); | |
93 list.push_back("Normalize Visible Area"); | |
85 return list; | 94 return list; |
86 } | 95 } |
87 | 96 |
88 QString | 97 QString |
89 Colour3DPlotLayer::getPropertyLabel(const PropertyName &name) const | 98 Colour3DPlotLayer::getPropertyLabel(const PropertyName &name) const |
90 { | 99 { |
91 if (name == "Colour Scale") return tr("Colour Scale"); | 100 if (name == "Colour") return tr("Colour"); |
101 if (name == "Colour Scale") return tr("Scale"); | |
102 if (name == "Normalize Columns") return tr("Normalize Columns"); | |
103 if (name == "Normalize Visible Area") return tr("Normalize Visible Area"); | |
92 return ""; | 104 return ""; |
93 } | 105 } |
94 | 106 |
95 Layer::PropertyType | 107 Layer::PropertyType |
96 Colour3DPlotLayer::getPropertyType(const PropertyName &name) const | 108 Colour3DPlotLayer::getPropertyType(const PropertyName &name) const |
97 { | 109 { |
110 if (name == "Normalize Columns") return ToggleProperty; | |
111 if (name == "Normalize Visible Area") return ToggleProperty; | |
98 return ValueProperty; | 112 return ValueProperty; |
99 } | 113 } |
100 | 114 |
101 QString | 115 QString |
102 Colour3DPlotLayer::getPropertyGroupName(const PropertyName &name) const | 116 Colour3DPlotLayer::getPropertyGroupName(const PropertyName &name) const |
103 { | 117 { |
118 if (name == "Normalize Columns" || | |
119 name == "Normalize Visible Area" || | |
120 name == "Colour Scale") return tr("Scale"); | |
104 return QString(); | 121 return QString(); |
105 } | 122 } |
106 | 123 |
107 int | 124 int |
108 Colour3DPlotLayer::getPropertyRangeAndValue(const PropertyName &name, | 125 Colour3DPlotLayer::getPropertyRangeAndValue(const PropertyName &name, |
115 if (!max) max = &garbage1; | 132 if (!max) max = &garbage1; |
116 | 133 |
117 if (name == "Colour Scale") { | 134 if (name == "Colour Scale") { |
118 | 135 |
119 *min = 0; | 136 *min = 0; |
120 *max = 3; | 137 *max = 2; |
121 | 138 |
122 deft = (int)m_colourScale; | 139 deft = (int)m_colourScale; |
140 | |
141 } else if (name == "Colour") { | |
142 | |
143 *min = 0; | |
144 *max = ColourMapper::getColourMapCount() - 1; | |
145 | |
146 deft = m_colourMap; | |
147 | |
148 } else if (name == "Normalize Columns") { | |
149 | |
150 deft = (m_normalizeColumns ? 1 : 0); | |
151 | |
152 } else if (name == "Normalize Visible Area") { | |
153 | |
154 deft = (m_normalizeVisibleArea ? 1 : 0); | |
123 | 155 |
124 } else { | 156 } else { |
125 deft = Layer::getPropertyRangeAndValue(name, min, max); | 157 deft = Layer::getPropertyRangeAndValue(name, min, max); |
126 } | 158 } |
127 | 159 |
130 | 162 |
131 QString | 163 QString |
132 Colour3DPlotLayer::getPropertyValueLabel(const PropertyName &name, | 164 Colour3DPlotLayer::getPropertyValueLabel(const PropertyName &name, |
133 int value) const | 165 int value) const |
134 { | 166 { |
167 if (name == "Colour") { | |
168 return ColourMapper::getColourMapName(value); | |
169 } | |
135 if (name == "Colour Scale") { | 170 if (name == "Colour Scale") { |
136 switch (value) { | 171 switch (value) { |
137 default: | 172 default: |
138 case 0: return tr("Linear"); | 173 case 0: return tr("Linear Scale"); |
139 case 1: return tr("Absolute"); | 174 case 1: return tr("Log Scale"); |
140 case 2: return tr("Meter"); | 175 case 2: return tr("+/-1 Scale"); |
141 case 3: return tr("dB"); | |
142 } | 176 } |
143 } | 177 } |
144 return tr("<unknown>"); | 178 return tr("<unknown>"); |
145 } | 179 } |
146 | 180 |
149 { | 183 { |
150 if (name == "Colour Scale") { | 184 if (name == "Colour Scale") { |
151 switch (value) { | 185 switch (value) { |
152 default: | 186 default: |
153 case 0: setColourScale(LinearScale); break; | 187 case 0: setColourScale(LinearScale); break; |
154 case 1: setColourScale(AbsoluteScale); break; | 188 case 1: setColourScale(LogScale); break; |
155 case 2: setColourScale(MeterScale); break; | 189 case 2: setColourScale(PlusMinusOneScale); break; |
156 case 3: setColourScale(dBScale); break; | |
157 } | 190 } |
191 } else if (name == "Colour") { | |
192 setColourMap(value); | |
193 } else if (name == "Normalize Columns") { | |
194 setNormalizeColumns(value ? true : false); | |
195 } else if (name == "Normalize Visible Area") { | |
196 setNormalizeVisibleArea(value ? true : false); | |
158 } | 197 } |
159 } | 198 } |
160 | 199 |
161 void | 200 void |
162 Colour3DPlotLayer::setColourScale(ColourScale scale) | 201 Colour3DPlotLayer::setColourScale(ColourScale scale) |
165 m_colourScale = scale; | 204 m_colourScale = scale; |
166 cacheInvalid(); | 205 cacheInvalid(); |
167 emit layerParametersChanged(); | 206 emit layerParametersChanged(); |
168 } | 207 } |
169 | 208 |
209 void | |
210 Colour3DPlotLayer::setColourMap(int map) | |
211 { | |
212 if (m_colourMap == map) return; | |
213 m_colourMap = map; | |
214 cacheInvalid(); | |
215 emit layerParametersChanged(); | |
216 } | |
217 | |
218 void | |
219 Colour3DPlotLayer::setNormalizeColumns(bool n) | |
220 { | |
221 if (m_normalizeColumns == n) return; | |
222 m_normalizeColumns = n; | |
223 cacheInvalid(); | |
224 emit layerParametersChanged(); | |
225 } | |
226 | |
227 bool | |
228 Colour3DPlotLayer::getNormalizeColumns() const | |
229 { | |
230 return m_normalizeColumns; | |
231 } | |
232 | |
233 void | |
234 Colour3DPlotLayer::setNormalizeVisibleArea(bool n) | |
235 { | |
236 if (m_normalizeVisibleArea == n) return; | |
237 m_normalizeVisibleArea = n; | |
238 cacheInvalid(); | |
239 emit layerParametersChanged(); | |
240 } | |
241 | |
242 bool | |
243 Colour3DPlotLayer::getNormalizeVisibleArea() const | |
244 { | |
245 return m_normalizeVisibleArea; | |
246 } | |
247 | |
170 bool | 248 bool |
171 Colour3DPlotLayer::isLayerScrollable(const View *v) const | 249 Colour3DPlotLayer::isLayerScrollable(const View *v) const |
172 { | 250 { |
251 if (m_normalizeVisibleArea) return false; | |
173 QPoint discard; | 252 QPoint discard; |
174 return !v->shouldIlluminateLocalFeatures(this, discard); | 253 return !v->shouldIlluminateLocalFeatures(this, discard); |
175 } | 254 } |
176 | 255 |
177 QString | 256 QString |
293 paint.drawText(cw + 5, ty, text); | 372 paint.drawText(cw + 5, ty, text); |
294 } | 373 } |
295 } | 374 } |
296 | 375 |
297 void | 376 void |
377 Colour3DPlotLayer::getColumn(size_t col, | |
378 DenseThreeDimensionalModel::Column &values) const | |
379 { | |
380 m_model->getColumn(col, values); | |
381 | |
382 float colMax = 0.f; | |
383 | |
384 float min = 0.f, max = 0.f; | |
385 if (m_normalizeColumns) { | |
386 min = m_model->getMinimumLevel(); | |
387 max = m_model->getMaximumLevel(); | |
388 } | |
389 | |
390 if (m_normalizeColumns) { | |
391 for (size_t y = 0; y < values.size(); ++y) { | |
392 if (values[y] > colMax || y == 0) colMax = values[y]; | |
393 } | |
394 if (m_colourScale == LogScale) { | |
395 colMax = LogRange::map(colMax); | |
396 } | |
397 } | |
398 | |
399 for (size_t y = 0; y < values.size(); ++y) { | |
400 | |
401 float value = min; | |
402 | |
403 value = values[y]; | |
404 if (m_colourScale == LogScale) { | |
405 value = LogRange::map(value); | |
406 } | |
407 | |
408 if (m_normalizeColumns) { | |
409 if (colMax != 0) { | |
410 value = max * (value / colMax); | |
411 } else { | |
412 value = 0; | |
413 } | |
414 } | |
415 | |
416 values[y] = value; | |
417 } | |
418 } | |
419 | |
420 void | |
421 Colour3DPlotLayer::fillCache(size_t firstBin, size_t lastBin) const | |
422 { | |
423 size_t modelStart = m_model->getStartFrame(); | |
424 size_t modelEnd = m_model->getEndFrame(); | |
425 size_t modelResolution = m_model->getResolution(); | |
426 | |
427 std::cerr << "Colour3DPlotLayer::fillCache: " << firstBin << " -> " << lastBin << std::endl; | |
428 | |
429 if (!m_normalizeVisibleArea || m_normalizeColumns) { | |
430 firstBin = modelStart / modelResolution; | |
431 lastBin = modelEnd / modelResolution; | |
432 } | |
433 | |
434 size_t cacheWidth = lastBin - firstBin + 1; | |
435 size_t cacheHeight = m_model->getHeight(); | |
436 | |
437 if (m_cache && | |
438 (m_cacheStart != firstBin || | |
439 m_cache->width() != cacheWidth || | |
440 m_cache->height() != cacheHeight)) { | |
441 | |
442 delete m_cache; | |
443 m_cache = 0; | |
444 } | |
445 | |
446 if (m_cache) return; | |
447 | |
448 m_cache = new QImage(cacheWidth, cacheHeight, QImage::Format_Indexed8); | |
449 m_cacheStart = firstBin; | |
450 | |
451 std::cerr << "Cache size " << cacheWidth << "x" << cacheHeight << " starting " << m_cacheStart << std::endl; | |
452 | |
453 m_cache->setNumColors(256); | |
454 DenseThreeDimensionalModel::Column values; | |
455 | |
456 float min = m_model->getMinimumLevel(); | |
457 float max = m_model->getMaximumLevel(); | |
458 | |
459 if (m_colourScale == LogScale) { | |
460 LogRange::mapRange(min, max); | |
461 } else if (m_colourScale == PlusMinusOneScale) { | |
462 min = -1.f; | |
463 max = 1.f; | |
464 } | |
465 | |
466 if (max == min) max = min + 1.0; | |
467 | |
468 ColourMapper mapper(m_colourMap, 0.f, 255.f); | |
469 | |
470 for (int index = 0; index < 256; ++index) { | |
471 | |
472 QColor colour = mapper.map(index); | |
473 m_cache->setColor(index, qRgb(colour.red(), colour.green(), colour.blue())); | |
474 } | |
475 | |
476 m_cache->fill(0); | |
477 | |
478 float visibleMax = 0.f; | |
479 | |
480 if (m_normalizeVisibleArea && !m_normalizeColumns) { | |
481 | |
482 for (size_t c = firstBin; c <= lastBin; ++c) { | |
483 | |
484 values.clear(); | |
485 getColumn(c, values); | |
486 | |
487 float colMax = 0.f; | |
488 | |
489 for (size_t y = 0; y < m_model->getHeight(); ++y) { | |
490 if (y >= values.size()) break; | |
491 if (y == 0 || values[y] > colMax) colMax = values[y]; | |
492 } | |
493 | |
494 if (c == firstBin || colMax > visibleMax) visibleMax = colMax; | |
495 } | |
496 } | |
497 | |
498 for (size_t c = firstBin; c <= lastBin; ++c) { | |
499 | |
500 values.clear(); | |
501 getColumn(c, values); | |
502 | |
503 for (size_t y = 0; y < m_model->getHeight(); ++y) { | |
504 | |
505 float value = min; | |
506 if (y < values.size()) { | |
507 value = values[y]; | |
508 } | |
509 | |
510 if (m_normalizeVisibleArea && !m_normalizeColumns) { | |
511 if (visibleMax != 0) { | |
512 value = max * (value / visibleMax); | |
513 } | |
514 } | |
515 | |
516 int pixel = int(((value - min) * 256) / (max - min)); | |
517 if (pixel < 0) pixel = 0; | |
518 if (pixel > 255) pixel = 255; | |
519 | |
520 m_cache->setPixel(c - firstBin, y, pixel); | |
521 } | |
522 } | |
523 } | |
524 | |
525 void | |
298 Colour3DPlotLayer::paint(View *v, QPainter &paint, QRect rect) const | 526 Colour3DPlotLayer::paint(View *v, QPainter &paint, QRect rect) const |
299 { | 527 { |
300 // Profiler profiler("Colour3DPlotLayer::paint"); | 528 // Profiler profiler("Colour3DPlotLayer::paint"); |
301 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT | 529 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT |
302 std::cerr << "Colour3DPlotLayer::paint(): m_model is " << m_model << ", zoom level is " << v->getZoomLevel() << std::endl; | 530 std::cerr << "Colour3DPlotLayer::paint(): m_model is " << m_model << ", zoom level is " << v->getZoomLevel() << std::endl; |
309 10, QColor(120, 120, 120)); | 537 10, QColor(120, 120, 120)); |
310 } | 538 } |
311 return; | 539 return; |
312 } | 540 } |
313 | 541 |
542 if (m_normalizeVisibleArea && !m_normalizeColumns) rect = v->rect(); | |
543 | |
314 size_t modelStart = m_model->getStartFrame(); | 544 size_t modelStart = m_model->getStartFrame(); |
315 size_t modelEnd = m_model->getEndFrame(); | 545 size_t modelEnd = m_model->getEndFrame(); |
316 size_t modelResolution = m_model->getResolution(); | 546 size_t modelResolution = m_model->getResolution(); |
317 | 547 |
318 size_t cacheWidth = (modelEnd - modelStart) / modelResolution + 1; | 548 // The cache is from the model's start frame to the model's end |
319 size_t cacheHeight = m_model->getHeight(); | 549 // frame at the model's window increment frames per pixel. We |
320 | 550 // want to draw from our start frame + x0 * zoomLevel to our start |
321 if (m_cache && | 551 // frame + x1 * zoomLevel at zoomLevel frames per pixel. |
322 (m_cache->width() != cacheWidth || | 552 |
323 m_cache->height() != cacheHeight)) { | 553 // We have quite different paint mechanisms for rendering "large" |
324 | 554 // bins (more than one bin per pixel in both directions) and |
325 delete m_cache; | 555 // "small". This is "large"; see paintDense below for "small". |
326 m_cache = 0; | 556 |
327 } | 557 int x0 = rect.left(); |
328 | 558 int x1 = rect.right() + 1; |
329 if (!m_cache) { | 559 |
330 | 560 int h = v->height(); |
331 m_cache = new QImage(cacheWidth, cacheHeight, QImage::Format_Indexed8); | 561 |
332 | 562 float srRatio = |
333 std::cerr << "Cache size " << cacheWidth << "x" << cacheHeight << std::endl; | 563 float(v->getViewManager()->getMainModelSampleRate()) / |
334 | 564 float(m_model->getSampleRate()); |
335 m_cache->setNumColors(256); | 565 |
336 DenseThreeDimensionalModel::Column values; | 566 int sx0 = int((v->getFrameForX(x0) / srRatio - long(modelStart)) |
337 | 567 / long(modelResolution)); |
338 float min = m_model->getMinimumLevel(); | 568 int sx1 = int((v->getFrameForX(x1) / srRatio - long(modelStart)) |
339 float max = m_model->getMaximumLevel(); | 569 / long(modelResolution)); |
340 | 570 int sh = m_model->getHeight(); |
341 if (max == min) max = min + 1.0; | 571 |
342 | 572 if (sx0 > 0) --sx0; |
343 int zeroIndex = 0; | 573 fillCache(sx0 < 0 ? 0 : sx0, |
344 if (min < 0.f) { | 574 sx1 < 0 ? 0 : sx1); |
345 if (m_colourScale == LinearScale) { | |
346 zeroIndex = int(((-min) * 256) / (max - min)); | |
347 } else { | |
348 max = std::max(-min, max); | |
349 min = 0; | |
350 } | |
351 } | |
352 if (zeroIndex < 0) zeroIndex = 0; | |
353 if (zeroIndex > 255) zeroIndex = 255; | |
354 | |
355 //!!! want this and spectrogram to share a colour mapping unit | |
356 | |
357 for (int index = 0; index < 256; ++index) { | |
358 int effective = abs(((index - zeroIndex) * 255) / | |
359 std::max(255 - zeroIndex, zeroIndex)); | |
360 int hue = 256 - effective; | |
361 if (zeroIndex > 0) { | |
362 if (index <= zeroIndex) hue = 255; | |
363 else hue = 0; | |
364 } | |
365 while (hue < 0) hue += 255; | |
366 while (hue > 255) hue -= 255; | |
367 int saturation = effective / 2 + 128; | |
368 if (saturation < 0) saturation = -saturation; | |
369 if (saturation > 255) saturation = 255; | |
370 int value = effective; | |
371 if (value < 0) value = -value; | |
372 if (value > 255) value = 255; | |
373 // std::cerr << "min: " << min << ", max: " << max << ", zi " << zeroIndex << ", index " << index << ": " << hue << ", " << saturation << ", " << value << std::endl; | |
374 QColor colour = QColor::fromHsv(hue, saturation, value); | |
375 // std::cerr << "rgb: " << colour.red() << "," << colour.green() << "," << colour.blue() << std::endl; | |
376 m_cache->setColor(index, qRgb(colour.red(), colour.green(), colour.blue())); | |
377 } | |
378 | |
379 m_cache->fill(zeroIndex); | |
380 | |
381 for (size_t f = modelStart; f <= modelEnd; f += modelResolution) { | |
382 | |
383 values.clear(); | |
384 m_model->getColumn(f / modelResolution, values); | |
385 | |
386 for (size_t y = 0; y < m_model->getHeight(); ++y) { | |
387 | |
388 float value = min; | |
389 if (y < values.size()) { | |
390 value = values[y]; | |
391 if (m_colourScale != LinearScale) { | |
392 value = fabs(value); | |
393 } | |
394 } | |
395 | |
396 int pixel = int(((value - min) * 256) / (max - min)); | |
397 if (pixel < 0) pixel = 0; | |
398 if (pixel > 255) pixel = 255; | |
399 | |
400 m_cache->setPixel(f / modelResolution, y, pixel); | |
401 } | |
402 } | |
403 } | |
404 | 575 |
405 if (m_model->getHeight() >= v->height() || | 576 if (m_model->getHeight() >= v->height() || |
406 modelResolution < v->getZoomLevel() / 2) { | 577 modelResolution < v->getZoomLevel() / 2) { |
407 paintDense(v, paint, rect); | 578 paintDense(v, paint, rect); |
408 return; | 579 return; |
409 } | 580 } |
410 | 581 |
411 int x0 = rect.left(); | |
412 int x1 = rect.right() + 1; | |
413 | |
414 int h = v->height(); | |
415 | |
416 // The cache is from the model's start frame to the model's end | |
417 // frame at the model's window increment frames per pixel. We | |
418 // want to draw from our start frame + x0 * zoomLevel to our start | |
419 // frame + x1 * zoomLevel at zoomLevel frames per pixel. | |
420 | |
421 //!!! Strictly speaking we want quite different paint mechanisms | |
422 //for models that have more than one bin per pixel in either | |
423 //direction. This one is only really appropriate for models with | |
424 //far fewer bins in both directions. | |
425 | |
426 float srRatio = | |
427 float(v->getViewManager()->getMainModelSampleRate()) / | |
428 float(m_model->getSampleRate()); | |
429 | |
430 int sx0 = int((v->getFrameForX(x0) / srRatio - long(modelStart)) / long(modelResolution)); | |
431 int sx1 = int((v->getFrameForX(x1) / srRatio - long(modelStart)) / long(modelResolution)); | |
432 int sh = m_model->getHeight(); | |
433 | |
434 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT | 582 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT |
435 std::cerr << "Colour3DPlotLayer::paint: w " << w << ", h " << h << ", sx0 " << sx0 << ", sx1 " << sx1 << ", sw " << sw << ", sh " << sh << std::endl; | 583 std::cerr << "Colour3DPlotLayer::paint: w " << w << ", h " << h << ", sx0 " << sx0 << ", sx1 " << sx1 << ", sw " << sw << ", sh " << sh << std::endl; |
436 std::cerr << "Colour3DPlotLayer: sample rate is " << m_model->getSampleRate() << ", resolution " << m_model->getResolution() << std::endl; | 584 std::cerr << "Colour3DPlotLayer: sample rate is " << m_model->getSampleRate() << ", resolution " << m_model->getResolution() << std::endl; |
437 #endif | 585 #endif |
438 | 586 |
439 QPoint illuminatePos; | 587 QPoint illuminatePos; |
440 bool illuminate = v->shouldIlluminateLocalFeatures(this, illuminatePos); | 588 bool illuminate = v->shouldIlluminateLocalFeatures(this, illuminatePos); |
441 char labelbuf[10]; | 589 char labelbuf[10]; |
442 | 590 |
443 for (int sx = sx0 - 1; sx <= sx1; ++sx) { | 591 for (int sx = sx0; sx <= sx1; ++sx) { |
444 | 592 |
593 int scx = 0; | |
594 if (sx > m_cacheStart) scx = sx - m_cacheStart; | |
595 | |
445 int fx = sx * int(modelResolution); | 596 int fx = sx * int(modelResolution); |
446 | 597 |
447 if (fx + modelResolution < int(modelStart) || | 598 if (fx + modelResolution < int(modelStart) || |
448 fx > int(modelEnd)) continue; | 599 fx > int(modelEnd)) continue; |
449 | 600 |
459 | 610 |
460 for (int sy = 0; sy < sh; ++sy) { | 611 for (int sy = 0; sy < sh; ++sy) { |
461 | 612 |
462 int ry0 = h - (sy * h) / sh - 1; | 613 int ry0 = h - (sy * h) / sh - 1; |
463 QRgb pixel = qRgb(255, 255, 255); | 614 QRgb pixel = qRgb(255, 255, 255); |
464 if (sx >= 0 && sx < m_cache->width() && | 615 if (scx >= 0 && scx < m_cache->width() && |
465 sy >= 0 && sy < m_cache->height()) { | 616 sy >= 0 && sy < m_cache->height()) { |
466 pixel = m_cache->pixel(sx, sy); | 617 pixel = m_cache->pixel(scx, sy); |
467 } | 618 } |
468 | 619 |
469 QRect r(rx0, ry0 - h / sh - 1, rw, h / sh + 1); | 620 QRect r(rx0, ry0 - h / sh - 1, rw, h / sh + 1); |
470 | 621 |
471 if (rw == 1) { | 622 if (rw == 1) { |
497 #endif | 648 #endif |
498 | 649 |
499 paint.drawRect(r); | 650 paint.drawRect(r); |
500 | 651 |
501 if (showLabel) { | 652 if (showLabel) { |
502 if (sx >= 0 && sx < m_cache->width() && | 653 if (scx >= 0 && scx < m_cache->width() && |
503 sy >= 0 && sy < m_cache->height()) { | 654 sy >= 0 && sy < m_cache->height()) { |
504 float value = m_model->getValueAt(sx, sy); | 655 float value = m_model->getValueAt(scx, sy); |
505 sprintf(labelbuf, "%06f", value); | 656 sprintf(labelbuf, "%06f", value); |
506 QString text(labelbuf); | 657 QString text(labelbuf); |
507 paint.setPen(Qt::white); | 658 paint.setPen(Qt::white); |
508 paint.drawText(rx0 + 2, | 659 paint.drawText(rx0 + 2, |
509 ry0 - h / sh - 1 + 2 + paint.fontMetrics().ascent(), | 660 ry0 - h / sh - 1 + 2 + paint.fontMetrics().ascent(), |
564 float mag = 0.0, div = 0.0; | 715 float mag = 0.0, div = 0.0; |
565 int max = 0; | 716 int max = 0; |
566 | 717 |
567 for (int sx = sx0i; sx <= sx1i; ++sx) { | 718 for (int sx = sx0i; sx <= sx1i; ++sx) { |
568 | 719 |
569 if (sx < 0 || sx >= m_cache->width()) continue; | 720 int scx = 0; |
721 if (sx > m_cacheStart) scx = sx - m_cacheStart; | |
722 | |
723 if (scx < 0 || scx >= m_cache->width()) continue; | |
570 | 724 |
571 for (int sy = sy0i; sy <= sy1i; ++sy) { | 725 for (int sy = sy0i; sy <= sy1i; ++sy) { |
572 | 726 |
573 if (sy < 0 || sy >= m_cache->height()) continue; | 727 if (sy < 0 || sy >= m_cache->height()) continue; |
574 | 728 |
576 if (sx == sx0i) prop *= (sx + 1) - sx0; | 730 if (sx == sx0i) prop *= (sx + 1) - sx0; |
577 if (sx == sx1i) prop *= sx1 - sx; | 731 if (sx == sx1i) prop *= sx1 - sx; |
578 if (sy == sy0i) prop *= (sy + 1) - sy0; | 732 if (sy == sy0i) prop *= (sy + 1) - sy0; |
579 if (sy == sy1i) prop *= sy1 - sy; | 733 if (sy == sy1i) prop *= sy1 - sy; |
580 | 734 |
581 mag += prop * m_cache->pixelIndex(sx, sy); | 735 mag += prop * m_cache->pixelIndex(scx, sy); |
582 max = std::max(max, m_cache->pixelIndex(sx, sy)); | 736 max = std::max(max, m_cache->pixelIndex(scx, sy)); |
583 div += prop; | 737 div += prop; |
584 } | 738 } |
585 } | 739 } |
586 | 740 |
587 if (div != 0) mag /= div; | 741 if (div != 0) mag /= div; |
622 } | 776 } |
623 | 777 |
624 return true; | 778 return true; |
625 } | 779 } |
626 | 780 |
781 QString | |
782 Colour3DPlotLayer::toXmlString(QString indent, QString extraAttributes) const | |
783 { | |
784 QString s; | |
785 | |
786 s += QString("scale=\"%1\" " | |
787 "colourScheme=\"%2\" " | |
788 "normalizeColumns=\"%3\" " | |
789 "normalizeVisibleArea=\"%4\"") | |
790 .arg((int)m_colourScale) | |
791 .arg(m_colourMap) | |
792 .arg(m_normalizeColumns ? "true" : "false") | |
793 .arg(m_normalizeVisibleArea ? "true" : "false"); | |
794 | |
795 return Layer::toXmlString(indent, extraAttributes + " " + s); | |
796 } | |
797 | |
798 void | |
799 Colour3DPlotLayer::setProperties(const QXmlAttributes &attributes) | |
800 { | |
801 bool ok = false; | |
802 | |
803 ColourScale scale = (ColourScale)attributes.value("scale").toInt(&ok); | |
804 if (ok) setColourScale(scale); | |
805 | |
806 int colourMap = attributes.value("colourScheme").toInt(&ok); | |
807 if (ok) setColourMap(colourMap); | |
808 | |
809 bool normalizeColumns = | |
810 (attributes.value("normalizeColumns").trimmed() == "true"); | |
811 setNormalizeColumns(normalizeColumns); | |
812 | |
813 bool normalizeVisibleArea = | |
814 (attributes.value("normalizeVisibleArea").trimmed() == "true"); | |
815 setNormalizeVisibleArea(normalizeVisibleArea); | |
816 } | |
817 | |
627 #ifdef INCLUDE_MOCFILES | 818 #ifdef INCLUDE_MOCFILES |
628 #include "Colour3DPlotLayer.moc.cpp" | 819 #include "Colour3DPlotLayer.moc.cpp" |
629 #endif | 820 #endif |
630 | 821 |
631 | 822 |