Statistics
| Revision:

root / branches / v2_0_0_prep / libraries / libFMap_dalindex / src / org / gvsig / fmap / dal / index / spatial / gt2 / QuadtreeGt2.java @ 24636

History | View | Annotate | Download (9.21 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.dal.index.spatial.gt2;
60

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

    
66
import org.geotools.index.quadtree.Node;
67
import org.geotools.index.quadtree.QuadTree;
68
import org.geotools.index.quadtree.StoreException;
69
import org.geotools.index.quadtree.fs.FileSystemIndexStore;
70
import org.geotools.index.quadtree.fs.IndexHeader;
71
import org.gvsig.fmap.dal.exception.InitializeException;
72
import org.gvsig.fmap.dal.feature.FeatureStore;
73
import org.gvsig.fmap.dal.feature.exception.FeatureIndexException;
74
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
75
import org.gvsig.fmap.dal.feature.spi.index.AbstractFeatureIndexProvider;
76
import org.gvsig.fmap.dal.feature.spi.index.FeatureIndexProvider;
77
import org.gvsig.tools.exception.BaseException;
78

    
79
import com.vividsolutions.jts.geom.Envelope;
80

    
81
/**
82
 * This Quadtree spatial index implementation is based in a fork of
83
 * org.geotools.index.quadtree.Quadtree implementation. <br>
84
 * This implementation offers us:
85
 * <ol>
86
 * <li>Persistence of spatial index</li>
87
 * </ol>
88
 * We had to fork geotools quadtree for many reasons:
89
 * <ol>
90
 * <li>It was strongly dependent of SHP format, so it returned not only a num
91
 * of rectangle, it also returned byte offset of this rectangle in shp file</li>
92
 * <li> Query artifact wasnt run well at all </li>
93
 * </ol>
94
 *
95
 * @author azabala
96
 *
97
 */
98
public class QuadtreeGt2 extends AbstractFeatureIndexProvider implements FeatureIndexProvider {
99

    
100
        public static final String NAME = "QuadtreeGt2";
101
        /**
102
         * Geotools quadtree implementation
103
         */
104
        QuadTree quadtree;
105
        /**
106
         * Persistent storage
107
         */
108
        String fileName;
109
        /**
110
         * Spatial index file extension
111
         */
112
        final String qExt = ".qix";
113
        /**
114
         * qix format has many versions, and allows different byte orders.
115
         */
116
        String byteOrder;
117
        /**
118
         * Bounds of the layer to index
119
         */
120
        //Envelope bounds;
121
        /**
122
         * Number of records of the layer to index
123
         */
124
        //int numRecs = 0;
125

    
126
        boolean inMemory = false;
127

    
128
        public QuadtreeGt2() {
129

    
130
        }
131

    
132
        public void initialize() throws InitializeException {
133
                try {
134
                        File file = File.createTempFile(getFeatureStore().getName(), ".qix");
135
                        this.fileName = file.getAbsolutePath();
136
                        org.gvsig.fmap.geom.primitive.Envelope env = getFeatureStore()
137
                                        .getEnvelope();
138
                        int featureCount = (int) getFeatureStore().getFeatureSet().getSize();
139
                        this.byteOrder = "NM";
140
                        quadtree = new QuadTree(featureCount, toJtsEnvelope(env));
141
                        if (exists()) {
142
                                load();
143
                        }
144
                } catch (IOException e) {
145
                        throw new InitializeException(e);
146
                } catch (BaseException e) {
147
                        throw new InitializeException(e);
148
                }
149
        }
150

    
151
        /**
152
         * If the spatial index file exists and has content
153
         */
154
        public boolean exists() {
155
                return (new File(fileName).length() != 0);
156
        }
157

    
158
        public void load() throws FeatureIndexException {
159
                if (quadtree == null) {
160
                        load(new File(fileName));
161
                }
162
        }
163

    
164
        public void load(File f) throws FeatureIndexException {
165
                try {
166
                        FileSystemIndexStore store = new FileSystemIndexStore(f);
167
                        quadtree = store.load();
168
                        this.fileName = f.getAbsolutePath();
169
                } catch (StoreException e) {
170
                        throw new FeatureIndexException(e);
171
                }
172
        }
173

    
174
        /**
175
         * Inserts an object in the index
176
         */
177
        public void insert(org.gvsig.fmap.geom.primitive.Envelope env, int index) {
178
                if (env == null) {
179
                        throw new IllegalArgumentException("Envelope cannot be null");
180
                }
181
                Envelope e = toJtsEnvelope(env);
182
                if (e == null) {
183
                        throw new IllegalStateException(
184
                                        "JTS Envelope conversion returns null");
185
                }
186
                System.out.println("recno=" + index);
187
                if (quadtree == null) {
188
                        throw new IllegalStateException("quadtree is null");
189
                }
190
                try {
191
                        quadtree.insert(index, toJtsEnvelope(env));
192
                } catch (StoreException se) {
193
                        // TODO Auto-generated catch block
194
                        se.printStackTrace();
195
                }
196
        }
197

    
198
        public void delete(org.gvsig.fmap.geom.primitive.Envelope env, int index) {
199
                if (inMemory) {
200
                        quadtree.delete(toJtsEnvelope(env), index);
201
                }
202
        }
203

    
204
        public Envelope toJtsEnvelope(org.gvsig.fmap.geom.primitive.Envelope env) {
205
                if (env == null) {
206
                        return null;
207
                }
208
                double[] min = env.getLowerCorner();
209
                double[] max = env.getUpperCorner();
210
                return new Envelope(min[0], max[0], min[1], max[1]);
211
        }
212

    
213
        /**
214
         *
215
         * @throws StoreException
216
         * @deprecated
217
         */
218
        void openQuadTree() throws StoreException {
219
                if (quadtree == null) {
220
                        File file = new File(this.fileName);
221
                        // Intento de cargar todo el quadtree en memoria
222
                        FileSystemIndexStore store = new FileSystemIndexStore(file);
223
                        quadtree = store.load();
224
                }
225
        }
226

    
227
        void openQuadTreeInMemory() throws StoreException {
228
                if (quadtree == null) {
229
                        File file = new File(fileName);
230
                        // Intento de cargar todo el quadtree en memoria
231
                        FileSystemIndexStore store = new FileSystemIndexStore(file);
232
                        QuadTree filequadtree = store.load();
233
                        quadtree = new QuadTree(filequadtree.getNumShapes(), filequadtree
234
                                        .getMaxDepth(), filequadtree.getRoot().getBounds());
235
                        Stack nodes = new Stack();
236
                        nodes.push(filequadtree.getRoot());
237
                        while (nodes.size() != 0) {
238
                                Node node = (Node) nodes.pop();
239
                                Envelope nodeEnv = node.getBounds();
240
                                int[] shapeIds = node.getShapesId();
241
                                for (int i = 0; i < shapeIds.length; i++) {
242
                                        quadtree.insert(shapeIds[i], nodeEnv);
243
                                }
244
                                int numSubnodes = node.getNumSubNodes();
245
                                for (int i = 0; i < numSubnodes; i++) {
246
                                        nodes.push(node.getSubNode(i));
247
                                }
248
                        }// while
249
                        filequadtree.close();
250
                }
251
        }
252

    
253
        public void flush() throws FeatureIndexException {
254
                flush(new File(fileName));
255
        }
256

    
257
        public void flush(File f) throws FeatureIndexException {
258
                byte order = 0;
259
                if ((byteOrder == null) || byteOrder.equalsIgnoreCase("NM")) {
260
                        order = IndexHeader.NEW_MSB_ORDER;
261
                } else if (byteOrder.equalsIgnoreCase("NL")) {
262
                        order = IndexHeader.NEW_LSB_ORDER;
263
                }
264
                FileSystemIndexStore store = new FileSystemIndexStore(f, order);
265
                try {
266
                        store.store(quadtree);
267
                        this.fileName = f.getAbsolutePath();
268
                } catch (StoreException e) {
269
                        throw new FeatureIndexException(e);
270
                }
271
        }
272

    
273
        private void close() throws FeatureIndexException {
274
                try {
275
                        quadtree.close();
276
                } catch (StoreException e) {
277
                        throw new FeatureIndexException(e);
278
                }
279
        }
280

    
281
        public File getFile() {
282
                return new File(this.fileName);
283
        }
284

    
285
        private FeatureStore getFeatureStore() {
286
                return getFeatureIndexProviderServices().getFeatureStore();
287
        }
288

    
289
        public void delete(Object value, FeatureReferenceProviderServices fref) {
290
                delete((org.gvsig.fmap.geom.primitive.Envelope) value, ((Integer) fref
291
                                .getOID()).intValue());
292
        }
293

    
294
        public void insert(Object value, FeatureReferenceProviderServices fref) {
295
                insert((org.gvsig.fmap.geom.primitive.Envelope) value, ((Integer) fref
296
                                .getOID()).intValue());
297
        }
298

    
299
        public List match(Object value) throws FeatureIndexException {
300
                if (quadtree == null) {
301
                        throw new IllegalStateException("This quadtree is null.");
302
                }
303
                if (value == null) {
304
                        throw new IllegalArgumentException("Envelope cannot be null.");
305
                }
306
                if (!(value instanceof org.gvsig.fmap.geom.primitive.Envelope)) {
307
                        throw new IllegalArgumentException("Not an envelope.");
308
                }
309
                return quadtree.query(toJtsEnvelope((org.gvsig.fmap.geom.primitive.Envelope) value));
310
        }
311

    
312
        public List nearest(int count, Object value) throws FeatureIndexException {
313
                throw new UnsupportedOperationException();
314
        }
315

    
316
        public boolean isMatchSupported() {
317
                return true;
318
        }
319

    
320
        public boolean isNearestSupported() {
321
                return false;
322
        }
323

    
324
        public boolean isNearestToleranceSupported() {
325
                return false;
326
        }
327

    
328
        public boolean isRangeSupported() {
329
                return false;
330
        }
331

    
332
        public List nearest(int count, Object value, double tolerance)
333
                        throws FeatureIndexException {
334
                throw new UnsupportedOperationException();
335
        }
336

    
337
        public List range(Object value1, Object value2) throws FeatureIndexException {
338
                throw new UnsupportedOperationException();
339
        }
340

    
341
}