Statistics
| Revision:

gvsig-projects-pool / org.gvsig.lidar.prov / org.gvsig.lidar.prov.whitebox / src / main / java / org / gvsig / lidar / prov / whitebox / WhiteboxLASDataStoreProvider.java @ 281

History | View | Annotate | Download (13.2 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright ? 2007-2016 gvSIG Association
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 any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.lidar.prov.whitebox;
25

    
26
import java.util.ArrayList;
27
import java.util.Date;
28
import java.util.List;
29

    
30
import org.gvsig.fmap.dal.DALLocator;
31
import org.gvsig.fmap.dal.DataStore;
32
import org.gvsig.fmap.dal.DataStoreParameters;
33
import org.gvsig.fmap.dal.DataTypes;
34
import org.gvsig.fmap.dal.FileHelper;
35
import org.gvsig.fmap.dal.exception.DataException;
36
import org.gvsig.fmap.dal.exception.InitializeException;
37
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
38
import org.gvsig.fmap.dal.feature.EditableFeatureType;
39
import org.gvsig.fmap.dal.feature.FeatureType;
40
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
41
import org.gvsig.fmap.dal.resource.ResourceAction;
42
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
43
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
44
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
45
import org.gvsig.fmap.geom.Geometry.TYPES;
46
import org.gvsig.fmap.geom.GeometryLocator;
47
import org.gvsig.fmap.geom.GeometryManager;
48
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
49
import org.gvsig.fmap.geom.exception.CreateGeometryException;
50
import org.gvsig.fmap.geom.primitive.Envelope;
51
import org.gvsig.fmap.geom.primitive.Point;
52
import org.gvsig.fmap.geom.type.GeometryType;
53
import org.gvsig.fmap.geom.type.GeometryTypeNotSupportedException;
54
import org.gvsig.fmap.geom.type.GeometryTypeNotValidException;
55
import org.gvsig.lidar.prov.LASDataStoreProvider;
56
import org.gvsig.lidar.prov.ConversionUtils;
57
import org.gvsig.lidar.prov.LASUnsupportedFormatException;
58
import org.gvsig.tools.dynobject.DynObject;
59
import org.gvsig.tools.exception.BaseException;
60
import org.slf4j.Logger;
61
import org.slf4j.LoggerFactory;
62

    
63
import whitebox.geospatialfiles.LASReader;
64
import whitebox.geospatialfiles.LASReader.PointRecColours;
65
import whitebox.geospatialfiles.LASReader.PointRecord;
66

    
67
/**
68
 * 
69
 * @author <a href="mailto:cmartinez@scolab.es">Cesar Martinez Izquierdo</a>
70
 *
71
 */
72
public class WhiteboxLASDataStoreProvider extends LASDataStoreProvider {
73

    
74
    private static final Logger LOG = LoggerFactory.getLogger(WhiteboxLASDataStoreProvider.class);
75

    
76
    public static final String NAME = "WhiteboxLASDataStoreProvider";
77

    
78
    public static final String DESCRIPTION = "LIDAR LAS file (whitebox)";
79
    
80
    public static final String METADATA_DEFINITION_NAME = "WhiteboxLASDataStoreProvider";
81

    
82

    
83
    protected LASReader reader = null;
84

    
85
    protected WhiteboxLASDataStoreProvider(DataStoreParameters dataParameters,
86
        DataStoreProviderServices storeServices, DynObject metadata) throws InitializeException {
87
        super(dataParameters, storeServices, metadata);
88
    }
89

    
90
    protected WhiteboxLASDataStoreProvider(DataStoreParameters dataParameters,
91
        DataStoreProviderServices storeServices) throws InitializeException {
92
            super(dataParameters, storeServices, FileHelper
93
                    .newMetadataContainer(METADATA_DEFINITION_NAME));
94
    }
95
    
96

    
97
    @Override
98
    public String getFullName() {
99
            return getName();
100
    }
101

    
102
    @Override
103
    public String getName() {
104
        return getLASParameters().getFile().getName();
105
    }
106

    
107
    @Override
108
    public String getProviderName() {
109
        return NAME;
110
    }
111

    
112
    @Override
113
    public boolean allowWrite() {
114
            return false;
115
    }
116

    
117
    protected boolean loadFeatureType() throws LASUnsupportedFormatException,
118
        GeometryTypeNotSupportedException, GeometryTypeNotValidException {
119

    
120
        return (boolean) getResource().execute(new ResourceAction() {
121

    
122
            @Override
123
            public Object run() throws Exception {
124
                    EditableFeatureType editableFeatureType = DALLocator.getDataManager().createFeatureType();
125
                editableFeatureType.setHasOID(true);
126
                EditableFeatureAttributeDescriptor attributeDescriptor = editableFeatureType.add("GEOM",  DataTypes.GEOMETRY);
127
                GeometryManager geometryManager = GeometryLocator.getGeometryManager();
128
                GeometryType geometryType =
129
                        geometryManager.getGeometryType(
130
                                        TYPES.POINT, SUBTYPES.GEOM3D);
131
                attributeDescriptor.setGeometryType(geometryType);
132
                if (getLASParameters().getCRS()!=null) {
133
                        attributeDescriptor.setSRS(getLASParameters().getCRS());
134
                }
135
                editableFeatureType.setDefaultGeometryAttributeName(WhiteboxLASDataStoreProvider.GEOM_FIELD);
136
                attributeDescriptor =
137
                        editableFeatureType.add(CLASS_FIELD, DataTypes.BYTE);
138
                attributeDescriptor =
139
                        editableFeatureType.add(POINTX_FIELD, DataTypes.DOUBLE);
140
                attributeDescriptor =
141
                        editableFeatureType.add(POINTY_FIELD, DataTypes.DOUBLE);
142
                attributeDescriptor =
143
                        editableFeatureType.add(POINTZ_FIELD, DataTypes.DOUBLE);
144

    
145
                attributeDescriptor =
146
                        editableFeatureType.add(INTENSITY_FIELD, DataTypes.INT);
147
                attributeDescriptor =
148
                        editableFeatureType.add(RETURNNUM_FIELD, DataTypes.BYTE);
149
                attributeDescriptor =
150
                        editableFeatureType.add(NUMRETURNS_FIELD, DataTypes.BYTE);
151

    
152
                short pointFormatId = getReader().getPointDataFormatID();
153
                switch (pointFormatId) {
154
                        case 1:
155
                        case 3:
156
                        case 4:
157
                        case 5:
158
                                if (getReader().getGPSTimeType()==1) {
159
                                        attributeDescriptor = editableFeatureType.add(TIME_FIELD, DataTypes.DATE);
160
                                }
161
                                else {
162
                                        attributeDescriptor = editableFeatureType.add(WEEKTIME_FIELD, DataTypes.LONG);
163
                                }
164
                                break;
165
                }
166
                switch (pointFormatId) {
167
                    case 2:
168
                    case 3:
169
                    case 5:
170
                    case 7:
171
                    case 8:
172
                    case 10:
173
                            attributeDescriptor =
174
                    editableFeatureType.add(COLOR_FIELD, DataTypes.INT);
175
                            break;
176
                }
177

    
178
                FeatureType featureType = editableFeatureType.getNotEditableCopy();
179
                if (featureType.getDefaultSRS() != null) {
180
                    setDynValue(DataStore.METADATA_CRS, featureType.getDefaultSRS());
181
                }
182

    
183
                List<FeatureType> featureTypes = new ArrayList<FeatureType>(1);
184
                featureTypes.add(featureType);
185

    
186
                getStoreServices().setFeatureTypes(featureTypes, featureType);
187
                return true;
188
            }
189
        });
190
    }
191

    
192
    public FeatureProvider internalGetFeatureProviderByIndex(
193
                    long index, FeatureType featureType)
194
                                    throws DataException {
195

    
196
            long decimatedIndex = (long) Math.floor(index * decimation);
197
            FeatureProvider featureProvider = this.createFeatureProvider(featureType);
198
            featureProvider.setOID(new Long(decimatedIndex));
199
            PointRecord record = getReader().getPointRecord((int)decimatedIndex);
200
            if (featureType.getAttributeDescriptor(GEOM_FIELD)!=null) {
201
                    try {
202
                            Point p = (Point) this.gm.create(TYPES.POINT, SUBTYPES.GEOM3D);
203
                            p.setCoordinateAt(0, record.getX());
204
                            p.setCoordinateAt(1, record.getY());
205
                            p.setCoordinateAt(2, record.getZ());
206
                            featureProvider.set(GEOM_FIELD, p);
207
                    } catch (CreateGeometryException e) {
208
                            // TODO Auto-generated catch block
209
                            e.printStackTrace();
210
                    }
211
            }
212
            if (featureType.getAttributeDescriptor(POINTX_FIELD)!=null) {
213
                    featureProvider.set(POINTX_FIELD, record.getX());
214
            }
215
            if (featureType.getAttributeDescriptor(POINTY_FIELD)!=null) {
216
                    featureProvider.set(POINTY_FIELD, record.getY());
217
            }
218
            if (featureType.getAttributeDescriptor(POINTZ_FIELD)!=null) {
219
                    featureProvider.set(POINTZ_FIELD, record.getZ());
220
            }
221
            if (featureType.getAttributeDescriptor(CLASS_FIELD)!=null) {
222
                    featureProvider.set(CLASS_FIELD, record.getClassification());
223
            }
224
            if (featureType.getAttributeDescriptor(INTENSITY_FIELD)!=null) {
225
                    featureProvider.set(INTENSITY_FIELD, record.getIntensity());
226
            }
227
            if (featureType.getAttributeDescriptor(RETURNNUM_FIELD)!=null) {
228
                    featureProvider.set(RETURNNUM_FIELD, record.getReturnNumber());
229
            }
230
            if (featureType.getAttributeDescriptor(NUMRETURNS_FIELD)!=null) {
231
                    featureProvider.set(NUMRETURNS_FIELD, record.getNumberOfReturns());
232
            }
233
            if (featureType.getAttributeDescriptor(TIME_FIELD)!=null) {
234
                    // file uses LAS 1.2/1.3/1.4 adjusted GPS Time
235
                    // convert to unix time and build a Date object
236
                    long las_time  = (long)record.getGPSTime();
237
                        Date unix_time = new Date(las_time + ConversionUtils.LAS_TIME_TO_UNIX_TIME);
238
                        featureProvider.set(TIME_FIELD, unix_time);
239
            }
240
            if (featureType.getAttributeDescriptor(WEEKTIME_FIELD)!=null) {
241
                    // LAS 1.0, 1.1 gps week time, we handle it as a plain long.
242
                        // It could be translated to Unix time using the following formulas:
243
                        // seconds_per_week = 604800
244
                        // las_gps_time = las_week_time + ( week_number_from_6_1_1980 * seconds_per_week)
245
                        // unix_time = las_gps_time + 315964800
246
                    long las_time  = (long)record.getGPSTime();
247
                    featureProvider.set(WEEKTIME_FIELD, new Long(las_time));
248
            }
249
            if (featureType.getAttributeDescriptor(COLOR_FIELD)!=null) {
250
                    PointRecColours colors = getReader().getPointRecordColours((int)decimatedIndex);
251
                    int rgb;
252
                    if (colors!=null) {
253
                            int red = colors.getRed();
254
                            int green = colors.getGreen();
255
                            int blue = colors.getBlue();
256
                            // RGB value representing the color in the default sRGB ColorModel.
257
                            // (Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are blue).
258
                            rgb = ConversionUtils.rgbToInt(red, green, blue);
259
                    }
260
                    else {
261
                            rgb = 0;
262
                    }
263
                    featureProvider.set(COLOR_FIELD, rgb);
264
            }
265
            return featureProvider;
266
    }
267
    
268
    protected synchronized LASReader getReader() throws LASUnsupportedFormatException {
269
        if (this.reader == null) {
270
                reader = new LASReader(file.getPath());
271
        }
272
        return this.reader;
273
    }
274
    
275
    /*
276
     * Lazy envelope initialization
277
     */
278
    @Override
279
    public Envelope getEnvelope() throws DataException {
280
            
281
        open();
282
        if (this.envelope == null) {
283
                Envelope env;
284
                        try {
285
                                env = this.gm.createEnvelope(SUBTYPES.GEOM3D);
286
                        Point p1 = (Point) this.gm.create(TYPES.POINT, SUBTYPES.GEOM3D);
287
                        Point p2 = (Point) this.gm.create(TYPES.POINT, SUBTYPES.GEOM3D);
288
                        // FIXME: do we need to consider projection for upper & lower corner?
289
                        p1.setCoordinateAt(0, getReader().getMinX());
290
                        p1.setCoordinateAt(1, getReader().getMinY());
291
                        p1.setCoordinateAt(2, getReader().getMinZ());
292
                        p2.setCoordinateAt(0, getReader().getMaxX());
293
                        p2.setCoordinateAt(1, getReader().getMaxY());
294
                        p2.setCoordinateAt(2, getReader().getMaxZ());
295
                        env.setLowerCorner(p1);
296
                        env.setUpperCorner(p2);
297
                        this.envelope = env;
298
                        } catch (CreateEnvelopeException e) {
299
                                // TODO Auto-generated catch block
300
                                e.printStackTrace();
301
                        } catch (CreateGeometryException e) {
302
                                // TODO Auto-generated catch block
303
                                e.printStackTrace();
304
                        }
305

    
306
        }
307
        return this.envelope;
308
    }
309

    
310

    
311
    @Override
312
    public long getFeatureCount() throws DataException {
313
        open();
314
        return ((Number) getResource().execute(new ResourceAction() {
315
            @Override
316
            public Object run() throws Exception {
317
                    long count = getReader().getNumPointRecords();
318
                    if (decimation>1.0d) {
319
                            count = (long) Math.floor((count/decimation));
320
                    }
321
                    return count;
322
            }
323
        })).longValue();
324
    }
325
    
326
    @Override
327
    protected void doDispose() throws BaseException {
328
        super.doDispose();
329
        getResource().removeConsumer(this);
330
        this.resourceProvider = null;
331
        this.gm = null;
332
        this.envelope = null;
333
        this.opened = false;
334
        this.reader = null;
335
    }
336

    
337
    @Override
338
    public boolean closeResourceRequested(ResourceProvider resource) {
339
        this.envelope = null;
340
        this.opened = false;
341
        this.reader = null;
342
        return true;
343
    }
344

    
345
    @Override
346
    public void resourceChanged(ResourceProvider resource) {
347
        this.envelope = null;
348
        this.opened = false;
349
        this.reader = null;
350
    }
351
}