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.7-cp311-cp311-musllinux_1_1_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 22fb724de257d9b0ada6d3da3ef690570a6813d8fa58ca947bf45c66c967c652 |
|
MD5 | a1709e369146aa5b68ba54d1e1bbdeeb |
|
BLAKE2b-256 | b4d3bb9d0e2bc91215196c269631300acab91b319067b04a63b27d9c8f45a46f |
Hashes for pydelatin-0.2.7-cp311-cp311-musllinux_1_1_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | d42a28eaec2e0392fe89da8e9f63612b33939836e87de31d55a925798494a327 |
|
MD5 | 042ca3880ef2f7ac981084977aa6703c |
|
BLAKE2b-256 | 292825e2b18fa977cbee327851ada0454b1426de22a046e2fadd44e4a0990e68 |
Hashes for pydelatin-0.2.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 28061f05767015f5f3bd130b008ac866e3d491d694f38fa5e2111ce39a07e33d |
|
MD5 | 60091ae33d25f66d57b0eedf4408bb9f |
|
BLAKE2b-256 | c3f14eabe1aa6a392c69ab2a933981dcd0ca80c91413355d01bcffb1628c118c |
Hashes for pydelatin-0.2.7-cp311-cp311-macosx_11_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5c69f8f4d5cd53c77d2d3a96c9937d59b9663a41350fb6646c4af675905b33c9 |
|
MD5 | ddc7d2bdbe036ed1a971cfd96ec2df14 |
|
BLAKE2b-256 | 0f65c5cb1fe5ae7ff5bd440916425a782d95d23c59fa593ed8c2305f8583e1c9 |
Hashes for pydelatin-0.2.7-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 414f7497300fa8a0535593198def97f5638ba21f73fb701490e281808f93bb0c |
|
MD5 | 105ffaf5343d992cc43d3af54b1852e0 |
|
BLAKE2b-256 | 03e1c6de6e7cb703a0d39b006771be23e68c957c3263024d74b2e24db28a3448 |
Hashes for pydelatin-0.2.7-cp310-cp310-musllinux_1_1_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 6a5cc834977abddbc36d964a94593561fcd9d6163fe1f69b6b4b52e4bfbd37b7 |
|
MD5 | 590a25469bbc9bac88260bee8a4ea9f4 |
|
BLAKE2b-256 | 2683918700fa9869b721a98952dab88d066c613193bc4cb2e75c440666ccd105 |
Hashes for pydelatin-0.2.7-cp310-cp310-musllinux_1_1_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 6ba4f7eed049d3b7510d586af0dcbb0e43a4384e08daffe166c146de438e901e |
|
MD5 | f222c1ea227861235251fd23018d16ec |
|
BLAKE2b-256 | 08f9b670ddee0d6f1a931cd2835cd4bbdc62c52696d8b389f77d94b34071aafd |
Hashes for pydelatin-0.2.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 49f3aa0181e4d74dc9b8a9511926b725a945dab1556baf21b959ac66b58a71a4 |
|
MD5 | 421a5a611cfabaea380ba7252bb35cae |
|
BLAKE2b-256 | 09fbb06f5b65e594dfae10674f70db0bcab77e4f5e287a023a04d887cf4f8da6 |
Hashes for pydelatin-0.2.7-cp310-cp310-macosx_11_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | b5526e4a45e40a5b721d078678202c6956b760053bab0ab79139f2cae7138f7f |
|
MD5 | e5effcf4ac70066bdfbbf7324b17f480 |
|
BLAKE2b-256 | eab4e7762eb050c499a47e79aed91d857caee048f63c1db5c88ed61e398b6f35 |
Hashes for pydelatin-0.2.7-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 91534a496f500f700b20f3258a9c39c19d6996f5ec42cec87da31c44a7c942dc |
|
MD5 | 72788cdd2c310f0e4fc3429752f66f00 |
|
BLAKE2b-256 | ee03c94ab05dc7fd12b1ea5d5d06623697e8770a21ebad21ff591fcd079afaf5 |
Hashes for pydelatin-0.2.7-cp39-cp39-musllinux_1_1_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | be597a801b0cb01ba7cc221c5c243fe7f0e44881522e437e7f1f42859778389c |
|
MD5 | 0fc3d532fd2a4b087c9b72d90a5e0b57 |
|
BLAKE2b-256 | 7a28f36cd95b25f609c3df5ee04a980c7f7f940aafb546e3d0daf33ba89a9bc9 |
Hashes for pydelatin-0.2.7-cp39-cp39-musllinux_1_1_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 7506357de91310f2fe0b66f5014f611cdba542a41a269456344ce1cf8b9028d8 |
|
MD5 | 525f1b7039d5fbe8a310bf47c9654b9c |
|
BLAKE2b-256 | dd6eeb0eae3261c2e06b84b78d00da475b48798c00295c1bed3adfce4a1e2d45 |
Hashes for pydelatin-0.2.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 7c82c1a96faf3cc96c119b72200e9383121ad361b067629c4ac1892c892307be |
|
MD5 | cfdbba1637332793b0dd92ada2842c07 |
|
BLAKE2b-256 | e5b63a1bce13fa0b8e6482e64126db2644a99ef3a0b2d290994823aae4beeef0 |
Hashes for pydelatin-0.2.7-cp39-cp39-macosx_11_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1dde7e9c5f282537c9d7702c354b8c0256299dbcda08c14ed02a228bb1b04eab |
|
MD5 | 03e26f3bfba98b664b3215e7f997d074 |
|
BLAKE2b-256 | c41ba76ec75e14e640520bcb276b4792e75a06aca03772ef5d2cdc984b40c624 |
Hashes for pydelatin-0.2.7-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | a8441fe27d14f1597567bb13545456c618d131d90ebf06d14c7eecf7b0ee2032 |
|
MD5 | 596c24626657843e3f5af02a35e3604c |
|
BLAKE2b-256 | d16b8627e06f82476a919127f4b1cce28491b3591064821cc86548100ddf9303 |
Hashes for pydelatin-0.2.7-cp38-cp38-musllinux_1_1_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | f51d6714053aa25f357149d8002cf021c3de64e2b758886c8667ef8971b01899 |
|
MD5 | 1c3e6409f4b0aa6ee70263fdd38bf387 |
|
BLAKE2b-256 | 984f14698d60b50d900b2f268e6fa26f53cbc8dba4ee6bf56206c4faa010cccb |
Hashes for pydelatin-0.2.7-cp38-cp38-musllinux_1_1_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 20ba4c3b9f9859f1fdbb5a04da64efcdc7f908e06447cc613cf79ef9a0fc8908 |
|
MD5 | c722651047b4a9fbea6105a9393ff0ec |
|
BLAKE2b-256 | 9e445da8dc1ea32590e441c1ab61755f856b9a668254b7fcddab8bd7966338d8 |
Hashes for pydelatin-0.2.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 412da14778c7290538fa3b7fee9e27383540c5ecd20738c21299517ae39e8651 |
|
MD5 | 487a53dc7aaa602bcbe64613ea424c39 |
|
BLAKE2b-256 | 986e93c82d280f337ec9d8a7e56d0e83262573387c1ff9ff2e997971698b7c5c |
Hashes for pydelatin-0.2.7-cp38-cp38-macosx_11_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | c5a572657245fb3ea210588de5ca2bea2a6779e81fab0730ad263f7fb4224a4a |
|
MD5 | 956eb1d20bc35a1c2640a01e1f4b98c5 |
|
BLAKE2b-256 | 7081add7cda733ae1ed09c92b8a5432a8caf2702a650caed1cb3ed14157d0242 |
Hashes for pydelatin-0.2.7-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 9d6a5a073e6c463dda9153193a665968079828b4d1369a36c982f60613183752 |
|
MD5 | 1da9b535585c166024d6fb7f0a959959 |
|
BLAKE2b-256 | ea20a8c3fcd30a71a47d62fa38793a0f94d12cf31ffa4bb06dbe8dd570ef0344 |
Hashes for pydelatin-0.2.7-cp37-cp37m-musllinux_1_1_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | c48d4cbf1916b879fe15e4b92f588d742ffaf2ae011d6480b33a57677d848ecf |
|
MD5 | 2cbf7c607ec4d963ff965e9add2a4478 |
|
BLAKE2b-256 | 08cf6c94428d0cfa99a8d27593a2aff20c6ced1b01455e8657a09274821ad1ce |
Hashes for pydelatin-0.2.7-cp37-cp37m-musllinux_1_1_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | ccf42beb57d8e343155b5e98788524c0d4ddb0e740a5c711083da4f5b72fc041 |
|
MD5 | eac811523008f0f757785b554292cc78 |
|
BLAKE2b-256 | a46cdd99c3b1307f86eed20d29a578b97e3f34a4f2230dcd6b007f949c714e3b |
Hashes for pydelatin-0.2.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 55bf263d127f843d10d3a34e2508df6a9cebccb59f7e76b9f2829d2b970d2822 |
|
MD5 | 6680961dfcac38cd561be7f008909c16 |
|
BLAKE2b-256 | 685d89c23b903cd2aa2cbf93510bea724375b4d60e579c476ef8f47b93b98f75 |
Hashes for pydelatin-0.2.7-cp37-cp37m-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 071564364359ccc3a731753f45ca454ac9aca894c3c6f0b1ff0c26c9973b6144 |
|
MD5 | b3cac2048817b4fd9ef55d5a4e5f693d |
|
BLAKE2b-256 | 1c62266e24a6af88da0706c3c74de1eee2804998948164b72f61786e988a169a |
Hashes for pydelatin-0.2.7-cp36-cp36m-musllinux_1_1_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5a9bbec86332eed40ac92860b5ae64beb928a2942d8a44fb209712011f91dbb4 |
|
MD5 | fbdaab423a72a071791aba67e1ff4f7f |
|
BLAKE2b-256 | 75faf8b05c30ecd86ec0adc24b8db9cfd7ceaf4b147e7ff3e0e0cfe803a8e17e |
Hashes for pydelatin-0.2.7-cp36-cp36m-musllinux_1_1_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 0ddf94f61a9cab76a624e393ecd709e206bf2082b5aefade3dd02c54366685fe |
|
MD5 | bf27ca2a382155b4382e4074def32a11 |
|
BLAKE2b-256 | 4eaeaa42f633de2361b5c84524776d425b9d4957a129844db17d14810001167e |
Hashes for pydelatin-0.2.7-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | c5bda27f2a8274df46f33200b7834e751ddcbb0eb3dded199cc6d4525b876d51 |
|
MD5 | e51937e6cc200a70313b25f6c6d928e3 |
|
BLAKE2b-256 | 30fc718dc1c2872ebb6e24c14153e86a4ff049b5521c3a9d9e200a1bdaebf173 |
Hashes for pydelatin-0.2.7-cp36-cp36m-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 56b1562067b672801018d41e3cc48c9d266dab73ff8e63ab34f5bb8b0a02fbe0 |
|
MD5 | 2b13ec705263667e6539e10da6f6e072 |
|
BLAKE2b-256 | a10595a63b622e9ad91242a56acaafb5645626fa98125679c85ed890c9386dfe |