Mercurial > hg > svgui
comparison layer/SliceLayer.cpp @ 1486:ac0a8addabcf
Merge from branch by-id
| author | Chris Cannam | 
|---|---|
| date | Wed, 17 Jul 2019 14:25:16 +0100 | 
| parents | 0e971e3d93e2 | 
| children | 
   comparison
  equal
  deleted
  inserted
  replaced
| 1468:de41a11cabc2 | 1486:ac0a8addabcf | 
|---|---|
| 30 #include <QPainterPath> | 30 #include <QPainterPath> | 
| 31 #include <QTextStream> | 31 #include <QTextStream> | 
| 32 | 32 | 
| 33 | 33 | 
| 34 SliceLayer::SliceLayer() : | 34 SliceLayer::SliceLayer() : | 
| 35 m_sliceableModel(nullptr), | |
| 36 m_binAlignment(BinsSpanScalePoints), | 35 m_binAlignment(BinsSpanScalePoints), | 
| 37 m_colourMap(int(ColourMapper::Ice)), | 36 m_colourMap(int(ColourMapper::Ice)), | 
| 38 m_colourInverted(false), | 37 m_colourInverted(false), | 
| 39 m_energyScale(dBScale), | 38 m_energyScale(dBScale), | 
| 40 m_samplingMode(SampleMean), | 39 m_samplingMode(SampleMean), | 
| 55 { | 54 { | 
| 56 | 55 | 
| 57 } | 56 } | 
| 58 | 57 | 
| 59 void | 58 void | 
| 60 SliceLayer::setSliceableModel(const Model *model) | 59 SliceLayer::setSliceableModel(ModelId modelId) | 
| 61 { | 60 { | 
| 62 const DenseThreeDimensionalModel *sliceable = | 61 auto newModel = ModelById::getAs<DenseThreeDimensionalModel>(modelId); | 
| 63 dynamic_cast<const DenseThreeDimensionalModel *>(model); | 62 | 
| 64 | 63 if (!modelId.isNone() && !newModel) { | 
| 65 if (model && !sliceable) { | 64 throw std::logic_error("Not a DenseThreeDimensionalModel"); | 
| 66 cerr << "WARNING: SliceLayer::setSliceableModel(" << model | 65 } | 
| 67 << "): model is not a DenseThreeDimensionalModel" << endl; | 66 | 
| 68 } | 67 if (m_sliceableModel == modelId) return; | 
| 69 | 68 m_sliceableModel = modelId; | 
| 70 if (m_sliceableModel == sliceable) return; | 69 | 
| 71 | 70 if (newModel) { | 
| 72 m_sliceableModel = sliceable; | 71 connectSignals(m_sliceableModel); | 
| 73 | 72 | 
| 74 if (!m_sliceableModel) return; | 73 if (m_minbin == 0 && m_maxbin == 0) { | 
| 75 | 74 m_minbin = 0; | 
| 76 connectSignals(m_sliceableModel); | 75 m_maxbin = newModel->getHeight(); | 
| 77 | 76 } | 
| 78 if (m_minbin == 0 && m_maxbin == 0) { | |
| 79 m_minbin = 0; | |
| 80 m_maxbin = m_sliceableModel->getHeight(); | |
| 81 } | 77 } | 
| 82 | 78 | 
| 83 emit modelReplaced(); | 79 emit modelReplaced(); | 
| 84 emit layerParametersChanged(); | 80 emit layerParametersChanged(); | 
| 85 } | 81 } | 
| 86 | 82 | 
| 87 void | 83 void | 
| 88 SliceLayer::sliceableModelReplaced(const Model *orig, const Model *replacement) | 84 SliceLayer::sliceableModelReplaced(ModelId orig, ModelId replacement) | 
| 89 { | 85 { | 
| 90 SVDEBUG << "SliceLayer::sliceableModelReplaced(" << orig << ", " << replacement << ")" << endl; | 86 SVDEBUG << "SliceLayer::sliceableModelReplaced(" << orig << ", " << replacement << ")" << endl; | 
| 91 | 87 | 
| 92 if (orig == m_sliceableModel) { | 88 if (orig == m_sliceableModel) { | 
| 93 setSliceableModel | 89 setSliceableModel(replacement); | 
| 94 (dynamic_cast<const DenseThreeDimensionalModel *>(replacement)); | |
| 95 } | |
| 96 } | |
| 97 | |
| 98 void | |
| 99 SliceLayer::modelAboutToBeDeleted(Model *m) | |
| 100 { | |
| 101 SVDEBUG << "SliceLayer::modelAboutToBeDeleted(" << m << ")" << endl; | |
| 102 | |
| 103 if (m == m_sliceableModel) { | |
| 104 setSliceableModel(nullptr); | |
| 105 } | 90 } | 
| 106 } | 91 } | 
| 107 | 92 | 
| 108 QString | 93 QString | 
| 109 SliceLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &p) const | 94 SliceLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &p) const | 
| 117 bool includeBinDescription, | 102 bool includeBinDescription, | 
| 118 int &minbin, int &maxbin, int &range) const | 103 int &minbin, int &maxbin, int &range) const | 
| 119 { | 104 { | 
| 120 minbin = 0; | 105 minbin = 0; | 
| 121 maxbin = 0; | 106 maxbin = 0; | 
| 122 if (!m_sliceableModel) return ""; | 107 | 
| 108 auto sliceableModel = | |
| 109 ModelById::getAs<DenseThreeDimensionalModel>(m_sliceableModel); | |
| 110 if (!sliceableModel) return ""; | |
| 123 | 111 | 
| 124 if (m_binAlignment == BinsSpanScalePoints) { | 112 if (m_binAlignment == BinsSpanScalePoints) { | 
| 125 minbin = int(getBinForX(v, p.x())); | 113 minbin = int(getBinForX(v, p.x())); | 
| 126 maxbin = int(getBinForX(v, p.x() + 1)); | 114 maxbin = int(getBinForX(v, p.x() + 1)); | 
| 127 } else { | 115 } else { | 
| 128 minbin = int(getBinForX(v, p.x()) + 0.5); | 116 minbin = int(getBinForX(v, p.x()) + 0.5); | 
| 129 maxbin = int(getBinForX(v, p.x() + 1) + 0.5); | 117 maxbin = int(getBinForX(v, p.x() + 1) + 0.5); | 
| 130 } | 118 } | 
| 131 | 119 | 
| 132 int mh = m_sliceableModel->getHeight(); | 120 int mh = sliceableModel->getHeight(); | 
| 133 if (minbin >= mh) minbin = mh - 1; | 121 if (minbin >= mh) minbin = mh - 1; | 
| 134 if (maxbin >= mh) maxbin = mh - 1; | 122 if (maxbin >= mh) maxbin = mh - 1; | 
| 135 if (minbin < 0) minbin = 0; | 123 if (minbin < 0) minbin = 0; | 
| 136 if (maxbin < 0) maxbin = 0; | 124 if (maxbin < 0) maxbin = 0; | 
| 137 | 125 | 
| 138 sv_samplerate_t sampleRate = m_sliceableModel->getSampleRate(); | 126 sv_samplerate_t sampleRate = sliceableModel->getSampleRate(); | 
| 139 | 127 | 
| 140 sv_frame_t f0 = m_currentf0; | 128 sv_frame_t f0 = m_currentf0; | 
| 141 sv_frame_t f1 = m_currentf1; | 129 sv_frame_t f1 = m_currentf1; | 
| 142 | 130 | 
| 143 RealTime rt0 = RealTime::frame2RealTime(f0, sampleRate); | 131 RealTime rt0 = RealTime::frame2RealTime(f0, sampleRate); | 
| 418 } | 406 } | 
| 419 | 407 | 
| 420 void | 408 void | 
| 421 SliceLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const | 409 SliceLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const | 
| 422 { | 410 { | 
| 423 if (!m_sliceableModel || | 411 auto sliceableModel = | 
| 424 !m_sliceableModel->isOK() || | 412 ModelById::getAs<DenseThreeDimensionalModel>(m_sliceableModel); | 
| 425 !m_sliceableModel->isReady()) return; | 413 if (!sliceableModel || | 
| 414 !sliceableModel->isOK() || | |
| 415 !sliceableModel->isReady()) return; | |
| 426 | 416 | 
| 427 Profiler profiler("SliceLayer::paint()"); | 417 Profiler profiler("SliceLayer::paint()"); | 
| 428 | 418 | 
| 429 paint.save(); | 419 paint.save(); | 
| 430 paint.setRenderHint(QPainter::Antialiasing, true); | 420 paint.setRenderHint(QPainter::Antialiasing, true); | 
| 440 rect.width(), m_scalePoints[i] * ratio); | 430 rect.width(), m_scalePoints[i] * ratio); | 
| 441 } | 431 } | 
| 442 } | 432 } | 
| 443 } | 433 } | 
| 444 | 434 | 
| 445 int mh = m_sliceableModel->getHeight(); | 435 int mh = sliceableModel->getHeight(); | 
| 446 int bin0 = 0; | 436 int bin0 = 0; | 
| 447 if (m_maxbin > m_minbin) { | 437 if (m_maxbin > m_minbin) { | 
| 448 mh = m_maxbin - m_minbin; | 438 mh = m_maxbin - m_minbin; | 
| 449 bin0 = m_minbin; | 439 bin0 = m_minbin; | 
| 450 } | 440 } | 
| 491 sv_frame_t f1 = v->getFrameForX(f0x + 1); | 481 sv_frame_t f1 = v->getFrameForX(f0x + 1); | 
| 492 if (f1 > f0) --f1; | 482 if (f1 > f0) --f1; | 
| 493 | 483 | 
| 494 // cerr << "centre frame " << v->getCentreFrame() << ", x " << f0x << ", f0 " << f0 << ", f1 " << f1 << endl; | 484 // cerr << "centre frame " << v->getCentreFrame() << ", x " << f0x << ", f0 " << f0 << ", f1 " << f1 << endl; | 
| 495 | 485 | 
| 496 int res = m_sliceableModel->getResolution(); | 486 int res = sliceableModel->getResolution(); | 
| 497 int col0 = int(f0 / res); | 487 int col0 = int(f0 / res); | 
| 498 int col1 = col0; | 488 int col1 = col0; | 
| 499 if (m_samplingMode != NearestSample) col1 = int(f1 / res); | 489 if (m_samplingMode != NearestSample) col1 = int(f1 / res); | 
| 500 f0 = col0 * res; | 490 f0 = col0 * res; | 
| 501 f1 = (col1 + 1) * res - 1; | 491 f1 = (col1 + 1) * res - 1; | 
| 510 getBiasCurve(curve); | 500 getBiasCurve(curve); | 
| 511 int cs = int(curve.size()); | 501 int cs = int(curve.size()); | 
| 512 | 502 | 
| 513 for (int col = col0; col <= col1; ++col) { | 503 for (int col = col0; col <= col1; ++col) { | 
| 514 DenseThreeDimensionalModel::Column column = | 504 DenseThreeDimensionalModel::Column column = | 
| 515 m_sliceableModel->getColumn(col); | 505 sliceableModel->getColumn(col); | 
| 516 for (int bin = 0; bin < mh; ++bin) { | 506 for (int bin = 0; bin < mh; ++bin) { | 
| 517 float value = column[bin0 + bin]; | 507 float value = column[bin0 + bin]; | 
| 518 if (bin < cs) value *= curve[bin]; | 508 if (bin < cs) value *= curve[bin]; | 
| 519 if (m_samplingMode == SamplePeak) { | 509 if (m_samplingMode == SamplePeak) { | 
| 520 if (value > m_values[bin]) m_values[bin] = value; | 510 if (value > m_values[bin]) m_values[bin] = value; | 
| 672 } | 662 } | 
| 673 | 663 | 
| 674 int | 664 int | 
| 675 SliceLayer::getVerticalScaleWidth(LayerGeometryProvider *, bool, QPainter &paint) const | 665 SliceLayer::getVerticalScaleWidth(LayerGeometryProvider *, bool, QPainter &paint) const | 
| 676 { | 666 { | 
| 667 // Qt 5.13 deprecates QFontMetrics::width(), but its suggested | |
| 668 // replacement (horizontalAdvance) was only added in Qt 5.11 | |
| 669 // which is too new for us | |
| 670 #pragma GCC diagnostic ignored "-Wdeprecated-declarations" | |
| 671 | |
| 677 int width; | 672 int width; | 
| 678 if (m_energyScale == LinearScale || m_energyScale == AbsoluteScale) { | 673 if (m_energyScale == LinearScale || m_energyScale == AbsoluteScale) { | 
| 679 width = std::max(paint.fontMetrics().width("0.0") + 13, | 674 width = std::max(paint.fontMetrics().width("0.0") + 13, | 
| 680 paint.fontMetrics().width("x10-10")); | 675 paint.fontMetrics().width("x10-10")); | 
| 681 } else { | 676 } else { | 
| 1164 | 1159 | 
| 1165 bool | 1160 bool | 
| 1166 SliceLayer::getValueExtents(double &min, double &max, bool &logarithmic, | 1161 SliceLayer::getValueExtents(double &min, double &max, bool &logarithmic, | 
| 1167 QString &unit) const | 1162 QString &unit) const | 
| 1168 { | 1163 { | 
| 1169 if (!m_sliceableModel) return false; | 1164 auto sliceableModel = | 
| 1165 ModelById::getAs<DenseThreeDimensionalModel>(m_sliceableModel); | |
| 1166 if (!sliceableModel) return false; | |
| 1170 | 1167 | 
| 1171 min = 0; | 1168 min = 0; | 
| 1172 max = double(m_sliceableModel->getHeight()); | 1169 max = double(sliceableModel->getHeight()); | 
| 1173 | 1170 | 
| 1174 logarithmic = (m_binScale == BinScale::LogBins); | 1171 logarithmic = (m_binScale == BinScale::LogBins); | 
| 1175 unit = ""; | 1172 unit = ""; | 
| 1176 | 1173 | 
| 1177 return true; | 1174 return true; | 
| 1178 } | 1175 } | 
| 1179 | 1176 | 
| 1180 bool | 1177 bool | 
| 1181 SliceLayer::getDisplayExtents(double &min, double &max) const | 1178 SliceLayer::getDisplayExtents(double &min, double &max) const | 
| 1182 { | 1179 { | 
| 1183 if (!m_sliceableModel) return false; | 1180 auto sliceableModel = | 
| 1184 | 1181 ModelById::getAs<DenseThreeDimensionalModel>(m_sliceableModel); | 
| 1185 double hmax = double(m_sliceableModel->getHeight()); | 1182 if (!sliceableModel) return false; | 
| 1183 | |
| 1184 double hmax = double(sliceableModel->getHeight()); | |
| 1186 | 1185 | 
| 1187 min = m_minbin; | 1186 min = m_minbin; | 
| 1188 max = m_maxbin; | 1187 max = m_maxbin; | 
| 1189 if (max <= min) { | 1188 if (max <= min) { | 
| 1190 min = 0; | 1189 min = 0; | 
| 1197 } | 1196 } | 
| 1198 | 1197 | 
| 1199 bool | 1198 bool | 
| 1200 SliceLayer::setDisplayExtents(double min, double max) | 1199 SliceLayer::setDisplayExtents(double min, double max) | 
| 1201 { | 1200 { | 
| 1202 if (!m_sliceableModel) return false; | 1201 auto sliceableModel = | 
| 1202 ModelById::getAs<DenseThreeDimensionalModel>(m_sliceableModel); | |
| 1203 if (!sliceableModel) return false; | |
| 1203 | 1204 | 
| 1204 m_minbin = int(lrint(min)); | 1205 m_minbin = int(lrint(min)); | 
| 1205 m_maxbin = int(lrint(max)); | 1206 m_maxbin = int(lrint(max)); | 
| 1206 | 1207 | 
| 1207 if (m_minbin < 0) { | 1208 if (m_minbin < 0) { | 
| 1208 m_minbin = 0; | 1209 m_minbin = 0; | 
| 1209 } | 1210 } | 
| 1210 if (m_maxbin < 0) { | 1211 if (m_maxbin < 0) { | 
| 1211 m_maxbin = 0; | 1212 m_maxbin = 0; | 
| 1212 } | 1213 } | 
| 1213 if (m_minbin > m_sliceableModel->getHeight()) { | 1214 if (m_minbin > sliceableModel->getHeight()) { | 
| 1214 m_minbin = m_sliceableModel->getHeight(); | 1215 m_minbin = sliceableModel->getHeight(); | 
| 1215 } | 1216 } | 
| 1216 if (m_maxbin > m_sliceableModel->getHeight()) { | 1217 if (m_maxbin > sliceableModel->getHeight()) { | 
| 1217 m_maxbin = m_sliceableModel->getHeight(); | 1218 m_maxbin = sliceableModel->getHeight(); | 
| 1218 } | 1219 } | 
| 1219 if (m_maxbin < m_minbin) { | 1220 if (m_maxbin < m_minbin) { | 
| 1220 m_maxbin = m_minbin; | 1221 m_maxbin = m_minbin; | 
| 1221 } | 1222 } | 
| 1222 | 1223 | 
| 1225 } | 1226 } | 
| 1226 | 1227 | 
| 1227 int | 1228 int | 
| 1228 SliceLayer::getVerticalZoomSteps(int &defaultStep) const | 1229 SliceLayer::getVerticalZoomSteps(int &defaultStep) const | 
| 1229 { | 1230 { | 
| 1230 if (!m_sliceableModel) return 0; | 1231 auto sliceableModel = | 
| 1232 ModelById::getAs<DenseThreeDimensionalModel>(m_sliceableModel); | |
| 1233 if (!sliceableModel) return 0; | |
| 1231 | 1234 | 
| 1232 defaultStep = 0; | 1235 defaultStep = 0; | 
| 1233 int h = m_sliceableModel->getHeight(); | 1236 int h = sliceableModel->getHeight(); | 
| 1234 return h; | 1237 return h; | 
| 1235 } | 1238 } | 
| 1236 | 1239 | 
| 1237 int | 1240 int | 
| 1238 SliceLayer::getCurrentVerticalZoomStep() const | 1241 SliceLayer::getCurrentVerticalZoomStep() const | 
| 1239 { | 1242 { | 
| 1240 if (!m_sliceableModel) return 0; | 1243 auto sliceableModel = | 
| 1244 ModelById::getAs<DenseThreeDimensionalModel>(m_sliceableModel); | |
| 1245 if (!sliceableModel) return 0; | |
| 1241 | 1246 | 
| 1242 double min, max; | 1247 double min, max; | 
| 1243 getDisplayExtents(min, max); | 1248 getDisplayExtents(min, max); | 
| 1244 return m_sliceableModel->getHeight() - int(lrint(max - min)); | 1249 return sliceableModel->getHeight() - int(lrint(max - min)); | 
| 1245 } | 1250 } | 
| 1246 | 1251 | 
| 1247 void | 1252 void | 
| 1248 SliceLayer::setVerticalZoomStep(int step) | 1253 SliceLayer::setVerticalZoomStep(int step) | 
| 1249 { | 1254 { | 
| 1250 if (!m_sliceableModel) return; | 1255 auto sliceableModel = | 
| 1256 ModelById::getAs<DenseThreeDimensionalModel>(m_sliceableModel); | |
| 1257 if (!sliceableModel) return; | |
| 1251 | 1258 | 
| 1252 // SVDEBUG << "SliceLayer::setVerticalZoomStep(" <<step <<"): before: minbin = " << m_minbin << ", maxbin = " << m_maxbin << endl; | 1259 // SVDEBUG << "SliceLayer::setVerticalZoomStep(" <<step <<"): before: minbin = " << m_minbin << ", maxbin = " << m_maxbin << endl; | 
| 1253 | 1260 | 
| 1254 int dist = m_sliceableModel->getHeight() - step; | 1261 int dist = sliceableModel->getHeight() - step; | 
| 1255 if (dist < 1) dist = 1; | 1262 if (dist < 1) dist = 1; | 
| 1256 double centre = m_minbin + (m_maxbin - m_minbin) / 2.0; | 1263 double centre = m_minbin + (m_maxbin - m_minbin) / 2.0; | 
| 1257 int minbin = int(lrint(centre - dist/2.0)); | 1264 int minbin = int(lrint(centre - dist/2.0)); | 
| 1258 int maxbin = minbin + dist; | 1265 int maxbin = minbin + dist; | 
| 1259 setDisplayExtents(minbin, maxbin); | 1266 setDisplayExtents(minbin, maxbin); | 
| 1260 } | 1267 } | 
| 1261 | 1268 | 
| 1262 RangeMapper * | 1269 RangeMapper * | 
| 1263 SliceLayer::getNewVerticalZoomRangeMapper() const | 1270 SliceLayer::getNewVerticalZoomRangeMapper() const | 
| 1264 { | 1271 { | 
| 1265 if (!m_sliceableModel) return nullptr; | 1272 auto sliceableModel = | 
| 1266 | 1273 ModelById::getAs<DenseThreeDimensionalModel>(m_sliceableModel); | 
| 1267 return new LinearRangeMapper(0, m_sliceableModel->getHeight(), | 1274 if (!sliceableModel) return nullptr; | 
| 1268 0, m_sliceableModel->getHeight(), ""); | 1275 | 
| 1276 return new LinearRangeMapper(0, sliceableModel->getHeight(), | |
| 1277 0, sliceableModel->getHeight(), ""); | |
| 1269 } | 1278 } | 
| 1270 | 1279 | 
| 1271 void | 1280 void | 
| 1272 SliceLayer::zoomToRegion(const LayerGeometryProvider *v, QRect rect) | 1281 SliceLayer::zoomToRegion(const LayerGeometryProvider *v, QRect rect) | 
| 1273 { | 1282 { | 
