package com.revolsys.elevation.cloud.las.pointformat;
import java.util.function.BiFunction;
import java.util.function.Function;
import com.revolsys.collection.map.IntHashMap;
import com.revolsys.datatype.DataTypes;
import com.revolsys.elevation.cloud.las.LasPointCloud;
import com.revolsys.elevation.cloud.las.LasPointCloudHeader;
import com.revolsys.elevation.cloud.las.Version;
import com.revolsys.geometry.model.GeometryFactory;
import com.revolsys.io.channels.ChannelReader;
import com.revolsys.record.code.Code;
import com.revolsys.record.schema.RecordDefinition;
import com.revolsys.record.schema.RecordDefinitionBuilder;
public enum LasPointFormat implements Code {
Core( //
0, //
20, //
LasPoint0Core::new, //
LasPointCloudHeader.VERSION_1_0 //
), //
GpsTime( //
1, //
28, //
LasPoint1GpsTime::new, //
LasPointCloudHeader.VERSION_1_0 //
), //
Rgb( //
2, //
26, //
LasPoint2Rgb::new, //
LasPointCloudHeader.VERSION_1_2), //
GpsTimeRgb( //
3, //
34, //
LasPoint3GpsTimeRgb::new, //
LasPointCloudHeader.VERSION_1_2), //
GpsTimeWavePackets( //
4, //
57, //
LasPoint4GpsTimeWavePackets::new, //
LasPointCloudHeader.VERSION_1_3), //
GpsTimeRgbWavePackets( //
5, //
63, //
LasPoint5GpsTimeRgbWavePackets::new, //
LasPointCloudHeader.VERSION_1_3), //
ExtendedGpsTime( //
6, //
30, //
LasPoint6GpsTime::new, //
LasPointCloudHeader.VERSION_1_4 //
), //
ExtendedGpsTimeRgb( //
7, //
36, //
LasPoint7GpsTimeRgb::new, //
LasPointCloudHeader.VERSION_1_4 //
), //
ExtendedGpsTimeRgbNir( //
8, //
38, //
LasPoint8GpsTimeRgbNir::new, //
LasPointCloudHeader.VERSION_1_4 //
), //
ExtendedGpsTimeWavePackets( //
9, //
59, //
LasPoint9GpsTimeWavePackets::new, //
LasPointCloudHeader.VERSION_1_4 //
), //
ExtendedGpsTimeRgbNirWavePackets( //
10, //
67, //
LasPoint10GpsTimeRgbNirWavePackets::new, //
LasPointCloudHeader.VERSION_1_4 //
);
private static final IntHashMap<LasPointFormat> FORMAT_BY_ID = new IntHashMap<>();
static {
for (final LasPointFormat format : values()) {
FORMAT_BY_ID.put(format.id, format);
}
}
public static LasPointFormat getById(final int id) {
final LasPointFormat format = FORMAT_BY_ID.get(id);
if (format == null) {
throw new IllegalArgumentException("Unsupported Las Point format=" + id);
} else {
return format;
}
}
private int id;
private int recordLength;
private BiFunction<LasPointCloud, ChannelReader, LasPoint> recordReader;
private Version minVersion;
private Function<LasPointCloud, LasPoint> constructor;
private LasPointFormat(final int id, final int recordLength,
final Function<LasPointCloud, LasPoint> constructor, final Version minVersion) {
this.id = id;
this.recordLength = recordLength;
this.constructor = constructor;
this.minVersion = minVersion;
}
@Override
public String getCode() {
return Integer.toString(this.id);
}
@Override
public String getDescription() {
return toString();
}
public int getId() {
return this.id;
}
public Version getMinVersion() {
return this.minVersion;
}
public int getRecordLength() {
return this.recordLength;
}
public BiFunction<LasPointCloud, ChannelReader, LasPoint> getRecordReader() {
return this.recordReader;
}
public LasPoint newLasPoint(final LasPointCloud pointCloud) {
return this.constructor.apply(pointCloud);
}
public LasPoint newLasPoint(final LasPointCloud pointCloud, final double x, final double y,
final double z) {
final BaseLasPoint point = (BaseLasPoint)newLasPoint(pointCloud);
point.setXYZ(pointCloud.toIntX(x), pointCloud.toIntY(y), pointCloud.toIntZ(z));
return point;
}
public RecordDefinition newRecordDefinition(final GeometryFactory geometryFactory) {
final RecordDefinitionBuilder builder = new RecordDefinitionBuilder("/LAS_POINT") //
.addField("x", DataTypes.DOUBLE, true) //
.addField("y", DataTypes.DOUBLE, true) //
.addField("z", DataTypes.DOUBLE, true) //
.addField("intensity", DataTypes.INT, false) //
.addField("returnNumber", DataTypes.BYTE, true) //
.addField("numberOfReturns", DataTypes.BYTE, true) //
.addField("scanDirectionFlag", DataTypes.BOOLEAN, true) //
.addField("edgeOfFlightLine", DataTypes.BOOLEAN, true) //
.addField("classification", DataTypes.BYTE, true) //
.addField("synthetic", DataTypes.BOOLEAN, true) //
.addField("keyPoint", DataTypes.BOOLEAN, true) //
.addField("withheld", DataTypes.BOOLEAN, true) //
.addField("overlap", DataTypes.BOOLEAN, true) //
.addField("scanAngleRank", DataTypes.SHORT, true) //
.addField("userData", DataTypes.SHORT, false) //
.addField("pointSourceID", DataTypes.INT, true) //
.setGeometryFactory(geometryFactory) //
;
if (this.id == 1 || this.id >= 3) {
builder.addField("gpsTime", DataTypes.DOUBLE, true);
}
if (this.id == 2 || this.id == 3 || this.id == 5 || this.id == 7 || this.id == 8
|| this.id == 10) {
builder.addField("red", DataTypes.INT, true);
builder.addField("green", DataTypes.INT, true);
builder.addField("blue", DataTypes.INT, true);
}
if (this.id == 8 || this.id == 10) {
builder.addField("nir", DataTypes.INT, true);
}
if (this.id == 4 || this.id == 5 || this.id == 9 || this.id == 10) {
builder.addField("wavePacketDescriptorIndex", DataTypes.SHORT, true);
builder.addField("byteOffsetToWaveformData", DataTypes.LONG, true);
builder.addField("waveformPacketSizeInBytes", DataTypes.LONG, true);
builder.addField("returnPointWaveformLocation", DataTypes.FLOAT, true);
builder.addField("xT", DataTypes.FLOAT, true);
builder.addField("yT", DataTypes.FLOAT, true);
builder.addField("zT", DataTypes.FLOAT, true);
}
builder.addField("geometry", DataTypes.POINT, true);
return builder.getRecordDefinition();
}
public LasPoint readLasPoint(final LasPointCloud pointCloud, final ChannelReader reader) {
final LasPoint point = this.constructor.apply(pointCloud);
point.read(pointCloud, reader);
return point;
}
}