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 { |