Statistics
| Revision:

svn-gvsig-desktop / branches / v10 / extensions / DielmoOpenLidar / src / com / dielmo / gvsig / lidar / drivers / LiDARWriter.java @ 25419

History | View | Annotate | Download (8.89 KB)

1
/* DielmoOpenLiDAR
2
 *
3
 * Copyright (C) 2008 DIELMO 3D S.L. (DIELMO) and Infrastructures  
4
 * and Transports Department 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
 * For more information, contact:
22
 *
23
 * DIELMO 3D S.L.
24
 * Plaza Vicente Andr?s Estell?s 1 Bajo E
25
 * 46950 Xirivella, Valencia
26
 * SPAIN
27
 *   
28
 * +34 963137212
29
 * dielmo@dielmo.com
30
 * www.dielmo.com
31
 * 
32
 * or
33
 * 
34
 * Generalitat Valenciana
35
 * Conselleria d'Infraestructures i Transport
36
 * Av. Blasco Ib??ez, 50
37
 * 46010 VALENCIA
38
 * SPAIN
39
 *
40
 * +34 963862235
41
 * gvsig@gva.es
42
 * www.gvsig.gva.es
43
 */
44

    
45
/*
46
 * AUTHORS (In addition to DIELMO and CIT):
47
 *  
48
 */
49

    
50
package com.dielmo.gvsig.lidar.drivers;
51

    
52
import java.awt.geom.Rectangle2D;
53
import java.io.File;
54
import java.io.IOException;
55
import java.io.RandomAccessFile;
56
import java.nio.ByteBuffer;
57
import java.nio.channels.FileChannel;
58
import java.nio.channels.WritableByteChannel;
59
import java.sql.Types;
60

    
61
import com.dielmo.lidar.LidarHeader;
62
import com.dielmo.lidar.LidarPoint;
63
import com.hardcode.gdbms.engine.values.DoubleValue;
64
import com.hardcode.gdbms.engine.values.Value;
65
import com.hardcode.gdbms.engine.values.ValueFactory;
66
import com.iver.cit.gvsig.fmap.core.FShape;
67
import com.iver.cit.gvsig.fmap.core.IFeature;
68
import com.iver.cit.gvsig.fmap.core.IGeometry;
69
import com.iver.cit.gvsig.fmap.drivers.FieldDescription;
70
import com.iver.cit.gvsig.fmap.edition.EditionException;
71
import com.iver.cit.gvsig.fmap.edition.IRowEdited;
72
import com.iver.cit.gvsig.fmap.edition.ISpatialWriter;
73
import com.iver.cit.gvsig.fmap.edition.writers.AbstractWriter;
74

    
75
/**
76
 * Writer of LiDAR.
77
 * 
78
 * @author Oscar Garcia
79
 */
80
public class LiDARWriter extends AbstractWriter implements ISpatialWriter {
81

    
82
        private String lidarPath;
83
        private File file;
84
        private LidarHeader hdr;
85
        private LidarPoint lp;
86
        private int numRows;
87
        private ByteBuffer bb = null;
88
        private FileChannel lidarChannel;
89
        private Rectangle2D fullExtent;
90
        
91
        public LiDARWriter() {
92
                super();
93
        }
94

    
95
        /**
96
         * La tabla Lidar no se deve alterar, por lo que
97
         * Esta funcion devolvera false siempre.
98
         */
99
        public boolean canAlterTable() {
100
                return false;
101
        }
102

    
103
        /**
104
         * Informa de si el fichero se puede editar o no
105
         */
106
        public boolean canSaveEdits() {
107
                return file.canWrite();
108
        }
109

    
110
        /**
111
         * Indica que atributos se pueden cambiar.
112
         */
113
        public boolean canWriteAttribute(int sqlType) {
114
                switch (sqlType) {
115
                        case Types.DOUBLE:
116
                        case Types.FLOAT:
117
                        case Types.INTEGER:
118
                        case Types.BIGINT:
119
                                return true;
120
                        case Types.DATE:
121
                                return false;
122
                        case Types.BIT:
123
                        case Types.BOOLEAN:
124
                                return false;
125
                        case Types.VARCHAR:
126
                        case Types.CHAR:
127
                        case Types.LONGVARCHAR:
128
                                return false; 
129
                }
130
                return false;
131
        }
132

    
133
        /**
134
         * Seteamos el fichero sobre el que trabajaremos en la escritura.
135
         * @param f fichero de trabajo.
136
         */
137
        public void setFile(File f) {
138
                
139
                try {
140
                        lidarPath = f.getAbsolutePath();
141
                        lidarChannel = (FileChannel) getWriteChannel(lidarPath);
142
                        file = f;
143
                } catch (IOException e) {
144
                        // TODO Auto-generated catch block
145
                        e.printStackTrace();
146
                }
147
        }
148
        
149
        /**
150
         * Seteamos las caracteristicas del Lidar.
151
         * @param h Cabecera lidar.
152
         * @param p Punto lidar.
153
         */
154
        public void setHeaderAndPoint(LidarHeader h, LidarPoint p) {
155
                hdr = h;
156
                lp = p;
157
        }
158
        
159
        /**
160
         * Obtiene el canal de escritura.
161
         * 
162
         * @param path ruta del fichero en el que queremos obtener el canal de escritura.
163
         * @return Canal de escritura del fichero dado.
164
         * @throws IOException
165
         */
166
        private WritableByteChannel getWriteChannel(String path)
167
        throws IOException {
168
                
169
                // FileChannel de escritura.
170
                WritableByteChannel channel;
171

    
172
                File f = new File(path);
173
                
174
                if (!f.exists()) {
175
                        System.out.println("Creando fichero " + f.getAbsolutePath());
176
                
177
                        // crear el fichero si no existia.
178
                        if (!f.createNewFile()) {
179
                                System.err.print("Error al crear el fichero " +
180
                                        f.getAbsolutePath());
181
                                throw new IOException("Cannot create file " + f);
182
                        }
183
                }
184
                
185
                // Obtenemos un canal de lectura escritura de acceso aleatorio.
186
                RandomAccessFile raf = new RandomAccessFile(f, "rw");
187
                channel = raf.getChannel();
188
                
189
                return channel;
190
        }
191

    
192
        /**
193
         * devuelve true si puede escribir la geometria dada.
194
         * Este driver solo devolvera true para las geomerias de punto.
195
         */
196
        public boolean canWriteGeometry(int gvSIGgeometryType) {
197
                switch (gvSIGgeometryType) {
198
                        case FShape.POINT:
199
                                return true;
200
                        case FShape.MULTIPOINT:
201
                                return false;
202
                }
203
                return false;
204
        }
205

    
206
        /**
207
         * Make sure our buffer is of size.
208
         *
209
         * @param size, size that buffer must contain
210
         */
211
        private void checkShapeBuffer(int size) {
212
                if (bb.capacity() < size) {
213
                        bb = ByteBuffer.allocateDirect(size);
214
                }
215
        }
216
        
217
        /**
218
         * Drain internal buffers into underlying channels.
219
         *
220
         * @throws IOException DOCUMENT ME!
221
         */
222
        private void drain() throws IOException {
223
                bb.flip();
224

    
225
                while (bb.remaining() > 0)
226
                        lidarChannel.write(bb);
227

    
228
                bb.flip().limit(bb.capacity());
229
        }
230
        
231
        /**
232
         * DOCUMENT ME!
233
         */
234
        private void allocateBuffer() {
235
                bb = ByteBuffer.allocateDirect(16 * 1024);
236
        }
237
        
238
        /**
239
         * Close the underlying Channels.
240
         *
241
         * @throws IOException DOCUMENT ME!
242
         */
243
        public void close() throws IOException {
244
                lidarChannel.close();
245
                lidarChannel = null;
246
                bb = null;
247
        }
248
        
249
        // reservar bytes para la cabecera
250
        public void preProcess() throws EditionException {
251
                
252
                // Por ahora solo escribimos los primeros bytes
253
                // de las cabeceras. Luego en el postprocess los escribiremos
254
                // correctamente, con el numero de
255
                // registros que tocan.
256
                try {
257
                        
258
                        numRows = 0;
259
                        if (bb == null) {
260
                                allocateBuffer();
261
                        }
262
                        
263
                        // Posicionamos al principio.
264
                        bb.position(0);
265
                        
266
                        checkShapeBuffer((int)hdr.getOffsetData());
267
                        byte b[] = new byte[(int) hdr.getOffsetData()];
268
                        bb.put(b);
269
                        lidarChannel.position(0);
270
                        //hdr.writeLidarHeader(bb);
271
                        fullExtent = null;
272
                        drain();
273

    
274
                        // seteamos la Z
275
                        hdr.setMaxZ(Double.MIN_VALUE);
276
                        hdr.setMinZ(Double.MAX_VALUE);
277
                        
278
                } catch (IOException e) {
279
                        // TODO Auto-generated catch block
280
                        e.printStackTrace();
281
                }                        
282
        }
283
        
284
        // cabecera
285
        public void postProcess() throws EditionException {
286
                
287
                if (bb == null) {
288
                        allocateBuffer();
289
                }
290

    
291
                // seteamos la cabecera
292
                hdr.setNumPointsRecord(numRows);
293
                hdr.setMaxX(fullExtent.getMaxX());
294
                hdr.setMaxY(fullExtent.getMaxY());
295
                hdr.setMinX(fullExtent.getMinX());
296
                hdr.setMinY(fullExtent.getMinY());
297
                
298
                try {
299
                        lidarChannel.position(0);
300
                        hdr.writeLidarHeader(bb);
301
                        
302
                        drain();
303
                        lidarChannel.close();
304
                        
305
                } catch (IOException e) {
306
                        // TODO Auto-generated catch block
307
                        e.printStackTrace();
308
                }
309
        }
310
        
311
        // datos
312
        public void process(IRowEdited row) throws EditionException {
313

    
314
                if(row.getStatus() == IRowEdited.STATUS_DELETED) {
315
                        return;
316
                }
317
                
318
                try {
319
                        
320
                        IFeature feat = (IFeature) row.getLinkedRow();
321
                        IGeometry theGeom = feat.getGeometry();
322
                        Value[] attrs = row.getAttributes();
323
                        
324
                        if (bb == null) {
325
                                allocateBuffer();
326
                                lidarChannel.position(0);
327
                        }
328
                        
329
                        // must allocate enough for point
330
                        checkShapeBuffer(lp.getSizeFormat());
331
                        
332
                        Rectangle2D boundsLidar = theGeom.getBounds2D();
333
                        // NOTA: estamo suponiendo que la posicion 0 y la 1 siempe tendra los valores de x e y de la geometria.
334
                        attrs[0]=ValueFactory.createValue(boundsLidar.getMinX());
335
                        attrs[1]=ValueFactory.createValue(boundsLidar.getMinY());
336
                        lp.setPoint(attrs, hdr);
337
                        lp.WritePoint(bb);
338
                        
339
                        // NOTA: estamos suponiendo que la columna dos del valor de la tabla es la Z.. OJO, cambiar mas adelante, a?adir un get indexByName o algo parecido
340
                        if(hdr.getMaxZ()<((DoubleValue)(attrs[2])).getValue() )
341
                                hdr.setMaxZ(((DoubleValue)(attrs[2])).getValue());
342
                        
343
                        if(hdr.getMinZ()>((DoubleValue)(attrs[2])).getValue() )
344
                                hdr.setMinZ(((DoubleValue)(attrs[2])).getValue());
345

    
346
                        if (fullExtent == null) {
347
                                fullExtent = boundsLidar;
348
                        } else {
349
                                
350
                                fullExtent.add(boundsLidar);
351
                        }
352
                        
353
                        drain();
354
                        numRows++;
355
                
356
                } catch (IOException e) {
357
                        // TODO Auto-generated catch block
358
                        e.printStackTrace();
359
                }
360
        }
361

    
362
        public String getName() {
363
                return "LiDAR Writer";
364
        }
365

    
366
}