Statistics
| Revision:

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

History | View | Annotate | Download (13.5 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

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

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

    
310
                                while (bb.remaining() > 0)
311
                                        fcoutLidar.write(bb);
312

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

    
325
                                        while (bb.remaining() > 0)
326
                                                fcoutLidar.write(bb);
327

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

    
351
        public boolean writeLidarHeader(ByteBuffer bb) {
352
                
353
                byte[] hdr = new byte[227];
354
                int i, index;        
355
            
356
                // fileSignature bytes 0-4
357
            for(i=0;i<4;i++)
358
                        hdr[i] = ((byte)(fileSignature[i] & 0XFF));
359

    
360
            // reserved bytes 4-6
361
            ByteUtilities.unsignedShort2Arr(getFileSourceID(), hdr, 4);
362
                
363
                // reserved bytes 6-8
364
            ByteUtilities.unsignedShort2Arr(getReserved(), hdr, 6);
365
                
366
         // GUID1 bytes 8-12
367
            ByteUtilities.unsignedInt2Arr(getGUID1(), hdr, 8);
368
                
369
                // GUID2 bytes 12-14
370
            ByteUtilities.unsignedShort2Arr(getGUID2(), hdr, 12);
371

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

    
477
                // maxZ bytes 211-219
478
                ByteUtilities.double2Arr(getMaxZ(), hdr, 211);
479

    
480
                // minZ bytes 219-227
481
                ByteUtilities.double2Arr(getMinZ(), hdr, 219);
482
                
483
                bb.put(hdr);
484

    
485
                // write VARIABLE LENGTH RECORD
486
                for(int j = 0;j<getNumVarLengthRecord();j++) {
487
                        // escribimos la cabecera de la Variable lengh record
488
                        VLR[(int) j].writeVarLegthRecord(bb);                    
489
                }
490
                
491
                return true;
492
        }
493
}