Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libFMap / src / com / iver / cit / gvsig / fmap / spatialindex / PersistentRTreeJsi.java @ 20701

History | View | Annotate | Download (6.53 KB)

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 com.iver.cit.gvsig.fmap.spatialindex;
54

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

    
70
import javax.imageio.stream.FileImageOutputStream;
71

    
72
import com.infomatiq.jsi.IntProcedure;
73
import com.infomatiq.jsi.Rectangle;
74
import com.infomatiq.jsi.rtree.RTree;
75

    
76
/**
77
 * Persistent spatial index which can resolve nearest neighbour queries.
78
 * <br>
79
 * 
80
 * To use:
81
 * 
82
 * PersistentRTreeJsi sptidx = new PersistentRtreeJsi("/home/kk");
83
 * if(sptidx.exists())
84
 *  sptidx.load();
85
 *  
86
 *  
87
 *  sptidx.add(rect, int);
88
 *  ...
89
 *  sptidx.add(rect2,int2);
90
 *  sptidx.flush();
91
 * 
92
 * @author azabala
93
 *
94
 */
95
public class PersistentRTreeJsi implements IPersistentSpatialIndex,
96
                INearestNeighbourFinder, ISpatialIndex {
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 SpatialIndexException 
119
         */
120
        public PersistentRTreeJsi(String file, boolean overwrite) throws SpatialIndexException {
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
        
131
        public void flush() {
132
                try {
133
                        if(! hasChange)
134
                                return;
135
                        RandomAccessFile file = new RandomAccessFile(rtreeFile,
136
                                                                                                                        "rw");
137
                        FileImageOutputStream output = new FileImageOutputStream(file);
138
                        output.setByteOrder(ByteOrder.LITTLE_ENDIAN);
139
                        int numShapes = rtree.size();
140
                        output.writeInt(numShapes);
141
                        
142
                        Iterator iterator = rtree.iterator();
143
                        int count = 0;
144
                        while(iterator.hasNext()){
145
                                Integer  idx = (Integer) iterator.next();
146
                                Rectangle nr = (Rectangle) rectangles.get(idx);
147
                                float xmin = nr.min[0];
148
                                float ymin = nr.min[1];
149
                                
150
                                float xmax = nr.max[0];
151
                                float ymax = nr.max[1];
152
                                
153
                                
154
                                output.writeFloat(xmin);
155
                                output.writeFloat(ymin);
156
                                output.writeFloat(xmax);
157
                                output.writeFloat(ymax);
158
                                
159
                                output.writeInt(idx.intValue());
160
                                count++;
161
                        }
162
                        output.flush();
163
                        output.close();
164
                        file.close();
165
                        hasChange = false;
166
                } catch (FileNotFoundException e) {
167
                        // TODO Auto-generated catch block
168
                        e.printStackTrace();
169
                } catch (IOException e) {
170
                        // TODO Auto-generated catch block
171
                        e.printStackTrace();
172
                }
173
        }
174

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

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

    
210
        public void close() {
211
                rectangles.clear();
212
                rectangles = null;
213
        }
214

    
215
        
216
        //TODO Make this class public and remove duplicates with
217
        //RTreeJsi
218
        class ListIntProcedure implements IntProcedure{
219
                ArrayList solution = new ArrayList();
220
                
221
                public boolean execute(int arg0) {
222
                        solution.add(new Integer(arg0));
223
                        return true;
224
                }
225
                
226
                public List getSolution(){
227
                        return solution;
228
                }
229
        }
230
        
231
        
232
        public List query(Rectangle2D rect) {
233
                ListIntProcedure solution = new ListIntProcedure();
234
                rtree.intersects(toJsiRect(rect), solution);
235
                return solution.getSolution();
236
        }
237

    
238
        public void insert(Rectangle2D rect, int index) {
239
                Rectangle jsiRect = toJsiRect(rect);
240
                rtree.add(jsiRect, index);
241
                rectangles.put(new Integer(index), jsiRect);
242
                hasChange = true;
243
        }
244

    
245
        
246
        public void delete(Rectangle2D rect, int index) {
247
                rtree.delete(toJsiRect(rect), index);
248
                rectangles.remove(new Integer(index));
249
                hasChange = true;
250
        }
251

    
252
        
253
        public List findNNearest(int numberOfNearest, Rectangle2D rect){
254
                return (List) rtree.nearest(toJsiRect(rect), numberOfNearest);
255
        }
256
        
257
        public List findNNearest(int numberOfNearest, Point2D point){
258
                com.infomatiq.jsi.Point jsiPoint =
259
                        new com.infomatiq.jsi.Point((float)point.getX(),(float)point.getY());
260
                return (List) rtree.nearest(jsiPoint, numberOfNearest);
261
        }
262
        
263
        
264
//        TODO Make this method abstract  and remove duplicates with
265
        //RTreeJsi
266
        private Rectangle toJsiRect(Rectangle2D rect){
267
                Rectangle jsiRect = new Rectangle((float)rect.getMinX(),
268
                                (float)rect.getMinY(),
269
                                (float)rect.getMaxX(),
270
                                (float)rect.getMaxY());
271
                return jsiRect;
272
        }
273
        
274
        public int size(){
275
                return rtree.size();
276
        }
277

    
278
}
279