UNPKG

gis-tools-ts

Version:

A collection of geospatial tools primarily designed for WGS84, Web Mercator, and S2.

790 lines 25.2 kB
import { toLASClassification, toLASClassification14, toLASClassificationFlag } from '../getPoint'; import { i16Quantize, i8Clamp } from '../util'; /** * @param input - 30bits input * @returns - parsed to a LASpoint14 output */ export function modifyPoint14RawInput(input) { const tmp = new LAStempReadPoint14(input); const res = new LASpoint14(); res.x = tmp.x; res.y = tmp.y; res.z = tmp.z; res.intensity = tmp.intensity; if (tmp.numberOfReturns > 7) { if (tmp.returnNumber > 6) { if (tmp.returnNumber >= tmp.numberOfReturns) { res.legacyReturnNumber = 7; } else { res.legacyReturnNumber = 6; } } else { res.legacyReturnNumber = tmp.returnNumber; } res.legacyNumberOfReturns = 7; } else { res.legacyReturnNumber = tmp.returnNumber; res.legacyNumberOfReturns = tmp.numberOfReturns; } res.scanDirectionFlag = tmp.scanDirectionFlag; res.edgeOfFlightLine = tmp.edgeOfFlightLine; res.legacyFlags = (tmp.classificationFlags << 5) & 0xe0; if (tmp.classification < 32) res.legacyClassification |= tmp.classification; res.legacyScanAngleRank = i8Clamp(i16Quantize(0.006 * tmp.scanAngle)); res.userData = tmp.userData; res.pointSourceID = tmp.pointSourceID; res.scannerChannel = tmp.scannerChannel; res.classificationFlags = tmp.classificationFlags; res.classification = tmp.classification; res.returnNumber = tmp.returnNumber; res.numberOfReturns = tmp.numberOfReturns; res.scanAngle = tmp.scanAngle; res.gpsTime = input.getFloat64(22, true); return res.data; } /** Base class for common data manipulation */ export class CopyDataView { data; /** @param data - the data to manipulate */ constructor(data) { this.data = data; } /** * @param data - the data to copy from * @param length - the length to copy */ copyFrom(data, length) { new Uint8Array(this.data.buffer).set(new Uint8Array(data.buffer, data.byteOffset, length)); } /** * @param item - the data to copy to * @param length - the length to copy */ copyTo(item, length) { const { data } = this; new Uint8Array(item.buffer, item.byteOffset, length).set(new Uint8Array(data.buffer, data.byteOffset, length)); } } /** * Point 1.0 Internal manipulation tool * [Reference](https://github.com/LASzip/LASzip/blob/658d03825b221fab91ddf4571439724fda930191/src/lasreaditemcompressed_v1.cpp#L44) * The struct form: * ```cpp * struct LASpoint10 * { * I32 x; * I32 y; * I32 z; * U16 intensity; * U8 return_number : 3; * U8 number_of_returns_of_given_pulse : 3; * U8 scan_direction_flag : 1; * U8 edge_of_flight_line : 1; * U8 classification; * I8 scan_angle_rank; * U8 user_data; * U16 point_source_ID; * }; * ``` */ export class LASpoint10 extends CopyDataView { /** @param data - 20 bytes */ constructor(data = new DataView(new ArrayBuffer(20))) { super(data); } /** * Modify the vector point given the input data and header * @param data - the raw data * @param header - the las header * @param point - the vector point to modify */ static rawToVectorPoint(data, header, point) { const { xOffset, yOffset, zOffset, xScaleFactor, yScaleFactor, zScaleFactor } = header; const lasPoint10 = new LASpoint10(data); point.x = lasPoint10.x * xScaleFactor + xOffset; point.y = lasPoint10.y * yScaleFactor + yOffset; point.z = lasPoint10.z * zScaleFactor + zOffset; point.m.intensity = lasPoint10.intensity; point.m.returnNumber = lasPoint10.returnNumber; point.m.numberOfReturns = lasPoint10.numberOfReturns; point.m.scanDirectionFlag = lasPoint10.scanDirectionFlag; point.m.edgeOfFlightLine = lasPoint10.edgeOfFlightLine; point.m.classification = toLASClassification(lasPoint10.class); point.m.isSynthetic = lasPoint10.isSynthetic; point.m.isKeyPoint = lasPoint10.isKeyPoint; point.m.isWithheld = lasPoint10.isWithheld; point.m.scanAngleRank = lasPoint10.scanAngleRank; point.m.userData = lasPoint10.userData; point.m.pointSourceID = lasPoint10.pointSourceID; } /** @returns the I32 at x position */ get x() { return this.data.getInt32(0, true); } /** set an I32 at x position */ set x(value) { this.data.setInt32(0, value, true); } /** @returns the I32 at y position */ get y() { return this.data.getInt32(4, true); } /** set an I32 at y position */ set y(value) { this.data.setInt32(4, value, true); } /** @returns the I32 at z position */ get z() { return this.data.getInt32(8, true); } /** set an I32 at z position */ set z(value) { this.data.setInt32(8, value, true); } /** @returns the U16 at intensity position */ get intensity() { return this.data.getUint16(12, true); } /** set an U16 at intensity position */ set intensity(value) { this.data.setUint16(12, value, true); } /** @returns the U8 at flags position */ get flags() { return this.data.getUint8(14); } /** @returns the return number flag */ get returnNumber() { return this.flags & 0b00000111; } /** @returns the number of returns flag */ get numberOfReturns() { return (this.flags & 0b00111000) >> 3; } /** @returns the scan direction flag */ get scanDirectionFlag() { return (this.flags & 0b01000000) >> 6; } /** @returns the edge of flight line flag */ get edgeOfFlightLine() { return this.flags >> 7; } /** set an U8 at flags position */ set flags(value) { this.data.setUint8(14, value); } /** @returns the U8 at class position */ get class() { return this.data.getUint8(15); } /** @returns the isSynthetic flag */ get isSynthetic() { return (this.class & (1 << 5)) !== 0; } /** @returns the isKeyPoint flag */ get isKeyPoint() { return (this.class & (1 << 6)) !== 0; } /** @returns the isWithheld flag */ get isWithheld() { return (this.class & (1 << 7)) !== 0; } /** set an U8 at class position */ set class(value) { this.data.setUint8(15, value); } /** @returns the I8 at scan angle rank */ get scanAngleRank() { return this.data.getInt8(16); } /** set an I8 at scan angle rank */ set scanAngleRank(value) { this.data.setInt8(16, value); } /** @returns the U8 at user data position */ get userData() { return this.data.getUint8(17); } /** set an U8 at user data position */ set userData(value) { this.data.setUint8(17, value); } /** @returns the U16 at point source ID position */ get pointSourceID() { return this.data.getUint16(18, true); } /** set an U16 at point source ID position */ set pointSourceID(value) { this.data.setUint16(18, value, true); } } /** LAS 1.0 RGBA Point data. Each color channel is 2 bytes. */ export class LASrgba extends CopyDataView { /** @param data - 6 bytes (2 bytes each for R, G, B) */ constructor(data = new DataView(new ArrayBuffer(6))) { super(data); } /** * Modify the vector point given the input data * @param data - the raw data * @param point - the vector point to modify */ static rawToVectorPoint(data, point) { const lasRgba = new LASrgba(data); point.m.rgba = { r: lasRgba.r, g: lasRgba.g, b: lasRgba.b, a: 255, }; } /** @returns the U16 red position */ get r() { return this.data.getInt16(0, true); } /** set an U16 red position */ set r(value) { this.data.setInt16(0, value, true); } /** @returns the U16 green position */ get g() { return this.data.getInt16(2, true); } /** set an U16 green position */ set g(value) { this.data.setInt16(2, value, true); } /** @returns the U16 blue position */ get b() { return this.data.getInt16(4, true); } /** set an U16 blue position */ set b(value) { this.data.setInt16(4, value, true); } } /** LAS 1.0 RGBA Point data. Each color channel is 2 bytes. */ export class LASrgbaNir extends LASrgba { /** @param data - 8 bytes (2 bytes each for R, G, B, and NIR) */ constructor(data = new DataView(new ArrayBuffer(8))) { super(data); } /** * Modify the vector point given the input data * @param data - the raw data * @param point - the vector point to modify */ static rawToVectorPoint(data, point) { super.rawToVectorPoint(data, point); point.m.nir = data.getInt16(6, true); } /** @returns the U16 blue position */ get nir() { return this.data.getInt16(6, true); } /** set an U16 blue position */ set nir(value) { this.data.setInt16(6, value, true); } } /** LAS 1.0 Wave Packet. Each wave packet is 29 bytes. */ export class LASWavePacket13 extends CopyDataView { /** @param data - 29 */ constructor(data = new DataView(new ArrayBuffer(29))) { const actualData = new DataView(data.buffer, data.byteOffset, data.byteLength); super(actualData); } /** * Modify the vector point given the input data * @param data - the raw data * @param point - the vector point to modify */ static rawToVectorPoint(data, point) { const lasWavePacket = new LASWavePacket13(data); point.m.wavePacketDescriptorIndex = lasWavePacket.index; point.m.wavePacketOffset = lasWavePacket.offset; point.m.wavePacketLength = lasWavePacket.packetSize; point.m.waveformLocationReturnPoint = lasWavePacket.returnPoint; point.m.xT = lasWavePacket.x; point.m.yT = lasWavePacket.y; point.m.zT = lasWavePacket.z; } /** @returns - the index */ get index() { return this.data.getUint8(0); } /** set the index */ set index(value) { this.data.setUint8(0, value); } /** @returns the offset */ get offset() { return Number(this.data.getBigUint64(1, true)); } /** set an offset */ set offset(value) { this.data.setBigUint64(1, BigInt(value), true); } /** @returns the packet size */ get packetSize() { return this.data.getUint32(9, true); } /** set an packet size */ set packetSize(value) { this.data.setUint32(9, value, true); } /** @returns the return point */ get returnPoint() { return this.data.getInt32(13, true); } /** set an return point */ set returnPoint(value) { this.data.setInt32(13, value, true); } /** @returns the x */ get x() { return this.data.getInt32(17, true); } /** set an x */ set x(value) { this.data.setInt32(17, value, true); } /** @returns the y */ get y() { return this.data.getInt32(21, true); } /** set an y */ set y(value) { this.data.setInt32(21, value, true); } /** @returns the z */ get z() { return this.data.getInt32(25, true); } /** set an z */ set z(value) { this.data.setInt32(25, value, true); } } /** * LAS Internal Temp Point Format 1.4 * The struct form: * ```cpp * typedef struct LAStempReadPoint14 { * I32 X; * I32 Y; * I32 Z; * U16 intensity; * U8 return_number : 4; * U8 number_of_returns : 4; * U8 classification_flags : 4; * U8 scanner_channel : 2; * U8 scan_direction_flag : 1; * U8 edge_of_flight_line : 1; * U8 classification; * U8 user_data; * I16 scan_angle; * U16 point_source_ID; * }; * ``` */ export class LAStempReadPoint14 extends CopyDataView { /** @param data - 22 bytes */ constructor(data = new DataView(new ArrayBuffer(22))) { super(data); } /** @returns the I32 at x position */ get x() { return this.data.getInt32(0, true); } /** @returns the I32 at y position */ get y() { return this.data.getInt32(4, true); } /** @returns the I32 at z position */ get z() { return this.data.getInt32(8, true); } /** @returns the U16 at intensity position */ get intensity() { return this.data.getUint16(12, true); } /** @returns the U8 at returnNumber position */ get returnNumber() { return this.data.getUint8(14) & 0b1111; } /** @returns the U8 at numberOfReturns position */ get numberOfReturns() { return (this.data.getUint8(14) & 0b11110000) >> 4; } /** @returns the U8 at classificationFlags position */ get classificationFlags() { return this.data.getUint8(15) & 0b1111; } /** @returns the U8 at scannerChannel position */ get scannerChannel() { return (this.data.getUint8(15) & 0b00110000) >> 4; } /** @returns the U8 at scanDirectionFlag position */ get scanDirectionFlag() { return (this.data.getUint8(15) & 0b01000000) >> 6; } /** @returns the U8 at edgeOfFlightLine position */ get edgeOfFlightLine() { return (this.data.getUint8(15) & 0b10000000) >> 7; } /** @returns the U8 at classification position */ get classification() { return this.data.getUint8(16); } /** @returns the U8 at userData position */ get userData() { return this.data.getUint8(17); } /** @returns the I16 at scanAngle position */ get scanAngle() { return this.data.getInt16(18, true); } /** @returns the U16 at pointSourceID position */ get pointSourceID() { return this.data.getUint16(20, true); } } /** * LAS Internal Point Format 1.4 * The struct form: * ```cpp * typedef struct LASpoint14 { * I32 X; * I32 Y; * I32 Z; * U16 intensity; * U8 legacy_return_number : 3; * U8 legacy_number_of_returns : 3; * U8 scan_direction_flag : 1; * U8 edge_of_flight_line : 1; * * U8 legacy_classification : 5; * U8 legacy_flags : 3; * I8 legacy_scan_angle_rank; * U8 user_data; * U16 point_source_ID; * // LAS 1.4 only * I16 scan_angle; * U8 legacy_point_type : 2; * U8 scanner_channel : 2; * U8 classification_flags : 4; * U8 classification; * U8 return_number : 4; * U8 number_of_returns : 4; * // LASlib internal use only * U8 deleted_flag; * // for 8 byte alignment of the GPS time * U8 dummy[2]; * // compressed LASzip 1.4 points only * BOOL gps_time_change; * F64 gps_time; * U16 rgb[4]; * LASwavepacket wavepacket; * } LASpoint14; * ``` */ export class LASpoint14 extends CopyDataView { /** @param data - 45 bytes */ constructor(data = new DataView(new ArrayBuffer(45))) { super(data); } /** * Modify the vector point given the input data and header * @param data - the raw data * @param header - the las header * @param point - the vector point to modify */ static rawToVectorPoint(data, header, point) { const { xOffset, yOffset, zOffset, xScaleFactor, yScaleFactor, zScaleFactor } = header; const lasPoint14 = new LASpoint14(data); point.x = lasPoint14.x * xScaleFactor + xOffset; point.y = lasPoint14.y * yScaleFactor + yOffset; point.z = lasPoint14.z * zScaleFactor + zOffset; point.m.intensity = lasPoint14.intensity; point.m.returnNumber = lasPoint14.legacyReturnNumber; point.m.numberOfReturns = lasPoint14.legacyNumberOfReturns; point.m.scanDirectionFlag = lasPoint14.scanDirectionFlag; point.m.edgeOfFlightLine = lasPoint14.edgeOfFlightLine; point.m.classification = toLASClassification14(lasPoint14.classification); point.m.classificationFlag = toLASClassificationFlag(lasPoint14.classificationFlags); point.m.isSynthetic = lasPoint14.isSynthetic; point.m.isKeyPoint = lasPoint14.isKeyPoint; point.m.isWithheld = lasPoint14.isWithheld; point.m.scanAngle = lasPoint14.scanAngle; point.m.userData = lasPoint14.userData; point.m.scannerChannel = lasPoint14.scannerChannel; point.m.pointSourceID = lasPoint14.pointSourceID; point.m.gpsTime = lasPoint14.gpsTime; } /** @returns the I32 at x position */ get x() { return this.data.getInt32(0, true); } /** set an I32 at x position */ set x(value) { this.data.setInt32(0, value, true); } /** @returns the I32 at y position */ get y() { return this.data.getInt32(4, true); } /** set an I32 at y position */ set y(value) { this.data.setInt32(4, value, true); } /** @returns the I32 at z position */ get z() { return this.data.getInt32(8, true); } /** set an I32 at z position */ set z(value) { this.data.setInt32(8, value, true); } /** @returns the U16 at intensity position */ get intensity() { return this.data.getUint16(12, true); } /** set an U16 at intensity position */ set intensity(value) { this.data.setUint16(12, value, true); } /** @returns the U8 at first flags position */ get flags1() { return this.data.getUint8(14); } /** @returns the U8 at legacy return number position */ get legacyReturnNumber() { return this.flags1 & 0b00000111; } /** set an U8 at legacy return number position */ set legacyReturnNumber(value) { this.data.setUint8(14, (this.flags1 & 0b11111000) | (value & 0b111)); } /** @returns the U8 at legacy number of returns position */ get legacyNumberOfReturns() { return (this.flags1 & 0b00111000) >> 3; } /** set an U8 at legacy number of returns position */ set legacyNumberOfReturns(value) { this.data.setUint8(14, (this.flags1 & 0b11000111) | ((value & 0b111) << 3)); } /** @returns the U8 at scan direction flag position */ get scanDirectionFlag() { return (this.flags1 & 0b01000000) >> 6; } /** set an U8 at scan direction flag position */ set scanDirectionFlag(value) { this.data.setUint8(14, (this.flags1 & 0b10111111) | ((value & 0b1) << 6)); } /** @returns the U8 at edge of flight line position */ get edgeOfFlightLine() { return (this.flags1 & 0b10000000) >> 7; } /** set an U8 at edge of flight line position */ set edgeOfFlightLine(value) { this.data.setUint8(14, (this.flags1 & 0b01111111) | ((value & 0b1) << 7)); } /** set an U8 at first flags position */ set flags1(value) { this.data.setUint8(14, value); } /** @returns the U8 at second flags position */ get flags2() { return this.data.getUint8(15); } /** @returns the U8 at legacy classification position */ get legacyClassification() { return this.flags2 & 0b11111; } /** @returns the isSynthetic flag */ get isSynthetic() { return (this.legacyClassification & (1 << 5)) !== 0; } /** @returns the isKeyPoint flag */ get isKeyPoint() { return (this.legacyClassification & (1 << 6)) !== 0; } /** @returns the isWithheld flag */ get isWithheld() { return (this.legacyClassification & (1 << 7)) !== 0; } /** set an U8 at legacy classification position */ set legacyClassification(value) { this.data.setUint8(15, (this.flags2 & 0b11100000) | (value & 0b11111)); } /** @returns the U8 at legacy flags position */ get legacyFlags() { return (this.flags2 & 0b11100000) >> 5; } /** set an U8 at legacy flags position */ set legacyFlags(value) { this.data.setUint8(15, (this.flags2 & 0b00011111) | ((value & 0b111) << 5)); } /** set an U8 at second flags position */ set flags2(value) { this.data.setUint8(15, value); } /** @returns the I8 at legacy scan angle rank position */ get legacyScanAngleRank() { return this.data.getInt8(16); } /** set an I8 at legacy scan angle rank position */ set legacyScanAngleRank(value) { this.data.setInt8(16, value); } /** @returns the U8 at user data position */ get userData() { return this.data.getUint8(17); } /** set an U8 at user data position */ set userData(value) { this.data.setUint8(17, value); } /** @returns the U16 at point source ID position */ get pointSourceID() { return this.data.getUint16(18, true); } /** set an U16 at point source ID position */ set pointSourceID(value) { this.data.setUint16(18, value, true); } /// LAS 1.4 only /** @returns the I16 at scan angle position */ get scanAngle() { return this.data.getInt16(20, true); } /** set an I16 at scan angle position */ set scanAngle(value) { this.data.setInt16(20, value, true); } /** @returns the U8 at third flags position */ get flags3() { return this.data.getUint8(22); } /** @returns the U8 at legacy point type position */ get legacyPointType() { return this.flags3 & 0b11; } /** @returns the U8 at scanner channel position */ get scannerChannel() { return (this.flags3 & 0b1100) >> 2; } /** set an U8 at scanner channel position */ set scannerChannel(value) { this.data.setUint8(22, (this.flags3 & 0b11110011) | ((value & 0b11) << 2)); } /** @returns the U8 at classification flags position */ get classificationFlags() { return (this.flags3 & 0b11110000) >> 4; } /** set an U8 at classification flags position */ set classificationFlags(value) { this.data.setUint8(22, (this.flags3 & 0b00001111) | ((value & 0b1111) << 4)); } /** set an U8 at third flags position */ set flags3(value) { this.data.setUint8(22, value); } /** @returns the U8 at classification position */ get classification() { return this.data.getUint8(23); } /** set an U8 at classification position */ set classification(value) { this.data.setUint8(23, value); } /** @returns the U8 at fourth flags position */ get flags4() { return this.data.getUint8(24); } /** @returns the U8 at return number position */ get returnNumber() { return this.flags4 & 0b00001111; } /** set an U8 at return number position */ set returnNumber(value) { this.data.setUint8(24, (this.flags4 & 0b11110000) | (value & 0b1111)); } /** @returns the U8 at number of returns position */ get numberOfReturns() { return (this.flags4 & 0b11110000) >> 4; } /** set an U8 at return number position */ set numberOfReturns(value) { this.data.setUint8(24, (this.flags4 & 0b00001111) | ((value & 0b1111) << 4)); } /** set an U8 at fourth flags position */ set flags4(value) { this.data.setUint8(24, value); } /// LASlib internal use only /** @returns the U8 at deleted flag position */ get deletedFlag() { return this.data.getUint8(25); } /** set an U8 at deleted flag position */ set deletedFlag(value) { this.data.setUint8(25, value); } /// For 8 byte alignment of the GPS time /** @returns the U8 at dummy position */ get dummy() { return this.data.getUint16(26, true); } /** set an U8 at dummy position */ set dummy(value) { this.data.setUint16(26, value, true); } /// Compressed LASzip 1.4 points only /** @returns the BOOL at gps time change position */ get gpsTimeChange() { return this.data.getUint8(28); } /** set an BOOL at gps time change position */ set gpsTimeChange(value) { this.data.setUint8(28, value); } /** @returns the F64 at gps time position */ get gpsTime() { return this.data.getFloat64(29, true); } /** set an F64 at gps time position */ set gpsTime(value) { this.data.setFloat64(29, value, true); } /** @returns the U16 red position */ get r() { return this.data.getUint16(37, true); } /** set an U16 red position */ set r(value) { this.data.setUint16(37, value, true); } /** @returns the U16 green position */ get g() { return this.data.getUint16(39, true); } /** set an U16 green position */ set g(value) { this.data.setUint16(39, value, true); } /** @returns the U16 blue position */ get b() { return this.data.getUint16(41, true); } /** set an U16 blue position */ set b(value) { this.data.setUint16(41, value, true); } } //# sourceMappingURL=items.js.map