forked from Xinyu-Li/rtree
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNonLeaf.java
More file actions
136 lines (119 loc) · 5.19 KB
/
NonLeaf.java
File metadata and controls
136 lines (119 loc) · 5.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package com.github.davidmoten.rtree;
import static com.google.common.base.Optional.of;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import rx.Subscriber;
import rx.functions.Func1;
import com.github.davidmoten.rtree.geometry.Geometry;
import com.github.davidmoten.rtree.geometry.ListPair;
import com.github.davidmoten.rtree.geometry.Rectangle;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
final class NonLeaf<T, S extends Geometry> implements Node<T, S> {
private final List<? extends Node<T, S>> children;
private final Rectangle mbr;
private final Context context;
NonLeaf(List<? extends Node<T, S>> children, Context context) {
Preconditions.checkArgument(!children.isEmpty());
this.context = context;
this.children = children;
this.mbr = Util.mbr(children);
}
@Override
public Geometry geometry() {
return mbr;
}
@Override
public void search(Func1<? super Geometry, Boolean> criterion,
Subscriber<? super Entry<T, S>> subscriber) {
if (!criterion.call(this.geometry().mbr()))
return;
for (final Node<T, S> child : children) {
if (subscriber.isUnsubscribed())
return;
else
child.search(criterion, subscriber);
}
}
@Override
public int count() {
return children.size();
}
List<? extends Node<T, S>> children() {
return children;
}
@Override
public List<Node<T, S>> add(Entry<? extends T, ? extends S> entry) {
final Node<T, S> child = context.selector().select(entry.geometry().mbr(), children);
List<Node<T, S>> list = child.add(entry);
List<? extends Node<T, S>> children2 = Util.replace(children, child, list);
if (children2.size() <= context.maxChildren())
return Collections.singletonList((Node<T, S>) new NonLeaf<T, S>(children2, context));
else {
ListPair<? extends Node<T, S>> pair = context.splitter().split(children2,
context.minChildren());
return makeNonLeaves(pair);
}
}
private List<Node<T, S>> makeNonLeaves(ListPair<? extends Node<T, S>> pair) {
List<Node<T, S>> list = new ArrayList<Node<T, S>>();
list.add(new NonLeaf<T, S>(pair.group1().list(), context));
list.add(new NonLeaf<T, S>(pair.group2().list(), context));
return list;
}
@Override
public NodeAndEntries<T, S> delete(Entry<? extends T, ? extends S> entry, boolean all) {
// the result of performing a delete of the given entry from this node
// will be that zero or more entries will be needed to be added back to
// the root of the tree (because num entries of their node fell below
// minChildren),
// zero or more children will need to be removed from this node,
// zero or more nodes to be added as children to this node(because
// entries have been deleted from them and they still have enough
// members to be active)
List<Entry<T, S>> addTheseEntries = new ArrayList<Entry<T, S>>();
List<Node<T, S>> removeTheseNodes = new ArrayList<Node<T, S>>();
List<Node<T, S>> addTheseNodes = new ArrayList<Node<T, S>>();
int countDeleted = 0;
for (final Node<T, S> child : children) {
if (entry.geometry().intersects(child.geometry().mbr())) {
final NodeAndEntries<T, S> result = child.delete(entry, all);
if (result.node().isPresent()) {
if (result.node().get() != child) {
// deletion occurred and child is above minChildren so
// we update it
addTheseNodes.add(result.node().get());
removeTheseNodes.add(child);
addTheseEntries.addAll(result.entriesToAdd());
countDeleted += result.countDeleted();
if (!all)
break;
}
// else nothing was deleted from that child
} else {
// deletion occurred and brought child below minChildren
// so we redistribute its entries
removeTheseNodes.add(child);
addTheseEntries.addAll(result.entriesToAdd());
countDeleted += result.countDeleted();
if (!all)
break;
}
}
}
if (removeTheseNodes.isEmpty())
return new NodeAndEntries<T, S>(of(this), Collections.<Entry<T, S>> emptyList(), 0);
else {
List<Node<T, S>> nodes = Util.remove(children, removeTheseNodes);
nodes.addAll(addTheseNodes);
if (nodes.size() == 0)
return new NodeAndEntries<T, S>(Optional.<Node<T, S>> absent(), addTheseEntries,
countDeleted);
else {
NonLeaf<T, S> node = new NonLeaf<T, S>(nodes, context);
return new NodeAndEntries<T, S>(of(node), addTheseEntries, countDeleted);
}
}
}
}