Statistics
| Revision:

svn-gvsig-desktop / branches / v10 / libraries / libLidar / src / com / dielmo / lidar / LASHeader_V11.java @ 25423

History | View | Annotate | Download (13.8 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.lidar;
51

    
52
import java.io.File;
53
import java.io.FileInputStream;
54
import java.io.FileNotFoundException;
55
import java.io.FileOutputStream;
56
import java.io.IOException;
57
import java.io.InputStream;
58
import java.nio.ByteBuffer;
59
import java.nio.channels.FileChannel;
60

    
61
import javax.swing.JOptionPane;
62

    
63
import com.hardcode.gdbms.driver.DriverUtilities;
64

    
65

    
66
public class LASHeader_V11 extends LASHeader_1X{        
67
        
68
        /**
69
         * vector of variable length record header
70
         */
71
        private LASVariableLengthRecord_V11[] VLR;
72
        
73
        /**
74
         * Flight line number; unsigned short
75
         */
76
        private int fileSourceID;
77
        
78
        /**
79
         * reserved, must be 0; unsigned short
80
         */
81
        private int reserved;
82
        
83
        /**
84
         * Default constructor, without arguments.
85
         * Initializes all components to zero.
86
         */ 
87
        public LASHeader_V11(File file)        {
88
                super(file);
89
                
90
                fileSourceID = 0;
91
                reserved = 0;
92
        }
93
        
94
        // GET METHOD
95
        /**
96
         * Return file source ID
97
         * 
98
         * @return file Source ID if version is LAS_1.1 else return -1
99
         */
100
        public int getFileSourceID() {
101
                return fileSourceID;
102
        }
103
        
104
        /**
105
         * Return file source ID
106
         * 
107
         * @return file Source ID if version is LAS_1.1 else return -1
108
         */
109
        public int getReserved() {
110
                return reserved;
111
        }
112
        
113
        
114
        // SET METHOD
115
        /**
116
         * set new file source ID
117
         * 
118
         * @param f new file source ID
119
         */
120
        public void setFileSourceID(int f) {
121
                
122
                if(f>=0 && f <= UNSIGNED_SHORT_MAX)
123
                        fileSourceID = f;
124
        }
125
        
126
        /**
127
         * set new reserved value
128
         * 
129
         * @param r new reserved value
130
         */
131
        public void setReserved(int r) {
132
                if(r>=0 && r <= UNSIGNED_SHORT_MAX)
133
                        reserved = r;
134
                else
135
                        reserved = 0;
136
        }
137
        
138
        /**
139
         * Read the header of LAS file
140
         * 
141
         * @param input input file to read
142
         * @return true if success else return false 
143
         */
144
        public boolean readLidarHeader() {
145
                
146
                int offset = 0,numRead = 0, i;
147
                long j;
148
                byte[] cabecera = new byte[227];
149
                File file = m_Fich;
150
                InputStream input; 
151
                
152
                //leemos la cabecera
153
              try {
154
                     
155
                    input = new FileInputStream(file);
156
                      
157
                        while (offset < 227 && (numRead = input.read(cabecera, offset, cabecera.length-offset) ) >= 0) {
158
                             offset += numRead;
159
                        }
160
                        
161
                    if (offset < cabecera.length) {
162
                            JOptionPane.showMessageDialog(null, "Bad input format");
163
                            return false;
164
                        }
165
                    
166
                    // set parameters
167
                    for(i=0;i<4;i++)
168
                                fileSignature[i] = (char)(cabecera[i] & 0xFF);
169
                        
170
                        setFileSourceID(ByteUtilities.arr2Unsignedshort(cabecera, 4));
171
                        setReserved(ByteUtilities.arr2Unsignedshort(cabecera, 6));
172
                        setGUID1(ByteUtilities.arr2UnsignedInt(cabecera, 8));
173
                        setGUID2(ByteUtilities.arr2Unsignedshort(cabecera, 12));
174
                        setGUID3(ByteUtilities.arr2Unsignedshort(cabecera, 14));
175
                        
176
                        for(i=0;i<8;i++)
177
                                GUID4[i] = (char)(cabecera[i+16] & 0xFF);
178
                        
179
                        setVersionMayor((char)(cabecera[24] & 0xFF));
180
                        setVersionMinor((char)(cabecera[25] & 0xFF));
181
                        
182
                        for(i=0;i<32;i++)
183
                                systemIDentifier[i] = (char)(cabecera[i+26] & 0xFF);
184
                        for(i=0;i<32;i++)
185
                                generatingSoftware[i] = (char)(cabecera[i+58] & 0xFF);
186
                        
187
                        setDay(ByteUtilities.arr2Unsignedshort(cabecera, 90));
188
                        setYear(ByteUtilities.arr2Unsignedshort(cabecera, 92));                
189
                        
190
                        setHdrSize(ByteUtilities.arr2Unsignedshort(cabecera, 94));
191
                        if (getHdrSize() < 227) {
192
                            JOptionPane.showMessageDialog(null, "Bad input format");
193
                            return false;
194
                        }                
195
                        
196
                        setOffsetData(ByteUtilities.arr2UnsignedInt(cabecera, 96));
197
                        setNumVarLengthRecord(ByteUtilities.arr2UnsignedInt(cabecera, 100));                
198
                        SetPointDataFormatID((char)(cabecera[104] & 0xFF));
199
                        SetPointDataRecordLength(ByteUtilities.arr2Unsignedshort(cabecera, 105));                
200
                        setNumPointsRecord(ByteUtilities.arr2UnsignedInt(cabecera, 107));
201
                        numPointsByReturn[0] = ByteUtilities.arr2UnsignedInt(cabecera, 111);
202
                        numPointsByReturn[1] = ByteUtilities.arr2UnsignedInt(cabecera, 115);
203
                        numPointsByReturn[2] = ByteUtilities.arr2UnsignedInt(cabecera, 119);
204
                        numPointsByReturn[3] = ByteUtilities.arr2UnsignedInt(cabecera, 123);
205
                        numPointsByReturn[4] = ByteUtilities.arr2UnsignedInt(cabecera, 127);
206
                        setXScale(ByteUtilities.arr2Double(cabecera, 131));
207
                        setYScale(ByteUtilities.arr2Double(cabecera, 139));
208
                        setZScale(ByteUtilities.arr2Double(cabecera, 147));
209
                        setXOffset(ByteUtilities.arr2Double(cabecera, 155));
210
                        setYOffset(ByteUtilities.arr2Double(cabecera, 163));
211
                        setZOffset(ByteUtilities.arr2Double(cabecera, 171));
212
                        setMaxX(ByteUtilities.arr2Double(cabecera, 179));
213
                        setMinX(ByteUtilities.arr2Double(cabecera, 187));
214
                        setMaxY(ByteUtilities.arr2Double(cabecera, 195));
215
                        setMinY(ByteUtilities.arr2Double(cabecera, 203));
216
                        setMaxZ(ByteUtilities.arr2Double(cabecera, 211));
217
                        setMinZ(ByteUtilities.arr2Double(cabecera, 219));
218
                        
219
                        if(getHdrSize() > 227)
220
                                input.skip(getHdrSize()-227);
221
                        
222
                        VLR = new LASVariableLengthRecord_V11[(int) getNumVarLengthRecord()];
223
                        
224
                        // read Variable lengh record
225
                    for(j=0;j<getNumVarLengthRecord();j++) {
226
                            
227
                            VLR[(int) j] = new LASVariableLengthRecord_V11();
228
                            VLR[(int) j].readVarLegthRecord(input);
229
                    }
230
                    input.close();
231
                    
232
                } catch (IOException e) {
233
                        // TODO Auto-generated catch block
234
                        e.printStackTrace();
235
                }
236

    
237
                return true;
238
        }
239
        
240
        public LASVariableLengthRecord_1X[] getLASHeaderVLR() {
241
                return VLR;
242
        }
243
        
244
        public LASVariableLengthRecord_1X getLASHeaderVLRByIndex(long i) {
245
                
246
                if(i<getNumVarLengthRecord())
247
                        return VLR[(int) i];
248
                
249
                return null;
250
        }
251
        
252
        public int getVersion() {
253
                
254
                if(getPointDataFormatID()==0)
255
                        return LidarHeader.LAS11F0;
256
                else if(getPointDataFormatID()==1)
257
                        return LidarHeader.LAS11F1;
258
                else 
259
                        return LidarHeader.UNEXPECTED;
260
        }
261
        
262
        /**
263
         * set new Variable length record
264
         * 
265
         * @param l new vector of Variable length record
266
         */ 
267
        public void setLASHeaderVLR(LASVariableLengthRecord_1X[] v) {
268
                
269
                int i;
270
                long countBytes=0;
271
                long oldOffsetData=0;
272
                
273
                // new VLR size
274
                VLR = new LASVariableLengthRecord_V11[v.length];
275
                for(i=0;i<v.length;i++){
276
                        
277
                        // cuentaBytes lleva la cuenta de los bytes que consumen cada una
278
                        // de las variable lengthRecord. Esto es el numero de bytes que
279
                        // a continuacion de esta vienen mas los 54 bytes de la cabecera de la variable en si
280
                        LASVariableLengthRecord_V11 vlrAux = (LASVariableLengthRecord_V11) v[i];
281
                        countBytes += vlrAux.getRecordLengthAfterHeader()+54;
282
                        VLR[i] = vlrAux;
283
                }
284
                
285
                // change number of VLR in LAS HEADER
286
                setNumVarLengthRecord(v.length);
287
                oldOffsetData = getOffsetData();
288
                
289
                // countBytes is number of bytes of all variable length record
290
                if(countBytes> (oldOffsetData - getHdrSize()) ){
291
                        
292
                        // OffsetData change 
293
                        setOffsetData(countBytes+getHdrSize());
294
                        
295
                        // temporal folder to make the new las file. This is because the Variable Length Records overlaps the data points
296
                        String tempDirectoryPath = System.getProperty("java.io.tmpdir");
297
                        
298
                        // escribe en un temporal el fichero.
299
                        int aux = (int)(Math.random() * 1000);
300
                        File fTemp = new File(tempDirectoryPath + "/tmpLidar" + aux + ".las");
301
                        try {
302
                                
303
                                FileChannel fcoutLidar = new FileOutputStream(fTemp).getChannel();
304
                                FileChannel fcinLidar = new FileInputStream(m_Fich).getChannel();
305
                                
306
                                // Write the new LAS header adn VLR.
307
                                ByteBuffer bb;
308
                                bb = ByteBuffer.allocateDirect((int) (countBytes+getHdrSize()));
309
                                writeLidarHeader(bb);
310
                                bb.flip();
311

    
312
                                while (bb.remaining() > 0)
313
                                        fcoutLidar.write(bb);
314

    
315
                                bb.flip().limit(bb.capacity());
316
                                
317
                                
318
                                long sizeOfFile = oldOffsetData + getNumPointsRecord()*getPointDataRecordLength();
319
                                long startToWrite = oldOffsetData;
320
                                
321
                                // write data points
322
                                while(startToWrite < sizeOfFile){
323
                                        
324
                                        startToWrite += fcinLidar.read(bb, startToWrite);
325
                                        bb.flip();
326

    
327
                                        while (bb.remaining() > 0)
328
                                                fcoutLidar.write(bb);
329

    
330
                                        bb.flip().limit(bb.capacity());
331
                                }
332
                                fcoutLidar.close();
333
                                fcinLidar.close();
334
                                
335
                                FileChannel fcinNewLidar = new FileInputStream(fTemp).getChannel();
336
                                FileChannel fcoutNewLidar = new FileOutputStream(m_Fich).getChannel();
337
                                // copy temporal file to the original file
338
                                DriverUtilities.copy(fcinNewLidar, fcoutNewLidar);
339
                                
340
                                
341
                        } catch (FileNotFoundException e) {
342
                                // TODO Auto-generated catch block
343
                                e.printStackTrace();
344
                        } catch (IOException e) {
345
                                // TODO Auto-generated catch block
346
                                e.printStackTrace();
347
                        }
348
                        
349
                }
350
                
351
        }
352

    
353
        public boolean writeVarLegthRecord(ByteBuffer bb) {
354
                // TODO Auto-generated method stub
355
                return false;
356
        }
357

    
358
        public boolean writeVarLegthRecordHeader(ByteBuffer input) {
359
                // TODO Auto-generated method stub
360
                return false;
361
        }
362
        
363

    
364
        public boolean writeLidarHeader(ByteBuffer bb) {
365
                
366
                byte[] hdr = new byte[227];
367
                int i, index;        
368
            
369
                // fileSignature bytes 0-4
370
            for(i=0;i<4;i++)
371
                        hdr[i] = ((byte)(fileSignature[i] & 0XFF));
372

    
373
            // reserved bytes 4-6
374
            ByteUtilities.unsignedShort2Arr(getFileSourceID(), hdr, 4);
375
                
376
                // reserved bytes 6-8
377
            ByteUtilities.unsignedShort2Arr(getReserved(), hdr, 6);
378
                
379
         // GUID1 bytes 8-12
380
            ByteUtilities.unsignedInt2Arr(getGUID1(), hdr, 8);
381
                
382
                // GUID2 bytes 12-14
383
            ByteUtilities.unsignedShort2Arr(getGUID2(), hdr, 12);
384

    
385
                // GUID3 bytes 14-16
386
            ByteUtilities.unsignedShort2Arr(getGUID3(), hdr, 14);
387
                
388
                // GUID4 bytes 16-24
389
                i=0;
390
                for(index=16;index<24;index++) {
391
                        
392
                        hdr[index] = (byte)(GUID4[i] & 0xFF);
393
                        i++;
394
                }
395
                
396
                // Version, byte 24 and 25
397
                hdr[24] = (byte)(getVersionMayor() & 0xFF);
398
                hdr[25] = (byte)(getVersionMinor() & 0xFF);
399
                
400
                // Sytem Identifier bytes 26-58
401
                i=0;
402
                for(index=26;index<58;index++) {
403
                        
404
                        hdr[index] = (byte)(systemIDentifier[i] & 0xFF);
405
                        i++;
406
                }
407
                
408
                // Generating Software bytes 58-90
409
                i=0;
410
                for(index=58;index<90;index++) {
411
                        
412
                        hdr[index] = (byte)(generatingSoftware[i] & 0xFF);
413
                        i++;
414
                }
415
                
416
                // day bytes 90-92
417
                ByteUtilities.unsignedShort2Arr(getDay(), hdr, 90);
418
                
419
                // year bytes 92-94
420
                ByteUtilities.unsignedShort2Arr(getYear(), hdr, 92);
421
                
422
                // hdrSize bytes 94-96
423
                ByteUtilities.int2Arr(getHdrSize(), hdr, 94);
424
                
425
                if (getHdrSize() < 227) {
426
                    JOptionPane.showMessageDialog(null, "bad input format");
427
                    return false;
428
                }
429
                
430
                // offsetData bytes 96-100
431
                ByteUtilities.unsignedInt2Arr(getOffsetData(), hdr, 96);
432
                
433
                // numVarLengthRecord bytes 100-104
434
                ByteUtilities.unsignedInt2Arr(getNumVarLengthRecord(), hdr, 100);
435
                
436
                // pointDataFormatID bytes 104
437
                hdr[104] = (byte)(getPointDataFormatID() & 0xFF);
438
                
439
                // pointDataRecordLength bytes 105-107
440
                ByteUtilities.unsignedShort2Arr(getPointDataRecordLength(), hdr, 105);
441
        
442
                // numPointsRecord bytes 107-111
443
                ByteUtilities.unsignedInt2Arr(getNumPointsRecord(), hdr, 107);
444
                
445
                // numPointsByReturn[0] bytes 111-115
446
                ByteUtilities.unsignedInt2Arr(getNumPointsByReturnIndex(0), hdr, 111);
447
                
448
                // numPointsByReturn[1] bytes 115-119
449
                ByteUtilities.unsignedInt2Arr(getNumPointsByReturnIndex(1), hdr, 115);
450
                
451
                // numPointsByReturn[2] bytes 119-123
452
                ByteUtilities.unsignedInt2Arr(getNumPointsByReturnIndex(2), hdr, 119);
453
                
454
                // numPointsByReturn[3] bytes 123-127
455
                ByteUtilities.unsignedInt2Arr(getNumPointsByReturnIndex(3), hdr, 123);
456
                
457
                // numPointsByReturn[4] bytes 127-131
458
                ByteUtilities.unsignedInt2Arr(getNumPointsByReturnIndex(4), hdr, 127);
459
                
460
                // xScale bytes 131-139
461
                ByteUtilities.double2Arr(getXScale(), hdr, 131);
462
                
463
                // yScale bytes 139-147
464
                ByteUtilities.double2Arr(getYScale(), hdr, 139);
465
                
466
                // zScale bytes 147-155
467
                ByteUtilities.double2Arr(getZScale(), hdr, 147);
468
                
469
                // xOffset bytes 155-163
470
                ByteUtilities.double2Arr(getXOffset(), hdr, 155);
471
                
472
                // yOffset bytes 163-171
473
                ByteUtilities.double2Arr(getYOffset(), hdr, 163);
474
                
475
                // zOffset bytes 171-179
476
                ByteUtilities.double2Arr(getZOffset(), hdr, 171);
477
                
478
                // maxX bytes 179-187
479
                ByteUtilities.double2Arr(getMaxX(), hdr, 179);
480
                
481
                // minX bytes 187-195
482
                ByteUtilities.double2Arr(getMinX(), hdr, 187);
483
                
484
                // maxY bytes 195-203
485
                ByteUtilities.double2Arr(getMaxY(), hdr, 195);
486
                
487
                // minY bytes 203-211
488
                ByteUtilities.double2Arr(getMinY(), hdr, 203);
489

    
490
                // maxZ bytes 211-219
491
                ByteUtilities.double2Arr(getMaxZ(), hdr, 211);
492

    
493
                // minZ bytes 219-227
494
                ByteUtilities.double2Arr(getMinZ(), hdr, 219);
495
                
496
                bb.put(hdr);
497

    
498
                // write VARIABLE LENGTH RECORD
499
                for(int j = 0;j<getNumVarLengthRecord();j++) {
500
                        // escribimos la cabecera de la Variable lengh record
501
                        VLR[(int) j].writeVarLegthRecord(bb);                    
502
                }
503
                
504
                return true;
505
        }
506
}