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

Python/Javascriptで読む点群

 Python/Javascriptで読む点群

FOSS4G 2020 Japan Online

Avatar for Taro Matsuzawa aka. btm

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を呼ぶ