Skip to content

Commit 4324407

Browse files
authored
Merge pull request #55 from eukarya-inc/dev/py3dtiles-beta
#54 supports new features and bump 0.0.13
2 parents c8b629b + 8328823 commit 4324407

12 files changed

+110
-80
lines changed

.vscode/settings.json

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
{
2-
"python.formatting.provider": "black",
3-
"editor.formatOnSave": true
2+
"[python]": {
3+
"editor.defaultFormatter": "ms-python.black-formatter",
4+
"editor.formatOnSave": true
5+
}
46
}

dev-requirements.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ pluggy==1.0.0
4040
plyfile==1.0.1
4141
psutil==5.9.5
4242
psycopg2-binary==2.9.7
43-
py3dtiles==6.0.0
43+
git+https://gitlab.com/Oslandia/py3dtiles.git@489289d2f7310fbcb8e95710e250d893999adf5d#egg=py3dtiles
4444
Pygments==2.15.1
4545
pyproj==3.6.1
4646
pyproject_hooks==1.0.0

doc/plateauutils.citygmlfinder.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ plateauutils.citygmlfinder パッケージ
22
======================================
33

44
plateauutils.citygmlfinder.from_reearth_cms モジュール
5-
--------------------------------------------------
5+
-------------------------------------------------------
66

77
.. automodule:: plateauutils.citygmlfinder.from_reearth_cms
88
:members:

plateauutils/abc/numpy_tile_parser.py

+17-6
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,28 @@ def _parse_tile(self):
1717
tile_list = self.__make_tile_list()
1818
lons = [] # 経度
1919
lats = [] # 緯度
20-
maps = [] # 標高
20+
dems = [] # 標高
21+
classifications = [] # 属性値
2122
# それぞれのタイルをパース
2223
for tile in tile_list:
2324
t = np.load(tile)
2425
lons.append(t["lons"])
2526
lats.append(t["lats"])
26-
map = t["map"]
27-
# 標高がnanの場合は0にする
28-
map[np.isnan(map)] = 0
29-
maps.append(map)
30-
return np.concatenate(lons), np.concatenate(lats), np.concatenate(maps)
27+
dems.append(t["dem"])
28+
classifications.append(t["classification"])
29+
# np.arrayに変換
30+
np_lons, np_lats, np_dems, np_classifications = (
31+
np.concatenate(lons),
32+
np.concatenate(lats),
33+
np.concatenate(dems),
34+
np.concatenate(classifications),
35+
)
36+
# nanを除去
37+
np_lons = np_lons[~np.isnan(np_dems)]
38+
np_lats = np_lats[~np.isnan(np_dems)]
39+
np_classifications = np_classifications[~np.isnan(np_dems)]
40+
np_dems = np_dems[~np.isnan(np_dems)]
41+
return np_lons, np_lats, np_dems, np_classifications
3142

3243
def __make_tile_list(self):
3344
"""タイルのリストを作成するメソッド"""

plateauutils/flood_converter/flood_to_3dtiles.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def convert(
2727
"""
2828
# xyzファイルを作成
2929
xyz = FloodToXyz(path).parse()
30-
tmp = tempfile.mktemp(suffix=".xyz")
30+
tmp = tempfile.mktemp(suffix=".csv")
3131
# 一時ファイルにxyzを書き込み
3232
with open(tmp, "w") as f:
3333
f.write(xyz)

plateauutils/flood_converter/flood_to_png.py

+57-61
Original file line numberDiff line numberDiff line change
@@ -26,49 +26,50 @@ def parse(self, output_dir: str = ""):
2626
output_dir : str
2727
pngの出力先
2828
"""
29-
# lontitude, latitude, altitudeを取得
30-
lons, lats, maps = self._parse_tile()
31-
# storeを作成
32-
store = Store()
33-
# storeのaddメソッドをベクトル化
34-
vfunc = np.vectorize(store.add)
35-
# storeにlontitude, latitude, altitudeを追加
36-
vfunc(lons, lats, maps)
37-
# pngを書き出す
38-
writer = PngWriter(output_dir, 15)
39-
writer.setStore(store)
40-
writer.write()
29+
# lontitude, latitude, classificationsを取得
30+
lons, lats, _, classifications = self._parse_tile()
31+
# ズームレベル8から15までのpngを作成
32+
for zoom in range(8, 16):
33+
# storeを作成
34+
store = Store(zoom)
35+
# storeのaddメソッドをベクトル化
36+
vfunc = np.vectorize(store.add)
37+
# storeにlontitude, latitude, classificationsを追加
38+
vfunc(lons, lats, classifications)
39+
# pngを書き出す
40+
writer = PngWriter(output_dir, zoom)
41+
writer.setStore(store)
42+
writer.write()
4143

4244

4345
class Store(object):
4446
"""タイルの座標及び標高を保持するクラス"""
4547

46-
def __init__(self):
47-
self.zoom = 15
48+
def __init__(self, zoom):
49+
self.zoom = zoom
4850
self.storage = dict()
4951

50-
def add(self, x, y, z):
52+
def add(self, x, y, classification):
5153
"""タイルの座標及び標高を格納するメソッド"""
52-
longitude, latitude, altitude = x, y, z
54+
longitude, latitude = x, y
5355
# 座標からタイルの座標とタイル内の座標を取得
5456
x, y, pos_x, pos_y = self._coordinate_to_position(longitude, latitude)
5557
# storageに格納
56-
self._insert(x, y, pos_x, pos_y, altitude)
58+
self._insert(x, y, pos_x, pos_y, classification)
5759

58-
def _insert(self, x, y, pos_x, pos_y, altitude):
60+
def _insert(self, x, y, pos_x, pos_y, classification):
5961
# keyがstorageに存在する場合はその値を取得
6062
key = (x, y)
6163
if key in self.storage.keys():
6264
array = self.storage[key]
6365
else:
6466
# 存在しない場合は256*256の配列を作成
65-
array = np.zeros((256, 256))
66-
array.fill(-np.inf)
67+
array = np.zeros((256, 256), dtype=np.int32)
6768
self.storage[key] = array
6869
# 標高を格納
6970
current = array[pos_x][pos_y]
70-
if current < altitude:
71-
array[pos_x][pos_y] = altitude
71+
if current < classification:
72+
array[pos_x][pos_y] = classification
7273
self.storage[key] = array
7374

7475
def _coordinate_to_position(self, longitude, latitude):
@@ -157,55 +158,50 @@ def _write(self, x, y, value):
157158
sys.exit(-1)
158159
# 標高をpngに変換
159160
dt = np.dtype(
160-
{"names": ["r", "g", "b"], "formats": [np.uint8, np.uint8, np.uint8]}
161+
{
162+
"names": ["r", "g", "b", "a"],
163+
"formats": [np.uint8, np.uint8, np.uint8, np.uint8],
164+
}
161165
)
162166
converted1 = np.array(
163-
[tuple(self._dem_to_png(v)) for v in value.reshape(value.size)], dtype=dt
167+
[tuple(self._classification_to_png(v)) for v in value.reshape(value.size)],
168+
dtype=dt,
164169
)
165170
converted2 = converted1.reshape(value.shape)
166171
filename = f"{self.directory}/{self.zoom}/{x}/{y}.png"
167172
width = 256
168-
img = Image.new("RGB", (width, width), (128, 0, 0))
173+
img = Image.new("RGBA", (width, width), (128, 0, 0, 0))
169174
draw = ImageDraw.Draw(img)
170175
for i in range(0, width):
171176
for j in range(0, width):
172177
p = converted2[i][j]
173-
draw.point([(i, j)], (int(p[0]), int(p[1]), int(p[2])))
178+
draw.point([(i, j)], (int(p[0]), int(p[1]), int(p[2]), int(p[3])))
174179
img.save(filename)
175180

176-
def _dem_to_png(self, dem):
177-
# 標高をPNGのRGBに変換するメソッド
178-
# 内容が入っていなかったら白色
179-
if dem == -np.inf:
180-
return (0xFF, 0xFF, 0xFF)
181-
# 標高に応じて色を変更
182-
if dem > 20:
183-
# 185 26 248
184-
return (0xB9, 0x1A, 0xF8)
185-
if dem > 10:
186-
# 169 8 91
187-
return (0xA9, 0x08, 0x5B)
188-
if dem > 5:
189-
# 253 35 21
190-
return (0xFD, 0x23, 0x15)
191-
if dem > 4:
192-
# 236 106 141
193-
return (0xEC, 0x6A, 0x8D)
194-
if dem > 3:
195-
# 254 115 117
196-
return (0xFE, 0x73, 0x75)
197-
if dem > 2:
198-
# 236 182 182
199-
return (0xEC, 0xB6, 0xB6)
200-
if dem > 1:
201-
# 255 141 36
202-
return (0xFF, 0x8D, 0x24)
203-
if dem > 0.3:
204-
# 255 225 53
205-
return (0xFF, 0xE1, 0x35)
206-
if dem > 0.01:
207-
# 48 254 55
208-
return (0x30, 0xFE, 0x37)
209-
# 0.01以下は白色
181+
def _classification_to_png(self, classification):
182+
# 属性をPNGのRGBに変換するメソッド
183+
# 内容が入っていなかったら透明色
184+
if classification == 0:
185+
return (0xFF, 0xFF, 0xFF, 0x00)
186+
# 属性に応じて色を変更
187+
if classification == 6:
188+
# 220 122 220
189+
return (0xDC, 0x7A, 0xDC, 0xFF)
190+
if classification == 5:
191+
# 242 133 201
192+
return (0xF2, 0x85, 0xC9, 0xFF)
193+
if classification == 4:
194+
# 255 145 145
195+
return (0xFF, 0x91, 0x91, 0xFF)
196+
if classification == 3:
197+
# 255 183 183
198+
return (0xFF, 0xB7, 0xB7, 0xFF)
199+
if classification == 2:
200+
# 255 216 192
201+
return (0xFF, 0xD8, 0xC0, 0xFF)
202+
if classification == 1:
203+
# 247 245 169
204+
return (0xF7, 0xF5, 0xA9, 0xFF)
205+
# 例外は透明色
210206
# 255 255 255
211-
return (0xFF, 0xFF, 0xFF)
207+
return (0xFF, 0xFF, 0xFF, 0x00)

plateauutils/flood_converter/flood_to_xyz.py

+21-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import numpy as np
12
import pandas as pd
23
from plateauutils.abc.numpy_tile_parser import NumpyTileParser
34

@@ -16,7 +17,23 @@ def __init__(self, path: str = ""):
1617

1718
def parse(self):
1819
"""洪水浸水域をxyzに変換するメソッド"""
19-
lons, lats, maps = self._parse_tile()
20-
# xyzファイルを作成, 並びはlatitude, longitude, altitude
21-
df = pd.DataFrame({"lat": lats, "lon": lons, "map": maps})
22-
return df.to_csv(index=False, header=False, sep=" ")
20+
lons, lats, dems, classifications = self._parse_tile()
21+
# IRGB値を作成
22+
i_values = np.ones_like(dems, dtype=np.int32) * 1
23+
r_values = np.ones_like(dems, dtype=np.int32) * 0
24+
g_values = np.ones_like(dems, dtype=np.int32) * 191
25+
b_values = np.ones_like(dems, dtype=np.int32) * 255
26+
# xyzファイルを作成, 並びはlatitude, longitude, altitude, i, r, g, b, classification
27+
df = pd.DataFrame(
28+
{
29+
"lat": lats,
30+
"lon": lons,
31+
"dem": dems,
32+
"i": i_values,
33+
"r": r_values,
34+
"g": g_values,
35+
"b": b_values,
36+
"classification": classifications,
37+
}
38+
)
39+
return df.to_csv(index=False, header=True, sep=" ")
Binary file not shown.

plateauutils/flood_converter/tests/test_flood_to_3dtiles.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ def test_convert(tmp_dir: str):
2222
assert Path(tmp_dir, "tileset.json").exists()
2323
assert Path(tmp_dir, "r.pnts").exists()
2424
tileset_path = tmp_dir / "tileset.json"
25-
assert 256 * 256 == number_of_points_in_tileset(tileset_path)
25+
assert 62615 == number_of_points_in_tileset(tileset_path)

plateauutils/flood_converter/tests/test_flood_to_xyz.py

+1
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ def test_convert(tmp_dir: str):
1818
flood_to_png = FloodToPng(str(DATA_DIRECTORY))
1919
flood_to_png.parse(output_dir=str(tmp_dir))
2020
assert Path(tmp_dir, "15/28264/13160.png").exists()
21+
assert Path(tmp_dir, "8/220/102.png").exists()

pyproject.toml

+5-2
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ classifiers = [
1111
"Development Status :: 2 - Pre-Alpha",
1212
"Programming Language :: Python :: 3",
1313
]
14-
version = "0.0.12"
14+
version = "0.0.13"
1515
dependencies = [
1616
"click",
1717
"numpy",
1818
"pandas",
1919
"Pillow",
20-
"py3dtiles",
20+
"py3dtiles @ git+https://gitlab.com/Oslandia/py3dtiles.git@489289d2f7310fbcb8e95710e250d893999adf5d",
2121
"pyproj",
2222
"requests",
2323
"reearthcmsapi",
@@ -34,6 +34,9 @@ keywords = ['plateau']
3434
[tool.hatch.build]
3535
exclude = ["tests/*"]
3636

37+
[tool.hatch.metadata]
38+
allow-direct-references = true
39+
3740
[project.urls]
3841
"Homepage" = "https://eukarya-inc.github.io/plateauutils/"
3942
"Bug Reports" = "https://github.com/eukarya-inc/plateauutils/issues"

requirements.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ reearthcmsapi==0.0.3
33
numpy==1.22.4
44
pandas==2.1.0
55
Pillow==10.0.1
6-
py3dtiles==6.0.0
6+
git+https://gitlab.com/Oslandia/py3dtiles.git@489289d2f7310fbcb8e95710e250d893999adf5d#egg=py3dtiles
77
pyproj==3.6.1
88
requests==2.31.0
99
shapely==2.0.1

0 commit comments

Comments
 (0)