comparison view/AlignmentView.cpp @ 1615:911330a28a7c

Where the "below" view represents only a subset of the "above" view, cut off the feature mappings at the outer edges of the "below" view - don't map everything outside this (it would all just map onto the same single points at beginning and end, which is excessive, confusing and not useful)
author Chris Cannam
date Thu, 02 Jul 2020 15:37:43 +0100
parents 8145a9c4c253
children 36634b427d61
comparison
equal deleted inserted replaced
1614:c6f5c822b10d 1615:911330a28a7c
27 using std::set; 27 using std::set;
28 28
29 AlignmentView::AlignmentView(QWidget *w) : 29 AlignmentView::AlignmentView(QWidget *w) :
30 View(w, false), 30 View(w, false),
31 m_above(nullptr), 31 m_above(nullptr),
32 m_below(nullptr) 32 m_below(nullptr),
33 m_reference(nullptr),
34 m_leftmostAbove(-1),
35 m_rightmostAbove(-1)
33 { 36 {
34 setObjectName(tr("AlignmentView")); 37 setObjectName(tr("AlignmentView"));
35 } 38 }
36 39
37 void 40 void
39 { 42 {
40 #ifdef DEBUG_ALIGNMENT_VIEW 43 #ifdef DEBUG_ALIGNMENT_VIEW
41 SVCERR << "AlignmentView " << getId() << "::keyFramesChanged" << endl; 44 SVCERR << "AlignmentView " << getId() << "::keyFramesChanged" << endl;
42 #endif 45 #endif
43 46
44 // This is just a notification that we need to rebuild it - so all 47 // This is just a notification that we need to rebuild - so all we
45 // we do here is clear it, and it'll be rebuilt on demand later 48 // do here is clear, and rebuild on demand later
46 QMutexLocker locker(&m_keyFrameMutex); 49 QMutexLocker locker(&m_mapsMutex);
47 m_keyFrameMap.clear(); 50 m_fromAboveMap.clear();
51 m_fromReferenceMap.clear();
48 } 52 }
49 53
50 void 54 void
51 AlignmentView::globalCentreFrameChanged(sv_frame_t f) 55 AlignmentView::globalCentreFrameChanged(sv_frame_t f)
52 { 56 {
84 { 88 {
85 update(); 89 update();
86 } 90 }
87 91
88 void 92 void
89 AlignmentView::setViewAbove(View *v) 93 AlignmentView::setAboveView(View *v)
90 { 94 {
91 if (m_above) { 95 if (m_above) {
92 disconnect(m_above, nullptr, this, nullptr); 96 disconnect(m_above, nullptr, this, nullptr);
93 } 97 }
94 98
111 115
112 keyFramesChanged(); 116 keyFramesChanged();
113 } 117 }
114 118
115 void 119 void
116 AlignmentView::setViewBelow(View *v) 120 AlignmentView::setBelowView(View *v)
117 { 121 {
118 if (m_below) { 122 if (m_below) {
119 disconnect(m_below, nullptr, this, nullptr); 123 disconnect(m_below, nullptr, this, nullptr);
120 } 124 }
121 125
138 142
139 keyFramesChanged(); 143 keyFramesChanged();
140 } 144 }
141 145
142 void 146 void
147 AlignmentView::setReferenceView(View *view)
148 {
149 m_reference = view;
150 }
151
152 void
143 AlignmentView::paintEvent(QPaintEvent *) 153 AlignmentView::paintEvent(QPaintEvent *)
144 { 154 {
145 if (m_above == nullptr || m_below == nullptr || !m_manager) return; 155 if (m_above == nullptr || m_below == nullptr || !m_manager) return;
146 156
147 #ifdef DEBUG_ALIGNMENT_VIEW 157 #ifdef DEBUG_ALIGNMENT_VIEW
165 paint.setBrush(Qt::NoBrush); 175 paint.setBrush(Qt::NoBrush);
166 paint.setRenderHint(QPainter::Antialiasing, true); 176 paint.setRenderHint(QPainter::Antialiasing, true);
167 177
168 paint.fillRect(rect(), bg); 178 paint.fillRect(rect(), bg);
169 179
170 QMutexLocker locker(&m_keyFrameMutex); 180 QMutexLocker locker(&m_mapsMutex);
171 181
172 if (m_keyFrameMap.empty()) { 182 if (m_fromAboveMap.empty()) {
173 reconnectModels(); 183 reconnectModels();
174 buildKeyFrameMap(); 184 buildMaps();
175 } 185 }
176 186
177 #ifdef DEBUG_ALIGNMENT_VIEW 187 #ifdef DEBUG_ALIGNMENT_VIEW
178 SVCERR << "AlignmentView " << getId() << "::paintEvent: painting " 188 SVCERR << "AlignmentView " << getId() << "::paintEvent: painting "
179 << m_keyFrameMap.size() << " mappings" << endl; 189 << m_fromAboveMap.size() << " mappings" << endl;
180 #endif 190 #endif
181 191
182 for (const auto &km: m_keyFrameMap) { 192 int w = width();
183 193 int h = height();
184 sv_frame_t af = km.first; 194
185 sv_frame_t bf = km.second; 195 if (m_leftmostAbove > 0) {
186 196
187 int ax = m_above->getXForFrame(af); 197 for (const auto &km: m_fromAboveMap) {
188 int bx = m_below->getXForFrame(bf); 198
189 199 sv_frame_t af = km.first;
190 if (ax >= 0 || ax < width() || bx >= 0 || bx < width()) { 200 sv_frame_t bf = km.second;
191 paint.drawLine(ax, 0, bx, height()); 201
202 if (af < m_leftmostAbove || af > m_rightmostAbove) {
203 continue;
204 }
205
206 int ax = m_above->getXForFrame(af);
207 int bx = m_below->getXForFrame(bf);
208
209 if (ax >= 0 || ax < w || bx >= 0 || bx < w) {
210 paint.drawLine(ax, 0, bx, h);
211 }
212 }
213 } else if (m_reference != nullptr) {
214 // the below has nothing in common with the above: show things
215 // in common with the reference instead
216
217 for (const auto &km: m_fromReferenceMap) {
218
219 sv_frame_t af = km.first;
220 sv_frame_t bf = km.second;
221
222 int ax = m_reference->getXForFrame(af);
223 int bx = m_below->getXForFrame(bf);
224
225 if (ax >= 0 || ax < w || bx >= 0 || bx < w) {
226 paint.drawLine(ax, 0, bx, h);
227 }
192 } 228 }
193 } 229 }
194 230
195 paint.end(); 231 paint.end();
196 } 232 }
225 } 261 }
226 } 262 }
227 } 263 }
228 264
229 void 265 void
230 AlignmentView::buildKeyFrameMap() 266 AlignmentView::buildMaps()
231 { 267 {
232 #ifdef DEBUG_ALIGNMENT_VIEW 268 #ifdef DEBUG_ALIGNMENT_VIEW
233 SVCERR << "AlignmentView " << getId() << "::buildKeyFrameMap" << endl; 269 SVCERR << "AlignmentView " << getId() << "::buildMaps" << endl;
234 #endif 270 #endif
235 271
236 sv_frame_t resolution = 1; 272 sv_frame_t resolution = 1;
237 273
238 set<sv_frame_t> keyFramesBelow; 274 set<sv_frame_t> keyFramesBelow;
239 for (auto f: getKeyFrames(m_below, resolution)) { 275 for (auto f: getKeyFrames(m_below, resolution)) {
240 keyFramesBelow.insert(f); 276 keyFramesBelow.insert(f);
241 } 277 }
242 278
279 foreach(sv_frame_t f, keyFramesBelow) {
280 sv_frame_t rf = m_below->alignToReference(f);
281 m_fromReferenceMap.insert({ rf, f });
282 }
283
243 vector<sv_frame_t> keyFrames = getKeyFrames(m_above, resolution); 284 vector<sv_frame_t> keyFrames = getKeyFrames(m_above, resolution);
244 285
286 // These are the most extreme leftward and rightward frames in
287 // "above" that have distinct corresponding frames in
288 // "below". Anything left of m_leftmostAbove or right of
289 // m_rightmostAbove maps effectively off one end or the other of
290 // the below view. (They don't actually map off the ends, they
291 // just all map to the same first/last destination frame. But we
292 // don't want to display their mappings, as they're just noise.)
293 m_leftmostAbove = -1;
294 m_rightmostAbove = -1;
295
296 sv_frame_t prevRf = -1;
297 sv_frame_t prevBf = -1;
298
245 foreach (sv_frame_t f, keyFrames) { 299 foreach (sv_frame_t f, keyFrames) {
246 300
247 sv_frame_t rf = m_above->alignToReference(f); 301 sv_frame_t rf = m_above->alignToReference(f);
248 sv_frame_t bf = m_below->alignFromReference(rf); 302 sv_frame_t bf = m_below->alignFromReference(rf);
249 303
304 if (prevBf > 0 && bf > prevBf) {
305 if (m_leftmostAbove < 0 && prevBf > 0 && bf > prevBf) {
306 m_leftmostAbove = prevRf;
307 }
308 m_rightmostAbove = rf;
309 }
310 prevRf = rf;
311 prevBf = bf;
312
250 bool mappedSomething = false; 313 bool mappedSomething = false;
251 314
252 if (resolution > 1) { 315 if (resolution > 1) {
253 if (keyFramesBelow.find(bf) == keyFramesBelow.end()) { 316 if (keyFramesBelow.find(bf) == keyFramesBelow.end()) {
254 317
256 sv_frame_t rf1 = m_above->alignToReference(f1); 319 sv_frame_t rf1 = m_above->alignToReference(f1);
257 sv_frame_t bf1 = m_below->alignFromReference(rf1); 320 sv_frame_t bf1 = m_below->alignFromReference(rf1);
258 321
259 for (sv_frame_t probe = bf + 1; probe <= bf1; ++probe) { 322 for (sv_frame_t probe = bf + 1; probe <= bf1; ++probe) {
260 if (keyFramesBelow.find(probe) != keyFramesBelow.end()) { 323 if (keyFramesBelow.find(probe) != keyFramesBelow.end()) {
261 m_keyFrameMap.insert({ f, probe }); 324 m_fromAboveMap.insert({ f, probe });
262 mappedSomething = true; 325 mappedSomething = true;
263 } 326 }
264 } 327 }
265 } 328 }
266 } 329 }
267 330
268 if (!mappedSomething) { 331 if (!mappedSomething) {
269 m_keyFrameMap.insert({ f, bf }); 332 m_fromAboveMap.insert({ f, bf });
270 } 333 }
271 } 334 }
272 335
273 #ifdef DEBUG_ALIGNMENT_VIEW 336 #ifdef DEBUG_ALIGNMENT_VIEW
274 SVCERR << "AlignmentView " << getId() << "::buildKeyFrameMap: have " 337 SVCERR << "AlignmentView " << getId() << "::buildMaps: have "
275 << m_keyFrameMap.size() << " mappings" << endl; 338 << m_fromAboveMap.size() << " mappings" << endl;
276 #endif 339 #endif
277 } 340 }
278 341
279 vector<sv_frame_t> 342 vector<sv_frame_t>
280 AlignmentView::getKeyFrames(View *view, sv_frame_t &resolution) 343 AlignmentView::getKeyFrames(View *view, sv_frame_t &resolution)