Statistics
| Revision:

gvsig-projects-pool / org.gvsig.lidar.prov / org.gvsig.lidar.prov.jgrass / src / main / java / org / gvsig / lidar / prov / jgrasstools / JGrassLASWriter.java @ 281

History | View | Annotate | Download (10.5 KB)

1
package org.gvsig.lidar.prov.jgrasstools;
2

    
3
import java.io.File;
4
import java.util.Date;
5

    
6
import org.apache.commons.io.FileUtils;
7
import org.cresques.cts.ICRSFactory;
8
import org.cresques.cts.IProjection;
9
import org.gvsig.fmap.dal.exception.CloseException;
10
import org.gvsig.fmap.dal.exception.DataException;
11
import org.gvsig.fmap.dal.exception.OpenException;
12
import org.gvsig.fmap.dal.exception.WriteException;
13
import org.gvsig.fmap.dal.feature.Feature;
14
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
15
import org.gvsig.fmap.dal.feature.FeatureSet;
16
import org.gvsig.fmap.dal.feature.FeatureType;
17
import org.gvsig.fmap.geom.Geometry.TYPES;
18
import org.gvsig.fmap.geom.primitive.Envelope;
19
import org.gvsig.fmap.geom.primitive.Point;
20
import org.gvsig.lidar.prov.ConversionUtils;
21
import org.gvsig.lidar.prov.LASDataStoreParameters;
22
import org.gvsig.lidar.prov.LASDataStoreProvider;
23
import org.gvsig.tools.dispose.DisposableIterator;
24
import org.gvsig.tools.dispose.DisposeUtils;
25
import org.jgrasstools.gears.io.las.core.ALasWriter;
26
import org.jgrasstools.gears.io.las.core.LasRecord;
27
import org.jgrasstools.gears.io.las.core.liblas.LiblasWriter;
28
import org.jgrasstools.gears.io.las.core.v_1_0.LasWriter;
29
import org.slf4j.Logger;
30
import org.slf4j.LoggerFactory;
31

    
32
public class JGrassLASWriter {
33
        protected LASDataStoreParameters params;
34
        protected Envelope outEnvelope;
35
        protected FeatureType fType;
36
        private int geomIndex, colorIdx, classificationIdx, weektimeIdx, gpstimeIdx, intensityIdx, returnNumIdx, numberOfReturnsIdx;
37
        protected ALasWriter writer = null;
38
        protected LasRecord record = null;
39
        double[] scale = null;
40
        double[] offset = null;
41
        int pointFormat = -1;
42
        
43
        private static final Logger LOG = LoggerFactory.getLogger(JGrassLASWriter.class);
44
        
45
        public JGrassLASWriter(LASDataStoreParameters outParams, FeatureType featType, Envelope outEnvelope) throws DataException {
46
                this.params = outParams;
47
                this.outEnvelope = outEnvelope;
48
                this.fType = featType;
49
        }
50
        
51
        protected ALasWriter getWriter() throws CantCreateWriterException {
52
                if (writer==null) {
53

    
54
                        try{
55
                                if (ALasWriter.supportsNative()) {
56
                                        writer = new LiblasWriter(this.params.getFile(), null);
57
                                }
58
                                else {
59
                                        writer = new LasWriter(this.params.getFile(), null);
60
                                }
61
                        } catch (Exception exc) {
62
                                throw new CantCreateWriterException("Can't create LAS writer", exc, "Can't create LAS writer", -1);
63
                        }
64
                }
65
                return writer;
66
        }
67
        
68
        protected int getPointFormat() {
69
                if (this.pointFormat!=-1) {
70
                        return this.pointFormat;
71
                }
72

    
73
                boolean color = this.fType.getAttributeDescriptor(LASDataStoreProvider.COLOR_FIELD)!=null?true:false;
74
                boolean weekTime = this.fType.getAttributeDescriptor(LASDataStoreProvider.WEEKTIME_FIELD)!=null?true:false;
75
                boolean time = this.fType.getAttributeDescriptor(LASDataStoreProvider.TIME_FIELD)!=null?true:false;
76
                int pointFormat;
77
                if ( (time||weekTime) && color ) {
78
                        pointFormat = 3;
79
                }
80
                else if (color) {
81
                        pointFormat = 2;
82
                }
83
                else if (time||weekTime) {
84
                        pointFormat = 1;
85
                }
86
                else {
87
                        pointFormat = 0;
88
                }
89
                return pointFormat;
90
        }
91

    
92
    class CantCreateWriterException extends DataException {
93
                public CantCreateWriterException(String messageFormat,
94
                                Throwable cause, String messageKey, long code) {
95
                        super(messageFormat, cause, messageKey, code);
96
                }
97
    }
98
        
99
        public boolean open() throws DataException {
100
                record = new LasRecord();
101
        record.returnNumber = 1; //set record defaults
102
        record.numberOfReturns = 1;
103
        ALasWriter writer = getWriter();
104
        final FeatureAttributeDescriptor geomAttrib = fType.getDefaultGeometryAttribute();
105
        geomIndex = geomAttrib.getIndex();
106
        if (geomAttrib.getGeomType().getType()!=TYPES.POINT) {
107
                new CantCreateWriterException("LAS files can only store points", null, "LAS files can only store points", -1);
108
        }
109
        if (fType.getAttributeDescriptor(LASDataStoreProvider.COLOR_FIELD)!=null) {
110
                colorIdx = fType.getAttributeDescriptor(LASDataStoreProvider.COLOR_FIELD).getIndex();
111
        }
112
        else {
113
                colorIdx = -1;
114
        }
115
        if (fType.getAttributeDescriptor(LASDataStoreProvider.CLASS_FIELD)!=null) {
116
                classificationIdx = fType.getAttributeDescriptor(LASDataStoreProvider.CLASS_FIELD).getIndex();
117
        }
118
        else {
119
                classificationIdx = -1;
120
        }
121
        if (fType.getAttributeDescriptor(LASDataStoreProvider.WEEKTIME_FIELD)!=null) {
122
                weektimeIdx = fType.getAttributeDescriptor(LASDataStoreProvider.WEEKTIME_FIELD).getIndex();
123
        }
124
        else {
125
                weektimeIdx = -1;
126
        }
127
        if (fType.getAttributeDescriptor(LASDataStoreProvider.TIME_FIELD)!=null) {
128
                writer.setGpsTimeType(1);
129
                gpstimeIdx = fType.getAttributeDescriptor(LASDataStoreProvider.TIME_FIELD).getIndex();
130
        }
131
        else {
132
                gpstimeIdx = -1;
133
        }
134
        if (fType.getAttributeDescriptor(LASDataStoreProvider.INTENSITY_FIELD)!=null) {
135
                intensityIdx = fType.getAttributeDescriptor(LASDataStoreProvider.INTENSITY_FIELD).getIndex();
136
        }
137
        else {
138
                intensityIdx = -1;
139
        }
140
        if (fType.getAttributeDescriptor(LASDataStoreProvider.RETURNNUM_FIELD)!=null) {
141
                returnNumIdx = fType.getAttributeDescriptor(LASDataStoreProvider.RETURNNUM_FIELD).getIndex();
142
        }
143
        else {
144
                returnNumIdx = -1;
145
        }
146
        if (fType.getAttributeDescriptor(LASDataStoreProvider.NUMRETURNS_FIELD)!=null) {
147
                numberOfReturnsIdx = fType.getAttributeDescriptor(LASDataStoreProvider.NUMRETURNS_FIELD).getIndex();
148
        }
149
        else {
150
                numberOfReturnsIdx = -1;
151
        }
152
        writer.setPointFormat(getPointFormat());
153
        if (outEnvelope!=null) {
154
                writer.setBounds(this.outEnvelope.getMinimum(0), this.outEnvelope.getMaximum(0), this.outEnvelope.getMinimum(1), this.outEnvelope.getMaximum(1), this.outEnvelope.getMinimum(2), this.outEnvelope.getMaximum(2));
155
        }
156

    
157
        if (offset==null) {
158
                offset = new double[3];
159
                offset[0] = (this.outEnvelope.getMinimum(0) + this.outEnvelope.getMaximum(0))/2;
160
                offset[1] = (this.outEnvelope.getMinimum(1) + this.outEnvelope.getMaximum(1))/2;
161
                offset[2] = (this.outEnvelope.getMinimum(2) + this.outEnvelope.getMaximum(2))/2;
162
        }
163
        writer.setOffset(offset[0], offset[1], offset[2]);
164
        
165
        if (scale==null) {
166
                scale = new double[3];
167
                // scaleX
168
                scale[0] = calculateScale(this.outEnvelope.getMinimum(0), this.outEnvelope.getMaximum(0), offset[0]);
169
                // scaleY
170
                scale[1] = calculateScale(this.outEnvelope.getMinimum(1), this.outEnvelope.getMaximum(1), offset[1]);
171
                // scaleZ
172
                scale[2] = calculateScale(this.outEnvelope.getMinimum(2), this.outEnvelope.getMaximum(2), offset[2]);
173
        }
174
        writer.setScales(scale[0], scale[1], scale[2]);
175
        
176
        try {
177
                        writer.open();
178
                } catch (Exception e) {
179
                        throw new OpenException(null, e);
180
                }
181
                return true;
182
        }
183
        
184
        public void setOffset(double offsetX, double offsetY, double offsetZ) {
185
                if (offset==null) {
186
                        offset = new double[3];
187
                }
188
                offset[0] = offsetX;
189
                offset[1] = offsetY;
190
                offset[2] = offsetZ;
191
        }
192
        
193
        public void setScale(double scaleX, double scaleY, double scaleZ) {
194
                if (scale==null) {
195
                        scale = new double[3];
196
                }
197
                scale[0] = scaleX;
198
                scale[1] = scaleY;
199
                scale[2] = scaleZ;
200
        }
201
        
202
        /**
203
         * Calculates a reasonable scale for the provided min, max and offset
204
         * values
205
         * 
206
         * @param min minimum value in the range to store
207
         * @param max maximum value in the range to store
208
         * @param offset
209
         * 
210
         * @return
211
         */
212
        private double calculateScale(double min, double max, double offset) {
213
                double offsettedMin = min - offset;
214
                double offsettedMax = max - offset;
215
                
216
                int absMax = (int) Math.max(Math.abs(offsettedMin), Math.abs(offsettedMax));
217
                int numDigits = Integer.toString(absMax).length();
218
                int maxDigits = 9; // Java ints can safely store 9 digits
219
                int decimalDigits = (maxDigits - numDigits);
220
                if (decimalDigits < 0) {
221
                        decimalDigits = 0;
222
                }
223
                return Math.pow(10, -decimalDigits);
224
        }
225
        
226
        public void close() throws CloseException {
227
                try {
228
                        getWriter().close();
229
                        IProjection crs = this.params.getCRS();
230
                        File projFile = this.params.getPrj();
231
                        if (crs!=null && projFile!=null) {
232
                                savePrjFile(projFile, crs);
233
                        }
234
                } catch (Exception e) {
235
                        throw new CloseException(null, e);
236
                }
237
        }
238
        
239
    protected void savePrjFile(File prjFile, IProjection proj){
240
        try {
241
            String export = proj.export(ICRSFactory.FORMAT_WKT);
242
            if(export!=null){
243
                FileUtils.writeStringToFile(prjFile, export);
244
            }
245
        } catch (Exception e) {
246
                LOG.info("Can't write prj file '" + prjFile.getAbsolutePath() + "'.");
247
        }
248
    }
249
        
250
        public void write(Feature feature) throws WriteException {
251
                try {
252
                        Point point = (Point) feature.getGeometry(geomIndex);
253
                        record.x = point.getCoordinateAt(0);
254
                        record.y = point.getCoordinateAt(1);
255
                        record.z = point.getCoordinateAt(2);
256
                        if (colorIdx!=-1) {
257
                                int[] rgbArray = ConversionUtils.intToRgb(feature.getInt(colorIdx));
258
                                record.color[0] = (short) rgbArray[0];
259
                                record.color[1] = (short) rgbArray[1];
260
                                record.color[2] = (short) rgbArray[2];
261

    
262
                        }
263
                        if (classificationIdx!=-1) {
264
                                record.classification = feature.getByte(classificationIdx);
265
                        }
266
                        if (weektimeIdx!=-1) {
267
                                record.gpsTime = (double) feature.getLong(weektimeIdx);
268
                        }
269
                        else if (gpstimeIdx!=-1) {
270
                                Date d = feature.getDate(gpstimeIdx);
271
                                if (d!=null) {
272
                                        long unixTime = d.getTime();
273
                                        long las_time = unixTime - ConversionUtils.LAS_TIME_TO_UNIX_TIME;
274
                                        record.gpsTime = (double) las_time;
275
                                }
276
                                else {
277
                                        record.gpsTime = 0.0d;
278
                                }
279
                        }
280
                        if (intensityIdx!=-1) {
281
                                record.intensity = (short) feature.getInt(intensityIdx);
282
                        }
283
                        if (returnNumIdx!=-1) {
284
                                record.returnNumber = (short) feature.getByte(returnNumIdx);
285
                        }
286
                        if (numberOfReturnsIdx!=-1) {
287
                                record.numberOfReturns = (short) feature.getByte(numberOfReturnsIdx);
288
                        }
289

    
290
                        writer.addPoint(record);
291
                } catch (NullPointerException e) {
292
                        throw new WriteException("The writer must be open() before starting writing", e);
293
                } catch (Exception e) {
294
                        throw new WriteException(e.getMessage(), e);
295
                }
296
        }
297
        
298
        public void write(FeatureSet set) throws DataException {
299
        DisposableIterator iter = null;
300
        try {
301
                iter = set.fastIterator();
302
                while (iter.hasNext()) {
303
                    Feature feature = (Feature) iter.next();
304
                    write(feature);
305
                }
306
        } finally {
307
                DisposeUtils.disposeQuietly(iter);
308
        }
309
        }
310
        
311
        public void setPointFormat(int pointFormat) {
312
                this.pointFormat = pointFormat;
313
        }
314
}