2025年9月30日火曜日

長崎市の点群データをPotreeで表示しAPEXアプリケーションに埋め込む

Oracle Corporationの製品チームはAskTOM Office Hoursというプログラムのもと、定期的に製品の機能などを紹介するオンライン・セミナーを開いています。最近、Oracle Spatialのチームの製品マネージャが、Oracle DatabaseでLiDARデータを扱う手順を紹介していました。

Getting started working with LiDAR Data
このセミナーで使用しているスクリプトは以下より参照できます。

Getting started working with LiDAR Data
このセミナーで使用しているスクリプトは以下より参照できます。

LAS/LAZ形式でファイルに保存されているLiDARデータをOracle Databaseにロードし、パッケージSDO_PC_PKGなどを呼び出して処理する手順を紹介するといった内容です。

この方面の初心者にはハードルが高かったので、データベースにロードして作業を行う前に、日本でオープンデータとして入手できるLAS/LAZ形式の点群データを見つけて、APEXアプリケーションに表示してみることにしました。

長崎市よりLAS形式のオープンデータが公開されています。
この中の長崎駅が含まれる地点(01KE9821)のデータをダウンロードして、Potreeで表示することにします。ライセンスはクリエィティブ・コモンズ・ライセンス表示 4.0 国際 です。データをダウンロードすることで、利用規約に同意したと見做されます。


選択した点群データは01KE9821.zipとしてダウンロードされます。このファイルを解凍すると、01ke9821_org.lasが作成されます。このLAS形式のデータをPotreeで表示します。

Potreeで表示するため、LAS形式のデータをPotreeで扱える形式に変換する必要があります。この作業を実施するためにPotreeConverterがあります。ARM64のmacOS向けのPotreeConverterのバイナリが無かったので、最初にPotreeConverterを作成します。

PotreeConverterのコンテナ・イメージを作成するDockerfileがあったので、それを元にmacOSで動作するコンテナを作成します。

作業ディレクトリPointCloudを作成し、そこに移動して作業を行います。

mkdir PointCloud
cd PointCloud

% mkdir PointCloud

% cd PointCloud

PointCloud % 


Christian Vadalàさん作成のDockerfileのあるリポジトリをクローンして、コンテナ・イメージをビルドします。

git clone https://github.com/chrvadala/potree-converter-docker.git
cd potree-converter-docker
podman build -t potreeconverter .


PointCloud % git clone https://github.com/chrvadala/potree-converter-docker.git

Cloning into 'potree-converter-docker'...

remote: Enumerating objects: 31, done.

remote: Counting objects: 100% (13/13), done.

remote: Compressing objects: 100% (9/9), done.

remote: Total 31 (delta 4), reused 12 (delta 4), pack-reused 18 (from 1)

Receiving objects: 100% (31/31), 5.54 KiB | 5.54 MiB/s, done.

Resolving deltas: 100% (8/8), done.

PointCloud % cd potree-converter-docker 

potree-converter-docker % podman build -t potreeconverter .

STEP 1/10: FROM ubuntu:20.04

STEP 2/10: MAINTAINER cvdlab

--> Using cache 189a5fd30ee23d507d39c3ee3fd05de66f76bb20ad493a8b3f30530779101e7f

--> 189a5fd30ee2

STEP 3/10: VOLUME ["/input", "/output"]

--> Using cache a0a14fadf0b388b7419bd2bd60bd25f878c1fd12ffa76522de265a35f56818ca

--> a0a14fadf0b3

STEP 4/10: ENV DEBIAN_FRONTEND=noninteractive

--> Using cache fb1ccb4708d30e13687c4b41e3ee927195d5e4d650fae445f4c8af3d36c8e7f1

--> fb1ccb4708d3

STEP 5/10: RUN apt-get update && apt-get install -y libtiff-dev libgeotiff-dev libgdal-dev libboost-system-dev libboost-thread-dev libboost-filesystem-dev libboost-program-options-dev libboost-regex-dev libboost-iostreams-dev libtbb-dev git cmake build-essential wget

Get:1 http://ports.ubuntu.com/ubuntu-ports focal InRelease [265 kB]

Get:2 http://ports.ubuntu.com/ubuntu-ports focal-updates InRelease [128 kB]

Get:3 http://ports.ubuntu.com/ubuntu-ports focal-backports InRelease [128 kB]

Get:4 http://ports.ubuntu.com/ubuntu-ports focal-security InRelease [128 kB]

Get:5 http://ports.ubuntu.com/ubuntu-ports focal/main arm64 Packages [1234 kB]

Get:6 http://ports.ubuntu.com/ubuntu-ports focal/restricted arm64 Packages [1317 B]

Get:7 http://ports.ubuntu.com/ubuntu-ports focal/universe arm64 Packages [11.1 MB]

Get:8 http://ports.ubuntu.com/ubuntu-ports focal/multiverse arm64 Packages [139 kB]

Get:9 http://ports.ubuntu.com/ubuntu-ports focal-updates/restricted arm64 Packages [82.9 kB]


[中略]


[ 98%] Building C object Converter/libs/brotli/CMakeFiles/brotlidec.dir/c/dec/state.c.o

[100%] Linking C shared library libbrotlidec.so

[100%] Built target brotlidec

--> 89ff00cc013c

STEP 9/10: WORKDIR /opt/PotreeConverter/build

--> 971f5d5068c6

STEP 10/10: ENTRYPOINT ["./PotreeConverter"]

COMMIT potreeconverter

--> 34a6fed88e28

Successfully tagged localhost/potreeconverter:latest

34a6fed88e28dee830f1c725ba77a7f87493ea9872b5d097583b89e512b83673

potree-converter-docker % 


ビルドが正常に終了すると、コンテナ・イメージとしてpotreeconverterが作成されます。

podman image ls potreeconverter

potree-converter-docker % podman image ls potreeconverter

REPOSITORY                 TAG         IMAGE ID      CREATED         SIZE

localhost/potreeconverter  latest      34a6fed88e28  34 seconds ago  1.38 GB

potree-converter-docker % 


作業ディレクトリに戻ります。

cd ..

potree-converter-docker % cd ..

PointCloud % 


変換前のLASファイルを配置するディレクトリとしてinput、変換後のPotreeデータを配置するディレクトリとしてoutputを作成します。

mkdir input
mkdir output

PointCloud % mkdir input 

PointCloud % mkdir output

PointCloud % 


ディレクトリinputの下に長崎市のオープンデータ01ke9821_org.lasを配置します。作業ディレクトリに01KE9821.zipを配置します。

unzip 01KE9821.zip
mv 01ke9821_org.las input

PointCloud % unzip 01KE9821.zip 

Archive:  01KE9821.zip

  inflating: 01ke9821_org.las        

PointCloud % mv 01ke9821_org.las input

PointCloud % 


PotreeConverterを実行し、ディレクトリoutput以下にPotree向けのデータを出力します。

podman run --rm -v $PWD/input:/input -v $PWD/output:/output potreeconverter PotreeConverter /input/01ke9821_org.las -o /output -p 01ke9821_org

PointCloud % podman run --rm -v $PWD/input:/input -v $PWD/output:/output potreeconverter PotreeConverter /input/01ke9821_org.las -o /output -p 01ke9821_org

#threads: 16

#paths: 1

WARNING: scale/offset/bounding box were adjusted. new scale: 9.3131698668002968e-07, 6.9849099963903408e-07, 9.6589326858520511e-08, new offset: 34000, -27750, -2.8069999999999999


output attributes: 

name                              offset    size

================================================

position                               0      12

intensity                             12       2

return number                         14       1

number of returns                     15       1

classification                        16       1

scan angle rank                       17       1

user data                             18       1

point source id                       19       2

rgb                                   21       6

================================================

                                              27

================================================

cubicAABB: {

"min": [34000.000000, -27750.000000, -2.807000],

"max": [34999.994000, -26750.006000, 997.187000],

"size": [999.994000, 999.994000, 999.994000]

}

#points: 18'175'075

total file size: 450.7 MB

ERROR(main.cpp:453): filesystem error: cannot copy: Permission denied [/opt/PotreeConverter/build/resources/page_template] [/output]

target directory: '/output/pointclouds/01ke9821_org'


=======================================

=== COUNTING                           

=======================================

tStartTaskAssembly: 0.000206s

countPointsInCells: 0.224844s

finished counting in 0s

=======================================

createLUT: 0.020166s


=======================================

=== CREATING CHUNKS                    

=======================================

distributePoints0: 0.000383s

distributePoints1: 0.000388s

WARNING: scale/offset/bounding box were adjusted. new scale: 9.3131698668002968e-07, 6.9849099963903408e-07, 9.6589326858520511e-08, new offset: 34000, -27750, -2.8069999999999999

finished creating chunks in 0s

=======================================


=======================================

=== INDEXING                           

=======================================


[67%, 1s], [INDEXING: 0%, duration: 0s, throughput: nanMPs][RAM: 3.5GB (highest 3.5GB), CPU: 93%]

sampling: 1.209807s

flushing: 1.222069s

metadata & hierarchy: 1.338338s

deleting temporary files


=======================================

=== STATS                              

=======================================

#points:               18'175'075

#input files:          1

sampling method:       poisson

chunk method:          LASZIP

input file size:       0.4GB

duration:              2.013s

throughput (MB/s)      224MB

throughput (points/s)  9.0M

output location:       /output/pointclouds/01ke9821_org

duration(chunking-count): 0.225

duration(chunking-distribute): 0.333

duration(chunking-total): 0.560

duration(indexing): 1.339

PointCloud % 


途中でfilesystem errorが発生していますが、特に原因は調べていません。

ディレクトリoutput以下に、01ke9821_org.htmlが作成されています。

PointCloud % ls output

01ke9821_org.html libs pointclouds

PointCloud % 


Potreeをホストする静的なサイトを、nginxで作成します。

Potreeのリポジトリをクローンしたのち、ビルドします。

git clone https://github.com/potree/potree.git
cd potree
npm install
npm run build

PointCloud % git clone https://github.com/potree/potree.git

Cloning into 'potree'...

remote: Enumerating objects: 19049, done.

remote: Total 19049 (delta 0), reused 0 (delta 0), pack-reused 19049 (from 1)

Receiving objects: 100% (19049/19049), 130.08 MiB | 8.40 MiB/s, done.

Resolving deltas: 100% (10945/10945), done.

PointCloud % cd potree

potree % npm install

npm warn deprecated ini@1.3.5: Please update to ini >=1.3.6 to avoid a prototype pollution issue

npm warn deprecated urix@0.1.0: Please see https://github.com/lydell/urix#deprecated


[中略]


To address all issues (including breaking changes), run:

  npm audit fix --force


Run `npm audit` for details.

potree % npm run build


> potree@1.8.0 build

> gulp build pack


[17:21:34] Using gulpfile ~/Documents/PointCloud/potree/gulpfile.js

[17:21:34] Starting 'build'...

[17:21:34] Starting 'pack'...

[17:21:34] Starting 'workers'...

[17:21:34] Starting 'lazylibs'...

[17:21:34] Starting 'shaders'...


[中略]


src/modules/loader/2.0/DecoderWorker_brotli.js → build/potree/workers/2.0/DecoderWorker_brotli.js...

created build/potree/workers/2.0/DecoderWorker_brotli.js in 28ms


potree % 


Potreeのビルドができたら、作業ディレクトリに戻ります。

cd ..

potree % cd ..

PointCloud % 


nginxの設定ファイルをdefault.confとして作成します。
server {
  listen 80;
  server_name _;
  root /usr/share/nginx/html;
  index index.html;

  # Potree の build を /libs/ 配下に見せる
  location /libs/ {
    alias /opt/potree/libs/;
  }
  # CORSを許可。
  add_header Access-Control-Allow-Origin *;
}
nginxをコンテナとして実行します。

ホーム・ディレクトリ/usr/share/nginx/htmlにPotree向けのデータを出力したディレクトリoutputをマウントし、Potree本体が含まれる/libs/以下にpotree/buildをマウントします。

ホスト・ポートの8080で接続を待ち受けるように、コンテナを実行しています。

podman run --rm -p 8080:80 \
-v $PWD/output:/usr/share/nginx/html:ro \
-v $PWD/potree/build:/opt/potree/libs:ro \
-v $PWD/default.conf:/etc/nginx/conf.d/default.conf:ro \
arm64v8/nginx:stable-alpine


PointCloud % podman run --rm -p 8080:80 \

-v $PWD/output:/usr/share/nginx/html:ro \

-v $PWD/potree/build:/opt/potree/libs:ro \

-v $PWD/default.conf:/etc/nginx/conf.d/default.conf:ro \

arm64v8/nginx:stable-alpine

/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration

/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/

/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh

10-listen-on-ipv6-by-default.sh: info: can not modify /etc/nginx/conf.d/default.conf (read-only file system?)

/docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh

/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh

/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh

/docker-entrypoint.sh: Configuration complete; ready for start up

2025/09/30 08:29:58 [notice] 1#1: using the "epoll" event method

2025/09/30 08:29:58 [notice] 1#1: nginx/1.28.0

2025/09/30 08:29:58 [notice] 1#1: built by gcc 14.2.0 (Alpine 14.2.0) 

2025/09/30 08:29:58 [notice] 1#1: OS: Linux 6.11.3-200.fc40.aarch64

2025/09/30 08:29:58 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 524288:524288

2025/09/30 08:29:58 [notice] 1#1: start worker processes

2025/09/30 08:29:58 [notice] 1#1: start worker process 16

2025/09/30 08:29:58 [notice] 1#1: start worker process 17

2025/09/30 08:29:58 [notice] 1#1: start worker process 18

2025/09/30 08:29:58 [notice] 1#1: start worker process 19

2025/09/30 08:29:58 [notice] 1#1: start worker process 20

2025/09/30 08:29:58 [notice] 1#1: start worker process 21

2025/09/30 08:29:58 [notice] 1#1: start worker process 22

2025/09/30 08:29:58 [notice] 1#1: start worker process 23

2025/09/30 08:29:58 [notice] 1#1: start worker process 24

2025/09/30 08:29:58 [notice] 1#1: start worker process 25

2025/09/30 08:29:58 [notice] 1#1: start worker process 26

2025/09/30 08:29:58 [notice] 1#1: start worker process 27

2025/09/30 08:29:58 [notice] 1#1: start worker process 28

2025/09/30 08:29:58 [notice] 1#1: start worker process 29

2025/09/30 08:29:58 [notice] 1#1: start worker process 30

2025/09/30 08:29:58 [notice] 1#1: start worker process 31


以上で、nginxが起動しました。

ブラウザからnginxにアクセスし、長崎市の点群データを表示します。

http://localhost:8080/01ke9821_org.html

長崎駅近辺の点群データがPotreeで表示されます。


APEXアプリケーションへの組み込みには、タイプURLのリージョンを使用します。


リージョンの属性設定で、URLhttp://localhost:8080/01ke9821_org.html組み入モードIFrameIFrame属性としてwidth="100%"   height="1000px"   style="border:none;"を設定します。


APEXアプリケーションには以下のように点群データが表示されます。


以上で作業は完了です。

今回の記事は以上になります。