}
/**
+ * return an iterator over visible segments between the given start and end
+ * boundaries
+ *
+ * @param start
+ * (first column - inclusive from 0)
+ * @param end
+ * (last column - inclusive)
+ * @param useVisibleCoords
+ * if true, start and end are visible column positions, not absolute
+ * positions
+ */
+ public Iterator<int[]> getVisibleBlocksIterator(int start, int end,
+ boolean useVisibleCoords)
+ {
+ if (useVisibleCoords)
+ {
+ // TODO
+ // we should really just convert start and end here with
+ // adjustForHiddenColumns
+ // and then create a VisibleBlocksIterator
+ // but without a cursor this will be horribly slow in some situations
+ // ... so until then...
+ return new VisibleBlocksVisBoundsIterator(start, end, true);
+ }
+ else
+ {
+ return new VisibleBlocksIterator(start, end, true);
+ }
+ }
+
+ /**
* An iterator which iterates over hidden column regions in a range.
*/
private class BoundedHiddenColsIterator implements Iterator<int[]>
}
}
+ /**
+ * An iterator which iterates over visible regions in a range as visible
+ * column positions.
+ */
+ public class VisibleBlocksVisBoundsIterator implements Iterator<int[]>
+ {
+ private List<int[]> vcontigs = new ArrayList<>();
+
+ private int currentPosition = 0;
+
+ private boolean endsAtHidden = true;
+
+ VisibleBlocksVisBoundsIterator(int start, int end, boolean usecopy)
+ {
+ try
+ {
+ if (usecopy)
+ {
+ LOCK.readLock().lock();
+ }
+
+ if (hiddenColumns != null && hiddenColumns.size() > 0)
+ {
+ int blockStart = start;
+ int blockEnd = end;
+ int hiddenSoFar = 0;
+ int visSoFar = 0;
+ int maxVisible = end - start;
+
+ // iterate until a region begins within (start,end]
+ int i = 0;
+ while ((i < hiddenColumns.size())
+ && (hiddenColumns.get(i)[0] <= blockStart + hiddenSoFar))
+ {
+ hiddenSoFar += hiddenColumns.get(i)[1] - hiddenColumns.get(i)[0]
+ + 1;
+ i++;
+ }
+
+ blockStart += hiddenSoFar; // convert start to absolute position
+ blockEnd += hiddenSoFar; // convert end too in
+
+ // iterate from start to end, adding each hidden region. Positions are
+ // absolute, and all regions which *overlap* [start,end] are used.
+ while (i < hiddenColumns.size()
+ && (hiddenColumns.get(i)[0] <= blockEnd))
+ {
+ int[] region = hiddenColumns.get(i);
+
+ blockEnd = Math.min(blockEnd, region[0] - 1);
+
+ int[] contig = new int[] { blockStart, blockEnd };
+ vcontigs.add(contig);
+
+ visSoFar += blockEnd - blockStart + 1;
+ blockStart = region[1] + 1;
+ blockEnd = end + hiddenSoFar;
+ hiddenSoFar += region[1] - region[0] + 1;
+
+ i++;
+ }
+ if (visSoFar < maxVisible)
+ {
+ blockEnd = blockStart + maxVisible - visSoFar;
+ int[] contig = new int[] { blockStart,
+ blockEnd };
+ vcontigs.add(contig);
+
+ endsAtHidden = false;
+ }
+ }
+ else
+ {
+ int[] contig = new int[] { start, end };
+ vcontigs.add(contig);
+ endsAtHidden = false;
+ }
+ } finally
+ {
+ if (usecopy)
+ {
+ LOCK.readLock().unlock();
+ }
+ }
+ }
+
+ @Override
+ public boolean hasNext()
+ {
+ return (currentPosition < vcontigs.size());
+ }
+
+ @Override
+ public int[] next()
+ {
+ int[] result = vcontigs.get(currentPosition);
+ currentPosition++;
+ return result;
+ }
+
+ public boolean endsAtHidden()
+ {
+ return endsAtHidden;
+ }
+ }
+
}