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.5-cp310-cp310-musllinux_1_1_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 02677cfca3dbe52ef3dfd5f087f10183baf8567ece228894435602db3da3ecb9 |
|
MD5 | 01daf93924bcba6be326b1b3e1cbee10 |
|
BLAKE2b-256 | b5d6f3e9245bfc470130376a1603821e872be630bdddab88b79823c98753117e |
Hashes for pydelatin-0.2.5-cp310-cp310-musllinux_1_1_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | f97ef493d660118ecedbd981935fccebfe0d91bbad34c8ff7ca2c096c99ec189 |
|
MD5 | c1b540a8e30803d156149046a60badc0 |
|
BLAKE2b-256 | 91e1f01a4ecba7c12a3d7d07ab838681ba096ee2bc4077a20ec87b30ef02a36c |
Hashes for pydelatin-0.2.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | b3d354f06676788dba89071d68969e84f7def0c3b3ff6cd18820708053665d44 |
|
MD5 | 160a074bb22741295353df2450811225 |
|
BLAKE2b-256 | eddb1d93c1c767578ddc3c72f460b11b565b4f8a8adddc3c77c80f36d57f1721 |
Hashes for pydelatin-0.2.5-cp310-cp310-macosx_11_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5e9dddcc0ea88acf199d3c3e857d0f9b4123719e9effe4a3a0fee515fd46fa58 |
|
MD5 | c99ec43d5216c41c30ea996c6b23c022 |
|
BLAKE2b-256 | f53fcec829d4adaeca15f7af778d908c1142413e6dcfd571cccf0fe0ad46f135 |
Hashes for pydelatin-0.2.5-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 51293417423cb3438cc41c256fd3618707e15d55f65e012144a125ce1ea370ea |
|
MD5 | 739e1af1c86787c4289828c1555928ca |
|
BLAKE2b-256 | ad016d65ff6889b623c34c5a50ec951fd77019ef536bf24aa9894f0254b44e99 |
Hashes for pydelatin-0.2.5-cp310-cp310-macosx_10_9_universal2.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | ebfabc6d96ead217959d6f0d100dd45654e42f719bb377618a810754566352cf |
|
MD5 | 4b1ed3d5056bff35c8459674b637abdc |
|
BLAKE2b-256 | 979c6d12f7e6b79f8962fc89b18a1027fdc6e3e5dd05adcb973cc072d3412eb7 |
Hashes for pydelatin-0.2.5-cp39-cp39-musllinux_1_1_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 321f47a73fabd88635e8bf54bd4e63261dcc9df6b79379776d3a29e91691a2c4 |
|
MD5 | 5c2280b37f551f1c393acc5efa6e32f2 |
|
BLAKE2b-256 | b183e76d855b4930a7e8ba2f792c6799ba16ea2cd157d25d2d05a1cc49782661 |
Hashes for pydelatin-0.2.5-cp39-cp39-musllinux_1_1_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | fb455dd8243c47f41a1fca6fced5804f2e3c0129df208d1db36fbaa39ee6e630 |
|
MD5 | 0cdee849ff77617d2283bd73540154f3 |
|
BLAKE2b-256 | 5a958e06df21517e010788a94f5c83d74d972bfe78c57ea0702518db523d406a |
Hashes for pydelatin-0.2.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2b7091627ea77460de86636c2f8b0e6a28bf83798691e89a93f4e403bca1ccd8 |
|
MD5 | daef8ca5e698fc2b677c0114c80d4bb4 |
|
BLAKE2b-256 | b98b77330dfa856428f4bb80e2102a79ace93a64b48748afcf8bee23841ef35d |
Hashes for pydelatin-0.2.5-cp39-cp39-macosx_11_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | d8b8ebece0c1e682ed9615c6d443aa284d44a0b9bc56f9297f6b57bd2dbda6ad |
|
MD5 | 1ba9370ed0fd29f72b7c36ff41e2a787 |
|
BLAKE2b-256 | f39a74efb9bf8c1e65c9558832a94ac5fe0e7ca342ae60fad0c255b01a00f580 |
Hashes for pydelatin-0.2.5-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 46a7cbe8ebf968d5df4765fcffac3cfd0349f37131532cd03efe31091dbcd925 |
|
MD5 | b8978cda3253509a9b53e7b1b53f6163 |
|
BLAKE2b-256 | 49afd6affad2cc470b3bb3dfce84693934344f70cc37af66b5a36810e6824e1e |
Hashes for pydelatin-0.2.5-cp39-cp39-macosx_10_9_universal2.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 8a319c88f75d4252af32f124ec743529bcde8759ba7b90e25a08d514a3c08077 |
|
MD5 | 0774107cbbd42995de85e3931d14d1fa |
|
BLAKE2b-256 | b999327d231345e5dd99e24c12a8d7ea33266851333d01c4acf974bf13bd3414 |
Hashes for pydelatin-0.2.5-cp38-cp38-musllinux_1_1_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | f4c622546fbec4bb74b5388062c484bf1fd55f9903ea0a502b7287c073d6dcda |
|
MD5 | dd9b175b7323dbd646b62c41bd68899b |
|
BLAKE2b-256 | 9ecf1f72af76d9928a5ece80d6b5296ad0df8e8ef2832dd99c444b1a31d68e7d |
Hashes for pydelatin-0.2.5-cp38-cp38-musllinux_1_1_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 549a9e3199c43b1266ea685da71a02c39f0f945241afb4fef1565d60e320f033 |
|
MD5 | d71d14988eca339f70b2160810448945 |
|
BLAKE2b-256 | f043d6ab02f1ada41efa9691e026839bf4fab329c2ea0c31ffb47a9ad3a1d177 |
Hashes for pydelatin-0.2.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 85bc602e4497c1238a798cbd44248a5305614b3e52ac0d4f03ddef79ca941bc4 |
|
MD5 | bcb65b3dce19ed54f08d6eb926d77fe5 |
|
BLAKE2b-256 | dfd9cc1eedd36979ab4aa1975c9112733fd56c5c7ec0ac3c4d93878e54981ee8 |
Hashes for pydelatin-0.2.5-cp38-cp38-macosx_11_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 989d667a86d746bb4de4d50bf3918ef32ca92744d6740b0cc465429f2159c7b3 |
|
MD5 | 0abda8569f53a7751eab4f4d39227ce1 |
|
BLAKE2b-256 | 2529195506233c2ac7b5f349c1723bd1579009a5569a2a7375407afbeddabb6a |
Hashes for pydelatin-0.2.5-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | b161f5b556b1ae82b4f1e3f77d5f1a0e7ca6cd9517f91c4cbd2526221d52b726 |
|
MD5 | 3e57f923cd5fb6399b239fde379405bf |
|
BLAKE2b-256 | 04e2dc7d8f1347f81b1a201ba8569aeaa1e9128bd0588b104c9be2e9a6e48f73 |
Hashes for pydelatin-0.2.5-cp38-cp38-macosx_10_9_universal2.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 03664e57f5a9c1139ed5f5c22f52563eb516a80375340954c403ff464d2495b8 |
|
MD5 | 71963deadd78d4347a871a03f444acb5 |
|
BLAKE2b-256 | f719d9a9f6adf456130fc3d87361c2ca53e488c58d94b678eeef6d0edabb7967 |
Hashes for pydelatin-0.2.5-cp37-cp37m-musllinux_1_1_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 8215f4b207725e58db9c7930d7d39107e363154bc85777abb4bc6bdad63911e0 |
|
MD5 | d0d86e5ea3be40d4ed8f35aadb717546 |
|
BLAKE2b-256 | df565b6c08bab99d5937f01e4a9392e446da40c9d5e624d09c7ee6479efcc995 |
Hashes for pydelatin-0.2.5-cp37-cp37m-musllinux_1_1_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 71a9700706dd88737fd603e6f64687dfa37265b06b922b8aac1bbb25fe2b8c84 |
|
MD5 | 335cadaba2d157941a86ec6d11ebee14 |
|
BLAKE2b-256 | d4bc17c9ad443eb117bdc5fbbcb1ca9a37e98a773a03a4239edf63036ff752a7 |
Hashes for pydelatin-0.2.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2cc0ccc2c572f1dc89777c641b3d330be62f87dbfa9e07b2404d5de85aa21c34 |
|
MD5 | ffafcc022a4f7c47b459877d6341b635 |
|
BLAKE2b-256 | fb4b7da966a8f99ee7f081394b86bd2ab49cdd51f695b0620744dced91ac24e4 |
Hashes for pydelatin-0.2.5-cp37-cp37m-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | b7a42dd896f8c1937113c88dea4ee5ca3d2127cbb879020bbb3621e12844b87e |
|
MD5 | 675550d0dab541be19b0298fd52b195d |
|
BLAKE2b-256 | c07aaec7fea4570c588e4a6f78d79f7eea7a5a753510089c6488e1127b52f109 |
Hashes for pydelatin-0.2.5-cp36-cp36m-musllinux_1_1_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 8ef97f1cc645e38a50b4443df59d079b206757a29e9d9d6036755594f566388b |
|
MD5 | bc44550605028b898ee7121bcb10a523 |
|
BLAKE2b-256 | c9a790574406ec8ca77dd356e9f00ebd651f28585ed1263b3d75562dffa58569 |
Hashes for pydelatin-0.2.5-cp36-cp36m-musllinux_1_1_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 12c108753db4e505e687cd5520a6cced470da88b283fe859ad3e6bbd0418ed70 |
|
MD5 | 4336fca613f80d13085941403d20a3aa |
|
BLAKE2b-256 | 8eb91ff41f4d3e238f7d460fd9d7ecca17c4309344c4befee790693d0bbaff3d |
Hashes for pydelatin-0.2.5-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 14837e6469954229b5d62134587e3754e299d582c00a6037f53f93b9443e340a |
|
MD5 | 5d4df091c91cc24f24f38f9b3ce25d79 |
|
BLAKE2b-256 | 4027501496efcf670efc42ca3e4102704a0f31e38694e0504526775d7b5edc6e |
Hashes for pydelatin-0.2.5-cp36-cp36m-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 84856a335cb694902511967c999c80fdb7497dde86b912fa154155f102a19012 |
|
MD5 | 6aae07cd40b8d464ea221e30fe10e506 |
|
BLAKE2b-256 | e326436c913b271d3aee296fad28fe6c6d3f4c209d55b032376dabd545f4eb42 |