diff --git a/src/main/java/com/github/davidmoten/rtree/Backpressure.java b/src/main/java/com/github/davidmoten/rtree/Backpressure.java index 9eacc420..5a34c3e9 100644 --- a/src/main/java/com/github/davidmoten/rtree/Backpressure.java +++ b/src/main/java/com/github/davidmoten/rtree/Backpressure.java @@ -68,6 +68,11 @@ private static StackAndRequest> searc final Func1 condition, final Subscriber> subscriber, StackAndRequest> state, NodePosition np) { + final long nextRequest=getNextRequest(condition, subscriber, state, np); + return StackAndRequest.create(state.stack.pop().push(np.nextPosition()), nextRequest); + } + + private static long getNextRequest(Func1 condition, Subscriber> subscriber, StackAndRequest> state, NodePosition np) { final long nextRequest; Entry entry = ((Leaf) np.node()).entry(np.position()); if (condition.call(entry.geometry())) { @@ -75,7 +80,7 @@ private static StackAndRequest> searc nextRequest = state.request - 1; } else nextRequest = state.request; - return StackAndRequest.create(state.stack.pop().push(np.nextPosition()), nextRequest); + return nextRequest; } private static ImmutableStack> searchNonLeaf( diff --git a/src/main/java/com/github/davidmoten/rtree/RTree.java b/src/main/java/com/github/davidmoten/rtree/RTree.java index d60a0ad9..e38161cb 100644 --- a/src/main/java/com/github/davidmoten/rtree/RTree.java +++ b/src/main/java/com/github/davidmoten/rtree/RTree.java @@ -378,12 +378,7 @@ private RTree packingSTR(List root; - if (isLeaf) { - root = context.factory().createLeaf((List>) objects, context); - } else { - root = context.factory().createNonLeaf((List>) objects, context); - } + Node root=getTsNode(objects, isLeaf, context); return new RTree(of(root), size, context); } @@ -416,6 +411,16 @@ private RTree packingSTR(List Node getTsNode(List objects, boolean isLeaf, Context context) { + Node root; + if (isLeaf) { + root = context.factory().createLeaf((List>) objects, context); + } else { + root = context.factory().createNonLeaf((List>) objects, context); + } + return root; + } + private static final class MidComparator implements Comparator { private final short dimension; // leave space for multiple dimensions, 0 for x, 1 for y, // ... @@ -450,13 +455,7 @@ private double mid(HasGeometry o) { @SuppressWarnings("unchecked") public RTree add(Entry entry) { if (root.isPresent()) { - List> nodes = root.get().add(entry); - Node node; - if (nodes.size() == 1) - node = nodes.get(0); - else { - node = context.factory().createNonLeaf(nodes, context); - } + Node node=getTsNode(entry); return new RTree(node, size + 1, context); } else { Leaf node = context.factory().createLeaf(Lists.newArrayList((Entry) entry), @@ -465,6 +464,17 @@ public RTree add(Entry entry) { } } + private Node getTsNode(Entry entry) { + List> nodes = root.get().add(entry); + Node node; + if (nodes.size() == 1) + node = nodes.get(0); + else { + node = context.factory().createNonLeaf(nodes, context); + } + return node; + } + /** * Returns an immutable copy of the RTree with the addition of an entry * comprised of the given value and Geometry. diff --git a/src/main/java/com/github/davidmoten/rtree/Serializers.java b/src/main/java/com/github/davidmoten/rtree/Serializers.java index 4f35bddc..4ae17ec9 100644 --- a/src/main/java/com/github/davidmoten/rtree/Serializers.java +++ b/src/main/java/com/github/davidmoten/rtree/Serializers.java @@ -163,22 +163,14 @@ private static Func1 javaIoSerializer() { @Override public byte[] call(Serializable o) { ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - ObjectOutputStream oos = null; - try { - oos = new ObjectOutputStream(bytes); + try (ObjectOutputStream oos=new ObjectOutputStream(bytes)) { oos.writeObject(o); oos.close(); return bytes.toByteArray(); } catch (IOException e) { throw new RuntimeException(e); - } finally { - try { - if (oos != null) - oos.close(); - } catch (IOException e) { - // ignore - } } + // ignore } }; } @@ -192,9 +184,7 @@ public Serializable call(byte[] bytes) { try { ois = new ObjectInputStream(is); return (Serializable) ois.readObject(); - } catch (IOException e) { - throw new RuntimeException(e); - } catch (ClassNotFoundException e) { + } catch (IOException | ClassNotFoundException e) { throw new RuntimeException(e); } finally { if (ois != null) diff --git a/src/main/java/com/github/davidmoten/rtree/SplitterRStar.java b/src/main/java/com/github/davidmoten/rtree/SplitterRStar.java index 70a73d7f..1890c772 100644 --- a/src/main/java/com/github/davidmoten/rtree/SplitterRStar.java +++ b/src/main/java/com/github/davidmoten/rtree/SplitterRStar.java @@ -39,14 +39,24 @@ public ListPair split(List items, int minSize) { // compute S the sum of all margin-values of the lists above // the list with the least S is then used to find minimum overlap + List> pairs=getListPairs(items, minSize); + return Collections.min(pairs, comparator); + } + + private List> getListPairs(List items, int minSize) { List> pairs = null; double lowestMarginSum = Double.POSITIVE_INFINITY; List list = null; + pairs=getListPairs(items, minSize, pairs, lowestMarginSum, list); + return pairs; + } + + private List> getListPairs(List items, int minSize, List> pairs, double lowestMarginSum, List list) { for (SortType sortType : SortType.values()) { if (list == null) { list = new ArrayList(items); } - Collections.sort(list, comparator(sortType)); + list.sort(comparator(sortType)); List> p = getPairs(minSize, list); double marginSum = marginValueSum(p); if (marginSum <= lowestMarginSum) { @@ -57,7 +67,7 @@ public ListPair split(List items, int minSize) { list = null; } } - return Collections.min(pairs, comparator); + return pairs; } private static Comparator comparator(SortType sortType) { diff --git a/src/main/java/com/github/davidmoten/rtree/fbs/NonLeafFlatBuffers.java b/src/main/java/com/github/davidmoten/rtree/fbs/NonLeafFlatBuffers.java index 765d48f8..7506c1b2 100644 --- a/src/main/java/com/github/davidmoten/rtree/fbs/NonLeafFlatBuffers.java +++ b/src/main/java/com/github/davidmoten/rtree/fbs/NonLeafFlatBuffers.java @@ -72,14 +72,7 @@ private static void searchWithoutBackpressure(Node_ node { // write bounds from node to bounds variable node.mbb(bounds); - final Rectangle rect; - if (bounds.type() == BoundsType_.BoundsDouble) { - BoxDouble_ b = bounds.boxDouble(); - rect = Geometries.rectangle(b.minX(), b.minY(), b.maxX(), b.maxY()); - } else { - BoxFloat_ b = bounds.boxFloat(); - rect = Geometries.rectangle(b.minX(), b.minY(), b.maxX(), b.maxY()); - } + final Rectangle rect=getRectangle(bounds); if (!criterion.call(rect)) { return; } @@ -117,6 +110,18 @@ private static void searchWithoutBackpressure(Node_ node } + private static Rectangle getRectangle(Bounds_ bounds) { + final Rectangle rect; + if (bounds.type() == BoundsType_.BoundsDouble) { + BoxDouble_ b = bounds.boxDouble(); + rect = Geometries.rectangle(b.minX(), b.minY(), b.maxX(), b.maxY()); + } else { + BoxFloat_ b = bounds.boxFloat(); + rect = Geometries.rectangle(b.minX(), b.minY(), b.maxX(), b.maxY()); + } + return rect; + } + private List> createChildren() { // reduce allocations by resusing objects diff --git a/src/main/java/com/github/davidmoten/rtree/fbs/SerializerFlatBuffers.java b/src/main/java/com/github/davidmoten/rtree/fbs/SerializerFlatBuffers.java index 0a261bae..d58397e7 100644 --- a/src/main/java/com/github/davidmoten/rtree/fbs/SerializerFlatBuffers.java +++ b/src/main/java/com/github/davidmoten/rtree/fbs/SerializerFlatBuffers.java @@ -53,12 +53,7 @@ public static Serializer create( @Override public void write(RTree tree, OutputStream os) throws IOException { FlatBufferBuilder builder = new FlatBufferBuilder(); - final Rectangle mbb; - if (tree.root().isPresent()) { - mbb = tree.root().get().geometry().mbr(); - } else { - mbb = Geometries.rectangle(0, 0, 0, 0); - } + final Rectangle mbb=getRectangle(tree); int b = toBounds(builder, mbb); Context_.startContext_(builder); Context_.addBounds(builder, b); @@ -86,6 +81,16 @@ public void write(RTree tree, OutputStream os) throws IOException { os.write(bb.array(), bb.position(), bb.remaining()); } + private Rectangle getRectangle(RTree tree) { + final Rectangle mbb; + if (tree.root().isPresent()) { + mbb = tree.root().get().geometry().mbr(); + } else { + mbb = Geometries.rectangle(0, 0, 0, 0); + } + return mbb; + } + private static int toBounds(FlatBufferBuilder builder, final Rectangle r) { Bounds_.startBounds_(builder); if (r.isDoublePrecision()) { @@ -134,18 +139,23 @@ public RTree read(InputStream is, long sizeBytes, InternalStructure struct if (node == null) { return SerializerHelper.create(Optional.empty(), 0, context); } else { - final Node root; - if (structure == InternalStructure.SINGLE_ARRAY) { - if (node.childrenLength() > 0) { - root = new NonLeafFlatBuffers(node, context, factory.deserializer()); - } else { - root = new LeafFlatBuffers(node, context, factory.deserializer()); - } + final Node root=getTsNode(structure, context, node); + return SerializerHelper.create(Optional.of(root), (int) t.size(), context); + } + } + + private Node getTsNode(InternalStructure structure, Context context, Node_ node) { + final Node root; + if (structure == InternalStructure.SINGLE_ARRAY) { + if (node.childrenLength() > 0) { + root = new NonLeafFlatBuffers(node, context, factory.deserializer()); } else { - root = toNodeDefault(node, context, factory.deserializer()); + root = new LeafFlatBuffers(node, context, factory.deserializer()); } - return SerializerHelper.create(Optional.of(root), (int) t.size(), context); + } else { + root = toNodeDefault(node, context, factory.deserializer()); } + return root; } private static Node toNodeDefault(Node_ node, diff --git a/src/main/java/com/github/davidmoten/rtree/internal/NonLeafHelper.java b/src/main/java/com/github/davidmoten/rtree/internal/NonLeafHelper.java index 9f110462..95de7adc 100644 --- a/src/main/java/com/github/davidmoten/rtree/internal/NonLeafHelper.java +++ b/src/main/java/com/github/davidmoten/rtree/internal/NonLeafHelper.java @@ -79,6 +79,23 @@ public static NodeAndEntries delete( List> addTheseNodes = new ArrayList>(); int countDeleted = 0; List> children = node.children(); + countDeleted=getCountDeleted(entry, all, addTheseEntries, removeTheseNodes, addTheseNodes, countDeleted, children); + if (removeTheseNodes.isEmpty()) + return new NodeAndEntries<>(of(node), Collections.emptyList(), 0); + else { + List> nodes = Util.remove(children, removeTheseNodes); + nodes.addAll(addTheseNodes); + if (nodes.isEmpty()) + return new NodeAndEntries<>(Optional.empty(), addTheseEntries, + countDeleted); + else { + NonLeaf nd = node.context().factory().createNonLeaf(nodes, node.context()); + return new NodeAndEntries<>(of(nd), addTheseEntries, countDeleted); + } + } + } + + private static int getCountDeleted(Entry entry, boolean all, List> addTheseEntries, List> removeTheseNodes, List> addTheseNodes, int countDeleted, List> children) { for (final Node child : children) { if (entry.geometry().intersects(child.geometry().mbr())) { final NodeAndEntries result = child.delete(entry, all); @@ -105,19 +122,7 @@ public static NodeAndEntries delete( } } } - if (removeTheseNodes.isEmpty()) - return new NodeAndEntries<>(of(node), Collections.emptyList(), 0); - else { - List> nodes = Util.remove(children, removeTheseNodes); - nodes.addAll(addTheseNodes); - if (nodes.isEmpty()) - return new NodeAndEntries<>(Optional.empty(), addTheseEntries, - countDeleted); - else { - NonLeaf nd = node.context().factory().createNonLeaf(nodes, node.context()); - return new NodeAndEntries<>(of(nd), addTheseEntries, countDeleted); - } - } + return countDeleted; } } diff --git a/src/main/java/com/github/davidmoten/rtree/internal/RectangleUtil.java b/src/main/java/com/github/davidmoten/rtree/internal/RectangleUtil.java index 421179b5..6ec0846d 100644 --- a/src/main/java/com/github/davidmoten/rtree/internal/RectangleUtil.java +++ b/src/main/java/com/github/davidmoten/rtree/internal/RectangleUtil.java @@ -60,17 +60,11 @@ private static boolean _rectangleIntersectsLine(double rectX, double rectY, doub return false; } if ((out1 & (OUT_LEFT | OUT_RIGHT)) != 0) { - double x = rectX; - if ((out1 & OUT_RIGHT) != 0) { - x += rectWidth; - } + double x=getX(rectX, rectWidth, out1, OUT_RIGHT); y1 = y1 + (x - x1) * (y2 - y1) / (x2 - x1); x1 = x; } else { - double y = rectY; - if ((out1 & OUT_BOTTOM) != 0) { - y += rectHeight; - } + double y=getX(rectY, rectHeight, out1, OUT_BOTTOM); x1 = x1 + (y - y1) * (x2 - x1) / (y2 - y1); y1 = y; } @@ -78,6 +72,14 @@ private static boolean _rectangleIntersectsLine(double rectX, double rectY, doub return true; } + private static double getX(double rectX, double rectWidth, int out1, int outRight) { + double x=rectX; + if ((out1 & outRight) != 0) { + x+=rectWidth; + } + return x; + } + private static boolean rectangleCornerOnSegment(double rectX, double rectY, double rectWidth, double rectHeight, double x1, double y1, double x2, double y2) { if (pointOnSegment(rectX, rectY, x1, y1, x2, y2)) {