Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

164
LINES

< > BotCompany Repo | #1035627 // G22_RegionToSSIs_v2 - full conversion with cohesion and fewest SSIs (WORKS)

JavaX fragment (include) [tags: use-pretranspiled]

Transpiled version (12679L) is out of date.

srecord noeq G22_RegionToSSIs_v2(IImageRegion region) extends Meta {
  Color color;
  L<SSI> ssis;
  new L<GrowingSSI> 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()); }
    
    // can add this line without breaking coherence?
    bool canAdd(IntRange r) {
      ret isEmpty()
        || intRangesOverlapNempty(r.start, r.end, lastx1()-diag(), lastx2()+diag());
    }
    
    void add(IntRange r) {
      if (checkCoherence() && !canAdd(r))
        fail("Coherence fail", +lastx1(), +lastx2(), +r);
      
      data.add(toShort_enforce(r.start));
      data.add(toShort_enforce(r.end));
    }
  }
  
  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);
    ret addAndReturn(growingSSIs, iSSI, ssi);
  }
  
  L<IntRange> lastStreaks() {
    ret reallyLazyMap(growingSSIs, -> .lastRange());
  }
  
  int diag() { ret withDiagonals ? 1 : 0; }
  
  L<SSI> 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<IntRange> 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;
        }
        
        // Now we know the streak and the SSI overlap.
        // Find out if we have a choice on the top or on the bottom.
        
        // Check choices for streak
        int jStreak = iStreak+1;
        while (jStreak < nStreaks && ssi.canAdd(streaks.get(jStreak)))
          ++jStreak;

        // Check choices for SSI
        int jSSI = iSSI+1;
        while (jSSI < l(growingSSIs) && growingSSIs.get(jSSI).canAdd(range))
          ++jSSI;
          
        int nSSI = jSSI-iSSI, nStreak = jStreak-iStreak;
        if (scaff) printVars(+nSSI, +nStreak);
        new Best<Int> best;
          
        if (nSSI > 1) {
          if (nStreak > 1)
            fail("ANOMALY", +nSSI, +nStreak,
              ssis := subList(lastStreaks(), iSSI, jSSI),
              streaks := subList(streaks, iStreak, jStreak));  
              
          // Choose longest SSI
          for (int idx = iSSI; idx < jSSI; idx++)
            best.put(idx, l(growingSSIs.get(idx).lastRange()));
          jSSI = best!;
          
          while (jSSI-- > iSSI) finishSSI(iSSI);
        } else if (nStreak > 1) {
          // Choose longest streak
          for (int idx = iStreak; idx < jStreak; idx++)
            best.put(idx, l(streaks.get(idx)));
          jStreak = best!;
          
          while (iStreak < jStreak)
            startSSI(iSSI++, streaks.get(iStreak++));
        }
        
        // add line to SSI
        growingSSIs.get(iSSI++).add(streaks.get(iStreak++));
      }
      
      // remaining SSIs are unpaired, close them
      while (iSSI < l(growingSSIs)) finishSSI(iSSI);
    }
    
    // finish all remaining SSIs
    for (ssi : cloneAndClear(growingSSIs)) ssi.finish();
    
    ret ssis;
  }
}

Author comment

Began life as a copy of #1035608

download  show line numbers  debug dex  old transpilations   

Travelled to 2 computer(s): elmgxqgtpvxh, mqqgnosmbjvj

No comments. add comment

Snippet ID: #1035627
Snippet name: G22_RegionToSSIs_v2 - full conversion with cohesion and fewest SSIs (WORKS)
Eternal ID of this version: #1035627/50
Text MD5: 7e2e563fa358d1a98f42cfc5e090c70a
Author: stefan
Category: javax / gazelle 22
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2022-07-25 10:50:34
Source code size: 5058 bytes / 164 lines
Pitched / IR pitched: No / No
Views / Downloads: 172 / 408
Version history: 49 change(s)
Referenced in: [show references]