Statistics
| Revision:

root / branches / Mobile_Compatible_Hito_1 / libFMap_dataFile / src / org / gvsig / data / datastores / vectorial / file / shp / SHPResource.java @ 21571

History | View | Annotate | Download (13.7 KB)

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 IVER T.I   {{Task}}
26
*/
27

    
28
/**
29
 *
30
 */
31
package org.gvsig.data.datastores.vectorial.file.shp;
32

    
33
import java.awt.geom.Point2D;
34
import java.io.File;
35
import java.io.FileInputStream;
36
import java.io.FileNotFoundException;
37
import java.io.IOException;
38
import java.nio.ByteOrder;
39
import java.nio.channels.FileChannel;
40

    
41
import org.gvsig.data.CloseException;
42
import org.gvsig.data.OpenException;
43
import org.gvsig.data.ReadException;
44
import org.gvsig.data.datastores.vectorial.file.FileResource;
45
import org.gvsig.data.datastores.vectorial.file.shp.utils.SHP;
46
import org.gvsig.data.datastores.vectorial.file.shp.utils.ShapeFileHeader2;
47
import org.gvsig.fmap.geom.Geometry;
48
import org.gvsig.fmap.geom.GeometryFactory;
49
import org.gvsig.fmap.geom.GeometryManager;
50
import org.gvsig.fmap.geom.primitive.DefaultEnvelope;
51
import org.gvsig.fmap.geom.primitive.Envelope;
52
import org.gvsig.fmap.geom.primitive.GeneralPathX;
53
import org.gvsig.fmap.geom.primitive.NullGeometry;
54

    
55
import com.iver.utiles.bigfile.BigByteBuffer2;
56

    
57
/**
58
 * @author jmvivo
59
 *
60
 */
61
public class SHPResource extends FileResource {
62
        private boolean firstOpen = true;
63

    
64
        private Envelope extent;
65
        private int type;
66

    
67
        private FileInputStream fin;
68
        private FileChannel channel;
69
        private BigByteBuffer2 bb;
70
        private File fileShx;
71
        private FileInputStream finShx;
72
        private FileChannel channelShx;
73
        private BigByteBuffer2 bbShx;
74

    
75

    
76

    
77
        SHPResource (SHPStoreParameters params){
78
                super(params);
79
                this.fileShx = params.getSHXFile();
80
                this.file = params.getSHPFile();
81
        }
82

    
83
        /* (non-Javadoc)
84
         * @see org.gvsig.data.Resource#getName()
85
         */
86
        public String getName() {
87
                return "SHP";
88
        }
89

    
90

    
91
        /* (non-Javadoc)
92
         * @see org.gvsig.data.datastores.vectorial.file.IFileResource#getTotalFiles()
93
         */
94
        public int getTotalFiles() {
95
                return 2;
96
        }
97

    
98

    
99

    
100

    
101
        /* (non-Javadoc)
102
         * @see org.gvsig.data.Resource#doOpen()
103
         */
104
        protected boolean doOpen() throws OpenException {
105
                if (this.firstOpen){
106
                        this.updateLastModified();
107
                } else{
108
                        this.checkChanged();
109
                }
110
                this.openShp();
111
                this.setOpened();
112
                return true;
113
        }
114

    
115
        /* (non-Javadoc)
116
         * @see org.gvsig.data.Resource#doClose()
117
         */
118
        protected boolean doClose() throws CloseException{
119
                CloseException ret = null;
120

    
121
                try {
122
                        channel.close();
123
                        channelShx.close();
124
                } catch (IOException e) {
125
                        ret = new CloseException(this.description(),e);
126
                } finally {
127
                        try {
128
                                fin.close();
129
                                finShx.close();
130
                        } catch (IOException e1) {
131
                                ret = new CloseException(this.description(),e1);
132
                        }
133
                }
134

    
135
                if (ret != null) {
136
                        throw ret;
137
                }
138
                bb = null;
139
                bbShx = null;
140

    
141

    
142
                return super.doClose();
143
        }
144

    
145

    
146

    
147
        private void openShp() throws OpenException{
148
                try {
149
                        fin = new FileInputStream(this.getFile());
150

    
151

    
152
                        // Open the file and then get a channel from the stream
153
                        channel = fin.getChannel();
154

    
155
                        // long size = channel.size();
156

    
157
                        // Get the file's size and then map it into memory
158
                        // bb = channel.map(FileChannel.MapMode.READ_ONLY, 0, size);
159
                        bb = new BigByteBuffer2(channel, FileChannel.MapMode.READ_ONLY);
160
                        finShx = new FileInputStream(this.fileShx);
161

    
162
                        // Open the file and then get a channel from the stream
163
                        channelShx = finShx.getChannel();
164

    
165
//                        long sizeShx = channelShx.size();
166

    
167
                        // Get the file's size and then map it into memory
168
                        // bb = channel.map(FileChannel.MapMode.READ_ONLY, 0, size);
169
                        // bbShx = channelShx.map(FileChannel.MapMode.READ_ONLY, 0, sizeShx);
170
                        bbShx = new BigByteBuffer2(channelShx, FileChannel.MapMode.READ_ONLY);
171
                        bbShx.order(ByteOrder.BIG_ENDIAN);
172

    
173

    
174
//                        create a new header.
175
                        ShapeFileHeader2 myHeader = new ShapeFileHeader2();
176

    
177
                        bb.position(0);
178

    
179
                        // read the header
180
                        myHeader.readHeader(bb);
181

    
182
                        double[] min=new double[2];
183
                        min[0]=myHeader.myXmin;
184
                        min[1]=myHeader.myYmin;
185
                        double[] max=new double[2];
186
                        max[0]=myHeader.myXmax;
187
                        max[1]=myHeader.myYmax;
188

    
189
                        extent = new DefaultEnvelope(2,min,max);
190
//                        extent = new Rectangle2D.Double(myHeader.myXmin, myHeader.myYmin,
191
//                        myHeader.myXmax - myHeader.myXmin,
192
//                        myHeader.myYmax - myHeader.myYmin);
193

    
194
                        type = myHeader.myShapeType;
195

    
196
                        double x = myHeader.myXmin;
197
                        double y = myHeader.myYmin;
198
                        double w = myHeader.myXmax - myHeader.myXmin;
199
                        double h = myHeader.myYmax - myHeader.myYmin;
200

    
201
                        if (w == 0) {
202
                                x -= 0.1;
203
                                w = 0.2;
204
                        }
205

    
206
                        if (h == 0) {
207
                                y -= 0.1;
208
                                h = 0.2;
209
                        }
210

    
211

    
212
                } catch (FileNotFoundException e) {
213
                        throw new OpenException(this.description(),e);
214
                } catch (IOException e) {
215
                        throw new OpenException(this.description(),e);
216
                }
217

    
218

    
219
        }
220

    
221
        protected Envelope getFullExtent() throws ReadException{
222
                this.checkOpen();
223
                return this.extent;
224
        }
225

    
226
        public boolean isEditable(){
227
                return super.isEditable() && this.fileShx.canWrite();
228
        }
229

    
230
        protected int getGeometryType() throws ReadException {
231
                this.checkOpen();
232
                int auxType = 0;
233

    
234
                switch (type) {
235
                case (SHP.POINT2D):
236
                case (SHP.POINT3D):
237
                        auxType = auxType | Geometry.TYPES.POINT;
238

    
239
                break;
240

    
241
                case (SHP.POLYLINE2D):
242
                case (SHP.POLYLINE3D):
243
                        auxType = auxType | Geometry.TYPES.CURVE;
244

    
245
                break;
246

    
247
                case (SHP.POLYGON2D):
248
                case (SHP.POLYGON3D):
249
                        auxType = auxType | Geometry.TYPES.SURFACE;
250

    
251
                break;
252
                case (SHP.MULTIPOINT2D):
253
                case (SHP.MULTIPOINT3D):
254
                        auxType = auxType | Geometry.TYPES.MULTIPOINT;
255

    
256
                break;
257
                }
258

    
259
                return auxType;
260
        }
261

    
262
        protected synchronized Geometry getGeometry(long position) throws ReadException {
263
                this.checkOpen();
264
                Point2D p = new Point2D.Double();
265
                int numParts;
266
                int numPoints;
267
                int i;
268
                int j;
269
                int shapeType;
270

    
271
                GeometryFactory gFactory = GeometryManager.getInstance().getGeometryFactory();
272

    
273
                bb.position(getPositionForRecord(position));
274
                bb.order(ByteOrder.LITTLE_ENDIAN);
275

    
276
                shapeType = bb.getInt();
277
                //el shape tal con tema tal y n?mro tal es null
278
                if (shapeType==SHP.NULL){
279
                        return new NullGeometry();
280
                }
281

    
282
                // retrieve that shape.
283
                // tempRecord.setShape(readShape(tempShapeType, tempContentLength, in));
284
                switch (type) {
285
                case (SHP.POINT2D):
286
                        p = readPoint(bb);
287

    
288
                return gFactory.createPoint2D(p.getX(), p.getY());
289

    
290
                case (SHP.POLYLINE2D):
291

    
292
                        bb.position(bb.position() + 32);
293
                numParts = bb.getInt();
294
                numPoints = bb.getInt();
295

    
296
                // part indexes.
297
                // Geometry geom = GeometryFactory.toGeometryArray();
298
                GeneralPathX elShape = new GeneralPathX(GeneralPathX.WIND_EVEN_ODD,
299
                                numPoints);
300

    
301
                int[] tempParts = new int[numParts];
302

    
303
                for (i = 0; i < numParts; i++) {
304
                        tempParts[i] = bb.getInt();
305
                }
306

    
307
                j = 0;
308

    
309
                for (i = 0; i < numPoints; i++) {
310
                        p = readPoint(bb);
311

    
312
                        if (i == tempParts[j]) {
313
                                elShape.moveTo(p.getX(), p.getY());
314

    
315
                                if (j < (numParts - 1)) {
316
                                        j++;
317
                                }
318
                        } else {
319
                                elShape.lineTo(p.getX(), p.getY());
320
                        }
321
                }
322

    
323
                return gFactory.createPolyline2D(elShape);
324

    
325
                case (SHP.POLYGON2D):
326

    
327
                        //                            BoundingBox = readRectangle(bb);
328
//                        bb.getDouble();
329
//                        bb.getDouble();
330
//                        bb.getDouble();
331
//                        bb.getDouble();
332
                        bb.position(bb.position() + 32);
333
                numParts = bb.getInt();
334

    
335
                numPoints = bb.getInt();
336

    
337
                // part indexes.
338
                // Geometry geom = GeometryFactory.toGeometryArray();
339
                elShape = new GeneralPathX(GeneralPathX.WIND_EVEN_ODD, numPoints);
340

    
341
                tempParts = new int[numParts];
342

    
343
                for (i = 0; i < numParts; i++) {
344
                        tempParts[i] = bb.getInt();
345
                }
346

    
347
                j = 0;
348

    
349
                for (i = 0; i < numPoints; i++) {
350
                        p = readPoint(bb);
351

    
352
                        if (i == tempParts[j]) {
353
                                elShape.moveTo(p.getX(), p.getY());
354

    
355
                                if (j < (numParts - 1)) {
356
                                        j++;
357
                                }
358
                        } else {
359
                                if (i==numPoints-1){
360
                                        elShape.closePath();
361
                                }else{
362
                                        elShape.lineTo(p.getX(), p.getY());
363
                                }
364
                        }
365
                }
366

    
367
                return gFactory.createPolygon2D(elShape);
368

    
369
                case (SHP.POINT3D):
370

    
371
                        double x = bb.getDouble();
372
                double y = bb.getDouble();
373
                double z = bb.getDouble();
374

    
375
                return gFactory.createPoint3D(x, y, z);
376

    
377
                case (SHP.POLYLINE3D):
378
                        bb.position(bb.position() + 32);
379
                numParts = bb.getInt();
380
                numPoints = bb.getInt();
381
                elShape = new GeneralPathX(GeneralPathX.WIND_EVEN_ODD, numPoints);
382
                tempParts = new int[numParts];
383

    
384
                for (i = 0; i < numParts; i++) {
385
                        tempParts[i] = bb.getInt();
386
                }
387

    
388
                j = 0;
389

    
390
                for (i = 0; i < numPoints; i++) {
391
                        p = readPoint(bb);
392

    
393
                        if (i == tempParts[j]) {
394
                                elShape.moveTo(p.getX(), p.getY());
395

    
396
                                if (j < (numParts - 1)) {
397
                                        j++;
398
                                }
399
                        } else {
400
                                elShape.lineTo(p.getX(), p.getY());
401
                        }
402
                }
403

    
404
                double[] boxZ = new double[2];
405
                boxZ[0] = bb.getDouble();
406
                boxZ[1] = bb.getDouble();
407

    
408
                double[] pZ = new double[numPoints];
409

    
410
                for (i = 0; i < numPoints; i++) {
411
                        pZ[i] = bb.getDouble();
412
                }
413

    
414
                return gFactory.createPolyline3D(elShape, pZ);
415
                case (SHP.POLYGON3D):
416
                        bb.position(bb.position() + 32);
417
                numParts = bb.getInt();
418
                numPoints = bb.getInt();
419
                elShape = new GeneralPathX(GeneralPathX.WIND_EVEN_ODD, numPoints);
420
                tempParts = new int[numParts];
421

    
422
                for (i = 0; i < numParts; i++) {
423
                        tempParts[i] = bb.getInt();
424
                }
425

    
426
                j = 0;
427

    
428
                for (i = 0; i < numPoints; i++) {
429
                        p = readPoint(bb);
430

    
431
                        if (i == tempParts[j]) {
432
                                elShape.moveTo(p.getX(), p.getY());
433

    
434
                                if (j < (numParts - 1)) {
435
                                        j++;
436
                                }
437
                        } else {
438
                                if (i==numPoints-1){
439
                                        elShape.closePath();
440
                                }else{
441
                                        elShape.lineTo(p.getX(), p.getY());
442
                                }
443
                        }
444
                }
445

    
446
                double[] boxpoZ = new double[2];
447
                boxpoZ[0] = bb.getDouble();
448
                boxpoZ[1] = bb.getDouble();
449

    
450
                double[] poZ = new double[numPoints];
451

    
452
                for (i = 0; i < numPoints; i++) {
453
                        poZ[i] = bb.getDouble();
454
                }
455

    
456
                return gFactory.createPolygon3D(elShape, poZ);
457

    
458
                case (SHP.MULTIPOINT2D):
459
                        bb.position(bb.position() + 32);
460
                numPoints = bb.getInt();
461

    
462
                double[] tempX = new double[numPoints];
463
                double[] tempY = new double[numPoints];
464

    
465
                for (i = 0; i < numPoints; i++) {
466
                        tempX[i] = bb.getDouble();
467
                        tempY[i] = bb.getDouble();
468
                }
469

    
470
                return gFactory.createMultipoint2D(tempX, tempY);
471

    
472
                case (SHP.MULTIPOINT3D):
473
                        bb.position(bb.position() + 32);
474
                numPoints = bb.getInt();
475

    
476
                double[] temX = new double[numPoints];
477
                double[] temY = new double[numPoints];
478
                double[] temZ = new double[numPoints];
479

    
480
                for (i = 0; i < numPoints; i++) {
481
                        temX[i] = bb.getDouble();
482
                        temY[i] = bb.getDouble();
483
                        //temZ[i] = bb.getDouble();
484
                }
485

    
486
                for (i = 0; i < numPoints; i++) {
487
                        temZ[i] = bb.getDouble();
488
                }
489
                return gFactory.createMultipoint3D(temX, temY, temZ);
490
                }
491

    
492
                return null;
493

    
494

    
495
        }
496

    
497
        private long getPositionForRecord(long numRec)
498
        {
499
                // shx file has a 100 bytes header, then, records
500
                // 8 bytes length, one for each entity.
501
                // first 4 bytes are the offset
502
                // next 4 bytes are length
503

    
504
                int posIndex = 100 + ((int)numRec * 8);
505
                // bbShx.position(posIndex);
506
                long pos = 8 + 2* bbShx.getInt(posIndex);
507

    
508
                return pos;
509
        }
510
        /**
511
         * Reads the Point from the shape file.
512
         *
513
         * @param in ByteBuffer.
514
         *
515
         * @return Point2D.
516
         */
517
        private synchronized Point2D readPoint(BigByteBuffer2 in){
518
                // create a new point
519
                Point2D.Double tempPoint = new Point2D.Double();
520

    
521
                // bytes 1 to 4 are the type and have already been read.
522
                // bytes 4 to 12 are the X coordinate
523
                in.order(ByteOrder.LITTLE_ENDIAN);
524
                tempPoint.setLocation(in.getDouble(), in.getDouble());
525

    
526
                return tempPoint;
527
        }
528

    
529
        /**
530
         * Lee un rect?ngulo del fichero.
531
         *
532
         * @param in ByteBuffer.
533
         *
534
         * @return Rect?ngulo.
535
         *
536
         * @throws IOException
537
         */
538
        private synchronized Envelope readRectangle(BigByteBuffer2 in){
539
                in.order(ByteOrder.LITTLE_ENDIAN);
540
                double x = in.getDouble();
541
                double y = in.getDouble();
542

    
543
                double x2 = in.getDouble();
544

    
545
                if (x2-x == 0) {
546
                        x2 = 0.2;
547
                        x -= 0.1;
548
                }
549

    
550
                double y2 = in.getDouble();
551

    
552
                if (y2-y == 0) {
553
                        y2 = 0.2;
554
                        y -= 0.1;
555
                }
556
                Envelope tempEnvelope=new DefaultEnvelope(2,new double[]{x,y},new double[]{x2,y2});
557
                return tempEnvelope;
558
        }
559

    
560
        public Envelope getBoundingBox(long featureIndex) throws ReadException {
561
                this.checkOpen();
562
                Point2D p = new Point2D.Double();
563
                Envelope BoundingBox = null;
564
                try {
565
                        bb.position(getPositionForRecord(featureIndex));
566
                }catch (Exception e) {
567
                        e.printStackTrace();
568
//                        logger.error(" Shapefile is corrupted. Drawing aborted. ="+e+ "  "+"index = "+index);
569
                }
570
                bb.order(ByteOrder.LITTLE_ENDIAN);
571

    
572
                int tipoShape = bb.getInt();
573

    
574
                //AZABALA: si tipoShape viene con valores erroneos deja de funcionar
575
                //el metodo getShape(i)
576
//                if (tipoShape != SHP.NULL) {
577
//                type = tipoShape;
578

    
579
//                }
580

    
581
                // retrieve that shape.
582
                // tempRecord.setShape(readShape(tempShapeType, tempContentLength, in));
583
                switch (tipoShape) {
584
                case (SHP.POINT2D):
585
                case (SHP.POINT3D):
586
                        p = readPoint(bb);
587
                BoundingBox = new DefaultEnvelope(2,new double[]{p.getX() - 0.1, p.getY() - 0.1},new double[]{p.getX()+0.2,p.getY()+0.2});
588
//                new Rectangle2D.Double(p.getX() - 0.1,
589
//                p.getY() - 0.1, 0.2, 0.2);
590

    
591
                break;
592

    
593
                case (SHP.POLYLINE2D):
594
                case (SHP.POLYGON2D):
595
                case (SHP.MULTIPOINT2D):
596
                case (SHP.POLYLINE3D):
597
                case (SHP.POLYGON3D):
598
                case (SHP.MULTIPOINT3D):
599

    
600
                        // BoundingBox
601
                        BoundingBox = readRectangle(bb);
602

    
603
                break;
604
                }
605

    
606
                return BoundingBox;
607
        }
608

    
609
        /**
610
         * @return
611
         */
612
        public String getSRS() {
613
                // TODO Auto-generated method stub
614
                return null;
615
        }
616

    
617
        /* (non-Javadoc)
618
         * @see org.gvsig.data.datastores.vectorial.file.FileResource#editing()
619
         */
620
        protected void editing() {
621
                super.editing();
622
        }
623

    
624
        /* (non-Javadoc)
625
         * @see org.gvsig.data.datastores.vectorial.file.FileResource#stopEditing()
626
         */
627
        protected void stopEditing() {
628
                super.stopEditing();
629
        }
630

    
631
}
632