Skip to content

Commit

Permalink
Merge pull request #13 from davidmoten/strong-typing
Browse files Browse the repository at this point in the history
strong typing of RTree entry geometry
  • Loading branch information
davidmoten committed Nov 2, 2014
2 parents 51957dc + b47c0f6 commit 5a582d0
Show file tree
Hide file tree
Showing 25 changed files with 468 additions and 414 deletions.
18 changes: 9 additions & 9 deletions src/main/java/com/github/davidmoten/rtree/Backpressure.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,38 +15,38 @@ private Backpressure() {
// prevent instantiation
}

static <T> ImmutableStack<NodePosition<T>> search(
static <T, S extends Geometry> ImmutableStack<NodePosition<T, S>> search(
final Func1<? super Geometry, Boolean> condition,
final Subscriber<? super Entry<T>> subscriber, ImmutableStack<NodePosition<T>> stack,
long request) {
final Subscriber<? super Entry<T, S>> subscriber,
ImmutableStack<NodePosition<T, S>> stack, long request) {
if (stack.isEmpty())
return stack;
while (true) {
NodePosition<T> np = stack.peek();
NodePosition<T, S> np = stack.peek();
if (subscriber.isUnsubscribed())
return ImmutableStack.empty();
else if (request == 0)
return stack;
else if (np.position() == np.node().count()) {
// handle after last position in node
ImmutableStack<NodePosition<T>> stack2 = stack.pop();
ImmutableStack<NodePosition<T, S>> stack2 = stack.pop();
if (stack2.isEmpty())
return stack2;
else {
NodePosition<T> previous = stack2.peek();
NodePosition<T, S> previous = stack2.peek();
stack = stack2.pop().push(previous.nextPosition());
}
} else if (np.node() instanceof NonLeaf) {
// handle non-leaf
Node<T> child = ((NonLeaf<T>) np.node()).children().get(np.position());
Node<T, S> child = ((NonLeaf<T, S>) np.node()).children().get(np.position());
if (condition.call(child.geometry())) {
stack = stack.push(new NodePosition<T>(child, 0));
stack = stack.push(new NodePosition<T, S>(child, 0));
} else {
stack = stack.pop().push(np.nextPosition());
}
} else {
// handle leaf
Entry<T> entry = ((Leaf<T>) np.node()).entries().get(np.position());
Entry<T, S> entry = ((Leaf<T, S>) np.node()).entries().get(np.position());
final long nextRequest;
if (condition.call(entry.geometry())) {
subscriber.onNext(entry);
Expand Down
10 changes: 6 additions & 4 deletions src/main/java/com/github/davidmoten/rtree/Comparators.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import rx.functions.Func1;

import com.github.davidmoten.rtree.geometry.Geometry;
import com.github.davidmoten.rtree.geometry.HasGeometry;
import com.github.davidmoten.rtree.geometry.ListPair;
import com.github.davidmoten.rtree.geometry.Rectangle;
Expand Down Expand Up @@ -38,7 +39,7 @@ public int compare(ListPair<?> p1, ListPair<?> p2) {
* total of the areas of overlap of the members of the list with the
* rectangle r.
*
* @param <T>
* @param <T>
* type of geometry being compared
* @param r
* rectangle
Expand Down Expand Up @@ -107,10 +108,11 @@ public int compare(T t1, T t2) {
* the entry type
* @return a comparator to sort by ascending distance from the rectangle
*/
public static <S> Comparator<Entry<S>> ascendingDistance(final Rectangle r) {
return new Comparator<Entry<S>>() {
public static <T, S extends Geometry> Comparator<Entry<T, S>> ascendingDistance(
final Rectangle r) {
return new Comparator<Entry<T, S>>() {
@Override
public int compare(Entry<S> e1, Entry<S> e2) {
public int compare(Entry<T, S> e1, Entry<T, S> e2) {
return ((Double) e1.geometry().distance(r)).compareTo(e2.geometry().distance(r));
}
};
Expand Down
21 changes: 12 additions & 9 deletions src/main/java/com/github/davidmoten/rtree/Entry.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
* @param <T>
* the type of Entry
*/
public final class Entry<T> implements HasGeometry {
public final class Entry<T, S extends Geometry> implements HasGeometry {
private final T value;
private final Geometry geometry;
private final S geometry;

/**
* Constructor.
Expand All @@ -25,7 +25,7 @@ public final class Entry<T> implements HasGeometry {
* @param geometry
* the geometry of the value
*/
public Entry(T value, Geometry geometry) {
public Entry(T value, S geometry) {
Preconditions.checkNotNull(geometry);
this.value = value;
this.geometry = geometry;
Expand All @@ -34,13 +34,16 @@ public Entry(T value, Geometry geometry) {
/**
* Factory method.
*
* @param <T> type of value
* @param value object being given a spatial context
* @param geometry geometry associated with the value
* @param <T>
* type of value
* @param value
* object being given a spatial context
* @param geometry
* geometry associated with the value
* @return entry wrapping value and associated geometry
*/
public static <T> Entry<T> entry(T value, Geometry geometry) {
return new Entry<T>(value, geometry);
public static <T, S extends Geometry> Entry<T, S> entry(T value, S geometry) {
return new Entry<T, S>(value, geometry);
}

/**
Expand All @@ -53,7 +56,7 @@ public T value() {
}

@Override
public Geometry geometry() {
public S geometry() {
return geometry;
}

Expand Down
51 changes: 27 additions & 24 deletions src/main/java/com/github/davidmoten/rtree/Leaf.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
import com.github.davidmoten.rtree.geometry.Rectangle;
import com.google.common.base.Optional;

final class Leaf<T> implements Node<T> {
final class Leaf<T, S extends Geometry> implements Node<T, S> {

private final List<Entry<T>> entries;
private final List<Entry<T, S>> entries;
private final Rectangle mbr;
private final Context context;

Leaf(List<Entry<T>> entries, Context context) {
Leaf(List<Entry<T, S>> entries, Context context) {
this.entries = entries;
this.context = context;
this.mbr = Util.mbr(entries);
Expand All @@ -31,22 +31,22 @@ public Geometry geometry() {
return mbr;
}

List<Entry<T>> entries() {
List<Entry<T, S>> entries() {
return entries;
}

@Override
public void search(Func1<? super Geometry, Boolean> criterion,
Subscriber<? super Entry<T>> subscriber) {
if (!criterion.call(this.geometry().mbr()))
public void search(Func1<? super Geometry, Boolean> condition,
Subscriber<? super Entry<T, S>> subscriber) {

if (!condition.call(this.geometry().mbr()))
return;

for (final Entry<T> entry : entries) {
for (final Entry<T, S> entry : entries) {
if (subscriber.isUnsubscribed())
return;
else {
if (criterion.call(entry.geometry()))
if (condition.call(entry.geometry()))
subscriber.onNext(entry);
}
}
Expand All @@ -58,42 +58,45 @@ public int count() {
}

@Override
public List<Node<T>> add(Entry<T> entry) {
final List<Entry<T>> entries2 = Util.add(entries, entry);
public List<Node<T, S>> add(Entry<? extends T, ? extends S> entry) {
@SuppressWarnings("unchecked")
final List<Entry<T, S>> entries2 = Util.add(entries, (Entry<T, S>) entry);
if (entries2.size() <= context.maxChildren())
return Collections.singletonList((Node<T>) new Leaf<T>(entries2, context));
return Collections.singletonList((Node<T, S>) new Leaf<T, S>(entries2, context));
else {
ListPair<Entry<T>> pair = context.splitter().split(entries2, context.minChildren());
ListPair<Entry<T, S>> pair = context.splitter().split(entries2, context.minChildren());
return makeLeaves(pair);
}
}

private List<Node<T>> makeLeaves(ListPair<Entry<T>> pair) {
List<Node<T>> list = new ArrayList<Node<T>>();
list.add(new Leaf<T>(pair.group1().list(), context));
list.add(new Leaf<T>(pair.group2().list(), context));
private List<Node<T, S>> makeLeaves(ListPair<Entry<T, S>> pair) {
List<Node<T, S>> list = new ArrayList<Node<T, S>>();
list.add(new Leaf<T, S>(pair.group1().list(), context));
list.add(new Leaf<T, S>(pair.group2().list(), context));
return list;
}

@Override
public NodeAndEntries<T> delete(Entry<T> entry, boolean all) {
public NodeAndEntries<T, S> delete(Entry<? extends T, ? extends S> entry, boolean all) {
if (!entries.contains(entry)) {
return new NodeAndEntries<T>(of(this), Collections.<Entry<T>> emptyList(), 0);
return new NodeAndEntries<T, S>(of(this), Collections.<Entry<T, S>> emptyList(), 0);
} else {
final List<Entry<T>> entries2 = new ArrayList<Entry<T>>(entries);
final List<Entry<T, S>> entries2 = new ArrayList<Entry<T, S>>(entries);
entries2.remove(entry);
int numDeleted = 1;
// keep deleting if all specified
while (all && entries2.remove(entry))
numDeleted += 1;

if (entries2.size() >= context.minChildren()) {
Leaf<T> node = new Leaf<T>(entries2, context);
return new NodeAndEntries<T>(of(node), Collections.<Entry<T>> emptyList(),
Leaf<T, S> node = new Leaf<T, S>(entries2, context);
return new NodeAndEntries<T, S>(of(node), Collections.<Entry<T, S>> emptyList(),
numDeleted);
} else {
return new NodeAndEntries<T>(Optional.<Node<T>> absent(), entries2, numDeleted);
return new NodeAndEntries<T, S>(Optional.<Node<T, S>> absent(), entries2,
numDeleted);
}
}
}

}
9 changes: 5 additions & 4 deletions src/main/java/com/github/davidmoten/rtree/Node.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@
import com.github.davidmoten.rtree.geometry.Geometry;
import com.github.davidmoten.rtree.geometry.HasGeometry;

interface Node<T> extends HasGeometry {
interface Node<T, S extends Geometry> extends HasGeometry {

List<Node<T>> add(Entry<T> entry);
List<Node<T, S>> add(Entry<? extends T, ? extends S> entry);

NodeAndEntries<T> delete(Entry<T> entry, boolean all);
NodeAndEntries<T, S> delete(Entry<? extends T, ? extends S> entry, boolean all);

void search(Func1<? super Geometry, Boolean> condition, Subscriber<? super Entry<T>> subscriber);
void search(Func1<? super Geometry, Boolean> condition,
Subscriber<? super Entry<T, S>> subscriber);

int count();

Expand Down
14 changes: 8 additions & 6 deletions src/main/java/com/github/davidmoten/rtree/NodeAndEntries.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.List;

import com.github.davidmoten.rtree.geometry.Geometry;
import com.google.common.base.Optional;

/**
Expand All @@ -10,10 +11,10 @@
* @param <T>
* entry type
*/
class NodeAndEntries<T> {
class NodeAndEntries<T, S extends Geometry> {

private final Optional<? extends Node<T>> node;
private final List<Entry<T>> entries;
private final Optional<? extends Node<T, S>> node;
private final List<Entry<T, S>> entries;
private final int count;

/**
Expand All @@ -29,17 +30,18 @@ class NodeAndEntries<T> {
* @param countDeleted
* count of the number of entries removed
*/
public NodeAndEntries(Optional<? extends Node<T>> node, List<Entry<T>> entries, int countDeleted) {
public NodeAndEntries(Optional<? extends Node<T, S>> node, List<Entry<T, S>> entries,
int countDeleted) {
this.node = node;
this.entries = entries;
this.count = countDeleted;
}

public Optional<? extends Node<T>> node() {
public Optional<? extends Node<T, S>> node() {
return node;
}

public List<Entry<T>> entriesToAdd() {
public List<Entry<T, S>> entriesToAdd() {
return entries;
}

Expand Down
14 changes: 8 additions & 6 deletions src/main/java/com/github/davidmoten/rtree/NodePosition.java
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
package com.github.davidmoten.rtree;

final class NodePosition<T> {
import com.github.davidmoten.rtree.geometry.Geometry;

private final Node<T> node;
final class NodePosition<T, S extends Geometry> {

private final Node<T, S> node;
private final int position;

NodePosition(Node<T> node, int position) {
NodePosition(Node<T, S> node, int position) {
this.node = node;
this.position = position;
}

Node<T> node() {
Node<T, S> node() {
return node;
}

int position() {
return position;
}

NodePosition<T> nextPosition() {
return new NodePosition<T>(node, position + 1);
NodePosition<T, S> nextPosition() {
return new NodePosition<T, S>(node, position + 1);
}

}
Loading

0 comments on commit 5a582d0

Please sign in to comment.