### Complete Workflow Example for GlobalGeodetic Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/global-geodetic.md Demonstrates initializing the GlobalGeodetic system, retrieving tile bounds, performing reverse lookups for locations, getting grid information, analyzing resolution, and integrating with terrain encoding. Ensure the 'quantized-mesh-tile' library is installed. ```python from quantized_mesh_tile import encode from quantized_mesh_tile.global_geodetic import GlobalGeodetic # Initialize geodetic system (compatible with Cesium) geodetic = GlobalGeodetic(tmscompatible=True) # Get information about a specific tile x, y, z = 533, 383, 9 # Method 1: Get tile bounds directly west, south, east, north = geodetic.TileBounds(x, y, z) print(f"Tile ({x}, {y}, {z}) covers: {west}°W to {east}°E, {south}°S to {north}°N") # Method 2: Reverse lookup - find tile for a location tx, ty = geodetic.LonLatToTile(lon=7.5, lat=44.8, zoom=9) print(f"Location (7.5°E, 44.8°N) is in tile ({tx}, {ty}, 9)") # Method 3: Get grid information num_x = geodetic.GetNumberOfXTilesAtZoom(9) num_y = geodetic.GetNumberOfYTilesAtZoom(9) print(f"Zoom level 9 has {num_x}×{num_y} tiles") # Method 4: Resolution analysis res = geodetic.Resolution(9) print(f"At zoom 9: {res:.6f}°/pixel = {res*111000:.1f}m/pixel at equator") # Use with terrain encoding tile = encode( geometries=[...], bounds=(west, south, east, north) ) tile.toFile(f'terrain/{z}/{y}/{x}.terrain') ``` -------------------------------- ### Install quantized-mesh-tile Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/QUICKSTART.md Install the library using pip. This is the first step to using the quantized-mesh-tile package. ```bash pip install quantized-mesh-tile ``` -------------------------------- ### Project Dependencies Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/README.md Lists the required Python packages and their minimum versions for the project. Ensure these are installed before running the project. ```text numpy>=2.0.0 # Numerical arrays and linear algebra shapely>=2.0.0 # Geometry parsing (WKT/WKB) and Delaunay triangulation ``` -------------------------------- ### Build and Serve Documentation Locally Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/README.md Navigate to the 'doc' directory, clean previous builds, generate HTML documentation, and start a local HTTP server to view the documentation. ```bash cd doc rm -rf build && make htm python -m http.server 8000 --directory build/html ``` -------------------------------- ### Usage Example for Safe Encoding Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/errors.md Demonstrates how to use the safe_encode function with valid 3D geometries and bounds. This example shows a typical workflow for creating a terrain tile. ```python # Usage geometries = [ 'POLYGON Z ((7.38 44.64 303.3, 7.38 45.0 320.2, 7.56 44.82 310.2, 7.38 44.64 303.3))' ] tile = safe_encode(geometries, bounds=(7.0, 44.0, 8.0, 45.0)) if tile: tile.toFile('output.terrain') ``` -------------------------------- ### Example: Calculate Bounding Sphere from Points Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/bounding-sphere.md Demonstrates how to create a BoundingSphere object and compute its bounding sphere from a list of ECEF points. The resulting center and radius are then printed. ```python from quantized_mesh_tile.bbsphere import BoundingSphere # ECEF coordinates (from LLH2ECEF conversion) points = [ [4202615.64, 767000.1, 4546674.0], # Some ECEF point [4202617.0, 767005.0, 4546670.0], # Another ECEF point [4202620.0, 767010.0, 4546675.0], # Third point ] sphere = BoundingSphere() sphere.fromPoints(points) print(f"Center: {sphere.center}") print(f"Radius: {sphere.radius}m") ``` -------------------------------- ### GlobalGeodetic Constructor Usage Examples Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/configuration.md Examples demonstrating how to initialize the GlobalGeodetic object for Cesium terrain (TMS compatible) and standard WMTS tiling schemes. ```python # For Cesium terrain (TMS compatible) geodetic = GlobalGeodetic(tmscompatible=True, tileSize=256) # For standard WMTS (1 tile at zoom 0) geodetic = GlobalGeodetic(tmscompatible=False, tileSize=256) ``` -------------------------------- ### Quantized Coordinates Example Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/types.md Demonstrates the internal representation for quantized coordinates (u, v, h) within binary tile files, ranging from 0 to 32767. ```python # u, v, h are quantized to 0-32767 range u = 16383 # Quantized longitude (0 = west, 32767 = east) v = 16383 # Quantized latitude (0 = south, 32767 = north) h = 16383 # Quantized height (0 = minHeight, 32767 = maxHeight) ``` -------------------------------- ### Tile Bounds Example Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/types.md Provides an example of the standard tuple format for geographic tile boundaries (west, south, east, north) in degrees WGS84. This format is returned by several library functions. ```python bounds = (west, south, east, north) # All in degrees WGS84 # Example: bounds = (-180.0, -90.0, -90.0, 0.0) ``` -------------------------------- ### Handle Unsupported Extensions with Warnings Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/errors.md This example shows how to capture and process warnings issued when reading tiles with unsupported extensions (ID 3+). It uses `warnings.catch_warnings` to intercept these messages instead of raising exceptions. ```python import warnings from quantized_mesh_tile.terrain import TerrainTile with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") tile = TerrainTile(west=0, south=0, east=1, north=1) tile.fromFile('tile_with_metadata.terrain', hasLighting=False, hasWatermask=False) for warning in w: if "Skipping unsupported" in str(warning.message): print(f"Warning: {warning.message}") # Extensions 3+ (e.g., Metadata) are skipped ``` -------------------------------- ### ECEF Coordinates Example Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/types.md Shows an example of Earth-Centered, Earth-Fixed cartesian coordinates in meters. Conversion functions are available in `quantized_mesh_tile.llh_ecef`. ```python # Example: [x, y, z] point = [4202615.64, 767000.1, 4546674.0] # ECEF point in meters ``` -------------------------------- ### Round-Trip Conversion Example Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/coordinate-conversion.md Demonstrates a round-trip conversion from geographic coordinates to ECEF and back to geographic coordinates. ```APIDOC ## Round-Trip Conversion ### Description This example demonstrates converting geographic coordinates to ECEF and then back to geographic coordinates to verify precision. ### Code Example ```python from quantized_mesh_tile.llh_ecef import LLH2ECEF, ECEF2LLH original_lon, original_lat, original_alt = 7.5, 44.8, 310.2 x, y, z = LLH2ECEF(original_lon, original_lat, original_alt) print(f"ECEF: ({x:.2f}, {y:.2f}, {z:.2f})") lon, lat, alt = ECEF2LLH(x, y, z) print(f"Geographic: ({lon:.10f}, {lat:.10f}, {alt:.6f})") print(f"Lon difference: {abs(lon - original_lon):.2e}") print(f"Lat difference: {abs(lat - original_lat):.2e}") print(f"Alt difference: {abs(alt - original_alt):.2e}") ``` ``` -------------------------------- ### Geographic Coordinates (LLH) Example Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/types.md Illustrates the Longitude, Latitude, Height format used for geographic coordinates. Values are in degrees for longitude and latitude, and meters for height. ```python # Example: (longitude, latitude, height) coord = (7.5, 44.8, 310.2) # 7.5°E, 44.8°N, 310.2m elevation ``` -------------------------------- ### Get Tile Bounds in SWNE Order Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/global-geodetic.md Retrieves tile boundaries in South-West-North-East (SWNE) order, which is a common convention in some GIS systems. Provides an alternative ordering for tile extents. ```python def TileLatLonBounds(self, tx: int, ty: int, zoom: int) -> tuple[float, float, float, float]: pass ``` -------------------------------- ### Get Terrain Tile Content as BytesIO Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/doc/source/tutorial.md Obtains the content of a quantized mesh terrain tile as a gzipped io.BytesIO object, useful when not needing to write to a physical file. ```python tile = encode(geometries, bounds=bounds) content = tile.toBytesIO(gzipped=True) ``` -------------------------------- ### Create Terrain Topology from Geometries Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/terrain-topology.md Demonstrates creating a TerrainTile object from WKT geometries. It shows how to initialize TerrainTopology with geometries and lighting enabled, access computed properties like bounds and vertex counts, and finally encode the topology into a terrain tile file. ```python from quantized_mesh_tile import TerrainTile, encode # Create topology from geometries wkts = [ 'POLYGON Z ((7.3828125 44.6484375 303.3, 7.3828125 45.0 320.2, 7.5585937 44.82421875 310.2, 7.3828125 44.6484375 303.3))', 'POLYGON Z ((7.3828125 44.6484375 303.3, 7.734375 44.6484375 350.3, 7.5585937 44.82421875 310.2, 7.3828125 44.6484375 303.3))', ] topology = TerrainTopology(geometries=wkts, hasLighting=True) # Access computed properties print(f"Bounds: lon [{topology.minLon}, {topology.maxLon}], lat [{topology.minLat}, {topology.maxLat}]") print(f"Heights: {topology.minHeight}m to {topology.maxHeight}m") print(f"Vertices: {len(topology.vertices)}") print(f"Triangles: {len(topology.faces)}") # Create terrain tile from topology tile = TerrainTile(topology=topology) tile.toFile('output.terrain') ``` -------------------------------- ### Write and Read Terrain Tiles with Compression Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/configuration.md Demonstrates writing terrain tiles to a file, both uncompressed for faster I/O and gzipped for smaller file sizes. Also shows how to read a gzipped tile. ```python tile = TerrainTile(topology=topology) # Write uncompressed (faster writing) tile.toFile('output.terrain', gzipped=False) # Write gzipped (smaller file, slower writing) tile.toFile('output.terrain.gz', gzipped=True) # Read compressed file tile2 = decode('output.terrain.gz', bounds=bounds, gzipped=True) ``` -------------------------------- ### TerrainTopology Initialization with WKT Geometries Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/coordinate-conversion.md Demonstrates initializing TerrainTopology with Well-Known Text (WKT) geometries. Vertices are automatically converted to ECEF coordinates upon addition. ```python from quantized_mesh_tile.topology import TerrainTopology # When geometries are added, each vertex is converted to ECEF wkts = ['POLYGON Z ((7.38 44.64 303.3, 7.38 45.0 320.2, 7.56 44.82 310.2, 7.38 44.64 303.3))'] topology = TerrainTopology(geometries=wkts) # Access ECEF vertices (computed internally) ecef_vertices = topology.cartesianVertices print(f"ECEF vertex 0: {ecef_vertices[0]}") # Access geographic vertices llh_vertices = topology.vertices print(f"LLH vertex 0: {llh_vertices[0]}") ``` -------------------------------- ### Shapely Polygons Geometry Format Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/INDEX.md Integrate with GIS libraries by using Shapely Polygon objects for geometry representation. Requires Shapely installation. ```python # Format 3: Shapely polygons (GIS interop) from shapely.geometry import Polygon Polygon([(lon, lat, h), (lon, lat, h), (lon, lat, h)]) ``` -------------------------------- ### Encode Terrain Tile with Watermask Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/doc/source/tutorial.md Encodes a quantized mesh terrain tile, specifying a watermask. The example shows how to define a water-only mask. ```python # Water only watermask = [255] tile = encode(geometries, bounds=bounds, watermask=watermask) ``` -------------------------------- ### Simple File Operations: Encode and Decode Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/QUICKSTART.md Demonstrates the basic usage of encoding geometries into a tile file and decoding a tile file back into usable data. Assumes geometries and bounds are defined elsewhere. ```python from quantized_mesh_tile import encode, decode # Create tile = encode(geometries, bounds=bounds) tile.toFile('tile.terrain') # Read tile = decode('tile.terrain', bounds=bounds) ``` -------------------------------- ### Get Terrain Tile Content Type Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/terrain-tile.md Determine the MIME content type of the terrain tile. This is useful for setting HTTP headers when serving tiles. ```python tile = TerrainTile(west=-180, south=-90, east=180, north=90) content_type = tile.getContentType() # Returns "application/vnd.quantized-mesh" ``` -------------------------------- ### Initialize BoundingSphere Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/bounding-sphere.md Creates a BoundingSphere instance with optional initial center coordinates and radius. ```python BoundingSphere( center: list = [], radius: float = 0 ) ``` -------------------------------- ### Three.js and OrbitControls Initialization Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/doc/source/viewer.md Initializes Three.js and OrbitControls, making them globally available and loading the tile loader script. ```javascript import * as THREE from 'three'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; // Make THREE and OrbitControls available globally for tileLoader.js window.THREE = THREE; window.OrbitControls = OrbitControls; // Load our tile loader after THREE is ready const script = document.createElement('script'); script.src = '_static/tileLoader.js'; document.head.appendChild(script); ``` -------------------------------- ### Get Sign of a Number (Excluding Zero) Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/utility-functions.md Returns the sign of a floating-point value. It returns -1.0 for negative numbers and 1.0 for non-negative numbers (including zero). ```python def signNotZero(v: float) -> float: # Returns the sign of a value: -1.0 for negative, 1.0 for non-negative. pass ``` -------------------------------- ### Retrieve Vertex Coordinates Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/terrain-tile.md Get all vertex coordinates from the tile in (longitude, latitude, height) format. This method may raise TerrainTileError if the tile data is corrupted. ```python coordinates = tile.getVerticesCoordinates() for lon, lat, height in coordinates: print(f"Vertex at {lon}, {lat} with height {height}m") ``` -------------------------------- ### Complete Quantized Mesh Tile Workflow Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/configuration.md Demonstrates a full cycle of encoding and decoding a quantized mesh tile. This includes setting up the geodetic system, defining tile bounds, preparing geometries, encoding the tile with various options, writing it to a file, and then reading it back for verification. ```python from quantized_mesh_tile import encode, decode from quantized_mesh_tile.global_geodetic import GlobalGeodetic # Step 1: Define geodetic system geodetic = GlobalGeodetic(tmscompatible=True) # Step 2: Get tile bounds x, y, z = 533, 383, 9 west, south, east, north = geodetic.TileBounds(x, y, z) bounds = (west, south, east, north) # Step 3: Define geometries (multiple formats possible) geometries_wkt = [ 'POLYGON Z ((7.38 44.64 303.3, 7.38 45.0 320.2, 7.56 44.82 310.2, 7.38 44.64 303.3))', 'POLYGON Z ((7.38 44.64 303.3, 7.73 44.64 350.3, 7.56 44.82 310.2, 7.38 44.64 303.3))', ] # Step 4: Encode with options tile = encode( geometries=geometries_wkt, bounds=bounds, autocorrectGeometries=False, # Geometries are exact triangles hasLighting=True, # Compute lighting normals watermask=[255] # Mark as water tile ) # Step 5: Write to file output_path = f'terrain/{z}/{y}/{x}.terrain' tile.toFile(output_path, gzipped=False) # Step 6: Verify by reading back tile_read = decode( filePath=output_path, bounds=bounds, hasLighting=True, hasWatermask=False, gzipped=False ) print(f"Tile verified: {len(tile_read.getVerticesCoordinates())} vertices") ``` -------------------------------- ### Initialize TerrainTopology with WKT Strings Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/terrain-topology.md Instantiate TerrainTopology using a list of Well-Known Text (WKT) strings representing polygons with Z coordinates. Ensure geometries are valid polygons with Z dimensions. ```python from quantized_mesh_tile.topology import TerrainTopology # Method 1: Using WKT strings wkts = [ 'POLYGON Z ((7.3828125 44.6484375 303.3, 7.3828125 45.0 320.2, 7.5585937 44.82421875 310.2, 7.3828125 44.6484375 303.3))', 'POLYGON Z ((7.3828125 44.6484375 303.3, 7.734375 44.6484375 350.3, 7.5585937 44.82421875 310.2, 7.3828125 44.6484375 303.3))' ] topology = TerrainTopology(geometries=wkts) ``` -------------------------------- ### Basic Encoding Workflow Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/module-functions.md Demonstrates a complete workflow for encoding geometries into a terrain tile, inspecting its properties, writing it to a file, and verifying by decoding it back. This covers preparation, encoding, inspection, and round-trip verification. ```python from quantized_mesh_tile import encode # 1. Prepare triangle geometries triangles = [ [[7.38, 44.64, 303.3], [7.38, 45.0, 320.2], [7.56, 44.82, 310.2]], [[7.38, 44.64, 303.3], [7.73, 44.64, 350.3], [7.56, 44.82, 310.2]], ] # 2. Encode to tile tile = encode( geometries=triangles, bounds=(7.0, 44.0, 8.0, 45.0), hasLighting=False, watermask=[] ) # 3. Inspect tile print(f"Content type: {tile.getContentType()}") print(f"Bounds: {tile.bounds}") vertices = tile.getVerticesCoordinates() print(f"Vertices: {len(vertices)}") # 4. Write to file tile.toFile('output/tile.terrain') # 5. Verify by reading back from quantized_mesh_tile import decode tile2 = decode('output/tile.terrain', bounds=(7.0, 44.0, 8.0, 45.0)) print(f"Round-trip successful: {len(tile2.getVerticesCoordinates())} vertices") ``` -------------------------------- ### Basic encoding workflow Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/module-functions.md Demonstrates a basic workflow for encoding terrain tiles, including preparing geometries, encoding, inspecting, and writing to a file, followed by verification. ```APIDOC ## Basic encoding workflow ### Description Demonstrates a basic workflow for encoding terrain tiles, including preparing geometries, encoding, inspecting, and writing to a file, followed by verification. ### Example ```python from quantized_mesh_tile import encode # 1. Prepare triangle geometries triangles = [ [[7.38, 44.64, 303.3], [7.38, 45.0, 320.2], [7.56, 44.82, 310.2]], [[7.38, 44.64, 303.3], [7.73, 44.64, 350.3], [7.56, 44.82, 310.2]], ] # 2. Encode to tile tile = encode( geometries=triangles, bounds=(7.0, 44.0, 8.0, 45.0), hasLighting=False, watermask=[] ) # 3. Inspect tile print(f"Content type: {tile.getContentType()}") print(f"Bounds: {tile.bounds}") vertices = tile.getVerticesCoordinates() print(f"Vertices: {len(vertices)}") # 4. Write to file tile.toFile('output/tile.terrain') # 5. Verify by reading back from quantized_mesh_tile import decode tile2 = decode('output/tile.terrain', bounds=(7.0, 44.0, 8.0, 45.0)) print(f"Round-trip successful: {len(tile2.getVerticesCoordinates())} vertices") ``` ``` -------------------------------- ### Get Number of Y Tiles at Zoom Level Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/global-geodetic.md Calculates and returns the total number of tiles along the Y-axis for a given zoom level. Essential for map tiling calculations and data management. ```python def GetNumberOfYTilesAtZoom(self, zoom: int) -> int: pass ``` -------------------------------- ### Initialize TerrainTopology with Coordinate Lists Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/terrain-topology.md Create a TerrainTopology instance by providing a list of coordinate triplets, where each triplet represents a triangle with longitude, latitude, and height. Ensure each coordinate has three dimensions (lon, lat, h). ```python # Method 2: Using coordinate lists triangles = [ [[7.3828125, 44.6484375, 303.3], [7.3828125, 45.0, 320.2], [7.5585937, 44.82421875, 310.2]], [[7.3828125, 44.6484375, 303.3], [7.734375, 44.6484375, 350.3], [7.5585937, 44.82421875, 310.2]] ] topology = TerrainTopology(geometries=triangles) ``` -------------------------------- ### ZigZag Decode Integer Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/utility-functions.md Decodes a zigzag-encoded integer back to its original signed form. This is the inverse operation of `zigZagEncode`. For example, decoding 1 returns -1, and decoding 10 returns 5. ```python from quantized_mesh_tile.utils import zigZagDecode original = zigZagDecode(1) # Returns -1 original = zigZagDecode(10) # Returns 5 ``` -------------------------------- ### Populate Terrain Tile from Topology Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/terrain-tile.md Initializes a TerrainTile with data from a TerrainTopology instance. This method computes essential header fields like center, bounding sphere, and horizon occlusion point. It requires a TerrainTopology object and optionally accepts tile bounds. ```python wkts = ['POLYGON Z ((7.3828125 44.6484375 303.3, ...))'] topology = TerrainTopology(geometries=wkts) tile = TerrainTile() tile.fromTerrainTopology(topology, bounds=(7.0, 44.0, 8.0, 45.0)) ``` -------------------------------- ### Get Number of X Tiles at Zoom Level Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/global-geodetic.md Calculates and returns the total number of tiles along the X-axis for a given zoom level. This is fundamental for understanding the grid structure of map tiles. ```python def GetNumberOfXTilesAtZoom(self, zoom: int) -> int: pass ``` -------------------------------- ### TerrainTopology Constructor Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/configuration.md Initializes a TerrainTopology with geometries and optional settings for auto-correction and lighting. Geometries can be provided in various formats. ```python TerrainTopology( geometries: list = None, autocorrectGeometries: bool = False, hasLighting: bool = False ) ``` -------------------------------- ### Get Geographic Bounds of a Tile Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/global-geodetic.md Retrieves the geographic boundaries (west, south, east, north) in degrees for a given tile at a specific zoom level. This is crucial for spatial referencing and tile processing. ```python geodetic = GlobalGeodetic(tmscompatible=True) x, y, z = 533, 383, 9 west, south, east, north = geodetic.TileBounds(x, y, z) print(f"Tile bounds: {west}, {south}, {east}, {north}") # Creates a TerrainTile with these exact bounds: # tile = TerrainTile(west=west, south=south, east=east, north=north) ``` -------------------------------- ### TerrainTopology Geometry Formats Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/configuration.md Demonstrates various ways to provide geometries to the TerrainTopology constructor, including WKT strings, coordinate triplets, Shapely polygons, and WKB bytes. ```python # Option 1: WKT strings (easiest for manual input) geometries = [ 'POLYGON Z ((7.38 44.64 303.3, 7.38 45.0 320.2, 7.56 44.82 310.2, 7.38 44.64 303.3))', 'POLYGON Z ((7.38 44.64 303.3, 7.73 44.64 350.3, 7.56 44.82 310.2, 7.38 44.64 303.3))', ] topology = TerrainTopology(geometries=geometries) ``` ```python # Option 2: Coordinate triplets (programmatic) geometries = [ [[7.38, 44.64, 303.3], [7.38, 45.0, 320.2], [7.56, 44.82, 310.2]], [[7.38, 44.64, 303.3], [7.73, 44.64, 350.3], [7.56, 44.82, 310.2]], ] topology = TerrainTopology(geometries=geometries) ``` ```python # Option 3: Shapely polygons (interoperability with GIS libraries) from shapely.geometry import Polygon geometries = [ Polygon([(7.38, 44.64, 303.3), (7.38, 45.0, 320.2), (7.56, 44.82, 310.2)]), Polygon([(7.38, 44.64, 303.3), (7.73, 44.64, 350.3), (7.56, 44.82, 310.2)]), ] topology = TerrainTopology(geometries=geometries) ``` ```python # Option 4: WKB bytes (from spatial databases) geometries = [wkb_bytes_1, wkb_bytes_2] topology = TerrainTopology(geometries=geometries) ``` -------------------------------- ### Navigate Global Geodetic Tile Grid Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/QUICKSTART.md Use GlobalGeodetic to get tile bounds, find tiles for coordinates, determine resolution, and count tiles at a specific zoom level. Assumes TMS-compatible grid. ```python from quantized_mesh_tile.global_geodetic import GlobalGeodetic # Create TMS-compatible geodetic grid (like Cesium) geo = GlobalGeodetic(tmscompatible=True) # Get bounds for tile at z/y/x x, y, z = 533, 383, 9 west, south, east, north = geo.TileBounds(x, y, z) print(f"Tile bounds: {west}, {south}, {east}, {north}") # Find tile for a coordinate tx, ty = geo.LonLatToTile(lon=7.5, lat=44.8, zoom=9) print(f"Coordinate is in tile: {tx}, {ty}, {z}") # Resolution info res = geo.Resolution(zoom=9) print(f"Resolution at zoom 9: {res:.6f}°/pixel") # How many tiles at this zoom? num_x = geo.GetNumberOfXTilesAtZoom(9) num_y = geo.GetNumberOfYTilesAtZoom(9) print(f"Zoom 9: {num_x}×{num_y} tiles") ``` -------------------------------- ### Handle Quantized Mesh Tile Errors Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/QUICKSTART.md Demonstrates how to catch specific exceptions during tile encoding, such as missing dimensions or invalid geometries. Ensure you have the necessary imports for exceptions. ```python from quantized_mesh_tile import encode from quantized_mesh_tile.exceptions import ( InvalidGeometryError, MissingDimensionError, TerrainTileError ) try: tile = encode(geometries=my_geometries, bounds=bounds) except MissingDimensionError: print("Geometries must have Z dimension (height)") except InvalidGeometryError as e: print(f"Invalid geometry: {e}") except TerrainTileError as e: print(f"Tile creation failed: {e}") ``` -------------------------------- ### TerrainTile.fromFile Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/terrain-tile.md Reads a terrain tile directly from a file on disk, with options for handling lighting, watermask, and gzip compression. ```APIDOC ## TerrainTile.fromFile Method ### Description Reads a terrain tile from a file on disk. ### Method POST ### Endpoint `/fromFile` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **filePath** (str) - Required - Absolute or relative path to the tile file. - **hasLighting** (bool) - Optional - Whether tile contains lighting extension data. Defaults to False. - **hasWatermask** (bool) - Optional - Whether tile contains water mask data. Defaults to False. - **gzipped** (bool) - Optional - Whether the file is gzip-compressed. Defaults to False. ``` -------------------------------- ### Convert LLH to ECEF Coordinates Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/coordinate-conversion.md Converts geographic coordinates (WGS84 latitude/longitude/altitude) to ECEF cartesian coordinates. Requires importing the LLH2ECEF function. Examples demonstrate conversions for specific locations like Paris, the North Pole, and the Equator. ```python from quantized_mesh_tile.llh_ecef import LLH2ECEF # Convert Paris coordinates lon, lat, alt = 2.3522, 48.8566, 35.0 # 2.35°E, 48.86°N, 35m x, y, z = LLH2ECEF(lon, lat, alt) print(f"ECEF: ({x:.2f}, {y:.2f}, {z:.2f})") # Output: ECEF: (4201949.27, 176374.31, 4778297.98) # North Pole x, y, z = LLH2ECEF(0, 90, 0) print(f"North Pole ECEF: {z:.2f}") # ~6356752 m (semi-minor axis) # Equator at Prime Meridian x, y, z = LLH2ECEF(0, 0, 0) print(f"Equator ECEF: {x:.2f}") # ~6378137 m (semi-major axis) ``` -------------------------------- ### Create Quantized Mesh Tile Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/README.md Use this pattern to encode geometries into a quantized mesh tile and save it to a file. Ensure geometries are in a suitable format. ```python from quantized_mesh_tile import encode tile = encode(geometries=triangles, bounds=(west, south, east, north)) tile.toFile('output.terrain') ``` -------------------------------- ### Initialize TerrainTopology with Shapely Polygons Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/terrain-topology.md Instantiate TerrainTopology using Shapely Polygon objects. Polygons must have a Z dimension. This method is suitable when already working with Shapely geometries. ```python # Method 3: Using Shapely polygons from shapely.geometry import Polygon poly = Polygon([(7.38, 44.64, 303.3), (7.38, 45.0, 320.2), (7.56, 44.82, 310.2)]) topology = TerrainTopology(geometries=[poly]) ``` -------------------------------- ### BoundingSphere Constructor Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/bounding-sphere.md Initializes a BoundingSphere object with optional center coordinates and radius. The center is expected in ECEF format, and the radius is in meters. ```APIDOC ## BoundingSphere Constructor ### Description Initializes a BoundingSphere object with optional center coordinates and radius. The center is expected in ECEF format, and the radius is in meters. ### Parameters #### Path Parameters - **center** (list) - Optional - Initial center coordinates `[x, y, z]` in ECEF - **radius** (float) - Optional - Initial radius in meters ``` -------------------------------- ### Initialize TerrainTile Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/terrain-tile.md Instantiate a TerrainTile object. You can specify the tile's geographic bounds and optionally provide terrain topology, watermask data, or indicate its presence. ```python tile = TerrainTile( west=-180, south=-90, east=180, north=90 ) ``` -------------------------------- ### Module Organization Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/README.md Provides an overview of the project's directory structure and the purpose of each Python module. ```text quantized_mesh_tile/ ├── __init__.py # encode(), decode() entry points ├── terrain.py # TerrainTile class ├── topology.py # TerrainTopology class ├── bbsphere.py # BoundingSphere class ├── global_geodetic.py # GlobalGeodetic class ├── horizon_occlusion_point.py # Occlusion point calculation ├── llh_ecef.py # Coordinate conversion (LLH ↔ ECEF) ├── cartesian3d.py # 3D vector math operations ├── utils.py # Encoding, geometry, compression utilities └── exceptions.py # TerrainTileError, InvalidGeometryError, MissingDimensionError ``` -------------------------------- ### TerrainTopology Constructor Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/terrain-topology.md Initializes a TerrainTopology object. It can take an initial list of geometries and configuration options for geometry correction and lighting. ```APIDOC ## TerrainTopology Constructor ### Description Initializes a TerrainTopology object. It can take an initial list of geometries and configuration options for geometry correction and lighting. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **geometries** (list) - Optional - List of triangle geometries. Can be: shapely Polygons, WKT/WKB strings, or coordinate triplets `[((lon, lat, h), (lon, lat, h), (lon, lat, h)), ...]` - **autocorrectGeometries** (bool) - Optional - If True, attempts to fix non-triangular geometries by triangulating polygons with >3 vertices. Defaults to False. - **hasLighting** (bool) - Optional - If True, computes per-vertex unit normal vectors for lighting extension. Defaults to False. ``` -------------------------------- ### Convert Coordinates (WGS84, ECEF, Tile) Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/INDEX.md Demonstrates conversion between geodetic (longitude, latitude, altitude) and Earth-Centered, Earth-Fixed (ECEF) coordinate systems. Also shows how to convert geodetic coordinates to tile coordinates for a given zoom level. ```python from quantized_mesh_tile.llh_ecef import LLH2ECEF, ECEF2LLH from quantized_mesh_tile.global_geodetic import GlobalGeodetic # WGS84 to ECEF x, y, z = LLH2ECEF(lon=7.5, lat=44.8, alt=310.2) print(f"ECEF: ({x:.2f}, {y:.2f}, {z:.2f})") # ECEF back to WGS84 lon, lat, alt = ECEF2LLH(x, y, z) print(f"WGS84: ({lon:.4f}, {lat:.4f}, {alt:.1f}m)") # Tile coordinate lookup geodetic = GlobalGeodetic(tmscompatible=True) tx, ty = geodetic.LonLatToTile(lon=7.5, lat=44.8, zoom=9) print(f"Tile: {tx}, {ty}") ``` -------------------------------- ### Import Map Configuration Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/doc/source/viewer.md Defines module imports for Three.js and its addons, specifying CDN versions. ```html ``` -------------------------------- ### Manage Topology Directly and Create Terrain Tile Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/QUICKSTART.md Create a TerrainTile by directly managing its topology, including options for geometry correction and lighting. This allows for fine-grained control over tile generation. ```python from quantized_mesh_tile import TerrainTile from quantized_mesh_tile.topology import TerrainTopology # Build topology with options wkts = ['POLYGON Z ((7.38 44.64 303.3, 7.38 45.0 320.2, 7.56 44.82 310.2, 7.38 44.64 303.3))'] topology = TerrainTopology( geometries=wkts, autocorrectGeometries=False, hasLighting=True ) # Create tile from topology tile = TerrainTile( topology=topology, west=7.0, south=44.0, east=8.0, north=45.0, watermask=[0] ) # Check computed properties print(f"Vertices: {len(topology.vertices)}") print(f"Height range: {topology.minHeight:.1f}m to {topology.maxHeight:.1f}m") tile.toFile('output.terrain') ``` -------------------------------- ### TerrainTile Constructor Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/configuration.md Initializes a TerrainTile with geographic bounds and optional watermask data. Bounds define the tile's extent for coordinate quantization. ```python TerrainTile( west: float = -1.0, east: float = 1.0, south: float = -1.0, north: float = 1.0, topology: TerrainTopology = None, watermask: list = [], hasWatermask: bool = False ) ``` -------------------------------- ### toFile Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/terrain-tile.md Writes terrain tile data to a file on disk. Allows specifying the file path and whether the output should be gzipped. ```APIDOC ## toFile ### Description Writes terrain tile data to a file on disk. ### Method `toFile` ### Parameters #### Path Parameters - **filePath** (str) - Required - Absolute or relative path where tile should be written. #### Query Parameters - **gzipped** (bool) - Optional - Whether to compress file with gzip. Defaults to False. ### Raises `IOError` - if file already exists ### Example ```python tile = TerrainTile(topology=topology, west=-180, south=-90, east=180, north=90) tile.toFile('output/tile.terrain', gzipped=False) ``` ``` -------------------------------- ### Visualize Terrain Tile Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/doc/source/index.md Use this form to visualize the geometry of a single quantized mesh tile. Ensure CORS is enabled. Unit vectors are also displayed if present. ```html
``` ```javascript var reload = function(event) { var z, x, y, tileUrl, viewer; event.preventDefault(); event.stopPropagation(); z = event.target.z.value; x = event.target.x.value; y = event.target.y.value; tileUrl = event.target.tileUrl.value; viewer = 'viewer.html?z=' + z + '&x=' + x + '&y=' + y + '&tileUrl=' + encodeURIComponent(tileUrl); window.open(viewer); }; ``` -------------------------------- ### Horizon Occlusion Point Calculation Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/coordinate-conversion.md Illustrates converting geographic coordinates to ECEF, computing a bounding sphere, and then calculating the horizon occlusion point using these ECEF coordinates. ```python from quantized_mesh_tile.horizon_occlusion_point import fromPoints from quantized_mesh_tile.bbsphere import BoundingSphere from quantized_mesh_tile.llh_ecef import LLH2ECEF # Geographic coordinates lats = [44.6, 44.7, 44.8, 44.9, 45.0] lons = [7.3, 7.4, 7.5, 7.6, 7.7] heights = [300, 310, 320, 310, 300] # Convert to ECEF ecef_points = [LLH2ECEF(lon, lat, h) for lon, lat, h in zip(lons, lats, heights)] # Compute bounding sphere sphere = BoundingSphere() sphere.fromPoints(ecef_points) # Compute horizon occlusion point (uses ECEF-scaled coordinates) occ_point = fromPoints(ecef_points, sphere) print(f"Horizon occlusion point: {occ_point}") ``` -------------------------------- ### Initialize GlobalGeodetic Constructor Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/global-geodetic.md Instantiate the GlobalGeodetic class with TMS compatibility and tile size. Set `tmscompatible` to True for Cesium compatibility or False for WMTS standard. ```python GlobalGeodetic( tmscompatible: bool, tileSize: int = 256 ) ``` -------------------------------- ### Encode Basic Tile Data Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/QUICKSTART.md Create a quantized-mesh tile from a list of triangles and geographic bounds. Supports various geometry input formats. ```python from quantized_mesh_tile import encode # Define triangles (multiple formats supported) triangles = [ [[7.38, 44.64, 303.3], [7.38, 45.0, 320.2], [7.56, 44.82, 310.2]], [[7.38, 44.64, 303.3], [7.73, 44.64, 350.3], [7.56, 44.82, 310.2]], ] # Encode and write tile = encode( geometries=triangles, bounds=(7.0, 44.0, 8.0, 45.0), hasLighting=False, watermask=[] ) tile.toFile('output.terrain') ``` -------------------------------- ### BoundingSphere.fromPoints Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/bounding-sphere.md Computes the bounding sphere from a list of 3D points. It uses Ritter's algorithm for efficiency and refines the result with a naive sphere approach if it yields a smaller sphere. Points should be in ECEF coordinates. ```APIDOC ## BoundingSphere.fromPoints ### Description Computes the bounding sphere from a list of 3D points. It uses Ritter's algorithm for efficiency and refines the result with a naive sphere approach if it yields a smaller sphere. Points should be in ECEF coordinates. ### Method `self.fromPoints(points: list)` ### Parameters #### Path Parameters - **points** (list) - Required - List of 3D points as `[[x, y, z], ...]` or numpy array. Points should be in ECEF coordinates ### Raises `TerrainTileError` - if fewer than 2 points provided ### Behavior - Finds the axis-aligned span for each dimension (X, Y, Z) - Computes diameter endpoints from the largest span - Calculates Ritter sphere from diameter endpoints - Computes naive sphere from min/max bounding box - Returns the smaller of the two spheres ### Example ```python from quantized_mesh_tile.bbsphere import BoundingSphere # ECEF coordinates (from LLH2ECEF conversion) points = [ [4202615.64, 767000.1, 4546674.0], # Some ECEF point [4202617.0, 767005.0, 4546670.0], # Another ECEF point [4202620.0, 767010.0, 4546675.0], # Third point ] sphere = BoundingSphere() sphere.fromPoints(points) print(f"Center: {sphere.center}") print(f"Radius: {sphere.radius}m") ``` ``` -------------------------------- ### Read Terrain Tile from File Source: https://github.com/loicgasser/quantized-mesh-tile/blob/master/_autodocs/api-reference/terrain-tile.md Load terrain tile data directly from a file on disk. This method supports gzipped files and optional lighting/watermask extensions. ```python tile = TerrainTile(west=-180, south=-90, east=180, north=90) tile.fromFile('terrain/9/383/533.terrain', hasWatermask=True) ```