Statistics
| Revision:

root / branches / Mobile_Compatible_Hito_1 / libFMap / src-file / org / gvsig / data / datastores / vectorial / file / shp / utils / SHPFileWrite.java @ 21606

History | View | Annotate | Download (9.47 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2004 IVER T.I. 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
 *      www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   IVER T.I. S.A
34
 *   Salamanca 50
35
 *   46005 Valencia
36
 *   Spain
37
 *
38
 *   +34 963163400
39
 *   dac@iver.es
40
 */
41
package org.gvsig.data.datastores.vectorial.file.shp.utils;
42

    
43
import java.awt.geom.Rectangle2D;
44
import java.io.IOException;
45
import java.nio.ByteOrder;
46

    
47
import org.gvsig.data.exception.InitializeWriterException;
48
import org.gvsig.data.exception.WriteException;
49
import org.gvsig.datasources.common.IByteBuffer;
50
import org.gvsig.datasources.common.IRandomFileChannel;
51
import org.gvsig.datasources.impljme.Impl;
52

    
53
import es.prodevelop.gvsig.mobile.fmap.core.FShape;
54
import es.prodevelop.gvsig.mobile.fmap.core.IGeometry;
55
import es.prodevelop.gvsig.mobile.fmap.symbol.FConstant;
56

    
57
//import com.iver.cit.gvsig.fmap.core.FShape;
58
//import com.iver.cit.gvsig.fmap.core.IGeometry;
59
//import com.iver.cit.gvsig.fmap.core.v02.FConstant;
60
//import com.iver.cit.gvsig.fmap.drivers.shp.write.ShapefileException;
61

    
62

    
63

    
64
/**
65
 * DOCUMENT ME!
66
 *
67
 * @author Vicente Caballero Navarro
68
 */
69
public class SHPFileWrite {
70
        private SHPShape m_shape = null;
71
        private IByteBuffer m_bb = null;
72
        private IByteBuffer m_indexBuffer = null;
73
        private int m_pos = 0;
74
        private int m_offset;
75
        private int m_type;
76
        private int m_cnt;
77
        private IRandomFileChannel shpChannel;
78
        private IRandomFileChannel shxChannel;
79
//        private double flatness;
80

    
81
        /**
82
         * Crea un nuevo SHPFileWrite.
83
         *
84
         * @param shpChannel DOCUMENT ME!
85
         * @param shxChannel DOCUMENT ME!
86
         */
87
        public SHPFileWrite(IRandomFileChannel shpChannel, IRandomFileChannel shxChannel) {
88
                this.shpChannel = shpChannel;
89
                this.shxChannel = shxChannel;
90
        }
91

    
92
        /**
93
         * Make sure our buffer is of size.
94
         *
95
         * @param size DOCUMENT ME!
96
         */
97
        private void checkShapeBuffer(int size) {
98
                if (m_bb.capacity() < size) {
99
                        m_bb = Impl.allocateDirect(size);
100
                }
101
        }
102

    
103
        /**
104
         * Drain internal buffers into underlying channels.
105
         * @throws WriteException
106
         *
107
         * @throws IOException DOCUMENT ME!
108
         */
109
        private void drain() throws InitializeWriterException {
110
                m_bb.flip();
111
                m_indexBuffer.flip();
112
                try{
113
                while (m_bb.remaining() > 0)
114
                        shpChannel.write(m_bb);
115

    
116
                while (m_indexBuffer.remaining() > 0)
117
                        shxChannel.write(m_indexBuffer);
118
                }catch (IOException e) {
119
                        throw new InitializeWriterException("SHP File Write Drain",e);
120
                }
121
                m_bb.flip().limit(m_bb.capacity());
122
                m_indexBuffer.flip().limit(m_indexBuffer.capacity());
123
        }
124

    
125
        /**
126
         * DOCUMENT ME!
127
         */
128
        private void allocateBuffers() {
129
                m_bb = Impl.allocateDirect(16 * 1024);
130
                m_indexBuffer = Impl.allocateDirect(100);
131
        }
132

    
133
        /**
134
         * Close the underlying Channels.
135
         * @throws WriteException
136
         *
137
         * @throws IOException DOCUMENT ME!
138
         */
139
        public void close() throws InitializeWriterException {
140
                try {
141
                        shpChannel.close();
142
                        shxChannel.close();
143
                } catch (IOException e) {
144
                        throw new InitializeWriterException("SHP File Write Close",e);
145
                }
146
                shpChannel = null;
147
                shxChannel = null;
148
                m_shape = null;
149

    
150
//                if (m_indexBuffer instanceof IByteBuffer) {
151
//                        if (m_indexBuffer != null) {
152
//                                ///NIOUtilities.clean(m_indexBuffer);
153
//                        }
154
//                }
155
//
156
//                if (m_indexBuffer instanceof ByteBuffer) {
157
//                        if (m_indexBuffer != null) {
158
//                                ///NIOUtilities.clean(m_bb);
159
//                        }
160
//                }
161

    
162
                m_indexBuffer = null;
163
                m_bb = null;
164
        }
165

    
166
        /**
167
         * DOCUMENT ME!
168
         *
169
         * @param geometries DOCUMENT ME!
170
         * @param type DOCUMENT ME!
171
         * @throws WriteException
172
         *
173
         * @throws IOException DOCUMENT ME!
174
         * @throws ShapefileException DOCUMENT ME!
175
         */
176
        public void write(IGeometry[] geometries, int type) throws InitializeWriterException {
177
                m_shape = SHP.create(type);
178
//                m_shape.setFlatness(flatness);
179
                writeHeaders(geometries, type);
180

    
181
                m_pos = m_bb.position();
182

    
183
                for (int i = 0, ii = geometries.length; i < ii; i++) {
184
                        writeGeometry(geometries[i]);
185
                }
186

    
187
                close();
188
        }
189

    
190
        /**
191
         * DOCUMENT ME!
192
         *
193
         * @param geometries DOCUMENT ME!
194
         * @param type DOCUMENT ME!
195
         * @throws WriteException
196
         *
197
         * @throws IOException DOCUMENT ME!
198
         */
199
        private void writeHeaders(IGeometry[] geometries, int type) throws InitializeWriterException{
200
                int fileLength = 100;
201
                Rectangle2D extent = null;
202

    
203
                for (int i = geometries.length - 1; i >= 0; i--) {
204
                        IGeometry fgeometry = geometries[i];
205
                        m_shape.obtainsPoints(fgeometry);
206
                        int size = m_shape.getLength(fgeometry) + 8;
207
                        fileLength += size;
208

    
209
                        if (extent == null) {
210
                                extent = new Rectangle2D.Double(fgeometry.getBounds2D().getMinX(),
211
                                                fgeometry.getBounds2D().getMinY(),
212
                                                fgeometry.getBounds2D().getWidth(),
213
                                                fgeometry.getBounds2D().getHeight());
214
                        } else {
215
                                extent.add(fgeometry.getBounds2D());
216
                        }
217
                }
218

    
219
                writeHeaders(extent, type, geometries.length, fileLength);
220
        }
221

    
222
        /**
223
         * Writes shape header (100 bytes)
224
         *
225
         * @param bounds DOCUMENT ME!
226
         * @param type DOCUMENT ME!
227
         * @param numberOfGeometries DOCUMENT ME!
228
         * @param fileLength DOCUMENT ME!
229
         * @throws WriteException
230
         *
231
         * @throws IOException DOCUMENT ME!
232
         */
233
        public void writeHeaders(Rectangle2D bounds, int type,
234
                int numberOfGeometries, int fileLength) throws InitializeWriterException {
235
                /*try {
236
                   handler = type.getShapeHandler();
237
                   } catch (ShapefileException se) {
238
                     throw new RuntimeException("unexpected Exception",se);
239
                   }
240
                 */
241
                if (m_bb == null) {
242
                        allocateBuffers();
243
                }
244
                // Posicionamos al principio.
245
                m_bb.position(0);
246
                m_indexBuffer.position(0);
247

    
248
                ShapeFileHeader2 header = new ShapeFileHeader2();
249

    
250
                header.write(m_bb, type, numberOfGeometries, fileLength / 2,
251
                        bounds.getMinX(), bounds.getMinY(), bounds.getMaxX(),
252
                        bounds.getMaxY(), 0, 0, 0, 0);
253

    
254
                header.write(m_indexBuffer, type, numberOfGeometries,
255
                        50 + (4 * numberOfGeometries), bounds.getMinX(), bounds.getMinY(),
256
                        bounds.getMaxX(), bounds.getMaxY(), 0, 0, 0, 0);
257

    
258
                m_offset = 50;
259
                m_type = type;
260
                m_cnt = 0;
261

    
262
                try {
263
                        shpChannel.position(0);
264
                        shxChannel.position(0);
265
                } catch (IOException e) {
266
                        throw new InitializeWriterException("SHP File Write Headers",e);
267
                }
268
                drain();
269
        }
270
        public int writeIGeometry(IGeometry g) throws InitializeWriterException{
271
                int shapeType = getShapeType(g.getGeometryType());
272
                m_shape = SHP.create(shapeType);
273
//                m_shape.setFlatness(flatness);
274
                return writeGeometry(g);
275
        }
276

    
277
        /**
278
         * Writes a single Geometry.
279
         *
280
         * @param g
281
         * @return the position of buffer (after the last geometry, it will allow you to
282
         * write the file size in the header.
283
         * @throws WriteException
284
         * @throws IOException
285
         */
286
        public synchronized int writeGeometry(IGeometry g) throws InitializeWriterException{
287
                if (m_bb == null) {
288
                        allocateBuffers();
289
                        m_offset = 50;
290
                        m_cnt = 0;
291

    
292
                        try {
293
                                shpChannel.position(0);
294
                                shxChannel.position(0);
295
                        } catch (IOException e) {
296
                                throw new InitializeWriterException("SHP File Write",e);
297
                        }
298
                        // throw new IOException("Must write headers first");
299
                }
300

    
301
                m_pos = m_bb.position();
302
                m_shape.obtainsPoints(g);
303
                int length = m_shape.getLength(g);
304

    
305
                // must allocate enough for shape + header (2 ints)
306
                checkShapeBuffer(length + 8);
307

    
308
                length /= 2;
309

    
310
                m_bb.order(ByteOrder.BIG_ENDIAN);
311
                m_bb.putInt(++m_cnt);
312
                m_bb.putInt(length);
313
                m_bb.order(ByteOrder.LITTLE_ENDIAN);
314
                m_bb.putInt(m_shape.getShapeType());
315
                m_shape.write(m_bb, g);
316

    
317
                ///assert (length * 2 == (m_bb.position() - m_pos) - 8);
318
                m_pos = m_bb.position();
319

    
320
                // write to the shx
321
                m_indexBuffer.putInt(m_offset);
322
                m_indexBuffer.putInt(length);
323
                m_offset += (length + 4);
324
                drain();
325

    
326
                ///assert(m_bb.position() == 0);
327
                return m_pos; // Devolvemos hasta donde hemos escrito
328
        }
329

    
330
        /**
331
         * Returns a shapeType compatible with shapeFile constants from a gvSIG's IGeometry type
332
         * @param geometryType
333
         * @return a shapeType compatible with shapeFile constants from a gvSIG's IGeometry type
334
         */
335
        public int getShapeType(int geometryType) {
336
                if (geometryType>=FShape.Z){
337
                        switch (geometryType - FShape.Z) {
338
                        case (FShape.POINT):
339
                                return FConstant.SHAPE_TYPE_POINTZ;
340

    
341
                        case (FShape.LINE):
342
                                return FConstant.SHAPE_TYPE_POLYLINEZ;
343

    
344
                        case FShape.POLYGON:
345
                                return FConstant.SHAPE_TYPE_POLYGONZ;
346

    
347
                        case FShape.MULTIPOINT:
348
                                return FConstant.SHAPE_TYPE_MULTIPOINTZ; //TODO falta aclarar cosas aqu?.
349
                }
350

    
351
                }else{
352
                        switch (geometryType) {
353
                                case FShape.POINT:
354
                                        return FConstant.SHAPE_TYPE_POINT;
355

    
356
                                case FShape.LINE:
357
                                case FShape.ELLIPSE:
358
                                case FShape.CIRCLE:
359
                                case FShape.ARC:
360
                                        return FConstant.SHAPE_TYPE_POLYLINE;
361

    
362
                                case FShape.POLYGON:
363
                                        return FConstant.SHAPE_TYPE_POLYGON;
364

    
365
                                case FShape.MULTIPOINT:
366
                                        return FConstant.SHAPE_TYPE_MULTIPOINT; //TODO falta aclarar cosas aqu?.
367
                        }
368
                }
369
                        return FConstant.SHAPE_TYPE_NULL;
370
                }
371

    
372
//        public void setFlatness(double flatness) {
373
//                this.flatness=flatness;
374
//        }
375

    
376
}