Warning: session_start(): open(/var/lib/php/sessions/sess_ne94vs8u93eq3hf3j8pp6f9hkb, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning: session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
srecord noeq G22_RegionToSSIs_v2(IImageRegion region) extends Meta {
RGB color;
L ssis;
new L growingSSIs;
settable bool withDiagonals;
settable bool checkCoherence = true;
settable bool checkStreaks = true;
private int x1, y;
class GrowingSSI {
settable int y1;
new ShortBuffer data;
int y2() { ret y1+l(data)/2; }
SSI finish() {
ret addAndReturn(ssis, new SSI(y1, y2()).data(data.toArray())
.color(color));
}
bool isEmpty() { ret data.isEmpty(); }
int lastx1() { ret data.get(l(data)-2); }
int lastx2() { ret data.get(l(data)-1); }
IntRange lastRange() { ret isEmpty() ? null : intRange(lastx1(), lastx2()); }
void add(int x1, int x2) {
if (checkCoherence() && !isEmpty()
&& !intRangesOverlap(x1, x2, lastx1()-diag(), lastx2()+diag()))
fail("Coherence fail", +lastx1(), +lastx2(), +x1, +x2);
data.add(toShort_enforce(x1));
data.add(toShort_enforce(x2));
}
}
void finishSSI(int iSSI) {
growingSSIs.remove(iSSI).finish();
}
private GrowingSSI startSSI(int iSSI default l(growingSSIs), IntRange range) {
if (scaffoldingEnabled()) printVars("startSSI", +iSSI, +range);
var ssi = new GrowingSSI().y1(y);
ssi.add(range.start, range.end);
ret addAndReturn(growingSSIs, iSSI, ssi);
}
L lastStreaks() {
ret reallyLazyMap(growingSSIs, -> .lastRange());
}
int diag() { ret withDiagonals ? 1 : 0; }
L get() {
if (region == null) null;
color = region.color();
ssis = new L;
Rect r = region.bounds();
int x1 = this.x1 = r.x1(), y1 = r.y1(), y2 = r.y2(), h = y2-y1, w = r.w;
bool scaff = scaffoldingEnabled();
for (y = y1; y < y2; y++) {
reMutable y;
L streaks = shiftIntRanges(x1, genericStreaks(w, x -> region.contains(x1+x, y)));
var lastStreaks = lastStreaks();
if (checkStreaks())
assertProperStreaks(lastStreaks);
// advance iSSI & iStreak simultaneously
int iStreak = 0, iSSI = 0;
int nStreaks = l(streaks);
if (scaff) printVars(+y, +lastStreaks, +streaks);
while ping (iStreak < nStreaks) {
var range = streaks.get(iStreak);
var ssi = _get(growingSSIs, iSSI);
if (scaff) printVars(+y, +iStreak, +iSSI, +range, ssi := ssi?.lastRange());
// case 1:
// ------
// -------
//
// case 2:
//
// -------
// (left of current SSI or to the right of everything)
if (ssi == null || range.end <= ssi.lastx1()-diag()) {
startSSI(iSSI++, range);
++iStreak;
continue;
}
// Now we know that we have another SSI.
// case 3:
// -------
// ------
// (Just end current SSI and do streak again.)
if (range.start >= ssi.lastx2()+diag()) {
finishSSI(iSSI);
continue;
}
// Find the rightmost streak still under the current SSI
int jStreak = iStreak+1;
while (jStreak < nStreaks && streaks.get(jStreak).start < ssi.lastx2()+diag())
++jStreak;
range = streaks.get(jStreak-1);
// Check if we have to merge with right neighbor(s)
int jSSI = iSSI+1;
while (jSSI < l(growingSSIs)
&& range.end > growingSSIs.get(jSSI).lastx1()-diag())
++jSSI;
int nSSI = jSSI-iSSI, nStreak = jStreak-iStreak;
if (scaff) printVars(+jStreak, +jSSI, +nSSI, +nStreak, +nStreaks, nSSIs := l(growingSSIs));
if (scaff) printVars(+nSSI, +nStreak);
// Now we go from [iSSI;jSSI) to [iStreak;jStreak)
// The only case without structural changes is when
// nSSI = nStreak = 1. Then we just add the line.
if (nSSI == 1 && nStreak == 1) {
ssi.add(range.start, range.end);
iSSI = jSSI; iStreak = jStreak; continue;
}
// If 2 -> 2, we can just assign them one-to-one I think
if (nSSI == 2 && nStreak == 2) {
if (scaff) printVars("2->2", ssis := subList(lastStreaks(), iSSI, jSSI),
streaks := subList(streaks, iStreak, jStreak));
while (iSSI < jSSI) {
range = streaks.get(iStreak++);
growingSSIs.get(iSSI++).add(range.start, range.end);
}
continue;
}
if (nSSI > 1 && nStreak > 1)
printVars("ANOMALY", +nSSI, +nStreak,
ssis := subList(lastStreaks(), iSSI, jSSI),
streaks := subList(streaks, iStreak, jStreak));
// Any kind of structural change means end all involved
// SSIs and start new ones.
while (jSSI-- > iSSI)
finishSSI(iSSI);
while (iStreak < jStreak)
startSSI(iSSI++, streaks.get(iStreak++));
}
// end SSIs to the right of all streaks
while (iSSI < l(growingSSIs))
finishSSI(iSSI);
}
for (ssi : cloneAndClear(growingSSIs)) ssi.finish();
ret ssis;
}
}