1 | srecord noeq G22_RegionToSSIs_v2(IImageRegion region) extends Meta { |
2 | RGB color; |
3 | L<SSI> ssis; |
4 | new L<GrowingSSI> growingSSIs; |
5 | settable bool withDiagonals; |
6 | settable bool checkCoherence = true; |
7 | settable bool checkStreaks = true; |
8 | |
9 | private int x1, y; |
10 | |
11 | class GrowingSSI { |
12 | settable int y1; |
13 | new ShortBuffer data; |
14 | |
15 | int y2() { ret y1+l(data)/2; } |
16 | |
17 | SSI finish() { |
18 | ret addAndReturn(ssis, new SSI(y1, y2()).data(data.toArray()) |
19 | .color(color)); |
20 | } |
21 | |
22 | bool isEmpty() { ret data.isEmpty(); } |
23 | int lastx1() { ret data.get(l(data)-2); } |
24 | int lastx2() { ret data.get(l(data)-1); } |
25 | IntRange lastRange() { ret isEmpty() ? null : intRange(lastx1(), lastx2()); } |
26 | |
27 | void add(int x1, int x2) { |
28 | if (checkCoherence() && !isEmpty() |
29 | && !intRangesOverlap(x1, x2, lastx1()-diag(), lastx2()+diag())) |
30 | fail("Coherence fail", +lastx1(), +lastx2(), +x1, +x2); |
31 | |
32 | data.add(toShort_enforce(x1)); |
33 | data.add(toShort_enforce(x2)); |
34 | } |
35 | } |
36 | |
37 | void finishSSI(int iSSI) { |
38 | growingSSIs.remove(iSSI).finish(); |
39 | } |
40 | |
41 | private GrowingSSI startSSI(int iSSI default l(growingSSIs), IntRange range) { |
42 | if (scaffoldingEnabled()) printVars("startSSI", +iSSI, +range); |
43 | var ssi = new GrowingSSI().y1(y); |
44 | ssi.add(range.start, range.end); |
45 | ret addAndReturn(growingSSIs, iSSI, ssi); |
46 | } |
47 | |
48 | L<IntRange> lastStreaks() { |
49 | ret reallyLazyMap(growingSSIs, -> .lastRange()); |
50 | } |
51 | |
52 | int diag() { ret withDiagonals ? 1 : 0; } |
53 | |
54 | L<SSI> get() { |
55 | if (region == null) null; |
56 | |
57 | color = region.color(); |
58 | ssis = new L; |
59 | Rect r = region.bounds(); |
60 | int x1 = this.x1 = r.x1(), y1 = r.y1(), y2 = r.y2(), h = y2-y1, w = r.w; |
61 | bool scaff = scaffoldingEnabled(); |
62 | |
63 | for (y = y1; y < y2; y++) { |
64 | reMutable y; |
65 | L<IntRange> streaks = shiftIntRanges(x1, genericStreaks(w, x -> region.contains(x1+x, y))); |
66 | |
67 | var lastStreaks = lastStreaks(); |
68 | if (checkStreaks()) |
69 | assertProperStreaks(lastStreaks); |
70 | |
71 | // advance iSSI & iStreak simultaneously |
72 | int iStreak = 0, iSSI = 0; |
73 | int nStreaks = l(streaks); |
74 | |
75 | if (scaff) printVars(+y, +lastStreaks, +streaks); |
76 | |
77 | while ping (iStreak < nStreaks) { |
78 | var range = streaks.get(iStreak); |
79 | var ssi = _get(growingSSIs, iSSI); |
80 | if (scaff) printVars(+y, +iStreak, +iSSI, +range, ssi := ssi?.lastRange()); |
81 | |
82 | // case 1: |
83 | // ------ |
84 | // ------- |
85 | // |
86 | // case 2: |
87 | // |
88 | // ------- |
89 | // (left of current SSI or to the right of everything) |
90 | if (ssi == null || range.end <= ssi.lastx1()-diag()) { |
91 | startSSI(iSSI++, range); |
92 | ++iStreak; |
93 | continue; |
94 | } |
95 | |
96 | // Now we know that we have another SSI. |
97 | |
98 | // case 3: |
99 | // ------- |
100 | // ------ |
101 | // (Just end current SSI and do streak again.) |
102 | if (range.start >= ssi.lastx2()+diag()) { |
103 | finishSSI(iSSI); |
104 | continue; |
105 | } |
106 | |
107 | // Find the rightmost streak still under the current SSI |
108 | int jStreak = iStreak+1; |
109 | while (jStreak < nStreaks && streaks.get(jStreak).start < ssi.lastx2()+diag()) |
110 | ++jStreak; |
111 | range = streaks.get(jStreak-1); |
112 | |
113 | // Check if we have to merge with right neighbor(s) |
114 | int jSSI = iSSI+1; |
115 | while (jSSI < l(growingSSIs) |
116 | && range.end > growingSSIs.get(jSSI).lastx1()-diag()) |
117 | ++jSSI; |
118 | |
119 | int nSSI = jSSI-iSSI, nStreak = jStreak-iStreak; |
120 | if (scaff) printVars(+jStreak, +jSSI, +nSSI, +nStreak, +nStreaks, nSSIs := l(growingSSIs)); |
121 | |
122 | if (scaff) printVars(+nSSI, +nStreak); |
123 | |
124 | // Now we go from [iSSI;jSSI) to [iStreak;jStreak) |
125 | // The only case without structural changes is when |
126 | // nSSI = nStreak = 1. Then we just add the line. |
127 | if (nSSI == 1 && nStreak == 1) { |
128 | ssi.add(range.start, range.end); |
129 | iSSI = jSSI; iStreak = jStreak; continue; |
130 | } |
131 | |
132 | // If 2 -> 2, we can just assign them one-to-one I think |
133 | if (nSSI == 2 && nStreak == 2) { |
134 | if (scaff) printVars("2->2", ssis := subList(lastStreaks(), iSSI, jSSI), |
135 | streaks := subList(streaks, iStreak, jStreak)); |
136 | |
137 | while (iSSI < jSSI) { |
138 | range = streaks.get(iStreak++); |
139 | growingSSIs.get(iSSI++).add(range.start, range.end); |
140 | } |
141 | continue; |
142 | } |
143 | |
144 | if (nSSI > 1 && nStreak > 1) |
145 | printVars("ANOMALY", +nSSI, +nStreak, |
146 | ssis := subList(lastStreaks(), iSSI, jSSI), |
147 | streaks := subList(streaks, iStreak, jStreak)); |
148 | |
149 | // Any kind of structural change means end all involved |
150 | // SSIs and start new ones. |
151 | while (jSSI-- > iSSI) |
152 | finishSSI(iSSI); |
153 | |
154 | while (iStreak < jStreak) |
155 | startSSI(iSSI++, streaks.get(iStreak++)); |
156 | } |
157 | |
158 | // end SSIs to the right of all streaks |
159 | while (iSSI < l(growingSSIs)) |
160 | finishSSI(iSSI); |
161 | } |
162 | |
163 | for (ssi : cloneAndClear(growingSSIs)) ssi.finish(); |
164 | |
165 | ret ssis; |
166 | } |
167 | } |
Began life as a copy of #1035627
download show line numbers debug dex old transpilations
Travelled to 1 computer(s): mqqgnosmbjvj
No comments. add comment
Snippet ID: | #1035639 |
Snippet name: | G22_RegionToSSIs_v2 - full conversion [backup] |
Eternal ID of this version: | #1035639/1 |
Text MD5: | 0cc358c08e2c15a5366370b5fddb3c6c |
Author: | stefan |
Category: | javax / gazelle 22 |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2022-06-27 06:56:21 |
Source code size: | 5375 bytes / 167 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 106 / 117 |
Referenced in: | [show references] |