UNPKG

gis-tools-ts

Version:

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

323 lines 14.2 kB
/** * Reads a point using the Point Data Record Format 0 * @param reader - data reader, works like a DataView * @param header - las header * @param offset - where to start reading in the point data * @param littleEndian - endianess. Defaults to true (LAS always LE but LAZ may have BE) * @returns - The parsed point with Format 0 metadata */ export function getPointFormat0(reader, header, offset = 0, littleEndian = true) { const { xOffset, yOffset, zOffset, xScaleFactor, yScaleFactor, zScaleFactor } = header; const bits = reader.getUint32(offset + 14, littleEndian); const classBits = reader.getUint8(offset + 15); const point = { x: reader.getInt32(offset, littleEndian) * xScaleFactor + xOffset, y: reader.getInt32(offset + 4, littleEndian) * yScaleFactor + yOffset, z: reader.getInt32(offset + 8, littleEndian) * zScaleFactor + zOffset, m: { intensity: reader.getUint16(offset + 12, littleEndian), returnNumber: bits & 0b00000111, // 3 bits (bits 0 – 2) numberOfReturns: (bits & 0b00111000) >> 3, // 3 bits (bits 3 – 5) scanDirectionFlag: (bits & 0b01000000) >> 6, // 1 bit (bit 6) edgeOfFlightLine: (bits & 0b10000000) >> 7, // 1 bit (bit 7) classification: toLASClassification(classBits), isSynthetic: (classBits & (1 << 5)) !== 0, isKeyPoint: (classBits & (1 << 6)) !== 0, isWithheld: (classBits & (1 << 7)) !== 0, scanAngleRank: reader.getInt8(offset + 16), userData: reader.getUint8(offset + 17), pointSourceID: reader.getUint16(offset + 18, littleEndian), }, }; return point; } /** * Reads a point using the Point Data Record Format 1 * @param reader - data reader, works like a DataView * @param header - las header * @param offset - where to start reading in the point data * @param littleEndian - endianess. Defaults to true (LAS always LE but LAZ may have BE) * @returns - The parsed point with Format 1 metadata */ export function getPointFormat1(reader, header, offset = 0, littleEndian = true) { const point = getPointFormat0(reader, header, offset, littleEndian); point.m.gpsTime = reader.getFloat64(offset + 20, littleEndian); return point; } /** * Reads a point using the Point Data Record Format 2 * @param reader - data reader, works like a DataView * @param header - las header * @param offset - where to start reading in the point data * @param littleEndian - endianess. Defaults to true (LAS always LE but LAZ may have BE) * @returns - The parsed point with Format 2 metadata */ export function getPointFormat2(reader, header, offset = 0, littleEndian = true) { const point = getPointFormat0(reader, header, offset, littleEndian); point.m.rgba = { r: reader.getUint16(offset + 20, littleEndian), g: reader.getUint16(offset + 22, littleEndian), b: reader.getUint16(offset + 24, littleEndian), a: 255, }; return point; } /** * Reads a point using the Point Data Record Format 3 * @param reader - data reader, works like a DataView * @param header - las header * @param offset - where to start reading in the point data * @param littleEndian - endianess. Defaults to true (LAS always LE but LAZ may have BE) * @returns - The parsed point with Format 3 metadata */ export function getPointFormat3(reader, header, offset = 0, littleEndian = true) { const point = getPointFormat1(reader, header, offset, littleEndian); point.m.rgba = { r: reader.getUint16(offset + 28, littleEndian), g: reader.getUint16(offset + 30, littleEndian), b: reader.getUint16(offset + 32, littleEndian), a: 255, }; return point; } /** * Reads a point using the Point Data Record Format 4 * https://github.com/ASPRSorg/LAS/wiki/Waveform-Data-Packet-Descriptors-Explained * @param reader - data reader, works like a DataView * @param header - las header * @param offset - where to start reading in the point data * @param littleEndian - endianess. Defaults to true (LAS always LE but LAZ may have BE) * @returns - The parsed point with Format 4 metadata */ export function getPointFormat4(reader, header, offset = 0, littleEndian = true) { const point = getPointFormat1(reader, header, offset, littleEndian); point.m.wavePacketDescriptorIndex = reader.getUint8(offset + 28); point.m.wavePacketOffset = Number(reader.getBigUint64(offset + 29, littleEndian)); point.m.wavePacketLength = reader.getUint32(offset + 37, littleEndian); point.m.waveformLocationReturnPoint = reader.getFloat32(offset + 41, littleEndian); point.m.xT = reader.getFloat32(offset + 45, littleEndian); point.m.yT = reader.getFloat32(offset + 49, littleEndian); point.m.zT = reader.getFloat32(offset + 53, littleEndian); return point; } /** * Reads a point using the Point Data Record Format 5 * @param reader - data reader, works like a DataView * @param header - las header * @param offset - where to start reading in the point data * @param littleEndian - endianess. Defaults to true (LAS always LE but LAZ may have BE) * @returns - The parsed point with Format 4 metadata */ export function getPointFormat5(reader, header, offset = 0, littleEndian = true) { const point = getPointFormat3(reader, header, offset, littleEndian); point.m.wavePacketDescriptorIndex = reader.getUint8(offset + 34); point.m.wavePacketOffset = Number(reader.getBigUint64(offset + 35, littleEndian)); point.m.wavePacketLength = reader.getUint32(offset + 43, littleEndian); point.m.waveformLocationReturnPoint = reader.getFloat32(offset + 47, littleEndian); point.m.xT = reader.getFloat32(offset + 51, littleEndian); point.m.yT = reader.getFloat32(offset + 55, littleEndian); point.m.zT = reader.getFloat32(offset + 59, littleEndian); return point; } /** * Reads a point using the Point Data Record Format 0 * @param reader - data reader, works like a DataView * @param header - las header * @param offset - where to start reading in the point data * @param littleEndian - endianess. Defaults to true (LAS always LE but LAZ may have BE) * @returns - The parsed point with Format 0 metadata */ export function getPointFormat6(reader, header, offset = 0, littleEndian = true) { const { xOffset, yOffset, zOffset, xScaleFactor, yScaleFactor, zScaleFactor } = header; const bits1 = reader.getUint8(offset + 14); const bits2 = reader.getUint8(offset + 15); const point = { x: reader.getInt32(offset, littleEndian) * xScaleFactor + xOffset, y: reader.getInt32(offset + 4, littleEndian) * yScaleFactor + yOffset, z: reader.getInt32(offset + 8, littleEndian) * zScaleFactor + zOffset, m: { intensity: reader.getUint16(offset + 12, littleEndian), returnNumber: bits1 & 0b00001111, // 4 bits (bits 0 – 3) numberOfReturns: (bits1 & 0b11110000) >> 4, // 4 bits (bits 4 – 7) classificationFlag: toLASClassificationFlag(bits2), // 4 bis (bit 0 - 3) scannerChannel: (bits2 & 0b00110000) >> 4, // 2 bits (bit 4 - 5) scanDirectionFlag: (bits2 & 0b01000000) >> 6, // 1 bit (bit 6) edgeOfFlightLine: (bits2 & 0b10000000) >> 7, // 1 bit (bit 7) classification: toLASClassification14(reader.getUint8(offset + 16)), userData: reader.getUint8(offset + 17), scanAngle: reader.getInt16(offset + 18, littleEndian), pointSourceID: reader.getUint16(offset + 20, littleEndian), gpsTime: reader.getFloat64(offset + 22, littleEndian), }, }; return point; } /** * Reads a point using the Point Data Record Format 7 * @param reader - data reader, works like a DataView * @param header - las header * @param offset - where to start reading in the point data * @param littleEndian - endianess. Defaults to true (LAS always LE but LAZ may have BE) * @returns - The parsed point with Format 7 metadata */ export function getPointFormat7(reader, header, offset = 0, littleEndian = true) { const point = getPointFormat6(reader, header, offset, littleEndian); point.m.rgba = { r: reader.getUint16(offset + 30, littleEndian), g: reader.getUint16(offset + 32, littleEndian), b: reader.getUint16(offset + 34, littleEndian), a: 255, }; return point; } /** * Reads a point using the Point Data Record Format 8 * @param reader - data reader, works like a DataView * @param header - las header * @param offset - where to start reading in the point data * @param littleEndian - endianess. Defaults to true (LAS always LE but LAZ may have BE) * @returns - The parsed point with Format 8 metadata */ export function getPointFormat8(reader, header, offset = 0, littleEndian = true) { const point = getPointFormat7(reader, header, offset, littleEndian); point.m.nir = reader.getUint16(offset + 36, littleEndian); return point; } /** * Reads a point using the Point Data Record Format 9 * @param reader - data reader, works like a DataView * @param header - las header * @param offset - where to start reading in the point data * @param littleEndian - endianess. Defaults to true (LAS always LE but LAZ may have BE) * @returns - The parsed point with Format 9 metadata */ export function getPointFormat9(reader, header, offset = 0, littleEndian = true) { const point = getPointFormat6(reader, header, offset, littleEndian); point.m.wavePacketDescriptorIndex = reader.getInt16(offset + 30, littleEndian); point.m.wavePacketOffset = Number(reader.getBigUint64(offset + 31, littleEndian)); point.m.wavePacketLength = reader.getUint32(offset + 39, littleEndian); point.m.waveformLocationReturnPoint = reader.getFloat32(offset + 43, littleEndian); point.m.xT = reader.getFloat32(offset + 47, littleEndian); point.m.yT = reader.getFloat32(offset + 51, littleEndian); point.m.zT = reader.getFloat32(offset + 55, littleEndian); return point; } /** * Reads a point using the Point Data Record Format 10 * @param reader - data reader, works like a DataView * @param header - las header * @param offset - where to start reading in the point data * @param littleEndian - endianess. Defaults to true (LAS always LE but LAZ may have BE) * @returns - The parsed point with Format 10 metadata */ export function getPointFormat10(reader, header, offset = 0, littleEndian = true) { const point = getPointFormat7(reader, header, offset, littleEndian); point.m.wavePacketDescriptorIndex = reader.getUint8(offset + 38); point.m.wavePacketOffset = Number(reader.getBigUint64(offset + 39, littleEndian)); point.m.wavePacketLength = reader.getUint32(offset + 47, littleEndian); point.m.waveformLocationReturnPoint = reader.getFloat32(offset + 51, littleEndian); point.m.xT = reader.getFloat32(offset + 55, littleEndian); point.m.yT = reader.getFloat32(offset + 59, littleEndian); point.m.zT = reader.getFloat32(offset + 63, littleEndian); return point; } /** * Converts a number into a LASClassification * @param classification - the number * @returns - the LASClassification */ export function toLASClassification(classification) { // we only wany the first 5 bits classification &= 0b11111; if (classification === 0) return 'Created, Never Classified'; if (classification === 1) return 'Unclassified'; if (classification === 2) return 'Ground'; if (classification === 3) return 'Low Vegetation'; if (classification === 4) return 'Medium Vegetation'; if (classification === 5) return 'High Vegetation'; if (classification === 6) return 'Building'; if (classification === 7) return 'Low Point (Noise)'; if (classification === 8) return 'Model Key-point (mass point)'; if (classification === 9) return 'Water'; if (classification === 12) return 'Overlap Points'; return 'Reserved'; } /** * Converts a number into a classification flag * @param classFlag - the input * @returns - the classification flag */ export function toLASClassificationFlag(classFlag) { const firstThreeBits = classFlag & 0b1111; if (firstThreeBits === 0) return 'Synthetic'; if (firstThreeBits === 1) return 'Key-point'; if (firstThreeBits === 2) return 'Withheld'; if (firstThreeBits === 3) return 'Overlap'; return 'Unknown'; } /** * Converts a number into a LASClassification v1.4 * @param classification - the number * @returns - the LASClassification */ export function toLASClassification14(classification) { if (classification === 0) return 'Created, Never Classified'; if (classification === 1) return 'Unclassified'; if (classification === 2) return 'Ground'; if (classification === 3) return 'Low Vegetation'; if (classification === 4) return 'Medium Vegetation'; if (classification === 5) return 'High Vegetation'; if (classification === 6) return 'Building'; if (classification === 7) return 'Low Point (Noise)'; if (classification === 8) return 'Reserved'; if (classification === 9) return 'Water'; if (classification === 10) return 'Rail'; if (classification === 11) return 'Road Surface'; if (classification === 12) return 'Reserved'; if (classification === 13) return 'Wire – Guard (Shield)'; if (classification === 14) return 'Wire – Conductor (Phase)'; if (classification === 15) return 'Transmission Tower'; if (classification === 16) return 'Wire-structure Connector (e.g. Insulator)'; if (classification === 17) return 'Bridge Deck'; if (classification === 18) return 'High Noise'; if (classification >= 19 && classification <= 63) return 'Reserved'; if (classification >= 64 && classification <= 255) return 'User Definable'; return 'Missing'; } //# sourceMappingURL=getPoint.js.map