00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "Colour3DPlotLayer.h"
00017
00018 #include "view/View.h"
00019 #include "base/Profiler.h"
00020 #include "base/LogRange.h"
00021 #include "base/ColourMapper.h"
00022
00023 #include <QPainter>
00024 #include <QImage>
00025 #include <QRect>
00026 #include <QTextStream>
00027
00028 #include <iostream>
00029
00030 #include <cassert>
00031
00032
00033
00034
00035 Colour3DPlotLayer::Colour3DPlotLayer() :
00036 m_model(0),
00037 m_cache(0),
00038 m_cacheStart(0),
00039 m_colourScale(LinearScale),
00040 m_colourMap(0),
00041 m_normalizeColumns(false),
00042 m_normalizeVisibleArea(false),
00043 m_invertVertical(false)
00044 {
00045
00046 }
00047
00048 Colour3DPlotLayer::~Colour3DPlotLayer()
00049 {
00050 }
00051
00052 void
00053 Colour3DPlotLayer::setModel(const DenseThreeDimensionalModel *model)
00054 {
00055 if (m_model == model) return;
00056 const DenseThreeDimensionalModel *oldModel = m_model;
00057 m_model = model;
00058 if (!m_model || !m_model->isOK()) return;
00059
00060 connectSignals(m_model);
00061
00062 connect(m_model, SIGNAL(modelChanged()), this, SLOT(cacheInvalid()));
00063 connect(m_model, SIGNAL(modelChanged(size_t, size_t)),
00064 this, SLOT(cacheInvalid(size_t, size_t)));
00065
00066 emit modelReplaced();
00067 emit sliceableModelReplaced(oldModel, model);
00068 }
00069
00070 void
00071 Colour3DPlotLayer::cacheInvalid()
00072 {
00073 delete m_cache;
00074 m_cache = 0;
00075 }
00076
00077 void
00078 Colour3DPlotLayer::cacheInvalid(size_t, size_t)
00079 {
00080 cacheInvalid();
00081 }
00082
00083 Layer::PropertyList
00084 Colour3DPlotLayer::getProperties() const
00085 {
00086 PropertyList list;
00087 list.push_back("Colour");
00088 list.push_back("Colour Scale");
00089 list.push_back("Normalize Columns");
00090 list.push_back("Normalize Visible Area");
00091 list.push_back("Invert Vertical Scale");
00092 return list;
00093 }
00094
00095 QString
00096 Colour3DPlotLayer::getPropertyLabel(const PropertyName &name) const
00097 {
00098 if (name == "Colour") return tr("Colour");
00099 if (name == "Colour Scale") return tr("Scale");
00100 if (name == "Normalize Columns") return tr("Normalize Columns");
00101 if (name == "Normalize Visible Area") return tr("Normalize Visible Area");
00102 if (name == "Invert Vertical Scale") return tr("Invert Vertical Scale");
00103 return "";
00104 }
00105
00106 QString
00107 Colour3DPlotLayer::getPropertyIconName(const PropertyName &name) const
00108 {
00109 if (name == "Normalize Columns") return "normalise-columns";
00110 if (name == "Normalize Visible Area") return "normalise";
00111 if (name == "Invert Vertical Scale") return "invert-vertical";
00112 return "";
00113 }
00114
00115 Layer::PropertyType
00116 Colour3DPlotLayer::getPropertyType(const PropertyName &name) const
00117 {
00118 if (name == "Normalize Columns") return ToggleProperty;
00119 if (name == "Normalize Visible Area") return ToggleProperty;
00120 if (name == "Invert Vertical Scale") return ToggleProperty;
00121 return ValueProperty;
00122 }
00123
00124 QString
00125 Colour3DPlotLayer::getPropertyGroupName(const PropertyName &name) const
00126 {
00127 if (name == "Normalize Columns" ||
00128 name == "Normalize Visible Area" ||
00129 name == "Invert Vertical Scale" ||
00130 name == "Colour Scale") return tr("Scale");
00131 return QString();
00132 }
00133
00134 int
00135 Colour3DPlotLayer::getPropertyRangeAndValue(const PropertyName &name,
00136 int *min, int *max, int *deflt) const
00137 {
00138 int val = 0;
00139
00140 int garbage0, garbage1, garbage2;
00141 if (!min) min = &garbage0;
00142 if (!max) max = &garbage1;
00143 if (!deflt) deflt = &garbage2;
00144
00145 if (name == "Colour Scale") {
00146
00147 *min = 0;
00148 *max = 2;
00149 *deflt = (int)LinearScale;
00150
00151 val = (int)m_colourScale;
00152
00153 } else if (name == "Colour") {
00154
00155 *min = 0;
00156 *max = ColourMapper::getColourMapCount() - 1;
00157 *deflt = 0;
00158
00159 val = m_colourMap;
00160
00161 } else if (name == "Normalize Columns") {
00162
00163 *deflt = 0;
00164 val = (m_normalizeColumns ? 1 : 0);
00165
00166 } else if (name == "Normalize Visible Area") {
00167
00168 *deflt = 0;
00169 val = (m_normalizeVisibleArea ? 1 : 0);
00170
00171 } else if (name == "Invert Vertical Scale") {
00172
00173 *deflt = 0;
00174 val = (m_invertVertical ? 1 : 0);
00175
00176 } else {
00177 val = Layer::getPropertyRangeAndValue(name, min, max, deflt);
00178 }
00179
00180 return val;
00181 }
00182
00183 QString
00184 Colour3DPlotLayer::getPropertyValueLabel(const PropertyName &name,
00185 int value) const
00186 {
00187 if (name == "Colour") {
00188 return ColourMapper::getColourMapName(value);
00189 }
00190 if (name == "Colour Scale") {
00191 switch (value) {
00192 default:
00193 case 0: return tr("Linear");
00194 case 1: return tr("Log");
00195 case 2: return tr("+/-1");
00196 }
00197 }
00198 return tr("<unknown>");
00199 }
00200
00201 void
00202 Colour3DPlotLayer::setProperty(const PropertyName &name, int value)
00203 {
00204 if (name == "Colour Scale") {
00205 switch (value) {
00206 default:
00207 case 0: setColourScale(LinearScale); break;
00208 case 1: setColourScale(LogScale); break;
00209 case 2: setColourScale(PlusMinusOneScale); break;
00210 }
00211 } else if (name == "Colour") {
00212 setColourMap(value);
00213 } else if (name == "Normalize Columns") {
00214 setNormalizeColumns(value ? true : false);
00215 } else if (name == "Normalize Visible Area") {
00216 setNormalizeVisibleArea(value ? true : false);
00217 } else if (name == "Invert Vertical Scale") {
00218 setInvertVertical(value ? true : false);
00219 }
00220 }
00221
00222 void
00223 Colour3DPlotLayer::setColourScale(ColourScale scale)
00224 {
00225 if (m_colourScale == scale) return;
00226 m_colourScale = scale;
00227 cacheInvalid();
00228 emit layerParametersChanged();
00229 }
00230
00231 void
00232 Colour3DPlotLayer::setColourMap(int map)
00233 {
00234 if (m_colourMap == map) return;
00235 m_colourMap = map;
00236 cacheInvalid();
00237 emit layerParametersChanged();
00238 }
00239
00240 void
00241 Colour3DPlotLayer::setNormalizeColumns(bool n)
00242 {
00243 if (m_normalizeColumns == n) return;
00244 m_normalizeColumns = n;
00245 cacheInvalid();
00246 emit layerParametersChanged();
00247 }
00248
00249 bool
00250 Colour3DPlotLayer::getNormalizeColumns() const
00251 {
00252 return m_normalizeColumns;
00253 }
00254
00255 void
00256 Colour3DPlotLayer::setNormalizeVisibleArea(bool n)
00257 {
00258 if (m_normalizeVisibleArea == n) return;
00259 m_normalizeVisibleArea = n;
00260 cacheInvalid();
00261 emit layerParametersChanged();
00262 }
00263
00264 bool
00265 Colour3DPlotLayer::getNormalizeVisibleArea() const
00266 {
00267 return m_normalizeVisibleArea;
00268 }
00269
00270 void
00271 Colour3DPlotLayer::setInvertVertical(bool n)
00272 {
00273 if (m_invertVertical == n) return;
00274 m_invertVertical = n;
00275 cacheInvalid();
00276 emit layerParametersChanged();
00277 }
00278
00279 bool
00280 Colour3DPlotLayer::getInvertVertical() const
00281 {
00282 return m_invertVertical;
00283 }
00284
00285 bool
00286 Colour3DPlotLayer::isLayerScrollable(const View *v) const
00287 {
00288 if (m_normalizeVisibleArea) return false;
00289 QPoint discard;
00290 return !v->shouldIlluminateLocalFeatures(this, discard);
00291 }
00292
00293 QString
00294 Colour3DPlotLayer::getFeatureDescription(View *v, QPoint &pos) const
00295 {
00296 if (!m_model) return "";
00297
00298 int x = pos.x();
00299 int y = pos.y();
00300
00301 size_t modelStart = m_model->getStartFrame();
00302 size_t modelResolution = m_model->getResolution();
00303
00304 float srRatio =
00305 float(v->getViewManager()->getMainModelSampleRate()) /
00306 float(m_model->getSampleRate());
00307
00308 int sx0 = int((v->getFrameForX(x) / srRatio - long(modelStart)) /
00309 long(modelResolution));
00310
00311 int f0 = sx0 * modelResolution;
00312 int f1 = f0 + modelResolution;
00313
00314 float binHeight = float(v->height()) / m_model->getHeight();
00315 int sy = int((v->height() - y) / binHeight);
00316
00317 if (m_invertVertical) sy = m_model->getHeight() - sy - 1;
00318
00319 float value = m_model->getValueAt(sx0, sy);
00320
00321
00322
00323 QString binName = m_model->getBinName(sy);
00324 if (binName == "") binName = QString("[%1]").arg(sy + 1);
00325 else binName = QString("%1 [%2]").arg(binName).arg(sy + 1);
00326
00327 QString text = tr("Time:\t%1 - %2\nBin:\t%3\nValue:\t%4")
00328 .arg(RealTime::frame2RealTime(f0, m_model->getSampleRate())
00329 .toText(true).c_str())
00330 .arg(RealTime::frame2RealTime(f1, m_model->getSampleRate())
00331 .toText(true).c_str())
00332 .arg(binName)
00333 .arg(value);
00334
00335 return text;
00336 }
00337
00338 int
00339 Colour3DPlotLayer::getColourScaleWidth(QPainter &) const
00340 {
00341 int cw = 20;
00342 return cw;
00343 }
00344
00345 int
00346 Colour3DPlotLayer::getVerticalScaleWidth(View *, QPainter &paint) const
00347 {
00348 if (!m_model) return 0;
00349
00350 QString sampleText = QString("[%1]").arg(m_model->getHeight());
00351 int tw = paint.fontMetrics().width(sampleText);
00352 bool another = false;
00353
00354 for (size_t i = 0; i < m_model->getHeight(); ++i) {
00355 if (m_model->getBinName(i).length() > sampleText.length()) {
00356 sampleText = m_model->getBinName(i);
00357 another = true;
00358 }
00359 }
00360 if (another) {
00361 tw = std::max(tw, paint.fontMetrics().width(sampleText));
00362 }
00363
00364 return tw + 13 + getColourScaleWidth(paint);
00365 }
00366
00367 void
00368 Colour3DPlotLayer::paintVerticalScale(View *v, QPainter &paint, QRect rect) const
00369 {
00370 if (!m_model) return;
00371
00372 int h = rect.height(), w = rect.width();
00373 float binHeight = float(v->height()) / m_model->getHeight();
00374
00375 int cw = getColourScaleWidth(paint);
00376
00377 int ch = h - 20;
00378 if (ch > 20 && m_cache) {
00379
00380 paint.setPen(v->getForeground());
00381 paint.drawRect(4, 10, cw - 8, ch - 19);
00382
00383 for (int y = 0; y < ch - 20; ++y) {
00384 QRgb c = m_cache->color(((ch - 20 - y) * 255) / (ch - 20));
00385
00386 paint.setPen(QColor(qRed(c), qGreen(c), qBlue(c)));
00387 paint.drawLine(5, 11 + y, cw - 5, 11 + y);
00388 }
00389 }
00390
00391 paint.setPen(v->getForeground());
00392
00393 int count = v->height() / paint.fontMetrics().height();
00394 int step = m_model->getHeight() / count;
00395 if (step == 0) step = 1;
00396
00397 for (size_t i = 0; i < m_model->getHeight(); ++i) {
00398
00399 size_t idx = i;
00400 if (m_invertVertical) idx = m_model->getHeight() - idx - 1;
00401
00402 if ((idx % step) != 0) continue;
00403
00404 int y0 = int(v->height() - (i * binHeight) - 1);
00405
00406 QString text = m_model->getBinName(idx);
00407 if (text == "") text = QString("[%1]").arg(idx + 1);
00408
00409 paint.drawLine(cw, y0, w, y0);
00410
00411 int cy = int(y0 - (step * binHeight)/2);
00412 int ty = cy + paint.fontMetrics().ascent()/2;
00413
00414 paint.drawText(cw + 5, ty, text);
00415 }
00416 }
00417
00418 void
00419 Colour3DPlotLayer::getColumn(size_t col,
00420 DenseThreeDimensionalModel::Column &values) const
00421 {
00422 m_model->getColumn(col, values);
00423
00424 float colMax = 0.f, colMin = 0.f;
00425
00426 float min = 0.f, max = 0.f;
00427 if (m_normalizeColumns) {
00428 min = m_model->getMinimumLevel();
00429 max = m_model->getMaximumLevel();
00430 }
00431
00432 if (m_normalizeColumns) {
00433 for (size_t y = 0; y < values.size(); ++y) {
00434 if (y == 0 || values[y] > colMax) colMax = values[y];
00435 if (y == 0 || values[y] < colMin) colMin = values[y];
00436 }
00437 if (colMin == colMax) colMax = colMin + 1;
00438 }
00439
00440 for (size_t y = 0; y < values.size(); ++y) {
00441
00442 float value = min;
00443
00444 value = values[y];
00445
00446 if (m_normalizeColumns) {
00447 float norm = (value - colMin) / (colMax - colMin);
00448 value = min + (max - min) * norm;
00449 }
00450
00451 values[y] = value;
00452 }
00453 }
00454
00455 void
00456 Colour3DPlotLayer::fillCache(size_t firstBin, size_t lastBin) const
00457 {
00458 size_t modelStart = m_model->getStartFrame();
00459 size_t modelEnd = m_model->getEndFrame();
00460 size_t modelResolution = m_model->getResolution();
00461
00462
00463
00464 if (!m_normalizeVisibleArea || m_normalizeColumns) {
00465 firstBin = modelStart / modelResolution;
00466 lastBin = modelEnd / modelResolution;
00467 }
00468
00469 size_t cacheWidth = lastBin - firstBin + 1;
00470 size_t cacheHeight = m_model->getHeight();
00471
00472 if (m_cache &&
00473 (m_cacheStart != firstBin ||
00474 m_cache->width() != int(cacheWidth) ||
00475 m_cache->height() != int(cacheHeight))) {
00476
00477 delete m_cache;
00478 m_cache = 0;
00479 }
00480
00481 if (m_cache) return;
00482
00483 m_cache = new QImage(cacheWidth, cacheHeight, QImage::Format_Indexed8);
00484 m_cacheStart = firstBin;
00485
00486
00487
00488 m_cache->setNumColors(256);
00489 DenseThreeDimensionalModel::Column values;
00490
00491 float min = m_model->getMinimumLevel();
00492 float max = m_model->getMaximumLevel();
00493
00494 if (m_colourScale == LogScale) {
00495 LogRange::mapRange(min, max);
00496 } else if (m_colourScale == PlusMinusOneScale) {
00497 min = -1.f;
00498 max = 1.f;
00499 }
00500
00501 if (max == min) max = min + 1.0;
00502
00503 ColourMapper mapper(m_colourMap, 0.f, 255.f);
00504
00505 for (int index = 0; index < 256; ++index) {
00506
00507 QColor colour = mapper.map(index);
00508 m_cache->setColor(index, qRgb(colour.red(), colour.green(), colour.blue()));
00509 }
00510
00511 m_cache->fill(0);
00512
00513 float visibleMax = 0.f, visibleMin = 0.f;
00514
00515 if (m_normalizeVisibleArea && !m_normalizeColumns) {
00516
00517 for (size_t c = firstBin; c <= lastBin; ++c) {
00518
00519 values.clear();
00520 getColumn(c, values);
00521
00522 float colMax = 0.f, colMin = 0.f;
00523
00524 for (size_t y = 0; y < m_model->getHeight(); ++y) {
00525 if (y >= values.size()) break;
00526 if (y == 0 || values[y] > colMax) colMax = values[y];
00527 if (y == 0 || values[y] < colMin) colMin = values[y];
00528 }
00529
00530 if (c == firstBin || colMax > visibleMax) visibleMax = colMax;
00531 if (c == firstBin || colMin < visibleMin) visibleMin = colMin;
00532 }
00533 }
00534
00535 if (visibleMin == visibleMax) visibleMax = visibleMin + 1;
00536
00537 for (size_t c = firstBin; c <= lastBin; ++c) {
00538
00539 values.clear();
00540 getColumn(c, values);
00541
00542 for (size_t y = 0; y < m_model->getHeight(); ++y) {
00543
00544 float value = min;
00545 if (y < values.size()) {
00546 value = values[y];
00547 }
00548
00549 if (m_normalizeVisibleArea && !m_normalizeColumns) {
00550 float norm = (value - visibleMin) / (visibleMax - visibleMin);
00551 value = min + (max - min) * norm;
00552 }
00553
00554 if (m_colourScale == LogScale) {
00555 value = LogRange::map(value);
00556 }
00557
00558 int pixel = int(((value - min) * 256) / (max - min));
00559 if (pixel < 0) pixel = 0;
00560 if (pixel > 255) pixel = 255;
00561
00562 if (m_invertVertical) {
00563 m_cache->setPixel(c - firstBin, m_model->getHeight() - y - 1,
00564 pixel);
00565 } else {
00566 m_cache->setPixel(c - firstBin, y, pixel);
00567 }
00568 }
00569 }
00570 }
00571
00572 void
00573 Colour3DPlotLayer::paint(View *v, QPainter &paint, QRect rect) const
00574 {
00575
00576 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
00577 std::cerr << "Colour3DPlotLayer::paint(): m_model is " << m_model << ", zoom level is " << v->getZoomLevel() << std::endl;
00578 #endif
00579
00580 int completion = 0;
00581 if (!m_model || !m_model->isOK() || !m_model->isReady(&completion)) {
00582 if (completion > 0) {
00583 paint.fillRect(0, 10, v->width() * completion / 100,
00584 10, QColor(120, 120, 120));
00585 }
00586 return;
00587 }
00588
00589 if (m_normalizeVisibleArea && !m_normalizeColumns) rect = v->rect();
00590
00591 size_t modelStart = m_model->getStartFrame();
00592 size_t modelEnd = m_model->getEndFrame();
00593 size_t modelResolution = m_model->getResolution();
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604 int x0 = rect.left();
00605 int x1 = rect.right() + 1;
00606
00607 int h = v->height();
00608
00609 float srRatio =
00610 float(v->getViewManager()->getMainModelSampleRate()) /
00611 float(m_model->getSampleRate());
00612
00613 int sx0 = int((v->getFrameForX(x0) / srRatio - long(modelStart))
00614 / long(modelResolution));
00615 int sx1 = int((v->getFrameForX(x1) / srRatio - long(modelStart))
00616 / long(modelResolution));
00617 int sh = m_model->getHeight();
00618
00619 if (sx0 > 0) --sx0;
00620 fillCache(sx0 < 0 ? 0 : sx0,
00621 sx1 < 0 ? 0 : sx1);
00622
00623 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
00624 std::cerr << "Colour3DPlotLayer::paint: height = "<< m_model->getHeight() << ", modelStart = " << modelStart << ", resolution = " << modelResolution << ", model rate = " << m_model->getSampleRate() << std::endl;
00625 #endif
00626
00627 if (int(m_model->getHeight()) >= v->height() ||
00628 int(modelResolution * m_model->getSampleRate()) < v->getZoomLevel() / 2) {
00629 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
00630 std::cerr << "calling paintDense" << std::endl;
00631 #endif
00632 paintDense(v, paint, rect);
00633 return;
00634 }
00635
00636 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
00637 std::cerr << "Colour3DPlotLayer::paint: w " << x1-x0 << ", h " << h << ", sx0 " << sx0 << ", sx1 " << sx1 << ", sw " << sx1-sx0 << ", sh " << sh << std::endl;
00638 std::cerr << "Colour3DPlotLayer: sample rate is " << m_model->getSampleRate() << ", resolution " << m_model->getResolution() << std::endl;
00639 #endif
00640
00641 QPoint illuminatePos;
00642 bool illuminate = v->shouldIlluminateLocalFeatures(this, illuminatePos);
00643 char labelbuf[10];
00644
00645 for (int sx = sx0; sx <= sx1; ++sx) {
00646
00647 int scx = 0;
00648 if (sx > int(m_cacheStart)) scx = sx - m_cacheStart;
00649
00650 int fx = sx * int(modelResolution);
00651
00652 if (fx + int(modelResolution) <= int(modelStart) ||
00653 fx > int(modelEnd)) continue;
00654
00655 int rx0 = v->getXForFrame(int((fx + int(modelStart)) * srRatio));
00656 int rx1 = v->getXForFrame(int((fx + int(modelStart) + int(modelResolution) + 1) * srRatio));
00657
00658 int rw = rx1 - rx0;
00659 if (rw < 1) rw = 1;
00660
00661 bool showLabel = (rw > 10 &&
00662 paint.fontMetrics().width("0.000000") < rw - 3 &&
00663 paint.fontMetrics().height() < (h / sh));
00664
00665 for (int sy = 0; sy < sh; ++sy) {
00666
00667 int ry0 = h - (sy * h) / sh - 1;
00668 QRgb pixel = qRgb(255, 255, 255);
00669 if (scx >= 0 && scx < m_cache->width() &&
00670 sy >= 0 && sy < m_cache->height()) {
00671 pixel = m_cache->pixel(scx, sy);
00672 }
00673
00674 QRect r(rx0, ry0 - h / sh - 1, rw, h / sh + 1);
00675
00676 if (rw == 1) {
00677 paint.setPen(pixel);
00678 paint.setBrush(Qt::NoBrush);
00679 paint.drawLine(r.x(), r.y(), r.x(), r.y() + r.height() - 1);
00680 continue;
00681 }
00682
00683 QColor pen(255, 255, 255, 80);
00684 QColor brush(pixel);
00685
00686 if (rw > 3 && r.height() > 3) {
00687 brush.setAlpha(160);
00688 }
00689
00690 paint.setPen(Qt::NoPen);
00691 paint.setBrush(brush);
00692
00693 if (illuminate) {
00694 if (r.contains(illuminatePos)) {
00695 paint.setPen(v->getForeground());
00696 }
00697 }
00698
00699 #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT
00700 std::cerr << "rect " << r.x() << "," << r.y() << " "
00701 << r.width() << "x" << r.height() << std::endl;
00702 #endif
00703
00704 paint.drawRect(r);
00705
00706 if (showLabel) {
00707 if (scx >= 0 && scx < m_cache->width() &&
00708 sy >= 0 && sy < m_cache->height()) {
00709 float value = m_model->getValueAt(scx, sy);
00710 sprintf(labelbuf, "%06f", value);
00711 QString text(labelbuf);
00712 paint.setPen(v->getBackground());
00713 paint.drawText(rx0 + 2,
00714 ry0 - h / sh - 1 + 2 + paint.fontMetrics().ascent(),
00715 text);
00716 }
00717 }
00718 }
00719 }
00720 }
00721
00722 void
00723 Colour3DPlotLayer::paintDense(View *v, QPainter &paint, QRect rect) const
00724 {
00725 size_t modelStart = m_model->getStartFrame();
00726 size_t modelResolution = m_model->getResolution();
00727
00728 float srRatio =
00729 float(v->getViewManager()->getMainModelSampleRate()) /
00730 float(m_model->getSampleRate());
00731
00732 int x0 = rect.left();
00733 int x1 = rect.right() + 1;
00734
00735 int w = x1 - x0;
00736 int h = v->height();
00737 int sh = m_model->getHeight();
00738
00739 QImage img(w, h, QImage::Format_RGB32);
00740
00741 for (int x = x0; x < x1; ++x) {
00742
00743 long xf = long(v->getFrameForX(x));
00744 if (xf < 0) {
00745 for (int y = 0; y < h; ++y) {
00746 img.setPixel(x - x0, y, m_cache->color(0));
00747 }
00748 continue;
00749 }
00750
00751 xf /= srRatio;
00752
00753 float sx0 = (float(xf) - modelStart) / modelResolution;
00754 float sx1 = (float(v->getFrameForX(x+1) / srRatio) - modelStart) / modelResolution;
00755
00756 int sx0i = int(sx0 + 0.001);
00757 int sx1i = int(sx1);
00758
00759 for (int y = 0; y < h; ++y) {
00760
00761 float sy0 = (float(h - y - 1) * sh) / h;
00762 float sy1 = (float(h - y) * sh) / h;
00763
00764 int sy0i = int(sy0 + 0.001);
00765 int sy1i = int(sy1);
00766
00767 float mag = 0.0, div = 0.0;
00768 int max = 0;
00769
00770 for (int sx = sx0i; sx <= sx1i; ++sx) {
00771
00772 int scx = 0;
00773 if (sx > int(m_cacheStart)) scx = sx - int(m_cacheStart);
00774
00775 if (scx < 0 || scx >= m_cache->width()) continue;
00776
00777 for (int sy = sy0i; sy <= sy1i; ++sy) {
00778
00779 if (sy < 0 || sy >= m_cache->height()) continue;
00780
00781 float prop = 1.0;
00782 if (sx == sx0i) prop *= (sx + 1) - sx0;
00783 if (sx == sx1i) prop *= sx1 - sx;
00784 if (sy == sy0i) prop *= (sy + 1) - sy0;
00785 if (sy == sy1i) prop *= sy1 - sy;
00786
00787 mag += prop * m_cache->pixelIndex(scx, sy);
00788 max = std::max(max, m_cache->pixelIndex(scx, sy));
00789 div += prop;
00790 }
00791 }
00792
00793 if (div != 0) mag /= div;
00794 if (mag < 0) mag = 0;
00795 if (mag > 255) mag = 255;
00796 if (max < 0) max = 0;
00797 if (max > 255) max = 255;
00798
00799 img.setPixel(x - x0, y, m_cache->color(int(mag + 0.001)));
00800
00801 }
00802 }
00803
00804 paint.drawImage(x0, 0, img);
00805 }
00806
00807 bool
00808 Colour3DPlotLayer::snapToFeatureFrame(View *v, int &frame,
00809 size_t &resolution,
00810 SnapType snap) const
00811 {
00812 if (!m_model) {
00813 return Layer::snapToFeatureFrame(v, frame, resolution, snap);
00814 }
00815
00816 resolution = m_model->getResolution();
00817 int left = (frame / resolution) * resolution;
00818 int right = left + resolution;
00819
00820 switch (snap) {
00821 case SnapLeft: frame = left; break;
00822 case SnapRight: frame = right; break;
00823 case SnapNearest:
00824 case SnapNeighbouring:
00825 if (frame - left > right - frame) frame = right;
00826 else frame = left;
00827 break;
00828 }
00829
00830 return true;
00831 }
00832
00833 void
00834 Colour3DPlotLayer::toXml(QTextStream &stream,
00835 QString indent, QString extraAttributes) const
00836 {
00837 QString s = QString("scale=\"%1\" "
00838 "colourScheme=\"%2\" "
00839 "normalizeColumns=\"%3\" "
00840 "normalizeVisibleArea=\"%4\"")
00841 .arg((int)m_colourScale)
00842 .arg(m_colourMap)
00843 .arg(m_normalizeColumns ? "true" : "false")
00844 .arg(m_normalizeVisibleArea ? "true" : "false");
00845
00846 Layer::toXml(stream, indent, extraAttributes + " " + s);
00847 }
00848
00849 void
00850 Colour3DPlotLayer::setProperties(const QXmlAttributes &attributes)
00851 {
00852 bool ok = false;
00853
00854 ColourScale scale = (ColourScale)attributes.value("scale").toInt(&ok);
00855 if (ok) setColourScale(scale);
00856
00857 int colourMap = attributes.value("colourScheme").toInt(&ok);
00858 if (ok) setColourMap(colourMap);
00859
00860 bool normalizeColumns =
00861 (attributes.value("normalizeColumns").trimmed() == "true");
00862 setNormalizeColumns(normalizeColumns);
00863
00864 bool normalizeVisibleArea =
00865 (attributes.value("normalizeVisibleArea").trimmed() == "true");
00866 setNormalizeVisibleArea(normalizeVisibleArea);
00867 }
00868