Statistics
| Revision:

root / branches / v2_0_0_prep / libraries / libFMap_spatialindex / src / org / gvsig / fmap / data / index / spatial / gt2 / QuadtreeGt2.java @ 23290

History | View | Annotate | Download (8 KB)

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.spatial.AbstractIntBasedSpatialIndex;
72
import org.gvsig.fmap.data.index.spatial.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
}