routeweave

MoonBit-native route encoding, GeoJSON export, route metrics, simplification, and Web Mercator tile coverage toolkit.

geojson
polyline
route
gps
mercator
map
moon add NBB2006/routeweave@0.2.0
Download zip
Author
Version
0.2.0
License
MIT
Last updated
5 hours ago
Downloads
3
README

#RouteWeave

RouteWeave 是一个 MoonBit 原生的路线数据工具库,用于把 GPS 点列转换成适合地图应用和轻量数据管线使用的格式。项目核心能力包括 Encoded Polyline 编解码、GeoJSON LineString/Feature 导出、路线距离计算、边界框计算、Douglas-Peucker 路线简化和 Web Mercator 瓦片覆盖。

#创新点

  • 不是轨迹模拟器,而是面向地图渲染、物流轨迹、离线瓦片缓存和 WebAssembly 前端的数据处理基础库。
  • 把“路线压缩、地图交换格式、空间范围、瓦片覆盖”放在同一个 MoonBit 包里,适合做端侧路线预处理。
  • 无第三方运行依赖,主要逻辑全部由 MoonBit 实现,便于发布到 mooncakes.io 后被其他 MoonBit 项目复用。

#主要功能

  • encode_polyline / decode_polyline:兼容常见 Encoded Polyline 算法,支持可配置精度。
  • to_geojson_linestring / to_geojson_feature:导出可被地图前端直接消费的 GeoJSON。
  • haversine_meters / route_distance_meters:计算点间和路线总距离。
  • bounding_box:生成路线经纬度边界框。
  • simplify_route:使用 Douglas-Peucker 算法减少路线点数。
  • point_to_tile / tile_cover:计算 Web Mercator 瓦片坐标和路线覆盖瓦片。
  • summarize_route:一次生成距离、边界框、编码结果、简化点数和瓦片清单。
  • route_stats / segment_metrics:生成路线总览、分段距离、方向角和弯曲度。
  • route_segment_spread / route_evenness_score:分析分段长度离散度,判断轨迹采样是否均匀。
  • sample_route_by_count / resample_route_every:按数量或固定距离对路线等距采样。
  • slice_route / split_route_by_distance:按里程裁切路线或拆分为多个子路线。
  • nearest_point_on_route / snap_point_to_route:把任意点投影、吸附到路线并计算沿线进度。
  • tile_bounds / tile_quadkey / tiles_for_bbox:提供瓦片边界、quadkey、bbox 覆盖等缓存辅助能力。
  • route_quality_report:检测重复点、停滞段、过长跳点、急转弯和自交风险。
  • route_report_geojson / tiles_to_geojson_feature_collection:导出带统计属性的 GeoJSON 调试数据。

#快速开始

从公开仓库获取项目后,在仓库根目录执行:

git clone https://github.com/NBB2006/routeweave.git cd routeweave

moon check moon build moon test moon run cmd/main

运行示例会输出路线摘要、压缩后的 polyline、瓦片覆盖和 GeoJSON。

项目页面:

  • GitHub: https://github.com/NBB2006/routeweave
  • mooncakes.io: https://mooncakes.io/docs/NBB2006/routeweave
  • API 文档:docs/API.md
  • 设计说明:docs/DESIGN.md
  • 发布清单:docs/RELEASE.md

#使用示例

let route = [
@routeweave.Point(31.23040, 121.47370),
@routeweave.Point(31.23120, 121.47800),
@routeweave.Point(31.23300, 121.48350),
]

let encoded = @routeweave.encode_polyline(route)
let geojson = @routeweave.to_geojson_feature(route, name="demo")
let summary = @routeweave.summarize_route(route, zoom=14)
let samples = @routeweave.sample_route_by_count(route, 5)
let spread = @routeweave.route_segment_spread(route)
let nearest = @routeweave.nearest_point_on_route(
@routeweave.Point(31.2320, 121.4800),
route,
)
let quality = @routeweave.route_quality_report(route)

命令行示例位于 cmd/main/main.mbt

#测试与 CI

项目包含可运行测试,覆盖标准 polyline 样例、异常输入、距离、边界框、GeoJSON、瓦片覆盖、路线简化、摘要输出、等距采样、路线裁切、最近点投影、瓦片工具和质量诊断。GitHub Actions 配置位于 .github/workflows/ci.yml,会执行:

moon fmt --check moon check --target all --deny-warn moon build moon test --target all --deny-warn moon run cmd/main moon info

moon info 用于检查公开接口信息是否能由当前源码正常生成;CI 使用 MoonBit 官方安装脚本和 Node.js,覆盖 wasm、wasm-gc、JavaScript 及 Native 目标,不依赖本地构建目录。

#功能边界

RouteWeave 专注于轻量路线处理,不做地图渲染、不联网下载瓦片、不提供数据库服务,也不替代完整 GIS 引擎。当前功能边界覆盖路线编码、交换格式导出、空间分析、瓦片缓存辅助、采样裁切、最近点投影、分段离散度分析和质量诊断;后续维护会围绕更多路线交换格式、更精细的瓦片覆盖算法和 WASM 使用示例展开。

#开源许可证

本项目使用 MIT License。当前实现不引入第三方代码、素材或运行依赖。仓库中的示例坐标为人工编写的公开演示数据,不包含个人轨迹或受限素材。

#
BBox

pub struct BBox {
min_lat : Double
min_lon : Double
max_lat : Double
max_lon : Double
}

Latitude/longitude bounding box in WGS84 degrees.

#
BBox::BBox

fn BBox::BBox(min_lat : Double, min_lon : Double, max_lat : Double, max_lon : Double) -> BBox

#
BBox::area_square_meters

fn BBox::area_square_meters(self : BBox) -> Result[Double, RouteError]

#
BBox::center

fn BBox::center(self : BBox) -> Point

#
BBox::contains

fn BBox::contains(self : BBox, point : Point) -> Bool

#
BBox::diagonal_meters

fn BBox::diagonal_meters(self : BBox) -> Result[Double, RouteError]

#
BBox::expand_to_include

fn BBox::expand_to_include(self : BBox, point : Point) -> Result[BBox, RouteError]

#
BBox::height_degrees

fn BBox::height_degrees(self : BBox) -> Double

#
BBox::merge

fn BBox::merge(self : BBox, other : BBox) -> BBox

#
BBox::pad_degrees

fn BBox::pad_degrees(self : BBox, padding : Double) -> Result[BBox, RouteError]

#
BBox::to_string

fn BBox::to_string(self : BBox) -> String

#
BBox::width_degrees

fn BBox::width_degrees(self : BBox) -> Double

#
NearestPoint

pub struct NearestPoint {
point : Point
distance_to_route_m : Double
distance_along_route_m : Double
segment_index : Int
fraction : Double
}

Nearest-point projection result for snapping a location onto a route.

#
NearestPoint::NearestPoint

fn NearestPoint::NearestPoint(point : Point, distance_to_route_m : Double, distance_along_route_m : Double, segment_index : Int, fraction : Double) -> NearestPoint

#
NearestPoint::to_string

fn NearestPoint::to_string(self : NearestPoint) -> String

#
Point

pub struct Point {
lat : Double
lon : Double
} derive(Eq)

WGS84 route point. Latitude and longitude are stored in degrees.

#
Point::Point

fn Point::Point(lat : Double, lon : Double) -> Point

#
Point::is_valid

fn Point::is_valid(self : Point) -> Bool

#
Point::to_string

fn Point::to_string(self : Point) -> String

#
RouteError

pub(all) enum RouteError {
EmptyRoute
InvalidCoordinate(index~ : Int, lat~ : Double, lon~ : Double)
InvalidPrecision(precision~ : Int)
InvalidZoom(zoom~ : Int)
InvalidTolerance(tolerance_m~ : Double)
InvalidDistance(distance_m~ : Double)
InvalidFraction(fraction~ : Double)
InvalidSegmentLength(length_m~ : Double)
InvalidSampleCount(count~ : Int)
InvalidTileCoordinate(tile~ : Tile)
MalformedPolyline(pos~ : Int, reason~ : String)
} derive(Eq)

Public error type shared by route codecs, metrics, simplification, and tiles.

#
RouteError::message

fn RouteError::message(self : RouteError) -> String

#
RouteIssue

pub struct RouteIssue {
index : Int
code : String
severity : Int
detail : String
}

#
RouteIssue::RouteIssue

fn RouteIssue::RouteIssue(index : Int, code : String, severity : Int, detail : String) -> RouteIssue

#
RouteIssue::to_string

fn RouteIssue::to_string(self : RouteIssue) -> String

#
RouteMarker

pub struct RouteMarker {
index : Int
point : Point
distance_m : Double
}

Cumulative distance marker at a concrete point on a route.

#
RouteMarker::RouteMarker

fn RouteMarker::RouteMarker(index : Int, point : Point, distance_m : Double) -> RouteMarker

#
RouteMarker::to_string

fn RouteMarker::to_string(self : RouteMarker) -> String

#
RouteQualityReport

pub struct RouteQualityReport {
point_count : Int
segment_count : Int
duplicate_points : Int
stationary_segments : Int
long_segments : Int
sharp_turns : Int
self_intersections : Int
score : Int
issues : Array[RouteIssue]
}

#
RouteQualityReport::report

fn RouteQualityReport::report(self : RouteQualityReport) -> String

#
RouteSample

pub struct RouteSample {
point : Point
distance_m : Double
segment_index : Int
fraction : Double
}

Sample generated from a route at a requested distance.

#
RouteSample::RouteSample

fn RouteSample::RouteSample(point : Point, distance_m : Double, segment_index : Int, fraction : Double) -> RouteSample

#
RouteSample::to_string

fn RouteSample::to_string(self : RouteSample) -> String

#
RouteSlice

pub struct RouteSlice {
start_m : Double
end_m : Double
distance_m : Double
points : Array[Point]
}

Result of cutting a route between two distances.

#
RouteSlice::RouteSlice

fn RouteSlice::RouteSlice(start_m : Double, end_m : Double, distance_m : Double, points : Array[Point]) -> RouteSlice

#
RouteSlice::to_string

fn RouteSlice::to_string(self : RouteSlice) -> String

#
RouteStats

pub struct RouteStats {
point_count : Int
segment_count : Int
distance_m : Double
direct_distance_m : Double
sinuosity : Double
min_segment_m : Double
max_segment_m : Double
average_segment_m : Double
bbox : BBox
center : Point
}

Aggregate route statistics for dashboards and validation records.

#
RouteStats::RouteStats

fn RouteStats::RouteStats(point_count : Int, segment_count : Int, distance_m : Double, direct_distance_m : Double, sinuosity : Double, min_segment_m : Double, max_segment_m : Double, average_segment_m : Double, bbox : BBox, center : Point) -> RouteStats

#
RouteStats::report

fn RouteStats::report(self : RouteStats) -> String

#
RouteSummary

pub struct RouteSummary {
point_count : Int
simplified_point_count : Int
distance_m : Double
bbox : BBox
encoded_polyline : String
tiles : Array[Tile]
zoom : Int
}

Compact summary for one route and one tile zoom level.

#
RouteSummary::report

fn RouteSummary::report(self : RouteSummary) -> String

#
SegmentMetric

pub struct SegmentMetric {
index : Int
start : Point
finish : Point
distance_m : Double
bearing_deg : Double
}

Per-segment route metrics, useful for route tables and diagnostics.

#
SegmentMetric::SegmentMetric

fn SegmentMetric::SegmentMetric(index : Int, start : Point, finish : Point, distance_m : Double, bearing_deg : Double) -> SegmentMetric

#
SegmentMetric::to_string

fn SegmentMetric::to_string(self : SegmentMetric) -> String

#
SegmentSpread

pub struct SegmentSpread {
segment_count : Int
total_distance_m : Double
shortest_segment_m : Double
longest_segment_m : Double
average_segment_m : Double
standard_deviation_m : Double
coefficient_of_variation : Double
longest_segment_index : Int
}

Distribution summary for route segment lengths.

#
SegmentSpread::SegmentSpread

fn SegmentSpread::SegmentSpread(segment_count : Int, total_distance_m : Double, shortest_segment_m : Double, longest_segment_m : Double, average_segment_m : Double, standard_deviation_m : Double, coefficient_of_variation : Double, longest_segment_index : Int) -> SegmentSpread

#
SegmentSpread::to_string

fn SegmentSpread::to_string(self : SegmentSpread) -> String

#
Tile

pub struct Tile {
z : Int
x : Int
y : Int
} derive(Eq)

Slippy-map tile coordinate in the Web Mercator tiling scheme.

#
Tile::Tile

fn Tile::Tile(z : Int, x : Int, y : Int) -> Tile

#
Tile::key

fn Tile::key(self : Tile) -> String

#
Tile::to_string

fn Tile::to_string(self : Tile) -> String

#
TileBounds

pub struct TileBounds {
tile : Tile
west : Double
south : Double
east : Double
north : Double
}

Geographic bounds of one Web Mercator tile.

#
TileBounds::TileBounds

fn TileBounds::TileBounds(tile : Tile, west : Double, south : Double, east : Double, north : Double) -> TileBounds

#
TileBounds::to_bbox

fn TileBounds::to_bbox(self : TileBounds) -> BBox

#
TileRange

pub struct TileRange {
z : Int
min_x : Int
min_y : Int
max_x : Int
max_y : Int
}

Inclusive tile coordinate range for a bounding box at one zoom level.

#
TileRange::TileRange

fn TileRange::TileRange(z : Int, min_x : Int, min_y : Int, max_x : Int, max_y : Int) -> TileRange

#
TileRange::to_string

fn TileRange::to_string(self : TileRange) -> String

#
along_track_distance_meters

fn along_track_distance_meters(query : Point, start : Point, finish : Point) -> Result[Double, RouteError]

#
bearing_delta_degrees

fn bearing_delta_degrees(from : Double, to : Double) -> Double

#
bounding_box

fn bounding_box(points : ArrayView[Point]) -> Result[BBox, RouteError]

#
close_route

fn close_route(points : ArrayView[Point]) -> Result[Array[Point], RouteError]

#
compass_direction

fn compass_direction(bearing_deg : Double) -> String

#
cross_track_distance_meters

fn cross_track_distance_meters(query : Point, start : Point, finish : Point) -> Result[Double, RouteError]

#
cumulative_distances

fn cumulative_distances(points : ArrayView[Point]) -> Result[Array[Double], RouteError]

#
cumulative_markers

fn cumulative_markers(points : ArrayView[Point]) -> Result[Array[RouteMarker], RouteError]

#
decode_polyline

fn decode_polyline(encoded : String, precision? : Int) -> Result[Array[Point], RouteError]

#
decode_polyline5

fn decode_polyline5(encoded : String) -> Result[Array[Point], RouteError]

#
degrees_to_radians

fn degrees_to_radians(value : Double) -> Double

#
densify_route

fn densify_route(points : ArrayView[Point], max_segment_m : Double) -> Result[Array[Point], RouteError]

#
distance_to_route_meters

fn distance_to_route_meters(query : Point, route : ArrayView[Point]) -> Result[Double, RouteError]

#
duplicate_point_indices

fn duplicate_point_indices(points : ArrayView[Point]) -> Result[Array[Int], RouteError]

#
encode_polyline

fn encode_polyline(points : ArrayView[Point], precision? : Int) -> Result[String, RouteError]

#
encode_polyline5

fn encode_polyline5(points : ArrayView[Point]) -> Result[String, RouteError]

#
expand_tiles_with_neighbors

fn expand_tiles_with_neighbors(tiles : ArrayView[Tile]) -> Result[Array[Tile], RouteError]

#
final_bearing_degrees

fn final_bearing_degrees(a : Point, b : Point) -> Result[Double, RouteError]

#
haversine_meters

fn haversine_meters(a : Point, b : Point) -> Result[Double, RouteError]

#
initial_bearing_degrees

fn initial_bearing_degrees(a : Point, b : Point) -> Result[Double, RouteError]

#
interpolate_point

fn interpolate_point(start : Point, finish : Point, fraction : Double) -> Result[Point, RouteError]

#
is_closed_route

fn is_closed_route(points : ArrayView[Point]) -> Result[Bool, RouteError]

#
is_point_near_route

fn is_point_near_route(query : Point, route : ArrayView[Point], tolerance_m : Double) -> Result[Bool, RouteError]

#
kilometers_to_meters

fn kilometers_to_meters(value : Double) -> Double

#
long_segment_indices

fn long_segment_indices(points : ArrayView[Point], max_segment_m : Double) -> Result[Array[Int], RouteError]

#
meters_to_kilometers

fn meters_to_kilometers(value : Double) -> Double

#
meters_to_miles

fn meters_to_miles(value : Double) -> Double

#
miles_to_meters

fn miles_to_meters(value : Double) -> Double

#
nearest_point_on_route

fn nearest_point_on_route(query : Point, route : ArrayView[Point]) -> Result[NearestPoint, RouteError]

#
nearest_points_to_geojson_feature_collection

fn nearest_points_to_geojson_feature_collection(points : ArrayView[NearestPoint], name? : String) -> Result[String, RouteError]

#
normalize_bearing_degrees

fn normalize_bearing_degrees(value : Double) -> Double

#
point_at_distance

fn point_at_distance(points : ArrayView[Point], distance_m : Double) -> Result[RouteSample, RouteError]

#
point_to_tile

fn point_to_tile(point : Point, zoom : Int) -> Result[Tile, RouteError]

#
points_within_route_buffer

fn points_within_route_buffer(queries : ArrayView[Point], route : ArrayView[Point], tolerance_m : Double) -> Result[Array[Point], RouteError]

#
prefix_route

fn prefix_route(points : ArrayView[Point], distance_m : Double) -> Result[RouteSlice, RouteError]

#
quadkey_to_tile

fn quadkey_to_tile(quadkey : String) -> Result[Tile, RouteError]

#
radians_to_degrees

fn radians_to_degrees(value : Double) -> Double

#
remove_consecutive_duplicates

fn remove_consecutive_duplicates(points : ArrayView[Point]) -> Result[Array[Point], RouteError]

#
remove_stationary_segments

fn remove_stationary_segments(points : ArrayView[Point], threshold_m? : Double) -> Result[Array[Point], RouteError]

#
resample_route_by_count

fn resample_route_by_count(points : ArrayView[Point], count : Int) -> Result[Array[Point], RouteError]

#
resample_route_every

fn resample_route_every(points : ArrayView[Point], interval_m : Double, include_end? : Bool) -> Result[Array[Point], RouteError]

#
reverse_route

fn reverse_route(points : ArrayView[Point]) -> Result[Array[Point], RouteError]

#
round_meters

fn round_meters(value : Double) -> Int

#
route_absolute_turn_degrees

fn route_absolute_turn_degrees(points : ArrayView[Point]) -> Result[Double, RouteError]

#
route_bearings

fn route_bearings(points : ArrayView[Point]) -> Result[Array[Double], RouteError]

#
route_centroid

fn route_centroid(points : ArrayView[Point]) -> Result[Point, RouteError]

#
route_debug_bundle_geojson

fn route_debug_bundle_geojson(route : ArrayView[Point], zoom? : Int) -> Result[String, RouteError]

#
route_distance_along_for_point

fn route_distance_along_for_point(query : Point, route : ArrayView[Point]) -> Result[Double, RouteError]

#
route_distance_meters

fn route_distance_meters(points : ArrayView[Point]) -> Result[Double, RouteError]

#
route_endpoints

fn route_endpoints(points : ArrayView[Point]) -> Result[(Point, Point), RouteError]

#
route_evenness_score

fn route_evenness_score(points : ArrayView[Point]) -> Result[Int, RouteError]

#
route_is_evenly_sampled

fn route_is_evenly_sampled(points : ArrayView[Point], max_coefficient_of_variation? : Double) -> Result[Bool, RouteError]

#
route_midpoint

fn route_midpoint(points : ArrayView[Point]) -> Result[RouteSample, RouteError]

#
route_progress_fraction

fn route_progress_fraction(query : Point, route : ArrayView[Point]) -> Result[Double, RouteError]

#
route_quality_issues

fn route_quality_issues(points : ArrayView[Point], stationary_threshold_m? : Double, max_segment_m? : Double, sharp_turn_deg? : Double) -> Result[Array[RouteIssue], RouteError]

#
route_quality_report

fn route_quality_report(points : ArrayView[Point], stationary_threshold_m? : Double, max_segment_m? : Double, sharp_turn_deg? : Double) -> Result[RouteQualityReport, RouteError]

#
route_report_geojson

fn route_report_geojson(route : ArrayView[Point], zoom? : Int, name? : String) -> Result[String, RouteError]

#
route_segment_distances

fn route_segment_distances(points : ArrayView[Point]) -> Result[Array[Double], RouteError]

#
route_segment_spread

fn route_segment_spread(points : ArrayView[Point]) -> Result[SegmentSpread, RouteError]

#
route_station_for_fraction

fn route_station_for_fraction(route : ArrayView[Point], fraction : Double) -> Result[RouteSample, RouteError]

#
route_station_points

fn route_station_points(route : ArrayView[Point], fractions : ArrayView[Double]) -> Result[Array[RouteSample], RouteError]

#
route_stats

fn route_stats(points : ArrayView[Point]) -> Result[RouteStats, RouteError]

#
route_tile_bounds

fn route_tile_bounds(points : ArrayView[Point], zoom : Int) -> Result[BBox, RouteError]

#
route_tile_range

fn route_tile_range(points : ArrayView[Point], zoom : Int) -> Result[TileRange, RouteError]

#
route_turn_angles

fn route_turn_angles(points : ArrayView[Point]) -> Result[Array[Double], RouteError]

#
routes_to_geojson_feature_collection

fn routes_to_geojson_feature_collection(routes : ArrayView[Array[Point]], name_prefix? : String) -> Result[String, RouteError]

#
sample_route_by_count

fn sample_route_by_count(points : ArrayView[Point], count : Int) -> Result[Array[RouteSample], RouteError]

#
sample_route_every

fn sample_route_every(points : ArrayView[Point], interval_m : Double, include_end? : Bool) -> Result[Array[RouteSample], RouteError]

#
samples_to_geojson_feature_collection

fn samples_to_geojson_feature_collection(samples : ArrayView[RouteSample], name? : String) -> Result[String, RouteError]

#
segment_fraction_for_projection

fn segment_fraction_for_projection(query : Point, start : Point, finish : Point) -> Result[Double, RouteError]

#
segment_metric

fn segment_metric(start : Point, finish : Point, index? : Int) -> Result[SegmentMetric, RouteError]

#
segment_metrics

fn segment_metrics(points : ArrayView[Point]) -> Result[Array[SegmentMetric], RouteError]

#
self_intersection_count

fn self_intersection_count(points : ArrayView[Point]) -> Result[Int, RouteError]

#
sharp_turn_indices

fn sharp_turn_indices(points : ArrayView[Point], threshold_deg? : Double) -> Result[Array[Int], RouteError]

#
simplify_route

fn simplify_route(points : ArrayView[Point], tolerance_m? : Double) -> Result[Array[Point], RouteError]

#
slice_route

fn slice_route(points : ArrayView[Point], start_m : Double, end_m : Double) -> Result[RouteSlice, RouteError]

#
smooth_route_window

fn smooth_route_window(points : ArrayView[Point], radius : Int) -> Result[Array[Point], RouteError]

#
snap_point_to_route

fn snap_point_to_route(query : Point, route : ArrayView[Point]) -> Result[Point, RouteError]

#
snap_points_to_route

fn snap_points_to_route(queries : ArrayView[Point], route : ArrayView[Point]) -> Result[Array[NearestPoint], RouteError]

#
split_route_by_count

fn split_route_by_count(points : ArrayView[Point], count : Int) -> Result[Array[RouteSlice], RouteError]

#
split_route_by_distance

fn split_route_by_distance(points : ArrayView[Point], max_slice_m : Double) -> Result[Array[RouteSlice], RouteError]

#
stationary_segment_indices

fn stationary_segment_indices(points : ArrayView[Point], threshold_m? : Double) -> Result[Array[Int], RouteError]

#
suffix_route

fn suffix_route(points : ArrayView[Point], distance_m : Double) -> Result[RouteSlice, RouteError]

#
summarize_route

fn summarize_route(points : ArrayView[Point], zoom? : Int, simplify_tolerance_m? : Double) -> Result[RouteSummary, RouteError]

#
tile_bounds

fn tile_bounds(tile : Tile) -> Result[TileBounds, RouteError]

#
tile_center

fn tile_center(tile : Tile) -> Result[Point, RouteError]

#
tile_children

fn tile_children(tile : Tile) -> Result[Array[Tile], RouteError]

#
tile_count_for_range

fn tile_count_for_range(range : TileRange) -> Result[Int, RouteError]

#
tile_cover

fn tile_cover(points : ArrayView[Point], zoom : Int) -> Result[Array[Tile], RouteError]

#
tile_neighbors

fn tile_neighbors(tile : Tile) -> Result[Array[Tile], RouteError]

#
tile_parent

fn tile_parent(tile : Tile) -> Result[Tile, RouteError]

#
tile_quadkey

fn tile_quadkey(tile : Tile) -> Result[String, RouteError]

#
tile_range_for_bbox

fn tile_range_for_bbox(bbox : BBox, zoom : Int) -> Result[TileRange, RouteError]

#
tile_range_to_string

fn tile_range_to_string(range : TileRange) -> String

#
tiles_for_bbox

fn tiles_for_bbox(bbox : BBox, zoom : Int) -> Result[Array[Tile], RouteError]

#
tiles_for_range

fn tiles_for_range(range : TileRange) -> Result[Array[Tile], RouteError]

#
tiles_to_geojson_feature_collection

fn tiles_to_geojson_feature_collection(tiles : ArrayView[Tile], name? : String) -> Result[String, RouteError]

#
tiles_to_string

fn tiles_to_string(tiles : ArrayView[Tile]) -> String

#
to_geojson_bbox_feature

fn to_geojson_bbox_feature(bbox : BBox, name? : String) -> Result[String, RouteError]

#
to_geojson_bbox_polygon

fn to_geojson_bbox_polygon(bbox : BBox) -> Result[String, RouteError]

#
to_geojson_feature

fn to_geojson_feature(points : ArrayView[Point], name? : String) -> Result[String, RouteError]

#
to_geojson_linestring

fn to_geojson_linestring(points : ArrayView[Point]) -> Result[String, RouteError]

#
to_geojson_multipoint

fn to_geojson_multipoint(points : ArrayView[Point]) -> Result[String, RouteError]

#
to_geojson_point

fn to_geojson_point(point : Point) -> Result[String, RouteError]