kopia lustrzana https://github.com/onthegomap/planetiler
				
				
				
			IntRange
							rodzic
							
								
									11e296a9cb
								
							
						
					
					
						commit
						51ecbc5955
					
				| 
						 | 
				
			
			@ -1,5 +1,95 @@
 | 
			
		|||
package com.onthegomap.flatmap.collections;
 | 
			
		||||
 | 
			
		||||
public class IntRange {
 | 
			
		||||
import com.google.common.collect.Range;
 | 
			
		||||
import com.google.common.collect.RangeSet;
 | 
			
		||||
import com.google.common.collect.TreeRangeSet;
 | 
			
		||||
import java.util.Iterator;
 | 
			
		||||
import java.util.PrimitiveIterator;
 | 
			
		||||
 | 
			
		||||
public class IntRange implements Iterable<Integer> {
 | 
			
		||||
 | 
			
		||||
  private final TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();
 | 
			
		||||
 | 
			
		||||
  public IntRange addAll(IntRange range) {
 | 
			
		||||
    rangeSet.addAll(range.rangeSet);
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public IntRange removeAll(IntRange range) {
 | 
			
		||||
    rangeSet.removeAll(range.rangeSet);
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public PrimitiveIterator.OfInt iterator() {
 | 
			
		||||
    return new Iter(rangeSet.asRanges().iterator());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public IntRange add(int a, int b) {
 | 
			
		||||
    rangeSet.add(Range.closedOpen(a, b + 1));
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public IntRange remove(int a) {
 | 
			
		||||
    rangeSet.remove(Range.closedOpen(a, a + 1));
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public boolean contains(int y) {
 | 
			
		||||
    return rangeSet.contains(y);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public IntRange intersect(IntRange other) {
 | 
			
		||||
    rangeSet.removeAll(other.rangeSet.complement());
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public int nextInRange(int lo, int hi) {
 | 
			
		||||
    RangeSet<Integer> subset = rangeSet.subRangeSet(Range.closed(lo, hi));
 | 
			
		||||
    if (subset.isEmpty()) {
 | 
			
		||||
      return hi;
 | 
			
		||||
    } else {
 | 
			
		||||
      return subset.span().lowerEndpoint();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private static class Iter implements PrimitiveIterator.OfInt {
 | 
			
		||||
 | 
			
		||||
    private final Iterator<Range<Integer>> rangeIter;
 | 
			
		||||
    Range<Integer> range;
 | 
			
		||||
    Integer cur;
 | 
			
		||||
    boolean hasNext = true;
 | 
			
		||||
 | 
			
		||||
    private Iter(Iterator<Range<Integer>> rangeIter) {
 | 
			
		||||
      this.rangeIter = rangeIter;
 | 
			
		||||
      advance();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void advance() {
 | 
			
		||||
      while (true) {
 | 
			
		||||
        if (range != null && cur < range.upperEndpoint() - 1) {
 | 
			
		||||
          cur++;
 | 
			
		||||
          return;
 | 
			
		||||
        } else if (rangeIter.hasNext()) {
 | 
			
		||||
          range = rangeIter.next();
 | 
			
		||||
          cur = range.lowerEndpoint() - 1;
 | 
			
		||||
        } else {
 | 
			
		||||
          hasNext = false;
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int nextInt() {
 | 
			
		||||
      int result = cur;
 | 
			
		||||
      advance();
 | 
			
		||||
      return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean hasNext() {
 | 
			
		||||
      return hasNext;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,7 +10,7 @@ public interface LongLongMap extends Closeable {
 | 
			
		|||
 | 
			
		||||
  long get(long key);
 | 
			
		||||
 | 
			
		||||
  Path filePath();
 | 
			
		||||
  long fileSize();
 | 
			
		||||
 | 
			
		||||
  class MapdbSortedTable implements LongLongMap {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -29,8 +29,8 @@ public interface LongLongMap extends Closeable {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Path filePath() {
 | 
			
		||||
      return null;
 | 
			
		||||
    public long fileSize() {
 | 
			
		||||
      return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -97,7 +97,7 @@ public class OpenStreetMapReader implements Closeable {
 | 
			
		|||
 | 
			
		||||
    var loggers = new ProgressLoggers("osm_pass1")
 | 
			
		||||
      .addRateCounter("nodes", TOTAL_NODES)
 | 
			
		||||
      .addFileSize(nodeDb.filePath())
 | 
			
		||||
      .addFileSize(nodeDb::fileSize)
 | 
			
		||||
      .addRateCounter("ways", TOTAL_WAYS)
 | 
			
		||||
      .addRateCounter("rels", TOTAL_RELATIONS)
 | 
			
		||||
      .addProcessStats()
 | 
			
		||||
| 
						 | 
				
			
			@ -156,7 +156,7 @@ public class OpenStreetMapReader implements Closeable {
 | 
			
		|||
 | 
			
		||||
    var logger = new ProgressLoggers("osm_pass2")
 | 
			
		||||
      .addRatePercentCounter("nodes", TOTAL_NODES.get(), nodesProcessed)
 | 
			
		||||
      .addFileSize(nodeDb.filePath())
 | 
			
		||||
      .addFileSize(nodeDb::fileSize)
 | 
			
		||||
      .addRatePercentCounter("ways", TOTAL_WAYS.get(), waysProcessed)
 | 
			
		||||
      .addRatePercentCounter("rels", TOTAL_RELATIONS.get(), relsProcessed)
 | 
			
		||||
      .addRateCounter("features", () -> writer.sorter().size())
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,160 @@
 | 
			
		|||
package com.onthegomap.flatmap.collections;
 | 
			
		||||
 | 
			
		||||
import static org.junit.jupiter.api.Assertions.assertEquals;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import org.junit.jupiter.api.Test;
 | 
			
		||||
 | 
			
		||||
public class IntRangeTest {
 | 
			
		||||
 | 
			
		||||
  private static List<Integer> getInts(IntRange range) {
 | 
			
		||||
    List<Integer> result = new ArrayList<>();
 | 
			
		||||
    for (Integer integer : range) {
 | 
			
		||||
      result.add(integer);
 | 
			
		||||
    }
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void testEmptyIntRange() {
 | 
			
		||||
    IntRange range = new IntRange();
 | 
			
		||||
    assertEquals(List.of(), getInts(range));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void testSingleIntRange() {
 | 
			
		||||
    IntRange range = new IntRange();
 | 
			
		||||
    range.add(1, 1);
 | 
			
		||||
    assertEquals(List.of(1), getInts(range));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void testLongerIntRange() {
 | 
			
		||||
    IntRange range = new IntRange();
 | 
			
		||||
    range.add(1, 3);
 | 
			
		||||
    assertEquals(List.of(1, 2, 3), getInts(range));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void testTwoIntRanges() {
 | 
			
		||||
    IntRange range = new IntRange();
 | 
			
		||||
    range.add(1, 3);
 | 
			
		||||
    range.add(5, 7);
 | 
			
		||||
    assertEquals(List.of(1, 2, 3, 5, 6, 7), getInts(range));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void testTwoOverlappingIntRanges() {
 | 
			
		||||
    IntRange range = new IntRange();
 | 
			
		||||
    range.add(1, 5);
 | 
			
		||||
    range.add(4, 7);
 | 
			
		||||
    assertEquals(List.of(1, 2, 3, 4, 5, 6, 7), getInts(range));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void testRemoveSingle() {
 | 
			
		||||
    IntRange range = new IntRange();
 | 
			
		||||
    range.add(1, 5);
 | 
			
		||||
    range.remove(3);
 | 
			
		||||
    assertEquals(List.of(1, 2, 4, 5), getInts(range));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void testRemoveOtherRange() {
 | 
			
		||||
    IntRange range = new IntRange();
 | 
			
		||||
    range.add(1, 5);
 | 
			
		||||
    IntRange range2 = new IntRange();
 | 
			
		||||
    range2.add(4, 6);
 | 
			
		||||
    range.removeAll(range2);
 | 
			
		||||
    assertEquals(List.of(1, 2, 3), getInts(range));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void testAddOtherRange() {
 | 
			
		||||
    IntRange range = new IntRange();
 | 
			
		||||
    range.add(1, 5);
 | 
			
		||||
    IntRange range2 = new IntRange();
 | 
			
		||||
    range2.add(8, 10);
 | 
			
		||||
    range.addAll(range2);
 | 
			
		||||
    assertEquals(List.of(1, 2, 3, 4, 5, 8, 9, 10), getInts(range));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void testContains() {
 | 
			
		||||
    IntRange range = new IntRange();
 | 
			
		||||
    range.add(1, 5);
 | 
			
		||||
    IntRange range2 = new IntRange();
 | 
			
		||||
    range2.add(8, 10);
 | 
			
		||||
    range.addAll(range2);
 | 
			
		||||
    range.remove(3);
 | 
			
		||||
 | 
			
		||||
    var expected = Map.ofEntries(
 | 
			
		||||
      Map.entry(1, true),
 | 
			
		||||
      Map.entry(2, true),
 | 
			
		||||
      Map.entry(3, false),
 | 
			
		||||
      Map.entry(4, true),
 | 
			
		||||
      Map.entry(5, true),
 | 
			
		||||
      Map.entry(6, false),
 | 
			
		||||
      Map.entry(7, false),
 | 
			
		||||
      Map.entry(8, true),
 | 
			
		||||
      Map.entry(9, true),
 | 
			
		||||
      Map.entry(10, true),
 | 
			
		||||
      Map.entry(11, false)
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    expected.forEach((num, val) -> assertEquals(val, range.contains(num), (val ? "" : "!") + num));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void testNoIntersection() {
 | 
			
		||||
    IntRange range = new IntRange();
 | 
			
		||||
    range.add(1, 5);
 | 
			
		||||
    IntRange range2 = new IntRange();
 | 
			
		||||
    range2.add(8, 10);
 | 
			
		||||
    range.intersect(range2);
 | 
			
		||||
    assertEquals(List.of(), getInts(range));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void testSingleIntersection() {
 | 
			
		||||
    IntRange range = new IntRange();
 | 
			
		||||
    range.add(1, 5);
 | 
			
		||||
    IntRange range2 = new IntRange();
 | 
			
		||||
    range2.add(5, 10);
 | 
			
		||||
    range.intersect(range2);
 | 
			
		||||
    assertEquals(List.of(5), getInts(range));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void testMultipleIntersection() {
 | 
			
		||||
    IntRange range = new IntRange();
 | 
			
		||||
    range.add(1, 5);
 | 
			
		||||
    IntRange range2 = new IntRange();
 | 
			
		||||
    range2.add(3, 10);
 | 
			
		||||
    range2.remove(4);
 | 
			
		||||
    range.intersect(range2);
 | 
			
		||||
    assertEquals(List.of(3, 5), getInts(range));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void testNextEmpty() {
 | 
			
		||||
    IntRange range = new IntRange();
 | 
			
		||||
    assertEquals(1, range.nextInRange(0, 1));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void testNextInRange() {
 | 
			
		||||
    IntRange range = new IntRange();
 | 
			
		||||
    range.add(0, 2);
 | 
			
		||||
    assertEquals(0, range.nextInRange(0, 1));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void testNextBelowInRange() {
 | 
			
		||||
    IntRange range = new IntRange();
 | 
			
		||||
    range.add(2, 4);
 | 
			
		||||
    assertEquals(2, range.nextInRange(1, 3));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Ładowanie…
	
		Reference in New Issue