Revision 23282

View differences:

branches/v2_0_0_prep/libraries/libFMap_spatialindex/src/org/gvsig/fmap/data/index/spatial/gt2/QuadtreeGt2.java
1
/*
2
 * Created on 16-may-2006
3
 *
4
 * gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
5
 *
6
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
7
 *
8
 * This program is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU General Public License
10
 * as published by the Free Software Foundation; either version 2
11
 * of the License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
21
 *
22
 * For more information, contact:
23
 *
24
 *  Generalitat Valenciana
25
 *   Conselleria d'Infraestructures i Transport
26
 *   Av. Blasco Ib??ez, 50
27
 *   46010 VALENCIA
28
 *   SPAIN
29
 *
30
 *      +34 963862235
31
 *   gvsig@gva.es
32
 *      www.gvsig.gva.es
33
 *
34
 *    or
35
 *
36
 *   IVER T.I. S.A
37
 *   Salamanca 50
38
 *   46005 Valencia
39
 *   Spain
40
 *
41
 *   +34 963163400
42
 *   dac@iver.es
43
 */
44
/* CVS MESSAGES:
45
 *
46
 * $Id: QuadtreeGt2.java 10627 2007-03-06 17:10:21Z caballero $
47
 * $Log$
48
 * Revision 1.3  2007-03-06 17:08:59  caballero
49
 * Exceptions
50
 *
51
 * Revision 1.2  2006/11/29 19:27:59  azabala
52
 * bug fixed (caused when we query for a bbox which is greater or equal to a layer bbox)
53
 *
54
 * Revision 1.1  2006/05/24 21:58:04  azabala
55
 * *** empty log message ***
56
 *
57
 *
58
 */
59
package org.gvsig.fmap.data.index.spatial.gt2;
60

  
61
import java.io.File;
62
import java.util.List;
63
import java.util.Stack;
64

  
65
import org.geotools.index.quadtree.Node;
66
import org.geotools.index.quadtree.QuadTree;
67
import org.geotools.index.quadtree.StoreException;
68
import org.geotools.index.quadtree.fs.FileSystemIndexStore;
69
import org.geotools.index.quadtree.fs.IndexHeader;
70
import org.gvsig.fmap.data.index.IndexException;
71
import org.gvsig.fmap.data.index.AbstractIntBasedSpatialIndex;
72
import org.gvsig.fmap.data.index.PersistentSpatialIndex;
73

  
74
import com.vividsolutions.jts.geom.Envelope;
75

  
76
/**
77
 * This Quadtree spatial index implementation is based in a fork of
78
 * org.geotools.index.quadtree.Quadtree implementation. <br>
79
 * This implementation offers us:
80
 * <ol>
81
 * <li>Persistence of spatial index</li>
82
 * </ol>
83
 * We had to fork geotools quadtree for many reasons:
84
 * <ol>
85
 * <li>It was strongly dependent of SHP format, so it returned not only a num
86
 * of rectangle, it also returned byte offset of this rectangle in shp file</li>
87
 * <li> Query artifact wasnt run well at all </li>
88
 * </ol>
89
 * 
90
 * @author azabala
91
 * 
92
 */
93
public class QuadtreeGt2 extends AbstractIntBasedSpatialIndex implements PersistentSpatialIndex {
94
	/**
95
	 * Geotools quadtree implementation
96
	 */
97
	QuadTree quadtree;
98
	/**
99
	 * Persistent storage
100
	 */
101
	String quadtreeFile;
102
	/**
103
	 * Spatial index file extension
104
	 */
105
	final String qExt = ".qix";
106
	/**
107
	 * qix format has many versions, and allows different byte orders.
108
	 */
109
	String byteOrder;
110
	/**
111
	 * Bounds of the layer to index
112
	 */
113
	Envelope bounds;
114
	/**
115
	 * Number of records of the layer to index
116
	 */
117
	int numRecs = 0;
118

  
119
	boolean inMemory = false;
120

  
121
	/**
122
	 * Constructor. You must say a qix file path, and if you want to overwrite
123
	 * this file if exists. Also, you must specify how many geometries are going
124
	 * to index, and the bounding box of all the geometries.
125
	 * 
126
	 * 
127
	 * @param quadtreeFile
128
	 *            qix file path
129
	 * @param byteOrder
130
	 *            byte order (bigendian, etc)
131
	 * @param bounds
132
	 *            Envelope of all the geometries to index
133
	 * @param numRecords
134
	 *            num of geometries to index
135
	 * @param overwrite
136
	 *            if we want to overwrite a possible existing qix file
137
	 * @throws IndexException
138
	 */
139
	public QuadtreeGt2(String quadtreeFile, String byteOrder,
140
			org.gvsig.fmap.geom.primitive.Envelope bounds, int numRecords,
141
			boolean overwrite) throws IndexException {
142

  
143
		this.quadtreeFile = quadtreeFile + qExt;
144
		this.byteOrder = byteOrder;
145
		this.bounds = toJtsEnvelope(bounds);
146
		this.numRecs = numRecords;
147

  
148
		if (exists()) {
149
			if (!overwrite) {
150
				load();
151
				return;
152
			}
153
		}
154
		quadtree = new QuadTree(numRecs, this.bounds);
155
	}
156

  
157
	/**
158
	 * If the spatial index file exists and has content
159
	 */
160
	public boolean exists() {
161
		return (new File(quadtreeFile).length() != 0);
162
	}
163

  
164
	public void load() throws IndexException {
165
		if (quadtree == null) {
166
			load(new File(quadtreeFile));
167
		}
168
	}
169

  
170
	public void load(File f) throws IndexException {
171
		try {
172
			FileSystemIndexStore store = new FileSystemIndexStore(f);
173
			quadtree = store.load();
174
			this.quadtreeFile = f.getAbsolutePath();
175
		} catch (StoreException e) {
176
			throw new IndexException(e);
177
		}
178
	}
179

  
180
	/**
181
	 * 
182
	 * 
183
	 */
184
	public List query(org.gvsig.fmap.geom.primitive.Envelope env) {
185
		if (quadtree == null)
186
			throw new IllegalStateException("This quadtree is null.");
187
		if (env == null)
188
			throw new IllegalArgumentException("Envelope cannot be null.");
189
		return quadtree.query(toJtsEnvelope(env));
190
	}
191

  
192
	/**
193
	 * Inserts an object in the index
194
	 */
195
	public void insert(org.gvsig.fmap.geom.primitive.Envelope env, int index) {
196
		if (env == null)
197
			throw new IllegalArgumentException("Envelope cannot be null");
198
		Envelope e = toJtsEnvelope(env);
199
		if (e == null)
200
			throw new IllegalStateException(
201
					"JTS Envelope conversion returns null");
202
		System.out.println("recno=" + index);
203
		if (quadtree == null)
204
			throw new IllegalStateException("quadtree is null");
205
		try {
206
			quadtree.insert(index, toJtsEnvelope(env));
207
		} catch (StoreException se) {
208
			// TODO Auto-generated catch block
209
			se.printStackTrace();
210
		}
211
	}
212

  
213
	public void delete(org.gvsig.fmap.geom.primitive.Envelope env, int index) {
214
		if (inMemory)
215
			quadtree.delete(toJtsEnvelope(env), index);
216
	}
217

  
218
	public Envelope toJtsEnvelope(org.gvsig.fmap.geom.primitive.Envelope env) {
219
		if (env == null)
220
			return null;
221
		double[] min = env.getLowerCorner();
222
		double[] max = env.getUpperCorner();
223
		return new Envelope(min[0], max[0], min[1], max[1]);
224
	}
225

  
226
	/**
227
	 * 
228
	 * @throws StoreException
229
	 * @deprecated
230
	 */
231
	void openQuadTree() throws StoreException {
232
		if (quadtree == null) {
233
			File file = new File(quadtreeFile);
234
			// Intento de cargar todo el quadtree en memoria
235
			FileSystemIndexStore store = new FileSystemIndexStore(file);
236
			quadtree = store.load();
237
		}
238
	}
239

  
240
	void openQuadTreeInMemory() throws StoreException {
241
		if (quadtree == null) {
242
			File file = new File(quadtreeFile);
243
			// Intento de cargar todo el quadtree en memoria
244
			FileSystemIndexStore store = new FileSystemIndexStore(file);
245
			QuadTree filequadtree = store.load();
246
			quadtree = new QuadTree(filequadtree.getNumShapes(), filequadtree
247
					.getMaxDepth(), filequadtree.getRoot().getBounds());
248
			Stack nodes = new Stack();
249
			nodes.push(filequadtree.getRoot());
250
			while (nodes.size() != 0) {
251
				Node node = (Node) nodes.pop();
252
				Envelope nodeEnv = node.getBounds();
253
				int[] shapeIds = node.getShapesId();
254
				for (int i = 0; i < shapeIds.length; i++) {
255
					quadtree.insert(shapeIds[i], nodeEnv);
256
				}
257
				int numSubnodes = node.getNumSubNodes();
258
				for (int i = 0; i < numSubnodes; i++) {
259
					nodes.push(node.getSubNode(i));
260
				}
261
			}// while
262
			filequadtree.close();
263
		}
264
	}
265

  
266
	public void flush() throws IndexException {
267
		flush(new File(quadtreeFile));
268
	}
269

  
270
	public void flush(File f) throws IndexException {
271
		byte order = 0;
272
		if ((byteOrder == null) || byteOrder.equalsIgnoreCase("NM")) {
273
			order = IndexHeader.NEW_MSB_ORDER;
274
		} else if (byteOrder.equalsIgnoreCase("NL")) {
275
			order = IndexHeader.NEW_LSB_ORDER;
276
		}
277
		FileSystemIndexStore store = new FileSystemIndexStore(f, order);
278
		try {
279
			store.store(quadtree);
280
			this.quadtreeFile = f.getAbsolutePath();
281
		} catch (StoreException e) {
282
			throw new IndexException(e);
283
		}
284
	}
285

  
286
	public void close() {
287
		try {
288
			quadtree.close();
289
		} catch (StoreException e) {
290
			// TODO Auto-generated catch block
291
			e.printStackTrace();
292
		}
293
	}
294

  
295
	public File getFile() {
296
		return new File(this.quadtreeFile);
297
	}
298

  
299
}
branches/v2_0_0_prep/libraries/libFMap_spatialindex/src/org/gvsig/fmap/data/index/spatial/gt2/QuadTreeGt2Factory.java
1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
5
 * 
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 * 
11
 * This program 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
14
 * GNU General Public License for more details.
15
 * 
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
19
 * MA  02110-1301, USA.
20
 * 
21
 */
22

  
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2008 {{Company}}   {{Task}}
26
 */
27

  
28
package org.gvsig.fmap.data.index.spatial.gt2;
29

  
30
import java.io.File;
31
import java.io.IOException;
32

  
33
import org.gvsig.fmap.data.index.IndexException;
34
import org.gvsig.fmap.data.index.SpatialIndex;
35
import org.gvsig.fmap.data.index.SpatialIndexFactory;
36
import org.gvsig.fmap.data.index.SpatialIndexParameters;
37

  
38
public class QuadTreeGt2Factory extends SpatialIndexFactory {
39
	
40
	static {
41
		registerFactory(Factories.GT2_QUADTREE, "QuadTreeGt2Factory", QuadTreeGt2Factory.class);
42
	}
43
	
44
	public SpatialIndex createSpatialIndex(SpatialIndexParameters params) throws IndexException {
45
		if (params == null) {
46
			params = new SpatialIndexParameters();
47
		}
48
		SpatialIndex index = null;
49
		
50
		try {
51
			String filename = params.getFilename();
52
			File file = null;
53
			
54
			if (filename != null) {
55
				file = new File(filename);
56
			} else {
57
				file = File.createTempFile("gvsig", ".qix");
58
			}
59
			
60
			index = new QuadtreeGt2(file.getAbsolutePath(), "NM", params.getEnvelope(), params.getFeatureCount(), params.isOverwrite());
61
			
62
		} catch (IOException ioe) {
63
			throw new IndexException(ioe);
64
		}
65
		
66
		return index;
67
	}
68
	
69
/*	Metodo extraido de FlyrVect
70
	
71
	public SpatialIndex createSpatialIndex(FeatureStore store, File indexFile) throws SpatialIndexException {
72
		SpatialIndex spatialIndex = null;
73
				
74
		String fileName = indexFile.getAbsolutePath();
75
		SpatialIndex localCopy = null;
76

  
77
		Envelope fullExtent = (Envelope) store.getMetadata().get("extent");
78
		int featureCount = store.getMetadata().getInt("featureCount");
79
		
80
		double[] lc = fullExtent.getLowerCorner();
81
		double[] uc = fullExtent.getUpperCorner();
82
		
83
		com.vividsolutions.jts.geom.Envelope env = new com.vividsolutions.jts.geom.Envelope(lc[0], uc[0], lc[1], uc[1]);
84

  
85
		try {
86
			localCopy = new QuadtreeGt2(fileName, "NM", env, featureCount, true);
87
		} catch (SpatialIndexException sie1) {
88
			// Probably we dont have writing permissions
89
			String directoryName = System.getProperty("java.io.tmpdir");
90
			File newFile = new File(directoryName + File.separator
91
					+ indexFile.getName());
92
			String newFileName = newFile.getName();
93
			try {
94
				localCopy = new QuadtreeGt2(newFileName, "NM", fullExtent,
95
						featureCount, true);
96
			} catch (SpatialIndexException sie2) {
97
				// if we cant build a file based spatial index, we'll build
98
				// a pure memory spatial index
99
				localCopy = new QuadtreeJts();
100
			}
101
		} catch (Exception e) {
102
			e.printStackTrace();
103
		}// try
104
		BoundedShapes shapeBounds = (BoundedShapes) va.getDriver();
105
		try {
106
			for (int i = 0; i < va.getShapeCount(); i++) {
107
				if (cancelMonitor != null) {
108
					if (cancelMonitor.isCanceled())
109
						return;
110
					cancelMonitor.reportStep();
111
				}
112
				Rectangle2D r = shapeBounds.getShapeBounds(i);
113
				if (r != null)
114
					localCopy.insert(r, i);
115
			} // for
116
			va.stop();
117
			if (localCopy instanceof PersistentSpatialIndex)
118
				((PersistentSpatialIndex) localCopy).flush();
119
			spatialIndex = localCopy;
120
			// vectorial adapter needs a reference to the spatial index, to
121
			// solve
122
			// request for feature iteration based in spatial queries
123
			source.setSpatialIndex(spatialIndex);
124
		} catch (ReadDriverException e) {
125
			// TODO Auto-generated catch block
126
			e.printStackTrace();
127
		}
128
		
129
		return spatialIndex;
130
	}
131
*/
132
}
branches/v2_0_0_prep/libraries/libFMap_spatialindex/src/org/gvsig/fmap/data/index/spatial/jts/QuadTreeJtsFactory.java
1
/* gvSIG. Geographic Information System of the Valencian Government
2
*
3
* Copyright (C) 2007-2008 Infrastructures and Transports Department
4
* of the Valencian Government (CIT)
5
* 
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License
8
* as published by the Free Software Foundation; either version 2
9
* of the License, or (at your option) any later version.
10
* 
11
* This program 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
14
* GNU General Public License for more details.
15
* 
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
19
* MA  02110-1301, USA.
20
* 
21
*/
22

  
23
/*
24
* AUTHORS (In addition to CIT):
25
* 2008 {{Company}}   {{Task}}
26
*/
27
 
28
package org.gvsig.fmap.data.index.spatial.jts;
29

  
30
import org.gvsig.fmap.data.index.IndexException;
31
import org.gvsig.fmap.data.index.SpatialIndex;
32
import org.gvsig.fmap.data.index.SpatialIndexFactory;
33
import org.gvsig.fmap.data.index.SpatialIndexParameters;
34

  
35
public class QuadTreeJtsFactory extends SpatialIndexFactory {
36

  
37
	static {
38
		registerFactory(Factories.JTS_QUADTREE, "QuadTreeJtsFactory", QuadTreeJtsFactory.class);
39
	}
40
	
41
	public SpatialIndex createSpatialIndex(SpatialIndexParameters params) throws IndexException {
42
		return new QuadtreeJts();
43
	}
44

  
45
}
branches/v2_0_0_prep/libraries/libFMap_spatialindex/src/org/gvsig/fmap/data/index/spatial/jts/QuadtreeJts.java
1
/*
2
 * Created on 28-abr-2006
3
 *
4
 * gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
5
 *
6
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
7
 *
8
 * This program is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU General Public License
10
 * as published by the Free Software Foundation; either version 2
11
 * of the License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
21
 *
22
 * For more information, contact:
23
 *
24
 *  Generalitat Valenciana
25
 *   Conselleria d'Infraestructures i Transport
26
 *   Av. Blasco Ib??ez, 50
27
 *   46010 VALENCIA
28
 *   SPAIN
29
 *
30
 *      +34 963862235
31
 *   gvsig@gva.es
32
 *      www.gvsig.gva.es
33
 *
34
 *    or
35
 *
36
 *   IVER T.I. S.A
37
 *   Salamanca 50
38
 *   46005 Valencia
39
 *   Spain
40
 *
41
 *   +34 963163400
42
 *   dac@iver.es
43
 */
44
/* CVS MESSAGES:
45
*
46
* $Id: QuadtreeJts.java 11288 2007-04-19 17:32:50Z azabala $
47
* $Log$
48
* Revision 1.2  2007-04-19 17:32:50  azabala
49
* new constructor (fmap spatial index from an existing jts spatial index)
50
*
51
* Revision 1.1  2006/05/01 18:38:41  azabala
52
* primera version en cvs del api de indices espaciales
53
*
54
*
55
*/
56
package org.gvsig.fmap.data.index.spatial.jts;
57

  
58
import java.util.List;
59

  
60
import org.gvsig.fmap.data.index.AbstractIntBasedSpatialIndex;
61
import org.gvsig.fmap.data.index.SpatialIndex;
62

  
63
import com.vividsolutions.jts.geom.Envelope;
64
import com.vividsolutions.jts.index.quadtree.Quadtree;
65
/**
66
 * Adapter for ISPatialIndex gvSIG's interface to
67
 * JTS Quadtree.
68
 * 
69
 * 
70
 * @author azabala
71
 *
72
 */
73
public class QuadtreeJts extends AbstractIntBasedSpatialIndex implements SpatialIndex {
74
	private Quadtree quadtree;
75
	
76
	public QuadtreeJts(){
77
		quadtree = new Quadtree();
78
	}
79
	
80
	public QuadtreeJts(Quadtree jtsidx){
81
		quadtree = jtsidx;
82
	}
83
		
84
	public List query(org.gvsig.fmap.geom.primitive.Envelope env) {
85
		return quadtree.query(fromEnvelope(env));
86
	}
87

  
88
	public void insert(org.gvsig.fmap.geom.primitive.Envelope env, int index) {
89
		quadtree.insert(fromEnvelope(env), new Integer(index));
90
	}
91

  
92
	public void delete(org.gvsig.fmap.geom.primitive.Envelope env, int index) {
93
		quadtree.remove(fromEnvelope(env), new Integer(index));
94
	}
95
	
96
	private Envelope fromEnvelope(org.gvsig.fmap.geom.primitive.Envelope env){
97
		double[] min = env.getLowerCorner();
98
		double[] max = env.getUpperCorner();
99
		Envelope env2 = new Envelope(min[0], max[0], min[1], max[1]);
100
		return env2;
101
	}
102
	
103

  
104
}
105

  
branches/v2_0_0_prep/libraries/libFMap_spatialindex/src/org/gvsig/fmap/data/index/spatial/jsi/RTreeJsiFactory.java
1
/* gvSIG. Geographic Information System of the Valencian Government
2
*
3
* Copyright (C) 2007-2008 Infrastructures and Transports Department
4
* of the Valencian Government (CIT)
5
* 
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License
8
* as published by the Free Software Foundation; either version 2
9
* of the License, or (at your option) any later version.
10
* 
11
* This program 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
14
* GNU General Public License for more details.
15
* 
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
19
* MA  02110-1301, USA.
20
* 
21
*/
22

  
23
/*
24
* AUTHORS (In addition to CIT):
25
* 2008 {{Company}}   {{Task}}
26
*/
27
 
28
package org.gvsig.fmap.data.index.spatial.jsi;
29

  
30
import org.gvsig.fmap.data.index.IndexException;
31
import org.gvsig.fmap.data.index.SpatialIndex;
32
import org.gvsig.fmap.data.index.SpatialIndexFactory;
33
import org.gvsig.fmap.data.index.SpatialIndexParameters;
34

  
35
public class RTreeJsiFactory extends SpatialIndexFactory {
36

  
37
	static {
38
		registerFactory(Factories.JSI_RTREE, "RTreeJsiFactory", RTreeJsiFactory.class);
39
	}
40

  
41
	public SpatialIndex createSpatialIndex(SpatialIndexParameters params) throws IndexException {
42
		SpatialIndex index = null;
43
		
44
		if (params == null) {
45
			params = new SpatialIndexParameters();
46
		}
47
		
48
		if (params.getFilename() != null) {
49
			index = new PersistentRTreeJsi(params.getFilename(), params.isOverwrite());
50
		} else {
51
			index = new RTreeJsi();
52
		}
53
		
54
		if (index != null) {
55
			((RTreeJsi)index).create();
56
		}
57
		
58
		return index;
59
	}
60
}
branches/v2_0_0_prep/libraries/libFMap_spatialindex/src/org/gvsig/fmap/data/index/spatial/jsi/RTreeJsi.java
1
/*
2
 * Created on 15-may-2006
3
 *
4
 * gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
5
 *
6
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
7
 *
8
 * This program is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU General Public License
10
 * as published by the Free Software Foundation; either version 2
11
 * of the License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
21
 *
22
 * For more information, contact:
23
 *
24
 *  Generalitat Valenciana
25
 *   Conselleria d'Infraestructures i Transport
26
 *   Av. Blasco Ib??ez, 50
27
 *   46010 VALENCIA
28
 *   SPAIN
29
 *
30
 *      +34 963862235
31
 *   gvsig@gva.es
32
 *      www.gvsig.gva.es
33
 *
34
 *    or
35
 *
36
 *   IVER T.I. S.A
37
 *   Salamanca 50
38
 *   46005 Valencia
39
 *   Spain
40
 *
41
 *   +34 963163400
42
 *   dac@iver.es
43
 */
44
/* CVS MESSAGES:
45
*
46
* $Id: RTreeJsi.java 13884 2007-09-19 16:26:04Z jaume $
47
* $Log$
48
* Revision 1.5  2007-09-19 16:25:39  jaume
49
* ReadExpansionFileException removed from this context and removed unnecessary imports
50
*
51
* Revision 1.4  2007/06/27 20:17:30  azabala
52
* new spatial index (rix)
53
*
54
* Revision 1.3  2007/03/06 17:08:59  caballero
55
* Exceptions
56
*
57
* Revision 1.2  2006/06/05 16:59:08  azabala
58
* implementada busqueda de vecino mas proximo a partir de rectangulos
59
*
60
* Revision 1.1  2006/05/24 21:58:04  azabala
61
* *** empty log message ***
62
*
63
*
64
*/
65
package org.gvsig.fmap.data.index.spatial.jsi;
66

  
67
import java.util.ArrayList;
68
import java.util.Iterator;
69
import java.util.List;
70
import java.util.Properties;
71

  
72
import org.gvsig.fmap.data.index.IndexException;
73
import org.gvsig.fmap.data.index.AbstractIntBasedSpatialIndex;
74
import org.gvsig.fmap.data.index.NearestNeighbourFinder;
75
import org.gvsig.fmap.data.index.SpatialIndex;
76
import org.gvsig.fmap.geom.primitive.Envelope;
77
import org.gvsig.fmap.geom.primitive.Point2D;
78

  
79
import com.infomatiq.jsi.IntProcedure;
80
import com.infomatiq.jsi.Rectangle;
81
import com.infomatiq.jsi.rtree.RTree;
82

  
83
/**
84
 * RTree spatial index implementation based in library
85
 * JSI (java spatial index).
86
 * 
87
 * http://jsi.sourceforge.net/
88
 * 
89
 * This RTree has better performance that Spatial Index Library
90
 * RTree, and that JTS'RTree, because
91
 * it uses the GNU's Trove Collections API.
92
 * 
93
 * We are doing some probes with it, because it offers
94
 * a Nearest Neighbour algorithm implementation 
95
 * (useful for Spatial Join geoprocess, for example).
96
 * 
97
 * It isnt persistent, and We've found some problems
98
 * with delete operations.
99
 * 
100
 * 
101
 * 
102
 * 
103
 * @author azabala
104
 *
105
 */
106
public class RTreeJsi extends AbstractIntBasedSpatialIndex implements SpatialIndex, NearestNeighbourFinder {
107
	private RTree rtree;
108
	
109
	public RTreeJsi(){
110
		rtree = new RTree();
111
	}
112
	
113
	public void create(){
114
		Properties props = new Properties();
115
//		props.setProperty("MaxNodeEntries", "500");
116
//		props.setProperty("MinNodeEntries", "200");
117
		rtree.init(props);
118
	}
119
	
120
	class ListIntProcedure implements IntProcedure{
121
		ArrayList solution = new ArrayList();
122
		
123
		public boolean execute(int arg0) {
124
			solution.add(new Integer(arg0));
125
			return true;
126
		}
127
		
128
		public List getSolution(){
129
			return solution;
130
		}
131
	}
132
	
133
	public List findNNearest(int numberOfNearest, Point2D point){
134
		com.infomatiq.jsi.Point jsiPoint =
135
			new com.infomatiq.jsi.Point((float)point.getX(), (float)point.getY());
136
		return (List) rtree.nearest(jsiPoint, numberOfNearest);
137
	}
138
	
139
	//FIXME Add this method to spatial index interface
140
	public Iterator iterator(){
141
		return rtree.iterator();
142
	}
143
	
144
	public int size(){
145
		return rtree.size();
146
	}	
147
	
148
	public void delete(Envelope env, int index) {		
149
		rtree.delete(toJsiRect(env), index);		
150
	}
151

  
152
	public void insert(Envelope env, int index) {
153
		rtree.add(toJsiRect(env), index);		
154
	}
155

  
156
	public List query(Envelope env) throws IndexException {
157
		ListIntProcedure solution = new ListIntProcedure();
158
		rtree.intersects(toJsiRect(env), solution);
159
		return solution.getSolution();
160
	}
161

  
162
	public List findNNearest(int numberOfNearest, Envelope env){
163
		return (List) rtree.nearest(toJsiRect(env), numberOfNearest);
164
	}	
165
	
166
	protected Rectangle toJsiRect(Envelope env){
167
		double[] min = env.getLowerCorner();
168
		double[] max = env.getUpperCorner();
169
		
170
		Rectangle jsiRect = new Rectangle((float)min[0],
171
				(float)min[1],
172
				(float)max[0],
173
				(float)max[1]);
174
		return jsiRect;
175
	}
176

  
177
	
178
	
179
	
180
	
181
}
182

  
branches/v2_0_0_prep/libraries/libFMap_spatialindex/src/org/gvsig/fmap/data/index/spatial/jsi/PersistentRTreeJsi.java
1
/*
2
 * Created on 13-jun-2007
3
 *
4
 * gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
5
 *
6
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
7
 *
8
 * This program is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU General Public License
10
 * as published by the Free Software Foundation; either version 2
11
 * of the License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
21
 *
22
 * For more information, contact:
23
 *
24
 *  Generalitat Valenciana
25
 *   Conselleria d'Infraestructures i Transport
26
 *   Av. Blasco Ib??ez, 50
27
 *   46010 VALENCIA
28
 *   SPAIN
29
 *
30
 *      +34 963862235
31
 *   gvsig@gva.es
32
 *      www.gvsig.gva.es
33
 *
34
 *    or
35
 *
36
 *   IVER T.I. S.A
37
 *   Salamanca 50
38
 *   46005 Valencia
39
 *   Spain
40
 *
41
 *   +34 963163400
42
 *   dac@iver.es
43
 */
44
/* CVS MESSAGES:
45
*
46
* $Id: PersistentRTreeJsi.java 12380 2007-06-27 20:17:30Z azabala $
47
* $Log$
48
* Revision 1.1  2007-06-27 20:17:30  azabala
49
* new spatial index (rix)
50
*
51
*
52
*/
53
package org.gvsig.fmap.data.index.spatial.jsi;
54

  
55
import java.awt.geom.Point2D;
56
import java.io.File;
57
import java.io.FileNotFoundException;
58
import java.io.IOException;
59
import java.io.RandomAccessFile;
60
import java.nio.ByteOrder;
61
import java.nio.MappedByteBuffer;
62
import java.nio.channels.FileChannel;
63
import java.util.Iterator;
64
import java.util.LinkedHashMap;
65
import java.util.List;
66
import java.util.Properties;
67

  
68
import javax.imageio.stream.FileImageOutputStream;
69

  
70
import org.gvsig.fmap.data.index.IndexException;
71
import org.gvsig.fmap.data.index.PersistentSpatialIndex;
72
import org.gvsig.fmap.geom.primitive.Envelope;
73

  
74
import com.infomatiq.jsi.Rectangle;
75
import com.infomatiq.jsi.rtree.RTree;
76

  
77
/**
78
 * Persistent spatial index which can resolve nearest neighbour queries.
79
 * <br>
80
 * 
81
 * To use:
82
 * 
83
 * PersistentRTreeJsi sptidx = new PersistentRtreeJsi("/home/kk");
84
 * if(sptidx.exists())
85
 *  sptidx.load();
86
 *  
87
 *  
88
 *  sptidx.add(rect, int);
89
 *  ...
90
 *  sptidx.add(rect2,int2);
91
 *  sptidx.flush();
92
 * 
93
 * @author azabala
94
 *
95
 */
96
public class PersistentRTreeJsi extends RTreeJsi implements PersistentSpatialIndex {
97

  
98
	/**
99
	 * Spatial index in memory
100
	 */
101
	private RTree rtree;
102
	/**
103
	 * Spatial index file
104
	 */
105
	private File rtreeFile;
106
	
107
	private boolean hasChange = false;
108
	/**
109
	 * Spatial index file extension
110
	 */
111
	final String rExt = ".rix";
112
	
113
	private LinkedHashMap  rectangles;
114
	
115
	/**
116
	 * Constructor
117
	 * @param file path of the spatial index file
118
	 * @throws IndexException 
119
	 */
120
	public PersistentRTreeJsi(String file, boolean overwrite) throws IndexException {
121
		rtree = new RTree();
122
		Properties props = new Properties();
123
		rtree.init(props);
124
		rtreeFile = new File(file + rExt);
125
		rectangles = new LinkedHashMap();
126
		if(! overwrite)
127
			load();
128
	}
129
	
130
	public void flush(File f) throws IndexException {
131
		try {
132
			if(! hasChange)
133
				return;
134
			RandomAccessFile file = new RandomAccessFile(f,
135
															"rw");
136
			FileImageOutputStream output = new FileImageOutputStream(file);
137
			output.setByteOrder(ByteOrder.LITTLE_ENDIAN);
138
			int numShapes = rtree.size();
139
			output.writeInt(numShapes);
140
			
141
			Iterator iterator = rtree.iterator();
142
			int count = 0;
143
			while(iterator.hasNext()){
144
				Integer  idx = (Integer) iterator.next();
145
				Rectangle nr = (Rectangle) rectangles.get(idx);
146
				float xmin = nr.min[0];
147
				float ymin = nr.min[1];
148
				
149
				float xmax = nr.max[0];
150
				float ymax = nr.max[1];
151
				
152
				output.writeFloat(xmin);
153
				output.writeFloat(ymin);
154
				output.writeFloat(xmax);
155
				output.writeFloat(ymax);
156
				
157
				output.writeInt(idx.intValue());
158
				count++;
159
			}
160
			output.flush();
161
			output.close();
162
			file.close();
163
			hasChange = false;
164
		} catch (FileNotFoundException e) {
165
			throw new IndexException(e);
166
		} catch (IOException e) {
167
			throw new IndexException(e);
168
		}
169
		
170
	}
171
	
172
	public void flush() throws IndexException {
173
		flush(rtreeFile);
174
	}
175

  
176
	public boolean exists() {
177
		return rtreeFile.exists();
178
	}
179

  
180
	public void load(File f) throws IndexException {
181
		if (f == null) throw new IllegalArgumentException("File f cannot be null");
182
		
183
		try {
184
			if(! f.exists()){
185
				return;
186
			}
187
			RandomAccessFile file = new RandomAccessFile(f, "r");
188
			FileChannel channel = file.getChannel();
189
			MappedByteBuffer buf = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
190
			buf.order(ByteOrder.LITTLE_ENDIAN);
191
			int numShapes = buf.getInt();
192
			for(int i = 0; i < numShapes; i++){
193
				float xmin, ymin, xmax, ymax;
194
				int shapeIndex;
195
				xmin = buf.getFloat();
196
				ymin = buf.getFloat();
197
				xmax = buf.getFloat();
198
				ymax = buf.getFloat();
199
				shapeIndex = buf.getInt();
200
				
201
				Rectangle jsiRect = new Rectangle(xmin, ymin, xmax, ymax);
202
				rtree.add(jsiRect, shapeIndex);
203
			}
204
		}catch(Exception e){
205
			throw new IndexException(e);
206
		}		
207
	}
208
	
209
	public void load() throws IndexException {
210
		load(rtreeFile);
211
	}
212

  
213
	public void close() {
214
		rectangles.clear();
215
		rectangles = null;
216
	}
217
	
218
	public void insert(Envelope env, int index) {
219
		super.insert(env, index);
220
		rectangles.put(new Integer(index), toJsiRect(env));
221
		hasChange = true;
222
	}
223

  
224
	
225
	public void delete(Envelope env, int index) {
226
		super.delete(env, index);
227
		rectangles.remove(new Integer(index));
228
		hasChange = true;
229
	}
230
	
231
	public List findNNearest(int numberOfNearest, Point2D point){
232
		com.infomatiq.jsi.Point jsiPoint =
233
			new com.infomatiq.jsi.Point((float)point.getX(),(float)point.getY());
234
		return (List) rtree.nearest(jsiPoint, numberOfNearest);
235
	}
236
	
237
	public File getFile() {
238
		return this.rtreeFile;
239
	}
240
}
241

  
branches/v2_0_0_prep/libraries/libFMap_spatialindex/src/org/gvsig/fmap/data/index/spatial/spatialindex/RTreeSptLib.java
1
package org.gvsig.fmap.data.index.spatial.spatialindex;
2

  
3
import java.io.File;
4
import java.io.FileNotFoundException;
5
import java.io.IOException;
6
import java.util.ArrayList;
7
import java.util.List;
8

  
9
import org.gvsig.fmap.data.index.IndexException;
10
import org.gvsig.fmap.data.index.AbstractIntBasedSpatialIndex;
11
import org.gvsig.fmap.data.index.NearestNeighbourFinder;
12
import org.gvsig.fmap.data.index.PersistentSpatialIndex;
13
import org.gvsig.fmap.geom.primitive.Envelope;
14
import org.gvsig.fmap.geom.primitive.Point2D;
15

  
16
import spatialindex.rtree.RTree;
17
import spatialindex.spatialindex.IData;
18
import spatialindex.spatialindex.INode;
19
import spatialindex.spatialindex.IVisitor;
20
import spatialindex.spatialindex.Region;
21
import spatialindex.storagemanager.DiskStorageManager;
22
import spatialindex.storagemanager.IBuffer;
23
import spatialindex.storagemanager.IStorageManager;
24
import spatialindex.storagemanager.PropertySet;
25
import spatialindex.storagemanager.RandomEvictionsBuffer;
26

  
27
/**
28
 * <p>
29
 * RTree spatial index based in spatial index library: <br>
30
 * http://u-foria.org/marioh/spatialindex/index.html <br>
31
 * marioh@cs.ucr.edu
32
 * </p>
33
 * It has the problem that spatial index file creation is a bit slowly
34
 * (in comparation with other indexes).
35
 */
36
public class RTreeSptLib extends AbstractIntBasedSpatialIndex implements PersistentSpatialIndex,
37
									NearestNeighbourFinder{
38
	/**
39
	 * Page size of associated file
40
	 */
41
	private static final int defaultPageSize = 32 * 1024;
42
	private static final double defaultFillFactor = 0.85d;
43

  
44
	/**
45
	 * Size of memory buffer of the index
46
	 */
47
	private static final int BUFFER_SIZE = 25000;
48
	RTree rtree;
49
	String rtreeFile;
50
	IStorageManager diskfile;
51
	/**
52
	 * Constructor
53
	 * @param overwriteFile tells if we must override existing files.
54
	 * If we are goint to create a new spatial index (or if we want to overwrite
55
	 * an existing one) we must to use always 'true'. If we want to load
56
	 * an existing spatial index file, overwrite must be 'false'
57
	 * @param fileName name of the rtree spatial index file
58
	 * @throws IndexException
59
	 */
60

  
61
	public RTreeSptLib(boolean overwriteFile, String fileName)
62
			throws IndexException {
63
		try {
64
			this.rtreeFile = fileName;
65
			PropertySet ps = new PropertySet();
66

  
67
			// overwrite the file if it exists.
68
			Boolean b = new Boolean(overwriteFile);
69
			ps.setProperty("Overwrite", b);
70

  
71
			// .idx and .dat extensions will be added.
72
			ps.setProperty("FileName", fileName);
73

  
74
			Integer i = new Integer(defaultPageSize);
75
			ps.setProperty("PageSize", i);
76
			diskfile = new DiskStorageManager(ps);
77
			load();
78
		} catch (SecurityException e) {
79
			throw new IndexException(e);
80
		} catch (FileNotFoundException e) {
81
			throw new IndexException(e);
82
		} catch (IOException e) {
83
			throw new IndexException(e);
84
		}
85
	}
86

  
87
	/**
88
	 * If the spatial index file exists and has content
89
	 */
90
	public boolean exists(){
91
		return (new File(rtreeFile+".dat").length() != 0);
92
	}
93

  
94

  
95
	class RTreeVisitor implements IVisitor{
96
		ArrayList solution = new ArrayList();
97
		public void visitNode(INode n) {
98
		}
99
		public void visitData(IData d) {
100
			solution.add(new Integer(d.getIdentifier()));
101
		}
102
		public List getSolution(){
103
			return solution;
104
		}
105
	}
106

  
107

  
108
	public List query(Envelope env) {
109
		List solution = null;
110
		Region region = createRegion(env);
111
		RTreeVisitor visitor = new RTreeVisitor();
112
		rtree.intersectionQuery(region,visitor);
113
		solution = visitor.getSolution();
114
		return solution;
115
	}
116

  
117
	public List containtmentQuery(Envelope env) {
118
		List solution = null;
119
		Region region = createRegion(env);
120
		RTreeVisitor visitor = new RTreeVisitor();
121
		rtree.containmentQuery(region,visitor);
122
		solution = visitor.getSolution();
123
		return solution;
124
	}
125

  
126
	/**
127
	 * Warn! This RTree implemention doesnt care if 'index'
128
	 * entry has been indexed yet
129
	 */
130
	public void insert(Envelope env, int index) {
131
		rtree.insertData(null, createRegion(env), index);
132
	}
133

  
134
	private Region createRegion(Envelope env){
135
		return new Region(env.getLowerCorner(), env.getUpperCorner());
136
	}
137

  
138
	public void delete(Envelope env, int index) {
139
		rtree.deleteData(createRegion(env), index);
140
	}
141

  
142
	/**
143
	 * Looks for N indexes nearest to the specified rect.
144
	 * @param numberOfNearest
145
	 * @param rect
146
	 * @return
147
	 */
148
	public List findNNearest(int numberOfNearest, Envelope env) {
149
		List solution = null;
150
		Region region = createRegion(env);
151
		RTreeVisitor visitor = new RTreeVisitor();
152
		rtree.nearestNeighborQuery(numberOfNearest, region,visitor);
153
		solution = visitor.getSolution();
154
		return solution;
155
	}
156

  
157
	/**
158
	 * Looks for the N indexes nearest to the specified point
159
	 * @param numberOfNearest
160
	 * @param point
161
	 * @return
162
	 */
163
	public List findNNearest(int numberOfNearest, Point2D point) {
164
		List solution = null;
165
		spatialindex.spatialindex.Point sptPoint = new
166
			spatialindex.spatialindex.Point(new double[]{point.getX(), point.getY()});
167
		RTreeVisitor visitor = new RTreeVisitor();
168
		rtree.nearestNeighborQuery(numberOfNearest, sptPoint,visitor);
169
		solution = visitor.getSolution();
170
		return solution;
171
	}
172

  
173

  
174

  
175
	public void flush(){
176
		rtree.flush();
177
	}
178

  
179
	public void load() {
180
//		 applies a main memory random buffer on top of the persistent
181
		// storage manager
182
		IBuffer buffer = new RandomEvictionsBuffer(diskfile, BUFFER_SIZE, false);
183

  
184
		// Create a new, empty, RTree with dimensionality 2, minimum load
185
		// 70%, using "file" as
186
		// the StorageManager and the RSTAR splitting policy.
187
		PropertySet ps2 = new PropertySet();
188

  
189
		Double f = new Double(defaultFillFactor);
190
		ps2.setProperty("FillFactor", f);
191

  
192
		Integer i = new Integer(2);
193
		ps2.setProperty("Dimension", i);
194

  
195
		File file = new File(rtreeFile + ".dat");
196
		if(file.length() != 0){
197
			ps2.setProperty("IndexIdentifier", new Integer(1));
198
		}
199
		rtree = new RTree(ps2, buffer);
200
	}
201
	
202
	public void load(File f) throws IndexException {
203
		load();
204
	}
205
	
206
	public void flush(File f) throws IndexException {
207
		flush();
208
	}
209

  
210
	public void close() {
211
	}
212

  
213
	public File getFile() {
214
		return new File(this.rtreeFile);
215
	}
216
}
branches/v2_0_0_prep/libraries/libFMap_spatialindex/src/org/gvsig/fmap/data/index/spatial/spatialindex/RTreeSptLibFactory.java
1
/* gvSIG. Geographic Information System of the Valencian Government
2
*
3
* Copyright (C) 2007-2008 Infrastructures and Transports Department
4
* of the Valencian Government (CIT)
5
* 
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License
8
* as published by the Free Software Foundation; either version 2
9
* of the License, or (at your option) any later version.
10
* 
11
* This program 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
14
* GNU General Public License for more details.
15
* 
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
19
* MA  02110-1301, USA.
20
* 
21
*/
22

  
23
/*
24
* AUTHORS (In addition to CIT):
25
* 2008 {{Company}}   {{Task}}
26
*/
27
 
28
package org.gvsig.fmap.data.index.spatial.spatialindex;
29

  
30
import java.io.File;
31
import java.io.IOException;
32

  
33
import org.gvsig.fmap.data.index.IndexException;
34
import org.gvsig.fmap.data.index.SpatialIndex;
35
import org.gvsig.fmap.data.index.SpatialIndexFactory;
36
import org.gvsig.fmap.data.index.SpatialIndexParameters;
37

  
38
public class RTreeSptLibFactory extends SpatialIndexFactory {
39

  
40
	static {
41
		registerFactory(Factories.SPATIALINDEX_RTREE, "RTreeSptLibFactory", RTreeSptLibFactory.class);
42
	}
43

  
44
	public SpatialIndex createSpatialIndex(SpatialIndexParameters params) throws IndexException {
45
		if  (params == null) {
46
			params = new SpatialIndexParameters();
47
		}
48
		
49
		String filename =  params.getFilename();
50
		
51
		if (filename == null) {
52
			try {
53
				File file = File.createTempFile("gvsig", ".qix");
54
				filename = file.getAbsolutePath();
55
				params.setOverwrite(true);
56
			} catch (IOException ioe) {
57
				throw new IndexException(ioe);
58
			}
59
		}
60
		
61
		return new RTreeSptLib(params.isOverwrite(), filename);
62
	}
63
	
64
}

Also available in: Unified diff