Statistics
| Revision:

root / branches / Mobile_Compatible_Hito_1 / libFMap / src / es / prodevelop / gvsig / mobile / fmap / driver / vect / shp / DiskShpDriver.java @ 21606

History | View | Annotate | Download (16.6 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2006 Prodevelop and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program 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
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 *
19
 * For more information, contact:
20
 *
21
 *   Generalitat Valenciana
22
 *   Conselleria d'Infraestructures i Transport
23
 *   Av. Blasco Ib??ez, 50
24
 *   46010 VALENCIA
25
 *   SPAIN
26
 *
27
 *   +34 963862235
28
 *   gvsig@gva.es
29
 *   http://www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   Prodevelop Integraci?n de Tecnolog?as SL
34
 *   Conde Salvatierra de ?lava , 34-10
35
 *   46004 Valencia
36
 *   Spain
37
 *
38
 *   +34 963 510 612
39
 *   +34 963 510 968
40
 *   gis@prodevelop.es
41
 *   http://www.prodevelop.es
42
 *
43
 *    or
44
 *
45
 *   Instituto de Rob?tica
46
 *   Apartado de correos 2085
47
 *   46071 Valencia
48
 *   (Spain)
49
 *   
50
 *   +34 963 543 577
51
 *   jjordan@robotica.uv.es
52
 *   http://robotica.uv.es
53
 *   
54
 */
55

    
56
package es.prodevelop.gvsig.mobile.fmap.driver.vect.shp;
57

    
58
import java.awt.geom.Rectangle2D;
59
import java.io.File;
60
import java.io.IOException;
61
import java.util.ArrayList;
62
import java.util.HashMap;
63

    
64
import org.apache.log4j.Logger;
65

    
66
import es.prodevelop.gvsig.mobile.fmap.core.FMapFastGeometry;
67
import es.prodevelop.gvsig.mobile.fmap.core.FNullGeometry;
68
import es.prodevelop.gvsig.mobile.fmap.core.FShape;
69
import es.prodevelop.gvsig.mobile.fmap.core.GeneralPathX;
70
import es.prodevelop.gvsig.mobile.fmap.core.IGeometry;
71
import es.prodevelop.gvsig.mobile.fmap.core.ShapeFactory;
72
import es.prodevelop.gvsig.mobile.fmap.driver.ITableDefinition;
73
import es.prodevelop.gvsig.mobile.fmap.util.Utils;
74

    
75
/**
76
 * SHP driver via JNI when the file does not have to be loaded into memory.
77
 * 
78
 * @see es.prodevelop.gvsig.mobile.fmap.driver.vect.shp.ShpReader
79
 * 
80
 * @author jldominguez
81
 */
82
public class DiskShpDriver extends MemoryShpDriver {
83
        
84
        private static Logger logger = Logger.getLogger(DiskShpDriver.class.getName());
85

    
86
        private long handler = 0;
87
        
88
        private int type;
89
        private int numReg;
90
        private Rectangle2D extent;
91
        private File fileShp = null;
92
        
93
        private HashMap shapesBoxes;
94

    
95
        /**
96
         * Closes the file
97
         *
98
         * @throws IOException
99
         *
100
         * @see com.iver.cit.gvsig.fmap.drivers.VectorialFileDriver#close()
101
         */
102
        public void close() throws IOException {
103
                // ShpReader.closeShpFile(handler);
104
        }
105

    
106
        /**
107
         * Opens the file with through JNI functions
108
         * 
109
         * @param f the file to be opened
110
         * 
111
         * @see com.iver.cit.gvsig.fmap.drivers.VectorialFileDriver#open(java.io.File)
112
         */
113
        public void open(File f) throws IOException {
114
                fileShp = f;
115
                handler = ShpReader.openShpFile(f.getCanonicalPath(), false);
116
        }
117
        /**
118
         * Gets the geometry for an index
119
         *
120
         * @param index index of the geometry of interest
121
         *
122
         * @return the geometry 
123
         *
124
         * @throws IOException 
125
         */
126
        public IGeometry getShape(int index) throws IOException {
127

    
128
                double[] shp = ShpReader.getShapeWithBox(handler, index);
129
                
130
                if (shp == null) return new FNullGeometry();
131
                addBoxToHash(index, shp[0], shp[1], shp[2], shp[3]);
132
                
133
                FMapFastGeometry resp = null;
134
                int _type = Math.round((float) shp[4]);
135
                int nparts = Math.round((float) shp[5]);
136
                int i;
137
                double[] coords;
138

    
139
                switch (_type) {
140

    
141
                case SHP.SHPT_POLYGON:
142
                        
143
                        resp = new FMapFastGeometry(2, true);
144
                        for (i=0; i<nparts; i++) {
145
                                coords = getPartSkipBox(shp, i, nparts, 2);
146
                                resp.addPart(coords);
147
                        }
148
                        break;
149

    
150
                        // -------------------------------------------------------------
151
                        // -------------------------------------------------------------
152

    
153
                case SHP.SHPT_ARC:
154
                        
155
                        resp = new FMapFastGeometry(2, false);
156
                        for (i=0; i<nparts; i++) {
157
                                        coords = getPartSkipBox(shp, i, nparts, 2);
158
                                        resp.addPart(coords);
159
                        }
160
                        break;
161

    
162
                                // -------------------------------------------------------------
163
                                // -------------------------------------------------------------
164
                
165
                case SHP.SHPT_ARCZ:
166
                case SHP.SHPT_ARCM:
167
                        resp = new FMapFastGeometry(3, false);
168

    
169
                                for (i = 0; i < nparts; i++) {
170
                                        coords = getPartSkipBox(shp, i, nparts, 3);
171
                                        resp.addPart(coords);
172
                                }
173
                                break;
174
                                
175
                                // -------------------------------------------------------------
176
                                // -------------------------------------------------------------
177

    
178
                case SHP.SHPT_POLYGONZ:
179
                case SHP.SHPT_POLYGONM:
180
                        
181
                        resp = new FMapFastGeometry(3, true);
182

    
183
                                for (i = 0; i < nparts; i++) {
184
                                        coords = getPartSkipBox(shp, i, nparts, 3);
185
                                        resp.addPart(coords);
186
                                }
187
                                break;
188
                        
189
                                // -------------------------------------------------------------
190
                                // -------------------------------------------------------------
191

    
192
                case SHP.SHPT_POINT:
193
                        resp = new FMapFastGeometry(2, false);
194
                                coords = getPartSkipBox(shp, 0, 1, 2);
195
                                resp.addPart(coords);
196
                                break;
197

    
198
                case SHP.SHPT_MULTIPOINT:
199
                        resp = new FMapFastGeometry(2, false);
200

    
201
                                for (i=0; i<nparts; i++) {
202
                                        coords = getPartSkipBox(shp, i, nparts, 2);
203
                                        resp.addPart(coords);
204
                                }
205
                                break;
206
                                
207
                                // -------------------------------------------------------------
208
                                // -------------------------------------------------------------
209
                                
210
                case SHP.SHPT_POINTZ:
211
                case SHP.SHPT_POINTM:
212
                        resp = new FMapFastGeometry(3, false);
213
                                coords = getPartSkipBox(shp, 0, 1, 3);
214
                                resp.addPart(coords);
215
                                break;
216
                                
217
                                // -------------------------------------------------------------
218
                                // -------------------------------------------------------------
219

    
220
                case SHP.SHPT_MULTIPOINTZ:
221
                case SHP.SHPT_MULTIPOINTM:
222
                        resp = new FMapFastGeometry(3, false);
223

    
224
                                for (i=0; i<nparts; i++) {
225
                                        coords = getPartSkipBox(shp, i, nparts, 3);
226
                                        resp.addPart(coords);
227
                        }
228
                                break;
229
                }
230

    
231
                try {
232
                        return fastGeometryToFMapGeometry(resp, _type);
233
                } catch (Exception ex) {
234
                        logger.debug("fastGeometryToFMapGeometry(resp, _type) DIO EXCEPCION, NULL");
235
                        return null;
236
                }
237
        }
238

    
239
        private void addBoxToHash(int index, double minx, double miny, double w, double h) {
240
                Rectangle2D rect = new Rectangle2D.Double(minx, miny, w, h);
241
                shapesBoxes.put(new Integer(index), rect);
242
        }
243

    
244
        /**
245
         * @return the number of geometries in this driver
246
         * @see com.iver.cit.gvsig.fmap.drivers.VectorialFileDriver#getShapeCount()
247
         */
248
        public int getShapeCount() {
249
                return numReg;
250
        }
251

    
252
        /**
253
         * @return the shape type of the geometries of this driver
254
         * 
255
         * @see com.iver.cit.gvsig.fmap.drivers.VectorialDriver#getShapeType()
256
         */
257
        public int getShapeType() {
258
                int auxType = 0;
259

    
260
                switch (type) {
261
                        case SHP.SHPT_POINT:
262
                        case SHP.SHPT_POINTZ:
263
                        case SHP.SHPT_POINTM:
264
                                auxType = auxType | FShape.POINT;
265
                                break;
266

    
267
                        case SHP.SHPT_ARC:
268
                        case SHP.SHPT_ARCZ:
269
                        case SHP.SHPT_ARCM:
270
                                auxType = auxType | FShape.LINE;
271
                                break;
272

    
273
                        case SHP.SHPT_POLYGON:
274
                        case SHP.SHPT_POLYGONZ:
275
                        case SHP.SHPT_POLYGONM:
276
                                auxType = auxType | FShape.POLYGON;
277
                                break;
278

    
279
                        case SHP.SHPT_MULTIPOINT:
280
                        case SHP.SHPT_MULTIPOINTZ:
281
                        case SHP.SHPT_MULTIPOINTM:
282
                                auxType = auxType | FShape.MULTIPOINT;
283

    
284
                                break;
285
                }
286

    
287
                return auxType;
288
        }
289

    
290

    
291
        /**
292
         * Initializes the driver
293
         * 
294
         * @see com.iver.cit.gvsig.fmap.drivers.VectorialFileDriver#initialize()
295
         */
296
        public void initialize() throws IOException {
297
                
298
                double[] meta = ShpReader.getShpMetadata(handler);
299
                
300
                shapesBoxes = new HashMap();
301
                // [tipo, ext_min_x, ext_min_y, ext_w, ext_h, numReg]
302
                
303
                if (meta == null) {
304
                        // error
305
                        logger.error(Utils.time() + "No se pudo obtener metadatos de archivo SHP: " + fileShp.getName());
306
                        type = SHP.SHPT_NULL;
307
                        extent = new Rectangle2D.Double(0, 0, 1, 1);
308
                        numReg = 0;
309
                } else {
310
                        // ok
311
                        type = Math.round((float) meta[0]);
312
                        extent = new Rectangle2D.Double(meta[1], meta[2], meta[3], meta[4]);
313
                        numReg = Math.round((float) meta[5]);
314
                }
315
        }
316

    
317

    
318
        /**
319
         * Gets the extent of the geometries of this driver
320
         * 
321
         * @see com.iver.cit.gvsig.fmap.drivers.VectorialFileDriver#getFullExtent()
322
         */
323
        public Rectangle2D getFullExtent() throws IOException {
324
                return extent;
325
        }
326

    
327

    
328
        /**
329
         * @see com.iver.cit.gvsig.fmap.drivers.VectorialFileDriver#accept(java.io.File)
330
         */
331
        public boolean accept(File f) {
332
                return (f.getName().toUpperCase().endsWith("SHP"));
333
        }
334

    
335
        /**
336
         * @see com.iver.cit.gvsig.fmap.drivers.VectorialFileDriver#getDataFile(java.io.File)
337
         */
338
        public File getDataFile(File f) {
339
                String str = f.getAbsolutePath();
340
                return new File(str.substring(0, str.length() - 3) + "dbf");
341
        }
342

    
343
        /**
344
         * Gets the SHX associated with the given SHP file
345
         * 
346
         * @param f a file objects that points to a SHP file
347
         * @return the associated SHX file
348
         *   
349
         */
350
    public File getShxFile(File f) {
351
        String str = f.getAbsolutePath();
352

    
353
        return new File(str.substring(0, str.length() - 3) + "shx");
354
    }
355

    
356

    
357
        /**
358
         * Gets the shape type of the geometry of interest. Currently redirects to
359
         * <code>getShapeType()</code> 
360
         * 
361
         * @param index the index of the geometry of interest
362
         * @return the type of the geometry
363
         */
364
        public int getShapeType(int index) {
365
                return getShapeType();
366
        }
367

    
368
    /**
369
     * 
370
     * @return the main SHP file
371
     */
372
        public File getFile() {
373
                return fileShp;
374
        }
375

    
376
        /**
377
         * Reloads this driver (reopens and initializes)
378
         */
379
        public void reload() throws IOException {
380
                open(fileShp);
381
                initialize();
382
        }
383

    
384
        /**
385
         * Initializes the driver with the given table definition. Currently unused.
386
         * 
387
         * @param layerDef the table definitiion to be used
388
         */
389
        public void initialize(ITableDefinition layerDef) {
390
        }
391

    
392
        /**
393
         * @return Whether the driver is writable. Currently unused. 
394
         *  
395
         */
396
        public boolean isWritable() {
397
                return fileShp.canWrite();
398
        }
399

    
400
        /**
401
         * @return whether the associated table can be altered. Returns false. Currently
402
         * unused.
403
         */
404
        public boolean canAlterTable() {
405
                return false;
406
        }
407

    
408
        /**
409
         * Currently unused.
410
         */
411
        public boolean isWriteAll() {
412
                return true;
413
        }
414

    
415
        /**
416
         * 
417
         * @return the main SHP file handler
418
         */
419
        public long getHandler() {
420
                return handler;
421
        }
422

    
423
        /**
424
         * Sets the main file handler
425
         * @param h the new handler
426
         */
427
        public void setHandler(long h) {
428
                handler = h;
429
        }
430

    
431
        /**
432
         * Gets the extent of one geometry of this driver.
433
         * 
434
         * @param index the index of the geometry of interest
435
         * @return the bounding box of the geometry
436
         */
437
        public Rectangle2D getShapeBounds(int index) throws IOException {
438
                
439
                Integer _index = new Integer(index);
440
                Rectangle2D rect = (Rectangle2D) shapesBoxes.get(_index);
441
                if (rect == null) {
442
                        double[] bounds = ShpReader.getShapeBounds(handler, index);
443
                        rect = new Rectangle2D.Double(bounds[0], bounds[1], bounds[2], bounds[3]);
444
                        shapesBoxes.put(_index, rect);
445
                }
446
                return rect;
447
        }
448

    
449
        private double[] getPartSkipBox(double[] shp, int part, int n_parts, int dim) {
450
                
451
                int part_start = dim * Math.round((float) shp[part + 6]);
452
                int part_size = dim * Math.round((float) shp[part + 7]) - part_start;
453
                
454
                double[] resp = new double[part_size];
455
                
456
                for (int i=0; i<part_size; i++) {
457
                        resp[i] = shp[7 + n_parts + part_start + i];
458
                }
459
                return resp;
460
        }
461
        
462
        private IGeometry fastGeometryToFMapGeometry(FMapFastGeometry fg, int type) throws Exception {
463
                
464
                if (fg == null) return null;
465
                IGeometry ig = null;
466
                
467
                GeneralPathX elShape;
468
                int numParts, i, v;
469
                double[] part;
470
                double[] zc;
471
                ArrayList zcoords = new ArrayList();
472
                double[] pointx;
473
                double[] pointy;
474
                double[] pointz;
475
                
476
                switch (type) {
477

    
478
                case SHP.SHPT_POLYGON:
479
                        numParts = fg.getNumberOfParts();
480
                        elShape = new GeneralPathX(GeneralPathX.WIND_EVEN_ODD, fg.getPart(0).length);
481
                        
482
                        for (i = 0; i < numParts; i++) {
483
                                part = fg.getPart(i);
484
                                int part_size = part.length / 2;
485
                                elShape.moveTo(part[0], part[1]);
486
                                for (v = 1; v < part_size; v++) {
487
                                        elShape.lineTo(part[2 * v], part[2 * v + 1]);
488
                                }
489
                        }
490
                        zc = getDoubleArray(zcoords);
491
                        ig = ShapeFactory.createPolygon2D(elShape);
492
                        break;
493

    
494
                        // -------------------------------------------------------------
495
                        // -------------------------------------------------------------
496

    
497
                case SHP.SHPT_ARC:
498
                        numParts = fg.getNumberOfParts();
499
                        elShape = new GeneralPathX(GeneralPathX.WIND_EVEN_ODD, fg.getPart(0).length);
500
                        
501
                        for (i = 0; i < numParts; i++) {
502
                                part = fg.getPart(i);
503
                                int part_size = part.length / 2;
504
                                elShape.moveTo(part[0], part[1]);
505
                                for (v = 1; v < part_size; v++) {
506
                                        elShape.lineTo(part[2 * v], part[2 * v + 1]);
507
                                }
508
                        }
509
                        ig = ShapeFactory.createPolyline2D(elShape);
510
                        break;
511

    
512
                                // -------------------------------------------------------------
513
                                // -------------------------------------------------------------
514
                
515
                case SHP.SHPT_ARCZ:
516
                case SHP.SHPT_ARCM:
517
                        numParts = fg.getNumberOfParts();
518
                        elShape = new GeneralPathX(GeneralPathX.WIND_EVEN_ODD, fg.getPart(0).length);
519
                        
520
                        for (i = 0; i < numParts; i++) {
521
                                part = fg.getPart(i);
522
                                int part_size = part.length / 3;
523
                                elShape.moveTo(part[0], part[1]);
524
                                zcoords.add(new Double(part[2]));
525
                                for (v = 1; v < part_size; v++) {
526
                                        elShape.lineTo(part[3 * v], part[3 * v + 1]);
527
                                        zcoords.add(new Double(part[3 * v + 2]));
528
                                }
529
                        }
530
                        zc = getDoubleArray(zcoords);
531
                        ig = ShapeFactory.createPolyline3D(elShape, zc);
532
                        break;
533
                                
534
                                // -------------------------------------------------------------
535
                                // -------------------------------------------------------------
536

    
537
                case SHP.SHPT_POLYGONZ:
538
                case SHP.SHPT_POLYGONM:
539
                        numParts = fg.getNumberOfParts();
540
                        elShape = new GeneralPathX(GeneralPathX.WIND_EVEN_ODD, fg.getPart(0).length);
541
                        
542
                        for (i = 0; i < numParts; i++) {
543
                                part = fg.getPart(i);
544
                                int part_size = part.length / 3;
545
                                elShape.moveTo(part[0], part[1]);
546
                                zcoords.add(new Double(part[2]));
547
                                for (v = 1; v < part_size; v++) {
548
                                        elShape.lineTo(part[3 * v], part[3 * v + 1]);
549
                                        zcoords.add(new Double(part[3 * v + 2]));
550
                                }
551
                        }
552
                        zc = getDoubleArray(zcoords);
553
                        ig = ShapeFactory.createPolygon3D(elShape, zc);
554
                        break;
555
                        
556
                                // -------------------------------------------------------------
557
                                // -------------------------------------------------------------
558

    
559
                case SHP.SHPT_POINT:
560
                        part = fg.getPart(0);
561
                        ig = ShapeFactory.createPoint2D(part[0], part[1]);
562
                        break;
563
                        
564
                        // -------------------------------------------------------------
565
                        // -------------------------------------------------------------
566

    
567
                case SHP.SHPT_MULTIPOINT:
568
                        numParts = fg.getNumberOfParts();
569
                        pointx = new double[numParts];
570
                        pointy = new double[numParts];
571
                        
572
                        for (i = 0; i < numParts; i++) {
573
                                part = fg.getPart(i);
574
                                pointx[i] = part[0];
575
                                pointy[i] = part[1];
576
                        }
577
                        ig = ShapeFactory.createMultipoint2D(pointx, pointy);
578
                        break;
579
                                
580
                                // -------------------------------------------------------------
581
                                // -------------------------------------------------------------
582
                                
583
                case SHP.SHPT_POINTZ:
584
                case SHP.SHPT_POINTM:
585
                        part = fg.getPart(0);
586
                        ig = ShapeFactory.createPoint3D(part[0], part[1], part[2]);
587
                        break;
588
                                
589
                                // -------------------------------------------------------------
590
                                // -------------------------------------------------------------
591

    
592
                case SHP.SHPT_MULTIPOINTZ:
593
                case SHP.SHPT_MULTIPOINTM:
594
                        numParts = fg.getNumberOfParts();
595
                        pointx = new double[numParts];
596
                        pointy = new double[numParts];
597
                        pointz = new double[numParts];
598
                        
599
                        for (i = 0; i < numParts; i++) {
600
                                part = fg.getPart(i);
601
                                pointx[i] = part[0];
602
                                pointy[i] = part[1];
603
                                pointz[i] = part[2];
604
                        }
605
                        ig = ShapeFactory.createMultipoint3D(pointx, pointy, pointz);
606
                        break;
607
                }
608

    
609
                return ig;
610
        }
611

    
612
        private double[] getDoubleArray(ArrayList zcoords) {
613
                int size = zcoords.size();
614
                double[] resp = new double[size];
615
                for (int i=0; i<size; i++) resp[i] = ((Double) zcoords.get(i)).doubleValue();
616
                return resp;
617
        }
618
        
619
        /**
620
         * Gets the indices of the geometries intersecting the given rectangle
621
         * 
622
         * @param rect the rectangle of interest
623
         * @param max the maximum number of indices to be returned
624
         */
625
        public int[] getIntersectingIndices(Rectangle2D rect, int max) throws IOException {
626
                
627
                ArrayList _resp = new ArrayList();
628
                for (int i=0; i<numReg; i++) {
629
                        Integer ind_obj = new Integer(i);
630
                        Rectangle2D item_bb = (Rectangle2D) shapesBoxes.get(ind_obj); 
631
                        if (Utils.rectanglesItersect(item_bb, rect)) {
632
                                IGeometry ig = getShape(i);
633
                                if (ig.getGeometryType() == FShape.POINT || ig.intersects(rect)) {
634
                                        _resp.add(new Integer(i));
635
                                        if (_resp.size() == max) {
636
                                                break;
637
                                        }
638
                                }
639
                        }
640
                }
641
                int size = _resp.size();
642
                int[] resp = new int[size];
643
                for (int i=0; i<size; i++) resp[i] = ((Integer) _resp.get(i)).intValue();
644
                return resp;
645
        }
646
        
647

    
648
}