Source code for py3dtiles.pnts
# -*- coding: utf-8 -*-
import struct
import numpy as np
from .tile import TileContent, TileHeader, TileBody, TileType
from .feature_table import FeatureTable
[docs]
class Pnts(TileContent):
[docs]
@staticmethod
def from_features(pdtype, cdtype, features):
"""
Parameters
----------
dtype : numpy.dtype
Numpy description of a single feature
features : Feature[]
Returns
-------
tile : TileContent
"""
ft = FeatureTable.from_features(pdtype, cdtype, features)
tb = PntsBody()
tb.feature_table = ft
th = PntsHeader()
t = TileContent()
t.body = tb
t.header = th
return t
[docs]
@staticmethod
def from_array(array):
"""
Parameters
----------
array : numpy.array
Returns
-------
t : TileContent
"""
# build tile header
h_arr = array[0:PntsHeader.BYTELENGTH]
h = PntsHeader.from_array(h_arr)
if h.tile_byte_length != len(array):
raise RuntimeError("Invalid byte length in header")
# build tile body
b_len = h.ft_json_byte_length + h.ft_bin_byte_length
b_arr = array[PntsHeader.BYTELENGTH:PntsHeader.BYTELENGTH + b_len]
b = PntsBody.from_array(h, b_arr)
# build TileContent with header and body
t = TileContent()
t.header = h
t.body = b
return t
[docs]
class PntsHeader(TileHeader):
BYTELENGTH = 28
def __init__(self):
self.type = TileType.POINTCLOUD
self.magic_value = b"pnts"
self.version = 1
self.tile_byte_length = 0
self.ft_json_byte_length = 0
self.ft_bin_byte_length = 0
self.bt_json_byte_length = 0
self.bt_bin_byte_length = 0
[docs]
def to_array(self):
header_arr = np.frombuffer(self.magic_value, np.uint8)
header_arr2 = np.array([self.version,
self.tile_byte_length,
self.ft_json_byte_length,
self.ft_bin_byte_length,
self.bt_json_byte_length,
self.bt_bin_byte_length], dtype=np.uint32)
return np.concatenate((header_arr, header_arr2.view(np.uint8)))
[docs]
def sync(self, body):
"""
Allow to synchronize headers with contents.
"""
# extract array
fth_arr = body.feature_table.header.to_array()
ftb_arr = body.feature_table.body.to_array()
# sync the tile header with feature table contents
self.tile_byte_length = (len(fth_arr) + len(ftb_arr)
+ PntsHeader.BYTELENGTH)
self.ft_json_byte_length = len(fth_arr)
self.ft_bin_byte_length = len(ftb_arr)
[docs]
@staticmethod
def from_array(array):
"""
Parameters
----------
array : numpy.array
Returns
-------
h : TileHeader
"""
h = PntsHeader()
if len(array) != PntsHeader.BYTELENGTH:
raise RuntimeError("Invalid header length")
h.magic_value = "pnts"
h.version = struct.unpack("i", array[4:8])[0]
h.tile_byte_length = struct.unpack("i", array[8:12])[0]
h.ft_json_byte_length = struct.unpack("i", array[12:16])[0]
h.ft_bin_byte_length = struct.unpack("i", array[16:20])[0]
h.bt_json_byte_length = struct.unpack("i", array[20:24])[0]
h.bt_bin_byte_length = struct.unpack("i", array[24:28])[0]
h.type = TileType.POINTCLOUD
return h
[docs]
class PntsBody(TileBody):
def __init__(self):
self.feature_table = FeatureTable()
# TODO : self.batch_table = BatchTable()
[docs]
@staticmethod
def from_array(th, array):
"""
Parameters
----------
th : TileHeader
array : numpy.array
Returns
-------
b : TileBody
"""
# build feature table
ft_len = th.ft_json_byte_length + th.ft_bin_byte_length
ft_arr = array[0:ft_len]
ft = FeatureTable.from_array(th, ft_arr)
# build batch table
# bt_len = th.bt_json_byte_length + th.bt_bin_byte_length
# bt_arr = array[ft_len:ft_len+ba_len]
# bt = BatchTable.from_array(th, bt_arr)
# build tile body with feature table
b = PntsBody()
b.feature_table = ft
# b.batch_table = bt
return b