comparison src/Finder.cpp @ 75:e1a5f3095ba6 cheap_diagonals

Merge from branch refactors
author Chris Cannam
date Wed, 19 Nov 2014 12:13:28 +0000
parents 7aa1ab3db7c9 7e3c1bc0984a
children eb3392bf6150
comparison
equal deleted inserted replaced
68:7aa1ab3db7c9 75:e1a5f3095ba6
18 18
19 #include "Path.h" 19 #include "Path.h"
20 20
21 #include <algorithm> 21 #include <algorithm>
22 22
23 23 using namespace std;
24 Finder::Finder(Matcher *p1, Matcher *p2) 24
25 { 25 Finder::Finder(Matcher *pm)
26 if (!p1->m_firstPM) 26 {
27 std::cerr << "Warning: wrong args in Finder()" << std::endl; 27 m_m = pm;
28 pm1 = p1; 28 m_duration1 = -1;
29 pm2 = p2; 29 m_duration2 = -1;
30 index1 = 0;
31 index2 = 0;
32 rowRange = new int[2];
33 colRange = new int[2];
34 duration1 = -1;
35 duration2 = -1;
36 } // constructor 30 } // constructor
37 31
38 Finder::~Finder() 32 Finder::~Finder()
39 { 33 {
40 delete[] rowRange;
41 delete[] colRange;
42 } 34 }
43 35
44 void 36 void
45 Finder::setDurations(int d1, int d2) 37 Finder::setDurations(int d1, int d2)
46 { 38 {
47 duration1 = d1; 39 m_duration1 = d1;
48 duration2 = d2; 40 m_duration2 = d2;
49 } 41 }
50
51 bool
52 Finder::find(int i1, int i2)
53 {
54 if (i1 >= 0) {
55 index1 = i1;
56 index2 = i2 - pm1->m_first[i1];
57 }
58 return (i1 >= 0) && (i2 >= pm1->m_first[i1]) && (i2 < pm1->m_last[i1]);
59 } // find()
60
61 void
62 Finder::getColRange(int row, int *range)
63 {
64 range[0] = pm1->m_first[row];
65 range[1] = pm1->m_last[row];
66 } // getColRange()
67
68 void
69 Finder::getRowRange(int col, int *range)
70 {
71 range[0] = pm2->m_first[col];
72 range[1] = pm2->m_last[col];
73 } // getRowRange()
74 42
75 Matcher::Advance 43 Matcher::Advance
76 Finder::getExpandDirection(int row, int col) 44 Finder::getExpandDirection(int row, int col)
77 { 45 {
78 return getExpandDirection(row, col, false); 46 return getExpandDirection(row, col, false);
79 } // getExpandDirection() 47 } // getExpandDirection()
80 48
81 Matcher::Advance 49 Matcher::Advance
82 Finder::getExpandDirection(int row, int col, bool check) 50 Finder::getExpandDirection(int row, int col, bool check)
83 { 51 {
84 double min = getPathCost(row, col); 52 double min = m_m->getPathCost(row, col);
85 bestRow = row; 53
86 bestCol = col; 54 int bestRow = row;
87 getRowRange(col, rowRange); 55 int bestCol = col;
88 if (rowRange[1] > row+1) 56
89 rowRange[1] = row+1; // don't cheat by looking at future :) 57 pair<int, int> rowRange = m_m->getRowRange(col);
90 for (int index = rowRange[0]; index < rowRange[1]; index++) { 58 if (rowRange.second > row+1) {
91 double tmp = getPathCost(index, col); 59 rowRange.second = row+1; // don't cheat by looking at future :)
60 }
61 for (int index = rowRange.first; index < rowRange.second; index++) {
62 double tmp = m_m->getPathCost(index, col);
92 if (tmp < min) { 63 if (tmp < min) {
93 min = tmp; 64 min = tmp;
94 bestRow = index; 65 bestRow = index;
95 } 66 }
96 } 67 }
97 getColRange(row, colRange); 68
98 if (colRange[1] > col+1) 69 pair<int, int> colRange = m_m->getColRange(row);
99 colRange[1] = col+1; // don't cheat by looking at future :) 70 if (colRange.second > col+1) {
100 for (int index = colRange[0]; index < colRange[1]; index++) { 71 colRange.second = col+1; // don't cheat by looking at future :)
101 double tmp = getPathCost(row, index); 72 }
73 for (int index = colRange.first; index < colRange.second; index++) {
74 double tmp = m_m->getPathCost(row, index);
102 if (tmp < min) { 75 if (tmp < min) {
103 min = tmp; 76 min = tmp;
104 bestCol = index; 77 bestCol = index;
105 bestRow = row; 78 bestRow = row;
106 }
107 }
108 // System.err.print(" BEST: " + bestRow + " " + bestCol + " " + check);
109 // System.err.println(" " + pm1->frameCount + " " + pm2->frameCount);
110 if (check) {
111 // System.err.println(find(row+1, col) + " " + find(row, col+1));
112 if (!find(row, col+1)) {
113 return Matcher::AdvanceThis;
114 } else if (!find(row+1, col)) {
115 return Matcher::AdvanceOther;
116 } 79 }
117 } 80 }
118 81
119 if (bestRow == row) { 82 if (bestRow == row) {
120 if (bestCol == col) { 83 if (bestCol == col) {
126 return Matcher::AdvanceOther; 89 return Matcher::AdvanceOther;
127 } else { 90 } else {
128 return Matcher::AdvanceNone; 91 return Matcher::AdvanceNone;
129 } 92 }
130 93
131 } // getExpandDirection() 94 }
132
133 float
134 Finder::getDistance(int row, int col)
135 {
136 if (find(row, col)) {
137 return pm1->m_distance[row][col - pm1->m_first[row]];
138 }
139 std::cerr << "getDistance(" << row << "," << col << "): out of bounds" << std::endl;
140 throw "getDistance index out of bounds";
141 } // getDistance()/2
142
143 void
144 Finder::setDistance(int row, int col, float b)
145 {
146 if (find(row, col)) {
147 pm1->m_distance[row][col - pm1->m_first[row]] = b;
148 return;
149 }
150 std::cerr << "setDistance(" << row << "," << col << "," << b << "): out of bounds" << std::endl;
151 throw "setDistance index out of bounds";
152 } // setDistance()
153
154 double
155 Finder::getPathCost(int row, int col)
156 {
157 if (find(row, col)) // "1" avoids div by 0 below
158 return pm1->m_bestPathCost[row][col - pm1->m_first[row]] / float(1+row+col);
159 std::cerr << "getPathCost(" << row << "," << col << "): out of bounds" << std::endl;
160 throw "getPathCost index out of bounds";
161 } // getPathCost()
162
163 double
164 Finder::getRawPathCost(int row, int col)
165 {
166 if (find(row, col))
167 return pm1->m_bestPathCost[row][col - pm1->m_first[row]];
168 std::cerr << "getRawPathCost(" << row << "," << col << "): out of bounds" << std::endl;
169 throw "getRawPathCost index out of bounds";
170 } // getRawPathCost()
171
172 void
173 Finder::setPathCost(int row, int col, double cost)
174 {
175 if (find(row, col)) {
176 pm1->m_bestPathCost[row][col - pm1->m_first[row]] = cost;
177 return;
178 }
179 std::cerr << "setPathCost(" << row << "," << col << "," << cost << "): out of bounds" << std::endl;
180 throw "setPathCost index out of bounds";
181 } // setPathCost()
182
183 Matcher::Advance
184 Finder::getAdvance()
185 {
186 return pm1->m_advance[index1][index2];
187 }
188
189 void
190 Finder::setAdvance(Matcher::Advance a)
191 {
192 pm1->m_advance[index1][index2] = a;
193 }
194
195 float
196 Finder::getDistance()
197 {
198 return pm1->m_distance[index1][index2];
199 } // getDistance()/0
200
201 void
202 Finder::setDistance(float b)
203 {
204 pm1->m_distance[index1][index2] = b;
205 } // setDistance()
206
207 double
208 Finder::getPathCost()
209 {
210 return pm1->m_bestPathCost[index1][index2];
211 } // getPathCost()
212
213 void
214 Finder::setPathCost(double cost)
215 {
216 pm1->m_bestPathCost[index1][index2] = cost;
217 } // setPathCost()
218 95
219 void 96 void
220 Finder::recalculatePathCostMatrix(int r1, int c1, int r2, int c2) 97 Finder::recalculatePathCostMatrix(int r1, int c1, int r2, int c2)
221 { 98 {
222 float diagonalWeight = sqrtf(2.f); 99 float diagonalWeight = sqrtf(2.f);
223 100
224 if (!find(r1,c1)) {
225 std::cerr << "recalculatePathCostMatrix(" << r1 << "," << c1 << "): out of bounds" << std::endl;
226 throw "recalculatePathCostMatrix index out of bounds";
227 }
228 int thisRowStart, c;
229 int prevRowStart = 0, prevRowStop = 0; 101 int prevRowStart = 0, prevRowStop = 0;
102
230 for (int r = r1; r <= r2; r++) { 103 for (int r = r1; r <= r2; r++) {
231 thisRowStart = pm1->m_first[r]; 104
232 if (thisRowStart < c1) 105 pair<int, int> colRange = m_m->getColRange(r);
233 thisRowStart = c1; 106
234 for (c = thisRowStart; c <= c2; c++) { 107 int rowStart = max(c1, colRange.first);
235 if (find(r,c)) { 108 int rowStop = min(c2 + 1, colRange.second);
236 int i2 = index2; 109
237 float newCost = pm1->m_distance[r][i2]; 110 for (int c = rowStart; c < rowStop; c++) {
238 Matcher::Advance dir = Matcher::AdvanceNone; 111
239 if (r > r1) { // not first row 112 float newCost = m_m->getDistance(r, c);
240 double min = -1; 113 Matcher::Advance dir = Matcher::AdvanceNone;
241 if ((c > prevRowStart) && (c <= prevRowStop)) { 114
242 // diagonal from (r-1,c-1) 115 if (r > r1) { // not first row
243 min = pm1->m_bestPathCost[r-1][c-pm1->m_first[r-1]-1] + 116 double min = -1;
244 newCost * diagonalWeight; 117 if ((c > prevRowStart) && (c <= prevRowStop)) {
245 dir = Matcher::AdvanceBoth; 118 // diagonal from (r-1,c-1)
119 min = m_m->getPathCost(r-1, c-1) + newCost * diagonalWeight;
120 dir = Matcher::AdvanceBoth;
121 }
122 if ((c >= prevRowStart) && (c < prevRowStop)) {
123 // vertical from (r-1,c)
124 double cost = m_m->getPathCost(r-1, c) + newCost;
125 if ((min < 0) || (cost < min)) {
126 min = cost;
127 dir = Matcher::AdvanceThis;
246 } 128 }
247 if ((c >= prevRowStart) && (c < prevRowStop)) { 129 }
248 // vertical from (r-1,c) 130 if (c > rowStart) {
249 double cost = pm1->m_bestPathCost[r-1][c-pm1->m_first[r-1]] + 131 // horizontal from (r,c-1)
250 newCost; 132 double cost = m_m->getPathCost(r, c-1) + newCost;
251 if ((min == -1) || (cost < min)) { 133 if ((min < 0) || (cost < min)) {
252 min = cost; 134 min = cost;
253 dir = Matcher::AdvanceThis; 135 dir = Matcher::AdvanceOther;
254 }
255 } 136 }
256 if (c > thisRowStart) {
257 // horizontal from (r,c-1)
258 double cost =pm1->m_bestPathCost[r][i2-1]+newCost;
259 if ((min == -1) || (cost < min)) {
260 min = cost;
261 dir = Matcher::AdvanceOther;
262 }
263 }
264 pm1->m_bestPathCost[r][i2] = min;
265 } else if (c > thisRowStart) { // first row
266 // horizontal from (r,c-1)
267 pm1->m_bestPathCost[r][i2] = pm1->m_bestPathCost[r][i2-1] +
268 newCost;
269 dir = Matcher::AdvanceOther;
270 } 137 }
271 pm1->m_advance[r][i2] = dir; 138
272 } else 139 m_m->setPathCost(r, c, dir, min);
273 break; // end of row 140
274 } 141 } else if (c > rowStart) { // first row
275 prevRowStart = thisRowStart; 142 // horizontal from (r,c-1)
276 prevRowStop = c; 143 m_m->setPathCost(r, c, Matcher::AdvanceOther,
277 } 144 m_m->getPathCost(r, c-1) + newCost);
278 } // recalculatePathCostMatrix() 145 }
146 }
147
148 prevRowStart = rowStart;
149 prevRowStop = rowStop;
150 }
151 }
279 152
280 int 153 int
281 Finder::retrievePath(bool smooth, vector<int> &pathx, vector<int> &pathy) 154 Finder::retrievePath(bool smooth, vector<int> &pathx, vector<int> &pathy)
282 { 155 {
283 int ex = pm2->getFrameCount() - 1; 156 pathx.clear();
284 int ey = pm1->getFrameCount() - 1; 157 pathy.clear();
158
159 int ex = m_m->getOtherFrameCount() - 1;
160 int ey = m_m->getFrameCount() - 1;
161
162 if (ex < 0 || ey < 0) {
163 return 0;
164 }
285 165
286 int x = ex; 166 int x = ex;
287 int y = ey; 167 int y = ey;
288 168
289 // cerr << "before: x = " << x << ", y = " << y << endl; 169 // cerr << "before: x = " << x << ", y = " << y << endl;
290 170
291 if (duration2 > 0 && duration2 < pm2->getFrameCount()) { 171 if (m_duration2 > 0 && m_duration2 < m_m->getOtherFrameCount()) {
292 x = duration2 - 1; 172 x = m_duration2 - 1;
293 } 173 }
294 if (duration1 > 0 && duration1 < pm1->getFrameCount()) { 174 if (m_duration1 > 0 && m_duration1 < m_m->getFrameCount()) {
295 y = duration1 - 1; 175 y = m_duration1 - 1;
296 } 176 }
297 177
298 if (!find(y, x)) { 178 if (!m_m->isAvailable(y, x)) {
299 // Path did not pass through the expected end point -- 179 // Path did not pass through the expected end point --
300 // probably means the pieces are substantially different in 180 // probably means the pieces are substantially different in
301 // the later bits. Reset the expected end point to the end of 181 // the later bits. Reset the expected end point to the end of
302 // both files including any trailing silence. 182 // both files including any trailing silence.
303 cerr << "NOTE: Path did not pass through expected end point, inputs are probably significantly different" << endl; 183 cerr << "NOTE: Path did not pass through expected end point, inputs are probably significantly different" << endl;
305 y = ey; 185 y = ey;
306 } 186 }
307 187
308 recalculatePathCostMatrix(0, 0, y, x); 188 recalculatePathCostMatrix(0, 0, y, x);
309 189
310 pathx.clear();
311 pathy.clear();
312
313 // cerr << "start: x = " << x << ", y = " << y << endl; 190 // cerr << "start: x = " << x << ", y = " << y << endl;
314 191
315 while (find(y, x) && ((x > 0) || (y > 0))) { 192 while (m_m->isAvailable(y, x) && (x > 0 || y > 0)) {
316 193
317 // cerr << "x = " << x << ", y = " << y; 194 // cerr << "x = " << x << ", y = " << y;
318 195
319 pathx.push_back(x); 196 pathx.push_back(x);
320 pathy.push_back(y); 197 pathy.push_back(y);
321 198
322 switch (getAdvance()) { 199 switch (m_m->getAdvance(y, x)) {
323 case Matcher::AdvanceThis: 200 case Matcher::AdvanceThis:
324 // cerr << ", going down (dist = " << (int)getDistance() << ")" << endl; 201 // cerr << ", going down (dist = " << getDistance() << ")" << endl;
325 y--; 202 y--;
326 break; 203 break;
327 case Matcher::AdvanceOther: 204 case Matcher::AdvanceOther:
328 // cerr << ", going left (dist = " << (int)getDistance() << ")" << endl; 205 // cerr << ", going left (dist = " << getDistance() << ")" << endl;
329 x--; 206 x--;
330 break; 207 break;
331 case Matcher::AdvanceBoth: 208 case Matcher::AdvanceBoth:
332 // cerr << ", going diag (dist = " << (int)getDistance() << ")" << endl; 209 // cerr << ", going diag (dist = " << getDistance() << ")" << endl;
333 x--; 210 x--;
334 y--; 211 y--;
335 break; 212 break;
336 case Matcher::AdvanceNone: // this would indicate a bug, but we wouldn't want to hang 213 case Matcher::AdvanceNone: // this would indicate a bug, but we wouldn't want to hang
337 // cerr << "WARNING: Neither matcher advanced in path backtrack at (" << x << "," << y << ")" << endl; 214 cerr << "WARNING: Neither matcher advanced in path backtrack at (" << x << "," << y << ")" << endl;
338 if (x > y) { 215 if (x > y) {
339 x--; 216 x--;
340 } else { 217 } else {
341 y--; 218 y--;
342 } 219 }
343 break; 220 break;
344 } 221 }
345 } 222 }
346 223
347 std::reverse(pathx.begin(), pathx.end()); 224 if (x > 0 || y > 0) {
348 std::reverse(pathy.begin(), pathy.end()); 225 cerr << "WARNING: Ran out of available path at (" << y << "," << x
226 << ")!" << endl;
227 }
228
229 reverse(pathx.begin(), pathx.end());
230 reverse(pathy.begin(), pathy.end());
349 231
350 if (smooth) { 232 if (smooth) {
351 int smoothedLen = Path().smooth(pathx, pathy, pathx.size()); 233 int smoothedLen = Path().smooth(pathx, pathy, pathx.size());
352 return smoothedLen; 234 return smoothedLen;
353 } else { 235 } else {