Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Python/Javascriptで読む点群

 Python/Javascriptで読む点群

FOSS4G 2020 Japan Online

Taro Matsuzawa aka. btm

November 08, 2020
Tweet

More Decks by Taro Matsuzawa aka. btm

Other Decks in Programming

Transcript

  1. こんな感じのコードになります 先頭を読む import struct f = open(‘your.las’, ‘rb’) file_signature =

    b"".join(list(struct.unpack('4c', f.read(1*4)))).decode(‘ascii') print(file_signature) f.close() # 閉じておく
  2. こんな感じのコードになります File Source IDを読む import struct f = open(‘your.las’, ‘rb’)

    file_signature = b"".join(list(struct.unpack('4c', f.read(1*4)))).decode(‘ascii') (file_source_id,) = struct.unpack(‘H’, f.read(2)) print(file_source_id) f.close() # 閉じておく tupleで返ってくるので注意
  3. こんな感じになる def header(self, f): file_signature = b"".join(list(struct.unpack('4c', f.read(1*4)))).decode('ascii') (file_source_id,) =

    struct.unpack('H', f.read(2)) (global_encoding,) = struct.unpack('H', f.read(2)) (guid_data1,) = struct.unpack('<L', f.read(4)) (guid_data2,) = struct.unpack('H', f.read(2)) (guid_data3,) = struct.unpack('H', f.read(2)) guid_data4 = struct.unpack('<8B', f.read(1*8)) …
  4. LASのversion minorによってヘッダの大きさが変わる LAS 1.2 -> 227byte LAS 1.3 -> 235byte

    LAS 1.4 -> 375byte 必ずversion checkを入れること 読む上で注意点
  5. sliceで読み取る範囲を指定して readAsArrayBufferで読み取る onloadイベントハンドラが読みとっ て、またreadAsArrayBufferを呼び 出して… イベントハンドラがバイナリを読 む責務を追っている 最後はreader.abort()をする ややこしい class

    LasReader { constructor(blob) { this.blob = blob } read(callback) { let offset = 0 let reader = new FileReader() let slice = this.blob.slice(offset, 4) reader.onload = (e) => { if (offset == 0) { const file_signature = char_to_string(e.target.result) console.log(`file_signature: ${file_signature}`) offset = 4 slice = self.blob.slice(offset, 6) } else if (offset == 6) { … } else { reader.abort() // call reader.onloaded } reader.readAsArrayBuffer(slice) } reader.onloaded = () => { callback(…) } reader.readAsArrayBuffer(slice) // 開始 } }
  6. offsetとreaderをthisで参照可能に する onloadのときにresolveを呼ぶ sliceを作るサイズを引数にして、成 功時にoffsetに加算する Promise class LasParser { constructor(blob)

    { this.blob = blob this.offset = 0 this.reader = new FileReader() } readSlice(size) { return new Promise((resolve, reject) => { this.reader.onload = (e) => { this.offset += size resolve(e.target.result) } this.reader.onerror = (e) => { console.log('onerror') reject(e) } const slice = this.blob.slice(this.offset, this.offset + size) this.reader.readAsArrayBuffer(slice) }) }
  7. async/await async read(target, callback) { let result = await this.readSlice(4)

    const file_signature = char_to_string(result) result = await this.readSlice(2) const file_source_id = (new DataView(result)).getUint16() result = await this.readSlice(2) const global_encording = (new DataView(result)).getUint16(0, true) result = await this.readSlice(4) const guid_data1 = (new DataView(result)).getUint32(0, true) … const z = new DataView(result) const max_z = z.getFloat64(0, true) const min_z = z.getFloat64(8, true) this.reader.abort() callback(max_x, min_x, max_y, min_y) } await this.readSlice で何バイト読 むか指定 読まれたバイナリの処理の責務が すべてread関数になる 最後はthis.reader.abort()を実行 してcallbackを呼ぶ