Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libFMap_dataFile / src / org / gvsig / data / datastores / vectorial / file / shp / SHPResource.java @ 20660

History | View | Annotate | Download (13.5 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.datastores.vectorial.file.FileResource;
42
import org.gvsig.data.datastores.vectorial.file.shp.utils.SHP;
43
import org.gvsig.data.datastores.vectorial.file.shp.utils.ShapeFileHeader2;
44
import org.gvsig.data.exception.CloseException;
45
import org.gvsig.data.exception.OpenException;
46
import org.gvsig.data.exception.ReadException;
47
import org.gvsig.data.spatialprovisional.Extent;
48
import org.gvsig.data.spatialprovisional.IExtent;
49

    
50
import com.iver.cit.gvsig.fmap.core.FNullGeometry;
51
import com.iver.cit.gvsig.fmap.core.FShape;
52
import com.iver.cit.gvsig.fmap.core.GeneralPathX;
53
import com.iver.cit.gvsig.fmap.core.IGeometry;
54
import com.iver.cit.gvsig.fmap.core.ShapeFactory;
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 Extent extent;
65
        private int type;
66

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

    
76

    
77

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

    
84
        /* (non-Javadoc)
85
         * @see org.gvsig.data.Resource#description()
86
         */
87
        public String description() {
88
                if (this.getFile()!= null){
89
                        return "SHP File resource: " + this.getFile().getAbsolutePath();
90
                } else{
91
                        return "SHP File resource: {No file}";
92
                }
93
        }
94

    
95
        /* (non-Javadoc)
96
         * @see org.gvsig.data.Resource#getKey()
97
         */
98
        public String getKey() {
99
                return "SHP:"+this.getFile().getAbsolutePath();
100
        }
101

    
102
        /* (non-Javadoc)
103
         * @see org.gvsig.data.datastores.vectorial.file.IFileResource#getTotalFiles()
104
         */
105
        public int getTotalFiles() {
106
                return 2;
107
        }
108

    
109

    
110

    
111

    
112
        /* (non-Javadoc)
113
         * @see org.gvsig.data.Resource#doOpen()
114
         */
115
        protected boolean doOpen() throws OpenException {
116
                if (this.firstOpen){
117
                        this.updateLastModified();
118
                } else{
119
                        this.checkChanged();
120
                }
121
                this.openShp();
122
                this.setOpened();
123
                return true;
124
        }
125

    
126
        /* (non-Javadoc)
127
         * @see org.gvsig.data.Resource#doClose()
128
         */
129
        protected boolean doClose() throws CloseException{
130
                CloseException ret = null;
131

    
132
                try {
133
                        channel.close();
134
                        channelShx.close();
135
                } catch (IOException e) {
136
                        ret = new CloseException(this.description(),e);
137
                } finally {
138
                        try {
139
                                fin.close();
140
                                finShx.close();
141
                        } catch (IOException e1) {
142
                                ret = new CloseException(this.description(),e1);
143
                        }
144
                }
145

    
146
                if (ret != null) {
147
                        throw ret;
148
                }
149
                bb = null;
150
                bbShx = null;
151

    
152

    
153
                return super.doClose();
154
        }
155

    
156

    
157

    
158
        private void openShp() throws OpenException{
159
                try {
160
                        fin = new FileInputStream(this.getFile());
161

    
162

    
163
                        // Open the file and then get a channel from the stream
164
                        channel = fin.getChannel();
165

    
166
                        // long size = channel.size();
167

    
168
                        // Get the file's size and then map it into memory
169
                        // bb = channel.map(FileChannel.MapMode.READ_ONLY, 0, size);
170
                        bb = new BigByteBuffer2(channel, FileChannel.MapMode.READ_ONLY);
171
                        finShx = new FileInputStream(this.fileShx);
172

    
173
                        // Open the file and then get a channel from the stream
174
                        channelShx = finShx.getChannel();
175

    
176
//                        long sizeShx = channelShx.size();
177

    
178
                        // Get the file's size and then map it into memory
179
                        // bb = channel.map(FileChannel.MapMode.READ_ONLY, 0, size);
180
                        // bbShx = channelShx.map(FileChannel.MapMode.READ_ONLY, 0, sizeShx);
181
                        bbShx = new BigByteBuffer2(channelShx, FileChannel.MapMode.READ_ONLY);
182
                        bbShx.order(ByteOrder.BIG_ENDIAN);
183

    
184

    
185
//                        create a new header.
186
                        ShapeFileHeader2 myHeader = new ShapeFileHeader2();
187

    
188
                        bb.position(0);
189

    
190
                        // read the header
191
                        myHeader.readHeader(bb);
192

    
193
                        extent = new Extent(myHeader.myXmin, myHeader.myYmin,myHeader.myXmax,myHeader.myYmax);
194
//                        extent = new Rectangle2D.Double(myHeader.myXmin, myHeader.myYmin,
195
//                        myHeader.myXmax - myHeader.myXmin,
196
//                        myHeader.myYmax - myHeader.myYmin);
197

    
198
                        type = myHeader.myShapeType;
199

    
200
                        double x = myHeader.myXmin;
201
                        double y = myHeader.myYmin;
202
                        double w = myHeader.myXmax - myHeader.myXmin;
203
                        double h = myHeader.myYmax - myHeader.myYmin;
204

    
205
                        if (w == 0) {
206
                                x -= 0.1;
207
                                w = 0.2;
208
                        }
209

    
210
                        if (h == 0) {
211
                                y -= 0.1;
212
                                h = 0.2;
213
                        }
214

    
215

    
216
                } catch (FileNotFoundException e) {
217
                        throw new OpenException(this.description(),e);
218
                } catch (IOException e) {
219
                        throw new OpenException(this.description(),e);
220
                }
221

    
222

    
223
        }
224

    
225
        protected IExtent getFullExtent() throws ReadException{
226
                this.checkOpen();
227
                return this.extent;
228
        }
229

    
230
        protected boolean isEditable(){
231
                return this.getFile().canWrite() && this.fileShx.canWrite();
232
        }
233

    
234
        protected int getGeometryType() throws ReadException {
235
                this.checkOpen();
236
                int auxType = 0;
237

    
238
                switch (type) {
239
                case (SHP.POINT2D):
240
                case (SHP.POINT3D):
241
                        auxType = auxType | FShape.POINT;
242

    
243
                break;
244

    
245
                case (SHP.POLYLINE2D):
246
                case (SHP.POLYLINE3D):
247
                        auxType = auxType | FShape.LINE;
248

    
249
                break;
250

    
251
                case (SHP.POLYGON2D):
252
                case (SHP.POLYGON3D):
253
                        auxType = auxType | FShape.POLYGON;
254

    
255
                break;
256
                case (SHP.MULTIPOINT2D):
257
                case (SHP.MULTIPOINT3D):
258
                        auxType = auxType | FShape.MULTIPOINT;
259

    
260
                break;
261
                }
262

    
263
                return auxType;
264
        }
265

    
266
        protected synchronized IGeometry getGeometry(long position) throws ReadException {
267
                this.checkOpen();
268
                Point2D p = new Point2D.Double();
269
                int numParts;
270
                int numPoints;
271
                int i;
272
                int j;
273
                int shapeType;
274

    
275
                bb.position(getPositionForRecord(position));
276
                bb.order(ByteOrder.LITTLE_ENDIAN);
277

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

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

    
290
                return ShapeFactory.createPoint2D(p.getX(), p.getY());
291

    
292
                case (SHP.POLYLINE2D):
293

    
294
                        bb.position(bb.position() + 32);
295
                numParts = bb.getInt();
296
                numPoints = bb.getInt();
297

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

    
303
                int[] tempParts = new int[numParts];
304

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

    
309
                j = 0;
310

    
311
                for (i = 0; i < numPoints; i++) {
312
                        p = readPoint(bb);
313

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

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

    
325
                return ShapeFactory.createPolyline2D(elShape);
326

    
327
                case (SHP.POLYGON2D):
328

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

    
337
                numPoints = bb.getInt();
338

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

    
343
                tempParts = new int[numParts];
344

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

    
349
                j = 0;
350

    
351
                for (i = 0; i < numPoints; i++) {
352
                        p = readPoint(bb);
353

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

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

    
369
                return ShapeFactory.createPolygon2D(elShape);
370

    
371
                case (SHP.POINT3D):
372

    
373
                        double x = bb.getDouble();
374
                double y = bb.getDouble();
375
                double z = bb.getDouble();
376

    
377
                return ShapeFactory.createPoint3D(x, y, z);
378

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

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

    
390
                j = 0;
391

    
392
                for (i = 0; i < numPoints; i++) {
393
                        p = readPoint(bb);
394

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

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

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

    
410
                double[] pZ = new double[numPoints];
411

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

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

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

    
428
                j = 0;
429

    
430
                for (i = 0; i < numPoints; i++) {
431
                        p = readPoint(bb);
432

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

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

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

    
452
                double[] poZ = new double[numPoints];
453

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

    
458
                return ShapeFactory.createPolygon3D(elShape, poZ);
459

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

    
464
                double[] tempX = new double[numPoints];
465
                double[] tempY = new double[numPoints];
466

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

    
472
                return ShapeFactory.createMultipoint2D(tempX, tempY);
473

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

    
478
                double[] temX = new double[numPoints];
479
                double[] temY = new double[numPoints];
480
                double[] temZ = new double[numPoints];
481

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

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

    
494
                return null;
495

    
496

    
497
        }
498

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

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

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

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

    
528
                return tempPoint;
529
        }
530

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

    
545
                double x2 = in.getDouble();
546

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

    
552
                double y2 = in.getDouble();
553

    
554
                if (y2-y == 0) {
555
                        y2 = 0.2;
556
                        y -= 0.1;
557
                }
558
                IExtent tempRect = new Extent(x,y,x2,y2);
559
                return tempRect;
560
        }
561

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

    
574
                int tipoShape = bb.getInt();
575

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

    
581
//                }
582

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

    
593
                break;
594

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

    
602
                        // BoundingBox
603
                        BoundingBox = readRectangle(bb);
604

    
605
                break;
606
                }
607

    
608
                return BoundingBox;
609
        }
610

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

    
619
}
620