A wrapper for hmm
Project description
pydelatin
A Python wrapper of hmm
(of which Delatin is a port) for fast terrain mesh generation.
A screenshot of Glacier National Park taken from the demo. The mesh
is created using pydelatin
, encoded using
quantized-mesh-encoder
, served on-demand using
dem-tiler
, and rendered with deck.gl.
Install
With pip:
pip install pydelatin
or with Conda:
conda install -c conda-forge pydelatin
On Windows, installing via Conda is strongly recommended.
If installing with pip on Windows, glm
is a prerequisite for building
from source. Open an issue if you'd like to help package binary wheels for
Windows.
Using
Example
from pydelatin import Delatin
tin = Delatin(terrain, width, height)
# Mesh vertices
tin.vertices
# Mesh triangles
tin.triangles
API
The API is similar to that of hmm
.
Additionally I include a helper function: decode_ele
, to decode a Mapbox
Terrain RGB or Terrarium PNG array to elevations.
Delatin
Arguments
arr
(numpyndarray
): data array. If a 2D array, dimensions are expected to be (height, width). If a 1D array, height and width parameters must be passed, and the array is assumed to be in C order.height
(int
, default:None
): height of array; required when arr is not 2Dwidth
(int
, default:None
): width of array; required when arr is not 2Dz_scale
(float
, default:1
): z scale relative to x & yz_exag
(float
, default:1
): z exaggerationmax_error
(float
, default:0.001
): maximum triangulation errormax_triangles
(int
, default:None
): maximum number of trianglesmax_points
(int
, default:None
): maximum number of verticesbase_height
(float
, default:0
): solid base heightlevel
(bool
, default:False
): auto level input to full grayscale rangeinvert
(bool
, default:False
): invert heightmapblur
(int
, default:0
): gaussian blur sigmagamma
(float
, default:0
): gamma curve exponentborder_size
(int
, default:0
): border size in pixelsborder_height
(float
, default:1
): border z height
Attributes
vertices
(ndarray
of shape(-1, 3)
): the interleaved 3D coordinates of each vertex, e.g.[[x0, y0, z0], [x1, y1, z1], ...]
.triangles
(ndarray
of shape(-1, 3)
): represents indices within thevertices
array. So[0, 1, 3, ...]
would use the first, second, and fourth vertices within thevertices
array as a single triangle.error
(float
): the maximum error of the mesh.
util.rescale_positions
A helper function to rescale the vertices
output to a new bounding box.
Returns an ndarray
of shape (-1, 3)
with positions rescaled. Each row
represents a single 3D point.
Arguments
vertices
: (np.ndarray
) vertices output from Delatinbounds
: (Tuple[float]
) linearly rescale position values to this extent. Expected to be[minx, miny, maxx, maxy]
.flip_y
: (bool
, defaultFalse
) Flip y coordinates. Can be useful since images' coordinate origin is in the top left.
Saving to mesh formats
Quantized Mesh
A common mesh format for the web is the Quantized Mesh
format, which is supported in Cesium and deck.gl (via
loaders.gl). You can use
quantized-mesh-encoder
to save in this format:
import quantized_mesh_encoder
from pydelatin import Delatin
from pydelatin.util import rescale_positions
tin = Delatin(terrain, max_error=30)
vertices, triangles = tin.vertices, tin.triangles
# Rescale vertices linearly from pixel units to world coordinates
rescaled_vertices = rescale_positions(vertices, bounds)
with open('output.terrain', 'wb') as f:
quantized_mesh_encoder.encode(f, rescaled_vertices, triangles)
Meshio
Alternatively, you can save to a variety of mesh formats using
meshio
:
from pydelatin import Delatin
import meshio
tin = Delatin(terrain, max_error=30)
vertices, triangles = tin.vertices, tin.triangles
cells = [("triangle", triangles)]
mesh = meshio.Mesh(vertices, cells)
# Example output format
# Refer to meshio documentation
mesh.write('foo.vtk')
Martini
or Delatin
?
Two popular algorithms for terrain mesh generation are the "Martini"
algorithm, found in the JavaScript martini
library and the Python
pymartini
library, and the "Delatin" algorithm, found in the
C++ hmm
library, this Python pydelatin
library, and the JavaScript
delatin
library.
Which to use?
For most purposes, use pydelatin
over pymartini
. A good breakdown from a
Martini issue:
Martini:
- Only works on square 2^n+1 x 2^n+1 grids.
- Generates a hierarchy of meshes (pick arbitrary detail after a single run)
- Optimized for meshing speed rather than quality.
Delatin:
- Works on arbitrary raster grids.
- Generates a single mesh for a particular detail.
- Optimized for quality (as few triangles as possible for a given error).
Benchmark
The following uses the same dataset as the pymartini
benchmarks, a 512x512 pixel heightmap of Mt. Fuji.
For the 30-meter mesh, pydelatin
is 25% slower than pymartini
, but the mesh
is much more efficient: it has 40% fewer vertices and triangles.
pydelatin
is 4-5x faster than the JavaScript delatin
package.
Python
git clone https://github.com/kylebarron/pydelatin
cd pydelatin
pip install '.[test]'
python bench.py
mesh (max_error=30m): 27.322ms
vertices: 5668, triangles: 11140
mesh (max_error=1m): 282.946ms
mesh (max_error=2m): 215.839ms
mesh (max_error=3m): 163.424ms
mesh (max_error=4m): 127.203ms
mesh (max_error=5m): 106.596ms
mesh (max_error=6m): 91.868ms
mesh (max_error=7m): 82.572ms
mesh (max_error=8m): 74.335ms
mesh (max_error=9m): 65.893ms
mesh (max_error=10m): 60.999ms
mesh (max_error=11m): 55.213ms
mesh (max_error=12m): 54.475ms
mesh (max_error=13m): 48.662ms
mesh (max_error=14m): 47.029ms
mesh (max_error=15m): 44.517ms
mesh (max_error=16m): 42.059ms
mesh (max_error=17m): 39.699ms
mesh (max_error=18m): 37.657ms
mesh (max_error=19m): 36.333ms
mesh (max_error=20m): 34.131ms
JS (Node)
This benchmarks against the delatin
JavaScript module.
git clone https://github.com/kylebarron/pydelatin
cd test/bench_js/
yarn
wget https://raw.githubusercontent.com/mapbox/delatin/master/index.js
node -r esm bench.js
mesh (max_error=30m): 143.038ms
vertices: 5668
triangles: 11140
mesh (max_error=0m): 1169.226ms
mesh (max_error=1m): 917.290ms
mesh (max_error=2m): 629.776ms
mesh (max_error=3m): 476.958ms
mesh (max_error=4m): 352.907ms
mesh (max_error=5m): 290.946ms
mesh (max_error=6m): 240.556ms
mesh (max_error=7m): 234.181ms
mesh (max_error=8m): 188.273ms
mesh (max_error=9m): 162.743ms
mesh (max_error=10m): 145.734ms
mesh (max_error=11m): 130.119ms
mesh (max_error=12m): 119.865ms
mesh (max_error=13m): 114.645ms
mesh (max_error=14m): 101.390ms
mesh (max_error=15m): 100.065ms
mesh (max_error=16m): 96.247ms
mesh (max_error=17m): 89.508ms
mesh (max_error=18m): 85.754ms
mesh (max_error=19m): 79.838ms
mesh (max_error=20m): 75.607ms
License
This package wraps @fogleman's hmm
, a C++ library that is also
MIT-licensed.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Hashes for pydelatin-0.2.6-cp310-cp310-musllinux_1_1_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2b77c2b610e1ee7a174d99dbfaba39666e7232f4fe1ce2f8d69ffe1fbccda80d |
|
MD5 | fd680de52ef7e65af89d91b3042cbee2 |
|
BLAKE2b-256 | 95f75883107f7a245449bfc5165bcfa0dd52ca9f5a70905915e330f4a5ee8d10 |
Hashes for pydelatin-0.2.6-cp310-cp310-musllinux_1_1_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 26229ab720d7df9705c04faccf93219ef08f7baad3708bd60f0bd222e1b2813f |
|
MD5 | cac37b37b9b8f7769c868a06b4ead0ab |
|
BLAKE2b-256 | 167f3df9cfe82d11f3e80c6c7f6e16f535470fdcd9fb8c1ccb6699cf4f35ccae |
Hashes for pydelatin-0.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 3a0b03a7a9538f72293f0be6522c6b8b0c8a23b12e4d4fd14c8482cd911b721b |
|
MD5 | 3dc0c4ca0852e124c499bd80f778e267 |
|
BLAKE2b-256 | fc8bc26131d704897969cb17cb471ac69a66ae2b8810c15ea81387e4f087a5d2 |
Hashes for pydelatin-0.2.6-cp310-cp310-macosx_11_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 079ac8d293c7e5d18f151630a88fc09d59bfdc1aa976c2066dfa6e332d417669 |
|
MD5 | 253c0624c62aa2332e0c791a4ce9d74a |
|
BLAKE2b-256 | 32494fb294a4744f95d88879f041ea9877077c4d47fcce4dbd058d8e656887d5 |
Hashes for pydelatin-0.2.6-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2cd908b3f833348f11064d7950232985569f563cce3c9d4cc4a6c43c50519abb |
|
MD5 | 18052d60282a877ad51b1838f65b601a |
|
BLAKE2b-256 | 8e09f8675cd6f65a0684b16664c8f102422262930fd036c1186c788a004afe4c |
Hashes for pydelatin-0.2.6-cp310-cp310-macosx_10_9_universal2.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 87d90c7bc451cd47b4090c0b16423e71d2dd22991e65b498c77aa5537ef83ae7 |
|
MD5 | 0b095d1710893ec1fb8c781b97c67840 |
|
BLAKE2b-256 | ff457dca8f1939528998d16c296fe913f1ff4e470ffca6efdbc2ce2888d32578 |
Hashes for pydelatin-0.2.6-cp39-cp39-musllinux_1_1_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 7b5640a1d7e7ad484299d89f3c1d3f1e65f178b6505d797a59e55eaa2e19c791 |
|
MD5 | 3d94bb47bdb82fed49cff25f1596981d |
|
BLAKE2b-256 | 5a2fca45dbea844089444d4b9993bd51ad7fa93cc6e3e9266c6feb645aaedff5 |
Hashes for pydelatin-0.2.6-cp39-cp39-musllinux_1_1_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | ca5f26f330b09fd5d2adcd0a4e2ec0596479adb83b41e121dd8c336a41ed08c4 |
|
MD5 | 7f00b8fe425dcea45656bb5b0f27e7b8 |
|
BLAKE2b-256 | aa567caa9cc76b3d68743ec8bdd16ea6d204cd7432b36b8aa49abe7a6aaf959a |
Hashes for pydelatin-0.2.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 89c460bce9d7c0f548fabfd0f59d52cfcbdf4c9298e9b9eeea0425b38029cff0 |
|
MD5 | c2e9a8f7f8cf0a232782696e952bd1a5 |
|
BLAKE2b-256 | 1251fa29f6446ea17feb358696e0feb80f6ef8b51fc73bcb23fb0b6cb9419add |
Hashes for pydelatin-0.2.6-cp39-cp39-macosx_11_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | b96bcf9c060995474dbd73dea1c9d8b733075ef1909f3c5050903157050b0ed0 |
|
MD5 | 1d24a159bb42d8eef336a600cbc2a61c |
|
BLAKE2b-256 | a193884ff4a572c40cc8350c268274d7e246be7152e9ba1caaf107791da874dc |
Hashes for pydelatin-0.2.6-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 64e24bd52c9717dac29e1288a482797c210e3b597e96f2403893de00b62468e8 |
|
MD5 | 64728f8c04a1c42fb408991dc91d0f99 |
|
BLAKE2b-256 | cbfc5c4b26142386af4b441f182a90cbccb27480cf6d5e420312f12e972ccc0b |
Hashes for pydelatin-0.2.6-cp39-cp39-macosx_10_9_universal2.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | b1754c67d87fadc55a588710e939de24cc20ba1d50e71a4507cc391e40b5801b |
|
MD5 | 7cabf53711a87fd972c3a6d2cd763cc5 |
|
BLAKE2b-256 | e18be1c7b849a9d72cbdcccb86c6a3dd934a5fe703d9f4a65688e923c625f631 |
Hashes for pydelatin-0.2.6-cp38-cp38-musllinux_1_1_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 37307eb5128404a27ed5ebe827020d07b699b9db68dfbc844af7c3fad8407bba |
|
MD5 | d646ba95c5b1f2b1f28b0d6bc8a54784 |
|
BLAKE2b-256 | e768102b7e608ea378920435068ccfe0ef670c28c0148f7d29c9093baf8a102b |
Hashes for pydelatin-0.2.6-cp38-cp38-musllinux_1_1_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 0b59c0a18762e13e039f6dc229b0531f506ccfe89d101e73ab84d28f5447a412 |
|
MD5 | 95ad31e3239c1df95f3ecd8b52d7bd38 |
|
BLAKE2b-256 | 6404501cd50ddc1fcae13494e8555dc752f3ac38b5e0ece822985b7ed113773d |
Hashes for pydelatin-0.2.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | e10d9b9f8b6669b0750f02d98995ef6e2d55b64e2d8f726fe3ed4edbbc4010d5 |
|
MD5 | 0a7665dfe63b3b8ac155147c04d156d8 |
|
BLAKE2b-256 | 21cfff12377a51cfc5b4f8c8270885dc43022973c1565bdf693c900ce3f28499 |
Hashes for pydelatin-0.2.6-cp38-cp38-macosx_11_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 4ebd0aa64b94dbbc59f647f8788937ddc627270ab395cb7a081b3dce5d85d70b |
|
MD5 | 99ad8793be2017c7609a9de9a0bf8e67 |
|
BLAKE2b-256 | 247c9a51b5185a769eea45f5b4953e4c87cd1528543af7f9eb5fb1588217a736 |
Hashes for pydelatin-0.2.6-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 8ea0e8e24eff3f5dfcb9401bd30fb12c368b1dae165eca1bc88eb3070a8cf86b |
|
MD5 | 1971675d587b503d6ad3b89e13e17ee0 |
|
BLAKE2b-256 | 4f4c4a9047265ce8aa5903cac78e5df0f455b29e9b1a1e808b02513d3dad6226 |
Hashes for pydelatin-0.2.6-cp38-cp38-macosx_10_9_universal2.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 7b928ec454aae343094f28d56604a8edf75aa097949d0917a5b2da50766ee418 |
|
MD5 | 29a7d568a6138710eed8e6bd3d53e9af |
|
BLAKE2b-256 | 0520924737b13fdef7da6fa0cdc83df84566e9cc6fb65c05c6e1d0cf6f6cc63e |
Hashes for pydelatin-0.2.6-cp37-cp37m-musllinux_1_1_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 4f6d1fe1e10f3ceba486aaea3ceac11f4ff6e76fbd4f18390b91c575b4747582 |
|
MD5 | 5091651abdf7821b8a131d4c196121c4 |
|
BLAKE2b-256 | 4dfd1d16cd2f66f4c57f7fcad7f8d2b53e8d93d11708386358b4983957be7fbb |
Hashes for pydelatin-0.2.6-cp37-cp37m-musllinux_1_1_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | d72ba3fd05eceec920fc7a465adde2e5bd703867a814120fdcc7631b4cd8c50a |
|
MD5 | 05e2ace159866be10f3df8abd9405072 |
|
BLAKE2b-256 | 20786e5b7f6cbfebee304391cba469a1a40fccd8007b2dc63e91837ac06a1a5b |
Hashes for pydelatin-0.2.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | e7e0b78b36f30e5c0f16ef95b7b09a841132f7eb1521fee8e071654226820a61 |
|
MD5 | 97ab6337c8988b702b0cff7e28cc2be3 |
|
BLAKE2b-256 | 3b5103524b33d8bfbf0f4afbab1e370a77178e31b1e983d799715a43c08fc98d |
Hashes for pydelatin-0.2.6-cp37-cp37m-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5e9243af0558c0f3b6b14b2db0c988f09330e58194b87026474c12c5c48c4e49 |
|
MD5 | 6135b5069e4f97fab4d1e07890328df0 |
|
BLAKE2b-256 | 43d31cc070cc88683c2bdeb7dda5fcc9cf23ecb92a4569ae6edcab264ab9e5f2 |
Hashes for pydelatin-0.2.6-cp36-cp36m-musllinux_1_1_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | fbe90963b20444bf451a747fc06bf44d8775786ae4df28cdc9bbd69dbc5eb042 |
|
MD5 | d3018dba6dc232b583b18a95066aec4b |
|
BLAKE2b-256 | 525843cb8a07faa3b407362aaa07f62d49b5ccecc2b1dc94262eacb7273235d0 |
Hashes for pydelatin-0.2.6-cp36-cp36m-musllinux_1_1_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 96dd6102e4f34a00a39b7fd9492d67eeddb343b9c824b8248a456b3da8360e76 |
|
MD5 | d272612b6903f33c12039c71e9bce90b |
|
BLAKE2b-256 | 3e661da760f149ef0750636c06b8b5485192ffe0231c2fa45fdbb051a13ecaf7 |
Hashes for pydelatin-0.2.6-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 56b22ff5c99ccfd2c0421450ed6770aba8d1ccc0656a0db9f2a21e3df834283b |
|
MD5 | fb084804c73f8a150f88781650f4732a |
|
BLAKE2b-256 | 03d560b8bc1a9b819388103a51252200eb525360451fef3f83f9f6c87a48f29c |
Hashes for pydelatin-0.2.6-cp36-cp36m-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | a7c7f2d4bc4020696ec8ac7c77fd88202923037b3d21972341f06a9b8f3357fc |
|
MD5 | 603fc5285853d4eaee470a9422a6f23d |
|
BLAKE2b-256 | f74d8f7cbbbfa8350f068dc5420cfa711deefb03f49f3655dfa56ab5dd110ba4 |