-
Notifications
You must be signed in to change notification settings - Fork 21
/
romalignerreliable.cpp
123 lines (105 loc) · 3.46 KB
/
romalignerreliable.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include "romalignerreliable.h"
#include "maskromtool.h"
/* These simple sorting functions were much more compliated
* in lesser algorithms. It's nice to have them be simple again.
*/
static bool leftOf(RomBitItem * left, RomBitItem * right){
return (left->x() < right->x());
}
static bool above(RomBitItem * top, RomBitItem * bottom){
return (top->y() < bottom->y());
}
RomAlignerReliable::RomAlignerReliable() {
name="RomAlignerReliable";
}
RomBitItem* RomAlignerReliable::markBitTable(MaskRomTool* mrt){
QList<RomBitItem *> bits=mrt->bits;
//First we remove all the old bit marks and pointers.
foreach (RomBitItem* bit, bits){
//Clear the markup details.
bit->marked=false; //Not used by this aligner.
bit->nextrow=0;
bit->nexttoright=0;
bit->lastinrow=0; //Speeds up linked list usage.
bit->row=-1;
bit->col=-1;
}
rowstarts.clear();
leftsorted.clear();
// We'll need presorted collections by X and Y.
for(RomBitItem *bit: bits){
leftsorted<<bit;
}
//We read each row from the left. Presorting doesn't help determinism.
std::sort(leftsorted.begin(), leftsorted.end(), leftOf);
//Each bit is either its own row or the next in an existing row.
for(RomBitItem *bit: leftsorted){
RomBitItem* nearest=nearestBit(bit);
if(!nearest){ //First bit is its own row.
rowstarts<<bit;
}else{
qreal dx=qFabs(nearest->x()-bit->x());
qreal dy=qFabs(nearest->y()-bit->y());
if(dx<dy){ //New row because Y distance is greater.
rowstarts<<bit;
}else{ //Existing row because X distance is greater.
nearest->nexttoright=bit;
}
}
}
return linkresults();
}
//Nearest bit from existing rows.
RomBitItem* RomAlignerReliable::nearestBit(RomBitItem *item){
/* This returns the best match, but it does not guarantee that it
* is a good match. If the best match is further in Y than in
* X, you should start a new row.
*/
RomBitItem* nearest=0;
qreal nearestdy=1000.0;
for(RomBitItem* bit: rowstarts){
/* Rather than chase the entire linked list, we try to keep the frist
* bit of each row pointing to either the end or some item near the end.
* This drops one test case from 1m24s to 6s.
*/
RomBitItem* startbit=bit;
if(bit->lastinrow)
bit=bit->lastinrow;
while(bit->nexttoright) bit=bit->nexttoright;
startbit->lastinrow=bit;
qreal dy=qFabs(item->y()-bit->y());
if(dy<nearestdy){
nearestdy=dy;
nearest=bit;
}
}
return nearest;
}
//This updates the linked lists that MRT uses internally.
RomBitItem* RomAlignerReliable::linkresults(){
//Having assembled rows, we now need to sort them and return the top left.
std::sort(rowstarts.begin(), rowstarts.end(), above);
//Apply the linked list.
RomBitItem* lastbit=0;
for(RomBitItem *bit: rowstarts){
if(lastbit)
lastbit->nextrow=bit;
lastbit=bit;
}
//Number the bits by row and column.
int expectedcols=0;
int row=0;
for(RomBitItem* bit: rowstarts){
int col=0;
while(bit){
bit->col=col;
bit->row=row;
bit=bit->nexttoright;
col++;
}
row++;
}
if(row)
return rowstarts[0];
return 0;
}