├── .gitignore
├── .travis.yml
├── doc
├── BUILD.txt
├── LICENSE.txt
├── README.txt
└── TEST.txt
├── pom.xml
├── readme.md
└── src
├── main
├── assembly
│ └── with-dependencies-zip.xml
├── java
│ └── net
│ │ └── sf
│ │ └── jsi
│ │ ├── BuildProperties.java
│ │ ├── Point.java
│ │ ├── PriorityQueue.java
│ │ ├── Rectangle.java
│ │ ├── SpatialIndex.java
│ │ └── rtree
│ │ ├── Node.java
│ │ ├── RTree.java
│ │ └── SortedList.java
└── resources
│ └── build.properties
├── site
├── site.xml
└── xdoc
│ └── index.xml
└── test
├── java
├── net
│ └── sf
│ │ └── jsi
│ │ ├── DeleteAllEntriesTest.java
│ │ ├── ListDecorator.java
│ │ ├── MoveEntriesTest.java
│ │ ├── NullIndex.java
│ │ ├── PerformanceTest.java
│ │ ├── RTreeWrapper.java
│ │ ├── RectangleMaxValueTest.java
│ │ ├── RectangleTest.java
│ │ ├── ReferenceCompareTest.java
│ │ ├── ReferenceCompareTest_1000.java
│ │ ├── ReferenceCompareTest_10000.java
│ │ ├── ReferenceCompareTest_100000.java
│ │ ├── SILWrapper.java
│ │ ├── Script.java
│ │ ├── SimpleIndex.java
│ │ ├── SortedListDecorator.java
│ │ ├── SortedListTest.java
│ │ └── SpatialIndexFactory.java
└── sil
│ ├── rtree
│ ├── Index.java
│ ├── Leaf.java
│ ├── Node.java
│ ├── RTree.java
│ ├── Statistics.java
│ └── makefile
│ ├── spatialindex
│ ├── IData.java
│ ├── IEntry.java
│ ├── INearestNeighborComparator.java
│ ├── INode.java
│ ├── INodeCommand.java
│ ├── IQueryStrategy.java
│ ├── IShape.java
│ ├── ISpatialIndex.java
│ ├── IStatistics.java
│ ├── IVisitor.java
│ ├── Point.java
│ ├── RWLock.java
│ ├── Region.java
│ └── SpatialIndex.java
│ └── storagemanager
│ ├── Buffer.java
│ ├── DiskStorageManager.java
│ ├── IBuffer.java
│ ├── IStorageManager.java
│ ├── InvalidPageException.java
│ ├── MemoryStorageManager.java
│ ├── PropertySet.java
│ ├── RandomEvictionsBuffer.java
│ └── makefile
└── resources
├── logback.xml
└── test-inputs
├── test-allfunctions-100-in
├── test-allfunctions-1000-in
├── test-allfunctions-10000-in
├── test-allfunctions-100000-in
├── test-allqueries-10000-in
├── test-contains-100-in
├── test-contains-1000-in
├── test-contains-10000-in
├── test-contains-100000-in
├── test-delete-100-in
├── test-delete-1000-in
├── test-delete-10000-in
├── test-delete-100000-in
├── test-intersect-100-in
├── test-intersect-1000-in
├── test-intersect-10000-in
├── test-intersect-100000-in
├── test-intersect-1000000-in
├── test-intersect-10000000-in
├── test-nearest-100-in
├── test-nearest-1000-in
├── test-nearest-10000-in
├── test-nearest-100000-in
├── test-nearestN-100-in
├── test-nearestN-1000-in
└── test-nearestN-10000-in
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 | .metadata
3 | .classpath
4 | .project
5 | .settings
6 | target
7 | *~
8 | *.swp
9 | *.log
10 | *.iml
11 | *.ipr
12 | *.iws
13 | /.idea/
14 |
15 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 |
--------------------------------------------------------------------------------
/doc/BUILD.txt:
--------------------------------------------------------------------------------
1 | To build the JSI library from source, install maven 3 and run the following:
2 |
3 | % cd
4 | % mvn package
5 |
6 | This will generate the binary package (jsi-x.y.z.jar) in the target subdirectory.
7 |
8 | The following is a list of useful maven targets:
9 | o eclipse:eclipse (generate eclipse project files; see below)
10 | o clean
11 | o compile
12 | o test
13 | o -Dtest=ReferenceCompareTest_10000 test
14 | o package
15 | o site
16 | o assembly:single (create package only)
17 | o site:deploy
18 | o deploy
19 |
20 | To import the project into eclipse, run mvn eclipse:eclipse, and then set the M2_REPO variable
21 | in Window -> Preferences -> Java -> Build Path -> Classpath Variables to point to your local
22 | maven repository (e.g. ~/.m2/repository)
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/doc/README.txt:
--------------------------------------------------------------------------------
1 | This is the Java Spatial Index library.
2 |
3 | For examples of usage, please see https://github.com/aled/jsi-examples
--------------------------------------------------------------------------------
/doc/TEST.txt:
--------------------------------------------------------------------------------
1 | These are the steps needed to check that the JSI library is working correctly.
2 | Note this will take a very long time to run:
3 |
4 | % cd
5 | % mvn test [This runs a short and quick test]
6 | % mvn -Dtest=ReferenceCompareTest_1000 test [Long test]
7 | % mvn -Dtest=ReferenceCompareTest_10000 test [Very long test]
8 | % mvn -Dtest=ReferenceCompareTest_100000 test [Ridiculously long test]
9 |
10 | If any errors occur, please raise an issue at https://github.com/aled/jsi/issues
11 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | net.sf.jsi
6 | jsi
7 | 1.1.0-SNAPSHOT
8 | jar
9 |
10 | jsi
11 | Java Spatial Index library
12 | https://www.sourceforge.net/projects/jsi
13 |
14 |
15 |
16 | The GNU Lesser General Public License, Version 2.1 or later
17 | https://www.gnu.org/licenses/lgpl-2.1.txt
18 |
19 |
20 |
21 |
22 |
23 | Aled Morris
24 | aled@users.sourceforge.net
25 | https://github.com/aled/jsi
26 |
27 |
28 |
29 |
30 | scm:git:https://github.com/aled/jsi.git
31 | scm:git:https://github.com/aled/jsi.git
32 | https://github.com/aled/jsi.git
33 |
34 |
35 |
36 | UTF-8
37 |
38 |
39 |
40 |
41 |
42 | src/main/resources
43 | true
44 |
45 | build.properties
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | maven-compiler-plugin
54 | 2.3.2
55 |
56 | 1.5
57 | 1.5
58 |
59 |
60 |
61 | org.apache.maven.plugins
62 | maven-surefire-plugin
63 | 2.10
64 |
65 |
66 | **/PerformanceTest.java
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | org.apache.maven.plugins
79 | maven-enforcer-plugin
80 | 1.1.1
81 |
82 |
83 | enforce-versions
84 |
85 | enforce
86 |
87 |
88 |
89 |
90 | [3.0.0,4.0.0)
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
123 |
124 |
125 | org.apache.maven.plugins
126 | maven-source-plugin
127 | 2.1.2
128 |
129 |
130 | attach-sources
131 |
132 | jar
133 |
134 |
135 |
136 |
137 |
138 |
139 | org.apache.maven.plugins
140 | maven-javadoc-plugin
141 | 2.8
142 |
143 |
144 | attach-javadocs
145 |
146 | jar
147 |
148 |
149 |
150 |
151 |
152 |
153 | org.apache.maven.plugins
154 | maven-dependency-plugin
155 | 2.4
156 |
157 |
158 | copy-dependencies
159 | package
160 |
161 | copy-dependencies
162 |
163 |
164 | ${project.build.directory}/dependencies
165 | compile
166 |
167 |
168 |
169 |
170 | copy-test-dependencies
171 | package
172 |
173 | copy-dependencies
174 |
175 |
176 | ${project.build.directory}/test-dependencies
177 | compile
178 |
179 |
180 |
181 |
182 |
183 |
203 |
204 |
205 | maven-deploy-plugin
206 | 2.7
207 |
208 |
209 |
210 | org.apache.maven.plugins
211 | maven-gpg-plugin
212 | 1.5
213 |
214 |
215 | sign-artifacts
216 | verify
217 |
218 | sign
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 | org.apache.maven.wagon
228 | wagon-ssh
229 | 2.2
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 | org.slf4j
238 | slf4j-api
239 | 1.6.3
240 | compile
241 |
242 |
243 |
244 | net.sf.trove4j
245 | trove4j
246 | 3.0.3
247 | compile
248 |
249 |
250 |
251 |
252 | ch.qos.logback
253 | logback-classic
254 | 1.2.0
255 | test
256 |
257 |
258 |
259 | ch.qos.logback
260 | logback-core
261 | 1.2.0
262 | test
263 |
264 |
265 |
266 | junit
267 | junit
268 | 4.13.1
269 | test
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 | ossrh
278 | https://oss.sonatype.org/content/repositories/snapshots
279 |
280 |
281 |
282 | ossrh
283 | https://oss.sonatype.org/service/local/staging/deploy/maven2/
284 |
285 |
286 |
289 |
290 |
291 |
295 |
296 |
297 |
301 |
302 |
303 |
304 |
305 |
306 |
307 | jsi.sourceforge.net
308 | scp://shell.sourceforge.net/home/project-web/jsi/htdocs
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 | org.apache.maven.plugins
317 | maven-javadoc-plugin
318 | 2.8
319 |
320 |
321 |
322 |
323 |
324 |
325 | docline-java8-disable
326 |
327 | [1.8,)
328 |
329 |
330 |
331 |
332 |
333 | org.apache.maven.plugins
334 | maven-javadoc-plugin
335 |
336 | -Xdoclint:none
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | [](https://www.travis-ci.org/aled/jsi)
2 |
3 | Overview
4 | --------
5 | The Java Spatial Index project aims to maintain a high performance Java version of the RTree spatial indexing algorithm as described in the 1984 paper "R-trees: A Dynamic Index Structure for Spatial Searching" by Antonin Guttman. (PDF on CiteSeerX)
6 |
7 | The JSI spatial index is deliberately limited in features,
8 | and does a small number of things well. It particular, it is fast.
9 |
10 | The code is open source, and released under the GNU Lesser General Public License, version 2.1 or later.
11 |
12 | Usage
13 | -----
14 | It is highly recommended to start by looking at the jsi-examples repository at https://github.com/aled/jsi-examples.
15 |
16 | Briefly, you need to initialize the RTree like this:
17 |
18 | // Create and initialize an rtree
19 | SpatialIndex si = new RTree();
20 | si.init(null);
21 |
22 | Then add some rectangles; each one has an ID.
23 |
24 | final Rectangle[] rects = new Rectangle[100];
25 | rects[0] = new Rectangle(0, 10, 0, 10);
26 | rects[1] = new Rectangle(0, 11, 1, 20);
27 | si.add(rects[0], 0);
28 | si.add(rects[1], 1);
29 | ...
30 |
31 | and finally query for the 3 nearest rectangles to (36.3, 84.3) by calling the nearestN() method.
32 |
33 | si.nearestN(
34 | new Point(36.3f, 84.3f), // the point for which we want to find nearby rectangles
35 | new TIntProcedure() { // a procedure whose execute() method will be called with the results
36 | public boolean execute(int i) {
37 | log.info("Rectangle " + i + " " + rects[i] + ", distance=" + rects[i].distance(p));
38 | return true; // return true here to continue receiving results
39 | }
40 | },
41 | 3, // the number of nearby rectangles to find
42 | Float.MAX_VALUE // Don't bother searching further than this. MAX_VALUE means search everything
43 | );
44 |
45 | A binary distribution that contains the JSI jar and all the runtime dependencies is available from http://sourceforge.net/projects/jsi/files.
46 |
47 | Alternatively, maven users can use this repository in their pom.xml:
48 |
49 |
50 | jsi.sourceforge.net
51 | sourceforge jsi repository
52 | http://sourceforge.net/projects/jsi/files/m2_repo
53 |
54 |
55 |
56 | net.sourceforge.jsi
57 | jsi
58 | 1.0.0
59 |
60 |
61 | Building
62 | -------
63 | To build the JSI library from source, install maven 3 and run the following:
64 |
65 | % cd
66 | % mvn package
67 |
68 | This will generate the binary package (jsi-x.y.z.jar) in the target subdirectory.
69 |
70 | The following is a list of useful maven targets:
71 |
72 | eclipse:eclipse (generate eclipse project files; see below)
73 | clean
74 | compile
75 | test
76 | -Dtest=ReferenceCompareTest_10000 test
77 | package
78 | site
79 | assembly:single (create package only)
80 | site:deploy
81 | deploy
82 |
83 | To import the project into eclipse, run mvn eclipse:eclipse, and then set the `M2_REPO` variable
84 | in `Window -> Preferences -> Java -> Build Path -> Classpath Variables` to point to your local maven repository (e.g. `~/.m2/repository`)
85 |
86 |
87 | Testing
88 | -------
89 |
90 | These are the steps needed to check that the JSI library is working correctly.
91 | Note this will take a very long time to run:
92 |
93 | % cd
94 | % mvn test [This runs a short and quick test]
95 | % mvn -Dtest=ReferenceCompareTest_1000 test [Long test]
96 | % mvn -Dtest=ReferenceCompareTest_10000 test [Very long test]
97 | % mvn -Dtest=ReferenceCompareTest_100000 test [Ridiculously long test]
98 |
99 | If any errors occur, please raise an issue at https://github.com/aled/jsi/issues
100 |
101 |
--------------------------------------------------------------------------------
/src/main/assembly/with-dependencies-zip.xml:
--------------------------------------------------------------------------------
1 |
4 | with-dependencies
5 |
6 | zip
7 |
8 |
9 |
10 | ${project.basedir}/target/dependencies
11 | /lib
12 |
13 | *.jar
14 |
15 |
16 |
17 | ${project.basedir}/target
18 | /
19 |
20 | *.jar
21 |
22 |
23 |
24 | ${project.basedir}/doc
25 | /
26 |
27 | README.txt
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/main/java/net/sf/jsi/BuildProperties.java:
--------------------------------------------------------------------------------
1 | // BuildProperties.java
2 | // Java Spatial Index Library
3 | // Copyright (C) 2012 Aled Morris
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 |
19 | package net.sf.jsi;
20 |
21 | import java.io.IOException;
22 | import java.util.Properties;
23 |
24 | import org.slf4j.Logger;
25 | import org.slf4j.LoggerFactory;
26 |
27 | /**
28 | * Allows build properties to be retrieved at runtime. Currently, version and
29 | * scmRevisionId are implemented.
30 | */
31 | public class BuildProperties {
32 | private static final Logger log = LoggerFactory.getLogger(BuildProperties.class);
33 | private static final BuildProperties instance = new BuildProperties();
34 |
35 | private String version = null;
36 | private String scmRevisionId = null;
37 |
38 | private BuildProperties() {
39 | Properties p = new Properties();
40 | try {
41 | p.load(getClass().getClassLoader().getResourceAsStream("build.properties"));
42 | version = p.getProperty("version", "");
43 | scmRevisionId = p.getProperty("scmRevisionId", "");
44 | } catch (IOException e) {
45 | log.warn("Unable to read from build.properties");
46 | }
47 | }
48 |
49 | /**
50 | * Version number as specified in pom.xml
51 | */
52 | public static String getVersion() {
53 | return instance.version;
54 | }
55 |
56 |
57 | /**
58 | * SCM revision ID. This is the git commit ID.
59 | */
60 | public static String getScmRevisionId() {
61 | return instance.scmRevisionId;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/net/sf/jsi/Point.java:
--------------------------------------------------------------------------------
1 | // Point.java
2 | // Java Spatial Index Library
3 | // Copyright (C) 2002-2005 Infomatiq Limited.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 |
19 | package net.sf.jsi;
20 |
21 | /**
22 | * Currently hardcoded to 2 dimensions, but could be extended.
23 | */
24 | public class Point {
25 | /**
26 | * The (x, y) coordinates of the point.
27 | */
28 | public float x, y;
29 |
30 | /**
31 | * Constructor.
32 | *
33 | * @param x The x coordinate of the point
34 | * @param y The y coordinate of the point
35 | */
36 | public Point(float x, float y) {
37 | this.x = x;
38 | this.y = y;
39 | }
40 |
41 | /**
42 | * Copy from another point into this one
43 | */
44 | public void set(Point other) {
45 | x = other.x;
46 | y = other.y;
47 | }
48 |
49 | /**
50 | * Print as a string in format "(x, y)"
51 | */
52 | @Override
53 | public String toString() {
54 | return "(" + x + ", " + y + ")";
55 | }
56 |
57 | /**
58 | * @return X coordinate rounded to an int
59 | */
60 | public int xInt() {
61 | return Math.round(x);
62 | }
63 |
64 | /**
65 | * @return Y coordinate rounded to an int
66 | */
67 | public int yInt() {
68 | return Math.round(y);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/main/java/net/sf/jsi/PriorityQueue.java:
--------------------------------------------------------------------------------
1 | // PriorityQueue.java
2 | // Java Spatial Index Library
3 | // Copyright (C) 2008 aled@users.sourceforge.net
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 |
19 | package net.sf.jsi;
20 |
21 | import java.io.Serializable;
22 |
23 | import gnu.trove.list.array.TIntArrayList;
24 | import gnu.trove.list.array.TFloatArrayList;
25 |
26 | /**
27 | *
28 | * Priority Queue that stores values as ints and priorities as floats. Uses a
29 | * Heap to sort the priorities; the values are sorted "in step" with the
30 | * priorities.
31 | *
32 | *
33 | * A Heap is simply an array that is kept semi sorted; in particular if the
34 | * elements of the array are arranged in a tree structure; ie
35 | *
46 | * then each parent is kept sorted with respect to it's immediate children. E.g.
47 | * 00 < 01, 00 < 02, 02 < 05, 02 < 06
48 | *
49 | *
50 | * This means that the array appears to be sorted, as long as we only ever look
51 | * at element 0.
52 | *
53 | *
54 | * Inserting new elements is much faster than if the entire array was kept
55 | * sorted; a new element is appended to the array, and then recursively swapped
56 | * with each parent to maintain the "parent is sorted w.r.t it's children"
57 | * property.
58 | *
59 | *
60 | * To return the "next" value it is necessary to remove the root element. The
61 | * last element in the array is placed in the root of the tree, and is
62 | * recursively swapped with one of it's children until the "parent is sorted
63 | * w.r.t it's children" property is restored.
64 | *
65 | *
66 | * Random access is slow (eg for deleting a particular value), and is not
67 | * implemented here - if this functionality is required, then a heap probably
68 | * isn't the right data structure.
69 | *
70 | */
71 | public class PriorityQueue implements Serializable {
72 | private static final long serialVersionUID = -5653506138757217673L;
73 | public static final boolean SORT_ORDER_ASCENDING = true;
74 | public static final boolean SORT_ORDER_DESCENDING = false;
75 |
76 | private TIntArrayList values = null;
77 | private TFloatArrayList priorities = null;
78 | private boolean sortOrder = SORT_ORDER_ASCENDING;
79 |
80 | private static boolean INTERNAL_CONSISTENCY_CHECKING = false;
81 |
82 | public PriorityQueue(boolean sortOrder) {
83 | this(sortOrder, 10);
84 | }
85 |
86 | public PriorityQueue(boolean sortOrder, int initialCapacity) {
87 | this.sortOrder = sortOrder;
88 | values = new TIntArrayList(initialCapacity);
89 | priorities = new TFloatArrayList(initialCapacity);
90 | }
91 |
92 | /**
93 | * @param p1
94 | * @param p2
95 | * @return true if p1 has an earlier sort order than p2.
96 | */
97 | private boolean sortsEarlierThan(float p1, float p2) {
98 | if (sortOrder == SORT_ORDER_ASCENDING) {
99 | return p1 < p2;
100 | }
101 | return p2 < p1;
102 | }
103 |
104 | // to insert a value, append it to the arrays, then
105 | // reheapify by promoting it to the correct place.
106 | public void insert(int value, float priority) {
107 | values.add(value);
108 | priorities.add(priority);
109 |
110 | promote(values.size() - 1, value, priority);
111 | }
112 |
113 | private void promote(int index, int value, float priority) {
114 | // Consider the index to be a "hole"; i.e. don't swap priorities/values
115 | // when moving up the tree, simply copy the parent into the hole and
116 | // then consider the parent to be the hole.
117 | // Finally, copy the value/priority into the hole.
118 | while (index > 0) {
119 | int parentIndex = (index - 1) / 2;
120 | float parentPriority = priorities.get(parentIndex);
121 |
122 | if (sortsEarlierThan(parentPriority, priority)) {
123 | break;
124 | }
125 |
126 | // copy the parent entry into the current index.
127 | values.set(index, values.get(parentIndex));
128 | priorities.set(index, parentPriority);
129 | index = parentIndex;
130 | }
131 |
132 | values.set(index, value);
133 | priorities.set(index, priority);
134 |
135 | if (INTERNAL_CONSISTENCY_CHECKING) {
136 | check();
137 | }
138 | }
139 |
140 | public int size() {
141 | return values.size();
142 | }
143 |
144 | public void clear() {
145 | values.clear();
146 | priorities.clear();
147 | }
148 |
149 | public void reset() {
150 | values.reset();
151 | priorities.reset();
152 | }
153 |
154 | public int getValue() {
155 | return values.get(0);
156 | }
157 |
158 | public float getPriority() {
159 | return priorities.get(0);
160 | }
161 |
162 | private void demote(int index, int value, float priority) {
163 | int childIndex = (index * 2) + 1; // left child
164 |
165 | while (childIndex < values.size()) {
166 | float childPriority = priorities.get(childIndex);
167 |
168 | if (childIndex + 1 < values.size()) {
169 | float rightPriority = priorities.get(childIndex + 1);
170 | if (sortsEarlierThan(rightPriority, childPriority)) {
171 | childPriority = rightPriority;
172 | childIndex++; // right child
173 | }
174 | }
175 |
176 | if (sortsEarlierThan(childPriority, priority)) {
177 | priorities.set(index, childPriority);
178 | values.set(index, values.get(childIndex));
179 | index = childIndex;
180 | childIndex = (index * 2) + 1;
181 | } else {
182 | break;
183 | }
184 | }
185 |
186 | values.set(index, value);
187 | priorities.set(index, priority);
188 | }
189 |
190 | // get the value with the lowest priority
191 | // creates a "hole" at the root of the tree.
192 | // The algorithm swaps the hole with the appropriate child, until
193 | // the last entry will fit correctly into the hole (ie is lower
194 | // priority than its children)
195 | public int pop() {
196 | int ret = values.get(0);
197 |
198 | // record the value/priority of the last entry
199 | int lastIndex = values.size() - 1;
200 | int tempValue = values.get(lastIndex);
201 | float tempPriority = priorities.get(lastIndex);
202 |
203 | values.removeAt(lastIndex);
204 | priorities.removeAt(lastIndex);
205 |
206 | if (lastIndex > 0) {
207 | demote(0, tempValue, tempPriority);
208 | }
209 |
210 | if (INTERNAL_CONSISTENCY_CHECKING) {
211 | check();
212 | }
213 |
214 | return ret;
215 | }
216 |
217 | public void setSortOrder(boolean sortOrder) {
218 | if (this.sortOrder != sortOrder) {
219 | this.sortOrder = sortOrder;
220 | // reheapify the arrays
221 | for (int i = (values.size() / 2) - 1; i >= 0; i--) {
222 | demote(i, values.get(i), priorities.get(i));
223 | }
224 | }
225 | if (INTERNAL_CONSISTENCY_CHECKING) {
226 | check();
227 | }
228 | }
229 |
230 | private void check() {
231 | // for each entry, check that the child entries have a lower or equal
232 | // priority
233 | int lastIndex = values.size() - 1;
234 |
235 | for (int i = 0; i < values.size() / 2; i++) {
236 | float currentPriority = priorities.get(i);
237 |
238 | int leftIndex = (i * 2) + 1;
239 | if (leftIndex <= lastIndex) {
240 | float leftPriority = priorities.get(leftIndex);
241 | if (sortsEarlierThan(leftPriority, currentPriority)) {
242 | System.err.println("Internal error in PriorityQueue");
243 | }
244 | }
245 |
246 | int rightIndex = (i * 2) + 2;
247 | if (rightIndex <= lastIndex) {
248 | float rightPriority = priorities.get(rightIndex);
249 | if (sortsEarlierThan(rightPriority, currentPriority)) {
250 | System.err.println("Internal error in PriorityQueue");
251 | }
252 | }
253 | }
254 | }
255 | }
256 |
--------------------------------------------------------------------------------
/src/main/java/net/sf/jsi/SpatialIndex.java:
--------------------------------------------------------------------------------
1 | // SpatialIndex.java
2 | // Java Spatial Index Library
3 | // Copyright (C) 2002-2005 Infomatiq Limited.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 |
19 | package net.sf.jsi;
20 |
21 | import gnu.trove.procedure.TIntProcedure;
22 |
23 | import java.util.Properties;
24 |
25 | /**
26 | * Defines methods that must be implemented by all
27 | * spatial indexes. This includes the RTree and its variants.
28 | */
29 | public interface SpatialIndex {
30 |
31 | /**
32 | * Initializes any implementation dependent properties
33 | * of the spatial index. For example, RTree implementations
34 | * will have a NodeSize property.
35 | *
36 | * @param props The set of properties used to initialize the spatial index.
37 | */
38 | public void init(Properties props);
39 |
40 | /**
41 | * Adds a new rectangle to the spatial index
42 | *
43 | * @param r The rectangle to add to the spatial index.
44 | * @param id The ID of the rectangle to add to the spatial index.
45 | * The result of adding more than one rectangle with
46 | * the same ID is undefined.
47 | */
48 | public void add(Rectangle r, int id);
49 |
50 | /**
51 | * Deletes a rectangle from the spatial index
52 | *
53 | * @param r The rectangle to delete from the spatial index
54 | * @param id The ID of the rectangle to delete from the spatial
55 | * index
56 | *
57 | * @return true if the rectangle was deleted
58 | * false if the rectangle was not found, or the
59 | * rectangle was found but with a different ID
60 | */
61 | public boolean delete(Rectangle r, int id);
62 |
63 | /**
64 | * Finds the nearest rectangles to the passed rectangle and calls
65 | * v.execute(id) for each one.
66 | *
67 | * If multiple rectangles are equally near, they will
68 | * all be returned.
69 | *
70 | * @param p The point for which this method finds the
71 | * nearest neighbours.
72 | *
73 | * @param v The IntProcedure whose execute() method is is called
74 | * for each nearest neighbour.
75 | *
76 | * @param furthestDistance The furthest distance away from the rectangle
77 | * to search. Rectangles further than this will not be found.
78 | *
79 | * This should be as small as possible to minimise
80 | * the search time.
81 | *
82 | * Use Float.POSITIVE_INFINITY to guarantee that the nearest rectangle is found,
83 | * no matter how far away, although this will slow down the algorithm.
84 | */
85 | public void nearest(Point p, TIntProcedure v, float furthestDistance);
86 |
87 | /**
88 | * Finds the N nearest rectangles to the passed rectangle, and calls
89 | * execute(id, distance) on each one, in order of increasing distance.
90 | *
91 | * Note that fewer than N rectangles may be found if fewer entries
92 | * exist within the specified furthest distance, or more if rectangles
93 | * N and N+1 have equal distances.
94 | *
95 | * @param p The point for which this method finds the
96 | * nearest neighbours.
97 | *
98 | * @param v The IntfloatProcedure whose execute() method is is called
99 | * for each nearest neighbour.
100 | *
101 | * @param n The desired number of rectangles to find (but note that
102 | * fewer or more may be returned)
103 | *
104 | * @param distance The furthest distance away from the rectangle
105 | * to search. Rectangles further than this will not be found.
106 | *
107 | * This should be as small as possible to minimise
108 | * the search time.
109 | *
110 | * Use Float.POSITIVE_INFINITY to guarantee that the nearest rectangle is found,
111 | * no matter how far away, although this will slow down the algorithm.
112 | */
113 | public void nearestN(Point p, TIntProcedure v, int n, float distance);
114 |
115 | /**
116 | * Same as nearestN, except the found rectangles are not returned
117 | * in sorted order. This will be faster, if sorting is not required
118 | */
119 | public void nearestNUnsorted(Point p, TIntProcedure v, int n, float distance);
120 |
121 | /**
122 | * Finds all rectangles that intersect the passed rectangle.
123 | *
124 | * @param r The rectangle for which this method finds
125 | * intersecting rectangles.
126 | *
127 | * @param ip The IntProcedure whose execute() method is is called
128 | * for each intersecting rectangle.
129 | */
130 | public void intersects(Rectangle r, TIntProcedure ip);
131 |
132 | /**
133 | * Finds all rectangles contained by the passed rectangle.
134 | *
135 | * @param r The rectangle for which this method finds
136 | * contained rectangles.
137 | *
138 | * @param ip The procedure whose visit() method is is called
139 | * for each contained rectangle.
140 | */
141 | public void contains(Rectangle r, TIntProcedure ip);
142 |
143 | /**
144 | * Returns the number of entries in the spatial index
145 | */
146 | public int size();
147 |
148 |
149 | /**
150 | * Returns the bounds of all the entries in the spatial index,
151 | * or null if there are no entries.
152 | */
153 | public Rectangle getBounds();
154 |
155 | /**
156 | * Returns a string identifying the type of
157 | * spatial index, and the version number,
158 | * eg "SimpleIndex-0.1"
159 | */
160 | public String getVersion();
161 |
162 | }
163 |
--------------------------------------------------------------------------------
/src/main/java/net/sf/jsi/rtree/Node.java:
--------------------------------------------------------------------------------
1 | // Node.java
2 | // Java Spatial Index Library
3 | // Copyright (C) 2002-2005 Infomatiq Limited
4 | // Copyright (C) 2008-2010 aled@users.sourceforge.net
5 | //
6 | // This library is free software; you can redistribute it and/or
7 | // modify it under the terms of the GNU Lesser General Public
8 | // License as published by the Free Software Foundation; either
9 | // version 2.1 of the License, or (at your option) any later version.
10 | //
11 | // This library is distributed in the hope that it will be useful,
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | // Lesser General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU Lesser General Public
17 | // License along with this library; if not, write to the Free Software
18 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 |
20 | package net.sf.jsi.rtree;
21 |
22 | import java.io.Serializable;
23 |
24 | /**
25 | *
Used by RTree. There are no public methods in this class.
26 | */
27 | public class Node implements Serializable {
28 | private static final long serialVersionUID = -2823316966528817396L;
29 | int nodeId = 0;
30 | float mbrMinX = Float.MAX_VALUE;
31 | float mbrMinY = Float.MAX_VALUE;
32 | float mbrMaxX = -Float.MAX_VALUE;
33 | float mbrMaxY = -Float.MAX_VALUE;
34 |
35 | float[] entriesMinX = null;
36 | float[] entriesMinY = null;
37 | float[] entriesMaxX = null;
38 | float[] entriesMaxY = null;
39 |
40 | int[] ids = null;
41 | int level;
42 | int entryCount;
43 |
44 | Node(int nodeId, int level, int maxNodeEntries) {
45 | this.nodeId = nodeId;
46 | this.level = level;
47 | entriesMinX = new float[maxNodeEntries];
48 | entriesMinY = new float[maxNodeEntries];
49 | entriesMaxX = new float[maxNodeEntries];
50 | entriesMaxY = new float[maxNodeEntries];
51 | ids = new int[maxNodeEntries];
52 | }
53 |
54 | void addEntry(float minX, float minY, float maxX, float maxY, int id) {
55 | ids[entryCount] = id;
56 | entriesMinX[entryCount] = minX;
57 | entriesMinY[entryCount] = minY;
58 | entriesMaxX[entryCount] = maxX;
59 | entriesMaxY[entryCount] = maxY;
60 |
61 | if (minX < mbrMinX) mbrMinX = minX;
62 | if (minY < mbrMinY) mbrMinY = minY;
63 | if (maxX > mbrMaxX) mbrMaxX = maxX;
64 | if (maxY > mbrMaxY) mbrMaxY = maxY;
65 |
66 | entryCount++;
67 | }
68 |
69 | // Return the index of the found entry, or -1 if not found
70 | int findEntry(float minX, float minY, float maxX, float maxY, int id) {
71 | for (int i = 0; i < entryCount; i++) {
72 | if (id == ids[i] &&
73 | entriesMinX[i] == minX && entriesMinY[i] == minY &&
74 | entriesMaxX[i] == maxX && entriesMaxY[i] == maxY) {
75 | return i;
76 | }
77 | }
78 | return -1;
79 | }
80 |
81 | // delete entry. This is done by setting it to null and copying the last entry into its space.
82 | void deleteEntry(int i) {
83 | int lastIndex = entryCount - 1;
84 | float deletedMinX = entriesMinX[i];
85 | float deletedMinY = entriesMinY[i];
86 | float deletedMaxX = entriesMaxX[i];
87 | float deletedMaxY = entriesMaxY[i];
88 |
89 | if (i != lastIndex) {
90 | entriesMinX[i] = entriesMinX[lastIndex];
91 | entriesMinY[i] = entriesMinY[lastIndex];
92 | entriesMaxX[i] = entriesMaxX[lastIndex];
93 | entriesMaxY[i] = entriesMaxY[lastIndex];
94 | ids[i] = ids[lastIndex];
95 | }
96 | entryCount--;
97 |
98 | // adjust the MBR
99 | recalculateMBRIfInfluencedBy(deletedMinX, deletedMinY, deletedMaxX, deletedMaxY);
100 | }
101 |
102 | // deletedMin/MaxX/Y is a rectangle that has just been deleted or made smaller.
103 | // Thus, the MBR is only recalculated if the deleted rectangle influenced the old MBR
104 | void recalculateMBRIfInfluencedBy(float deletedMinX, float deletedMinY, float deletedMaxX, float deletedMaxY) {
105 | if (mbrMinX == deletedMinX || mbrMinY == deletedMinY || mbrMaxX == deletedMaxX || mbrMaxY == deletedMaxY) {
106 | recalculateMBR();
107 | }
108 | }
109 |
110 | void recalculateMBR() {
111 | mbrMinX = entriesMinX[0];
112 | mbrMinY = entriesMinY[0];
113 | mbrMaxX = entriesMaxX[0];
114 | mbrMaxY = entriesMaxY[0];
115 |
116 | for (int i = 1; i < entryCount; i++) {
117 | if (entriesMinX[i] < mbrMinX) mbrMinX = entriesMinX[i];
118 | if (entriesMinY[i] < mbrMinY) mbrMinY = entriesMinY[i];
119 | if (entriesMaxX[i] > mbrMaxX) mbrMaxX = entriesMaxX[i];
120 | if (entriesMaxY[i] > mbrMaxY) mbrMaxY = entriesMaxY[i];
121 | }
122 | }
123 |
124 | /**
125 | * eliminate null entries, move all entries to the start of the source node
126 | */
127 | void reorganize(RTree rtree) {
128 | int countdownIndex = rtree.maxNodeEntries - 1;
129 | for (int index = 0; index < entryCount; index++) {
130 | if (ids[index] == -1) {
131 | while (ids[countdownIndex] == -1 && countdownIndex > index) {
132 | countdownIndex--;
133 | }
134 | entriesMinX[index] = entriesMinX[countdownIndex];
135 | entriesMinY[index] = entriesMinY[countdownIndex];
136 | entriesMaxX[index] = entriesMaxX[countdownIndex];
137 | entriesMaxY[index] = entriesMaxY[countdownIndex];
138 | ids[index] = ids[countdownIndex];
139 | ids[countdownIndex] = -1;
140 | }
141 | }
142 | }
143 |
144 | public int getEntryCount() {
145 | return entryCount;
146 | }
147 |
148 | public int getId(int index) {
149 | if (index < entryCount) {
150 | return ids[index];
151 | }
152 | return -1;
153 | }
154 |
155 | boolean isLeaf() {
156 | return (level == 1);
157 | }
158 |
159 | public int getLevel() {
160 | return level;
161 | }
162 | }
163 |
--------------------------------------------------------------------------------
/src/main/java/net/sf/jsi/rtree/SortedList.java:
--------------------------------------------------------------------------------
1 | // SortedList.java
2 | // Java Spatial Index Library
3 | // Copyright (C) 2002-2005 Infomatiq Limited.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 |
19 | package net.sf.jsi.rtree;
20 |
21 | import java.io.Serializable;
22 |
23 | import gnu.trove.list.array.TFloatArrayList;
24 | import gnu.trove.list.array.TIntArrayList;
25 | import gnu.trove.procedure.TIntProcedure;
26 |
27 | /**
28 | *
29 | * Sorted List, backed by a TArrayList.
30 | *
31 | * The elements in the list are always ordered by priority.
32 | * Methods exists to remove elements with the highest and lowest priorities.
33 | *
34 | * If more than one element has the highest priority, they will
35 | * all be removed by calling removeHighest. Ditto for the lowest priority.
36 | *
37 | * The list has a preferred maximum size. If possible, entries with the lowest priority
38 | * will be removed to limit the maximum size. Note that entries with the lowest priority
39 | * will not be removed if this would leave fewer than the preferred maximum number
40 | * of entries.
41 | *
42 | * This class is not optimised for large values of preferredMaximumSize. Values greater than,
43 | * say, 5, are not recommended.
44 | *
45 | */
46 | public class SortedList implements Serializable {
47 | private static final long serialVersionUID = -1549539544212731131L;
48 |
49 | private static final int DEFAULT_PREFERRED_MAXIMUM_SIZE = 10;
50 |
51 | private int preferredMaximumSize = 1;
52 | private TIntArrayList ids = null;
53 | private TFloatArrayList priorities = null;
54 |
55 | public void init(int preferredMaximumSize) {
56 | this.preferredMaximumSize = preferredMaximumSize;
57 | ids.clear(preferredMaximumSize);
58 | priorities.clear(preferredMaximumSize);
59 | }
60 |
61 | public void reset() {
62 | ids.reset();
63 | priorities.reset();
64 | }
65 |
66 | public SortedList() {
67 | ids = new TIntArrayList(DEFAULT_PREFERRED_MAXIMUM_SIZE);
68 | priorities = new TFloatArrayList(DEFAULT_PREFERRED_MAXIMUM_SIZE);
69 | }
70 |
71 | public void add(int id, float priority) {
72 | float lowestPriority = Float.NEGATIVE_INFINITY;
73 |
74 | if (priorities.size() > 0) {
75 | lowestPriority = priorities.get(priorities.size() - 1);
76 | }
77 |
78 | if ((priority == lowestPriority) ||
79 | (priority < lowestPriority && ids.size() < preferredMaximumSize)) {
80 | // simply add the new entry at the lowest priority end
81 | ids.add(id);
82 | priorities.add(priority);
83 | } else if (priority > lowestPriority) {
84 | if (ids.size() >= preferredMaximumSize) {
85 | int lowestPriorityIndex = ids.size() - 1;
86 | while ((lowestPriorityIndex - 1 >= 0) &&
87 | (priorities.get(lowestPriorityIndex - 1) == lowestPriority)) {
88 | lowestPriorityIndex--;
89 | }
90 |
91 | if (lowestPriorityIndex >= preferredMaximumSize - 1) {
92 | ids.remove(lowestPriorityIndex, ids.size() - lowestPriorityIndex);
93 | priorities.remove(lowestPriorityIndex, priorities.size() - lowestPriorityIndex);
94 | }
95 | }
96 |
97 | // put the new entry in the correct position. Could do a binary search here if the
98 | // preferredMaximumSize was large.
99 | int insertPosition = ids.size();
100 | while (insertPosition - 1 >= 0 && priority > priorities.get(insertPosition - 1)) {
101 | insertPosition--;
102 | }
103 |
104 | ids.insert(insertPosition, id);
105 | priorities.insert(insertPosition, priority);
106 | }
107 | }
108 |
109 | /**
110 | * return the lowest priority currently stored, or float.NEGATIVE_INFINITY if no
111 | * entries are stored
112 | */
113 | public float getLowestPriority() {
114 | float lowestPriority = Float.NEGATIVE_INFINITY;
115 | if (priorities.size() >= preferredMaximumSize) {
116 | lowestPriority = priorities.get(priorities.size() - 1);
117 | }
118 | return lowestPriority;
119 | }
120 |
121 | public void forEachId(TIntProcedure v) {
122 | for (int i = 0; i < ids.size(); i++) {
123 | if (!v.execute(ids.get(i))) {
124 | break;
125 | }
126 | }
127 | }
128 |
129 | public int[] toNativeArray() {
130 | return ids.toArray();
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/src/main/resources/build.properties:
--------------------------------------------------------------------------------
1 | # standard maven properties
2 | version=${version}
3 |
4 | # the scm revision id is set using the environment variable BUILD_VCS_NUMBER, which is set by teamcity.
5 | scmRevisionId=${env.BUILD_VCS_NUMBER}
6 |
--------------------------------------------------------------------------------
/src/site/site.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | org.apache.maven.skins
5 | maven-default-skin
6 | 1.1
7 |
8 |
9 |
10 | JSI (Java Spatial Index) RTree Library
11 | http://web.sourceforge.net/home/project-web/jsi/htdocs
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/site/xdoc/index.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Aled Morris
4 | JSI (Java Spatial Index) RTree Library
5 |
6 |
7 |
8 |
The Java Spatial Index project aims to maintain a high performance Java version of the RTree spatial indexing algorithm.
9 | as described in the 1984 paper "R-trees: A Dynamic Index Structure for Spatial Searching" by Antonin Guttman.
10 | (PDF on CiteSeerX)
The JSI spatial index is deliberately limited in features,
21 | and does a small number of things well. It particular, it is fast. On a test
22 | machine, it takes about 500ms to add 10,000 entries
23 | to the spatial index. By comparison, an alternative implementation (that seems
24 | to be unmaintained now) takes over 6000ms (but it has more features).
25 |
The source is hosted at github, at http://github.com/aled/jsi. Feel
34 | free to send pull requests. To build the source or run tests, you will need maven 3 installed
35 | and a working internet connection. Note that the CVS and SVN repositories on sourceforge are well out of date.
36 |
54 | YourKit is kindly supporting open source projects with its full-featured Java Profiler.
55 | YourKit, LLC is the creator of innovative and intelligent tools for profiling
56 | Java and .NET applications. Take a look at YourKit's leading software products:
57 | YourKit Java Profiler and
58 | YourKit .NET Profiler."
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/src/test/java/net/sf/jsi/DeleteAllEntriesTest.java:
--------------------------------------------------------------------------------
1 | // DeleteAllEntriesTest.java
2 | // Java Spatial Index Library
3 | // Copyright (C) 2010 aled@users.sourceforge.net
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 |
19 | package net.sf.jsi;
20 |
21 | import gnu.trove.procedure.TIntProcedure;
22 |
23 | import java.util.Properties;
24 | import java.util.Random;
25 |
26 | import junit.framework.TestCase;
27 |
28 | import net.sf.jsi.rtree.RTree;
29 |
30 | public class DeleteAllEntriesTest extends TestCase {
31 |
32 | Rectangle[] rects = null;
33 |
34 | class Counter implements TIntProcedure {
35 | public int count = 0;
36 | public boolean execute(int arg0) {
37 | count++;
38 | return true;
39 | }
40 | };
41 |
42 | public DeleteAllEntriesTest(String name) {
43 | super(name);
44 | }
45 |
46 | public void testDeleteAllEntries() {
47 | System.out.println("testDeleteAllEntries");
48 |
49 | int numRects = 500;
50 |
51 | rects = new Rectangle[numRects];
52 | Random r = new Random();
53 | r.setSeed(0);
54 | for (int i = 0; i < numRects; i+=1) {
55 | rects[i] = new Rectangle(r.nextFloat(), r.nextFloat(), r.nextFloat(), r.nextFloat());
56 | }
57 |
58 | run(1, 2, numRects);
59 | run(1, 3, numRects);
60 | run(2, 4, numRects);
61 | run(2, 5, numRects);
62 | run(2, 6, numRects);
63 | }
64 |
65 | private void run(int minNodeEntries, int maxNodeEntries, int numRects) {
66 | Properties p = new Properties();
67 | p.setProperty("MinNodeEntries", Integer.toString(minNodeEntries));
68 | p.setProperty("MaxNodeEntries", Integer.toString(maxNodeEntries));
69 | RTree rtree = (RTree) SpatialIndexFactory.newInstance("rtree.RTree", p);
70 |
71 | for (int i = 0; i <= numRects; i+=100) {
72 | // add some entries
73 | for (int j = 0; j < i; j++) {
74 | rtree.add(rects[j], j);
75 | }
76 | assertTrue(rtree.checkConsistency());
77 |
78 | // now delete them all
79 | for (int j = 0; j < i; j++) {
80 | rtree.delete(rects[j], j);
81 | }
82 | assertTrue(rtree.size() == 0);
83 | assertTrue(rtree.checkConsistency());
84 |
85 | // check that we can make queries on an empty rtree without error.
86 | Rectangle testRect = new Rectangle(1,2,3,4);
87 | Point testPoint = new Point(1,2);
88 |
89 | Counter counter = new Counter();
90 | rtree.intersects(testRect, counter);
91 | assertTrue(counter.count == 0);
92 |
93 | rtree.nearest(testPoint, counter, Float.MAX_VALUE);
94 | assertTrue(counter.count == 0);
95 |
96 | rtree.nearestN(testPoint, counter, 10, Float.MAX_VALUE);
97 | assertTrue(counter.count == 0);
98 |
99 | rtree.nearestNUnsorted(testPoint, counter, 10, Float.MAX_VALUE);
100 | assertTrue(counter.count == 0);
101 |
102 | rtree.contains(testRect, counter);
103 | assertTrue(counter.count == 0);
104 | }
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/src/test/java/net/sf/jsi/ListDecorator.java:
--------------------------------------------------------------------------------
1 | // ListDecorator.java
2 | // Java Spatial Index Library
3 | // Copyright (C) 2002-2005 Infomatiq Limited.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 |
19 | package net.sf.jsi;
20 |
21 | import gnu.trove.procedure.TIntProcedure;
22 |
23 | import java.util.ArrayList;
24 | import java.util.List;
25 |
26 | /**
27 | * ListDecorator
28 | */
29 | public class ListDecorator {
30 | SpatialIndex m_si = null;
31 |
32 | public ListDecorator(SpatialIndex si) {
33 | m_si = si;
34 | }
35 |
36 | class AddToListProcedure implements TIntProcedure {
37 | private List m_list = new ArrayList();
38 |
39 | public boolean execute(int id) {
40 | m_list.add(new Integer(id));
41 | return true;
42 | }
43 |
44 | public List getList() {
45 | return m_list;
46 | }
47 | }
48 |
49 | /**
50 | * Finds all rectangles that are nearest to the passed
51 | * rectangle.
52 | *
53 | * @param p The p point which this method finds
54 | * the nearest neighbours.
55 | *
56 | * @return List of IDs of rectangles that are nearest
57 | * to the passed rectangle, ordered by distance (nearest first).
58 | */
59 | public List nearest(Point p, float furthestDistance) {
60 | AddToListProcedure v = new AddToListProcedure();
61 | m_si.nearest(p, v, furthestDistance);
62 | return v.getList();
63 | }
64 |
65 | /**
66 | * Finds all rectangles that are nearest to the passed
67 | * rectangle.
68 | *
69 | * @param p The p point which this method finds
70 | * the nearest neighbours.
71 | *
72 | * @return List of IDs of rectangles that are nearest
73 | * to the passed rectangle, ordered by distance (nearest first).
74 | * If multiple rectangles have the same distance, order by ID.
75 | */
76 | public List nearestN(Point p, int maxCount, float furthestDistance) {
77 | AddToListProcedure v = new AddToListProcedure();
78 | m_si.nearestN(p, v, maxCount, furthestDistance);
79 | return v.getList();
80 | }
81 |
82 | /**
83 | * Finds all rectangles that intersect the passed rectangle.
84 | *
85 | * @param r The rectangle for which this method finds
86 | * intersecting rectangles.
87 | *
88 | * @return List of IDs of rectangles that intersect the passed
89 | * rectangle.
90 | */
91 | public List intersects(Rectangle r) {
92 | AddToListProcedure v = new AddToListProcedure();
93 | m_si.intersects(r, v);
94 | return v.getList();
95 | }
96 |
97 | /**
98 | * Finds all rectangles contained by the passed rectangle.
99 | *
100 | * @param r The rectangle for which this method finds
101 | * contained rectangles.
102 | *
103 | * @return Collection of IDs of rectangles that are contained by the
104 | * passed rectangle.
105 | */
106 | public List contains(Rectangle r) {
107 | AddToListProcedure v = new AddToListProcedure();
108 | m_si.contains(r, v);
109 | return v.getList();
110 | }
111 |
112 | }
113 |
--------------------------------------------------------------------------------
/src/test/java/net/sf/jsi/MoveEntriesTest.java:
--------------------------------------------------------------------------------
1 | // MoveEntriesTest.java
2 | // Java Spatial Index Library
3 | // Copyright (C) 2011 Aled Morris
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 |
19 | package net.sf.jsi;
20 |
21 | import java.util.Properties;
22 | import java.util.Random;
23 |
24 | import net.sf.jsi.Rectangle;
25 | import net.sf.jsi.rtree.RTree;
26 |
27 | import junit.framework.TestCase;
28 |
29 | public class MoveEntriesTest extends TestCase {
30 |
31 | Random r = new Random();
32 |
33 | public MoveEntriesTest(String name) {
34 | super(name);
35 | r.setSeed(0);
36 | }
37 |
38 | private Rectangle nextRect() {
39 | return new Rectangle(r.nextInt(100), r.nextInt(100), r.nextInt(100), r.nextInt(100));
40 | }
41 |
42 | public void testMoveEntries() {
43 | run(4, 50, 4, 10);
44 | }
45 |
46 | private void run(int minNodeEntries, int maxNodeEntries, int numRects, int numMoves) {
47 | Properties p = new Properties();
48 | p.setProperty("MinNodeEntries", Integer.toString(minNodeEntries));
49 | p.setProperty("MaxNodeEntries", Integer.toString(maxNodeEntries));
50 | RTree rtree = (RTree) SpatialIndexFactory.newInstance("rtree.RTree", p);
51 |
52 | Rectangle[] rects = new Rectangle[numRects];
53 |
54 | // first add the rects
55 | for (int i = 0; i < numRects; i++) {
56 | rects[i] = nextRect();
57 | rtree.add(rects[i], i);
58 | }
59 |
60 | // now move each one in turn
61 | for (int move = 0; move < numMoves; move++) {
62 | for (int i = 0; i < numRects; i++) {
63 | rtree.delete(rects[i], i);
64 | rects[i].set(nextRect());
65 | rtree.add(rects[i], i);
66 | assertTrue(rtree.checkConsistency());
67 | }
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/test/java/net/sf/jsi/NullIndex.java:
--------------------------------------------------------------------------------
1 | // NullIndex.java
2 | // Java Spatial Index Library
3 | // Copyright (C) 2002-2005 Infomatiq Limited.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 |
19 | package net.sf.jsi;
20 |
21 | import gnu.trove.procedure.TIntProcedure;
22 |
23 | import java.util.Properties;
24 |
25 | /**
26 | * An implementation of SpatialIndex that does absolutely nothing.
27 | * The purpose of this class is to measure the overhead of the
28 | * testing framework.
29 | */
30 | public class NullIndex implements SpatialIndex {
31 |
32 | /**
33 | * @see net.sf.jsi.SpatialIndex#init(Properties)
34 | */
35 | public void init(Properties props) {
36 | }
37 |
38 | /**
39 | * @see net.sf.jsi.SpatialIndex#nearest(Point, gnu.trove.TIntProcedure, float)
40 | */
41 | public void nearest(Point p, TIntProcedure v, float distance) {
42 | }
43 |
44 | /**
45 | * @see net.sf.jsi.SpatialIndex#nearestN(Point, gnu.trove.TIntProcedure, int, float)
46 | */
47 | public void nearestN(Point p, TIntProcedure v, int n, float distance) {
48 | }
49 |
50 | /**
51 | * @see net.sf.jsi.SpatialIndex#nearestNUnsorted(Point, gnu.trove.TIntProcedure, int, float)
52 | */
53 | public void nearestNUnsorted(Point p, TIntProcedure v, int n, float distance) {
54 | }
55 |
56 | /**
57 | * @see net.sf.jsi.SpatialIndex#intersects(Rectangle, gnu.trove.TIntProcedure)
58 | */
59 | public void intersects(Rectangle r, TIntProcedure ip) {
60 | }
61 |
62 | /**
63 | * @see net.sf.jsi.SpatialIndex#contains(Rectangle, gnu.trove.TIntProcedure)
64 | */
65 | public void contains(Rectangle r, TIntProcedure ip) {
66 | }
67 |
68 | /**
69 | * @see net.sf.jsi.SpatialIndex#add(Rectangle, int)
70 | */
71 | public void add(Rectangle r, int id) {
72 | }
73 |
74 | /**
75 | * @see net.sf.jsi.SpatialIndex#delete(Rectangle, int)
76 | */
77 | public boolean delete(Rectangle r, int id) {
78 | return false;
79 | }
80 |
81 | /**
82 | * @see net.sf.jsi.SpatialIndex#size()
83 | */
84 | public int size() {
85 | return 0;
86 | }
87 |
88 | /**
89 | * @see net.sf.jsi.SpatialIndex#getBounds()
90 | */
91 | public Rectangle getBounds() {
92 | return null;
93 | }
94 |
95 | /**
96 | * @see net.sf.jsi.SpatialIndex#getVersion()
97 | */
98 | public String getVersion() {
99 | return "NullIndex-" + BuildProperties.getVersion();
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/test/java/net/sf/jsi/PerformanceTest.java:
--------------------------------------------------------------------------------
1 | // PerformanceTest.java
2 | // Java Spatial Index Library
3 | // Copyright (C) 2002-2005 Infomatiq Limited.
4 | // Copyright (C) 2013 Aled Morris
5 | //
6 | //
7 | // This library is free software; you can redistribute it and/or
8 | // modify it under the terms of the GNU Lesser General Public
9 | // License as published by the Free Software Foundation; either
10 | // version 2.1 of the License, or (at your option) any later version.
11 | //
12 | // This library is distributed in the hope that it will be useful,
13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | // Lesser General Public License for more details.
16 | //
17 | // You should have received a copy of the GNU Lesser General Public
18 | // License along with this library; if not, write to the Free Software
19 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 |
21 | package net.sf.jsi;
22 |
23 | import java.util.Properties;
24 | import java.util.Random;
25 | import java.util.concurrent.ExecutorService;
26 | import java.util.concurrent.Executors;
27 | import java.util.concurrent.TimeUnit;
28 |
29 | import net.sf.jsi.rtree.RTree;
30 | import gnu.trove.procedure.TIntProcedure;
31 |
32 | import org.junit.Test;
33 | import org.slf4j.Logger;
34 | import org.slf4j.LoggerFactory;
35 |
36 | /**
37 | * PerformanceTest
38 | *
39 | * Generates results used for comparing the performance of the Java Spatial
40 | * Index library against alternative implementations.
41 | *
42 | * The idea is for the raw data to be imported into a database, and results
43 | * extracted from that.
44 | *
45 | * This test requires 1024M memory (i.e. use -Xmx1024M)
46 | */
47 | public class PerformanceTest {
48 |
49 | private static final Logger log = LoggerFactory.getLogger(PerformanceTest.class);
50 | private SpatialIndex si;
51 |
52 | private float randomFloat(Random r, float min, float max) {
53 | return (r.nextFloat() * (max - min)) + min;
54 | }
55 |
56 | protected Point randomPoint(Random r) {
57 | return new Point(randomFloat(r, 0, 100), randomFloat(r, 0, 100));
58 | }
59 |
60 | private Rectangle randomRectangle(Random r, float size) {
61 | float x = randomFloat(r, 0, 100);
62 | float y = randomFloat(r, 0, 100);
63 | return new Rectangle(x, y, x + randomFloat(r, 0, size), y + randomFloat(r, 0, size));
64 | }
65 |
66 | abstract class Operation {
67 | private final int count[] = new int[1];
68 | private String description;
69 | public Random r;
70 |
71 | public Operation(String description, Random r) {
72 | this.description = description;
73 | this.r = r;
74 | }
75 |
76 | protected TIntProcedure countProc = new TIntProcedure() {
77 | public boolean execute(int value) {
78 | count[0]++;
79 | return true;
80 | }
81 | };
82 |
83 | public int callbackCount() {
84 | return count[0];
85 | }
86 |
87 | public String getDescription() {
88 | return description;
89 | }
90 |
91 | abstract void execute(SpatialIndex si, Random r);
92 | }
93 |
94 | private void benchmark(Operation o, int repetitions) {
95 | long duration = 0;
96 | long startTime = System.nanoTime();
97 | for (int j = 0; j < repetitions; j++) o.execute(si, o.r);
98 | duration += (System.nanoTime() - startTime);
99 |
100 | log.info(o.getDescription() + ", " +
101 | "avg callbacks = " + ((float) o.callbackCount() / repetitions) + ", " +
102 | "avg time = " + (duration / repetitions) + " ns");
103 | }
104 |
105 | /**
106 | * First attempt at a benchmark
107 | */
108 | @Test
109 | public void benchmark_1() {
110 | Random rand = new Random(0);
111 | Properties p = new Properties();
112 | p.setProperty("MinNodeEntries", "20");
113 | p.setProperty("MaxNodeEntries", "50");
114 | si = new RTree();
115 | si.init(p);
116 |
117 | final int rectangleCount = 1000000;
118 | final Rectangle[] rects = new Rectangle[rectangleCount];
119 | for (int i = 0; i < rectangleCount; i++) {
120 | rects[i] = randomRectangle(rand, 0.01f);
121 | }
122 |
123 | long duration;
124 | long startTime;
125 |
126 | for (int j = 0; j < 5; j++) {
127 | duration = 0;
128 | startTime = System.nanoTime();
129 | for (int i = 0; i < rectangleCount; i++) {
130 | si.add(rects[i], i);
131 | }
132 | duration += (System.nanoTime() - startTime);
133 | log.info("add " + rectangleCount + " avg tme = " + (duration / rectangleCount) + " ns");
134 |
135 | if (j == 4) break; // don't do the delete on the last iteration
136 |
137 | duration = 0;
138 | startTime = System.nanoTime();
139 | for (int i = 0; i < rectangleCount; i++) {
140 | si.delete(rects[i], i);
141 | }
142 | duration += (System.nanoTime() - startTime);
143 | log.info("delete " + rectangleCount + " avg tme = " + (duration / rectangleCount) + " ns");
144 | }
145 |
146 | ExecutorService exec = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
147 | try {
148 | for (int i = 0; i < 100; i++) {
149 | exec.submit(new Runnable() {public void run() {benchmark(new Operation("nearest", new Random(0)) {void execute(SpatialIndex si, Random r) {si.nearest(randomPoint(r), countProc, 0.1f);}}, 100); }});
150 | exec.submit(new Runnable() {public void run() {benchmark(new Operation("nearestNUnsorted", new Random(0)) {void execute(SpatialIndex si, Random r) {si.nearestNUnsorted(randomPoint(r), countProc, 10, 0.16f);}}, 100); }});
151 | exec.submit(new Runnable() {public void run() {benchmark(new Operation("nearestN", new Random(0)) {void execute(SpatialIndex si, Random r) {si.nearestN(randomPoint(r), countProc, 10, 0.16f);}}, 100); }});
152 | exec.submit(new Runnable() {public void run() {benchmark(new Operation("intersects", new Random(0)) {void execute(SpatialIndex si, Random r) {si.intersects(randomRectangle(r, 0.6f), countProc);}}, 100); }});
153 | exec.submit(new Runnable() {public void run() {benchmark(new Operation("contains", new Random(0)) {void execute(SpatialIndex si, Random r) {si.contains(randomRectangle(r, 0.65f), countProc);}}, 100); }});
154 | }
155 | try { exec.awaitTermination(1, TimeUnit.DAYS); } catch (Exception e) {}
156 | }
157 | finally {
158 | exec.shutdown();
159 | }
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/src/test/java/net/sf/jsi/RTreeWrapper.java:
--------------------------------------------------------------------------------
1 | // RTreeWrapper.java
2 | // Java Spatial Index Library
3 | // Copyright (C) 2002-2005 Infomatiq Limited.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 |
19 | package net.sf.jsi;
20 |
21 | import gnu.trove.procedure.TIntProcedure;
22 |
23 | import java.util.Properties;
24 |
25 | import net.sf.jsi.rtree.RTree;
26 |
27 | /**
28 | * A completely useless wrapper class for the RTree class.
29 | *
30 | * Actually the point to introduce the same overhead as
31 | * the SILWrapper class, so that performance comparisons
32 | * can be made.
33 | */
34 | public class RTreeWrapper implements SpatialIndex {
35 | private RTree tree;
36 |
37 | class IntProcedure2 implements TIntProcedure {
38 | private TIntProcedure m_intProcedure = null;
39 |
40 | public IntProcedure2(TIntProcedure ip) {
41 | m_intProcedure = ip;
42 | }
43 |
44 | public boolean execute(int i) {
45 | return m_intProcedure.execute(i);
46 | }
47 | }
48 |
49 | /**
50 | * @see net.sf.jsi.SpatialIndex#init(Properties)
51 | */
52 | public void init(Properties props) {
53 | // create a memory-based storage manager
54 |
55 | tree = new RTree();
56 | tree.init(props);
57 | }
58 |
59 | /**
60 | * @see net.sf.jsi.SpatialIndex#nearest(Point, gnu.trove.TIntProcedure, float)
61 | */
62 | public void nearest(Point p, TIntProcedure v, float furthestDistance) {
63 | tree.nearest(new Point(p.x, p.y),
64 | new IntProcedure2(v),
65 | Float.POSITIVE_INFINITY);
66 | }
67 |
68 | /**
69 | * @see net.sf.jsi.SpatialIndex#nearestN(Point, gnu.trove.TIntProcedure, int, float)
70 | */
71 | public void nearestN(Point p, TIntProcedure v, int n, float furthestDistance) {
72 | tree.nearestN(new Point(p.x, p.y),
73 | new IntProcedure2(v),
74 | n,
75 | furthestDistance);
76 | }
77 |
78 | /**
79 | * @see net.sf.jsi.SpatialIndex#nearestNUnsorted(Point, gnu.trove.TIntProcedure, int, float)
80 | */
81 | public void nearestNUnsorted(Point p, TIntProcedure v, int n, float furthestDistance) {
82 | tree.nearestNUnsorted(new Point(p.x, p.y),
83 | new IntProcedure2(v),
84 | n,
85 | furthestDistance);
86 | }
87 |
88 | /**
89 | * @see net.sf.jsi.SpatialIndex#intersects(Rectangle, gnu.trove.TIntProcedure)
90 | */
91 | public void intersects(Rectangle r, TIntProcedure ip) {
92 | Rectangle r2 = new Rectangle(r.minX, r.minY, r.maxX, r.maxY);
93 | tree.intersects(r2, new IntProcedure2(ip));
94 | }
95 |
96 | /**
97 | * @see net.sf.jsi.SpatialIndex#contains(Rectangle, gnu.trove.TIntProcedure)
98 | */
99 | public void contains(Rectangle r, TIntProcedure ip) {
100 | Rectangle r2 = new Rectangle(r.minX, r.minY, r.maxX, r.maxY);
101 | tree.contains(r2, new IntProcedure2(ip));
102 | }
103 |
104 | /**
105 | * @see net.sf.jsi.SpatialIndex#add(Rectangle, int)
106 | */
107 | public void add(Rectangle r, int id) {
108 | Rectangle r2 = new Rectangle(r.minX, r.minY, r.maxX, r.maxY);
109 | tree.add(r2, id);
110 | }
111 |
112 | /**
113 | * @see net.sf.jsi.SpatialIndex#delete(Rectangle, int)
114 | */
115 | public boolean delete(Rectangle r, int id) {
116 | Rectangle r2 = new Rectangle(r.minX, r.minY, r.maxX, r.maxY);
117 | return tree.delete(r2, id);
118 | }
119 |
120 | /**
121 | * @see net.sf.jsi.SpatialIndex#size()
122 | */
123 | public int size() {
124 | return tree.size();
125 | }
126 |
127 | /**
128 | * @see net.sf.jsi.SpatialIndex#getBounds()
129 | */
130 | public Rectangle getBounds() {
131 | return tree.getBounds();
132 | }
133 |
134 | /**
135 | * @see net.sf.jsi.SpatialIndex#getVersion()
136 | */
137 | public String getVersion() {
138 | return "RTreeWrapper-" + BuildProperties.getVersion();
139 | }
140 |
141 | }
142 |
--------------------------------------------------------------------------------
/src/test/java/net/sf/jsi/RectangleMaxValueTest.java:
--------------------------------------------------------------------------------
1 | package net.sf.jsi;
2 |
3 | import junit.framework.TestCase;
4 |
5 | import net.sf.jsi.Rectangle;
6 | import net.sf.jsi.rtree.RTree;
7 |
8 | public class RectangleMaxValueTest extends TestCase {
9 | public RectangleMaxValueTest(String name) {
10 | super(name);
11 | }
12 |
13 | public void testMaxValue() {
14 | RTree rTree = new RTree();
15 | rTree.init(null);
16 | rTree.add(new Rectangle(8.0f, 6.0f, Float.MAX_VALUE, Float.MAX_VALUE), 1);
17 | rTree.add(new Rectangle(1.0f, 5.0f, Float.MAX_VALUE, Float.MAX_VALUE), 2);
18 | rTree.add(new Rectangle(10.0f, 6.0f, Float.MAX_VALUE, Float.MAX_VALUE), 3);
19 | rTree.add(new Rectangle(5.0f, 8.0f, Float.MAX_VALUE, Float.MAX_VALUE), 4);
20 | rTree.add(new Rectangle(6.0f, 1.0f, Float.MAX_VALUE, Float.MAX_VALUE), 6);
21 | rTree.add(new Rectangle(3.0f, 1.0f, Float.MAX_VALUE, Float.MAX_VALUE), 7);
22 | rTree.add(new Rectangle(9.0f, 8.0f, Float.MAX_VALUE, Float.MAX_VALUE), 8);
23 | rTree.add(new Rectangle(5.0f, 7.0f, Float.MAX_VALUE, Float.MAX_VALUE), 9);
24 | rTree.add(new Rectangle(2.0f, 5.0f, Float.MAX_VALUE, Float.MAX_VALUE), 10);
25 | rTree.add(new Rectangle(2.0f, 2.0f, Float.MAX_VALUE, Float.MAX_VALUE), 11);
26 | rTree.add(new Rectangle(5.0f, 3.0f, Float.MAX_VALUE, Float.MAX_VALUE), 14);
27 | rTree.add(new Rectangle(7.0f, 3.0f, Float.MAX_VALUE, Float.MAX_VALUE), 15);
28 | rTree.add(new Rectangle(6.0f, 3.0f, Float.MAX_VALUE, Float.MAX_VALUE), 16);
29 | rTree.delete(new Rectangle(9.0f, 8.0f, Float.MAX_VALUE, Float.MAX_VALUE), 8);
30 | rTree.add(new Rectangle(7.0f, 8.0f, Float.MAX_VALUE, Float.MAX_VALUE), 17);
31 | rTree.add(new Rectangle(3.0f, 5.0f, Float.MAX_VALUE, Float.MAX_VALUE), 18);
32 | rTree.delete(new Rectangle(5.0f, 7.0f, Float.MAX_VALUE, Float.MAX_VALUE), 9);
33 | rTree.add(new Rectangle(4.0f, 7.0f, Float.MAX_VALUE, Float.MAX_VALUE), 19);
34 | rTree.delete(new Rectangle(2.0f, 5.0f, Float.MAX_VALUE, Float.MAX_VALUE), 10);
35 | rTree.add(new Rectangle(2.0f, 1.0f, Float.MAX_VALUE, Float.MAX_VALUE), 20);
36 | rTree.add(new Rectangle(9.0f, 6.0f, Float.MAX_VALUE, Float.MAX_VALUE), 21);
37 | rTree.add(new Rectangle(7.0f, 6.0f, Float.MAX_VALUE, Float.MAX_VALUE), 22);
38 | rTree.delete(new Rectangle(10.0f, 6.0f, Float.MAX_VALUE, Float.MAX_VALUE), 3);
39 | rTree.add(new Rectangle(3.0f, 4.0f, Float.MAX_VALUE, Float.MAX_VALUE), 23);
40 | rTree.delete(new Rectangle(3.0f, 1.0f, Float.MAX_VALUE, Float.MAX_VALUE), 7);
41 | rTree.add(new Rectangle(3.0f, 1.0f, Float.MAX_VALUE, Float.MAX_VALUE), 24);
42 | rTree.delete(new Rectangle(8.0f, 6.0f, Float.MAX_VALUE, Float.MAX_VALUE), 1);
43 | rTree.add(new Rectangle(3.0f, 6.0f, Float.MAX_VALUE, Float.MAX_VALUE), 25);
44 | rTree.delete(new Rectangle(7.0f, 8.0f, Float.MAX_VALUE, Float.MAX_VALUE), 17);
45 | rTree.add(new Rectangle(7.0f, 8.0f, Float.MAX_VALUE, Float.MAX_VALUE), 26);
46 | rTree.delete(new Rectangle(2.0f, 1.0f, Float.MAX_VALUE, Float.MAX_VALUE), 20);
47 | rTree.add(new Rectangle(0.0f, 1.0f, Float.MAX_VALUE, Float.MAX_VALUE), 27);
48 | rTree.delete(new Rectangle(2.0f, 2.0f, Float.MAX_VALUE, Float.MAX_VALUE), 11);
49 | rTree.add(new Rectangle(2.0f, 2.0f, Float.MAX_VALUE, Float.MAX_VALUE), 28);
50 | rTree.delete(new Rectangle(5.0f, 8.0f, Float.MAX_VALUE, Float.MAX_VALUE), 4);
51 | rTree.add(new Rectangle(4.0f, 2.0f, Float.MAX_VALUE, Float.MAX_VALUE), 29);
52 | rTree.delete(new Rectangle(5.0f, 3.0f, Float.MAX_VALUE, Float.MAX_VALUE), 14);
53 | rTree.add(new Rectangle(5.0f, 3.0f, Float.MAX_VALUE, Float.MAX_VALUE), 30);
54 | rTree.add(new Rectangle(7.0f, 5.0f, Float.MAX_VALUE, Float.MAX_VALUE), 31);
55 | rTree.delete(new Rectangle(7.0f, 5.0f, Float.MAX_VALUE, Float.MAX_VALUE), 31);
56 | rTree.add(new Rectangle(7.0f, 5.0f, Float.MAX_VALUE, Float.MAX_VALUE), 32);
57 | rTree.add(new Rectangle(5.0f, 8.0f, Float.MAX_VALUE, Float.MAX_VALUE), 33);
58 | rTree.delete(new Rectangle(2.0f, 2.0f, Float.MAX_VALUE, Float.MAX_VALUE), 28);
59 | rTree.add(new Rectangle(1.0f, 2.0f, Float.MAX_VALUE, Float.MAX_VALUE), 34);
60 | rTree.delete(new Rectangle(0.0f, 1.0f, Float.MAX_VALUE, Float.MAX_VALUE), 27);
61 | rTree.add(new Rectangle(0.0f, 1.0f, Float.MAX_VALUE, Float.MAX_VALUE), 35);
62 | rTree.add(new Rectangle(8.0f, 5.0f, Float.MAX_VALUE, Float.MAX_VALUE), 36);
63 | rTree.delete(new Rectangle(3.0f, 5.0f, Float.MAX_VALUE, Float.MAX_VALUE), 18);
64 | rTree.add(new Rectangle(3.0f, 5.0f, Float.MAX_VALUE, Float.MAX_VALUE), 37);
65 | rTree.add(new Rectangle(8.0f, 7.0f, Float.MAX_VALUE, Float.MAX_VALUE), 39);
66 | rTree.delete(new Rectangle(7.0f, 6.0f, Float.MAX_VALUE, Float.MAX_VALUE), 22);
67 | rTree.add(new Rectangle(5.0f, 2.0f, Float.MAX_VALUE, Float.MAX_VALUE), 40);
68 | rTree.delete(new Rectangle(3.0f, 1.0f, Float.MAX_VALUE, Float.MAX_VALUE), 24);
69 | rTree.add(new Rectangle(3.0f, 0.0f, Float.MAX_VALUE, Float.MAX_VALUE), 41);
70 | rTree.delete(new Rectangle(7.0f, 8.0f, Float.MAX_VALUE, Float.MAX_VALUE), 26);
71 | rTree.add(new Rectangle(7.0f, 5.0f, Float.MAX_VALUE, Float.MAX_VALUE), 42);
72 | rTree.delete(new Rectangle(7.0f, 3.0f, Float.MAX_VALUE, Float.MAX_VALUE), 15);
73 | rTree.add(new Rectangle(3.0f, 2.0f, Float.MAX_VALUE, Float.MAX_VALUE), 43);
74 | rTree.delete(new Rectangle(4.0f, 2.0f, Float.MAX_VALUE, Float.MAX_VALUE), 29);
75 | rTree.add(new Rectangle(4.0f, 2.0f, Float.MAX_VALUE, Float.MAX_VALUE), 44);
76 | rTree.delete(new Rectangle(3.0f, 6.0f, Float.MAX_VALUE, Float.MAX_VALUE), 25);
77 | rTree.add(new Rectangle(3.0f, 5.0f, Float.MAX_VALUE, Float.MAX_VALUE), 45);
78 | rTree.delete(new Rectangle(3.0f, 2.0f, Float.MAX_VALUE, Float.MAX_VALUE), 43);
79 | rTree.add(new Rectangle(1.0f, 0.0f, Float.MAX_VALUE, Float.MAX_VALUE), 46);
80 | rTree.delete(new Rectangle(1.0f, 5.0f, Float.MAX_VALUE, Float.MAX_VALUE), 2);
81 | rTree.add(new Rectangle(1.0f, 5.0f, Float.MAX_VALUE, Float.MAX_VALUE), 47);
82 | rTree.delete(new Rectangle(9.0f, 6.0f, Float.MAX_VALUE, Float.MAX_VALUE), 21);
83 | rTree.add(new Rectangle(7.0f, 6.0f, Float.MAX_VALUE, Float.MAX_VALUE), 48);
84 | rTree.delete(new Rectangle(4.0f, 7.0f, Float.MAX_VALUE, Float.MAX_VALUE), 19);
85 | rTree.add(new Rectangle(4.0f, 0.0f, Float.MAX_VALUE, Float.MAX_VALUE), 49);
86 | rTree.delete(new Rectangle(5.0f, 3.0f, Float.MAX_VALUE, Float.MAX_VALUE), 30);
87 | rTree.add(new Rectangle(0.0f, 2.0f, Float.MAX_VALUE, Float.MAX_VALUE), 50);
88 | rTree.delete(new Rectangle(5.0f, 8.0f, Float.MAX_VALUE, Float.MAX_VALUE), 33);
89 | rTree.add(new Rectangle(4.0f, 8.0f, Float.MAX_VALUE, Float.MAX_VALUE), 51);
90 | rTree.delete(new Rectangle(3.0f, 5.0f, Float.MAX_VALUE, Float.MAX_VALUE), 45);
91 | rTree.add(new Rectangle(3.0f, 5.0f, Float.MAX_VALUE, Float.MAX_VALUE), 52);
92 | rTree.delete(new Rectangle(7.0f, 5.0f, Float.MAX_VALUE, Float.MAX_VALUE), 42);
93 | rTree.add(new Rectangle(7.0f, 5.0f, Float.MAX_VALUE, Float.MAX_VALUE), 53);
94 | rTree.delete(new Rectangle(5.0f, 2.0f, Float.MAX_VALUE, Float.MAX_VALUE), 40);
95 | rTree.add(new Rectangle(3.0f, 2.0f, Float.MAX_VALUE, Float.MAX_VALUE), 54);
96 | rTree.delete(new Rectangle(6.0f, 1.0f, Float.MAX_VALUE, Float.MAX_VALUE), 6);
97 | rTree.add(new Rectangle(6.0f, 1.0f, Float.MAX_VALUE, Float.MAX_VALUE), 55);
98 | rTree.delete(new Rectangle(4.0f, 8.0f, Float.MAX_VALUE, Float.MAX_VALUE), 51);
99 | rTree.add(new Rectangle(4.0f, 8.0f, Float.MAX_VALUE, Float.MAX_VALUE), 56);
100 | rTree.delete(new Rectangle(1.0f, 5.0f, Float.MAX_VALUE, Float.MAX_VALUE), 47);
101 | rTree.add(new Rectangle(1.0f, 5.0f, Float.MAX_VALUE, Float.MAX_VALUE), 57);
102 | rTree.delete(new Rectangle(0.0f, 2.0f, Float.MAX_VALUE, Float.MAX_VALUE), 50);
103 | rTree.add(new Rectangle(0.0f, 2.0f, Float.MAX_VALUE, Float.MAX_VALUE), 58);
104 | rTree.delete(new Rectangle(3.0f, 0.0f, Float.MAX_VALUE, Float.MAX_VALUE), 41);
105 | rTree.add(new Rectangle(3.0f, 0.0f, Float.MAX_VALUE, Float.MAX_VALUE), 59);
106 | rTree.delete(new Rectangle(7.0f, 5.0f, Float.MAX_VALUE, Float.MAX_VALUE), 53);
107 | rTree.add(new Rectangle(0.0f, 5.0f, Float.MAX_VALUE, Float.MAX_VALUE), 60);
108 | rTree.delete(new Rectangle(6.0f, 1.0f, Float.MAX_VALUE, Float.MAX_VALUE), 55);
109 | rTree.add(new Rectangle(2.0f, 1.0f, Float.MAX_VALUE, Float.MAX_VALUE), 61);
110 | rTree.delete(new Rectangle(7.0f, 5.0f, Float.MAX_VALUE, Float.MAX_VALUE), 32);
111 | rTree.add(new Rectangle(0.0f, 5.0f, Float.MAX_VALUE, Float.MAX_VALUE), 62);
112 | rTree.delete(new Rectangle(0.0f, 2.0f, Float.MAX_VALUE, Float.MAX_VALUE), 58);
113 | rTree.add(new Rectangle(0.0f, 2.0f, Float.MAX_VALUE, Float.MAX_VALUE), 63);
114 | rTree.delete(new Rectangle(3.0f, 4.0f, Float.MAX_VALUE, Float.MAX_VALUE), 23);
115 | rTree.add(new Rectangle(3.0f, 3.0f, Float.MAX_VALUE, Float.MAX_VALUE), 64);
116 | rTree.delete(new Rectangle(8.0f, 7.0f, Float.MAX_VALUE, Float.MAX_VALUE), 39);
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/src/test/java/net/sf/jsi/RectangleTest.java:
--------------------------------------------------------------------------------
1 | // RectangleTest.java
2 | // Java Spatial Index Library
3 | // Copyright (C) 2002-2005 Infomatiq Limited.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 |
19 | package net.sf.jsi;
20 |
21 | import junit.framework.TestCase;
22 |
23 | import net.sf.jsi.Rectangle;
24 |
25 | /**
26 | * RectangleTest
27 | */
28 | public class RectangleTest extends TestCase {
29 | public RectangleTest(String s) {
30 | super(s);
31 | }
32 |
33 | public void testContains() {
34 |
35 | }
36 |
37 | public void testDistance() {
38 |
39 | }
40 |
41 | public void testIntersects() {
42 | Rectangle r0_0_0_0 = new Rectangle (0, 0, 0, 0);
43 | Rectangle r1_1_1_1 = new Rectangle (1, 1, 1, 1);
44 | Rectangle r2_2_6_6 = new Rectangle (2, 2, 6, 6);
45 | Rectangle r3_3_7_5 = new Rectangle (3, 3, 7, 5);
46 | Rectangle r3_3_5_7 = new Rectangle (3, 3, 5, 7);
47 | Rectangle r1_3_5_5 = new Rectangle (1, 3, 5, 5);
48 | Rectangle r3_1_5_5 = new Rectangle (3, 1, 5, 5);
49 |
50 | // A rectangle always intersects itself
51 | assertTrue(r0_0_0_0.intersects(r0_0_0_0));
52 | assertTrue(r2_2_6_6.intersects(r2_2_6_6));
53 |
54 | assertTrue(r0_0_0_0.intersects(r1_1_1_1) == false);
55 | assertTrue(r1_1_1_1.intersects(r0_0_0_0) == false);
56 |
57 | // Rectangles that intersect only on the right-hand side
58 | assertTrue(r2_2_6_6.intersects(r3_3_7_5));
59 | assertTrue(r3_3_7_5.intersects(r2_2_6_6));
60 |
61 | // Rectangles that touch only on the right hand side
62 | //assertTrue(r
63 |
64 | // Rectangles that intersect only on the top side
65 | assertTrue(r2_2_6_6.intersects(r3_3_5_7));
66 | assertTrue(r3_3_5_7.intersects(r2_2_6_6));
67 |
68 | // Rectangles that intersect only on the left-hand side
69 | assertTrue(r2_2_6_6.intersects(r1_3_5_5));
70 | assertTrue(r1_3_5_5.intersects(r2_2_6_6));
71 |
72 | // Rectangles that intersect only on the bottom side
73 | assertTrue(r2_2_6_6.intersects(r3_1_5_5));
74 | assertTrue(r3_1_5_5.intersects(r2_2_6_6));
75 |
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/test/java/net/sf/jsi/ReferenceCompareTest.java:
--------------------------------------------------------------------------------
1 | // ReferenceCompareTest.java
2 | // Java Spatial Index Library
3 | // Copyright (C) 2002-2005 Infomatiq Limited.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 |
19 | package net.sf.jsi;
20 |
21 | import java.util.Properties;
22 |
23 | import junit.framework.TestCase;
24 |
25 | import org.slf4j.Logger;
26 | import org.slf4j.LoggerFactory;
27 |
28 | /**
29 | * ReferenceCompareTest
30 | *
31 | * Generates results used for comparing the performance of the Java Spatial
32 | * Index library against alternative implementations.
33 | */
34 | public class ReferenceCompareTest extends TestCase {
35 |
36 | private static final Logger log = LoggerFactory.getLogger(ReferenceCompareTest.class);
37 |
38 | private Script script = new Script();
39 | private Properties linear_3_6 = props("Linear", 3, 6);
40 | private Properties linear_5_10 = props("Linear", 5, 10);
41 | private Properties rstar_1_13 = props("RStar", 1, 13);
42 | private Properties rstar_6_13 = props("RStar", 6, 13);
43 |
44 | protected int entriesToTest = 100;
45 |
46 | public ReferenceCompareTest(String s) {
47 | super(s);
48 | }
49 |
50 | public int GetNumEntriesToTest() {
51 | return 100;
52 | }
53 |
54 | public Properties props(String treeVariant, int minNodeEntries, int maxNodeEntries) {
55 | Properties p = new Properties();
56 | p.setProperty("MinNodeEntries", Integer.toString(minNodeEntries));
57 | p.setProperty("MaxNodeEntries", Integer.toString(maxNodeEntries));
58 | p.setProperty("TreeVariant", treeVariant);
59 | return p;
60 | }
61 |
62 | private void runComparisonTest(String scriptName, String referenceType, Properties refProps, String testType, Properties testProps) {
63 | log.info(scriptName + " - creating reference test results");
64 | script.run(referenceType, refProps, scriptName, Script.REFERENCE_GENERATE);
65 |
66 | log.info(scriptName + " - running comparison test");
67 | script.run(testType, testProps, scriptName, Script.REFERENCE_COMPARISON);
68 | }
69 |
70 |
71 | // 100, 1000, 10,000
72 | // Reference results are generated by the SimpleIndex implementation.
73 | // Therefore, compare results for both SIL and JSI implementations.
74 | //
75 | // 100,000
76 | // Reference result generated by SIL, therefore compare results
77 | // for JSI only
78 | public void testReferenceCompareAllFunctions() {
79 | log.debug("testReferenceCompareAllFunctions()");
80 |
81 | if (entriesToTest >= 100) {
82 | runComparisonTest("allfunctions-100", "SimpleIndex", null, "SILWrapper", linear_3_6);
83 | runComparisonTest("allfunctions-100", "SimpleIndex", null, "rtree.RTree", linear_3_6);
84 | }
85 |
86 | if (entriesToTest >= 1000) {
87 | runComparisonTest("allfunctions-1000", "SimpleIndex", null, "SILWrapper", linear_3_6);
88 | runComparisonTest("allfunctions-1000", "SimpleIndex", null, "rtree.RTree", linear_3_6);
89 | }
90 |
91 | if (entriesToTest >= 10000) {
92 | runComparisonTest("allfunctions-10000", "SimpleIndex", null, "SILWrapper", linear_3_6);
93 | runComparisonTest("allfunctions-10000", "SimpleIndex", null, "rtree.RTree", linear_3_6);
94 | }
95 |
96 | if (entriesToTest >= 100000) {
97 | runComparisonTest("allfunctions-100000", "SILWrapper", rstar_1_13, "rtree.RTree", linear_3_6);
98 | }
99 | }
100 |
101 | public void testReferenceCompareDelete() {
102 | log.debug("testReferenceCompareDelete()");
103 |
104 | if (entriesToTest >= 100) {
105 | runComparisonTest("delete-100", "SimpleIndex", null, "SILWrapper", linear_3_6);
106 | runComparisonTest("delete-100", "SimpleIndex", null, "rtree.RTree", linear_3_6);
107 | }
108 |
109 | if (entriesToTest >= 1000) {
110 | runComparisonTest("delete-1000", "SimpleIndex", null, "SILWrapper", linear_3_6);
111 | runComparisonTest("delete-1000", "SimpleIndex", null, "rtree.RTree", linear_3_6);
112 | }
113 |
114 | if (entriesToTest >= 10000) {
115 | runComparisonTest("delete-10000", "SimpleIndex", null, "SILWrapper", linear_3_6);
116 | runComparisonTest("delete-10000", "SimpleIndex", null, "rtree.RTree", linear_3_6);
117 | }
118 |
119 | if (entriesToTest >= 100000) {
120 | runComparisonTest("delete-100000", "SILWrapper", rstar_1_13, "rtree.RTree", linear_3_6);
121 | }
122 | }
123 |
124 | public void testReferenceCompareIntersect() {
125 | log.debug("testReferenceCompareIntersect()");
126 |
127 | if (entriesToTest >= 100) {
128 | runComparisonTest("intersect-100", "SimpleIndex", null, "SILWrapper", linear_5_10);
129 | runComparisonTest("intersect-100", "SimpleIndex", null, "rtree.RTree", linear_5_10);
130 | }
131 |
132 | if (entriesToTest >= 1000) {
133 | runComparisonTest("intersect-1000", "SimpleIndex", null, "SILWrapper", linear_5_10);
134 | runComparisonTest("intersect-1000", "SimpleIndex", null, "rtree.RTree", linear_5_10);
135 | }
136 |
137 | if (entriesToTest >= 10000) {
138 | runComparisonTest("intersect-10000", "SimpleIndex", null, "SILWrapper", linear_5_10);
139 | runComparisonTest("intersect-10000", "SimpleIndex", null, "rtree.RTree", linear_5_10);
140 | }
141 |
142 | if (entriesToTest >= 100000) {
143 | runComparisonTest("intersect-100000", "SILWrapper", rstar_1_13, "rtree.RTree", linear_5_10);
144 | }
145 | }
146 |
147 | public void testReferenceCompareNearest() {
148 | log.debug("testReferenceCompareNearest()");
149 |
150 | if (entriesToTest >= 100) {
151 | runComparisonTest("nearest-100", "SimpleIndex", null, "SILWrapper", linear_5_10);
152 | runComparisonTest("nearest-100", "SimpleIndex", null, "rtree.RTree", linear_5_10);
153 | }
154 |
155 | if (entriesToTest >= 1000) {
156 | runComparisonTest("nearest-1000", "SimpleIndex", null, "SILWrapper", linear_5_10);
157 | runComparisonTest("nearest-1000", "SimpleIndex", null, "rtree.RTree", linear_5_10);
158 | }
159 |
160 | if (entriesToTest >= 10000) {
161 | runComparisonTest("nearest-10000", "SimpleIndex", null, "SILWrapper", linear_5_10);
162 | runComparisonTest("nearest-10000", "SimpleIndex", null, "rtree.RTree", linear_5_10);
163 | }
164 |
165 | if (entriesToTest >= 100000) {
166 | runComparisonTest("nearest-100000", "SILWrapper", rstar_1_13, "rtree.RTree", linear_5_10);
167 | }
168 | }
169 |
170 | public void testReferenceCompareNearestN() {
171 | log.debug("testReferenceCompareNearestN()");
172 |
173 | if (entriesToTest >= 100) {
174 | runComparisonTest("nearestN-100", "SimpleIndex", null, "SILWrapper", linear_5_10);
175 | runComparisonTest("nearestN-100", "SimpleIndex", null, "rtree.RTree", linear_5_10);
176 | }
177 |
178 | if (entriesToTest >= 1000) {
179 | runComparisonTest("nearestN-1000", "SimpleIndex", null, "SILWrapper", linear_5_10);
180 | runComparisonTest("nearestN-1000", "SimpleIndex", null, "rtree.RTree", linear_5_10);
181 | }
182 |
183 | if (entriesToTest >= 10000) {
184 | runComparisonTest("nearestN-10000", "SimpleIndex", null, "SILWrapper", linear_5_10);
185 | runComparisonTest("nearestN-10000", "SimpleIndex", null, "rtree.RTree", linear_5_10);
186 | }
187 |
188 | if (entriesToTest >= 100000) {
189 | runComparisonTest("nearestN-100000", "SILWrapper", rstar_1_13, "rtree.RTree", linear_5_10);
190 | }
191 | }
192 |
193 | public void testReferenceCompareContains() {
194 | log.debug("testReferenceCompareContains()");
195 |
196 | if (entriesToTest >= 100) {
197 | runComparisonTest("contains-100", "SimpleIndex", null, "SILWrapper", linear_5_10);
198 | runComparisonTest("contains-100", "SimpleIndex", null, "rtree.RTree", linear_5_10);
199 | }
200 |
201 | if (entriesToTest >= 1000) {
202 | runComparisonTest("contains-1000", "SimpleIndex", null, "SILWrapper", linear_5_10);
203 | runComparisonTest("contains-1000", "SimpleIndex", null, "rtree.RTree", linear_5_10);
204 | }
205 |
206 | if (entriesToTest >= 10000) {
207 | runComparisonTest("contains-10000", "SimpleIndex", null, "SILWrapper", linear_5_10);
208 | runComparisonTest("contains-10000", "SimpleIndex", null, "rtree.RTree", linear_5_10);
209 | }
210 |
211 | if (entriesToTest >= 100000) {
212 | runComparisonTest("contains-100000", "SILWrapper", rstar_6_13, "rtree.RTree", linear_5_10);
213 | }
214 | }
215 | }
216 |
--------------------------------------------------------------------------------
/src/test/java/net/sf/jsi/ReferenceCompareTest_1000.java:
--------------------------------------------------------------------------------
1 | package net.sf.jsi;
2 |
3 | public class ReferenceCompareTest_1000 extends ReferenceCompareTest {
4 | public ReferenceCompareTest_1000(String s) {
5 | super(s);
6 | entriesToTest = 1000;
7 | }
8 | }
9 |
10 |
--------------------------------------------------------------------------------
/src/test/java/net/sf/jsi/ReferenceCompareTest_10000.java:
--------------------------------------------------------------------------------
1 | package net.sf.jsi;
2 |
3 | public class ReferenceCompareTest_10000 extends ReferenceCompareTest {
4 | public ReferenceCompareTest_10000(String s) {
5 | super(s);
6 | entriesToTest = 10000;
7 | }
8 | }
9 |
10 |
--------------------------------------------------------------------------------
/src/test/java/net/sf/jsi/ReferenceCompareTest_100000.java:
--------------------------------------------------------------------------------
1 | package net.sf.jsi;
2 |
3 | public class ReferenceCompareTest_100000 extends ReferenceCompareTest {
4 | public ReferenceCompareTest_100000(String s) {
5 | super(s);
6 | entriesToTest = 100000;
7 | }
8 | }
9 |
10 |
--------------------------------------------------------------------------------
/src/test/java/net/sf/jsi/SILWrapper.java:
--------------------------------------------------------------------------------
1 | // SILWrapper.java
2 | // Java Spatial Index Library
3 | // Copyright (C) 2002-2005 Infomatiq Limited.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 |
19 | package net.sf.jsi;
20 |
21 | import gnu.trove.procedure.TIntProcedure;
22 |
23 | import java.util.Properties;
24 |
25 | import org.slf4j.Logger;
26 | import org.slf4j.LoggerFactory;
27 |
28 | import sil.rtree.RTree;
29 | import sil.spatialindex.IData;
30 | import sil.spatialindex.INode;
31 | import sil.spatialindex.ISpatialIndex;
32 | import sil.spatialindex.IVisitor;
33 | import sil.spatialindex.Region;
34 | import sil.storagemanager.IStorageManager;
35 | import sil.storagemanager.MemoryStorageManager;
36 | import sil.storagemanager.PropertySet;
37 |
38 | /**
39 | * Wrapper class for the Spatial Index Library (v0.43b) written by
40 | * Marios Hadjieleftheriou (marioh@cs.ucr.edu), with minor modifications.
41 | *
42 | * Used to generate test results and performance comparisons.
43 | */
44 | public class SILWrapper implements SpatialIndex {
45 |
46 | private static final Logger log = LoggerFactory.getLogger(SILWrapper.class);
47 |
48 | private IStorageManager storageManager = null;
49 | private ISpatialIndex tree = null;
50 | private int size = 0;
51 |
52 | class IntProcedureVisitor implements IVisitor {
53 | private TIntProcedure m_intProcedure = null;
54 |
55 | public IntProcedureVisitor(TIntProcedure ip) {
56 | m_intProcedure = ip;
57 | }
58 |
59 | public void visitNode(final INode n) {
60 | return;
61 | }
62 |
63 | public void visitData(final IData d) {
64 | m_intProcedure.execute(d.getIdentifier());
65 | }
66 | }
67 |
68 | /**
69 | * @see net.sf.jsi.SpatialIndex#init(Properties)
70 | */
71 | public void init(Properties props) {
72 | int minNodeEntries = Integer.parseInt(props.getProperty("MinNodeEntries", "0"));
73 | int maxNodeEntries = Integer.parseInt(props.getProperty("MaxNodeEntries", "0"));
74 |
75 | float fillFactor = (float) minNodeEntries / (float) maxNodeEntries;
76 |
77 | // create a memory-based storage manager
78 | storageManager = new MemoryStorageManager();
79 | PropertySet propertySet = new PropertySet();
80 | propertySet.setProperty("FillFactor", new Double(fillFactor));
81 | propertySet.setProperty("IndexCapacity", new Integer(maxNodeEntries));
82 | propertySet.setProperty("LeafCapacity", new Integer(maxNodeEntries));
83 | propertySet.setProperty("Dimension", new Integer(2));
84 |
85 | String strTreeVariant = props.getProperty("TreeVariant");
86 | Integer intTreeVariant = null;
87 | if (strTreeVariant.equalsIgnoreCase("Linear")) {
88 | intTreeVariant = new Integer(sil.spatialindex.SpatialIndex.RtreeVariantLinear);
89 | } else if (strTreeVariant.equalsIgnoreCase("Quadratic")) {
90 | intTreeVariant = new Integer(sil.spatialindex.SpatialIndex.RtreeVariantQuadratic);
91 | } else {
92 | // default
93 | if (!strTreeVariant.equalsIgnoreCase("Rstar")) {
94 | log.error("Property key TreeVariant: invalid value " + strTreeVariant + ", defaulting to Rstar");
95 | }
96 | intTreeVariant = new Integer(sil.spatialindex.SpatialIndex.RtreeVariantRstar);
97 | }
98 | propertySet.setProperty("TreeVariant", intTreeVariant);
99 |
100 | tree = new RTree(propertySet, storageManager);
101 | }
102 |
103 | /**
104 | * @see net.sf.jsi.SpatialIndex#nearest(Point p, gnu.trove.TIntProcedure ip, float)
105 | */
106 | public void nearest(Point p, TIntProcedure v, float furthestDistance) {
107 | tree.nearestNeighborQuery(1,
108 | new sil.spatialindex.Point(new double[] {p.x, p.y}),
109 | new IntProcedureVisitor(v));
110 | }
111 |
112 | /**
113 | * @see net.sf.jsi.SpatialIndex#nearestN(Point, gnu.trove.TIntProcedure, int, float)
114 | */
115 | public void nearestN(Point p, TIntProcedure v, int n, float furthestDistance) {
116 | tree.nearestNeighborQuery(n,
117 | new sil.spatialindex.Point(new double[] {p.x, p.y}),
118 | new IntProcedureVisitor(v));
119 | }
120 |
121 | /**
122 | * Same as nearestN
123 | *
124 | * @see net.sf.jsi.SpatialIndex#nearestNUnsorted(Point, gnu.trove.TIntProcedure, int, float)
125 | */
126 | public void nearestNUnsorted(Point p, TIntProcedure v, int n, float furthestDistance) {
127 | nearestN(p, v, n, furthestDistance);
128 | }
129 |
130 |
131 | /**
132 | * @see net.sf.jsi.SpatialIndex#intersects(Rectangle, gnu.trove.TIntProcedure)
133 | */
134 | public void intersects(Rectangle r, TIntProcedure v) {
135 | Region region = new Region(new double[] {r.minX, r.minY}, new double[] {r.maxX, r.maxY});
136 | tree.intersectionQuery(region, new IntProcedureVisitor(v));
137 | }
138 |
139 | /**
140 | * @see net.sf.jsi.SpatialIndex#contains(Rectangle, gnu.trove.TIntProcedure)
141 | */
142 | public void contains(Rectangle r, TIntProcedure v) {
143 | Region region = new Region(new double[] {r.minX, r.minY}, new double[] {r.maxX, r.maxY});
144 | tree.containmentQuery(region, new IntProcedureVisitor(v));
145 | }
146 |
147 | /**
148 | * @see net.sf.jsi.SpatialIndex#add(Rectangle, int)
149 | */
150 | public void add(Rectangle r, int id) {
151 | Region region = new Region(new double[] {r.minX, r.minY}, new double[] {r.maxX, r.maxY});
152 | tree.insertData(null, region, (int)id);
153 | size++;
154 | }
155 |
156 | /**
157 | * @see net.sf.jsi.SpatialIndex#delete(Rectangle, int)
158 | */
159 | public boolean delete(Rectangle r, int id) {
160 | Region region = new Region(new double[] {r.minX, r.minY}, new double[] {r.maxX, r.maxY});
161 | if (tree.deleteData(region, (int)id)) {
162 | size--;
163 | return true;
164 | }
165 | return false;
166 | }
167 |
168 | /**
169 | * @see net.sf.jsi.SpatialIndex#size()
170 | */
171 | public int size() {
172 | return size;
173 | }
174 |
175 | /**
176 | * @see net.sf.jsi.SpatialIndex#getBounds()
177 | */
178 | public Rectangle getBounds() {
179 | return null; // operation not supported in Spatial Index Library
180 | }
181 |
182 | /**
183 | * @see net.sf.jsi.SpatialIndex#getVersion()
184 | */
185 | public String getVersion() {
186 | return "SILWrapper-" + BuildProperties.getVersion();
187 | }
188 |
189 | }
190 |
--------------------------------------------------------------------------------
/src/test/java/net/sf/jsi/SimpleIndex.java:
--------------------------------------------------------------------------------
1 | // SimpleIndex.java
2 | // Java Spatial Index Library
3 | // Copyright (C) 2002-2005 Infomatiq Limited.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 |
19 | package net.sf.jsi;
20 |
21 | import gnu.trove.list.array.TFloatArrayList;
22 | import gnu.trove.list.array.TIntArrayList;
23 | import gnu.trove.map.hash.TIntObjectHashMap;
24 | import gnu.trove.iterator.TIntObjectIterator;
25 | import gnu.trove.procedure.TIntProcedure;
26 |
27 | import java.util.Properties;
28 |
29 | /**
30 | * SimpleIndex
31 | *
32 | *
A very simple (and slow!) spatial index implementation,
33 | * intended only for generating test results.
34 | *
35 | *
All of the search methods, ie nearest(), contains() and intersects(),
36 | * run in linear time, so performance will be very slow with more
37 | * than 1000 or so entries.
38 | *
39 | *
On the other hand, the add() and delete() methods are very fast :-)
40 | */
41 | public class SimpleIndex implements SpatialIndex {
42 | TIntObjectHashMap m_map = new TIntObjectHashMap();
43 |
44 | /**
45 | * Does nothing. There are no implementation dependent properties for
46 | * the SimpleIndex spatial index.
47 | */
48 | public void init(Properties p) {
49 | return;
50 | }
51 |
52 | /**
53 | * Nearest
54 | */
55 | private TIntArrayList nearest(Point p, float furthestDistance) {
56 | TIntArrayList ret = new TIntArrayList();
57 | float nearestDistance = furthestDistance;
58 | TIntObjectIterator i = m_map.iterator();
59 | while (i.hasNext()) {
60 | i.advance();
61 | int currentId = i.key();
62 | Rectangle currentRectangle = i.value();
63 | float distance = currentRectangle.distance(p);
64 | if (distance < nearestDistance) {
65 | nearestDistance = distance;
66 | ret.clear();
67 | }
68 | if (distance <= nearestDistance) {
69 | ret.add(currentId);
70 | }
71 | }
72 | return ret;
73 | }
74 |
75 | /**
76 | * @see net.sf.jsi.SpatialIndex#nearest(Point, gnu.trove.TIntProcedure, float)
77 | */
78 | public void nearest(Point p, final TIntProcedure v, float furthestDistance) {
79 | TIntArrayList nearestList = nearest(p, furthestDistance);
80 | nearestList.forEach(new TIntProcedure() {
81 | public boolean execute(int id) {
82 | v.execute(id);
83 | return true;
84 | }
85 | });
86 | }
87 |
88 | private TIntArrayList nearestN(Point p, int n, float furthestDistance) {
89 | TIntArrayList ids = new TIntArrayList();
90 | TFloatArrayList distances = new TFloatArrayList();
91 |
92 | TIntObjectIterator iter = m_map.iterator();
93 | while (iter.hasNext()) {
94 | iter.advance();
95 | int currentId = iter.key();
96 | Rectangle currentRectangle = iter.value();
97 | float distance = currentRectangle.distance(p);
98 |
99 | if (distance <= furthestDistance) {
100 | int insertionIndex = 0;
101 | while (ids.size() > insertionIndex && distances.get(insertionIndex) <= distance) {
102 | insertionIndex++;
103 | }
104 |
105 | ids.insert(insertionIndex, currentId);
106 | distances.insert(insertionIndex, distance);
107 |
108 | // remove the entries with the greatest distance, if necessary.
109 | if (ids.size() > n) {
110 | // check that removing all entries with equal greatest distance
111 | // would leave at least N entries.
112 | int maxDistanceCount = 1;
113 | int currentIndex = distances.size() - 1;
114 | float maxDistance = distances.get(currentIndex);
115 | while (currentIndex - 1 >= 0 && distances.get(currentIndex - 1) == maxDistance) {
116 | currentIndex--;
117 | maxDistanceCount++;
118 | }
119 | if (ids.size() - maxDistanceCount >= n) {
120 | ids.remove(currentIndex, maxDistanceCount);
121 | distances.remove(currentIndex, maxDistanceCount);
122 | }
123 | }
124 | }
125 | }
126 |
127 | return ids;
128 | }
129 |
130 | /**
131 | * @see net.sf.jsi.SpatialIndex#nearestN(Point, gnu.trove.TIntProcedure, int, float)
132 | */
133 | public void nearestN(Point p, final TIntProcedure v, int n, float furthestDistance) {
134 | TIntArrayList nearestList = nearestN(p, n, furthestDistance);
135 | nearestList.forEach(new TIntProcedure() {
136 | public boolean execute(int id) {
137 | v.execute(id);
138 | return true;
139 | }
140 | });
141 | }
142 |
143 | /**
144 | * Same as nearestN
145 | *
146 | * @see net.sf.jsi.SpatialIndex#nearestNUnsorted(Point, gnu.trove.TIntProcedure, int, float)
147 | */
148 | public void nearestNUnsorted(Point p, final TIntProcedure v, int n, float furthestDistance) {
149 | nearestN(p, v, n, furthestDistance);
150 | }
151 |
152 | /**
153 | * @see net.sf.jsi.SpatialIndex#intersects(Rectangle, gnu.trove.TIntProcedure)
154 | */
155 | public void intersects(Rectangle r, TIntProcedure v) {
156 | TIntObjectIterator i = m_map.iterator();
157 | while (i.hasNext()) {
158 | i.advance();
159 | int currentId = i.key();
160 | Rectangle currentRectangle = i.value();
161 | if (r.intersects(currentRectangle)) {
162 | v.execute(currentId);
163 | }
164 | }
165 | }
166 |
167 | /**
168 | * @see net.sf.jsi.SpatialIndex#contains(Rectangle, gnu.trove.TIntProcedure)
169 | */
170 | public void contains(Rectangle r, TIntProcedure v) {
171 | TIntObjectIterator i = m_map.iterator();
172 | while (i.hasNext()) {
173 | i.advance();
174 | int currentId = i.key();
175 | Rectangle currentRectangle = i.value();
176 | if (r.contains(currentRectangle)) {
177 | v.execute(currentId);
178 | }
179 | }
180 | return;
181 | }
182 |
183 | /**
184 | * @see net.sf.jsi.SpatialIndex#add(Rectangle, int)
185 | */
186 | public void add(Rectangle r, int id) {
187 | m_map.put(id, r.copy());
188 | }
189 |
190 | /**
191 | * @see net.sf.jsi.SpatialIndex#delete(Rectangle, int)
192 | */
193 | public boolean delete(Rectangle r, int id) {
194 | Rectangle value = m_map.get(id);
195 |
196 | if (r.equals(value)) {
197 | m_map.remove(id);
198 | return true;
199 | }
200 | return false;
201 | }
202 |
203 | /**
204 | * @see net.sf.jsi.SpatialIndex#size()
205 | */
206 | public int size() {
207 | return m_map.size();
208 | }
209 |
210 | /**
211 | * @see net.sf.jsi.SpatialIndex#getBounds()
212 | */
213 | public Rectangle getBounds() {
214 | Rectangle bounds = null;
215 | TIntObjectIterator i = m_map.iterator();
216 | while (i.hasNext()) {
217 | i.advance();
218 | Rectangle currentRectangle = i.value();
219 | if (bounds == null) {
220 | bounds = currentRectangle.copy();
221 | } else {
222 | bounds.add(currentRectangle);
223 | }
224 | }
225 | return bounds;
226 | }
227 |
228 | /**
229 | * @see net.sf.jsi.SpatialIndex#getVersion
230 | */
231 | public String getVersion() {
232 | return "SimpleIndex-" + BuildProperties.getVersion();
233 | }
234 | }
235 |
--------------------------------------------------------------------------------
/src/test/java/net/sf/jsi/SortedListDecorator.java:
--------------------------------------------------------------------------------
1 | // SortedListDecorator.java
2 | // Java Spatial Index Library
3 | // Copyright (C) 2002-2005 Infomatiq Limited.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 |
19 | package net.sf.jsi;
20 |
21 | import java.util.Collections;
22 | import java.util.List;
23 |
24 | import net.sf.jsi.Point;
25 | import net.sf.jsi.Rectangle;
26 | import net.sf.jsi.SpatialIndex;
27 |
28 | /**
29 | * SortedListDecorator
30 | */
31 | public class SortedListDecorator extends ListDecorator {
32 |
33 | public SortedListDecorator(SpatialIndex si) {
34 | super(si);
35 | }
36 |
37 | private List sort(List l) {
38 | Collections.sort(l);
39 | return l;
40 | }
41 |
42 | public List nearestN(Point p, int maxCount, float furthestDistance) {
43 | return sort(super.nearestN(p, maxCount, furthestDistance));
44 | }
45 |
46 | public List nearest(Point p, float furthestDistance) {
47 | return sort(super.nearest(p, furthestDistance));
48 | }
49 |
50 | public List intersects(Rectangle r) {
51 | return sort(super.intersects(r));
52 | }
53 |
54 | public List contains(Rectangle r) {
55 | return sort(super.contains(r));
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/test/java/net/sf/jsi/SortedListTest.java:
--------------------------------------------------------------------------------
1 | // SortedListTest.java
2 | // Java Spatial Index Library
3 | // Copyright (C) 2002-2005 Infomatiq Limited.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 |
19 | package net.sf.jsi;
20 |
21 | import java.util.Arrays;
22 |
23 | import junit.framework.TestCase;
24 |
25 | import net.sf.jsi.rtree.SortedList;
26 |
27 | public class SortedListTest extends TestCase {
28 |
29 | public SortedListTest(String s) {
30 | super(s);
31 | }
32 |
33 | private boolean checkExpected(SortedList sl, int[] ids) {
34 | if (Arrays.equals(sl.toNativeArray(), ids)) {
35 | return true;
36 | }
37 | return false;
38 | }
39 |
40 | public void testSortedList() {
41 | SortedList sl = new SortedList();
42 | sl.init(1);
43 |
44 | sl.add(10, 10.0F);
45 | checkExpected(sl, new int[] {10});
46 |
47 | sl.add(9, 9.0F);
48 | checkExpected(sl, new int[] {10});
49 |
50 | sl.init(3);
51 |
52 | // add in reverse priority order
53 | sl.add(10, 10.0F);
54 | checkExpected(sl, new int[] {10});
55 |
56 | sl.add(9, 9.0F);
57 | checkExpected(sl, new int[] {10, 9});
58 |
59 | sl.add(8, 8.0F);
60 | checkExpected(sl, new int[] {10, 9, 8});
61 |
62 | // add elements with priority lower than lowest priority;
63 | // when current size = preferredMaxSize
64 | sl.add(7, 7.0F);
65 | checkExpected(sl, new int[] {10, 9, 8});
66 |
67 | sl.add(6, 6.0F);
68 | checkExpected(sl, new int[] {10, 9, 8});
69 |
70 | // add element with priority equal to lowest priority
71 | // when currentSize = preferredMaxSize
72 | sl.add(8, 8.0F);
73 | checkExpected(sl, new int[] {10, 9, 8, 8});
74 |
75 | // add elements with priority lower than lowest priority;
76 | // when current size = preferredMaxSize + 1
77 | sl.add(7, 7.0F);
78 | checkExpected(sl, new int[] {10, 9, 8, 8});
79 |
80 | // add element with priority equal to lowest priority
81 | // when current size = preferredMaxSize + 1
82 | sl.add(8, 8.0F);
83 | checkExpected(sl, new int[] {10, 9, 8, 8, 8});
84 |
85 | // add elements with priority lower than lowest priority;
86 | // when current size = preferredMaxSize + 2
87 | sl.add(7, 7.0F);
88 | checkExpected(sl, new int[] {10, 9, 8, 8, 8});
89 |
90 | // add element that will remove multiple entries of lowest priority
91 | sl.add(9, 9.0F);
92 | checkExpected(sl, new int[] {10, 9, 9});
93 |
94 |
95 | // add in priority order
96 | sl.init(3);
97 | sl.add(1, 1.0F);
98 | checkExpected(sl, new int[] {1});
99 |
100 | sl.add(2, 2.0F);
101 | checkExpected(sl, new int[] {2, 1});
102 |
103 | sl.add(3, 3.0F);
104 | checkExpected(sl, new int[] {3, 2, 1});
105 |
106 | sl.add(4, 4.0F);
107 | checkExpected(sl, new int[] {4, 3, 2});
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/test/java/net/sf/jsi/SpatialIndexFactory.java:
--------------------------------------------------------------------------------
1 | // SpatialIndexFactory.java
2 | // Java Spatial Index Library
3 | // Copyright (C) 2002-2005 Infomatiq Limited.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 |
19 | package net.sf.jsi;
20 |
21 | import java.util.Properties;
22 |
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 |
26 | import net.sf.jsi.SpatialIndex;
27 |
28 | /**
29 | * Factory class used to create instances of spatial indexes
30 | */
31 | public class SpatialIndexFactory {
32 |
33 | private final static Logger log =
34 | LoggerFactory.getLogger(SpatialIndexFactory.class);
35 |
36 | public static SpatialIndex newInstance(String type) {
37 | return newInstance(type, null);
38 | }
39 |
40 | public static SpatialIndex newInstance(String type, Properties props) {
41 | SpatialIndex si = null;
42 | String className = "net.sf.jsi." + type;
43 | try {
44 | si = (SpatialIndex) Class.forName(className).newInstance();
45 | si.init(props);
46 | } catch (ClassNotFoundException cnfe) {
47 | log.error(cnfe.toString());
48 | } catch (IllegalAccessException iae) {
49 | log.error(iae.toString());
50 | } catch (InstantiationException ie) {
51 | log.error(ie.toString());
52 | }
53 |
54 | return si;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/test/java/sil/rtree/Index.java:
--------------------------------------------------------------------------------
1 | // Spatial Index Library
2 | //
3 | // Copyright (C) 2002 Navel Ltd.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License aint with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 | //
19 | // Contact information:
20 | // Mailing address:
21 | // Marios Hadjieleftheriou
22 | // University of California, Riverside
23 | // Department of Computer Science
24 | // Surge Building, Room 310
25 | // Riverside, CA 92521
26 | //
27 | // Email:
28 | // marioh@cs.ucr.edu
29 |
30 | package sil.rtree;
31 |
32 | import java.util.ArrayList;
33 | import java.util.Arrays;
34 | import java.util.Comparator;
35 | import java.util.Stack;
36 |
37 | import sil.spatialindex.SpatialIndex;
38 | import sil.spatialindex.Region;
39 |
40 | public class Index extends Node
41 | {
42 | public Index(RTree pTree, int id, int level)
43 | {
44 | super(pTree, id, level, pTree.m_indexCapacity);
45 | }
46 |
47 | protected Node chooseSubtree(Region mbr, int level, Stack pathBuffer)
48 | {
49 | if (m_level == level) return this;
50 |
51 | pathBuffer.push(new Integer(m_identifier));
52 |
53 | int child = 0;
54 |
55 | switch (m_pTree.m_treeVariant)
56 | {
57 | case SpatialIndex.RtreeVariantLinear:
58 | case SpatialIndex.RtreeVariantQuadratic:
59 | child = findLeastEnlargement(mbr);
60 | break;
61 | case SpatialIndex.RtreeVariantRstar:
62 | if (m_level == 1)
63 | {
64 | // if this node points to leaves...
65 | child = findLeastOverlap(mbr);
66 | }
67 | else
68 | {
69 | child = findLeastEnlargement(mbr);
70 | }
71 | break;
72 | default:
73 | throw new IllegalStateException("Unknown RTree variant.");
74 | }
75 |
76 | Node n = m_pTree.readNode(m_pIdentifier[child]);
77 | Node ret = n.chooseSubtree(mbr, level, pathBuffer);
78 |
79 | return ret;
80 | }
81 |
82 | protected Leaf findLeaf(Region mbr, int id, Stack pathBuffer)
83 | {
84 | pathBuffer.push(new Integer(m_identifier));
85 |
86 | for (int cChild = 0; cChild < m_children; cChild++)
87 | {
88 | if (m_pMBR[cChild].contains(mbr))
89 | {
90 | Node n = m_pTree.readNode(m_pIdentifier[cChild]);
91 | Leaf l = n.findLeaf(mbr, id, pathBuffer);
92 | if (l != null) return l;
93 | }
94 | }
95 |
96 | pathBuffer.pop();
97 |
98 | return null;
99 | }
100 |
101 | protected Node[] split(byte[] pData, Region mbr, int id)
102 | {
103 | m_pTree.m_stats.m_splits++;
104 |
105 | ArrayList g1 = new ArrayList(), g2 = new ArrayList();
106 |
107 | switch (m_pTree.m_treeVariant)
108 | {
109 | case SpatialIndex.RtreeVariantLinear:
110 | case SpatialIndex.RtreeVariantQuadratic:
111 | rtreeSplit(pData, mbr, id, g1, g2);
112 | break;
113 | case SpatialIndex.RtreeVariantRstar:
114 | rstarSplit(pData, mbr, id, g1, g2);
115 | break;
116 | default:
117 | throw new IllegalStateException("Unknown RTree variant.");
118 | }
119 |
120 | Node left = new Index(m_pTree, m_identifier, m_level);
121 | Node right = new Index(m_pTree, -1, m_level);
122 |
123 | int cIndex;
124 |
125 | for (cIndex = 0; cIndex < g1.size(); cIndex++)
126 | {
127 | int i = ((Integer) g1.get(cIndex)).intValue();
128 | left.insertEntry(null, m_pMBR[i], m_pIdentifier[i]);
129 | }
130 |
131 | for (cIndex = 0; cIndex < g2.size(); cIndex++)
132 | {
133 | int i = ((Integer) g2.get(cIndex)).intValue();
134 | right.insertEntry(null, m_pMBR[i], m_pIdentifier[i]);
135 | }
136 |
137 | Node[] ret = new Node[2];
138 | ret[0] = left;
139 | ret[1] = right;
140 | return ret;
141 | }
142 |
143 | protected int findLeastEnlargement(Region r)
144 | {
145 | double area = Double.POSITIVE_INFINITY;
146 | int best = -1;
147 |
148 | for (int cChild = 0; cChild < m_children; cChild++)
149 | {
150 | Region t = m_pMBR[cChild].combinedRegion(r);
151 |
152 | double a = m_pMBR[cChild].getArea();
153 | double enl = t.getArea() - a;
154 |
155 | if (enl < area)
156 | {
157 | area = enl;
158 | best = cChild;
159 | }
160 | else if (enl == area)
161 | {
162 | if (a < m_pMBR[best].getArea()) best = cChild;
163 | }
164 | }
165 |
166 | return best;
167 | }
168 |
169 | protected int findLeastOverlap(Region r)
170 | {
171 | OverlapEntry[] entries = new OverlapEntry[m_children];
172 |
173 | double leastOverlap = Double.POSITIVE_INFINITY;
174 | double me = Double.POSITIVE_INFINITY;
175 | int best = -1;
176 |
177 | // find combined region and enlargement of every entry and store it.
178 | for (int cChild = 0; cChild < m_children; cChild++)
179 | {
180 | OverlapEntry e = new OverlapEntry();
181 |
182 | e.m_id = cChild;
183 | e.m_original = m_pMBR[cChild];
184 | e.m_combined = m_pMBR[cChild].combinedRegion(r);
185 | e.m_oa = e.m_original.getArea();
186 | e.m_ca = e.m_combined.getArea();
187 | e.m_enlargement = e.m_ca - e.m_oa;
188 | entries[cChild] = e;
189 |
190 | if (e.m_enlargement < me)
191 | {
192 | me = e.m_enlargement;
193 | best = cChild;
194 | }
195 | else if (e.m_enlargement == me && e.m_oa < entries[best].m_oa)
196 | {
197 | best = cChild;
198 | }
199 | }
200 |
201 | if (me < SpatialIndex.EPSILON || me > SpatialIndex.EPSILON)
202 | {
203 | int cIterations;
204 |
205 | if (m_children > m_pTree.m_nearMinimumOverlapFactor)
206 | {
207 | // sort entries in increasing order of enlargement.
208 | Arrays.sort(entries, new OverlapEntryComparator());
209 | cIterations = m_pTree.m_nearMinimumOverlapFactor;
210 | }
211 | else
212 | {
213 | cIterations = m_children;
214 | }
215 |
216 | // calculate overlap of most important original entries (near minimum overlap cost).
217 | for (int cIndex = 0; cIndex < cIterations; cIndex++)
218 | {
219 | double dif = 0.0;
220 | OverlapEntry e = entries[cIndex];
221 |
222 | for (int cChild = 0; cChild < m_children; cChild++)
223 | {
224 | if (e.m_id != cChild)
225 | {
226 | double f = e.m_combined.getIntersectingArea(m_pMBR[cChild]);
227 | if (f != 0.0) dif += f - e.m_original.getIntersectingArea(m_pMBR[cChild]);
228 | }
229 | } // for (cChild)
230 |
231 | if (dif < leastOverlap)
232 | {
233 | leastOverlap = dif;
234 | best = cIndex;
235 | }
236 | else if (dif == leastOverlap)
237 | {
238 | if (e.m_enlargement == entries[best].m_enlargement)
239 | {
240 | // keep the one with least area.
241 | if (e.m_original.getArea() < entries[best].m_original.getArea()) best = cIndex;
242 | }
243 | else
244 | {
245 | // keep the one with least enlargement.
246 | if (e.m_enlargement < entries[best].m_enlargement) best = cIndex;
247 | }
248 | }
249 | } // for (cIndex)
250 | }
251 |
252 | return entries[best].m_id;
253 | }
254 |
255 | protected void adjustTree(Node n, Stack pathBuffer)
256 | {
257 | m_pTree.m_stats.m_adjustments++;
258 |
259 | // find entry pointing to old node;
260 | int child;
261 | for (child = 0; child < m_children; child++)
262 | {
263 | if (m_pIdentifier[child] == n.m_identifier) break;
264 | }
265 |
266 | // MBR needs recalculation if either:
267 | // 1. the NEW child MBR is not contained.
268 | // 2. the OLD child MBR is touching.
269 | boolean b = m_nodeMBR.contains(n.m_nodeMBR);
270 | boolean recalc = (! b) ? true : m_nodeMBR.touches(m_pMBR[child]);
271 |
272 | m_pMBR[child] = (Region) n.m_nodeMBR.clone();
273 |
274 | if (recalc)
275 | {
276 | for (int cDim = 0; cDim < m_pTree.m_dimension; cDim++)
277 | {
278 | m_nodeMBR.m_pLow[cDim] = Double.POSITIVE_INFINITY;
279 | m_nodeMBR.m_pHigh[cDim] = Double.NEGATIVE_INFINITY;
280 |
281 | for (int cChild = 0; cChild < m_children; cChild++)
282 | {
283 | m_nodeMBR.m_pLow[cDim] = Math.min(m_nodeMBR.m_pLow[cDim], m_pMBR[cChild].m_pLow[cDim]);
284 | m_nodeMBR.m_pHigh[cDim] = Math.max(m_nodeMBR.m_pHigh[cDim], m_pMBR[cChild].m_pHigh[cDim]);
285 | }
286 | }
287 | }
288 |
289 | m_pTree.writeNode(this);
290 |
291 | if (recalc && ! pathBuffer.empty())
292 | {
293 | int cParent = ((Integer) pathBuffer.pop()).intValue();
294 | Index p = (Index) m_pTree.readNode(cParent);
295 | p.adjustTree(this, pathBuffer);
296 | }
297 | }
298 |
299 | protected void adjustTree(Node n1, Node n2, Stack pathBuffer, boolean[] overflowTable)
300 | {
301 | m_pTree.m_stats.m_adjustments++;
302 |
303 | // find entry pointing to old node;
304 | int child;
305 | for (child = 0; child < m_children; child++)
306 | {
307 | if (m_pIdentifier[child] == n1.m_identifier) break;
308 | }
309 |
310 | // MBR needs recalculation if either:
311 | // 1. the NEW child MBR is not contained.
312 | // 2. the OLD child MBR is touching.
313 | boolean b = m_nodeMBR.contains(n1.m_nodeMBR);
314 | boolean recalc = (! b) ? true : m_nodeMBR.touches(m_pMBR[child]);
315 |
316 | m_pMBR[child] = (Region) n1.m_nodeMBR.clone();
317 |
318 | if (recalc)
319 | {
320 | for (int cDim = 0; cDim < m_pTree.m_dimension; cDim++)
321 | {
322 | m_nodeMBR.m_pLow[cDim] = Double.POSITIVE_INFINITY;
323 | m_nodeMBR.m_pHigh[cDim] = Double.NEGATIVE_INFINITY;
324 |
325 | for (int cChild = 0; cChild < m_children; cChild++)
326 | {
327 | m_nodeMBR.m_pLow[cDim] = Math.min(m_nodeMBR.m_pLow[cDim], m_pMBR[cChild].m_pLow[cDim]);
328 | m_nodeMBR.m_pHigh[cDim] = Math.max(m_nodeMBR.m_pHigh[cDim], m_pMBR[cChild].m_pHigh[cDim]);
329 | }
330 | }
331 | }
332 |
333 | // No write necessary here. insertData will write the node if needed.
334 | //m_pTree.writeNode(this);
335 |
336 | boolean adjusted = insertData(null, (Region) n2.m_nodeMBR.clone(), n2.m_identifier, pathBuffer, overflowTable);
337 |
338 | // if n2 is contained in the node and there was no split or reinsert,
339 | // we need to adjust only if recalculation took place.
340 | // In all other cases insertData above took care of adjustment.
341 | if (! adjusted && recalc && ! pathBuffer.empty())
342 | {
343 | int cParent = ((Integer) pathBuffer.pop()).intValue();
344 | Index p = (Index) m_pTree.readNode(cParent);
345 | p.adjustTree(this, pathBuffer);
346 | }
347 | }
348 |
349 | class OverlapEntry
350 | {
351 | int m_id;
352 | double m_enlargement;
353 | Region m_original;
354 | Region m_combined;
355 | double m_oa;
356 | double m_ca;
357 | }
358 |
359 | class OverlapEntryComparator implements Comparator
360 | {
361 | public int compare(Object o1, Object o2)
362 | {
363 | OverlapEntry e1 = (OverlapEntry) o1;
364 | OverlapEntry e2 = (OverlapEntry) o2;
365 |
366 | if (e1.m_enlargement < e2.m_enlargement) return -1;
367 | if (e1.m_enlargement > e2.m_enlargement) return 1;
368 | return 0;
369 | }
370 | }
371 | }
372 |
--------------------------------------------------------------------------------
/src/test/java/sil/rtree/Leaf.java:
--------------------------------------------------------------------------------
1 | // Spatial Index Library
2 | //
3 | // Copyright (C) 2002 Navel Ltd.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 | //
19 | // Contact information:
20 | // Mailing address:
21 | // Marios Hadjieleftheriou
22 | // University of California, Riverside
23 | // Department of Computer Science
24 | // Surge Building, Room 310
25 | // Riverside, CA 92521
26 | //
27 | // Email:
28 | // marioh@cs.ucr.edu
29 |
30 | package sil.rtree;
31 |
32 | import java.util.ArrayList;
33 | import java.util.Stack;
34 |
35 | import sil.spatialindex.Region;
36 | import sil.spatialindex.SpatialIndex;
37 |
38 | public class Leaf extends Node
39 | {
40 | public Leaf(RTree pTree, int id)
41 | {
42 | super(pTree, id, 0, pTree.m_leafCapacity);
43 | }
44 |
45 | protected Node chooseSubtree(Region mbr, int level, Stack pathBuffer)
46 | {
47 | return this;
48 | }
49 |
50 | protected Leaf findLeaf(Region mbr, int id, Stack pathBuffer)
51 | {
52 | for (int cChild = 0; cChild < m_children; cChild++)
53 | {
54 | if (m_pIdentifier[cChild] == id && mbr.equals(m_pMBR[cChild])) return this;
55 | }
56 |
57 | return null;
58 | }
59 |
60 | protected Node[] split(byte[] pData, Region mbr, int id)
61 | {
62 | m_pTree.m_stats.m_splits++;
63 |
64 | ArrayList g1 = new ArrayList(), g2 = new ArrayList();
65 |
66 | switch (m_pTree.m_treeVariant)
67 | {
68 | case SpatialIndex.RtreeVariantLinear:
69 | case SpatialIndex.RtreeVariantQuadratic:
70 | rtreeSplit(pData, mbr, id, g1, g2);
71 | break;
72 | case SpatialIndex.RtreeVariantRstar:
73 | rstarSplit(pData, mbr, id, g1, g2);
74 | break;
75 | default:
76 | throw new IllegalStateException("Unknown RTree variant.");
77 | }
78 |
79 | Node left = new Leaf(m_pTree, -1);
80 | Node right = new Leaf(m_pTree, -1);
81 |
82 | int cIndex;
83 |
84 | for (cIndex = 0; cIndex < g1.size(); cIndex++)
85 | {
86 | int i = ((Integer) g1.get(cIndex)).intValue();
87 | left.insertEntry(m_pData[i], m_pMBR[i], m_pIdentifier[i]);
88 |
89 | // we don't want to delete the data array from this node's destructor!
90 | m_pData[i] = null;
91 | }
92 |
93 | for (cIndex = 0; cIndex < g2.size(); cIndex++)
94 | {
95 | int i = ((Integer) g2.get(cIndex)).intValue();
96 | right.insertEntry(m_pData[i], m_pMBR[i], m_pIdentifier[i]);
97 |
98 | // we don't want to delete the data array from this node's destructor!
99 | m_pData[i] = null;
100 | }
101 |
102 | Node[] ret = new Node[2];
103 | ret[0] = left;
104 | ret[1] = right;
105 | return ret;
106 | }
107 |
108 | protected void deleteData(int id, Stack pathBuffer)
109 | {
110 | int child;
111 | for (child = 0; child < m_children; child++)
112 | {
113 | if (m_pIdentifier[child] == id) break;
114 | }
115 |
116 | deleteEntry(child);
117 | m_pTree.writeNode(this);
118 |
119 | Stack toReinsert = new Stack();
120 | condenseTree(toReinsert, pathBuffer);
121 |
122 | // re-insert eliminated nodes.
123 | while (! toReinsert.empty())
124 | {
125 | Node n = (Node) toReinsert.pop();
126 | m_pTree.deleteNode(n);
127 |
128 | for (int cChild = 0; cChild < n.m_children; cChild++)
129 | {
130 | // keep this in the for loop. The tree height might change after insertions.
131 | boolean[] overflowTable = new boolean[m_pTree.m_stats.m_treeHeight];
132 | for (int cLevel = 0; cLevel < m_pTree.m_stats.m_treeHeight; cLevel++) overflowTable[cLevel] = false;
133 |
134 | m_pTree.insertData_impl(n.m_pData[cChild],
135 | n.m_pMBR[cChild], n.m_pIdentifier[cChild],
136 | n.m_level, overflowTable);
137 | n.m_pData[cChild] = null;
138 | }
139 | }
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/src/test/java/sil/rtree/Statistics.java:
--------------------------------------------------------------------------------
1 | // Spatial Index Library
2 | //
3 | // Copyright (C) 2002 Navel Ltd.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 | //
19 | // Contact information:
20 | // Mailing address:
21 | // Marios Hadjieleftheriou
22 | // University of California, Riverside
23 | // Department of Computer Science
24 | // Surge Building, Room 310
25 | // Riverside, CA 92521
26 | //
27 | // Email:
28 | // marioh@cs.ucr.edu
29 |
30 | package sil.rtree;
31 |
32 | import java.util.ArrayList;
33 |
34 | import sil.spatialindex.IStatistics;
35 |
36 | public class Statistics implements IStatistics, Cloneable
37 | {
38 | protected long m_reads;
39 | protected long m_writes;
40 | protected long m_splits;
41 | protected long m_hits;
42 | protected long m_misses;
43 | protected long m_nodes;
44 | protected long m_adjustments;
45 | protected long m_queryResults;
46 | protected long m_data;
47 | protected int m_treeHeight;
48 | protected ArrayList m_nodesInLevel = new ArrayList();
49 |
50 | public Statistics()
51 | {
52 | reset();
53 | }
54 |
55 | public Statistics(Statistics s)
56 | {
57 | m_reads = s.m_reads;
58 | m_writes = s.m_writes;
59 | m_splits = s.m_splits;
60 | m_hits = s.m_hits;
61 | m_misses = s.m_misses;
62 | m_nodes = s.m_nodes;
63 | m_adjustments = s.m_adjustments;
64 | m_queryResults = s.m_queryResults;
65 | m_data = s.m_data;
66 | m_treeHeight = s.m_treeHeight;
67 | m_nodesInLevel = (ArrayList) s.m_nodesInLevel.clone();
68 | }
69 |
70 | public long getReads()
71 | {
72 | return m_reads;
73 | }
74 |
75 | public long getWrites()
76 | {
77 | return m_writes;
78 | }
79 |
80 | public long getNumberOfNodes()
81 | {
82 | return m_nodes;
83 | }
84 |
85 | public long getNumberOfData()
86 | {
87 | return m_data;
88 | }
89 |
90 | public long getSplits()
91 | {
92 | return m_splits;
93 | }
94 |
95 | public long getHits()
96 | {
97 | return m_hits;
98 | }
99 |
100 | public long getMisses()
101 | {
102 | return m_misses;
103 | }
104 |
105 | public long getAdjustments()
106 | {
107 | return m_adjustments;
108 | }
109 |
110 | public long getQueryResults()
111 | {
112 | return m_queryResults;
113 | }
114 |
115 | public int getTreeHeight()
116 | {
117 | return m_treeHeight;
118 | }
119 |
120 | public int getNumberOfNodesInLevel(int l) throws IndexOutOfBoundsException
121 | {
122 | return ((Integer) m_nodesInLevel.get(l)).intValue();
123 | }
124 |
125 | public void reset()
126 | {
127 | m_reads = 0;
128 | m_writes = 0;
129 | m_splits = 0;
130 | m_hits = 0;
131 | m_misses = 0;
132 | m_nodes = 0;
133 | m_adjustments = 0;
134 | m_queryResults = 0;
135 | m_data = 0;
136 | m_treeHeight = 0;
137 | m_nodesInLevel.clear();
138 | }
139 |
140 | public String toString()
141 | {
142 | String s = "Reads: " + m_reads + "\n" +
143 | "Writes: " + m_writes + "\n" +
144 | "Hits: " + m_hits + "\n" +
145 | "Misses: " + m_misses + "\n" +
146 | "Tree height: " + m_treeHeight + "\n" +
147 | "Number of data: " + m_data + "\n" +
148 | "Number of nodes: " + m_nodes + "\n";
149 |
150 | for (int cLevel = 0; cLevel < m_treeHeight; cLevel++)
151 | {
152 | s += "Level " + cLevel + " pages: " + ((Integer) m_nodesInLevel.get(cLevel)).intValue() + "\n";
153 | }
154 |
155 | s += "Splits: " + m_splits + "\n" +
156 | "Adjustments: " + m_adjustments + "\n" +
157 | "Query results: " + m_queryResults;
158 |
159 | return s;
160 | }
161 |
162 | public Object clone()
163 | {
164 | return new Statistics(this);
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/src/test/java/sil/rtree/makefile:
--------------------------------------------------------------------------------
1 | # Spatial Index Library
2 | #
3 | # Copyright (C) 2002 Navel Ltd.
4 | #
5 | # This library is free software; you can redistribute it and/or
6 | # modify it under the terms of the GNU Lesser General Public
7 | # License as published by the Free Software Foundation; either
8 | # version 2.1 of the License, or (at your option) any later version.
9 | #
10 | # This library is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # Lesser General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU Lesser General Public
16 | # License along with this library; if not, write to the Free Software
17 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 | #
19 | # Contact information:
20 | # Mailing address:
21 | # Marios Hadjieleftheriou
22 | # University of California, Riverside
23 | # Department of Computer Science
24 | # Surge Building, Room 310
25 | # Riverside, CA 92521
26 | #
27 | # Email:
28 | # marioh@cs.ucr.edu
29 |
30 | all:
31 | javac -source 1.4 -classpath ../lib -d ../lib -g:none *.java
32 |
33 | debug:
34 | javac -source 1.4 -classpath ../lib -d ../lib -g *.java
35 |
36 | clean:
37 | rm -rf ../lib/spatialindex/rtree
38 |
39 |
--------------------------------------------------------------------------------
/src/test/java/sil/spatialindex/IData.java:
--------------------------------------------------------------------------------
1 | // Spatial Index Library
2 | //
3 | // Copyright (C) 2002 Navel Ltd.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 | //
19 | // Contact information:
20 | // Mailing address:
21 | // Marios Hadjieleftheriou
22 | // University of California, Riverside
23 | // Department of Computer Science
24 | // Surge Building, Room 310
25 | // Riverside, CA 92521
26 | //
27 | // Email:
28 | // marioh@cs.ucr.edu
29 |
30 | package sil.spatialindex;
31 |
32 | public interface IData extends IEntry
33 | {
34 | public byte[] getData();
35 | } // IData
36 |
--------------------------------------------------------------------------------
/src/test/java/sil/spatialindex/IEntry.java:
--------------------------------------------------------------------------------
1 | // Spatial Index Library
2 | //
3 | // Copyright (C) 2002 Navel Ltd.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 | //
19 | // Contact information:
20 | // Mailing address:
21 | // Marios Hadjieleftheriou
22 | // University of California, Riverside
23 | // Department of Computer Science
24 | // Surge Building, Room 310
25 | // Riverside, CA 92521
26 | //
27 | // Email:
28 | // marioh@cs.ucr.edu
29 |
30 | package sil.spatialindex;
31 |
32 | public interface IEntry
33 | {
34 | public int getIdentifier();
35 | public IShape getShape();
36 | } // IEntry
37 |
--------------------------------------------------------------------------------
/src/test/java/sil/spatialindex/INearestNeighborComparator.java:
--------------------------------------------------------------------------------
1 | // Spatial Index Library
2 | //
3 | // Copyright (C) 2002 Navel Ltd.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 | //
19 | // Contact information:
20 | // Mailing address:
21 | // Marios Hadjieleftheriou
22 | // University of California, Riverside
23 | // Department of Computer Science
24 | // Surge Building, Room 310
25 | // Riverside, CA 92521
26 | //
27 | // Email:
28 | // marioh@cs.ucr.edu
29 |
30 | package sil.spatialindex;
31 |
32 | public interface INearestNeighborComparator
33 | {
34 | public double getMinimumDistance(IShape query, IEntry e);
35 | } // INearestNeighborComparator
36 |
--------------------------------------------------------------------------------
/src/test/java/sil/spatialindex/INode.java:
--------------------------------------------------------------------------------
1 | // Spatial Index Library
2 | //
3 | // Copyright (C) 2002 Navel Ltd.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 | //
19 | // Contact information:
20 | // Mailing address:
21 | // Marios Hadjieleftheriou
22 | // University of California, Riverside
23 | // Department of Computer Science
24 | // Surge Building, Room 310
25 | // Riverside, CA 92521
26 | //
27 | // Email:
28 | // marioh@cs.ucr.edu
29 |
30 | package sil.spatialindex;
31 |
32 | public interface INode extends IEntry
33 | {
34 | public int getChildrenCount();
35 | public int getChildIdentifier(int index) throws IndexOutOfBoundsException;
36 | public IShape getChildShape(int index) throws IndexOutOfBoundsException;
37 | public int getLevel();
38 | public boolean isIndex();
39 | public boolean isLeaf();
40 | } // INode
41 |
--------------------------------------------------------------------------------
/src/test/java/sil/spatialindex/INodeCommand.java:
--------------------------------------------------------------------------------
1 | // Spatial Index Library
2 | //
3 | // Copyright (C) 2002 Navel Ltd.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 | //
19 | // Contact information:
20 | // Mailing address:
21 | // Marios Hadjieleftheriou
22 | // University of California, Riverside
23 | // Department of Computer Science
24 | // Surge Building, Room 310
25 | // Riverside, CA 92521
26 | //
27 | // Email:
28 | // marioh@cs.ucr.edu
29 |
30 | package sil.spatialindex;
31 |
32 | public interface INodeCommand
33 | {
34 | public void execute(INode n);
35 | } // INodeCommand
36 |
--------------------------------------------------------------------------------
/src/test/java/sil/spatialindex/IQueryStrategy.java:
--------------------------------------------------------------------------------
1 | //
2 | // This library is free software; you can redistribute it and/or
3 | // modify it under the terms of the GNU Lesser General Public
4 | // License as published by the Free Software Foundation; either
5 | // version 2.1 of the License, or (at your option) any later version.
6 | //
7 | // This library is distributed in the hope that it will be useful,
8 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 | // Lesser General Public License for more details.
11 | //
12 | // You should have received a copy of the GNU Lesser General Public
13 | // License along with this library; if not, write to the Free Software
14 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | //
16 | // Contact information:
17 | // Mailing address:
18 | // Marios Hadjieleftheriou
19 | // University of California, Riverside
20 | // Department of Computer Science
21 | // Surge Building, Room 310
22 | // Riverside, CA 92521
23 | //
24 | // Email:
25 | // marioh@cs.ucr.edu
26 |
27 | package sil.spatialindex;
28 |
29 | public interface IQueryStrategy
30 | {
31 | public void getNextEntry(IEntry e, int[] nextEntry, boolean[] hasNext);
32 | } // IQueryStrategy
33 |
--------------------------------------------------------------------------------
/src/test/java/sil/spatialindex/IShape.java:
--------------------------------------------------------------------------------
1 | // Spatial Index Library
2 | //
3 | // Copyright (C) 2002 Navel Ltd.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 | //
19 | // Contact information:
20 | // Mailing address:
21 | // Marios Hadjieleftheriou
22 | // University of California, Riverside
23 | // Department of Computer Science
24 | // Surge Building, Room 310
25 | // Riverside, CA 92521
26 | //
27 | // Email:
28 | // marioh@cs.ucr.edu
29 |
30 | package sil.spatialindex;
31 |
32 | public interface IShape
33 | {
34 | public boolean intersects(final IShape s);
35 | public boolean contains(final IShape s);
36 | public boolean touches(final IShape s);
37 | public double[] getCenter();
38 | public long getDimension();
39 | public Region getMBR();
40 | public double getArea();
41 | public double getMinimumDistance(final IShape s);
42 | } // IShape
43 |
--------------------------------------------------------------------------------
/src/test/java/sil/spatialindex/ISpatialIndex.java:
--------------------------------------------------------------------------------
1 | // Spatial Index Library
2 | //
3 | // Copyright (C) 2002 Navel Ltd.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 | //
19 | // Contact information:
20 | // Mailing address:
21 | // Marios Hadjieleftheriou
22 | // University of California, Riverside
23 | // Department of Computer Science
24 | // Surge Building, Room 310
25 | // Riverside, CA 92521
26 | //
27 | // Email:
28 | // marioh@cs.ucr.edu
29 |
30 | package sil.spatialindex;
31 |
32 | import sil.storagemanager.PropertySet;
33 |
34 | public interface ISpatialIndex
35 | {
36 | public void flush() throws IllegalStateException;
37 | public void insertData(final byte[] data, final IShape shape, int id);
38 | public boolean deleteData(final IShape shape, int id);
39 | public void containmentQuery(final IShape query, final IVisitor v);
40 | public void intersectionQuery(final IShape query, final IVisitor v);
41 | public void pointLocationQuery(final IShape query, final IVisitor v);
42 | public void nearestNeighborQuery(int k, final IShape query, final IVisitor v, INearestNeighborComparator nnc);
43 | public void nearestNeighborQuery(int k, final IShape query, final IVisitor v);
44 | public void queryStrategy(final IQueryStrategy qs);
45 | public PropertySet getIndexProperties();
46 | public void addWriteNodeCommand(INodeCommand nc);
47 | public void addReadNodeCommand(INodeCommand nc);
48 | public void addDeleteNodeCommand(INodeCommand nc);
49 | public boolean isIndexValid();
50 | public IStatistics getStatistics();
51 | } // ISpatialIndex
52 |
53 |
--------------------------------------------------------------------------------
/src/test/java/sil/spatialindex/IStatistics.java:
--------------------------------------------------------------------------------
1 | //
2 | // This library is free software; you can redistribute it and/or
3 | // modify it under the terms of the GNU Lesser General Public
4 | // License as published by the Free Software Foundation; either
5 | // version 2.1 of the License, or (at your option) any later version.
6 | //
7 | // This library is distributed in the hope that it will be useful,
8 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 | // Lesser General Public License for more details.
11 | //
12 | // You should have received a copy of the GNU Lesser General Public
13 | // License along with this library; if not, write to the Free Software
14 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | //
16 | // Contact information:
17 | // Mailing address:
18 | // Marios Hadjieleftheriou
19 | // University of California, Riverside
20 | // Department of Computer Science
21 | // Surge Building, Room 310
22 | // Riverside, CA 92521
23 | //
24 | // Email:
25 | // marioh@cs.ucr.edu
26 |
27 | package sil.spatialindex;
28 |
29 | public interface IStatistics
30 | {
31 | public long getReads();
32 | public long getWrites();
33 | public long getNumberOfNodes();
34 | public long getNumberOfData();
35 | } // IStatistics
36 |
--------------------------------------------------------------------------------
/src/test/java/sil/spatialindex/IVisitor.java:
--------------------------------------------------------------------------------
1 | //
2 | // This library is free software; you can redistribute it and/or
3 | // modify it under the terms of the GNU Lesser General Public
4 | // License as published by the Free Software Foundation; either
5 | // version 2.1 of the License, or (at your option) any later version.
6 | //
7 | // This library is distributed in the hope that it will be useful,
8 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 | // Lesser General Public License for more details.
11 | //
12 | // You should have received a copy of the GNU Lesser General Public
13 | // License along with this library; if not, write to the Free Software
14 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | //
16 | // Contact information:
17 | // Mailing address:
18 | // Marios Hadjieleftheriou
19 | // University of California, Riverside
20 | // Department of Computer Science
21 | // Surge Building, Room 310
22 | // Riverside, CA 92521
23 | //
24 | // Email:
25 | // marioh@cs.ucr.edu
26 |
27 | package sil.spatialindex;
28 |
29 | public interface IVisitor
30 | {
31 | public void visitNode(final INode n);
32 | public void visitData(final IData d);
33 | } // IVisitor
34 |
--------------------------------------------------------------------------------
/src/test/java/sil/spatialindex/Point.java:
--------------------------------------------------------------------------------
1 | // Spatial Index Library
2 | //
3 | // Copyright (C) 2002 Navel Ltd.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 | //
19 | // Contact information:
20 | // Mailing address:
21 | // Marios Hadjieleftheriou
22 | // University of California, Riverside
23 | // Department of Computer Science
24 | // Surge Building, Room 310
25 | // Riverside, CA 92521
26 | //
27 | // Email:
28 | // marioh@cs.ucr.edu
29 |
30 | package sil.spatialindex;
31 |
32 | public class Point implements IShape, Cloneable
33 | {
34 | public double[] m_pCoords = null;
35 |
36 | public Point(double[] pCoords)
37 | {
38 | m_pCoords = new double[pCoords.length];
39 | System.arraycopy(pCoords, 0, m_pCoords, 0, pCoords.length);
40 | }
41 |
42 | public Point(final Point pt)
43 | {
44 | m_pCoords = new double[pt.m_pCoords.length];
45 | System.arraycopy(pt.m_pCoords, 0, m_pCoords, 0, pt.m_pCoords.length);
46 | }
47 |
48 | public boolean equals(Object o)
49 | {
50 | if (o instanceof Point)
51 | {
52 | Point pt = (Point) o;
53 |
54 | if (pt.m_pCoords.length != m_pCoords.length) return false;
55 |
56 | for (int cIndex = 0; cIndex < m_pCoords.length; cIndex++)
57 | {
58 | if (m_pCoords[cIndex] < pt.m_pCoords[cIndex] - SpatialIndex.EPSILON ||
59 | m_pCoords[cIndex] > pt.m_pCoords[cIndex] + SpatialIndex.EPSILON) return false;
60 | }
61 |
62 | return true;
63 | }
64 |
65 | return false;
66 | }
67 |
68 | //
69 | // Cloneable interface
70 | //
71 |
72 | public Object clone()
73 | {
74 | return new Point(m_pCoords);
75 | }
76 |
77 | //
78 | // IShape interface
79 | //
80 |
81 | public boolean intersects(final IShape s)
82 | {
83 | if (s instanceof Region) return ((Region) s).contains(this);
84 |
85 | return false;
86 | }
87 |
88 | public boolean contains(final IShape s)
89 | {
90 | return false;
91 | }
92 |
93 | public boolean touches(final IShape s)
94 | {
95 | if (s instanceof Point && this.equals(s)) return true;
96 |
97 | if (s instanceof Region) return ((Region) s).touches(this);
98 |
99 | return false;
100 | }
101 |
102 | public double[] getCenter()
103 | {
104 | double[] pCoords = new double[m_pCoords.length];
105 | System.arraycopy(m_pCoords, 0, pCoords, 0, m_pCoords.length);
106 | return pCoords;
107 | }
108 |
109 | public long getDimension()
110 | {
111 | return m_pCoords.length;
112 | }
113 |
114 | public Region getMBR()
115 | {
116 | return new Region(m_pCoords, m_pCoords);
117 | }
118 |
119 | public double getArea()
120 | {
121 | return 0.0f;
122 | }
123 |
124 | public double getMinimumDistance(final IShape s)
125 | {
126 | if (s instanceof Region) return ((Region) s).getMinimumDistance(this);
127 |
128 | if (s instanceof Point) return getMinimumDistance((Point) s);
129 |
130 | throw new IllegalStateException("getMinimumDistance: Not implemented yet!");
131 | }
132 |
133 | double getMinimumDistance(final Point p)
134 | {
135 | if (m_pCoords.length != p.m_pCoords.length) throw new IllegalArgumentException("getMinimumDistance: Shape has the wrong number of dimensions.");
136 |
137 | double ret = 0.0;
138 |
139 | for (int cIndex = 0; cIndex < m_pCoords.length; cIndex++)
140 | {
141 | ret += Math.pow(m_pCoords[cIndex] - p.m_pCoords[cIndex], 2.0);
142 | }
143 |
144 | return Math.sqrt(ret);
145 | }
146 |
147 | public double getCoord(int index) throws IndexOutOfBoundsException
148 | {
149 | if (index >= m_pCoords.length) throw new IndexOutOfBoundsException("" + index);
150 | return m_pCoords[index];
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/src/test/java/sil/spatialindex/RWLock.java:
--------------------------------------------------------------------------------
1 | // Spatial Index Library
2 | //
3 | // Copyright (C) 2002 Navel Ltd.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License aint with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 | //
19 | // Contact information:
20 | // Mailing address:
21 | // Marios Hadjieleftheriou
22 | // University of California, Riverside
23 | // Department of Computer Science
24 | // Surge Building, Room 310
25 | // Riverside, CA 92521
26 | //
27 | // Email:
28 | // marioh@cs.ucr.edu
29 |
30 | // Readers/Writers lock by Allen Holub
31 |
32 | package sil.spatialindex;
33 |
34 | import java.util.*;
35 |
36 | public class RWLock
37 | {
38 | private int active_readers;
39 | private int waiting_readers;
40 | private int active_writers;
41 |
42 | private final LinkedList writer_locks = new LinkedList();
43 |
44 | public synchronized void read_lock()
45 | {
46 | if (active_writers == 0 && writer_locks.size() == 0)
47 | ++active_readers;
48 | else
49 | {
50 | ++waiting_readers;
51 | try{ wait(); } catch (InterruptedException e) {}
52 | }
53 | }
54 |
55 | public synchronized boolean read_lock_noblock()
56 | {
57 | if (active_writers == 0 && writer_locks.size() == 0)
58 | {
59 | ++active_readers;
60 | return true;
61 | }
62 | return false;
63 | }
64 |
65 | public synchronized void read_unlock()
66 | {
67 | if (--active_readers == 0) notify_writers();
68 | }
69 |
70 | public void write_lock()
71 | {
72 | Object lock = new Object();
73 | synchronized(lock)
74 | {
75 | synchronized(this)
76 | {
77 | boolean okay_to_write = writer_locks.size() == 0 && active_readers == 0 && active_writers == 0;
78 | if (okay_to_write)
79 | {
80 | ++active_writers;
81 | return; // the "return" jumps over the "wait" call
82 | }
83 |
84 | writer_locks.addLast(lock);
85 | }
86 | try { lock.wait(); } catch (InterruptedException e) {}
87 | }
88 | }
89 |
90 | synchronized public boolean write_lock_noblock()
91 | {
92 | if (writer_locks.size() == 0 && active_readers == 0 && active_writers == 0)
93 | {
94 | ++active_writers;
95 | return true;
96 | }
97 | return false;
98 | }
99 |
100 | public synchronized void write_unlock()
101 | {
102 | --active_writers;
103 | if (waiting_readers > 0) // priority to waiting readers
104 | notify_readers();
105 | else
106 | notify_writers();
107 | }
108 |
109 | private void notify_readers() // must be accessed from a
110 | { // synchronized method
111 | active_readers += waiting_readers;
112 | waiting_readers = 0;
113 | notifyAll();
114 | }
115 |
116 | private void notify_writers() // must be accessed from a
117 | { // synchronized method
118 | if (writer_locks.size() > 0)
119 | {
120 | Object oldest = writer_locks.removeFirst();
121 | ++active_writers;
122 | synchronized(oldest) { oldest.notify(); }
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/src/test/java/sil/spatialindex/Region.java:
--------------------------------------------------------------------------------
1 | // Spatial Index Library
2 | //
3 | // Copyright (C) 2002 Navel Ltd.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 | //
19 | // Contact information:
20 | // Mailing address:
21 | // Marios Hadjieleftheriou
22 | // University of California, Riverside
23 | // Department of Computer Science
24 | // Surge Building, Room 310
25 | // Riverside, CA 92521
26 | //
27 | // Email:
28 | // marioh@cs.ucr.edu
29 |
30 | package sil.spatialindex;
31 |
32 | public class Region implements IShape
33 | {
34 | public double[] m_pLow = null;
35 | public double[] m_pHigh = null;
36 |
37 | public Region()
38 | {
39 | }
40 |
41 | public Region(final double[] pLow, final double[] pHigh)
42 | {
43 | if (pLow.length != pHigh.length) throw new IllegalArgumentException("Region: arguments have different number of dimensions.");
44 |
45 | m_pLow = new double[pLow.length];
46 | System.arraycopy(pLow, 0, m_pLow, 0, pLow.length);
47 |
48 | m_pHigh = new double[pHigh.length];
49 | System.arraycopy(pHigh, 0, m_pHigh, 0, pHigh.length);
50 | }
51 |
52 | public Region(final Point low, final Point high)
53 | {
54 | if (low.m_pCoords.length != high.m_pCoords.length) throw new IllegalArgumentException("Region: arguments have different number of dimensions.");
55 |
56 | m_pLow = new double[low.m_pCoords.length];
57 | System.arraycopy(low.m_pCoords, 0, m_pLow, 0, low.m_pCoords.length);
58 | m_pHigh = new double[high.m_pCoords.length];
59 | System.arraycopy(high.m_pCoords, 0, m_pHigh, 0, high.m_pCoords.length);
60 | }
61 |
62 | public Region(final Region r)
63 | {
64 | m_pLow = new double[r.m_pLow.length];
65 | System.arraycopy(r.m_pLow, 0, m_pLow, 0, r.m_pLow.length);
66 | m_pHigh = new double[r.m_pHigh.length];
67 | System.arraycopy(r.m_pHigh, 0, m_pHigh, 0, r.m_pHigh.length);
68 | }
69 |
70 | public boolean equals(Object o)
71 | {
72 | if (o instanceof Region)
73 | {
74 | Region r = (Region) o;
75 |
76 | if (r.m_pLow.length != m_pLow.length) return false;
77 |
78 | for (int cIndex = 0; cIndex < m_pLow.length; cIndex++)
79 | {
80 | if (m_pLow[cIndex] < r.m_pLow[cIndex] - SpatialIndex.EPSILON || m_pLow[cIndex] > r.m_pLow[cIndex] + SpatialIndex.EPSILON ||
81 | m_pHigh[cIndex] < r.m_pHigh[cIndex] - SpatialIndex.EPSILON || m_pHigh[cIndex] > r.m_pHigh[cIndex] + SpatialIndex.EPSILON)
82 | return false;
83 | }
84 | return true;
85 | }
86 | return false;
87 | }
88 |
89 | //
90 | // Cloneable interface
91 | //
92 |
93 | public Object clone()
94 | {
95 | return new Region(m_pLow, m_pHigh);
96 | }
97 |
98 | //
99 | // IShape interface
100 | //
101 |
102 | public boolean intersects(final IShape s)
103 | {
104 | if (s instanceof Region) return intersects((Region) s);
105 |
106 | if (s instanceof Point) return contains((Point) s);
107 |
108 | throw new IllegalStateException("intersects: Not implemented yet!");
109 | }
110 |
111 | public boolean contains(final IShape s)
112 | {
113 | if (s instanceof Region) return contains((Region) s);
114 |
115 | if (s instanceof Point) return contains((Point) s);
116 |
117 | throw new IllegalStateException("contains: Not implemented yet!");
118 | }
119 |
120 | public boolean touches(final IShape s)
121 | {
122 | if (s instanceof Region) return touches((Region) s);
123 |
124 | if (s instanceof Point) return touches((Point) s);
125 |
126 | throw new IllegalStateException("touches: Not implemented yet!");
127 | }
128 |
129 | public double[] getCenter()
130 | {
131 | double[] pCoords = new double[m_pLow.length];
132 |
133 | for (int cIndex = 0; cIndex < m_pLow.length; cIndex++)
134 | {
135 | pCoords[cIndex] = (m_pLow[cIndex] + m_pHigh[cIndex]) / 2.0;
136 | }
137 |
138 | return pCoords;
139 | }
140 |
141 | public long getDimension()
142 | {
143 | return m_pLow.length;
144 | }
145 |
146 | public Region getMBR()
147 | {
148 | return new Region(m_pLow, m_pHigh);
149 | }
150 |
151 | public double getArea()
152 | {
153 | double area = 1.0;
154 |
155 | for (int cIndex = 0; cIndex < m_pLow.length; cIndex++)
156 | {
157 | area *= m_pHigh[cIndex] - m_pLow[cIndex];
158 | }
159 |
160 | return area;
161 | }
162 |
163 | public double getMinimumDistance(final IShape s)
164 | {
165 | if (s instanceof Region) return getMinimumDistance((Region) s);
166 |
167 | if (s instanceof Point) return getMinimumDistance((Point) s);
168 |
169 | throw new IllegalStateException("getMinimumDistance: Not implemented yet!");
170 | }
171 |
172 | public boolean intersects(final Region r)
173 | {
174 | if (m_pLow.length != r.m_pLow.length) throw new IllegalArgumentException("intersects: Shape has the wrong number of dimensions.");
175 |
176 | for (int cIndex = 0; cIndex < m_pLow.length; cIndex++)
177 | {
178 | if (m_pLow[cIndex] > r.m_pHigh[cIndex] || m_pHigh[cIndex] < r.m_pLow[cIndex]) return false;
179 | }
180 | return true;
181 | }
182 |
183 | public boolean contains(final Region r)
184 | {
185 | if (m_pLow.length != r.m_pLow.length) throw new IllegalArgumentException("contains: Shape has the wrong number of dimensions.");
186 |
187 | for (int cIndex = 0; cIndex < m_pLow.length; cIndex++)
188 | {
189 | if (m_pLow[cIndex] > r.m_pLow[cIndex] || m_pHigh[cIndex] < r.m_pHigh[cIndex]) return false;
190 | }
191 | return true;
192 | }
193 |
194 | public boolean touches(final Region r)
195 | {
196 | if (m_pLow.length != r.m_pLow.length) throw new IllegalArgumentException("touches: Shape has the wrong number of dimensions.");
197 |
198 | for (int cIndex = 0; cIndex < m_pLow.length; cIndex++)
199 | {
200 | if ((m_pLow[cIndex] > r.m_pLow[cIndex] - SpatialIndex.EPSILON && m_pLow[cIndex] < r.m_pLow[cIndex] + SpatialIndex.EPSILON) ||
201 | (m_pHigh[cIndex] > r.m_pHigh[cIndex] - SpatialIndex.EPSILON && m_pHigh[cIndex] < r.m_pHigh[cIndex] + SpatialIndex.EPSILON))
202 | return true;
203 | }
204 | return false;
205 | }
206 |
207 | public double getMinimumDistance(final Region r)
208 | {
209 | if (m_pLow.length != r.m_pLow.length) throw new IllegalArgumentException("getMinimumDistance: Shape has the wrong number of dimensions.");
210 |
211 | double ret = 0.0;
212 |
213 | for (int cIndex = 0; cIndex < m_pLow.length; cIndex++)
214 | {
215 | double x = 0.0;
216 |
217 | if (r.m_pHigh[cIndex] < m_pLow[cIndex])
218 | {
219 | x = Math.abs(r.m_pHigh[cIndex] - m_pLow[cIndex]);
220 | }
221 | else if (m_pHigh[cIndex] < r.m_pLow[cIndex])
222 | {
223 | x = Math.abs(r.m_pLow[cIndex] - m_pHigh[cIndex]);
224 | }
225 |
226 | ret += x * x;
227 | }
228 |
229 | return Math.sqrt(ret);
230 | }
231 |
232 | public boolean contains(final Point p)
233 | {
234 | if (m_pLow.length != p.m_pCoords.length) throw new IllegalArgumentException("contains: Shape has the wrong number of dimensions.");
235 |
236 | for (int cIndex = 0; cIndex < m_pLow.length; cIndex++)
237 | {
238 | if (m_pLow[cIndex] > p.m_pCoords[cIndex] || m_pHigh[cIndex] < p.m_pCoords[cIndex]) return false;
239 | }
240 | return true;
241 | }
242 |
243 | public boolean touches(final Point p)
244 | {
245 | if (m_pLow.length != p.m_pCoords.length) throw new IllegalArgumentException("touches: Shape has the wrong number of dimensions.");
246 |
247 | for (int cIndex = 0; cIndex < m_pLow.length; cIndex++)
248 | {
249 | if ((m_pLow[cIndex] > p.m_pCoords[cIndex] - SpatialIndex.EPSILON && m_pLow[cIndex] < p.m_pCoords[cIndex] + SpatialIndex.EPSILON) ||
250 | (m_pHigh[cIndex] > p.m_pCoords[cIndex] - SpatialIndex.EPSILON && m_pHigh[cIndex] < p.m_pCoords[cIndex] + SpatialIndex.EPSILON))
251 | return true;
252 | }
253 | return false;
254 | }
255 |
256 | public double getMinimumDistance(final Point p)
257 | {
258 | if (m_pLow.length != p.m_pCoords.length) throw new IllegalArgumentException("getMinimumDistance: Shape has the wrong number of dimensions.");
259 |
260 | double ret = 0.0;
261 |
262 | for (int cIndex = 0; cIndex < m_pLow.length; cIndex++)
263 | {
264 | if (p.m_pCoords[cIndex] < m_pLow[cIndex])
265 | {
266 | ret += Math.pow(m_pLow[cIndex] - p.m_pCoords[cIndex], 2.0);
267 | }
268 | else if (p.m_pCoords[cIndex] > m_pHigh[cIndex])
269 | {
270 | ret += Math.pow(p.m_pCoords[cIndex] - m_pHigh[cIndex], 2.0);
271 | }
272 | }
273 |
274 | return Math.sqrt(ret);
275 | }
276 |
277 | public double getIntersectingArea(final Region r)
278 | {
279 | if (m_pLow.length != r.m_pLow.length) throw new IllegalArgumentException("getIntersectingArea: Shape has the wrong number of dimensions.");
280 |
281 | int cIndex;
282 |
283 | // check for intersection.
284 | // marioh: avoid function call since this is called billions of times.
285 | for (cIndex = 0; cIndex < m_pLow.length; cIndex++)
286 | {
287 | if (m_pLow[cIndex] > r.m_pHigh[cIndex] || m_pHigh[cIndex] < r.m_pLow[cIndex]) return 0.0;
288 | }
289 |
290 | double ret = 1.0;
291 | double f1, f2;
292 |
293 | for (cIndex = 0; cIndex < m_pLow.length; cIndex++)
294 | {
295 | f1 = Math.max(m_pLow[cIndex], r.m_pLow[cIndex]);
296 | f2 = Math.min(m_pHigh[cIndex], r.m_pHigh[cIndex]);
297 | ret *= f2 - f1;
298 | }
299 |
300 | return ret;
301 | }
302 |
303 | public Region combinedRegion(final Region r)
304 | {
305 | if (m_pLow.length != r.m_pLow.length) throw new IllegalArgumentException("combinedRegion: Shape has the wrong number of dimensions.");
306 |
307 | double[] mn = new double[m_pLow.length];
308 | double[] mx = new double[m_pLow.length];
309 |
310 | for (int cIndex = 0; cIndex < m_pLow.length; cIndex++)
311 | {
312 | mn[cIndex] = Math.min(m_pLow[cIndex], r.m_pLow[cIndex]);
313 | mx[cIndex] = Math.max(m_pHigh[cIndex], r.m_pHigh[cIndex]);
314 | }
315 |
316 | return new Region(mn, mx);
317 | }
318 |
319 | public static Region combinedRegion(Region[] pRegions)
320 | {
321 | double[] mn = new double[pRegions[0].m_pLow.length];
322 | double[] mx = new double[pRegions[0].m_pLow.length];
323 |
324 | for (int cDim = 0; cDim < pRegions[0].m_pLow.length; cDim++)
325 | {
326 | mn[cDim] = Double.POSITIVE_INFINITY;
327 | mx[cDim] = Double.NEGATIVE_INFINITY;
328 |
329 | for (int cIndex = 0; cIndex < pRegions.length; cIndex++)
330 | {
331 | mn[cDim] = Math.min(mn[cDim], pRegions[cIndex].m_pLow[cDim]);
332 | mx[cDim] = Math.max(mx[cDim], pRegions[cIndex].m_pHigh[cDim]);
333 | }
334 | }
335 |
336 | return new Region(mn, mx);
337 | }
338 |
339 | // Modifies the first argument to include the second.
340 | public static void combinedRegion(Region pToModify, final Region pConst)
341 | {
342 | if (pToModify.m_pLow.length != pConst.m_pLow.length) throw new IllegalArgumentException("combineRegion: Shape has the wrong number of dimensions.");
343 |
344 | for (int cIndex = 0; cIndex < pToModify.m_pLow.length; cIndex++)
345 | {
346 | pToModify.m_pLow[cIndex] = Math.min(pToModify.m_pLow[cIndex], pConst.m_pLow[cIndex]);
347 | pToModify.m_pHigh[cIndex] = Math.max(pToModify.m_pHigh[cIndex], pConst.m_pHigh[cIndex]);
348 | }
349 | }
350 |
351 | // Returns the margin of a region. It is calcuated as the sum of 2^(d-1) * width in each dimension.
352 | public double getMargin()
353 | {
354 | double mul = Math.pow(2.0, ((double) m_pLow.length) - 1.0);
355 | double margin = 0.0;
356 |
357 | for (int cIndex = 0; cIndex < m_pLow.length; cIndex++)
358 | {
359 | margin += (m_pHigh[cIndex] - m_pLow[cIndex]) * mul;
360 | }
361 |
362 | return margin;
363 | }
364 |
365 | public double getLow(int index) throws IndexOutOfBoundsException
366 | {
367 | if (index >= m_pLow.length) throw new IndexOutOfBoundsException("" + index);
368 | return m_pLow[index];
369 | }
370 |
371 | public double getHigh(int index) throws IndexOutOfBoundsException
372 | {
373 | if (index >= m_pLow.length) throw new IndexOutOfBoundsException("" + index);
374 | return m_pHigh[index];
375 | }
376 |
377 | public String toString()
378 | {
379 | String s = "";
380 |
381 | for (int cIndex = 0; cIndex < m_pLow.length; cIndex++) s += m_pLow[cIndex] + " ";
382 |
383 | s += ": ";
384 |
385 | for (int cIndex = 0; cIndex < m_pHigh.length; cIndex++) s += m_pHigh[cIndex] + " ";
386 |
387 | return s;
388 | }
389 | }
390 |
--------------------------------------------------------------------------------
/src/test/java/sil/spatialindex/SpatialIndex.java:
--------------------------------------------------------------------------------
1 | // Spatial Index Library
2 | //
3 | // Copyright (C) 2002 Navel Ltd.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 | //
19 | // Contact information:
20 | // Mailing address:
21 | // Marios Hadjieleftheriou
22 | // University of California, Riverside
23 | // Department of Computer Science
24 | // Surge Building, Room 310
25 | // Riverside, CA 92521
26 | //
27 | // Email:
28 | // marioh@cs.ucr.edu
29 |
30 | package sil.spatialindex;
31 |
32 | import java.io.FileNotFoundException;
33 | import java.io.IOException;
34 |
35 | import sil.storagemanager.DiskStorageManager;
36 | import sil.storagemanager.IStorageManager;
37 | import sil.storagemanager.MemoryStorageManager;
38 | import sil.storagemanager.PropertySet;
39 |
40 | public class SpatialIndex
41 | {
42 | public static final String EMAIL = "marioh@cs.ucr.edu";
43 | public static final String VERSION = "0.44.2b";
44 | public static final String DATE = "27 July 2003";
45 |
46 | public static final double EPSILON = 1.192092896e-07;
47 |
48 | public static final int RtreeVariantQuadratic = 1;
49 | public static final int RtreeVariantLinear = 2;
50 | public static final int RtreeVariantRstar = 3;
51 |
52 | public static final int PersistentIndex = 1;
53 | public static final int PersistentLeaf = 2;
54 |
55 | public static final int ContainmentQuery = 1;
56 | public static final int IntersectionQuery = 2;
57 |
58 | public static ISpatialIndex createRTree(PropertySet ps, IStorageManager sm)
59 | {
60 | return null;
61 | }
62 |
63 | public static IStorageManager createMemoryStorageManager(PropertySet ps)
64 | {
65 | IStorageManager sm = (IStorageManager) new MemoryStorageManager();
66 | return sm;
67 | }
68 |
69 | public static IStorageManager createDiskStorageManager(PropertySet ps)
70 | throws SecurityException, NullPointerException, IOException, FileNotFoundException, IllegalArgumentException
71 | {
72 | IStorageManager sm = (IStorageManager) new DiskStorageManager(ps);
73 | return sm;
74 | }
75 | } // SpatialIndex
76 |
--------------------------------------------------------------------------------
/src/test/java/sil/storagemanager/Buffer.java:
--------------------------------------------------------------------------------
1 | // Spatial Index Library
2 | //
3 | // Copyright (C) 2002 Navel Ltd.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 | //
19 | // Contact information:
20 | // Mailing address:
21 | // Marios Hadjieleftheriou
22 | // University of California, Riverside
23 | // Department of Computer Science
24 | // Surge Building, Room 310
25 | // Riverside, CA 92521
26 | //
27 | // Email:
28 | // marioh@cs.ucr.edu
29 |
30 | package sil.storagemanager;
31 |
32 | import java.util.*;
33 |
34 | public abstract class Buffer implements IBuffer
35 | {
36 | int m_capacity = 10;
37 | boolean m_bWriteThrough = false;
38 | IStorageManager m_storageManager = null;
39 | HashMap m_buffer = new HashMap();
40 | long m_hits = 0;
41 |
42 | abstract void addEntry(int id, Entry entry);
43 | abstract void removeEntry();
44 |
45 | public Buffer(IStorageManager sm, int capacity, boolean bWriteThrough)
46 | {
47 | m_storageManager = sm;
48 | m_capacity = capacity;
49 | m_bWriteThrough = bWriteThrough;
50 | }
51 |
52 | public byte[] loadByteArray(final int id)
53 | {
54 | byte[] ret = null;
55 | Entry e = (Entry) m_buffer.get(new Integer(id));
56 |
57 | if (e != null)
58 | {
59 | m_hits++;
60 |
61 | ret = new byte[e.m_data.length];
62 | System.arraycopy(e.m_data, 0, ret, 0, e.m_data.length);
63 | }
64 | else
65 | {
66 | ret = m_storageManager.loadByteArray(id);
67 | e = new Entry(ret);
68 | addEntry(id, e);
69 | }
70 |
71 | return ret;
72 | }
73 | public int storeByteArray(final int id, final byte[] data)
74 | {
75 | int ret = id;
76 |
77 | if (id == NewPage)
78 | {
79 | ret = m_storageManager.storeByteArray(id, data);
80 | Entry e = new Entry(data);
81 | addEntry(ret, e);
82 | }
83 | else
84 | {
85 | if (m_bWriteThrough)
86 | {
87 | m_storageManager.storeByteArray(id, data);
88 | }
89 |
90 | Entry e = (Entry) m_buffer.get(new Integer(id));
91 | if (e != null)
92 | {
93 | e.m_data = new byte[data.length];
94 | System.arraycopy(data, 0, e.m_data, 0, data.length);
95 |
96 | if (m_bWriteThrough == false)
97 | {
98 | e.m_bDirty = true;
99 | m_hits++;
100 | }
101 | else
102 | {
103 | e.m_bDirty = false;
104 | }
105 | }
106 | else
107 | {
108 | e = new Entry(data);
109 | if (m_bWriteThrough == false) e.m_bDirty = true;
110 | addEntry(id, e);
111 | }
112 | }
113 |
114 | return ret;
115 | }
116 | public void deleteByteArray(final int id)
117 | {
118 | Integer ID = new Integer(id);
119 | Entry e = (Entry) m_buffer.get(ID);
120 | if (e != null)
121 | {
122 | m_buffer.remove(ID);
123 | }
124 |
125 | m_storageManager.deleteByteArray(id);
126 | }
127 |
128 | public void flush()
129 | {
130 | Iterator it = m_buffer.entrySet().iterator();
131 |
132 | while (it.hasNext())
133 | {
134 | Map.Entry me = (Map.Entry) it.next();
135 | Entry e = (Entry) me.getValue();
136 | int id = ((Integer) me.getKey()).intValue();
137 | if (e.m_bDirty) m_storageManager.storeByteArray(id, e.m_data);
138 | }
139 |
140 | m_storageManager.flush();
141 | }
142 | public void clear()
143 | {
144 | Iterator it = m_buffer.entrySet().iterator();
145 |
146 | while (it.hasNext())
147 | {
148 | Map.Entry me = (Map.Entry) it.next();
149 | Entry e = (Entry) me.getValue();
150 |
151 | if (e.m_bDirty)
152 | {
153 | int id = ((Integer) me.getKey()).intValue();
154 | m_storageManager.storeByteArray(id, e.m_data);
155 | }
156 | }
157 |
158 | m_buffer.clear();
159 | m_hits = 0;
160 | }
161 |
162 | public long getHits()
163 | {
164 | return m_hits;
165 | }
166 |
167 | class Entry
168 | {
169 | byte[] m_data = null;
170 | boolean m_bDirty = false;
171 |
172 | Entry(final byte[] d)
173 | {
174 | m_data = new byte[d.length];
175 | System.arraycopy(d, 0, m_data, 0, d.length);
176 | }
177 | }; // Entry
178 |
179 | } // Buffer
180 |
--------------------------------------------------------------------------------
/src/test/java/sil/storagemanager/DiskStorageManager.java:
--------------------------------------------------------------------------------
1 | // Spatial Index Library
2 | //
3 | // Copyright (C) 2002 Navel Ltd.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 | //
19 | // Contact information:
20 | // Mailing address:
21 | // Marios Hadjieleftheriou
22 | // University of California, Riverside
23 | // Department of Computer Science
24 | // Surge Building, Room 310
25 | // Riverside, CA 92521
26 | //
27 | // Email:
28 | // marioh@cs.ucr.edu
29 |
30 | package sil.storagemanager;
31 |
32 | import java.util.*;
33 | import java.io.*;
34 |
35 | public class DiskStorageManager implements IStorageManager
36 | {
37 | private RandomAccessFile m_dataFile = null;
38 | private RandomAccessFile m_indexFile = null;
39 | private int m_pageSize = 0;
40 | private int m_nextPage = -1;
41 | private TreeSet m_emptyPages = new TreeSet();
42 | private HashMap m_pageIndex = new HashMap();
43 | private byte[] m_buffer = null;
44 |
45 | public DiskStorageManager(PropertySet ps)
46 | throws SecurityException, NullPointerException, IOException, FileNotFoundException, IllegalArgumentException
47 | {
48 | Object var;
49 |
50 | // Open/Create flag.
51 | boolean bOverwrite = false;
52 | var = ps.getProperty("Overwrite");
53 |
54 | if (var != null)
55 | {
56 | if (! (var instanceof Boolean)) throw new IllegalArgumentException("Property Overwrite must be a Boolean");
57 | bOverwrite = ((Boolean) var).booleanValue();
58 | }
59 |
60 | // storage filename.
61 | var = ps.getProperty("FileName");
62 |
63 | if (var != null)
64 | {
65 | if (! (var instanceof String)) throw new IllegalArgumentException("Property FileName must be a String");
66 |
67 | File indexFile = new File((String) var + ".idx");
68 | File dataFile = new File((String) var + ".dat");
69 |
70 | // check if files exist.
71 | if (bOverwrite == false && (! indexFile.exists() || ! dataFile.exists())) bOverwrite = true;
72 |
73 | if (bOverwrite)
74 | {
75 | if (indexFile.exists()) indexFile.delete();
76 | if (dataFile.exists()) dataFile.delete();
77 |
78 | boolean b = indexFile.createNewFile();
79 | if (b == false) throw new IOException("Index file cannot be opened.");
80 |
81 | b = dataFile.createNewFile();
82 | if (b == false) throw new IOException("Data file cannot be opened.");
83 | }
84 |
85 | m_indexFile = new RandomAccessFile(indexFile, "rw");
86 | m_dataFile = new RandomAccessFile(dataFile, "rw");
87 | }
88 | else
89 | {
90 | throw new IllegalArgumentException("Property FileName was not specified.");
91 | }
92 |
93 | // find page size.
94 | if (bOverwrite == true)
95 | {
96 | var = ps.getProperty("PageSize");
97 |
98 | if (var != null)
99 | {
100 | if (! (var instanceof Integer)) throw new IllegalArgumentException("Property PageSize must be an Integer");
101 | m_pageSize = ((Integer) var).intValue();
102 | m_nextPage = 0;
103 | }
104 | else
105 | {
106 | throw new IllegalArgumentException("Property PageSize was not specified.");
107 | }
108 | }
109 | else
110 | {
111 | try
112 | {
113 | m_pageSize = m_indexFile.readInt();
114 | }
115 | catch (EOFException ex)
116 | {
117 | throw new IllegalStateException("Failed reading pageSize.");
118 | }
119 |
120 | try
121 | {
122 | m_nextPage = m_indexFile.readInt();
123 | }
124 | catch (EOFException ex)
125 | {
126 | throw new IllegalStateException("Failed reading nextPage.");
127 | }
128 | }
129 |
130 | // create buffer.
131 | m_buffer = new byte[m_pageSize];
132 |
133 | if (bOverwrite == false)
134 | {
135 | int count, id, page;
136 |
137 | // load empty pages in memory.
138 | try
139 | {
140 | count = m_indexFile.readInt();
141 |
142 | for (int cCount = 0; cCount < count; cCount++)
143 | {
144 | page = m_indexFile.readInt();
145 | m_emptyPages.add(new Integer(page));
146 | }
147 |
148 | // load index table in memory.
149 | count = m_indexFile.readInt();
150 |
151 | for (int cCount = 0; cCount < count; cCount++)
152 | {
153 | Entry e = new Entry();
154 |
155 | id = m_indexFile.readInt();
156 | e.m_length = m_indexFile.readInt();
157 |
158 | int count2 = m_indexFile.readInt();
159 |
160 | for (int cCount2 = 0; cCount2 < count2; cCount2++)
161 | {
162 | page = m_indexFile.readInt();
163 | e.m_pages.add(new Integer(page));
164 | }
165 | m_pageIndex.put(new Integer(id), e);
166 | }
167 | }
168 | catch (EOFException ex)
169 | {
170 | throw new IllegalStateException("Corrupted index file.");
171 | }
172 | }
173 | }
174 |
175 | public void flush()
176 | {
177 | try
178 | {
179 | m_indexFile.seek(0l);
180 |
181 | m_indexFile.writeInt(m_pageSize);
182 | m_indexFile.writeInt(m_nextPage);
183 |
184 | int id, page;
185 | int count = m_emptyPages.size();
186 |
187 | m_indexFile.writeInt(count);
188 |
189 | Iterator it = m_emptyPages.iterator();
190 | while (it.hasNext())
191 | {
192 | page = ((Integer) it.next()).intValue();
193 | m_indexFile.writeInt(page);
194 | }
195 |
196 | count = m_pageIndex.size();
197 | m_indexFile.writeInt(count);
198 |
199 | it = m_pageIndex.entrySet().iterator();
200 |
201 | while (it.hasNext())
202 | {
203 | Map.Entry me = (Map.Entry) it.next();
204 | id = ((Integer) me.getKey()).intValue();
205 | m_indexFile.writeInt(id);
206 |
207 | Entry e = (Entry) me.getValue();
208 | count = e.m_length;
209 | m_indexFile.writeInt(count);
210 |
211 | count = e.m_pages.size();
212 | m_indexFile.writeInt(count);
213 |
214 | for (int cIndex = 0; cIndex < count; cIndex++)
215 | {
216 | page = ((Integer) e.m_pages.get(cIndex)).intValue();
217 | m_indexFile.writeInt(page);
218 | }
219 | }
220 | }
221 | catch (IOException ex)
222 | {
223 | throw new IllegalStateException("Corrupted index file.");
224 | }
225 | }
226 |
227 | public byte[] loadByteArray(final int id)
228 | {
229 | Entry e = (Entry) m_pageIndex.get(new Integer(id));
230 | if (e == null) throw new InvalidPageException(id);
231 |
232 | int cNext = 0;
233 | int cTotal = e.m_pages.size();
234 |
235 | byte[] data = new byte[e.m_length];
236 | int cIndex = 0;
237 | int cLen;
238 | int cRem = e.m_length;
239 |
240 | do
241 | {
242 | try
243 | {
244 | m_dataFile.seek(((Integer) e.m_pages.get(cNext)).intValue() * m_pageSize);
245 | int bytesread = m_dataFile.read(m_buffer);
246 | if (bytesread != m_pageSize) throw new IllegalStateException("Corrupted data file.");
247 | }
248 | catch (IOException ex)
249 | {
250 | throw new IllegalStateException("Corrupted data file.");
251 | }
252 |
253 | cLen = (cRem > m_pageSize) ? m_pageSize : cRem;
254 | System.arraycopy(m_buffer, 0, data, cIndex, cLen);
255 |
256 | cIndex += cLen;
257 | cRem -= cLen;
258 | cNext++;
259 | }
260 | while (cNext < cTotal);
261 |
262 | return data;
263 | }
264 |
265 | public int storeByteArray(final int id, final byte[] data)
266 | {
267 | if (id == NewPage)
268 | {
269 | Entry e = new Entry();
270 | e.m_length = data.length;
271 |
272 | int cIndex = 0;
273 | int cPage;
274 | int cRem = data.length;
275 | int cLen;
276 |
277 | while (cRem > 0)
278 | {
279 | if (! m_emptyPages.isEmpty())
280 | {
281 | Integer i = (Integer) m_emptyPages.first();
282 | m_emptyPages.remove(i);
283 | cPage = i.intValue();
284 | }
285 | else
286 | {
287 | cPage = m_nextPage;
288 | m_nextPage++;
289 | }
290 |
291 | cLen = (cRem > m_pageSize) ? m_pageSize : cRem;
292 | System.arraycopy(data, cIndex, m_buffer, 0, cLen);
293 |
294 | try
295 | {
296 | m_dataFile.seek(cPage * m_pageSize);
297 | m_dataFile.write(m_buffer);
298 | }
299 | catch (IOException ex)
300 | {
301 | throw new IllegalStateException("Corrupted data file.");
302 | }
303 |
304 | cIndex += cLen;
305 | cRem -= cLen;
306 | e.m_pages.add(new Integer(cPage));
307 | }
308 |
309 | Integer i = (Integer) e.m_pages.get(0);
310 | m_pageIndex.put(i, e);
311 |
312 | return i.intValue();
313 | }
314 | else
315 | {
316 | // find the entry.
317 | Entry oldEntry = (Entry) m_pageIndex.get(new Integer(id));
318 | if (oldEntry == null) throw new InvalidPageException(id);
319 |
320 | m_pageIndex.remove(new Integer(id));
321 |
322 | Entry e = new Entry();
323 | e.m_length = data.length;
324 |
325 | int cIndex = 0;
326 | int cPage;
327 | int cRem = data.length;
328 | int cLen, cNext = 0;
329 |
330 | while (cRem > 0)
331 | {
332 | if (cNext < oldEntry.m_pages.size())
333 | {
334 | cPage = ((Integer) oldEntry.m_pages.get(cNext)).intValue();
335 | cNext++;
336 | }
337 | else if (! m_emptyPages.isEmpty())
338 | {
339 | Integer i = (Integer) m_emptyPages.first();
340 | m_emptyPages.remove(i);
341 | cPage = i.intValue();
342 | }
343 | else
344 | {
345 | cPage = m_nextPage;
346 | m_nextPage++;
347 | }
348 |
349 | cLen = (cRem > m_pageSize) ? m_pageSize : cRem;
350 | System.arraycopy(data, cIndex, m_buffer, 0, cLen);
351 |
352 | try
353 | {
354 | m_dataFile.seek(cPage * m_pageSize);
355 | m_dataFile.write(m_buffer);
356 | }
357 | catch (IOException ex)
358 | {
359 | throw new IllegalStateException("Corrupted data file.");
360 | }
361 |
362 | cIndex += cLen;
363 | cRem -= cLen;
364 | e.m_pages.add(new Integer(cPage));
365 | }
366 |
367 | while (cNext < oldEntry.m_pages.size())
368 | {
369 | m_emptyPages.add(oldEntry.m_pages.get(cNext));
370 | cNext++;
371 | }
372 |
373 | Integer i = (Integer) e.m_pages.get(0);
374 | m_pageIndex.put(i, e);
375 |
376 | return i.intValue();
377 | }
378 | }
379 |
380 | public void deleteByteArray(final int id)
381 | {
382 | // find the entry.
383 | Entry e = (Entry) m_pageIndex.get(new Integer(id));
384 | if (e == null) throw new InvalidPageException(id);
385 |
386 | m_pageIndex.remove(new Integer(id));
387 |
388 | for (int cIndex = 0; cIndex < e.m_pages.size(); cIndex++)
389 | {
390 | m_emptyPages.add(e.m_pages.get(cIndex));
391 | }
392 | }
393 |
394 | public void close()
395 | {
396 | flush();
397 | }
398 |
399 | class Entry
400 | {
401 | int m_length = 0;
402 | ArrayList m_pages = new ArrayList();
403 | }
404 | }
405 |
--------------------------------------------------------------------------------
/src/test/java/sil/storagemanager/IBuffer.java:
--------------------------------------------------------------------------------
1 | // Spatial Index Library
2 | //
3 | // Copyright (C) 2002 Navel Ltd.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 | //
19 | // Contact information:
20 | // Mailing address:
21 | // Marios Hadjieleftheriou
22 | // University of California, Riverside
23 | // Department of Computer Science
24 | // Surge Building, Room 310
25 | // Riverside, CA 92521
26 | //
27 | // Email:
28 | // marioh@cs.ucr.edu
29 |
30 | package sil.storagemanager;
31 |
32 | public interface IBuffer extends IStorageManager
33 | {
34 | public long getHits();
35 | public void clear();
36 | public void flush();
37 | } // IBuffer
38 |
39 |
--------------------------------------------------------------------------------
/src/test/java/sil/storagemanager/IStorageManager.java:
--------------------------------------------------------------------------------
1 | // Spatial Index Library
2 | //
3 | // Copyright (C) 2002 Navel Ltd.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 | //
19 | // Contact information:
20 | // Mailing address:
21 | // Marios Hadjieleftheriou
22 | // University of California, Riverside
23 | // Department of Computer Science
24 | // Surge Building, Room 310
25 | // Riverside, CA 92521
26 | //
27 | // Email:
28 | // marioh@cs.ucr.edu
29 |
30 | package sil.storagemanager;
31 |
32 | public interface IStorageManager
33 | {
34 | public static final int NewPage = -1;
35 |
36 | public void flush();
37 | public byte[] loadByteArray(final int id);
38 | public int storeByteArray(final int id, final byte[] data);
39 | public void deleteByteArray(final int id);
40 | } // IStorageManager
41 |
--------------------------------------------------------------------------------
/src/test/java/sil/storagemanager/InvalidPageException.java:
--------------------------------------------------------------------------------
1 | // Spatial Index Library
2 | //
3 | // Copyright (C) 2002 Navel Ltd.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 | //
19 | // Contact information:
20 | // Mailing address:
21 | // Marios Hadjieleftheriou
22 | // University of California, Riverside
23 | // Department of Computer Science
24 | // Surge Building, Room 310
25 | // Riverside, CA 92521
26 | //
27 | // Email:
28 | // marioh@cs.ucr.edu
29 |
30 | package sil.storagemanager;
31 |
32 | public class InvalidPageException extends RuntimeException
33 | {
34 | public InvalidPageException(int id)
35 | {
36 | super("" + id);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/test/java/sil/storagemanager/MemoryStorageManager.java:
--------------------------------------------------------------------------------
1 | // Spatial Index Library
2 | //
3 | // Copyright (C) 2002 Navel Ltd.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 | //
19 | // Contact information:
20 | // Mailing address:
21 | // Marios Hadjieleftheriou
22 | // University of California, Riverside
23 | // Department of Computer Science
24 | // Surge Building, Room 310
25 | // Riverside, CA 92521
26 | //
27 | // Email:
28 | // marioh@cs.ucr.edu
29 |
30 | package sil.storagemanager;
31 |
32 | import java.util.*;
33 |
34 | public class MemoryStorageManager implements IStorageManager
35 | {
36 | private ArrayList m_buffer = new ArrayList();
37 | private Stack m_emptyPages = new Stack();
38 |
39 | public void flush()
40 | {
41 | }
42 |
43 | public byte[] loadByteArray(final int id)
44 | {
45 | Entry e = null;
46 |
47 | try
48 | {
49 | e = (Entry) m_buffer.get(id);
50 | }
51 | catch (IndexOutOfBoundsException ex)
52 | {
53 | throw new InvalidPageException(id);
54 | }
55 |
56 | byte[] ret = new byte[e.m_pData.length];
57 | System.arraycopy(e.m_pData, 0, ret, 0, e.m_pData.length);
58 | return ret;
59 | }
60 |
61 | public int storeByteArray(final int id, final byte[] data)
62 | {
63 | int ret = id;
64 | Entry e = new Entry(data);
65 |
66 | if (id == NewPage)
67 | {
68 | if (m_emptyPages.empty())
69 | {
70 | m_buffer.add(e);
71 | ret = m_buffer.size() - 1;
72 | }
73 | else
74 | {
75 | ret = ((Integer) m_emptyPages.pop()).intValue();
76 | m_buffer.set(ret, e);
77 | }
78 | }
79 | else
80 | {
81 | if (id < 0 || id >= m_buffer.size()) throw new InvalidPageException(id);
82 | m_buffer.set(id, e);
83 | }
84 |
85 | return ret;
86 | }
87 |
88 | public void deleteByteArray(final int id)
89 | {
90 | Entry e = null;
91 | try
92 | {
93 | e = (Entry) m_buffer.get(id);
94 | }
95 | catch (IndexOutOfBoundsException ex)
96 | {
97 | throw new InvalidPageException(id);
98 | }
99 |
100 | m_buffer.set(id, null);
101 | m_emptyPages.push(new Integer(id));
102 | }
103 |
104 | class Entry
105 | {
106 | byte[] m_pData;
107 |
108 | Entry(final byte[] d)
109 | {
110 | m_pData = new byte[d.length];
111 | System.arraycopy(d, 0, m_pData, 0, d.length);
112 | }
113 | } // Entry
114 | }
115 |
--------------------------------------------------------------------------------
/src/test/java/sil/storagemanager/PropertySet.java:
--------------------------------------------------------------------------------
1 | // Spatial Index Library
2 | //
3 | // Copyright (C) 2002 Navel Ltd.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 | //
19 | // Contact information:
20 | // Mailing address:
21 | // Marios Hadjieleftheriou
22 | // University of California, Riverside
23 | // Department of Computer Science
24 | // Surge Building, Room 310
25 | // Riverside, CA 92521
26 | //
27 | // Email:
28 | // marioh@cs.ucr.edu
29 |
30 | package sil.storagemanager;
31 |
32 | import java.util.*;
33 |
34 | public class PropertySet
35 | {
36 | private HashMap m_propertySet = new HashMap();
37 |
38 | public Object getProperty(String property)
39 | {
40 | return m_propertySet.get(property);
41 | }
42 |
43 | public void setProperty(String property, Object o)
44 | {
45 | m_propertySet.put(property, o);
46 | }
47 | } // PropertySet
48 |
--------------------------------------------------------------------------------
/src/test/java/sil/storagemanager/RandomEvictionsBuffer.java:
--------------------------------------------------------------------------------
1 | // Spatial Index Library
2 | //
3 | // Copyright (C) 2002 Navel Ltd.
4 | //
5 | // This library is free software; you can redistribute it and/or
6 | // modify it under the terms of the GNU Lesser General Public
7 | // License as published by the Free Software Foundation; either
8 | // version 2.1 of the License, or (at your option) any later version.
9 | //
10 | // This library is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | // Lesser General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU Lesser General Public
16 | // License along with this library; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 | //
19 | // Contact information:
20 | // Mailing address:
21 | // Marios Hadjieleftheriou
22 | // University of California, Riverside
23 | // Department of Computer Science
24 | // Surge Building, Room 310
25 | // Riverside, CA 92521
26 | //
27 | // Email:
28 | // marioh@cs.ucr.edu
29 |
30 | package sil.storagemanager;
31 |
32 | import java.util.*;
33 |
34 | public class RandomEvictionsBuffer extends Buffer
35 | {
36 | Random m_random = new Random();
37 |
38 | public RandomEvictionsBuffer(IStorageManager sm, int capacity, boolean bWriteThrough)
39 | {
40 | super(sm, capacity, bWriteThrough);
41 | }
42 |
43 | void addEntry(int id, Entry e)
44 | {
45 | // assert m_buffer.size() <= m_capacity;
46 |
47 | if (m_buffer.size() == m_capacity) removeEntry();
48 | m_buffer.put(new Integer(id), e);
49 | }
50 |
51 | void removeEntry()
52 | {
53 | if (m_buffer.size() == 0) return;
54 |
55 | int entry = m_random.nextInt(m_buffer.size());
56 |
57 | Iterator it = m_buffer.entrySet().iterator();
58 | for (int cIndex = 0; cIndex < entry - 1; cIndex++) it.next();
59 |
60 | Map.Entry me = (Map.Entry) it.next();
61 | Entry e = (Entry) me.getValue();
62 | int id = ((Integer) me.getKey()).intValue();
63 |
64 | if (e.m_bDirty)
65 | {
66 | m_storageManager.storeByteArray(id, e.m_data);
67 | }
68 |
69 | m_buffer.remove(new Integer(id));
70 | }
71 | } // RandomEvictionsBuffer
72 |
--------------------------------------------------------------------------------
/src/test/java/sil/storagemanager/makefile:
--------------------------------------------------------------------------------
1 | # Spatial Index Library
2 | #
3 | # Copyright (C) 2002 Navel Ltd.
4 | #
5 | # This library is free software; you can redistribute it and/or
6 | # modify it under the terms of the GNU Lesser General Public
7 | # License as published by the Free Software Foundation; either
8 | # version 2.1 of the License, or (at your option) any later version.
9 | #
10 | # This library is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # Lesser General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU Lesser General Public
16 | # License along with this library; if not, write to the Free Software
17 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 | #
19 | # Contact information:
20 | # Mailing address:
21 | # Marios Hadjieleftheriou
22 | # University of California, Riverside
23 | # Department of Computer Science
24 | # Surge Building, Room 310
25 | # Riverside, CA 92521
26 | #
27 | # Email:
28 | # marioh@cs.ucr.edu
29 |
30 | all:
31 | javac -source 1.4 -classpath ../lib -d ../lib -g:none *.java
32 |
33 | debug:
34 | javac -source 1.4 -classpath ../lib -d ../lib -g *.java
35 |
36 | clean:
37 | rm -rf ../lib/spatialindex/storagemanager
38 |
39 |
--------------------------------------------------------------------------------
/src/test/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | [%level] %msg%n
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/test/resources/test-inputs/test-allfunctions-100-in:
--------------------------------------------------------------------------------
1 | randomize 1
2 | addRandom 40 0 20000
3 | randomize 1
4 | deleteRandom 20 0 20000
5 | #
6 | randomize 2
7 | addRandom 40 40 20000
8 | randomize 2
9 | deleteRandom 20 40 20000
10 | #
11 | randomize 3
12 | addRandom 40 80 20000
13 | randomize 3
14 | deleteRandom 20 80 20000
15 | #
16 | randomize 4
17 | addRandom 40 120 20000
18 | randomize 4
19 | deleteRandom 20 120 20000
20 | #
21 | randomize 5
22 | addRandom 40 160 20000
23 | randomize 5
24 | deleteRandom 20 160 20000
25 | #
26 | randomize 6
27 | intersectRandom 100 20000
28 | #
29 | randomize 7
30 | nearestRandom 100
31 | #
32 | randomize 8
33 | nearestNRandom 100 5
34 | #
35 | randomize 9
36 | containsRandom 100 100000
--------------------------------------------------------------------------------
/src/test/resources/test-inputs/test-allfunctions-1000-in:
--------------------------------------------------------------------------------
1 | randomize 1
2 | addRandom 400 0 100
3 | randomize 1
4 | deleteRandom 200 0 100
5 | #
6 | randomize 2
7 | addRandom 400 400 200
8 | randomize 2
9 | deleteRandom 200 400 200
10 | #
11 | randomize 3
12 | addRandom 400 800 400
13 | randomize 3
14 | deleteRandom 200 800 400
15 | #
16 | randomize 4
17 | addRandom 400 1200 800
18 | randomize 4
19 | deleteRandom 200 1200 800
20 | #
21 | randomize 5
22 | addRandom 400 1600 1600
23 | randomize 5
24 | deleteRandom 200 1600 1600
25 | #
26 | randomize 6
27 | intersectRandom 200 100
28 | intersectRandom 200 200
29 | intersectRandom 200 400
30 | intersectRandom 200 800
31 | intersectRandom 200 1600
32 | #
33 | randomize 7
34 | nearestRandom 200 100
35 | nearestRandom 200 200
36 | nearestRandom 200 400
37 | nearestRandom 200 800
38 | nearestRandom 200 1600
39 | #
40 | randomize 8
41 | nearestNRandom 200 1000
42 | nearestNRandom 200 2000
43 | nearestNRandom 200 4000
44 | nearestNRandom 200 8000
45 | nearestNRandom 200 16000
46 | #
47 | randomize 9
48 | containsRandom 200 100
49 | containsRandom 200 200
50 | containsRandom 200 400
51 | containsRandom 200 800
52 | containsRandom 200 1600
--------------------------------------------------------------------------------
/src/test/resources/test-inputs/test-allfunctions-10000-in:
--------------------------------------------------------------------------------
1 | randomize 1
2 | addRandom 4000 0 100
3 | randomize 1
4 | deleteRandom 2000 0 100
5 | #
6 | randomize 2
7 | addRandom 4000 4000 200
8 | randomize 2
9 | deleteRandom 2000 4000 200
10 | #
11 | randomize 3
12 | addRandom 4000 8000 400
13 | randomize 3
14 | deleteRandom 2000 8000 400
15 | #
16 | randomize 4
17 | addRandom 4000 12000 800
18 | randomize 4
19 | deleteRandom 2000 12000 800
20 | #
21 | randomize 5
22 | addRandom 4000 16000 1600
23 | randomize 5
24 | deleteRandom 2000 16000 1600
25 | #
26 | randomize 6
27 | intersectRandom 2000 100
28 | intersectRandom 2000 200
29 | intersectRandom 2000 400
30 | intersectRandom 2000 800
31 | intersectRandom 2000 1600
32 | #
33 | randomize 7
34 | nearestRandom 2000 100
35 | nearestRandom 2000 200
36 | nearestRandom 2000 400
37 | nearestRandom 2000 800
38 | nearestRandom 2000 1600
39 | #
40 | randomize 8
41 | nearestNRandom 2000 10000
42 | nearestNRandom 2000 20000
43 | nearestNRandom 2000 40000
44 | nearestNRandom 2000 80000
45 | nearestNRandom 2000 160000
46 | #
47 | randomize 9
48 | containsRandom 2000 100
49 | containsRandom 2000 200
50 | containsRandom 2000 400
51 | containsRandom 2000 800
52 | containsRandom 2000 1600
--------------------------------------------------------------------------------
/src/test/resources/test-inputs/test-allfunctions-100000-in:
--------------------------------------------------------------------------------
1 | # Full test script. Add 200 entries. After 40 have been added delete 20.
2 | # Use a range of scales from 100 to 1600
3 | randomize 1
4 | addRandom 4000 0 100
5 | randomize 1
6 | deleteRandom 2000 0 100
7 | #
8 | randomize 2
9 | addRandom 4000 40000 200
10 | randomize 2
11 | deleteRandom 2000 40000 200
12 | #
13 | randomize 3
14 | addRandom 40000 80000 400
15 | randomize 3
16 | deleteRandom 20000 80000 400
17 | #
18 | randomize 4
19 | addRandom 40000 120000 800
20 | randomize 4
21 | deleteRandom 20000 120000 800
22 | #
23 | randomize 5
24 | addRandom 40000 160000 1600
25 | randomize 5
26 | deleteRandom 20000 160000 1600
27 | #
28 | randomize 6
29 | intersectRandom 20000 100
30 | intersectRandom 20000 200
31 | intersectRandom 20000 400
32 | intersectRandom 20000 800
33 | intersectRandom 20000 1600
34 | #
35 | randomize 7
36 | nearestRandom 20000 100
37 | nearestRandom 20000 200
38 | nearestRandom 20000 400
39 | nearestRandom 20000 800
40 | nearestRandom 20000 1600
41 | #
42 | randomize 8
43 | nearestNRandom 20000 100000
44 | nearestNRandom 20000 200000
45 | nearestNRandom 20000 400000
46 | nearestNRandom 20000 800000
47 | nearestNRandom 20000 1600000
48 | #
49 | randomize 9
50 | containsRandom 20000 100
51 | containsRandom 20000 200
52 | containsRandom 20000 400
53 | containsRandom 20000 800
54 | containsRandom 20000 1600
--------------------------------------------------------------------------------
/src/test/resources/test-inputs/test-allqueries-10000-in:
--------------------------------------------------------------------------------
1 | randomize 1
2 | addRandom 10000 0 5000
3 |
4 | randomize 2
5 | #intersectRandom 10000 5000
6 |
7 | randomize 3
8 | nearestRandom 10000 10
9 |
10 | randomize 4
11 | #nearestNRandom 10000 5 6000
12 |
13 | randomize 5
14 | #containsRandom 10000 15000
15 |
16 | # deletion test - delete all of the entries
17 | randomize 1
18 | #deleteRandom 10000 0 5000
--------------------------------------------------------------------------------
/src/test/resources/test-inputs/test-contains-100-in:
--------------------------------------------------------------------------------
1 | randomize 1
2 | addRandom 100 0 5
3 | containsRandom 100 5
4 |
--------------------------------------------------------------------------------
/src/test/resources/test-inputs/test-contains-1000-in:
--------------------------------------------------------------------------------
1 | randomize 1
2 | addRandom 1000 0 60
3 | containsRandom 1000 60
4 |
--------------------------------------------------------------------------------
/src/test/resources/test-inputs/test-contains-10000-in:
--------------------------------------------------------------------------------
1 | randomize 1
2 | addRandom 10000 0 280
3 | containsRandom 10000 280
4 |
--------------------------------------------------------------------------------
/src/test/resources/test-inputs/test-contains-100000-in:
--------------------------------------------------------------------------------
1 | randomize 1
2 | addRandom 100000 0 800
3 | containsRandom 100000 800
4 |
--------------------------------------------------------------------------------
/src/test/resources/test-inputs/test-delete-100-in:
--------------------------------------------------------------------------------
1 | # specific test to isolate bug whereby tree was not shrunk correctly
2 | deleteAllRandom 1 100 0 235.4
3 |
4 | # original tests
5 | #randomize 1
6 | #addRandom 200 0 235.4
7 | #randomize 1
8 | #deleteRandom 100 0 235.4
9 | #randomize 123456
10 | #deleteRandom 100 0 235.4
11 | #randomize 2
12 | #intersectRandom 100 0 235.4
13 |
--------------------------------------------------------------------------------
/src/test/resources/test-inputs/test-delete-1000-in:
--------------------------------------------------------------------------------
1 | randomize 1
2 | addRandom 2000 0 646.8
3 | randomize 1
4 | deleteRandom 1000 0 646.8
5 | randomize 123456
6 | deleteRandom 1000 0 646.8
7 | randomize 2
8 | intersectRandom 1000 0 646.8
--------------------------------------------------------------------------------
/src/test/resources/test-inputs/test-delete-10000-in:
--------------------------------------------------------------------------------
1 | # 1000 = 43
2 | # 1500 = 21.8101
3 | # 1800 = 15
4 | # 2100 = 11.9093
5 | # 2200 = 10.969
6 | # 2300 = 10.2979
7 | # 2400 = 9.7034
8 | randomize 1
9 | addRandom 20000 0 2350
10 | randomize 1
11 | deleteRandom 10000 0 2350
12 | randomize 123456
13 | deleteRandom 10000 0 2350
14 | randomize 2
15 | intersectRandom 10000 0 2350
--------------------------------------------------------------------------------
/src/test/resources/test-inputs/test-delete-100000-in:
--------------------------------------------------------------------------------
1 | #4995=15.77595
2 | randomize 1
3 | addRandom 200000 0 5500
4 | randomize 1
5 | deleteRandom 100000 0 5500
6 | randomize 123456
7 | deleteRandom 100000 0 5500
8 | randomize 2
9 | intersectRandom 100000 0 5500
--------------------------------------------------------------------------------
/src/test/resources/test-inputs/test-intersect-100-in:
--------------------------------------------------------------------------------
1 | # scale chosen by trial-and-error to give about 10 intersects per query.
2 | randomize 1
3 | addRandom 100 0 129.7
4 | intersectRandom 100 129.7
5 |
--------------------------------------------------------------------------------
/src/test/resources/test-inputs/test-intersect-1000-in:
--------------------------------------------------------------------------------
1 | # scale chosen by trial-and-error to give an average of 10 intersects per query.
2 | # 435.7 = 10.001
3 | randomize 1
4 | addRandom 1000 0 435.7
5 | intersectRandom 1000 435.7
6 |
--------------------------------------------------------------------------------
/src/test/resources/test-inputs/test-intersect-10000-in:
--------------------------------------------------------------------------------
1 | randomize 1
2 | addRandom 10000 0 1463
3 | intersectRandom 10000 1463
4 |
--------------------------------------------------------------------------------
/src/test/resources/test-inputs/test-intersect-100000-in:
--------------------------------------------------------------------------------
1 | randomize 1
2 | addRandom 100000 0 4917
3 | intersectRandom 100000 4917
4 |
--------------------------------------------------------------------------------
/src/test/resources/test-inputs/test-intersect-1000000-in:
--------------------------------------------------------------------------------
1 | randomize 1
2 | addRandom 1000000 0 1000000
3 | intersectRandom 1000000 1000000
4 |
--------------------------------------------------------------------------------
/src/test/resources/test-inputs/test-intersect-10000000-in:
--------------------------------------------------------------------------------
1 | randomize 1
2 | addRandom 10000000 0 10000000
3 | intersectRandom 10000000 10000000
4 |
--------------------------------------------------------------------------------
/src/test/resources/test-inputs/test-nearest-100-in:
--------------------------------------------------------------------------------
1 | randomize 1
2 | addRandom 100 0 1000
3 | nearestRandom 100 1000
4 |
--------------------------------------------------------------------------------
/src/test/resources/test-inputs/test-nearest-1000-in:
--------------------------------------------------------------------------------
1 | randomize 1
2 | addRandom 1000 0 3162
3 | nearestRandom 1000 3162
--------------------------------------------------------------------------------
/src/test/resources/test-inputs/test-nearest-10000-in:
--------------------------------------------------------------------------------
1 | randomize 1
2 | addRandom 10000 0 10000
3 | nearestRandom 10000 10000
--------------------------------------------------------------------------------
/src/test/resources/test-inputs/test-nearest-100000-in:
--------------------------------------------------------------------------------
1 | randomize 1
2 | addRandom 100000 0 31623
3 | nearestRandom 100000 31623
--------------------------------------------------------------------------------
/src/test/resources/test-inputs/test-nearestN-100-in:
--------------------------------------------------------------------------------
1 | randomize 1
2 | addRandom 50 0 1000
3 | nearestNRandom 100 1 1000
4 | nearestNRandom 100 2 1000
5 | nearestNRandom 100 8 1000
6 | nearestNRandom 100 32 1000
7 |
8 | distanceQuantizer 10000
9 | addRandom 50 50 1000
10 | nearestNRandom 100 1 1000
11 | nearestNRandom 100 2 1000
12 | nearestNRandom 100 8 1000
13 | nearestNRandom 100 64 1000
14 |
--------------------------------------------------------------------------------
/src/test/resources/test-inputs/test-nearestN-1000-in:
--------------------------------------------------------------------------------
1 | randomize 1
2 | addRandom 500 0 3162
3 | nearestNRandom 1000 1 3162
4 | nearestNRandom 1000 2 3162
5 | nearestNRandom 1000 8 3162
6 | nearestNRandom 1000 32 3162
7 | nearestNRandom 1000 256 3162
8 |
9 | distanceQuantizer 10000
10 | addRandom 500 500 3162
11 | nearestNRandom 1000 1 3162
12 | nearestNRandom 1000 2 3162
13 | nearestNRandom 1000 64 3162
14 | nearestNRandom 1000 512 3162
--------------------------------------------------------------------------------
/src/test/resources/test-inputs/test-nearestN-10000-in:
--------------------------------------------------------------------------------
1 | randomize 1
2 | addRandom 5000 0 10000
3 | nearestNRandom 10000 1 10000
4 | nearestNRandom 10000 2 10000
5 | nearestNRandom 10000 8 10000
6 | nearestNRandom 10000 32 10000
7 | nearestNRandom 10000 256 10000
8 |
9 | distanceQuantizer 10000
10 | addRandom 5000 5000 10000
11 | nearestNRandom 10000 1 10000
12 | nearestNRandom 10000 2 10000
13 | nearestNRandom 10000 64 10000
14 | nearestNRandom 10000 512 10000
--------------------------------------------------------------------------------