///|
/// Re-export of all public types and functions from sub-packages.
/// Users can import a single package `walkzzz/moon-geometry` to access all APIs.
///
/// 重导出所有子包的公开类型和函数。
/// 用户只需导入单个包 `walkzzz/moon-geometry` 即可访问全部 API。

///|
/// 2D point. / 二维点。
pub type Point2D = @core.Point2D

///|
/// 3D point. / 三维点。
pub type Point3D = @core.Point3D

///|
/// Line segment. / 线段。
pub type Segment = @core.Segment

///|
/// Infinite line (a*x + b*y + c = 0). / 无限直线。
pub type Line = @core.Line

///|
/// Polygon. / 多边形。
pub type Polygon = @core.Polygon

///|
/// Triangle. / 三角形。
pub type Triangle = @core.Triangle

///|
/// Circle-segment intersection points (0/1/2). / 圆与线段交点。
pub fn circle_segment_intersect(
  circle : Circle,
  seg : Segment,
) -> Array[Point2D] {
  @circle_ops.circle_segment_intersect(circle, seg)
}

///|
/// Circle-circle intersection points (0/1/2). / 两圆交点。
pub fn circle_circle_intersect(c1 : Circle, c2 : Circle) -> Array[Point2D] {
  @circle_ops.circle_circle_intersect(c1, c2)
}

///|
/// Circle-line intersection points (0/1/2). / 圆与直线交点。
pub fn circle_line_intersect(circle : Circle, line : Line) -> Array[Point2D] {
  @circle_ops.circle_line_intersect(circle, line)
}

///|
/// Circle-polygon boundary intersection points. / 圆与多边形边界交点。
pub fn circle_polygon_intersect(
  circle : Circle,
  poly : Polygon,
) -> Array[Point2D] {
  @circle_ops.circle_polygon_intersect(circle, poly)
}
// ---------------------------------------------------------------------------
// triangulate: polygon triangulation / 多边形三角剖分
// ---------------------------------------------------------------------------

///|
/// Triangulate a simple polygon via ear clipping.
/// Returns vertex index triples. / 简单多边形三角剖分(ear clipping),返回顶点索引三元组。
pub fn triangulate_polygon(poly : Polygon) -> Array[(Int32, Int32, Int32)] {
  @triangulate.triangulate_polygon(poly)
}
// ---------------------------------------------------------------------------
// minkowski: Minkowski operations / Minkowski 运算
// ---------------------------------------------------------------------------

///|
/// Minkowski sum of two convex polygons. / 两个凸多边形的 Minkowski 和。
pub fn minkowski_sum_convex(poly1 : Polygon, poly2 : Polygon) -> Array[Point2D] {
  @minkowski.minkowski_sum_convex(poly1, poly2)
}

///|
/// Minkowski difference of two convex polygons. / 两个凸多边形的 Minkowski 差。
pub fn minkowski_difference_convex(
  poly1 : Polygon,
  poly2 : Polygon,
) -> Array[Point2D] {
  @minkowski.minkowski_difference_convex(poly1, poly2)
}

///|
pub fn cover_tree_count(tree : CoverTree) -> Int32 {
  @cover_tree.cover_tree_count(tree)
}

// ---------------------------------------------------------------------------
// interval_tree: Interval tree / 区间树
// ---------------------------------------------------------------------------

///|
pub type IntervalEntry = @interval_tree.Interval

///|
pub type IntervalNode = @interval_tree.IntervalNode

///|
pub fn interval_tree_build(intervals : Array[IntervalEntry]) -> IntervalNode? {
  @interval_tree.interval_tree_build(intervals)
}

///|
pub fn interval_tree_query(
  node : IntervalNode?,
  x : Double,
) -> Array[IntervalEntry] {
  @interval_tree.interval_tree_query(node, x)
}

///|
pub fn interval_tree_count(node : IntervalNode?) -> Int32 {
  @interval_tree.interval_tree_count(node)
}

// ---------------------------------------------------------------------------
// skip_quadtree: Skip quadtree / 跳跃四叉树
// ---------------------------------------------------------------------------

///|

///|
pub type SkipQuadtree = @skip_quadtree.SkipQuadtree

///|
pub fn skip_quadtree_new(
  cx : Double,
  cy : Double,
  size : Double,
  max_level : Int32,
) -> SkipQuadtree {
  @skip_quadtree.skip_quadtree_new(cx, cy, size, max_level)
}

///|
pub fn skip_quadtree_insert(tree : SkipQuadtree, p : Point2D) -> Unit {
  @skip_quadtree.skip_quadtree_insert(tree, p)
}

///|
pub fn skip_quadtree_query(
  tree : SkipQuadtree,
  min_x : Double,
  min_y : Double,
  max_x : Double,
  max_y : Double,
) -> Array[Point2D] {
  @skip_quadtree.skip_quadtree_query(tree, min_x, min_y, max_x, max_y)
}

///|
pub fn skip_quadtree_count(tree : SkipQuadtree) -> Int32 {
  @skip_quadtree.skip_quadtree_count(tree)
}

// ---------------------------------------------------------------------------
// loose_octree: Loose octree / 松散八叉树
// ---------------------------------------------------------------------------

///|
pub type LooseOctNode = @loose_octree.LooseOctNode

///|
pub fn loose_octree_new(
  cx : Double,
  cy : Double,
  cz : Double,
  size : Double,
  loose_factor : Double,
  max_depth : Int32,
) -> LooseOctNode {
  @loose_octree.loose_octree_new(cx, cy, cz, size, loose_factor, max_depth)
}

///|
pub fn loose_octree_insert(node : LooseOctNode, p : Point3D) -> Unit {
  @loose_octree.loose_octree_insert(node, p)
} ///|

///|
pub fn loose_octree_query(
  node : LooseOctNode,
  min_x : Double,
  min_y : Double,
  min_z : Double,
  max_x : Double,
  max_y : Double,
  max_z : Double,
) -> Array[Point3D] {
  @loose_octree.loose_octree_query(
    node, min_x, min_y, min_z, max_x, max_y, max_z,
  )
}

///|
pub fn loose_octree_count(node : LooseOctNode) -> Int32 {
  @loose_octree.loose_octree_count(node)
}
// ---------------------------------------------------------------------------
// shortest_path: Dijkstra shortest path / Dijkstra 最短路径
// ---------------------------------------------------------------------------

///|
pub type GraphEdge = @shortest_path.GraphEdge

///|
pub fn dijkstra(
  n : Int32,
  adj : Array[Array[GraphEdge]],
  src : Int32,
) -> Array[Double] {
  @shortest_path.dijkstra(n, adj, src)
}

///|
pub fn shortest_path_dist(
  n : Int32,
  adj : Array[Array[GraphEdge]],
  src : Int32,
  dst : Int32,
) -> Double {
  @shortest_path.shortest_path_dist(n, adj, src, dst)
}

///|
pub fn shortest_path_vertices(
  n : Int32,
  adj : Array[Array[GraphEdge]],
  src : Int32,
  dst : Int32,
) -> Array[Int32] {
  @shortest_path.shortest_path_vertices(n, adj, src, dst)
}

// ---------------------------------------------------------------------------
// visibility_graph: Visibility graph / 可见性图
// ---------------------------------------------------------------------------

///|
pub fn build_visibility_graph(
  obstacles : Array[Array[Point2D]],
  start : Point2D,
  goal : Point2D,
) -> Array[Array[(Int32, Double)]] {
  @visibility_graph.build_visibility_graph(obstacles, start, goal)
} ///|

///|
pub fn visibility_vertices(
  obstacles : Array[Array[Point2D]],
  start : Point2D,
  goal : Point2D,
) -> Array[Point2D] {
  @visibility_graph.visibility_vertices(obstacles, start, goal)
}

///|
pub fn visibility_edge_count(
  obstacles : Array[Array[Point2D]],
  start : Point2D,
  goal : Point2D,
) -> Int32 {
  @visibility_graph.visibility_edge_count(obstacles, start, goal)
}

// ---------------------------------------------------------------------------
// motion_plan: Motion planning / 运动规划
// ---------------------------------------------------------------------------

///|
pub fn plan_path(
  obstacles : Array[Array[Point2D]],
  start : Point2D,
  goal : Point2D,
) -> Array[Point2D] {
  @motion_plan.plan_path(obstacles, start, goal)
}

///|
pub fn path_length(path : Array[Point2D]) -> Double {
  @motion_plan.path_length(path)
}

///|
pub fn is_path_valid(
  path : Array[Point2D],
  obstacles : Array[Array[Point2D]],
) -> Bool {
  @motion_plan.is_path_valid(path, obstacles)
}

// ---------------------------------------------------------------------------
// voronoi_adv: Advanced Voronoi / 高级 Voronoi
// ---------------------------------------------------------------------------

///|
pub fn voronoi_cell(
  sites : Array[Point2D],
  site_idx : Int32,
  bounds : (Point2D, Point2D),
) -> Array[Point2D] {
  @voronoi_adv.voronoi_cell(sites, site_idx, bounds)
}

///|
pub fn farthest_voronoi_cell(
  sites : Array[Point2D],
  site_idx : Int32,
  bounds : (Point2D, Point2D),
) -> Array[Point2D] {
  @voronoi_adv.farthest_voronoi_cell(sites, site_idx, bounds)
} ///|

///|
pub fn voronoi_cell_area(
  sites : Array[Point2D],
  site_idx : Int32,
  bounds : (Point2D, Point2D),
) -> Double {
  @voronoi_adv.voronoi_cell_area(sites, site_idx, bounds)
}

///|
pub fn voronoi_cell_count(sites : Array[Point2D]) -> Int32 {
  @voronoi_adv.voronoi_cell_count(sites)
}

// ---------------------------------------------------------------------------
// delaunay_refine: Delaunay refinement / Delaunay 细化
// ---------------------------------------------------------------------------

///|
pub fn delaunay_refine(
  pts : Array[Point2D],
  min_angle : Double,
  max_iter : Int32,
) -> Array[Point2D] {
  @delaunay_refine.delaunay_refine(pts, min_angle, max_iter)
}

///|
pub fn circumcenter(a : Point2D, b : Point2D, c : Point2D) -> Point2D {
  @delaunay_refine.circumcenter(a, b, c)
}

///|
pub fn min_triangle_angle(a : Point2D, b : Point2D, c : Point2D) -> Double {
  @delaunay_refine.min_triangle_angle(a, b, c)
}

///|
pub fn delaunay_triangle_count(pts : Array[Point2D]) -> Int32 {
  @delaunay_refine.triangle_count(pts)
}

// ---------------------------------------------------------------------------
// graph_color: Graph coloring / 图着色
// ---------------------------------------------------------------------------

///|
pub fn greedy_color(n : Int32, adj : Array[Array[Int32]]) -> Array[Int32] {
  @graph_color.greedy_color(n, adj)
} ///|

///|
pub fn chromatic_number_upper(n : Int32, adj : Array[Array[Int32]]) -> Int32 {
  @graph_color.chromatic_number_upper(n, adj)
}

///|
pub fn is_valid_coloring(
  n : Int32,
  adj : Array[Array[Int32]],
  colors : Array[Int32],
) -> Bool {
  @graph_color.is_valid_coloring(n, adj, colors)
}

///|
pub fn is_bipartite(n : Int32, adj : Array[Array[Int32]]) -> Bool {
  @graph_color.is_bipartite(n, adj)
}

// ---------------------------------------------------------------------------
// graph_cut: Graph cut / 图割
// ---------------------------------------------------------------------------

///|
pub fn max_flow(
  n : Int32,
  capacity : Array[Array[Double]],
  src : Int32,
  sink : Int32,
) -> Double {
  @graph_cut.max_flow(n, capacity, src, sink)
}

///|
pub fn min_cut(
  n : Int32,
  capacity : Array[Array[Double]],
  src : Int32,
  sink : Int32,
) -> Double {
  @graph_cut.min_cut(n, capacity, src, sink)
}

///|
pub fn min_cut_partition(
  n : Int32,
  capacity : Array[Array[Double]],
  src : Int32,
  sink : Int32,
) -> Array[Int32] {
  @graph_cut.min_cut_partition(n, capacity, src, sink)
}

// ---------------------------------------------------------------------------
// spanning_tree: Minimum spanning tree / 最小生成树
// ---------------------------------------------------------------------------

///|

///|
pub type WEdge = @spanning_tree.WEdge

///|
pub fn kruskal_mst(n : Int32, edges : Array[WEdge]) -> Array[WEdge] {
  @spanning_tree.kruskal_mst(n, edges)
}

///|
pub fn mst_weight(n : Int32, edges : Array[WEdge]) -> Double {
  @spanning_tree.mst_weight(n, edges)
}

///|
pub fn mst_edge_count(n : Int32, edges : Array[WEdge]) -> Int32 {
  @spanning_tree.mst_edge_count(n, edges)
}

///|
pub fn is_connected(n : Int32, edges : Array[WEdge]) -> Bool {
  @spanning_tree.is_connected(n, edges)
}

// ---------------------------------------------------------------------------
// polynomial: Polynomial operations / 多项式运算
// ---------------------------------------------------------------------------

///|
pub fn poly_eval(coeffs : Array[Double], x : Double) -> Double {
  @polynomial.poly_eval(coeffs, x)
}

///|
pub fn poly_derivative(coeffs : Array[Double]) -> Array[Double] {
  @polynomial.poly_derivative(coeffs)
}

///|
pub fn poly_add(a : Array[Double], b : Array[Double]) -> Array[Double] {
  @polynomial.poly_add(a, b)
} ///|

///|
pub fn poly_mul(a : Array[Double], b : Array[Double]) -> Array[Double] {
  @polynomial.poly_mul(a, b)
}

///|
pub fn poly_roots(coeffs : Array[Double]) -> Array[Double] {
  @polynomial.poly_roots(coeffs)
}

// ---------------------------------------------------------------------------
// root_find: Root finding / 求根
// ---------------------------------------------------------------------------

///|
pub fn bisection(
  f : (Double) -> Double,
  lo : Double,
  hi : Double,
  max_iter : Int32,
) -> Double {
  @root_find.bisection(f, lo, hi, max_iter)
}

///|
pub fn newton(
  f : (Double) -> Double,
  fp : (Double) -> Double,
  x0 : Double,
  max_iter : Int32,
) -> Double {
  @root_find.newton(f, fp, x0, max_iter)
}

///|
pub fn secant(
  f : (Double) -> Double,
  x0 : Double,
  x1 : Double,
  max_iter : Int32,
) -> Double {
  @root_find.secant(f, x0, x1, max_iter)
}

///|
pub fn find_all_roots(
  f : (Double) -> Double,
  lo : Double,
  hi : Double,
  n_samples : Int32,
) -> Array[Double] {
  @root_find.find_all_roots(f, lo, hi, n_samples)
}

// ---------------------------------------------------------------------------
// integration: Numerical integration / 数值积分
// ---------------------------------------------------------------------------

// ---------------------------------------------------------------------------
// differentiation: Numerical differentiation / 数值微分
// ---------------------------------------------------------------------------

// ---------------------------------------------------------------------------
// interpolation: Interpolation / 插值
// ---------------------------------------------------------------------------

///|
pub fn lagrange_interp(
  xs : Array[Double],
  ys : Array[Double],
  x : Double,
) -> Double {
  @interpolation.lagrange_interp(xs, ys, x)
} ///|

///|
pub fn newton_divdiff(xs : Array[Double], ys : Array[Double]) -> Array[Double] {
  @interpolation.newton_divdiff(xs, ys)
}

///|
pub fn newton_interp(
  xs : Array[Double],
  ys : Array[Double],
  x : Double,
) -> Double {
  @interpolation.newton_interp(xs, ys, x)
}

///|
pub fn linear_interp(
  x0 : Double,
  y0 : Double,
  x1 : Double,
  y1 : Double,
  x : Double,
) -> Double {
  @interpolation.linear_interp(x0, y0, x1, y1, x)
}

///|
pub fn bilinear_interp(
  x0 : Double,
  x1 : Double,
  y0 : Double,
  y1 : Double,
  f00 : Double,
  f10 : Double,
  f01 : Double,
  f11 : Double,
  x : Double,
  y : Double,
) -> Double {
  @interpolation.bilinear_interp(x0, x1, y0, y1, f00, f10, f01, f11, x, y)
}

// ---------------------------------------------------------------------------
// eigen: Eigenvalue computation / 特征值计算
// ---------------------------------------------------------------------------

///|
pub fn power_iteration(
  matrix : Array[Array[Double]],
  n : Int32,
  max_iter : Int32,
) -> Double {
  @eigen.power_iteration(matrix, n, max_iter)
}

///|
pub fn jacobi_eigenvalues(
  matrix : Array[Array[Double]],
  n : Int32,
  max_iter : Int32,
) -> Array[Double] {
  @eigen.jacobi_eigenvalues(matrix, n, max_iter)
}

///|
pub fn matrix_trace(matrix : Array[Array[Double]], n : Int32) -> Double {
  @eigen.matrix_trace(matrix, n)
}

// ---------------------------------------------------------------------------
// linalg: Linear algebra / 线性代数
// ---------------------------------------------------------------------------///|

///|
pub fn solve_linear(
  a : Array[Array[Double]],
  b : Array[Double],
  n : Int32,
) -> Array[Double] {
  @linalg.solve_linear(a, b, n)
}

///|
pub fn determinant(a : Array[Array[Double]], n : Int32) -> Double {
  @linalg.determinant(a, n)
}

///|
pub fn matrix_inverse(
  a : Array[Array[Double]],
  n : Int32,
) -> Array[Array[Double]]? {
  @linalg.matrix_inverse(a, n)
}

// ---------------------------------------------------------------------------
// matrix3d: 3D matrix operations / 3D 矩阵运算
// ---------------------------------------------------------------------------

///|
pub fn identity4() -> Array[Array[Double]] {
  @matrix3d.identity4()
}

///|
pub fn translation(
  tx : Double,
  ty : Double,
  tz : Double,
) -> Array[Array[Double]] {
  @matrix3d.translation(tx, ty, tz)
}

///|
pub fn scaling(sx : Double, sy : Double, sz : Double) -> Array[Array[Double]] {
  @matrix3d.scaling(sx, sy, sz)
}

///|
pub fn rotation_x(angle : Double) -> Array[Array[Double]] {
  @matrix3d.rotation_x(angle)
} ///|
/// Minkowski sum of a circle and a convex polygon. / 圆与凸多边形的 Minkowski 和。

///|
pub fn minkowski_sum_circle_polygon(
  circle : Circle,
  poly : Polygon,
) -> (Array[Point2D], Double) {
  @minkowski.minkowski_sum_circle_polygon(circle, poly)
}

///|
/// Check if two convex polygons collide via Minkowski difference. / 用 Minkowski 差检查两凸多边形碰撞。
pub fn convex_polygons_collide(poly1 : Polygon, poly2 : Polygon) -> Bool {
  @minkowski.convex_polygons_collide(poly1, poly2)
}
// ---------------------------------------------------------------------------
// rotating_calipers: rotating calipers / 旋转卡壳
// ---------------------------------------------------------------------------

///|
/// Convex polygon diameter (farthest vertex pair). / 凸多边形直径(最远顶点对)。
pub fn convex_polygon_diameter(poly : Polygon) -> (Point2D, Point2D, Double) {
  @rotating_calipers.convex_polygon_diameter(poly)
}

///|
/// Convex polygon width (min parallel supporting line distance). / 凸多边形宽度。
pub fn convex_polygon_width(poly : Polygon) -> Double {
  @rotating_calipers.convex_polygon_width(poly)
}

///|
/// Farthest point pair from a point set. / 点集最远点对。
pub fn farthest_point_pair(
  points : Array[Point2D],
) -> (Point2D, Point2D, Double)? {
  @rotating_calipers.farthest_point_pair(points)
}

///|
/// Min perimeter bounding rectangle of convex polygon. / 凸多边形最小周长包围矩形。
pub fn min_perimeter_bounding_rect(
  poly : Polygon,
) -> (Double, Double, Double, Double, Double) {
  @rotating_calipers.min_perimeter_bounding_rect(poly)
}

// ---------------------------------------------------------------------------
// ellipse: ellipse geometry / 椭圆几何
// ---------------------------------------------------------------------------

///|
pub fn rotation_y(angle : Double) -> Array[Array[Double]] {
  @matrix3d.rotation_y(angle)
}

///|
pub fn rotation_z(angle : Double) -> Array[Array[Double]] {
  @matrix3d.rotation_z(angle)
}

///|
pub fn mat4_mul(
  a : Array[Array[Double]],
  b : Array[Array[Double]],
) -> Array[Array[Double]] {
  @matrix3d.mat4_mul(a, b)
}

///|
pub fn transform_point(
  m : Array[Array[Double]],
  x : Double,
  y : Double,
  z : Double,
) -> (Double, Double, Double) {
  @matrix3d.transform_point(m, x, y, z)
}

///|
pub fn transform_direction(
  m : Array[Array[Double]],
  x : Double,
  y : Double,
  z : Double,
) -> (Double, Double, Double) {
  @matrix3d.transform_direction(m, x, y, z)
}

///|
pub fn mat4_transpose(m : Array[Array[Double]]) -> Array[Array[Double]] {
  @matrix3d.mat4_transpose(m)
}

///|
pub fn mat4_determinant(m : Array[Array[Double]]) -> Double {
  @matrix3d.mat4_determinant(m)
} ///|

///|
pub fn mat4_inverse(m : Array[Array[Double]]) -> Array[Array[Double]]? {
  @matrix3d.mat4_inverse(m)
}

///|
pub fn look_at(
  eye : (Double, Double, Double),
  target : (Double, Double, Double),
  up : (Double, Double, Double),
) -> Array[Array[Double]] {
  @matrix3d.look_at(eye, target, up)
}

///|
pub fn perspective(
  fovy : Double,
  aspect : Double,
  near : Double,
  far : Double,
) -> Array[Array[Double]] {
  @matrix3d.perspective(fovy, aspect, near, far)
}

///|
pub fn ortho(
  left : Double,
  right : Double,
  bottom : Double,
  top : Double,
  near : Double,
  far : Double,
) -> Array[Array[Double]] {
  @matrix3d.ortho(left, right, bottom, top, near, far)
}

// ---------------------------------------------------------------------------
// nurbs: NURBS curves and surfaces / NURBS 曲线与曲面
// ---------------------------------------------------------------------------

///|
pub fn nurbs_basis(
  i : Int32,
  p : Int32,
  u : Double,
  knots : Array[Double],
) -> Double {
  @nurbs.bspline_basis(i, p, u, knots)
}

///|
pub fn bspline_curve_point(
  control_pts : Array[(Double, Double, Double)],
  degree : Int32,
  u : Double,
  knots : Array[Double],
) -> (Double, Double, Double) {
  @nurbs.bspline_curve_point(control_pts, degree, u, knots)
}

///|
pub fn nurbs_curve_point(
  control_pts : Array[(Double, Double, Double)],
  weights : Array[Double],
  degree : Int32,
  u : Double,
  knots : Array[Double],
) -> (Double, Double, Double) {
  @nurbs.nurbs_curve_point(control_pts, weights, degree, u, knots)
} ///|

///|
pub fn nurbs_surface_point(
  control_net : Array[Array[(Double, Double, Double)]],
  weights : Array[Array[Double]],
  degree_u : Int32,
  degree_v : Int32,
  u : Double,
  v : Double,
  knots_u : Array[Double],
  knots_v : Array[Double],
) -> (Double, Double, Double) {
  @nurbs.nurbs_surface_point(
    control_net, weights, degree_u, degree_v, u, v, knots_u, knots_v,
  )
}

///|
pub fn find_span(
  n : Int32,
  p : Int32,
  u : Double,
  knots : Array[Double],
) -> Int32 {
  @nurbs.find_span(n, p, u, knots)
}

///|
pub fn nurbs_uniform_knots(num_ctrl : Int32, degree : Int32) -> Array[Double] {
  @nurbs.uniform_knots(num_ctrl, degree)
}

// ---------------------------------------------------------------------------
// surface_mesh: Surface mesh operations / 曲面网格操作
// ---------------------------------------------------------------------------

///|
pub fn surf_face_normal(
  vertices : Array[(Double, Double, Double)],
  face : (Int32, Int32, Int32),
) -> (Double, Double, Double) {
  @surface_mesh.face_normal(vertices, face)
}

///|
pub fn surf_vertex_normal(
  vertices : Array[(Double, Double, Double)],
  faces : Array[(Int32, Int32, Int32)],
  vidx : Int32,
) -> (Double, Double, Double) {
  @surface_mesh.vertex_normal(vertices, faces, vidx)
}

///|
pub fn triangle_area(
  vertices : Array[(Double, Double, Double)],
  face : (Int32, Int32, Int32),
) -> Double {
  @surface_mesh.triangle_area(vertices, face)
}

///|
pub fn mesh_area(
  vertices : Array[(Double, Double, Double)],
  faces : Array[(Int32, Int32, Int32)],
) -> Double {
  @surface_mesh.mesh_area(vertices, faces)
} ///|

///|
pub fn midpoint_subdivide(
  vertices : Array[(Double, Double, Double)],
  faces : Array[(Int32, Int32, Int32)],
) -> (Array[(Double, Double, Double)], Array[(Int32, Int32, Int32)]) {
  @surface_mesh.midpoint_subdivide(vertices, faces)
}

///|
pub fn surf_mesh_bounding_box(
  vertices : Array[(Double, Double, Double)],
) -> (Double, Double, Double, Double, Double, Double) {
  @surface_mesh.mesh_bounding_box(vertices)
}

///|
pub fn validate_mesh(
  vertices : Array[(Double, Double, Double)],
  faces : Array[(Int32, Int32, Int32)],
) -> Bool {
  @surface_mesh.validate_mesh(vertices, faces)
}

// ---------------------------------------------------------------------------
// surface_param: Parametric surfaces / 参数曲面
// ---------------------------------------------------------------------------

// ---------------------------------------------------------------------------
// surface_revolve: Surface of revolution / 旋转曲面
// ---------------------------------------------------------------------------

// ---------------------------------------------------------------------------
// surface_sweep: Sweep surfaces / 扫掠曲面
// ---------------------------------------------------------------------------

// ---------------------------------------------------------------------------
// surface_loft: Lofted surfaces / 放样曲面
// ---------------------------------------------------------------------------

// ---------------------------------------------------------------------------
// surface_trim: Trimmed surfaces / 裁剪曲面
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// bezier_surface: Bezier surfaces / 贝塞尔曲面
// ---------------------------------------------------------------------------

///|
pub fn bernstein(i : Int32, n : Int32, t : Double) -> Double {
  @bezier_surface.bernstein(i, n, t)
}

///|
pub fn bezier_curve(
  control_pts : Array[(Double, Double, Double)],
  t : Double,
) -> (Double, Double, Double) {
  @bezier_surface.bezier_curve(control_pts, t)
}

///|
pub fn bezier_surface(
  control_net : Array[Array[(Double, Double, Double)]],
  u : Double,
  v : Double,
) -> (Double, Double, Double) {
  @bezier_surface.bezier_surface(control_net, u, v)
}

///|
pub fn bezier_surface_decasteljau(
  control_net : Array[Array[(Double, Double, Double)]],
  u : Double,
  v : Double,
) -> (Double, Double, Double) {
  @bezier_surface.bezier_surface_decasteljau(control_net, u, v)
} ///|

///|
pub fn bezier_curve_derivative(
  control_pts : Array[(Double, Double, Double)],
  t : Double,
) -> (Double, Double, Double) {
  @bezier_surface.bezier_curve_derivative(control_pts, t)
}

///|
pub fn bezier_degree_elevate(
  control_pts : Array[(Double, Double, Double)],
) -> Array[(Double, Double, Double)] {
  @bezier_surface.bezier_degree_elevate(control_pts)
}
// Batch Q: Application Algorithms / 应用算法

// packing / 装填

///|
pub fn pack_circles(
  radii : Array[Double],
  container_size : Double,
) -> Array[(Double, Double)] {
  @packing.pack_circles(radii, container_size)
}

///|
pub fn pack_rectangles(
  rects : Array[(Double, Double)],
  bin_w : Double,
  bin_h : Double,
) -> Array[(Double, Double)] {
  @packing.pack_rectangles(rects, bin_w, bin_h)
}

///|
pub fn packing_density(
  radii : Array[Double],
  container_size : Double,
) -> Double {
  @packing.packing_density(radii, container_size)
}

// covering / 覆盖

///|
pub fn min_enclosing_circle(
  pts : Array[(Double, Double)],
) -> (Double, Double, Double) {
  @covering.min_enclosing_circle(pts)
}

///|
pub fn greedy_cover(
  pts : Array[(Double, Double)],
  radius : Double,
) -> Array[(Double, Double)] {
  @covering.greedy_cover(pts, radius)
}

///|
pub fn covering_radius(pts : Array[(Double, Double)], k : Int32) -> Double {
  @covering.covering_radius(pts, k)
}

// clustering / 聚类

///|
pub fn kmeans(
  pts : Array[(Double, Double)],
  k : Int32,
  max_iter : Int32,
) -> Array[Int32] {
  @clustering.kmeans(pts, k, max_iter)
}

///|
pub fn dbscan(
  pts : Array[(Double, Double)],
  eps : Double,
  min_pts : Int32,
) -> Array[Int32] {
  @clustering.dbscan(pts, eps, min_pts)
}

///|
pub fn cluster_centroids(
  pts : Array[(Double, Double)],
  labels : Array[Int32],
  k : Int32,
) -> Array[(Double, Double)] {
  @clustering.cluster_centroids(pts, labels, k)
}

// registration / 配准

///|
pub fn centroid_3d(
  pts : Array[(Double, Double, Double)],
) -> (Double, Double, Double) {
  @registration.centroid_3d(pts)
}

///|
pub fn translate_pts(
  pts : Array[(Double, Double, Double)],
  tx : Double,
  ty : Double,
  tz : Double,
) -> Array[(Double, Double, Double)] {
  @registration.translate_pts(pts, tx, ty, tz)
}

///|
pub fn icp(
  source : Array[(Double, Double, Double)],
  target : Array[(Double, Double, Double)],
  max_iter : Int32,
) -> (Array[(Double, Double, Double)], (Double, Double, Double)) {
  @registration.icp(source, target, max_iter)
}

///|
pub fn rms_error(
  source : Array[(Double, Double, Double)],
  target : Array[(Double, Double, Double)],
) -> Double {
  @registration.rms_error(source, target)
}

// matching / 匹配

///|
pub fn nearest_neighbor_match(
  source : Array[(Double, Double)],
  target : Array[(Double, Double)],
) -> Array[Int32] {
  @matching.nearest_neighbor_match(source, target)
}

///|
pub fn match_hausdorff_distance(
  a : Array[(Double, Double)],
  b : Array[(Double, Double)],
) -> Double {
  @matching.hausdorff_distance(a, b)
}

///|
pub fn match_chamfer_distance(
  a : Array[(Double, Double)],
  b : Array[(Double, Double)],
) -> Double {
  @matching.chamfer_distance(a, b)
}

///|
pub fn match_points(
  source : Array[(Double, Double)],
  target : Array[(Double, Double)],
  threshold : Double,
) -> Array[(Int32, Int32)] {
  @matching.match_points(source, target, threshold)
}

// reconstruction / 重建

///|
pub fn estimate_normal(
  pts : Array[(Double, Double, Double)],
  idx : Int32,
  k : Int32,
) -> (Double, Double, Double) {
  @reconstruction.estimate_normal(pts, idx, k)
}

///|
pub fn ball_pivot_reconstruct(
  pts : Array[(Double, Double, Double)],
  radius : Double,
) -> (Array[(Double, Double, Double)], Array[(Int32, Int32, Int32)]) {
  @reconstruction.ball_pivot_reconstruct(pts, radius)
}

///|
pub fn distance_to_mesh(
  pt : (Double, Double, Double),
  vertices : Array[(Double, Double, Double)],
  faces : Array[(Int32, Int32, Int32)],
) -> Double {
  @reconstruction.distance_to_mesh(pt, vertices, faces)
}

// hough_transform / 霍夫变换

///|
pub type HoughLine = @hough_transform.HoughLine

///|
pub type HoughCircle = @hough_transform.HoughCircle

///|
pub fn hough_lines(
  pts : Array[Point2D],
  threshold : Int32,
  theta_steps : Int32,
) -> Array[HoughLine] {
  @hough_transform.hough_lines(pts, threshold, theta_steps)
}

///|
pub fn hough_circles(
  pts : Array[Point2D],
  radius : Double,
  threshold : Int32,
  resolution : Int32,
) -> Array[HoughCircle] {
  @hough_transform.hough_circles(pts, radius, threshold, resolution)
}

///|
pub fn hough_accumulator(
  pts : Array[Point2D],
  theta_steps : Int32,
  rho_steps : Int32,
) -> Array[Array[Int32]] {
  @hough_transform.hough_accumulator(pts, theta_steps, rho_steps)
}

///|
pub fn hough_peaks(
  accumulator : Array[Array[Int32]],
  threshold : Int32,
  window : Int32,
) -> Array[(Int32, Int32, Int32)] {
  @hough_transform.hough_peaks(accumulator, threshold, window)
}

///|
pub fn hough_line_to_points(
  theta : Double,
  rho : Double,
  length : Double,
) -> (Point2D, Point2D) {
  @hough_transform.hough_line_to_points(theta, rho, length)
}

// ransac / RANSAC

///|
/// === Phase 1: 3D Geometry & Polyhedra ===
pub type AABB3D = @aabb3d.AABB3D

///|
pub type BoundingSphere = @bounding_sphere.BoundingSphere

///|
pub type OBB = @obb.OBB

///|
pub type MeshQualityMetrics = @mesh_quality.MeshQualityMetrics

///|
pub type Polyhedron = @polyhedron.Polyhedron

///|
pub type MeshRepairResult = @mesh_repair.MeshRepairResult

///|
pub type UV = @mesh_param.UV

///|
pub type MeshParamResult = @mesh_param.MeshParamResult

///|
pub type BoolOp = @mesh_boolean.BoolOp

///|
pub type MeshBoolResult = @mesh_boolean.MeshBoolResult

///|
pub type PolyBoolResult = @polyhedron_boolean.PolyBoolResult

///|
pub type DynamicHull3D = @convex_hull_3d_dynamic.DynamicHull3D

///|
pub fn min_bounding_sphere(points : Array[Point3D]) -> BoundingSphere {
  @bounding_sphere.min_bounding_sphere(points)
}

///|
pub fn obb_from_points(points : Array[Point3D]) -> OBB {
  @obb.obb_from_points(points)
}

///|
pub fn triangle_quality(
  p0 : Point3D,
  p1 : Point3D,
  p2 : Point3D,
) -> MeshQualityMetrics {
  @mesh_quality.triangle_quality(p0, p1, p2)
}

///|
pub fn mesh_average_quality(
  vertices : Array[Point3D],
  faces : Array[(Int32, Int32, Int32)],
) -> MeshQualityMetrics {
  @mesh_quality.mesh_average_quality(vertices, faces)
}

///|
pub fn count_degenerate(
  vertices : Array[Point3D],
  faces : Array[(Int32, Int32, Int32)],
  eps : Double,
) -> Int32 {
  @mesh_quality.count_degenerate(vertices, faces, eps)
}

///|
pub fn remove_degenerate_faces(
  vertices : Array[Point3D],
  faces : Array[(Int32, Int32, Int32)],
  eps : Double,
) -> (Array[(Int32, Int32, Int32)], Int32) {
  @mesh_repair.remove_degenerate_faces(vertices, faces, eps)
}

///|
pub fn merge_duplicate_vertices(
  vertices : Array[Point3D],
  faces : Array[(Int32, Int32, Int32)],
  eps : Double,
) -> (Array[Point3D], Array[(Int32, Int32, Int32)], Int32) {
  @mesh_repair.merge_duplicate_vertices(vertices, faces, eps)
}

///|
pub fn find_boundary_edges(
  faces : Array[(Int32, Int32, Int32)],
) -> Array[(Int32, Int32)] {
  @mesh_repair.find_boundary_edges(faces)
}

///|
pub fn fill_holes(
  vertices : Array[Point3D],
  faces : Array[(Int32, Int32, Int32)],
) -> (Array[(Int32, Int32, Int32)], Int32) {
  @mesh_repair.fill_holes(vertices, faces)
}

///|
pub fn repair_mesh(
  vertices : Array[Point3D],
  faces : Array[(Int32, Int32, Int32)],
  eps : Double,
) -> MeshRepairResult {
  @mesh_repair.repair_mesh(vertices, faces, eps)
}

///|
pub fn project_parametrize(vertices : Array[Point3D]) -> Array[UV] {
  @mesh_param.project_parametrize(vertices)
}

///|
pub fn harmonic_parametrize(
  vertices : Array[Point3D],
  faces : Array[(Int32, Int32, Int32)],
  boundary : Array[Int32],
) -> MeshParamResult {
  @mesh_param.harmonic_parametrize(vertices, faces, boundary)
}

///|
pub fn area_distortion(
  vertices : Array[Point3D],
  faces : Array[(Int32, Int32, Int32)],
  uv : Array[UV],
) -> Double {
  @mesh_param.area_distortion(vertices, faces, uv)
}

///|
pub fn mesh_union(
  verts_a : Array[Point3D],
  faces_a : Array[(Int32, Int32, Int32)],
  verts_b : Array[Point3D],
  faces_b : Array[(Int32, Int32, Int32)],
) -> MeshBoolResult {
  @mesh_boolean.mesh_union(verts_a, faces_a, verts_b, faces_b)
}

///|
pub fn mesh_intersection(
  verts_a : Array[Point3D],
  faces_a : Array[(Int32, Int32, Int32)],
  verts_b : Array[Point3D],
  faces_b : Array[(Int32, Int32, Int32)],
) -> MeshBoolResult {
  @mesh_boolean.mesh_intersection(verts_a, faces_a, verts_b, faces_b)
}

///|
pub fn mesh_difference(
  verts_a : Array[Point3D],
  faces_a : Array[(Int32, Int32, Int32)],
  verts_b : Array[Point3D],
  faces_b : Array[(Int32, Int32, Int32)],
) -> MeshBoolResult {
  @mesh_boolean.mesh_difference(verts_a, faces_a, verts_b, faces_b)
}

///|
pub fn polyhedron_union(
  verts_a : Array[Point3D],
  faces_a : Array[Array[Int32]],
  verts_b : Array[Point3D],
  faces_b : Array[Array[Int32]],
) -> PolyBoolResult {
  @polyhedron_boolean.polyhedron_union(verts_a, faces_a, verts_b, faces_b)
}

///|
pub fn polyhedron_intersection(
  verts_a : Array[Point3D],
  faces_a : Array[Array[Int32]],
  verts_b : Array[Point3D],
  faces_b : Array[Array[Int32]],
) -> PolyBoolResult {
  @polyhedron_boolean.polyhedron_intersection(
    verts_a, faces_a, verts_b, faces_b,
  )
}

///|
pub fn polyhedron_difference(
  verts_a : Array[Point3D],
  faces_a : Array[Array[Int32]],
  verts_b : Array[Point3D],
  faces_b : Array[Array[Int32]],
) -> PolyBoolResult {
  @polyhedron_boolean.polyhedron_difference(verts_a, faces_a, verts_b, faces_b)
}

///|
pub fn compute_hull_3d(points : Array[Point3D]) -> Array[(Int32, Int32, Int32)] {
  @convex_hull_3d_dynamic.compute_hull_3d(points)
}
// ---------------------------------------------------------------------------
// delaunay_3d: 3D Delaunay triangulation / 三维 Delaunay 三角剖分
// ---------------------------------------------------------------------------

///|
/// Tetrahedron in 3D Delaunay. / Delaunay 四面体。
pub type Tetrahedron = @delaunay_3d.Tetrahedron

///|
/// 3D Delaunay triangulation result. / 三维 Delaunay 三角剖分结果。
pub type Delaunay3D = @delaunay_3d.Delaunay3D

///|
pub fn delaunay_3d_new() -> Delaunay3D {
  @delaunay_3d.Delaunay3D::new()
}

///|
pub fn delaunay_3d_tetrahedron_count(d : Delaunay3D) -> Int32 {
  @delaunay_3d.Delaunay3D::tetrahedron_count(d)
}

///|
pub fn delaunay_3d_vertex_count(d : Delaunay3D) -> Int32 {
  @delaunay_3d.Delaunay3D::vertex_count(d)
}

///|
pub fn tetrahedron_volume(
  a : Point3D,
  b : Point3D,
  c : Point3D,
  d : Point3D,
) -> Double {
  @delaunay_3d.tetrahedron_volume(a, b, c, d)
}

///|
pub fn circumsphere_center(
  a : Point3D,
  b : Point3D,
  c : Point3D,
  d : Point3D,
) -> Point3D {
  @delaunay_3d.circumsphere_center(a, b, c, d)
}

///|
pub fn circumsphere_radius_sq(
  a : Point3D,
  b : Point3D,
  c : Point3D,
  d : Point3D,
) -> Double {
  @delaunay_3d.circumsphere_radius_sq(a, b, c, d)
}

///|
pub fn in_circumsphere(
  p : Point3D,
  a : Point3D,
  b : Point3D,
  c : Point3D,
  d : Point3D,
) -> Bool {
  @delaunay_3d.in_circumsphere(p, a, b, c, d)
}

///|
pub fn delaunay_3d(points : Array[Point3D]) -> Delaunay3D {
  @delaunay_3d.delaunay_3d(points)
}

///|
pub fn is_delaunay(d : Delaunay3D) -> Bool {
  @delaunay_3d.is_delaunay(d)
}

// ---------------------------------------------------------------------------
// voronoi_3d: 3D Voronoi diagram / 三维 Voronoi 图
// ---------------------------------------------------------------------------

///|
/// 3D Voronoi cell. / 三维 Voronoi 单元。
pub type VoronoiCell3D = @voronoi_3d.VoronoiCell3D

///|
/// 3D Voronoi diagram. / 三维 Voronoi 图。
pub type Voronoi3D = @voronoi_3d.Voronoi3D

///|
pub fn voronoi_3d_new() -> Voronoi3D {
  @voronoi_3d.Voronoi3D::new()
}

///|
pub fn voronoi_3d_cell_count(v : Voronoi3D) -> Int32 {
  @voronoi_3d.Voronoi3D::cell_count(v)
}

///|
pub fn voronoi_3d_vertex_count(v : Voronoi3D) -> Int32 {
  @voronoi_3d.Voronoi3D::vertex_count(v)
}

///|
pub fn voronoi_3d(sites : Array[Point3D]) -> Voronoi3D {
  @voronoi_3d.voronoi_3d(sites)
}

///|
pub fn voronoi_cell_3d(v : Voronoi3D, site_idx : Int32) -> VoronoiCell3D {
  @voronoi_3d.voronoi_cell_3d(v, site_idx)
}

///|
pub fn voronoi_3d_cell_count_from_sites(sites : Array[Point3D]) -> Int32 {
  @voronoi_3d.voronoi_cell_count(sites)
}

///|
pub fn voronoi_3d_vertex_count_from_sites(sites : Array[Point3D]) -> Int32 {
  @voronoi_3d.voronoi_vertex_count(sites)
}

///|
pub fn dual_delaunay(sites : Array[Point3D]) -> Delaunay3D {
  @voronoi_3d.dual_delaunay(sites)
}

// ---------------------------------------------------------------------------
// constrained_delaunay: Constrained Delaunay triangulation / 约束 Delaunay 三角剖分
// ---------------------------------------------------------------------------

///|
/// Constrained Delaunay triangulation. / 约束 Delaunay 三角剖分。
pub type ConstrainedDelaunay = @constrained_delaunay.ConstrainedDelaunay

///|
pub fn constrained_delaunay_new() -> ConstrainedDelaunay {
  @constrained_delaunay.ConstrainedDelaunay::new()
}

///|
pub fn constrained_delaunay_triangle_count(cd : ConstrainedDelaunay) -> Int32 {
  @constrained_delaunay.ConstrainedDelaunay::triangle_count(cd)
}

///|
pub fn constrained_delaunay_constraint_count(cd : ConstrainedDelaunay) -> Int32 {
  @constrained_delaunay.ConstrainedDelaunay::constraint_count(cd)
}

///|
pub fn is_constrained_edge(
  cd : ConstrainedDelaunay,
  a : Int32,
  b : Int32,
) -> Bool {
  @constrained_delaunay.is_constrained_edge(cd, a, b)
}

///|
pub fn add_constraint(cd : ConstrainedDelaunay, a : Int32, b : Int32) -> Unit {
  @constrained_delaunay.add_constraint(cd, a, b)
}

///|
pub fn constrained_delaunay(
  points : Array[Point2D],
  constraints : Array[(Int32, Int32)],
) -> ConstrainedDelaunay {
  @constrained_delaunay.constrained_delaunay(points, constraints)
}

///|
pub fn constrained_triangle_count(cd : ConstrainedDelaunay) -> Int32 {
  @constrained_delaunay.constrained_triangle_count(cd)
}

// ---------------------------------------------------------------------------
// power_diagram: Power diagram / 幂图
// ---------------------------------------------------------------------------

///|
/// Weighted point for power diagram. / 幂图加权站点。
pub type WeightedPoint = @power_diagram.WeightedPoint

///|
/// Power cell. / 幂单元。
pub type PowerCell = @power_diagram.PowerCell

///|
/// Power diagram. / 幂图。
pub type PowerDiagram = @power_diagram.PowerDiagram

///|
pub fn weighted_point_new(point : Point2D, weight : Double) -> WeightedPoint {
  @power_diagram.WeightedPoint::new(point, weight)
}

///|
pub fn power_diagram_new() -> PowerDiagram {
  @power_diagram.PowerDiagram::new()
}

///|
pub fn power_diagram_cell_count(pd : PowerDiagram) -> Int32 {
  @power_diagram.PowerDiagram::cell_count(pd)
}

///|
pub fn power_distance(x : Point2D, site : WeightedPoint) -> Double {
  @power_diagram.power_distance(x, site)
}

///|
pub fn power_diagram(
  sites : Array[WeightedPoint],
  bounds : (Point2D, Point2D),
) -> PowerDiagram {
  @power_diagram.power_diagram(sites, bounds)
}

///|
pub fn power_cell(pd : PowerDiagram, site_idx : Int32) -> PowerCell {
  @power_diagram.power_cell(pd, site_idx)
}

///|
pub fn power_cell_area(pd : PowerDiagram, site_idx : Int32) -> Double {
  @power_diagram.power_cell_area(pd, site_idx)
}

///|
pub fn regular_triangulation(
  sites : Array[WeightedPoint],
) -> Array[(Int32, Int32, Int32)] {
  @power_diagram.regular_triangulation(sites)
}

// ---------------------------------------------------------------------------
// centroidal_voronoi: Centroidal Voronoi tessellation / 质心 Voronoi 镶嵌
// ---------------------------------------------------------------------------

///|
/// CVT result. / CVT 结果。
pub type CVTResult = @centroidal_voronoi.CVTResult

///|
pub fn cvt_result_new() -> CVTResult {
  @centroidal_voronoi.CVTResult::new()
}

///|
pub fn compute_centroid(poly : Array[Point2D]) -> Point2D {
  @centroidal_voronoi.compute_centroid(poly)
}

///|
pub fn lloyd_energy(
  sites : Array[Point2D],
  bounds : (Point2D, Point2D),
) -> Double {
  @centroidal_voronoi.lloyd_energy(sites, bounds)
}

///|
pub fn lloyd_iteration(
  sites : Array[Point2D],
  bounds : (Point2D, Point2D),
  max_iter : Int32,
) -> Array[Point2D] {
  @centroidal_voronoi.lloyd_iteration(sites, bounds, max_iter)
}

///|
pub fn centroidal_voronoi(
  sites : Array[Point2D],
  bounds : (Point2D, Point2D),
  max_iter : Int32,
) -> CVTResult {
  @centroidal_voronoi.centroidal_voronoi(sites, bounds, max_iter)
}

// ---------------------------------------------------------------------------
// alpha_complex: Alpha complex / Alpha 复形
// ---------------------------------------------------------------------------

///|
/// Alpha simplex. / Alpha 单纯形。
pub type AlphaSimplex = @alpha_complex.AlphaSimplex

///|
/// Alpha complex. / Alpha 复形。
pub type AlphaComplex = @alpha_complex.AlphaComplex

///|
pub fn alpha_complex_new() -> AlphaComplex {
  @alpha_complex.AlphaComplex::new()
}

///|
pub fn alpha_complex_simplex_count(ac : AlphaComplex) -> Int32 {
  @alpha_complex.AlphaComplex::simplex_count(ac)
}

///|
pub fn is_alpha_exposed(simplex : AlphaSimplex, alpha : Double) -> Bool {
  @alpha_complex.is_alpha_exposed(simplex, alpha)
}

///|
pub fn alpha_complex(points : Array[Point2D], alpha : Double) -> AlphaComplex {
  @alpha_complex.alpha_complex(points, alpha)
}

///|
pub fn alpha_shape(
  points : Array[Point2D],
  alpha : Double,
) -> Array[(Int32, Int32)] {
  @alpha_complex.alpha_shape(points, alpha)
}

///|
pub fn alpha_complex_count(ac : AlphaComplex) -> Int32 {
  @alpha_complex.alpha_complex_count(ac)
}

// ---------------------------------------------------------------------------
// persistent_homology: Persistent homology / 持久同调
// ---------------------------------------------------------------------------

///|
/// Persistence barcode. / 持久同调条形码。
pub type Barcode = @persistent_homology.Barcode

///|
/// Simplex with filtration value. / 带过滤值的单纯形。
pub type SimplexWithFiltration = @persistent_homology.SimplexWithFiltration

///|
/// Persistence diagram. / 持久同调图。
pub type PersistenceDiagram = @persistent_homology.PersistenceDiagram

///|
pub fn barcode_new(
  birth : Double,
  death : Double,
  dimension : Int32,
) -> Barcode {
  @persistent_homology.Barcode::new(birth, death, dimension)
}

///|
pub fn barcode_is_infinite(b : Barcode) -> Bool {
  @persistent_homology.Barcode::is_infinite(b)
}

///|
pub fn simplex_with_filtration_new(
  vertices : Array[Int32],
  filtration : Double,
) -> SimplexWithFiltration {
  @persistent_homology.SimplexWithFiltration::new(vertices, filtration)
}

///|
pub fn persistence_diagram_new() -> PersistenceDiagram {
  @persistent_homology.PersistenceDiagram::new()
}

///|
pub fn persistence_diagram_barcode_count(pd : PersistenceDiagram) -> Int32 {
  @persistent_homology.PersistenceDiagram::barcode_count(pd)
}

///|
pub fn persistence_pairs(
  simplices : Array[SimplexWithFiltration],
) -> Array[(Int32, Int32)] {
  @persistent_homology.persistence_pairs(simplices)
}

///|
pub fn compute_barcode(
  simplices : Array[SimplexWithFiltration],
) -> Array[Barcode] {
  @persistent_homology.compute_barcode(simplices)
}

///|
pub fn persistent_homology(
  simplices : Array[SimplexWithFiltration],
) -> PersistenceDiagram {
  @persistent_homology.persistent_homology(simplices)
}

///|
pub fn betti_from_barcode(
  barcodes : Array[Barcode],
  threshold : Double,
) -> Array[Int32] {
  @persistent_homology.betti_from_barcode(barcodes, threshold)
}

// ---------------------------------------------------------------------------
// betti_numbers: Betti numbers / Betti 数
// ---------------------------------------------------------------------------

///|
/// Betti numbers result. / Betti 数结果。
pub type BettiResult = @betti_numbers.BettiResult

///|
pub fn betti_result_new(b0 : Int32, b1 : Int32, b2 : Int32) -> BettiResult {
  @betti_numbers.BettiResult::new(b0, b1, b2)
}

///|
pub fn betti_numbers_0(simplices : Array[Array[Int32]]) -> Int32 {
  @betti_numbers.betti_0(simplices)
}

///|
pub fn betti_1(simplices : Array[Array[Int32]]) -> Int32 {
  @betti_numbers.betti_1(simplices)
}

///|
pub fn betti_2(simplices : Array[Array[Int32]]) -> Int32 {
  @betti_numbers.betti_2(simplices)
}

///|
pub fn betti_numbers(simplices : Array[Array[Int32]]) -> BettiResult {
  @betti_numbers.betti_numbers(simplices)
}

///|
pub fn compute_euler(simplices : Array[Array[Int32]]) -> Int32 {
  @betti_numbers.compute_euler(simplices)
}

// ---------------------------------------------------------------------------
// reeb_graph: Reeb graph / Reeb 图
// ---------------------------------------------------------------------------

///|
/// Critical point type. / 临界点类型。
pub type CriticalType = @reeb_graph.CriticalType

///|
/// Reeb graph node. / Reeb 图节点。
pub type ReebNode = @reeb_graph.ReebNode

///|
/// Reeb graph edge. / Reeb 图边。
pub type ReebEdge = @reeb_graph.ReebEdge

///|
/// Reeb graph. / Reeb 图。
pub type ReebGraph = @reeb_graph.ReebGraph

///|
pub fn reeb_node_new(
  vertex_idx : Int32,
  level : Double,
  crit_type : CriticalType,
) -> ReebNode {
  @reeb_graph.ReebNode::new(vertex_idx, level, crit_type)
}

///|
pub fn reeb_edge_new(from : Int32, to : Int32) -> ReebEdge {
  @reeb_graph.ReebEdge::new(from, to)
}

///|
pub fn reeb_graph_new() -> ReebGraph {
  @reeb_graph.ReebGraph::new()
}

///|
pub fn reeb_graph_node_count(rg : ReebGraph) -> Int32 {
  @reeb_graph.ReebGraph::node_count(rg)
}

///|
pub fn reeb_graph_edge_count(rg : ReebGraph) -> Int32 {
  @reeb_graph.ReebGraph::edge_count(rg)
}

///|
pub fn critical_points(
  values : Array[Double],
  edges : Array[(Int32, Int32)],
) -> Array[ReebNode] {
  @reeb_graph.critical_points(values, edges)
}

///|
pub fn reeb_graph(
  values : Array[Double],
  edges : Array[(Int32, Int32)],
) -> ReebGraph {
  @reeb_graph.reeb_graph(values, edges)
}

///|
pub fn reeb_node_count(rg : ReebGraph) -> Int32 {
  @reeb_graph.reeb_node_count(rg)
}

///|
pub fn reeb_edge_count(rg : ReebGraph) -> Int32 {
  @reeb_graph.reeb_edge_count(rg)
}

// ---------------------------------------------------------------------------
// morse_complex: Morse complex / Morse 复形
// ---------------------------------------------------------------------------

// ---------------------------------------------------------------------------
// rrt: Rapidly-exploring Random Trees / 快速探索随机树
// ---------------------------------------------------------------------------

///|
/// RRT node. / RRT 节点。
pub type RRTNode = @rrt.RRTNode

///|
/// RRT configuration. / RRT 配置。
pub type RRTConfig = @rrt.RRTConfig

///|
/// RRT result. / RRT 结果。
pub type RRTResult = @rrt.RRTResult

///|
/// Construct an RRT node. / 构造 RRT 节点。
pub fn rrt_node_new(point : Point2D, parent : Int32) -> RRTNode {
  @rrt.RRTNode::new(point, parent)
}

///|
/// Construct RRT configuration. / 构造 RRT 配置。
pub fn rrt_config_new(
  step_size : Double,
  max_iterations : Int32,
  goal_bias : Double,
  goal_radius : Double,
  seed : UInt32,
  x_min : Double,
  x_max : Double,
  y_min : Double,
  y_max : Double,
) -> RRTConfig {
  @rrt.RRTConfig::new(
    step_size, max_iterations, goal_bias, goal_radius, seed, x_min, x_max, y_min,
    y_max,
  )
}

///|
/// Plan a path using basic RRT. / 使用基本 RRT 规划路径。
pub fn rrt_plan(
  config : RRTConfig,
  start : Point2D,
  goal : Point2D,
  obstacles : Array[Array[Point2D]],
) -> RRTResult {
  @rrt.rrt_plan(config, start, goal, obstacles)
}

///|
/// Plan a path using RRT*. / 使用 RRT* 规划路径。
pub fn rrt_star_plan(
  config : RRTConfig,
  start : Point2D,
  goal : Point2D,
  obstacles : Array[Array[Point2D]],
) -> RRTResult {
  @rrt.rrt_star_plan(config, start, goal, obstacles)
}

///|
/// Plan a path using bidirectional RRT. / 使用双向 RRT 规划路径。
pub fn rrt_connect_plan(
  config : RRTConfig,
  start : Point2D,
  goal : Point2D,
  obstacles : Array[Array[Point2D]],
) -> RRTResult {
  @rrt.rrt_connect_plan(config, start, goal, obstacles)
}

///|
/// Compute the total length of an RRT path. / 计算 RRT 路径总长度。
pub fn rrt_path_length(path : Array[Point2D]) -> Double {
  @rrt.rrt_path_length(path)
}

///|
/// Count nodes in an RRT tree. / 统计 RRT 树中节点数。
pub fn rrt_node_count(nodes : Array[RRTNode]) -> Int32 {
  @rrt.rrt_node_count(nodes)
}

// ---------------------------------------------------------------------------
// prm: Probabilistic Roadmap / 概率路线图
// ---------------------------------------------------------------------------

///|
/// PRM configuration. / PRM 配置。
pub type PRMConfig = @prm.PRMConfig

///|
/// PRM roadmap. / PRM 路线图。
pub type PRMRoadmap = @prm.PRMRoadmap

///|
/// PRM result. / PRM 结果。
pub type PRMResult = @prm.PRMResult

///|
/// Construct PRM configuration. / 构造 PRM 配置。
pub fn prm_config_new(
  num_samples : Int32,
  connection_radius : Double,
  seed : UInt32,
  x_min : Double,
  x_max : Double,
  y_min : Double,
  y_max : Double,
) -> PRMConfig {
  @prm.PRMConfig::new(
    num_samples, connection_radius, seed, x_min, x_max, y_min, y_max,
  )
}

///|
/// Build a PRM roadmap. / 构建 PRM 路线图。
pub fn prm_build(
  config : PRMConfig,
  obstacles : Array[Array[Point2D]],
) -> PRMRoadmap {
  @prm.prm_build(config, obstacles)
}

///|
/// Query shortest path on a PRM roadmap. / 在 PRM 路线图上查询最短路径。
pub fn prm_query(
  roadmap : PRMRoadmap,
  start : Point2D,
  goal : Point2D,
  obstacles : Array[Array[Point2D]],
) -> PRMResult {
  @prm.prm_query(roadmap, start, goal, obstacles)
}

///|
/// Count nodes in a PRM roadmap. / 统计 PRM 路线图节点数。
pub fn prm_node_count(roadmap : PRMRoadmap) -> Int32 {
  @prm.prm_node_count(roadmap)
}

///|
/// Count edges in a PRM roadmap. / 统计 PRM 路线图边数。
pub fn prm_edge_count(roadmap : PRMRoadmap) -> Int32 {
  @prm.prm_edge_count(roadmap)
}

// ---------------------------------------------------------------------------
// a_star: A* path planning / A* 路径规划
// ---------------------------------------------------------------------------

///|
/// A* grid. / A* 网格。
pub type AStarGrid = @a_star.AStarGrid

///|
/// Ellipse type. / 椭圆类型。
pub type Ellipse = @ellipse.Ellipse

///|
/// Construct an ellipse. / 构造椭圆。
pub fn ellipse_new(
  center : Point2D,
  a : Double,
  b : Double,
  angle : Double,
) -> Ellipse {
  @ellipse.Ellipse::new(center, a, b, angle)
}

///|
/// Area of the ellipse. / 椭圆面积。
pub fn ellipse_area(e : Ellipse) -> Double {
  @ellipse.Ellipse::area(e)
}

///|
/// Perimeter of the ellipse (Ramanujan approximation). / 椭圆周长。
pub fn ellipse_perimeter(e : Ellipse) -> Double {
  @ellipse.Ellipse::perimeter(e)
}

///|
/// Eccentricity of the ellipse. / 椭圆离心率。
pub fn ellipse_eccentricity(e : Ellipse) -> Double {
  @ellipse.Ellipse::eccentricity(e)
}

///|
/// Check if a point is inside the ellipse. / 检查点是否在椭圆内。
pub fn ellipse_contains(e : Ellipse, p : Point2D) -> Bool {
  @ellipse.Ellipse::contains(e, p)
}

///|
/// A* result. / A* 结果。
pub type AStarResult = @a_star.AStarResult

///|
/// A* heuristic type. / A* 启发式类型。
pub type AStarHeuristic = @a_star.AStarHeuristic

///|
/// A* graph node. / A* 图节点。
pub type AStarGraphNode = @a_star.AStarGraphNode

///|
/// Construct an A* grid. / 构造 A* 网格。
pub fn astar_grid_new(width : Int32, height : Int32) -> AStarGrid {
  @a_star.AStarGrid::new(width, height)
}

///|
/// Mark a cell as blocked. / 标记格子为障碍。
pub fn astar_grid_set_blocked(grid : AStarGrid, x : Int32, y : Int32) -> Unit {
  @a_star.AStarGrid::set_blocked(grid, x, y)
}

///|
/// Check if a cell is blocked. / 检查格子是否为障碍。
pub fn astar_grid_is_blocked(grid : AStarGrid, x : Int32, y : Int32) -> Bool {
  @a_star.AStarGrid::is_blocked(grid, x, y)
}

///|
/// Construct an A* graph node. / 构造 A* 图节点。
pub fn astar_graph_node_new(
  id : Int32,
  x : Double,
  y : Double,
) -> AStarGraphNode {
  @a_star.AStarGraphNode::new(id, x, y)
}

///|
/// Plan path on a grid using A*. / 使用 A* 在网格上规划路径。
pub fn astar_grid(
  grid : AStarGrid,
  start : (Int32, Int32),
  goal : (Int32, Int32),
  heuristic : AStarHeuristic,
  allow_diagonal : Bool,
) -> AStarResult {
  @a_star.astar_grid(grid, start, goal, heuristic, allow_diagonal)
}

///|
/// Plan path on a graph using A*. / 使用 A* 在图上规划路径。
pub fn astar_graph(
  nodes : Array[AStarGraphNode],
  adj : Array[Array[(Int32, Double)]],
  start : Int32,
  goal : Int32,
) -> AStarResult {
  @a_star.astar_graph(nodes, adj, start, goal)
}

///|
/// Compute path cost on a grid. / 计算网格路径代价。
pub fn astar_path_cost(path : Array[(Int32, Int32)]) -> Double {
  @a_star.astar_path_cost(path)
}

// ---------------------------------------------------------------------------
// dubins: Dubins curves / Dubins 曲线
// ---------------------------------------------------------------------------

///|
/// Dubins path segment type. / Dubins 路径段类型。
pub type DubinsSegmentType = @dubins.DubinsSegmentType

///|
/// Dubins path segment. / Dubins 路径段。
pub type DubinsSegment = @dubins.DubinsSegment

///|
/// Dubins path. / Dubins 路径。
pub type DubinsPath = @dubins.DubinsPath

///|
/// Dubins pose. / Dubins 位姿。
pub type DubinsPose = @dubins.DubinsPose

///|
/// Construct a Dubins pose. / 构造 Dubins 位姿。
pub fn dubins_pose_new(x : Double, y : Double, theta : Double) -> DubinsPose {
  @dubins.DubinsPose::new(x, y, theta)
}

///|
/// Compute the shortest Dubins path. / 计算最短 Dubins 路径。
pub fn dubins_shortest_path(
  start : DubinsPose,
  goal : DubinsPose,
  radius : Double,
) -> DubinsPath {
  @dubins.dubins_shortest_path(start, goal, radius)
}

///|
/// Sample points along a Dubins path. / 沿 Dubins 路径采样点。
pub fn dubins_sample(
  path : DubinsPath,
  start : DubinsPose,
  num_samples : Int32,
) -> Array[Point2D] {
  @dubins.dubins_sample(path, start, num_samples)
}

///|
/// Get the total length of a Dubins path. / 获取 Dubins 路径总长度。
pub fn dubins_path_length(path : DubinsPath) -> Double {
  @dubins.dubins_path_length(path)
}

///|
/// Count segments in a Dubins path. / 统计 Dubins 路径段数。
pub fn dubins_segment_count(path : DubinsPath) -> Int32 {
  @dubins.dubins_segment_count(path)
}

// ---------------------------------------------------------------------------
// reed_shepp: Reeds-Shepp curves / Reeds-Shepp 曲线
// ---------------------------------------------------------------------------

///|
/// Reeds-Shepp path segment type. / Reeds-Shepp 路径段类型。
pub type RSSegmentType = @reed_shepp.RSSegmentType

///|
/// Reeds-Shepp path segment. / Reeds-Shepp 路径段。
pub type RSSegment = @reed_shepp.RSSegment

///|
/// Reeds-Shepp path. / Reeds-Shepp 路径。
pub type RSPath = @reed_shepp.RSPath

///|
/// Reeds-Shepp pose. / Reeds-Shepp 位姿。
pub type RSPose = @reed_shepp.RSPose

///|
/// Construct a Reeds-Shepp pose. / 构造 Reeds-Shepp 位姿。
pub fn rs_pose_new(x : Double, y : Double, theta : Double) -> RSPose {
  @reed_shepp.RSPose::new(x, y, theta)
}

///|
/// Compute the shortest Reeds-Shepp path. / 计算最短 Reeds-Shepp 路径。
pub fn reed_shepp_shortest_path(
  start : RSPose,
  goal : RSPose,
  radius : Double,
) -> RSPath {
  @reed_shepp.reed_shepp_shortest_path(start, goal, radius)
}

///|
/// Sample points along a Reeds-Shepp path. / 沿 Reeds-Shepp 路径采样点。
pub fn reed_shepp_sample(
  path : RSPath,
  start : RSPose,
  num_samples : Int32,
) -> Array[Point2D] {
  @reed_shepp.reed_shepp_sample(path, start, num_samples)
}

///|
/// Get the total length of a Reeds-Shepp path. / 获取 Reeds-Shepp 路径总长度。
pub fn reed_shepp_path_length(path : RSPath) -> Double {
  @reed_shepp.reed_shepp_path_length(path)
}

///|
/// Count segments in a Reeds-Shepp path. / 统计 Reeds-Shepp 路径段数。
pub fn reed_shepp_segment_count(path : RSPath) -> Int32 {
  @reed_shepp.reed_shepp_segment_count(path)
}

///|
/// Check if a Reeds-Shepp path contains backward motion. / 检查 Reeds-Shepp 路径是否包含后退运动。
pub fn reed_shepp_has_backward(path : RSPath) -> Bool {
  @reed_shepp.reed_shepp_has_backward(path)
}

// ---------------------------------------------------------------------------
// collision_detect: Collision detection / 碰撞检测
// ---------------------------------------------------------------------------

///|
/// AABB. / 轴对齐包围盒。
pub type AABB = @collision_detect.AABB

///|
/// Collision pair. / 碰撞对。
pub type CollisionPair = @collision_detect.CollisionPair

///|
/// Construct an AABB. / 构造 AABB。
pub fn aabb_new(
  min_x : Double,
  min_y : Double,
  max_x : Double,
  max_y : Double,
) -> AABB {
  @collision_detect.AABB::new(min_x, min_y, max_x, max_y)
}

///|
/// Construct an AABB from center and half-extents. / 从中心和半边长构造 AABB。
pub fn aabb_from_center(
  cx : Double,
  cy : Double,
  hx : Double,
  hy : Double,
) -> AABB {
  @collision_detect.AABB::from_center(cx, cy, hx, hy)
}

///|
/// Check if two AABBs overlap. / 检查两个 AABB 是否重叠。
pub fn aabb_overlap(a : AABB, b : AABB) -> Bool {
  @collision_detect.aabb_overlap(a, b)
}

///|
/// Check if a point is inside an AABB. / 检查点是否在 AABB 内。
pub fn aabb_contains(box : AABB, x : Double, y : Double) -> Bool {
  @collision_detect.aabb_contains(box, x, y)
}

///|
/// Compute the AABB of a polygon. / 计算多边形的 AABB。
pub fn aabb_from_polygon(poly : Array[Point2D]) -> AABB {
  @collision_detect.aabb_from_polygon(poly)
}

///|
/// Broad phase collision detection. / 宽相碰撞检测。
pub fn broad_phase_aabb(boxes : Array[AABB]) -> Array[CollisionPair] {
  @collision_detect.broad_phase_aabb(boxes)
}

///|
/// Segment-segment collision. / 线段-线段碰撞。
pub fn segment_segment_collide(
  a1 : Point2D,
  a2 : Point2D,
  b1 : Point2D,
  b2 : Point2D,
) -> Bool {
  @collision_detect.segment_segment_collide(a1, a2, b1, b2)
}

///|
/// Point in polygon test. / 点在多边形内测试。
pub fn point_in_polygon_arr(p : Point2D, poly : Array[Point2D]) -> Bool {
  @collision_detect.point_in_polygon(p, poly)
}

///|
/// Circle-circle collision. / 圆-圆碰撞。
pub fn circle_circle_collide(
  c1 : Point2D,
  r1 : Double,
  c2 : Point2D,
  r2 : Double,
) -> Bool {
  @collision_detect.circle_circle_collide(c1, r1, c2, r2)
}

///|
/// Segment-polygon collision. / 线段-多边形碰撞。
pub fn segment_polygon_collide(
  a : Point2D,
  b : Point2D,
  poly : Array[Point2D],
) -> Bool {
  @collision_detect.segment_polygon_collide(a, b, poly)
}

///|
/// Polygon-polygon collision. / 多边形-多边形碰撞。
pub fn polygon_polygon_collide(
  poly1 : Array[Point2D],
  poly2 : Array[Point2D],
) -> Bool {
  @collision_detect.polygon_polygon_collide(poly1, poly2)
}

///|
/// Circle-polygon collision. / 圆-多边形碰撞。
pub fn circle_polygon_collide(
  center : Point2D,
  radius : Double,
  poly : Array[Point2D],
) -> Bool {
  @collision_detect.circle_polygon_collide(center, radius, poly)
}

///|
/// AABB-polygon collision. / AABB-多边形碰撞。
pub fn aabb_polygon_collide(box : AABB, poly : Array[Point2D]) -> Bool {
  @collision_detect.aabb_polygon_collide(box, poly)
}

///|
/// Compute AABB intersection. / 计算 AABB 交集。
pub fn aabb_intersection(a : AABB, b : AABB) -> AABB? {
  @collision_detect.aabb_intersection(a, b)
}

///|
/// Compute AABB union. / 计算 AABB 并集。
pub fn aabb_union(a : AABB, b : AABB) -> AABB {
  @collision_detect.aabb_union(a, b)
}

///|
/// Compute AABB area. / 计算 AABB 面积。
pub fn aabb_area(box : AABB) -> Double {
  @collision_detect.aabb_area(box)
}

// ---------------------------------------------------------------------------
// gjk: GJK collision detection / GJK 碰撞检测
// ---------------------------------------------------------------------------

///|
/// GJK result. / GJK 结果。
pub type GJKResult = @gjk.GJKResult

///|
/// Polygon support function. / 多边形支撑函数。
pub fn polygon_support(
  poly : Array[Point2D],
  dx : Double,
  dy : Double,
) -> Point2D {
  @gjk.polygon_support(poly, dx, dy)
}

///|
/// Circle support function. / 圆支撑函数。
pub fn circle_support(
  center : Point2D,
  radius : Double,
  dx : Double,
  dy : Double,
) -> Point2D {
  @gjk.circle_support(center, radius, dx, dy)
}

///|
/// Check collision between two convex polygons using GJK. / 使用 GJK 检测两凸多边形碰撞。
pub fn gjk_collide_polygons(
  poly1 : Array[Point2D],
  poly2 : Array[Point2D],
) -> GJKResult {
  @gjk.gjk_collide_polygons(poly1, poly2)
}

///|
/// Check collision between two circles using GJK. / 使用 GJK 检测两圆碰撞。
pub fn gjk_collide_circles(
  c1 : Point2D,
  r1 : Double,
  c2 : Point2D,
  r2 : Double,
) -> GJKResult {
  @gjk.gjk_collide_circles(c1, r1, c2, r2)
}

///|
/// Check collision between a polygon and a circle using GJK. / 使用 GJK 检测多边形与圆碰撞。
pub fn gjk_collide_polygon_circle(
  poly : Array[Point2D],
  center : Point2D,
  radius : Double,
) -> GJKResult {
  @gjk.gjk_collide_polygon_circle(poly, center, radius)
}

///|
/// Check if a point is inside a convex polygon using GJK. / 使用 GJK 检测点是否在凸多边形内。
pub fn gjk_point_in_polygon(p : Point2D, poly : Array[Point2D]) -> GJKResult {
  @gjk.gjk_point_in_polygon(p, poly)
}

// ---------------------------------------------------------------------------
// sat: SAT collision detection / SAT 碰撞检测
// ---------------------------------------------------------------------------

///|
/// SAT collision result. / SAT 碰撞结果。
pub type SATResult = @sat.SATResult

///|
/// Check collision between two convex polygons using SAT. / 使用 SAT 检测两凸多边形碰撞。
pub fn sat_collide_polygons(
  poly1 : Array[Point2D],
  poly2 : Array[Point2D],
) -> SATResult {
  @sat.sat_collide_polygons(poly1, poly2)
}

///|
/// Check if a convex polygon contains a point using SAT. / 使用 SAT 检测凸多边形是否包含点。
pub fn sat_contains_point(poly : Array[Point2D], p : Point2D) -> Bool {
  @sat.sat_contains_point(poly, p)
}

///|
/// Check collision between two circles using SAT. / 使用 SAT 检测两圆碰撞。
pub fn sat_collide_circles(
  c1 : Point2D,
  r1 : Double,
  c2 : Point2D,
  r2 : Double,
) -> SATResult {
  @sat.sat_collide_circles(c1, r1, c2, r2)
}

///|
/// Check collision between a polygon and a circle using SAT. / 使用 SAT 检测多边形与圆碰撞。
pub fn sat_collide_polygon_circle(
  poly : Array[Point2D],
  center : Point2D,
  radius : Double,
) -> SATResult {
  @sat.sat_collide_polygon_circle(poly, center, radius)
}

///|
/// Get the minimum translation vector. / 获取最小平移向量。
pub fn sat_mtv(result : SATResult) -> Point2D {
  @sat.sat_mtv(result)
}

///|
/// Get the separating axis direction. / 获取分离轴方向。
pub fn sat_separating_axis(result : SATResult) -> Point2D {
  @sat.sat_separating_axis(result)
}

// ---------------------------------------------------------------------------
// config_space: Configuration space / 配置空间
// ---------------------------------------------------------------------------

///|
/// C-space obstacle. / 配置空间障碍物。
pub type CSpaceObstacle = @config_space.CSpaceObstacle

///|
/// Construct a C-space obstacle. / 构造配置空间障碍物。
pub fn cspace_obstacle_new(vertices : Array[Point2D]) -> CSpaceObstacle {
  @config_space.CSpaceObstacle::new(vertices)
}

///|
/// Expand a polygonal obstacle by a circular robot radius. / 用圆形机器人半径膨胀多边形障碍物。
pub fn cspace_expand_circle(
  obstacle : Array[Point2D],
  radius : Double,
  num_arc_samples : Int32,
) -> CSpaceObstacle {
  @config_space.cspace_expand_circle(obstacle, radius, num_arc_samples)
}

///|
/// Check if a point is on the ellipse boundary. / 检查点是否在椭圆边界上。
pub fn ellipse_on_boundary(e : Ellipse, p : Point2D, eps : Double) -> Bool {
  @ellipse.Ellipse::on_boundary(e, p, eps)
}

///|
/// Focal points of the ellipse. / 椭圆焦点。
pub fn ellipse_foci(e : Ellipse) -> (Point2D, Point2D) {
  @ellipse.Ellipse::foci(e)
}

// ---------------------------------------------------------------------------
// bezier: Bezier curves / 贝塞尔曲线
// ---------------------------------------------------------------------------

///|
/// Quadratic Bezier curve type. / 二次贝塞尔曲线类型。
pub type Bezier2 = @bezier.Bezier2

///|
/// Cubic Bezier curve type. / 三次贝塞尔曲线类型。
pub type Bezier3 = @bezier.Bezier3

///|
/// Construct a quadratic Bezier curve. / 构造二次贝塞尔曲线。
pub fn bezier2_new(p0 : Point2D, p1 : Point2D, p2 : Point2D) -> Bezier2 {
  @bezier.Bezier2::new(p0, p1, p2)
}

///|
/// Evaluate quadratic Bezier at t. / 计算二次贝塞尔曲线在 t 处的值。
pub fn bezier2_eval(b : Bezier2, t : Double) -> Point2D {
  @bezier.Bezier2::eval(b, t)
}

///|
/// Expand a polygonal obstacle by a polygonal robot. / 用多边形机器人膨胀多边形障碍物。
pub fn cspace_expand_polygon(
  obstacle : Array[Point2D],
  robot : Array[Point2D],
) -> CSpaceObstacle {
  @config_space.cspace_expand_polygon(obstacle, robot)
}

///|
/// Check if a configuration point is valid. / 检查配置点是否有效。
pub fn cspace_point_valid(
  q : Point2D,
  cspace_obstacles : Array[CSpaceObstacle],
) -> Bool {
  @config_space.cspace_point_valid(q, cspace_obstacles)
}

///|
/// Check if a configuration space segment is valid. / 检查配置空间线段是否有效。
pub fn cspace_segment_valid(
  q1 : Point2D,
  q2 : Point2D,
  cspace_obstacles : Array[CSpaceObstacle],
) -> Bool {
  @config_space.cspace_segment_valid(q1, q2, cspace_obstacles)
}

///|
/// Build C-space obstacles. / 构建配置空间障碍物。
pub fn cspace_build(
  obstacles : Array[Array[Point2D]],
  robot_radius : Double,
  num_arc_samples : Int32,
) -> Array[CSpaceObstacle] {
  @config_space.cspace_build(obstacles, robot_radius, num_arc_samples)
}

// ---------------------------------------------------------------------------
// path_smooth: Path smoothing / 路径平滑
// ---------------------------------------------------------------------------

///|
/// Smoothing configuration. / 平滑配置。
pub type SmoothConfig = @path_smooth.SmoothConfig

///|
/// Construct smoothing configuration. / 构造平滑配置。
pub fn smooth_config_new(
  num_samples : Int32,
  tension : Double,
  preserve_endpoints : Bool,
) -> SmoothConfig {
  @path_smooth.SmoothConfig::new(num_samples, tension, preserve_endpoints)
}

///|
/// Smooth a path using Catmull-Rom spline. / 使用 Catmull-Rom 样条平滑路径。
pub fn smooth_path(
  path : Array[Point2D],
  config : SmoothConfig,
) -> Array[Point2D] {
  @path_smooth.smooth_path(path, config)
}

///|
/// Smooth a path using uniform cubic B-spline. / 使用均匀三次 B 样条平滑路径。
pub fn bspline_smooth(
  path : Array[Point2D],
  num_samples : Int32,
) -> Array[Point2D] {
  @path_smooth.bspline_smooth(path, num_samples)
}

///|
/// Smooth a path while preserving specified keypoint indices. / 平滑路径同时保留指定关键点索引。
pub fn smooth_preserve_keypoints(
  path : Array[Point2D],
  keypoints : Array[Int32],
  num_samples : Int32,
) -> Array[Point2D] {
  @path_smooth.smooth_preserve_keypoints(path, keypoints, num_samples)
}

///|
/// Compute the total length of a path. / 计算路径总长度。
pub fn path_smooth_length(path : Array[Point2D]) -> Double {
  @path_smooth.path_length(path)
}

///|
/// Reduce path to key points. / 将路径简化为关键点。
pub fn simplify_path(path : Array[Point2D], eps : Double) -> Array[Point2D] {
  @path_smooth.simplify_path(path, eps)
}

///|
/// Compute the maximum deviation between original and smoothed path. / 计算原始路径与平滑路径间的最大偏差。
pub fn path_max_deviation(
  original : Array[Point2D],
  smoothed : Array[Point2D],
) -> Double {
  @path_smooth.path_max_deviation(original, smoothed)
}
// ---------------------------------------------------------------------------
// conic_section: Conic sections / 圆锥曲线
// ---------------------------------------------------------------------------

///|
/// Conic section type. / 圆锥曲线类型。
pub type ConicType = @conic_section.ConicType

///|
/// Conic section. / 圆锥曲线。
pub type Conic = @conic_section.Conic

///|
pub fn conic_new(
  a : Double,
  b : Double,
  c : Double,
  d : Double,
  e : Double,
  f : Double,
) -> Conic {
  @conic_section.Conic::new(a, b, c, d, e, f)
}

///|
pub fn conic_eval(conic : Conic, p : Point2D) -> Double {
  @conic_section.Conic::eval(conic, p)
}

///|
pub fn conic_on_curve(conic : Conic, p : Point2D, eps : Double) -> Bool {
  @conic_section.Conic::on_curve(conic, p, eps)
}

///|
pub fn conic_discriminant(conic : Conic) -> Double {
  @conic_section.Conic::discriminant(conic)
}

///|
pub fn conic_classify(conic : Conic) -> ConicType {
  @conic_section.Conic::classify(conic)
}

///|
pub fn conic_center(conic : Conic) -> Point2D? {
  @conic_section.Conic::center(conic)
}

///|
pub fn conic_tangent_at(conic : Conic, p : Point2D) -> (Double, Double, Double) {
  @conic_section.Conic::tangent_at(conic, p)
}

///|
pub fn conic_asymptotes(
  conic : Conic,
) -> ((Double, Double, Double), (Double, Double, Double))? {
  @conic_section.Conic::asymptotes(conic)
}

///|
pub fn conic_eccentricity(conic : Conic) -> Double? {
  @conic_section.Conic::eccentricity(conic)
}

///|
pub fn conic_axis_aligned(conic : Conic) -> (Conic, Double) {
  @conic_section.Conic::axis_aligned(conic)
}

// ---------------------------------------------------------------------------
// quadric_surface: Quadric surfaces / 二次曲面
// ---------------------------------------------------------------------------

///|
/// Quadric surface type. / 二次曲面类型。
pub type QuadricType = @quadric_surface.QuadricType

///|
/// Quadric surface. / 二次曲面。
pub type Quadric = @quadric_surface.Quadric

///|
pub fn quadric_new(
  a : Double,
  b : Double,
  c : Double,
  d : Double,
  e : Double,
  f : Double,
  g : Double,
  h : Double,
  i : Double,
  j : Double,
) -> Quadric {
  @quadric_surface.Quadric::new(a, b, c, d, e, f, g, h, i, j)
}

///|
pub fn quadric_eval(q : Quadric, p : Point3D) -> Double {
  @quadric_surface.Quadric::eval(q, p)
}

///|
pub fn quadric_on_surface(q : Quadric, p : Point3D, eps : Double) -> Bool {
  @quadric_surface.Quadric::on_surface(q, p, eps)
}

///|
pub fn quadric_gradient(q : Quadric, p : Point3D) -> Point3D {
  @quadric_surface.Quadric::gradient(q, p)
}

///|
pub fn quadric_normal(q : Quadric, p : Point3D) -> Point3D {
  @quadric_surface.Quadric::normal(q, p)
}

///|
pub fn quadric_center(q : Quadric) -> Point3D? {
  @quadric_surface.Quadric::center(q)
}

///|
pub fn quadric_classify(q : Quadric) -> QuadricType {
  @quadric_surface.Quadric::classify(q)
}

// ---------------------------------------------------------------------------
// resultant: Resultant computation / 结式计算
// ---------------------------------------------------------------------------

///|
pub fn sylvester_matrix(
  p : Array[Double],
  q : Array[Double],
) -> Array[Array[Double]] {
  @resultant.sylvester_matrix(p, q)
}

///|
pub fn matrix_determinant(mat : Array[Array[Double]]) -> Double {
  @resultant.matrix_determinant(mat)
}

///|
pub fn resultant(p : Array[Double], q : Array[Double]) -> Double {
  @resultant.resultant(p, q)
}

///|
pub fn discriminant(coeffs : Array[Double]) -> Double {
  @resultant.discriminant(coeffs)
}

///|
pub fn poly_degree(coeffs : Array[Double]) -> Int32 {
  @resultant.poly_degree(coeffs)
}

///|
pub fn poly_sub(a : Array[Double], b : Array[Double]) -> Array[Double] {
  @resultant.poly_sub(a, b)
}

///|
pub fn poly_gcd(a : Array[Double], b : Array[Double]) -> Array[Double] {
  @resultant.poly_gcd(a, b)
}

///|
pub fn have_common_root(
  p : Array[Double],
  q : Array[Double],
  eps : Double,
) -> Bool {
  @resultant.have_common_root(p, q, eps)
}

// ---------------------------------------------------------------------------
// bezier_clipping: Bezier clipping / 贝塞尔裁剪
// ---------------------------------------------------------------------------

// ---------------------------------------------------------------------------
// implicit_curve: Implicit curve tracing / 隐式曲线追踪
// ---------------------------------------------------------------------------

///|
pub fn trace_curve(
  f : (Double, Double) -> Double,
  fx : (Double, Double) -> Double,
  fy : (Double, Double) -> Double,
  seed : Point2D,
  step : Double,
  n_steps : Int32,
) -> Array[Point2D] {
  @implicit_curve.trace_curve(f, fx, fy, seed, step, n_steps)
}

///|
pub fn newton_correct(
  f : (Double, Double) -> Double,
  fx : (Double, Double) -> Double,
  fy : (Double, Double) -> Double,
  p : Point2D,
  max_iter : Int32,
) -> Point2D {
  @implicit_curve.newton_correct(f, fx, fy, p, max_iter)
}

///|
pub fn implicit_curve_tangent(
  fx : (Double, Double) -> Double,
  fy : (Double, Double) -> Double,
  p : Point2D,
) -> Point2D {
  @implicit_curve.tangent(fx, fy, p)
}

///|
pub fn implicit_curve_normal(
  fx : (Double, Double) -> Double,
  fy : (Double, Double) -> Double,
  p : Point2D,
) -> Point2D {
  @implicit_curve.normal(fx, fy, p)
}

///|
pub fn implicit_curve_curvature(
  fx : (Double, Double) -> Double,
  fy : (Double, Double) -> Double,
  fxx : (Double, Double) -> Double,
  fxy : (Double, Double) -> Double,
  fyy : (Double, Double) -> Double,
  p : Point2D,
) -> Double {
  @implicit_curve.curvature(fx, fy, fxx, fxy, fyy, p)
}

///|
pub fn find_seed(
  f : (Double, Double) -> Double,
  x_lo : Double,
  x_hi : Double,
  y_lo : Double,
  y_hi : Double,
  n_samples : Int32,
) -> Point2D? {
  @implicit_curve.find_seed(f, x_lo, x_hi, y_lo, y_hi, n_samples)
}

// ---------------------------------------------------------------------------
// implicit_surface: Implicit surface / 隐式曲面
// ---------------------------------------------------------------------------

///|
pub fn implicit_surface_normal(
  fx : (Double, Double, Double) -> Double,
  fy : (Double, Double, Double) -> Double,
  fz : (Double, Double, Double) -> Double,
  p : Point3D,
) -> Point3D {
  @implicit_surface.surface_normal(fx, fy, fz, p)
}

///|
pub fn surface_gradient(
  fx : (Double, Double, Double) -> Double,
  fy : (Double, Double, Double) -> Double,
  fz : (Double, Double, Double) -> Double,
  p : Point3D,
) -> Point3D {
  @implicit_surface.surface_gradient(fx, fy, fz, p)
}

///|
pub fn implicit_gaussian_curvature(
  fx : (Double, Double, Double) -> Double,
  fy : (Double, Double, Double) -> Double,
  fz : (Double, Double, Double) -> Double,
  fxx : (Double, Double, Double) -> Double,
  fxy : (Double, Double, Double) -> Double,
  fxz : (Double, Double, Double) -> Double,
  fyy : (Double, Double, Double) -> Double,
  fyz : (Double, Double, Double) -> Double,
  fzz : (Double, Double, Double) -> Double,
  p : Point3D,
) -> Double {
  @implicit_surface.gaussian_curvature(
    fx, fy, fz, fxx, fxy, fxz, fyy, fyz, fzz, p,
  )
}

///|
pub fn implicit_mean_curvature(
  fx : (Double, Double, Double) -> Double,
  fy : (Double, Double, Double) -> Double,
  fz : (Double, Double, Double) -> Double,
  fxx : (Double, Double, Double) -> Double,
  fyy : (Double, Double, Double) -> Double,
  fzz : (Double, Double, Double) -> Double,
  p : Point3D,
) -> Double {
  @implicit_surface.mean_curvature(fx, fy, fz, fxx, fyy, fzz, p)
}

///|
pub fn principal_curvatures(
  k_gauss : Double,
  k_mean : Double,
) -> (Double, Double) {
  @implicit_surface.principal_curvatures(k_gauss, k_mean)
}

///|
pub fn project_to_surface(
  f : (Double, Double, Double) -> Double,
  fx : (Double, Double, Double) -> Double,
  fy : (Double, Double, Double) -> Double,
  fz : (Double, Double, Double) -> Double,
  p : Point3D,
  max_iter : Int32,
) -> Point3D {
  @implicit_surface.project_to_surface(f, fx, fy, fz, p, max_iter)
}

///|
pub fn tangent_plane(
  fx : (Double, Double, Double) -> Double,
  fy : (Double, Double, Double) -> Double,
  fz : (Double, Double, Double) -> Double,
  p : Point3D,
) -> (Double, Double, Double, Double) {
  @implicit_surface.tangent_plane(fx, fy, fz, p)
}

// ---------------------------------------------------------------------------
// ifs: Iterated Function Systems / 迭代函数系统
// ---------------------------------------------------------------------------

// ---------------------------------------------------------------------------
// l_system: L-systems / L 系统
// ---------------------------------------------------------------------------

// ---------------------------------------------------------------------------
// fractal_dimension: Fractal dimension / 分形维数
// ---------------------------------------------------------------------------

// ---------------------------------------------------------------------------
// hausdorff_dimension: Hausdorff dimension / Hausdorff 维数
// ---------------------------------------------------------------------------

// ---------------------------------------------------------------------------
// gis_projection: Map projections / 地图投影
// ---------------------------------------------------------------------------

///|
/// Projected coordinate pair. / 投影坐标对。
pub type ProjXY = @gis_projection.ProjXY

///|
pub fn proj_xy_new(x : Double, y : Double) -> ProjXY {
  @gis_projection.ProjXY::new(x, y)
}

///|
pub fn mercator_forward(lat : Double, lon : Double) -> ProjXY {
  @gis_projection.mercator_forward(lat, lon)
}

///|
pub fn mercator_inverse(x : Double, y : Double) -> (Double, Double) {
  @gis_projection.mercator_inverse(x, y)
}

///|
pub fn web_mercator_forward(lat : Double, lon : Double) -> ProjXY {
  @gis_projection.web_mercator_forward(lat, lon)
}

///|
pub fn web_mercator_inverse(x : Double, y : Double) -> (Double, Double) {
  @gis_projection.web_mercator_inverse(x, y)
}

///|
pub fn utm_zone_from_lon(lon : Double) -> Int32 {
  @gis_projection.utm_zone_from_lon(lon)
}

///|
pub fn utm_central_meridian(zone : Int32) -> Double {
  @gis_projection.utm_central_meridian(zone)
}

///|
pub fn utm_forward(lat : Double, lon : Double) -> ProjXY {
  @gis_projection.utm_forward(lat, lon)
}

///|
pub fn utm_forward_zone(lat : Double, lon : Double, zone : Int32) -> ProjXY {
  @gis_projection.utm_forward_zone(lat, lon, zone)
}

///|
pub fn lambert_conformal_forward(
  lat : Double,
  lon : Double,
  lat1 : Double,
  lat2 : Double,
  lat0 : Double,
  lon0 : Double,
) -> ProjXY {
  @gis_projection.lambert_conformal_forward(lat, lon, lat1, lat2, lat0, lon0)
}

///|
pub fn albers_equal_area_forward(
  lat : Double,
  lon : Double,
  lat1 : Double,
  lat2 : Double,
  lat0 : Double,
  lon0 : Double,
) -> ProjXY {
  @gis_projection.albers_equal_area_forward(lat, lon, lat1, lat2, lat0, lon0)
}

///|
pub fn mercator_scale(lat : Double) -> Double {
  @gis_projection.mercator_scale(lat)
}

// ---------------------------------------------------------------------------
// geodesic: Geodesic distance / 测地距离
// ---------------------------------------------------------------------------

///|
pub fn haversine_distance(
  lat1 : Double,
  lon1 : Double,
  lat2 : Double,
  lon2 : Double,
) -> Double {
  @geodesic.haversine_distance(lat1, lon1, lat2, lon2)
}

///|
pub fn spherical_distance(
  lat1 : Double,
  lon1 : Double,
  lat2 : Double,
  lon2 : Double,
) -> Double {
  @geodesic.spherical_distance(lat1, lon1, lat2, lon2)
}

///|
pub fn initial_bearing(
  lat1 : Double,
  lon1 : Double,
  lat2 : Double,
  lon2 : Double,
) -> Double {
  @geodesic.initial_bearing(lat1, lon1, lat2, lon2)
}

///|
pub fn destination_point(
  lat1 : Double,
  lon1 : Double,
  bearing : Double,
  distance : Double,
) -> (Double, Double) {
  @geodesic.destination_point(lat1, lon1, bearing, distance)
}

///|
pub fn vincenty_distance(
  lat1 : Double,
  lon1 : Double,
  lat2 : Double,
  lon2 : Double,
) -> Double {
  @geodesic.vincenty_distance(lat1, lon1, lat2, lon2)
}

///|
pub fn is_antipodal(
  lat1 : Double,
  lon1 : Double,
  lat2 : Double,
  lon2 : Double,
) -> Bool {
  @geodesic.is_antipodal(lat1, lon1, lat2, lon2)
}

// ---------------------------------------------------------------------------
// gis_buffer: Buffer operations / 缓冲操作
// ---------------------------------------------------------------------------

///|
pub fn point_buffer(center : Point2D, radius : Double, n : Int32) -> Polygon {
  @gis_buffer.point_buffer(center, radius, n)
}

///|
pub fn segment_buffer(
  a : Point2D,
  b : Point2D,
  radius : Double,
  cap_segments : Int32,
) -> Polygon {
  @gis_buffer.segment_buffer(a, b, radius, cap_segments)
}

///|
pub fn polyline_buffer(
  points : Array[Point2D],
  radius : Double,
  cap_segments : Int32,
) -> Polygon {
  @gis_buffer.polyline_buffer(points, radius, cap_segments)
}

///|
pub fn gis_minkowski_sum_convex(poly_a : Polygon, poly_b : Polygon) -> Polygon {
  @gis_buffer.minkowski_sum_convex(poly_a, poly_b)
}

///|
pub fn convex_polygon_buffer(
  poly : Polygon,
  radius : Double,
  n : Int32,
) -> Polygon {
  @gis_buffer.convex_polygon_buffer(poly, radius, n)
}

///|
pub fn polygon_offset_buffer(poly : Polygon, radius : Double) -> Polygon {
  @gis_buffer.polygon_offset_buffer(poly, radius)
}

// ---------------------------------------------------------------------------
// tin: Triangulated Irregular Network / 不规则三角网
// ---------------------------------------------------------------------------

///|
/// TIN (Triangulated Irregular Network). / 不规则三角网。
pub type TIN = @tin.TIN

///|
pub fn build_tin(points : Array[Point3D]) -> TIN {
  @tin.build_tin(points)
}

///|
pub fn tin_point_count(t : TIN) -> Int32 {
  @tin.TIN::point_count(t)
}

///|
pub fn tin_triangle_count(t : TIN) -> Int32 {
  @tin.TIN::triangle_count(t)
}

///|
pub fn tin_interpolate(t : TIN, p : Point2D) -> Double? {
  @tin.TIN::interpolate(t, p)
}

///|
pub fn tin_volume(t : TIN) -> Double {
  @tin.TIN::volume(t)
}

///|
pub fn tin_slope_at(t : TIN, p : Point2D) -> Double? {
  @tin.TIN::slope_at(t, p)
}

///|
pub fn tin_aspect_at(t : TIN, p : Point2D) -> Double? {
  @tin.TIN::aspect_at(t, p)
}

///|
pub fn tin_elevation_range(t : TIN) -> (Double, Double) {
  @tin.TIN::elevation_range(t)
}

// ---------------------------------------------------------------------------
// coordinate_convert: Coordinate conversion / 坐标转换
// ---------------------------------------------------------------------------

///|
/// ECEF coordinate. / 地心地固坐标。
pub type ECEF = @coordinate_convert.ECEF

///|
/// Geodetic coordinate. / 大地坐标。
pub type Geodetic = @coordinate_convert.Geodetic

///|
pub fn ecef_new(x : Double, y : Double, z : Double) -> ECEF {
  @coordinate_convert.ECEF::new(x, y, z)
}

///|
pub fn geodetic_new(lat : Double, lon : Double, h : Double) -> Geodetic {
  @coordinate_convert.Geodetic::new(lat, lon, h)
}

///|
pub fn wgs84_to_ecef(g : Geodetic) -> ECEF {
  @coordinate_convert.wgs84_to_ecef(g)
}

///|
pub fn ecef_to_wgs84(e : ECEF) -> Geodetic {
  @coordinate_convert.ecef_to_wgs84(e)
}

///|
pub fn cgcs2000_to_ecef(g : Geodetic) -> ECEF {
  @coordinate_convert.cgcs2000_to_ecef(g)
}

///|
pub fn ecef_to_cgcs2000(e : ECEF) -> Geodetic {
  @coordinate_convert.ecef_to_cgcs2000(e)
}

///|
pub fn wgs84_to_cgcs2000(g : Geodetic) -> Geodetic {
  @coordinate_convert.wgs84_to_cgcs2000(g)
}

///|
pub fn cgcs2000_to_wgs84(g : Geodetic) -> Geodetic {
  @coordinate_convert.cgcs2000_to_wgs84(g)
}

///|
pub fn ecef_distance(e1 : ECEF, e2 : ECEF) -> Double {
  @coordinate_convert.ecef_distance(e1, e2)
}

// ---------------------------------------------------------------------------
// datum_transform: Datum transformation / 基准转换
// ---------------------------------------------------------------------------

///|
/// 7-parameter Helmert transform. / 七参数 Helmert 变换。
pub type Helmert7 = @datum_transform.Helmert7

///|
/// 3-parameter transform. / 三参数变换。
pub type Helmert3 = @datum_transform.Helmert3

///|
pub fn helmert7_new(
  tx : Double,
  ty : Double,
  tz : Double,
  rx : Double,
  ry : Double,
  rz : Double,
  scale : Double,
) -> Helmert7 {
  @datum_transform.Helmert7::new(tx, ty, tz, rx, ry, rz, scale)
}

///|
pub fn helmert3_new(tx : Double, ty : Double, tz : Double) -> Helmert3 {
  @datum_transform.Helmert3::new(tx, ty, tz)
}

///|
pub fn apply_helmert7(
  h : Helmert7,
  x : Double,
  y : Double,
  z : Double,
) -> (Double, Double, Double) {
  @datum_transform.apply_helmert7(h, x, y, z)
}

///|
pub fn apply_helmert3(
  h : Helmert3,
  x : Double,
  y : Double,
  z : Double,
) -> (Double, Double, Double) {
  @datum_transform.apply_helmert3(h, x, y, z)
}

///|
pub fn inverse_helmert7(h : Helmert7) -> Helmert7 {
  @datum_transform.inverse_helmert7(h)
}

///|
pub fn inverse_helmert3(h : Helmert3) -> Helmert3 {
  @datum_transform.inverse_helmert3(h)
}

///|
pub fn helmert7_identity() -> Helmert7 {
  @datum_transform.helmert7_identity()
}

///|
pub fn compose_helmert7(a : Helmert7, b : Helmert7) -> Helmert7 {
  @datum_transform.compose_helmert7(a, b)
}

// ---------------------------------------------------------------------------
// raster_ops: Raster operations / 栅格操作
// ---------------------------------------------------------------------------

///|
/// Raster grid. / 栅格网格。
pub type Raster = @raster_ops.Raster

///|
pub fn raster_new(
  cols : Int32,
  rows : Int32,
  fill : Double,
  nodata : Double,
) -> Raster {
  @raster_ops.Raster::new(cols, rows, fill, nodata)
}

///|
pub fn raster_from_data(
  cols : Int32,
  rows : Int32,
  data : Array[Double],
  nodata : Double,
) -> Raster {
  @raster_ops.Raster::from_data(cols, rows, data, nodata)
}

///|
pub fn raster_get(r : Raster, col : Int32, row : Int32) -> Double {
  @raster_ops.Raster::get(r, col, row)
}

///|
pub fn raster_set(r : Raster, col : Int32, row : Int32, val : Double) -> Unit {
  @raster_ops.Raster::set(r, col, row, val)
}

///|
pub fn raster_cols(r : Raster) -> Int32 {
  @raster_ops.Raster::cols(r)
}

///|
pub fn raster_rows(r : Raster) -> Int32 {
  @raster_ops.Raster::rows(r)
}

///|
pub fn resample_nearest(
  r : Raster,
  new_cols : Int32,
  new_rows : Int32,
) -> Raster {
  @raster_ops.resample_nearest(r, new_cols, new_rows)
}

///|
pub fn resample_bilinear(
  r : Raster,
  new_cols : Int32,
  new_rows : Int32,
) -> Raster {
  @raster_ops.resample_bilinear(r, new_cols, new_rows)
}

///|
pub fn raster_mosaic(r1 : Raster, r2 : Raster) -> Raster {
  @raster_ops.mosaic(r1, r2)
}

///|
pub fn raster_add(r1 : Raster, r2 : Raster) -> Raster {
  @raster_ops.raster_add(r1, r2)
}

///|
pub fn raster_subtract(r1 : Raster, r2 : Raster) -> Raster {
  @raster_ops.raster_subtract(r1, r2)
}

///|
pub fn raster_multiply(r1 : Raster, r2 : Raster) -> Raster {
  @raster_ops.raster_multiply(r1, r2)
}

///|
pub fn raster_add_scalar(r : Raster, c : Double) -> Raster {
  @raster_ops.raster_add_scalar(r, c)
}

///|
pub fn raster_min(r : Raster) -> Double {
  @raster_ops.raster_min(r)
}

///|
pub fn raster_max(r : Raster) -> Double {
  @raster_ops.raster_max(r)
}

// ---------------------------------------------------------------------------
// contour_line: Contour line extraction / 等值线提取
// ---------------------------------------------------------------------------

///|
/// Contour line segment. / 等值线段。
pub type ContourSegment = @contour_line.ContourSegment

///|
/// Contour grid. / 等值线栅格。
pub type ContourGrid = @contour_line.ContourGrid

///|
pub fn contour_segment_new(
  x1 : Double,
  y1 : Double,
  x2 : Double,
  y2 : Double,
) -> ContourSegment {
  @contour_line.ContourSegment::new(x1, y1, x2, y2)
}

///|
pub fn contour_grid_new(
  cols : Int32,
  rows : Int32,
  data : Array[Double],
  cell_size : Double,
  x_origin : Double,
  y_origin : Double,
) -> ContourGrid {
  @contour_line.ContourGrid::new(
    cols, rows, data, cell_size, x_origin, y_origin,
  )
}

///|
pub fn marching_squares(
  g : ContourGrid,
  level : Double,
) -> Array[ContourSegment] {
  @contour_line.marching_squares(g, level)
}

///|
pub fn extract_contours(
  g : ContourGrid,
  levels : Array[Double],
) -> Array[(Double, Array[ContourSegment])] {
  @contour_line.extract_contours(g, levels)
}

///|
pub fn label_cell(
  g : ContourGrid,
  col : Int32,
  row : Int32,
  level : Double,
) -> Int32 {
  @contour_line.label_cell(g, col, row, level)
}

///|
pub fn count_contour_segments(g : ContourGrid, level : Double) -> Int32 {
  @contour_line.count_contour_segments(g, level)
}

// ---------------------------------------------------------------------------
// watershed: Watershed algorithm / 分水岭算法
// ---------------------------------------------------------------------------

///|
/// Watershed result. / 分水岭结果。
pub type WatershedResult = @watershed.WatershedResult

///|
pub fn marker_watershed(
  cols : Int32,
  rows : Int32,
  dem : Array[Double],
  markers : Array[Int32],
) -> WatershedResult {
  @watershed.marker_watershed(cols, rows, dem, markers)
}

///|
pub fn d8_flow_directions(
  cols : Int32,
  rows : Int32,
  dem : Array[Double],
) -> Array[Int32] {
  @watershed.d8_flow_directions(cols, rows, dem)
}

///|
pub fn basin_cell_counts(r : WatershedResult) -> Array[(Int32, Int32)] {
  @watershed.basin_cell_counts(r)
}

///|
pub fn fill_depressions(
  cols : Int32,
  rows : Int32,
  dem : Array[Double],
) -> Array[Double] {
  @watershed.fill_depressions(cols, rows, dem)
}

///|
pub fn watershed_result_cols(r : WatershedResult) -> Int32 {
  @watershed.WatershedResult::cols(r)
}

///|
pub fn watershed_result_rows(r : WatershedResult) -> Int32 {
  @watershed.WatershedResult::rows(r)
}

///|
pub fn watershed_result_get(
  r : WatershedResult,
  col : Int32,
  row : Int32,
) -> Int32 {
  @watershed.WatershedResult::get(r, col, row)
}

// ---------------------------------------------------------------------------
// delaunay_terrain: Terrain Delaunay / 地形 Delaunay
// ---------------------------------------------------------------------------

///|
/// Terrain from Delaunay triangulation. / Delaunay 三角剖分地形。
pub type Terrain = @delaunay_terrain.Terrain

///|
pub fn build_terrain(points : Array[Point3D]) -> Terrain {
  @delaunay_terrain.build_terrain(points)
}

///|
pub fn build_constrained_terrain(
  points : Array[Point3D],
  constraints : Array[(Int32, Int32)],
) -> Terrain {
  @delaunay_terrain.build_constrained_terrain(points, constraints)
}

///|
pub fn terrain_point_count(t : Terrain) -> Int32 {
  @delaunay_terrain.Terrain::point_count(t)
}

///|
pub fn terrain_triangle_count(t : Terrain) -> Int32 {
  @delaunay_terrain.Terrain::triangle_count(t)
}

///|
pub fn terrain_average_slope(t : Terrain) -> Double {
  @delaunay_terrain.Terrain::average_slope(t)
}

///|
pub fn terrain_aspect_at(t : Terrain, p : Point2D) -> Double? {
  @delaunay_terrain.Terrain::aspect_at(t, p)
}

///|
pub fn terrain_slope_at(t : Terrain, p : Point2D) -> Double? {
  @delaunay_terrain.Terrain::slope_at(t, p)
}

///|
pub fn terrain_surface_area(t : Terrain) -> Double {
  @delaunay_terrain.Terrain::surface_area(t)
}

///|
pub fn terrain_constraint_count(t : Terrain) -> Int32 {
  @delaunay_terrain.Terrain::constraint_count(t)
}

// ---------------------------------------------------------------------------
// Phase 4: Shape Analysis & Descriptors / 形状分析与描述子
// ---------------------------------------------------------------------------

///|
/// === Phase 4: Shape Analysis & Descriptors ===

// --- shape_context ---

pub fn shape_context(
  points : Array[Point2D],
  n_r_bins : Int32,
  n_theta_bins : Int32,
) -> Array[Array[Double]] {
  @shape_context.shape_context(points, n_r_bins, n_theta_bins)
}

///|
pub fn shape_context_distance(h1 : Array[Double], h2 : Array[Double]) -> Double {
  @shape_context.shape_context_distance(h1, h2)
}

///|
pub fn shape_context_cost(
  sc1 : Array[Array[Double]],
  sc2 : Array[Array[Double]],
) -> Array[Array[Double]] {
  @shape_context.shape_context_cost(sc1, sc2)
}

///|
pub fn shape_context_match(
  source : Array[Point2D],
  target : Array[Point2D],
  n_r_bins : Int32,
  n_theta_bins : Int32,
) -> Array[Int32] {
  @shape_context.shape_context_match(source, target, n_r_bins, n_theta_bins)
}

// --- fourier_descriptor ---

///|
pub fn fourier_descriptors(points : Array[Point2D]) -> Array[(Double, Double)] {
  @fourier_descriptor.fourier_descriptors(points)
}

///|
pub fn fourier_invariant(points : Array[Point2D]) -> Array[Double] {
  @fourier_descriptor.fourier_invariant(points)
}

///|
pub fn fourier_reconstruct(
  coeffs : Array[(Double, Double)],
  n : Int32,
) -> Array[Point2D] {
  @fourier_descriptor.fourier_reconstruct(coeffs, n)
}

///|
pub fn fourier_truncate(
  coeffs : Array[(Double, Double)],
  k : Int32,
) -> Array[(Double, Double)] {
  @fourier_descriptor.fourier_truncate(coeffs, k)
}

// --- moment_invariants ---

///|
pub fn raw_moment(points : Array[Point2D], p : Int32, q : Int32) -> Double {
  @moment_invariants.raw_moment(points, p, q)
}

///|
pub fn moment_centroid(points : Array[Point2D]) -> (Point2D, Double) {
  @moment_invariants.centroid(points)
}

///|
pub fn central_moment(points : Array[Point2D], p : Int32, q : Int32) -> Double {
  @moment_invariants.central_moment(points, p, q)
}

///|
pub fn normalized_moment(
  points : Array[Point2D],
  p : Int32,
  q : Int32,
) -> Double {
  @moment_invariants.normalized_moment(points, p, q)
}

///|
pub fn hu_moments(points : Array[Point2D]) -> Array[Double] {
  @moment_invariants.hu_moments(points)
}

///|
pub fn zernike_moment(
  points : Array[Point2D],
  n : Int32,
  m : Int32,
) -> (Double, Double) {
  @moment_invariants.zernike_moment(points, n, m)
}

///|
pub fn zernike_magnitude(
  points : Array[Point2D],
  n : Int32,
  m : Int32,
) -> Double {
  @moment_invariants.zernike_magnitude(points, n, m)
}

// --- skeleton_3d ---

///|
pub fn voxel_index(
  x : Int32,
  y : Int32,
  z : Int32,
  nx : Int32,
  ny : Int32,
) -> Int32 {
  @skeleton_3d.voxel_index(x, y, z, nx, ny)
}

///|
pub fn count_6_neighbors(
  voxels : Array[Bool],
  x : Int32,
  y : Int32,
  z : Int32,
  nx : Int32,
  ny : Int32,
  nz : Int32,
) -> Int32 {
  @skeleton_3d.count_6_neighbors(voxels, x, y, z, nx, ny, nz)
}

///|
pub fn count_26_neighbors(
  voxels : Array[Bool],
  x : Int32,
  y : Int32,
  z : Int32,
  nx : Int32,
  ny : Int32,
  nz : Int32,
) -> Int32 {
  @skeleton_3d.count_26_neighbors(voxels, x, y, z, nx, ny, nz)
}

///|
pub fn is_boundary_voxel(
  voxels : Array[Bool],
  x : Int32,
  y : Int32,
  z : Int32,
  nx : Int32,
  ny : Int32,
  nz : Int32,
) -> Bool {
  @skeleton_3d.is_boundary(voxels, x, y, z, nx, ny, nz)
}

///|
pub fn skeleton_3d(
  voxels : Array[Bool],
  nx : Int32,
  ny : Int32,
  nz : Int32,
) -> Array[Bool] {
  @skeleton_3d.skeleton_3d(voxels, nx, ny, nz)
}

///|
pub fn skeleton_volume(voxels : Array[Bool]) -> Int32 {
  @skeleton_3d.skeleton_volume(voxels)
}

///|
pub fn skeleton_endpoints(
  voxels : Array[Bool],
  nx : Int32,
  ny : Int32,
  nz : Int32,
) -> Int32 {
  @skeleton_3d.skeleton_endpoints(voxels, nx, ny, nz)
}

///|
pub fn skeleton_field(
  voxels : Array[Bool],
  nx : Int32,
  ny : Int32,
  nz : Int32,
) -> Array[Bool] {
  @skeleton_3d.skeleton_field(voxels, nx, ny, nz)
}

// --- medial_axis_3d ---

///|
/// Medial ball in 3D. / 三维中轴球。
pub type MedialBall3D = @medial_axis_3d.MedialBall3D

///|
pub fn medial_ball_3d_new(center : Point3D, radius : Double) -> MedialBall3D {
  @medial_axis_3d.MedialBall3D::new(center, radius)
}

///|
pub fn medial_ball_3d_center(ball : MedialBall3D) -> Point3D {
  @medial_axis_3d.MedialBall3D::center(ball)
}

///|
pub fn medial_ball_3d_radius(ball : MedialBall3D) -> Double {
  @medial_axis_3d.MedialBall3D::radius(ball)
}

///|
pub fn medial_axis_from_pairs(points : Array[Point3D]) -> Array[MedialBall3D] {
  @medial_axis_3d.medial_axis_from_pairs(points)
}

///|
pub fn medial_axis_from_triples(points : Array[Point3D]) -> Array[MedialBall3D] {
  @medial_axis_3d.medial_axis_from_triples(points)
}

///|
pub fn medial_axis_3d(points : Array[Point3D]) -> Array[MedialBall3D] {
  @medial_axis_3d.medial_axis_3d(points)
}

///|
pub fn medial_axis_filter(
  balls : Array[MedialBall3D],
  r_min : Double,
  r_max : Double,
) -> Array[MedialBall3D] {
  @medial_axis_3d.medial_axis_filter(balls, r_min, r_max)
}

///|
pub fn medial_axis_sort(balls : Array[MedialBall3D]) -> Array[MedialBall3D] {
  @medial_axis_3d.medial_axis_sort(balls)
}

// --- shape_matching ---

///|
pub fn hungarian(cost : Array[Array[Double]]) -> Array[Int32] {
  @shape_matching.hungarian(cost)
}

///|
pub fn shape_matching_icp(
  source : Array[Point2D],
  target : Array[Point2D],
  max_iter : Int32,
) -> Array[Int32] {
  @shape_matching.shape_matching_icp(source, target, max_iter)
}

///|
pub fn shape_matching_hungarian(
  source : Array[Point2D],
  target : Array[Point2D],
) -> Array[Int32] {
  @shape_matching.shape_matching_hungarian(source, target)
}

///|
pub fn shape_matching_score(
  source : Array[Point2D],
  target : Array[Point2D],
) -> Double {
  @shape_matching.shape_matching_score(source, target)
}

// --- curvature_scale ---

///|
pub fn gaussian_smooth(
  points : Array[Point2D],
  sigma : Double,
) -> Array[Point2D] {
  @curvature_scale.gaussian_smooth(points, sigma)
}

///|
pub fn css_curvature(points : Array[Point2D], sigma : Double) -> Array[Double] {
  @curvature_scale.css_curvature(points, sigma)
}

///|
pub fn css_inflection_points(
  points : Array[Point2D],
  sigma : Double,
) -> Array[Int32] {
  @curvature_scale.css_inflection_points(points, sigma)
}

///|
pub fn css_image(
  points : Array[Point2D],
  n_sigmas : Int32,
) -> Array[(Double, Int32)] {
  @curvature_scale.css_image(points, n_sigmas)
}

///|
pub fn css_maxima(points : Array[Point2D], n_sigmas : Int32) -> Array[Double] {
  @curvature_scale.css_maxima(points, n_sigmas)
}

// --- bend_energy ---

///|
pub fn bend_energy(points : Array[Point2D]) -> Double {
  @bend_energy.bend_energy(points)
}

///|
pub fn bend_energy_open(points : Array[Point2D]) -> Double {
  @bend_energy.bend_energy_open(points)
}

///|
pub fn total_curvature_energy(points : Array[Point2D]) -> Double {
  @bend_energy.total_curvature_energy(points)
}

///|
pub fn elastic_energy(points : Array[Point2D], tension : Double) -> Double {
  @bend_energy.elastic_energy(points, tension)
}

///|
pub fn curve_length(points : Array[Point2D]) -> Double {
  @bend_energy.curve_length(points)
}

///|
pub fn normalized_bend_energy(points : Array[Point2D]) -> Double {
  @bend_energy.normalized_bend_energy(points)
}

// --- procrustes ---

///|
/// Procrustes alignment result. / Procrustes 对齐结果。
pub type ProcrustesResult = @procrustes.ProcrustesResult

///|
pub fn procrustes_result_new(
  rotation : Double,
  tx : Double,
  ty : Double,
  scale : Double,
  error : Double,
) -> ProcrustesResult {
  @procrustes.ProcrustesResult::new(rotation, tx, ty, scale, error)
}

///|
pub fn procrustes_result_rotation(r : ProcrustesResult) -> Double {
  @procrustes.ProcrustesResult::rotation(r)
}

///|
pub fn procrustes_result_tx(r : ProcrustesResult) -> Double {
  @procrustes.ProcrustesResult::tx(r)
}

///|
pub fn procrustes_result_ty(r : ProcrustesResult) -> Double {
  @procrustes.ProcrustesResult::ty(r)
}

///|
pub fn procrustes_result_scale(r : ProcrustesResult) -> Double {
  @procrustes.ProcrustesResult::scale(r)
}

///|
pub fn procrustes_result_error(r : ProcrustesResult) -> Double {
  @procrustes.ProcrustesResult::error(r)
}

///|
pub fn procrustes(
  src : Array[Point2D],
  tgt : Array[Point2D],
) -> ProcrustesResult {
  @procrustes.procrustes(src, tgt)
}

///|
pub fn procrustes_apply(
  src : Array[Point2D],
  result : ProcrustesResult,
) -> Array[Point2D] {
  @procrustes.procrustes_apply(src, result)
}

///|
pub fn procrustes_error(src : Array[Point2D], tgt : Array[Point2D]) -> Double {
  @procrustes.procrustes_error(src, tgt)
}

///|
pub fn procrustes_analyze(
  shapes : Array[Array[Point2D]],
  max_iter : Int32,
) -> Array[Array[Point2D]] {
  @procrustes.procrustes_analyze(shapes, max_iter)
}

// --- icp ---

///|
/// ICP registration result. / ICP 配准结果。
pub type IcpResult = @icp.IcpResult

///|
pub fn icp_result_new(
  rotation : Array[Double],
  translation : Point3D,
  error : Double,
  iterations : Int32,
) -> IcpResult {
  @icp.IcpResult::new(rotation, translation, error, iterations)
}

///|
pub fn icp_result_rotation(r : IcpResult) -> Array[Double] {
  @icp.IcpResult::rotation(r)
}

///|
pub fn icp_result_translation(r : IcpResult) -> Point3D {
  @icp.IcpResult::translation(r)
}

///|
pub fn icp_result_error(r : IcpResult) -> Double {
  @icp.IcpResult::error(r)
}

///|
pub fn icp_result_iterations(r : IcpResult) -> Int32 {
  @icp.IcpResult::iterations(r)
}

///|
pub fn icp_point_to_point(
  source : Array[Point3D],
  target : Array[Point3D],
  max_iter : Int32,
) -> IcpResult {
  @icp.icp_point_to_point(source, target, max_iter)
}

///|
pub fn icp_point_to_plane(
  source : Array[Point3D],
  target : Array[Point3D],
  normals : Array[Point3D],
  max_iter : Int32,
) -> IcpResult {
  @icp.icp_point_to_plane(source, target, normals, max_iter)
}

///|
pub fn icp_apply(points : Array[Point3D], result : IcpResult) -> Array[Point3D] {
  @icp.icp_apply(points, result)
}

///|
pub fn icp_rms_error(
  source : Array[Point3D],
  target : Array[Point3D],
) -> Double {
  @icp.icp_rms_error(source, target)
}
// ---------------------------------------------------------------------------
// quadratic_prog: Quadratic programming / 二次规划
// ---------------------------------------------------------------------------

///|

///|
pub type QPResult = @quadratic_prog.QPResult

///|
pub fn qp_result_new(
  x : Array[Double],
  value : Double,
  success : Bool,
) -> QPResult {
  @quadratic_prog.QPResult::new(x, value, success)
}

///|
pub fn qp_solve_linear(
  a : Array[Array[Double]],
  b : Array[Double],
  n : Int32,
) -> Array[Double]? {
  @quadratic_prog.solve_linear(a, b, n)
}

///|
pub fn solve_unconstrained_qp(
  q : Array[Array[Double]],
  c : Array[Double],
  n : Int32,
) -> Array[Double]? {
  @quadratic_prog.solve_unconstrained_qp(q, c, n)
}

///|
pub fn active_set_qp(
  q : Array[Array[Double]],
  c : Array[Double],
  a : Array[Array[Double]],
  b : Array[Double],
  n : Int32,
  max_iter : Int32,
) -> QPResult {
  @quadratic_prog.active_set_qp(q, c, a, b, n, max_iter)
}

///|
pub fn qp_2d_box(
  q11 : Double,
  q12 : Double,
  q22 : Double,
  c1 : Double,
  c2 : Double,
  lo1 : Double,
  hi1 : Double,
  lo2 : Double,
  hi2 : Double,
) -> Point2D {
  @quadratic_prog.qp_2d_box(q11, q12, q22, c1, c2, lo1, hi1, lo2, hi2)
}

///|
pub fn qp_objective(
  q : Array[Array[Double]],
  c : Array[Double],
  x : Array[Double],
  n : Int32,
) -> Double {
  @quadratic_prog.qp_objective(q, c, x, n)
}

// ---------------------------------------------------------------------------
// gradient_descent: Gradient descent / 梯度下降
// ---------------------------------------------------------------------------

///|
pub fn gradient_descent(
  grad : (Array[Double]) -> Array[Double],
  x0 : Array[Double],
  lr : Double,
  max_iter : Int32,
) -> Array[Double] {
  @gradient_descent.gradient_descent(grad, x0, lr, max_iter)
} ///|

///|
pub fn momentum_gd(
  grad : (Array[Double]) -> Array[Double],
  x0 : Array[Double],
  lr : Double,
  momentum : Double,
  max_iter : Int32,
) -> Array[Double] {
  @gradient_descent.momentum_gd(grad, x0, lr, momentum, max_iter)
}

///|
pub fn nesterov_gd(
  grad : (Array[Double]) -> Array[Double],
  x0 : Array[Double],
  lr : Double,
  momentum : Double,
  max_iter : Int32,
) -> Array[Double] {
  @gradient_descent.nesterov_gd(grad, x0, lr, momentum, max_iter)
}

///|
pub fn adam(
  grad : (Array[Double]) -> Array[Double],
  x0 : Array[Double],
  lr : Double,
  beta1 : Double,
  beta2 : Double,
  eps : Double,
  max_iter : Int32,
) -> Array[Double] {
  @gradient_descent.adam(grad, x0, lr, beta1, beta2, eps, max_iter)
}

///|
pub fn gd_2d(
  grad : (Double, Double) -> (Double, Double),
  x0 : Double,
  y0 : Double,
  lr : Double,
  max_iter : Int32,
) -> Point2D {
  @gradient_descent.gd_2d(grad, x0, y0, lr, max_iter)
}

///|
pub fn rmsprop(
  grad : (Array[Double]) -> Array[Double],
  x0 : Array[Double],
  lr : Double,
  decay : Double,
  eps : Double,
  max_iter : Int32,
) -> Array[Double] {
  @gradient_descent.rmsprop(grad, x0, lr, decay, eps, max_iter)
}

// ---------------------------------------------------------------------------
// newton_method: Newton's method / 牛顿法
// ---------------------------------------------------------------------------

///|
pub fn newton_1d(
  f : (Double) -> Double,
  fp : (Double) -> Double,
  x0 : Double,
  tol : Double,
  max_iter : Int32,
) -> Double {
  @newton_method.newton_1d(f, fp, x0, tol, max_iter)
}

///|
pub fn newton_multi(
  grad : (Array[Double]) -> Array[Double],
  hess : (Array[Double]) -> Array[Array[Double]],
  x0 : Array[Double],
  tol : Double,
  max_iter : Int32,
) -> Array[Double] {
  @newton_method.newton_multi(grad, hess, x0, tol, max_iter)
} ///|

///|
pub fn newton_line_search(
  f : (Array[Double]) -> Double,
  grad : (Array[Double]) -> Array[Double],
  hess : (Array[Double]) -> Array[Array[Double]],
  x0 : Array[Double],
  max_iter : Int32,
) -> Array[Double] {
  @newton_method.newton_line_search(f, grad, hess, x0, max_iter)
}

///|
pub fn newton_trust_region(
  f : (Array[Double]) -> Double,
  grad : (Array[Double]) -> Array[Double],
  hess : (Array[Double]) -> Array[Array[Double]],
  x0 : Array[Double],
  max_delta : Double,
  max_iter : Int32,
) -> Array[Double] {
  @newton_method.newton_trust_region(f, grad, hess, x0, max_delta, max_iter)
}

///|
pub fn newton_2d(
  grad : (Double, Double) -> (Double, Double),
  hess : (Double, Double) -> ((Double, Double), (Double, Double)),
  x0 : Double,
  y0 : Double,
  max_iter : Int32,
) -> Point2D {
  @newton_method.newton_2d(grad, hess, x0, y0, max_iter)
}

// ---------------------------------------------------------------------------
// levenberg_marquardt: Levenberg-Marquardt / 非线性最小二乘
// ---------------------------------------------------------------------------

///|
pub type LMResult = @levenberg_marquardt.LMResult

///|
pub fn lm_result_new(
  x : Array[Double],
  residual : Double,
  iterations : Int32,
  success : Bool,
) -> LMResult {
  @levenberg_marquardt.LMResult::new(x, residual, iterations, success)
}

///|
pub fn levenberg_marquardt(
  residual : (Array[Double]) -> Array[Double],
  x0 : Array[Double],
  max_iter : Int32,
) -> LMResult {
  @levenberg_marquardt.levenberg_marquardt(residual, x0, max_iter)
}

///|
pub fn levenberg_marquardt_jac(
  residual : (Array[Double]) -> Array[Double],
  jacobian : (Array[Double]) -> Array[Array[Double]],
  x0 : Array[Double],
  max_iter : Int32,
) -> LMResult {
  @levenberg_marquardt.levenberg_marquardt_jac(residual, jacobian, x0, max_iter)
} ///|

///|
pub fn lm_line_fit(xs : Array[Double], ys : Array[Double]) -> (Double, Double) {
  @levenberg_marquardt.lm_line_fit(xs, ys)
}

///|
pub fn lm_rms_error(residual_sq : Double, n : Int32) -> Double {
  @levenberg_marquardt.lm_rms_error(residual_sq, n)
}

///|
pub fn lm_log_residual(residual_sq : Double) -> Double {
  @levenberg_marquardt.lm_log_residual(residual_sq)
}

// ---------------------------------------------------------------------------
// conjugate_gradient: Conjugate gradient / 共轭梯度
// ---------------------------------------------------------------------------

///|
pub fn cg_linear(
  a : Array[Array[Double]],
  b : Array[Double],
  x0 : Array[Double],
  max_iter : Int32,
) -> Array[Double] {
  @conjugate_gradient.cg_linear(a, b, x0, max_iter)
}

///|
pub fn pcg_linear(
  a : Array[Array[Double]],
  b : Array[Double],
  m_inv : (Array[Double]) -> Array[Double],
  x0 : Array[Double],
  max_iter : Int32,
) -> Array[Double] {
  @conjugate_gradient.pcg_linear(a, b, m_inv, x0, max_iter)
}

///|
pub fn nonlinear_cg(
  f : (Array[Double]) -> Double,
  grad : (Array[Double]) -> Array[Double],
  x0 : Array[Double],
  max_iter : Int32,
) -> Array[Double] {
  @conjugate_gradient.nonlinear_cg(f, grad, x0, max_iter)
}

///|
pub fn nonlinear_cg_2d(
  f : (Double, Double) -> Double,
  grad : (Double, Double) -> (Double, Double),
  x0 : Double,
  y0 : Double,
  max_iter : Int32,
) -> Point2D {
  @conjugate_gradient.nonlinear_cg_2d(f, grad, x0, y0, max_iter)
} ///|

///|
pub fn jacobi_preconditioner(
  a : Array[Array[Double]],
  n : Int32,
) -> (Array[Double]) -> Array[Double] {
  @conjugate_gradient.jacobi_preconditioner(a, n)
}

// ---------------------------------------------------------------------------
// simplex_method: Simplex method / 单纯形法
// ---------------------------------------------------------------------------

///|
pub type SimplexResult = @simplex_method.SimplexResult

///|
pub fn simplex_result_new(
  x : Array[Double],
  value : Double,
  success : Bool,
) -> SimplexResult {
  @simplex_method.SimplexResult::new(x, value, success)
}

///|
pub fn simplex(
  a : Array[Array[Double]],
  b : Array[Double],
  c : Array[Double],
  max_iter : Int32,
) -> SimplexResult {
  @simplex_method.simplex(a, b, c, max_iter)
}

///|
pub fn simplex_max(
  a : Array[Array[Double]],
  b : Array[Double],
  c : Array[Double],
  max_iter : Int32,
) -> SimplexResult {
  @simplex_method.simplex_max(a, b, c, max_iter)
}

// ---------------------------------------------------------------------------
// interior_point: Interior point method / 内点法
// ---------------------------------------------------------------------------

///|
pub type IPResult = @interior_point.IPResult

///|
pub fn ip_result_new(
  x : Array[Double],
  value : Double,
  success : Bool,
) -> IPResult {
  @interior_point.IPResult::new(x, value, success)
} ///|
/// Derivative of quadratic Bezier at t. / 二次贝塞尔曲线在 t 处的导数。

///|
pub fn bezier2_derivative(b : Bezier2, t : Double) -> Point2D {
  @bezier.Bezier2::derivative(b, t)
}

///|
/// Arc length of quadratic Bezier. / 二次贝塞尔曲线弧长。
pub fn bezier2_length(b : Bezier2) -> Double {
  @bezier.Bezier2::length(b)
}

///|
/// Bounding box of quadratic Bezier. / 二次贝塞尔曲线包围盒。
pub fn bezier2_bbox(b : Bezier2) -> (Double, Double, Double, Double) {
  @bezier.Bezier2::bbox(b)
}

///|
/// Subdivide quadratic Bezier at t. / 细分二次贝塞尔曲线。
pub fn bezier2_subdivide(b : Bezier2, t : Double) -> (Bezier2, Bezier2) {
  @bezier.Bezier2::subdivide(b, t)
}

///|
/// Construct a cubic Bezier curve. / 构造三次贝塞尔曲线。
pub fn bezier3_new(
  p0 : Point2D,
  p1 : Point2D,
  p2 : Point2D,
  p3 : Point2D,
) -> Bezier3 {
  @bezier.Bezier3::new(p0, p1, p2, p3)
}

///|
/// Evaluate cubic Bezier at t. / 计算三次贝塞尔曲线在 t 处的值。
pub fn bezier3_eval(b : Bezier3, t : Double) -> Point2D {
  @bezier.Bezier3::eval(b, t)
}

///|
/// Derivative of cubic Bezier at t. / 三次贝塞尔曲线在 t 处的导数。
pub fn bezier3_derivative(b : Bezier3, t : Double) -> Point2D {
  @bezier.Bezier3::derivative(b, t)
}

///|
pub fn interior_point(
  a : Array[Array[Double]],
  b : Array[Double],
  c : Array[Double],
  max_iter : Int32,
) -> IPResult {
  @interior_point.interior_point(a, b, c, max_iter)
}

///|
pub fn interior_point_max(
  a : Array[Array[Double]],
  b : Array[Double],
  c : Array[Double],
  max_iter : Int32,
) -> IPResult {
  @interior_point.interior_point_max(a, b, c, max_iter)
}

///|
pub fn duality_gap(x : Array[Double], s : Array[Double], n : Int32) -> Double {
  @interior_point.duality_gap(x, s, n)
}

// ---------------------------------------------------------------------------
// simulated_annealing: Simulated annealing / 模拟退火
// ---------------------------------------------------------------------------

///|
pub type CoolingSchedule = @simulated_annealing.CoolingSchedule

///|
pub type SAResult = @simulated_annealing.SAResult

///|
pub type SA_rng = @simulated_annealing.SA_rng

///|
pub fn sa_rng_new(seed : UInt32) -> SA_rng {
  @simulated_annealing.SA_rng::new(seed)
} ///|

///|
pub fn sa_rng_next(r : SA_rng) -> Double {
  @simulated_annealing.SA_rng::next(r)
}

///|
pub fn simulated_annealing(
  f : (Array[Double]) -> Double,
  x0 : Array[Double],
  neighbor : (Array[Double], SA_rng) -> Array[Double],
  t0 : Double,
  schedule : CoolingSchedule,
  min_temp : Double,
  max_iter : Int32,
  seed : UInt32,
) -> SAResult {
  @simulated_annealing.simulated_annealing(
    f, x0, neighbor, t0, schedule, min_temp, max_iter, seed,
  )
}

///|
pub fn uniform_neighbor(
  x : Array[Double],
  step : Double,
  rng : SA_rng,
) -> Array[Double] {
  @simulated_annealing.uniform_neighbor(x, step, rng)
}

///|
pub fn sa_1d(
  f : (Double) -> Double,
  x0 : Double,
  step : Double,
  t0 : Double,
  cooling_rate : Double,
  max_iter : Int32,
  seed : UInt32,
) -> Double {
  @simulated_annealing.sa_1d(f, x0, step, t0, cooling_rate, max_iter, seed)
}

///|
pub fn sa_reheat(
  f : (Array[Double]) -> Double,
  x0 : Array[Double],
  neighbor : (Array[Double], SA_rng) -> Array[Double],
  t0 : Double,
  cooling_rate : Double,
  max_iter : Int32,
  n_reheats : Int32,
  seed : UInt32,
) -> SAResult {
  @simulated_annealing.sa_reheat(
    f, x0, neighbor, t0, cooling_rate, max_iter, n_reheats, seed,
  )
}

// ---------------------------------------------------------------------------
// genetic_algorithm: Genetic algorithm / 遗传算法
// ---------------------------------------------------------------------------

///|
pub type GAConfig = @genetic_algorithm.GAConfig

///|

///|
pub type GAResult = @genetic_algorithm.GAResult

///|
pub fn ga_config_new(
  pop_size : Int32,
  n_genes : Int32,
  crossover_rate : Double,
  mutation_rate : Double,
  elite_count : Int32,
  lo : Array[Double],
  hi : Array[Double],
) -> GAConfig {
  @genetic_algorithm.GAConfig::new(
    pop_size, n_genes, crossover_rate, mutation_rate, elite_count, lo, hi,
  )
}

///|
pub fn ga_result_new(
  x : Array[Double],
  fitness : Double,
  generations : Int32,
) -> GAResult {
  @genetic_algorithm.GAResult::new(x, fitness, generations)
}

///|
pub fn genetic_algorithm(
  fitness : (Array[Double]) -> Double,
  config : GAConfig,
  max_generations : Int32,
  seed : UInt32,
) -> GAResult {
  @genetic_algorithm.genetic_algorithm(fitness, config, max_generations, seed)
}

///|
pub fn ga_minimize(
  f : (Array[Double]) -> Double,
  config : GAConfig,
  max_generations : Int32,
  seed : UInt32,
) -> GAResult {
  @genetic_algorithm.ga_minimize(f, config, max_generations, seed)
}

///|
pub fn ga_1d(
  f : (Double) -> Double,
  lo : Double,
  hi : Double,
  pop_size : Int32,
  max_generations : Int32,
  seed : UInt32,
) -> Double {
  @genetic_algorithm.ga_1d(f, lo, hi, pop_size, max_generations, seed)
}

///|
pub fn ga_population_std(fitness : Array[Double]) -> Double {
  @genetic_algorithm.ga_population_std(fitness)
}

///|
pub fn ga_mutation_schedule(
  initial_rate : Double,
  decay : Double,
  generation : Int32,
) -> Double {
  @genetic_algorithm.ga_mutation_schedule(initial_rate, decay, generation)
}

// ---------------------------------------------------------------------------
// pso: Particle swarm optimization / 粒子群优化
// ---------------------------------------------------------------------------

///|
pub type PSOConfig = @pso.PSOConfig

///|

///|
pub type PSOResult = @pso.PSOResult

///|
pub type PSOTopology = @pso.PSOTopology

///|
pub fn pso_config_new(
  n_particles : Int32,
  n_dims : Int32,
  w : Double,
  c1 : Double,
  c2 : Double,
  lo : Array[Double],
  hi : Array[Double],
  v_max : Double,
) -> PSOConfig {
  @pso.PSOConfig::new(n_particles, n_dims, w, c1, c2, lo, hi, v_max)
}

///|
pub fn pso_result_new(
  x : Array[Double],
  value : Double,
  iterations : Int32,
) -> PSOResult {
  @pso.PSOResult::new(x, value, iterations)
}

///|
pub fn pso(
  f : (Array[Double]) -> Double,
  config : PSOConfig,
  topology : PSOTopology,
  max_iter : Int32,
  seed : UInt32,
) -> PSOResult {
  @pso.pso(f, config, topology, max_iter, seed)
}

///|
pub fn pso_decreasing_w(
  f : (Array[Double]) -> Double,
  config : PSOConfig,
  w_max : Double,
  w_min : Double,
  topology : PSOTopology,
  max_iter : Int32,
  seed : UInt32,
) -> PSOResult {
  @pso.pso_decreasing_w(f, config, w_max, w_min, topology, max_iter, seed)
}

///|
pub fn pso_1d(
  f : (Double) -> Double,
  lo : Double,
  hi : Double,
  n_particles : Int32,
  max_iter : Int32,
  seed : UInt32,
) -> Double {
  @pso.pso_1d(f, lo, hi, n_particles, max_iter, seed)
}

///|
pub fn pso_swarm_radius(positions : Array[Double]) -> Double {
  @pso.pso_swarm_radius(positions)
}

///|
pub fn pso_inertia_schedule(
  w_max : Double,
  decay : Double,
  iteration : Int32,
) -> Double {
  @pso.pso_inertia_schedule(w_max, decay, iteration)
} // ---------------------------------------------------------------------------
// obj_io: OBJ file I/O / OBJ 文件读写
// ---------------------------------------------------------------------------

///|

///|
pub type ObjFaceVertex = @obj_io.ObjFaceVertex

///|
pub type ObjFace = @obj_io.ObjFace

///|
pub type ObjMesh = @obj_io.ObjMesh

///|
pub fn obj_face_vertex_new(v : Int32, vt : Int32, vn : Int32) -> ObjFaceVertex {
  @obj_io.ObjFaceVertex::new(v, vt, vn)
}

///|
pub fn obj_face_new(verts : Array[ObjFaceVertex]) -> ObjFace {
  @obj_io.ObjFace::new(verts)
}

///|
pub fn obj_mesh_new() -> ObjMesh {
  @obj_io.ObjMesh::new()
}

///|
pub fn obj_mesh_vertex_count(m : ObjMesh) -> Int32 {
  @obj_io.ObjMesh::vertex_count(m)
}

///|
pub fn obj_mesh_face_count(m : ObjMesh) -> Int32 {
  @obj_io.ObjMesh::face_count(m)
}

///|
pub fn obj_write(mesh : ObjMesh) -> String {
  @obj_io.obj_write(mesh)
}

///|
pub fn obj_parse(text : String) -> ObjMesh {
  @obj_io.obj_parse(text)
}
// ---------------------------------------------------------------------------
// stl_io: STL file I/O / STL 文件读写
// ---------------------------------------------------------------------------

///|
pub type StlTriangle = @stl_io.StlTriangle

///|
pub type StlMesh = @stl_io.StlMesh

///|
pub fn stl_triangle_new(
  normal : Point3D,
  v0 : Point3D,
  v1 : Point3D,
  v2 : Point3D,
) -> StlTriangle {
  @stl_io.StlTriangle::new(normal, v0, v1, v2)
}

///|
pub fn stl_mesh_new(name : String) -> StlMesh {
  @stl_io.StlMesh::new(name)
}

///|
pub fn stl_mesh_triangle_count(m : StlMesh) -> Int32 {
  @stl_io.StlMesh::triangle_count(m)
}

///|
pub fn stl_write_ascii(mesh : StlMesh) -> String {
  @stl_io.stl_write_ascii(mesh)
}

///|
pub fn stl_parse_ascii(text : String) -> StlMesh {
  @stl_io.stl_parse_ascii(text)
}

///|
pub fn stl_write_binary(mesh : StlMesh) -> Bytes {
  @stl_io.stl_write_binary(mesh)
}

///|
pub fn stl_parse_binary(data : Bytes) -> StlMesh {
  @stl_io.stl_parse_binary(data)
}
// ---------------------------------------------------------------------------
// ply_io: PLY file I/O / PLY 文件读写
// ---------------------------------------------------------------------------

///|
pub type PlyMesh = @ply_io.PlyMesh

///|
pub fn ply_mesh_new() -> PlyMesh {
  @ply_io.PlyMesh::new()
}

///|
pub fn ply_mesh_vertex_count(m : PlyMesh) -> Int32 {
  @ply_io.PlyMesh::vertex_count(m)
}

///|
pub fn ply_mesh_face_count(m : PlyMesh) -> Int32 {
  @ply_io.PlyMesh::face_count(m)
}

///|
pub fn ply_write_ascii(mesh : PlyMesh) -> String {
  @ply_io.ply_write_ascii(mesh)
}

///|
pub fn ply_parse_ascii(text : String) -> PlyMesh {
  @ply_io.ply_parse_ascii(text)
}

///|
pub fn ply_write_binary(mesh : PlyMesh) -> Bytes {
  @ply_io.ply_write_binary(mesh)
}

///|
pub fn ply_parse_binary(data : Bytes) -> PlyMesh {
  @ply_io.ply_parse_binary(data)
}
// ---------------------------------------------------------------------------
// gltf_io: glTF file I/O / glTF 文件读写
// ---------------------------------------------------------------------------

///|
pub type GltfMesh = @gltf_io.GltfMesh

///|
pub fn gltf_mesh_new() -> GltfMesh {
  @gltf_io.GltfMesh::new()
}

///|
pub fn gltf_mesh_vertex_count(m : GltfMesh) -> Int32 {
  @gltf_io.GltfMesh::vertex_count(m)
}

///|
pub fn gltf_mesh_index_count(m : GltfMesh) -> Int32 {
  @gltf_io.GltfMesh::index_count(m)
}

///|
pub fn gltf_write_json(mesh : GltfMesh) -> String {
  @gltf_io.gltf_write_json(mesh)
}

///|
pub fn gltf_parse_json(text : String) -> GltfMesh {
  @gltf_io.gltf_parse_json(text)
}

///|
pub fn gltf_write_binary(mesh : GltfMesh) -> Bytes {
  @gltf_io.gltf_write_binary(mesh)
}

///|
pub fn gltf_parse_binary(data : Bytes) -> GltfMesh {
  @gltf_io.gltf_parse_binary(data)
}
// ---------------------------------------------------------------------------
// geojson_io: GeoJSON I/O / GeoJSON 读写
// ---------------------------------------------------------------------------

///|
pub type GeoJsonGeometry = @geojson_io.GeoJsonGeometry

///|
pub fn geojson_point(p : Point2D) -> String {
  @geojson_io.geojson_point(p)
}

///|
pub fn geojson_linestring(points : Array[Point2D]) -> String {
  @geojson_io.geojson_linestring(points)
}

///|
pub fn geojson_polygon(rings : Array[Array[Point2D]]) -> String {
  @geojson_io.geojson_polygon(rings)
}

///|
pub fn geojson_multipoint(points : Array[Point2D]) -> String {
  @geojson_io.geojson_multipoint(points)
}

///|
pub fn geojson_multilinestring(lines : Array[Array[Point2D]]) -> String {
  @geojson_io.geojson_multilinestring(lines)
}

///|
pub fn geojson_multipolygon(polygons : Array[Array[Array[Point2D]]]) -> String {
  @geojson_io.geojson_multipolygon(polygons)
}

///|
pub fn geojson_write(geom : GeoJsonGeometry) -> String {
  @geojson_io.geojson_write(geom)
}

///|
pub fn geojson_parse(text : String) -> GeoJsonGeometry? {
  @geojson_io.geojson_parse(text)
}
// ---------------------------------------------------------------------------
// dxf_io: DXF file I/O / DXF 文件读写
// ---------------------------------------------------------------------------///|

///|
pub type DxfEntity = @dxf_io.DxfEntity

///|
pub type DxfDocument = @dxf_io.DxfDocument

///|
pub fn dxf_document_new() -> DxfDocument {
  @dxf_io.DxfDocument::new()
}

///|
pub fn dxf_document_entity_count(d : DxfDocument) -> Int32 {
  @dxf_io.DxfDocument::entity_count(d)
}

///|
pub fn dxf_write(doc : DxfDocument) -> String {
  @dxf_io.dxf_write(doc)
}

///|
pub fn dxf_parse(text : String) -> DxfDocument {
  @dxf_io.dxf_parse(text)
}
// ---------------------------------------------------------------------------
// ray_tracing: Ray tracing / 光线追踪
// ---------------------------------------------------------------------------

///|
pub type Ray3 = @ray_tracing.Ray3

///|
pub fn ray3_new(origin : Point3D, dir : Point3D) -> Ray3 {
  @ray_tracing.Ray3::new(origin, dir)
}

///|
pub fn ray3_eval(r : Ray3, t : Double) -> Point3D {
  @ray_tracing.ray_eval(r, t)
}

///|
pub fn ray_triangle_intersect(
  r : Ray3,
  v0 : Point3D,
  v1 : Point3D,
  v2 : Point3D,
) -> Double? {
  @ray_tracing.ray_triangle_intersect(r, v0, v1, v2)
}

///|
pub fn ray_sphere_intersect(
  r : Ray3,
  center : Point3D,
  radius : Double,
) -> Double? {
  @ray_tracing.ray_sphere_intersect(r, center, radius)
}

///|
pub fn ray_plane_intersect(
  r : Ray3,
  point : Point3D,
  normal : Point3D,
) -> Double? {
  @ray_tracing.ray_plane_intersect(r, point, normal)
}

///|
pub fn point_in_shadow(
  point : Point3D,
  light : Point3D,
  triangles : Array[(Point3D, Point3D, Point3D)],
) -> Bool {
  @ray_tracing.point_in_shadow(point, light, triangles)
}

///|
pub fn ray_nearest_triangle(
  r : Ray3,
  triangles : Array[(Point3D, Point3D, Point3D)],
) -> (Double, Int32)? {
  @ray_tracing.ray_nearest_triangle(r, triangles)
}
// ---------------------------------------------------------------------------
// marching_cubes: Marching Cubes / 移动立方体
// ---------------------------------------------------------------------------

///|
pub type McGrid = @marching_cubes.McGrid

///|
pub fn mc_grid_new(
  values : Array[Double],
  nx : Int32,
  ny : Int32,
  nz : Int32,
) -> McGrid {
  @marching_cubes.McGrid::new(values, nx, ny, nz)
}

///|
pub fn mc_grid_get(g : McGrid, i : Int32, j : Int32, k : Int32) -> Double {
  @marching_cubes.McGrid::get(g, i, j, k)
}

///|
pub fn marching_cubes(
  grid : McGrid,
  isolevel : Double,
) -> Array[(Point3D, Point3D, Point3D)] {
  @marching_cubes.marching_cubes(grid, isolevel)
}

///|
pub fn marching_cubes_count(grid : McGrid, isolevel : Double) -> Int32 {
  @marching_cubes.marching_cubes_count(grid, isolevel)
}

///|
pub fn cube_config_class(cube_idx : Int32) -> Int32 {
  @marching_cubes.cube_config_class(cube_idx)
}

///|
pub fn count_active_configs(grid : McGrid, isolevel : Double) -> Int32 {
  @marching_cubes.count_active_configs(grid, isolevel)
}
// ---------------------------------------------------------------------------
// hidden_line: Hidden line removal / 隐藏线消除
// ---------------------------------------------------------------------------

///|
pub type LineSeg3D = @hidden_line.LineSeg3D

///|
pub fn line_seg_3d_new(start : Point3D, end : Point3D) -> LineSeg3D {
  @hidden_line.LineSeg3D::new(start, end)
}

///|
pub fn project_to_2d(p : Point3D) -> Point2D {
  @hidden_line.project_to_2d(p)
}

///|
pub fn project_segment(s : LineSeg3D) -> (Point2D, Point2D) {
  @hidden_line.project_segment(s)
}

///|
pub fn point_in_triangle_2d(
  p : Point2D,
  a : Point2D,
  b : Point2D,
  c : Point2D,
) -> Bool {
  @hidden_line.point_in_triangle_2d(p, a, b, c)
}

///|
pub fn triangle_z_at(
  tri : (Point3D, Point3D, Point3D),
  x : Double,
  y : Double,
) -> Double? {
  @hidden_line.triangle_z_at(tri, x, y)
}

///|
pub fn hidden_line_remove(
  segments : Array[LineSeg3D],
  triangles : Array[(Point3D, Point3D, Point3D)],
) -> Array[(Point2D, Point2D)] {
  @hidden_line.hidden_line_remove(segments, triangles)
}

///|
pub fn count_visible(
  segments : Array[LineSeg3D],
  triangles : Array[(Point3D, Point3D, Point3D)],
) -> Int32 {
  @hidden_line.count_visible(segments, triangles)
}

///|
pub fn back_face_cull(
  triangles : Array[(Point3D, Point3D, Point3D)],
  view_dir : Point3D,
) -> Array[(Point3D, Point3D, Point3D)] {
  @hidden_line.back_face_cull(triangles, view_dir)
}
// ---------------------------------------------------------------------------
// rasterization: Rasterization / 光栅化
// ---------------------------------------------------------------------------

///|
pub type RasterBuffer = @rasterization.RasterBuffer

///|
pub fn raster_buffer_new(width : Int32, height : Int32) -> RasterBuffer {
  @rasterization.RasterBuffer::new(width, height)
}

///|
pub fn clear_buffer(buf : RasterBuffer, color : Int32, depth : Double) -> Unit {
  @rasterization.clear_buffer(buf, color, depth)
}

///|
pub fn set_pixel(
  buf : RasterBuffer,
  x : Int32,
  y : Int32,
  color : Int32,
) -> Unit {
  @rasterization.set_pixel(buf, x, y, color)
}

///|
pub fn set_pixel_depth(
  buf : RasterBuffer,
  x : Int32,
  y : Int32,
  color : Int32,
  depth : Double,
) -> Unit {
  @rasterization.set_pixel_depth(buf, x, y, color, depth)
}

///|
pub fn get_pixel(buf : RasterBuffer, x : Int32, y : Int32) -> Int32 {
  @rasterization.get_pixel(buf, x, y)
}

///|
pub fn get_depth(buf : RasterBuffer, x : Int32, y : Int32) -> Double {
  @rasterization.get_depth(buf, x, y)
}

///|
pub fn raster_line(
  buf : RasterBuffer,
  x0 : Int32,
  y0 : Int32,
  x1 : Int32,
  y1 : Int32,
  color : Int32,
) -> Unit {
  @rasterization.raster_line(buf, x0, y0, x1, y1, color)
}

///|
pub fn raster_triangle(
  buf : RasterBuffer,
  v0 : Point3D,
  v1 : Point3D,
  v2 : Point3D,
  color : Int32,
) -> Unit {
  @rasterization.raster_triangle(buf, v0, v1, v2, color)
}

///|
pub fn count_filled(buf : RasterBuffer, bg : Int32) -> Int32 {
  @rasterization.count_filled(buf, bg)
}

// ========== point_cloud ==========

///|
pub fn point_cloud_centroid(points : Array[@core.Point3D]) -> @core.Point3D {
  @point_cloud.point_cloud_centroid(points)
}

///|
pub fn point_cloud_aabb(
  points : Array[@core.Point3D],
) -> (@core.Point3D, @core.Point3D) {
  @point_cloud.point_cloud_aabb(points)
}

///|
pub fn voxel_downsample(
  points : Array[@core.Point3D],
  voxel_size : Double,
) -> Array[@core.Point3D] {
  @point_cloud.voxel_downsample(points, voxel_size)
}

///|
pub fn avg_nearest_neighbor_dist(points : Array[@core.Point3D]) -> Double {
  @point_cloud.avg_nearest_neighbor_dist(points)
}

///|
pub fn point_cloud_size(points : Array[@core.Point3D]) -> Int32 {
  @point_cloud.point_cloud_size(points)
}

// ========== voxel_grid ==========

///|
pub type VoxelGrid = @voxel_grid.VoxelGrid

///|
pub fn vg_voxel_index(grid : VoxelGrid, p : @core.Point3D) -> Int32 {
  @voxel_grid.voxel_index(grid, p)
}

///|
pub fn voxel_set(grid : VoxelGrid, p : @core.Point3D) -> VoxelGrid {
  @voxel_grid.voxel_set(grid, p)
}

///|
pub fn voxel_occupied(grid : VoxelGrid, p : @core.Point3D) -> Bool {
  @voxel_grid.voxel_occupied(grid, p)
}

///|
pub fn voxel_count_occupied(grid : VoxelGrid) -> Int32 {
  @voxel_grid.voxel_count_occupied(grid)
}

// ========== normal_est ==========

///|
pub fn pc_estimate_normal(
  center : @core.Point3D,
  neighbors : Array[@core.Point3D],
) -> @core.Point3D {
  @normal_est.estimate_normal(center, neighbors)
}

///|
pub fn normalize_normal(n : @core.Point3D) -> @core.Point3D {
  @normal_est.normalize_normal(n)
}

///|
pub fn orient_normal(
  normal : @core.Point3D,
  ref_dir : @core.Point3D,
) -> @core.Point3D {
  @normal_est.orient_normal(normal, ref_dir)
}

// ========== curvature_est ==========

///|
pub fn estimate_mean_curvature(
  center : @core.Point3D,
  neighbors : Array[@core.Point3D],
  normals : Array[@core.Point3D],
  center_normal : @core.Point3D,
) -> Double {
  @curvature_est.estimate_mean_curvature(
    center, neighbors, normals, center_normal,
  )
}

///|
pub fn estimate_gaussian_curvature(
  center : @core.Point3D,
  neighbors : Array[@core.Point3D],
) -> Double {
  @curvature_est.estimate_gaussian_curvature(center, neighbors)
}

///|
pub fn pc_principal_curvatures(
  k_gaussian : Double,
  k_mean : Double,
) -> (Double, Double) {
  @curvature_est.principal_curvatures(k_gaussian, k_mean)
}

// ========== pc_segment ==========

///|
pub fn segment_by_height(
  points : Array[@core.Point3D],
  threshold : Double,
) -> (Array[Int32], Array[Int32]) {
  @pc_segment.segment_by_height(points, threshold)
}

///|
pub fn segment_by_distance(
  points : Array[@core.Point3D],
  max_dist : Double,
) -> Array[Array[Int32]] {
  @pc_segment.segment_by_distance(points, max_dist)
}

///|
pub fn segment_count(clusters : Array[Array[Int32]]) -> Int32 {
  @pc_segment.segment_count(clusters)
}

// ========== pc_feature ==========

///|
pub fn local_density(
  points : Array[@core.Point3D],
  center : @core.Point3D,
  radius : Double,
) -> Int32 {
  @pc_feature.local_density(points, center, radius)
}

///|
pub fn curvature_feature(eigenvalues : Array[Double]) -> Double {
  @pc_feature.curvature_feature(eigenvalues)
}

///|
pub fn planarity_feature(eigenvalues : Array[Double]) -> Double {
  @pc_feature.planarity_feature(eigenvalues)
}

///|
pub fn scattering_feature(eigenvalues : Array[Double]) -> Double {
  @pc_feature.scattering_feature(eigenvalues)
}

// ========== pc_filter ==========

///|
pub fn statistical_filter(
  points : Array[@core.Point3D],
  k : Int32,
  threshold : Double,
) -> Array[Int32] {
  @pc_filter.statistical_filter(points, k, threshold)
}

///|
pub fn radius_filter(
  points : Array[@core.Point3D],
  radius : Double,
  min_neighbors : Int32,
) -> Array[Int32] {
  @pc_filter.radius_filter(points, radius, min_neighbors)
}

///|
pub fn removed_count(original : Int32, kept : Int32) -> Int32 {
  @pc_filter.removed_count(original, kept)
}

// ========== pc_transform ==========

///|
pub fn translate_cloud(
  points : Array[@core.Point3D],
  dx : Double,
  dy : Double,
  dz : Double,
) -> Array[@core.Point3D] {
  @pc_transform.translate_cloud(points, dx, dy, dz)
}

///|
pub fn scale_cloud(
  points : Array[@core.Point3D],
  factor : Double,
) -> Array[@core.Point3D] {
  @pc_transform.scale_cloud(points, factor)
}

///|
pub fn rotate_z_cloud(
  points : Array[@core.Point3D],
  angle : Double,
) -> Array[@core.Point3D] {
  @pc_transform.rotate_z_cloud(points, angle)
}

///|
pub fn center_cloud(points : Array[@core.Point3D]) -> Array[@core.Point3D] {
  @pc_transform.center_cloud(points)
}

// ========== simplicial_complex ==========

///|
pub type SimplicialComplex = @simplicial_complex.SimplicialComplex

///|
pub fn simplex_count(sc : SimplicialComplex) -> Int32 {
  @simplicial_complex.simplex_count(sc)
}

///|
pub fn complex_dimension(sc : SimplicialComplex) -> Int32 {
  @simplicial_complex.complex_dimension(sc)
}

///|
pub fn is_valid_complex(sc : SimplicialComplex) -> Bool {
  @simplicial_complex.is_valid_complex(sc)
}

///|
pub fn add_simplex(
  sc : SimplicialComplex,
  vertices : Array[Int32],
) -> SimplicialComplex {
  @simplicial_complex.add_simplex(sc, vertices)
}

// ========== cech_complex ==========

///|
pub fn cech_complex_simplices(
  n_points : Int32,
  max_dim : Int32,
) -> Array[Array[Int32]] {
  @cech_complex.cech_complex_simplices(n_points, max_dim)
}

///|
pub fn cech_nerve(balls : Int32) -> Array[Array[Int32]] {
  @cech_complex.cech_nerve(balls)
}

///|
pub fn cech_dimension(max_dim : Int32) -> Int32 {
  @cech_complex.cech_dimension(max_dim)
}

// ========== exact_predicates ==========

///|
pub fn exact_orientation(
  a : @core.Point2D,
  b : @core.Point2D,
  c : @core.Point2D,
) -> Int32 {
  @exact_predicates.exact_orientation(a, b, c)
}

///|
pub fn exact_incircle(
  a : @core.Point2D,
  b : @core.Point2D,
  c : @core.Point2D,
  d : @core.Point2D,
) -> Int32 {
  @exact_predicates.exact_incircle(a, b, c, d)
}

///|
pub fn exact_left_turn(
  a : @core.Point2D,
  b : @core.Point2D,
  c : @core.Point2D,
) -> Bool {
  @exact_predicates.exact_left_turn(a, b, c)
}

///|
pub fn exact_collinear(
  a : @core.Point2D,
  b : @core.Point2D,
  c : @core.Point2D,
) -> Bool {
  @exact_predicates.exact_collinear(a, b, c)
}

// ========== interval_arithmetic ==========

///|
pub type IAInterval = @interval_arithmetic.Interval

///|
pub fn interval_add(a : IAInterval, b : IAInterval) -> IAInterval {
  @interval_arithmetic.interval_add(a, b)
}

///|
pub fn interval_sub(a : IAInterval, b : IAInterval) -> IAInterval {
  @interval_arithmetic.interval_sub(a, b)
}

///|
pub fn interval_mul(a : IAInterval, b : IAInterval) -> IAInterval {
  @interval_arithmetic.interval_mul(a, b)
}

///|
pub fn ia_interval_contains(i : IAInterval, x : Double) -> Bool {
  @interval_arithmetic.interval_contains(i, x)
}

///|
pub fn interval_width(i : IAInterval) -> Double {
  @interval_arithmetic.interval_width(i)
}

///|
pub fn ia_interval_midpoint(i : IAInterval) -> Double {
  @interval_arithmetic.interval_midpoint(i)
}

// ========== filtered_predicates ==========

///|
pub fn filtered_orientation(
  a : @core.Point2D,
  b : @core.Point2D,
  c : @core.Point2D,
) -> Int32 {
  @filtered_predicates.filtered_orientation(a, b, c)
}

///|
pub fn filtered_incircle(
  a : @core.Point2D,
  b : @core.Point2D,
  c : @core.Point2D,
  d : @core.Point2D,
) -> Int32 {
  @filtered_predicates.filtered_incircle(a, b, c, d)
}

///|
pub fn perturbation_orientation(det : Double, eps : Double) -> Int32 {
  @filtered_predicates.perturbation_orientation(det, eps)
}

// ========== perturbation ==========

///|
pub fn sos_orientation(
  a : @core.Point2D,
  b : @core.Point2D,
  c : @core.Point2D,
  ia : Int32,
  ib : Int32,
  ic : Int32,
) -> Int32 {
  @perturbation.sos_orientation(a, b, c, ia, ib, ic)
}

///|
pub fn sos_sign(det : Double, perturbation_order : Int32) -> Int32 {
  @perturbation.sos_sign(det, perturbation_order)
}

///|
pub fn sos_compare(a : Double, b : Double, ia : Int32, ib : Int32) -> Int32 {
  @perturbation.sos_compare(a, b, ia, ib)
}

// ========== robust_construction ==========

///|
pub fn robust_circumcenter(
  a : @core.Point2D,
  b : @core.Point2D,
  c : @core.Point2D,
) -> @core.Point2D {
  @robust_construction.robust_circumcenter(a, b, c)
}

///|
pub fn robust_intersection(
  a : @core.Point2D,
  b : @core.Point2D,
  c : @core.Point2D,
  d : @core.Point2D,
) -> @core.Point2D {
  @robust_construction.robust_intersection(a, b, c, d)
}

///|
pub fn robust_midpoint(a : @core.Point2D, b : @core.Point2D) -> @core.Point2D {
  @robust_construction.robust_midpoint(a, b)
}

// ========== big_rational ==========

///|
pub type Rational = @big_rational.Rational

///|
pub fn rational_add(a : Rational, b : Rational) -> Rational {
  @big_rational.rational_add(a, b)
}

///|
pub fn rational_mul(a : Rational, b : Rational) -> Rational {
  @big_rational.rational_mul(a, b)
}

///|
pub fn rational_to_double(r : Rational) -> Double {
  @big_rational.rational_to_double(r)
}

///|
pub fn rational_equal(a : Rational, b : Rational) -> Bool {
  @big_rational.rational_equal(a, b)
}

///|
pub fn rational_sub(a : Rational, b : Rational) -> Rational {
  @big_rational.rational_sub(a, b)
}

// ========== de9im ==========

///|
pub fn de9im_intersects(
  a_bounds : (@core.Point2D, @core.Point2D),
  b_bounds : (@core.Point2D, @core.Point2D),
) -> Bool {
  @de9im.de9im_intersects(a_bounds, b_bounds)
}

///|
pub fn de9im_contains(
  a_bounds : (@core.Point2D, @core.Point2D),
  b_bounds : (@core.Point2D, @core.Point2D),
) -> Bool {
  @de9im.de9im_contains(a_bounds, b_bounds)
}

///|
pub fn de9im_disjoint(
  a_bounds : (@core.Point2D, @core.Point2D),
  b_bounds : (@core.Point2D, @core.Point2D),
) -> Bool {
  @de9im.de9im_disjoint(a_bounds, b_bounds)
}

///|
pub fn de9im_touches(
  a_bounds : (@core.Point2D, @core.Point2D),
  b_bounds : (@core.Point2D, @core.Point2D),
) -> Bool {
  @de9im.de9im_touches(a_bounds, b_bounds)
}

///|
pub fn de9im_within(
  a_bounds : (@core.Point2D, @core.Point2D),
  b_bounds : (@core.Point2D, @core.Point2D),
) -> Bool {
  @de9im.de9im_within(a_bounds, b_bounds)
}

// ========== lazy_exact ==========

///|
pub type LazyExact = @lazy_exact.LazyExact

///|
pub fn lazy_value(le : LazyExact) -> Double {
  @lazy_exact.lazy_value(le)
}

///|
pub fn lazy_approx(le : LazyExact) -> Double {
  @lazy_exact.lazy_approx(le)
}

///|
pub fn lazy_error(le : LazyExact) -> Double {
  @lazy_exact.lazy_error(le)
}

// ========== rounded_geometry ==========

///|
pub fn round_double(x : Double, precision : Int32) -> Double {
  @rounded_geometry.round_double(x, precision)
}

///|
pub fn rounded_area(points : Array[@core.Point2D], precision : Int32) -> Double {
  @rounded_geometry.rounded_area(points, precision)
}

///|
pub fn rounded_length(
  a : @core.Point2D,
  b : @core.Point2D,
  precision : Int32,
) -> Double {
  @rounded_geometry.rounded_length(a, b, precision)
}

// ========== affine_arithmetic ==========

///|
pub type AffineForm = @affine_arithmetic.AffineForm

///|
pub fn affine_add(a : AffineForm, b : AffineForm) -> AffineForm {
  @affine_arithmetic.affine_add(a, b)
}

///|
pub fn affine_to_interval(a : AffineForm) -> (Double, Double) {
  @affine_arithmetic.affine_to_interval(a)
}

///|
pub fn affine_scale(a : AffineForm, s : Double) -> AffineForm {
  @affine_arithmetic.affine_scale(a, s)
}

// ========== rational_map ==========

///|
pub type RationalMap = @rational_map.RationalMap

///|
pub fn rational_eval(m : RationalMap, x : Double) -> Double {
  @rational_map.rational_eval(m, x)
}

///|
pub fn rational_degree(m : RationalMap) -> Int32 {
  @rational_map.rational_degree(m)
}

///|
pub fn rational_is_defined(m : RationalMap, x : Double) -> Bool {
  @rational_map.rational_is_defined(m, x)
}

// ========== discrete_curvature ==========

///|
pub fn discrete_gaussian_curvature(angle_defect : Double) -> Double {
  @discrete_curvature.discrete_gaussian_curvature(angle_defect)
}

///|
pub fn discrete_mean_curvature(
  area : Double,
  edge_lengths : Array[Double],
  dihedral_angles : Array[Double],
) -> Double {
  @discrete_curvature.discrete_mean_curvature(
    area, edge_lengths, dihedral_angles,
  )
}

///|
pub fn angle_defect(angles : Array[Double]) -> Double {
  @discrete_curvature.angle_defect(angles)
}

///|
pub fn voronoi_area(edge_len : Double) -> Double {
  @discrete_curvature.voronoi_area(edge_len)
}

///|
pub fn mixed_area(a1 : Double, a2 : Double) -> Double {
  @discrete_curvature.mixed_area(a1, a2)
}

// ========== discrete_laplacian ==========

///|
pub fn uniform_laplacian(
  values : Array[Double],
  neighbors : Array[Double],
) -> Double {
  @discrete_laplacian.uniform_laplacian(values, neighbors)
}

///|
pub fn cotangent_weight(cot_a : Double, cot_b : Double) -> Double {
  @discrete_laplacian.cotangent_weight(cot_a, cot_b)
}

///|
pub fn cotangent_laplacian(
  center_val : Double,
  neighbor_vals : Array[Double],
  weights : Array[Double],
) -> Double {
  @discrete_laplacian.cotangent_laplacian(center_val, neighbor_vals, weights)
}

///|
pub fn laplacian_eigenvalue(mode : Int32, area : Double) -> Double {
  @discrete_laplacian.laplacian_eigenvalue(mode, area)
}

///|
pub fn is_harmonic(laplacian_val : Double, tol : Double) -> Bool {
  @discrete_laplacian.is_harmonic(laplacian_val, tol)
}

// ========== conformal_map ==========

///|
pub fn conformal_factor(scale_x : Double, scale_y : Double) -> Double {
  @conformal_map.conformal_factor(scale_x, scale_y)
}

///|
pub fn is_conformal(
  j11 : Double,
  j12 : Double,
  j21 : Double,
  j22 : Double,
  tol : Double,
) -> Bool {
  @conformal_map.is_conformal(j11, j12, j21, j22, tol)
}

///|
pub fn conformal_energy(stretch_u : Double, stretch_v : Double) -> Double {
  @conformal_map.conformal_energy(stretch_u, stretch_v)
}

///|
pub fn angle_distortion(theta_before : Double, theta_after : Double) -> Double {
  @conformal_map.angle_distortion(theta_before, theta_after)
}

///|
pub fn cm_area_distortion(area_before : Double, area_after : Double) -> Double {
  @conformal_map.area_distortion(area_before, area_after)
}

// ========== persistence_diagram ==========

///|
pub type PersistencePoint = @persistence_diagram.PersistencePoint

///|
pub fn persistence(p : PersistencePoint) -> Double {
  @persistence_diagram.persistence(p)
}

///|
pub fn is_essential(p : PersistencePoint) -> Bool {
  @persistence_diagram.is_essential(p)
}

///|
pub fn diagram_dimension(diagram : Array[PersistencePoint]) -> Int32 {
  @persistence_diagram.diagram_dimension(diagram)
}

///|
pub fn max_persistence(diagram : Array[PersistencePoint]) -> Double {
  @persistence_diagram.max_persistence(diagram)
}

// ========== finite_element ==========

///|
pub fn element_stiffness(
  grad_u : (Double, Double),
  grad_v : (Double, Double),
  area : Double,
) -> Double {
  @finite_element.element_stiffness(grad_u, grad_v, area)
}

///|
pub fn element_mass(u_val : Double, v_val : Double, area : Double) -> Double {
  @finite_element.element_mass(u_val, v_val, area)
}

///|
pub fn assemble_stiffness(
  n : Int32,
  elements : Array[(Int32, Int32, Int32, Double)],
) -> Array[Array[Double]] {
  @finite_element.assemble_stiffness(n, elements)
}

///|
pub fn apply_dirichlet(
  k : Array[Array[Double]],
  boundary_nodes : Array[Int32],
) -> Array[Array[Double]] {
  @finite_element.apply_dirichlet(k, boundary_nodes)
}

///|
pub fn fem_l2_error(exact : Array[Double], approx : Array[Double]) -> Double {
  @finite_element.fem_l2_error(exact, approx)
}

// ========== boundary_element ==========

///|
pub fn fundamental_solution_2d(r : Double) -> Double {
  @boundary_element.fundamental_solution_2d(r)
}

///|
pub fn boundary_integral_kernel(r : Double, normal_dist : Double) -> Double {
  @boundary_element.boundary_integral_kernel(r, normal_dist)
}

///|
pub fn bem_matrix_entry(r : Double, weight : Double) -> Double {
  @boundary_element.bem_matrix_entry(r, weight)
}

///|
pub fn bem_solve(
  matrix : Array[Array[Double]],
  rhs : Array[Double],
) -> Array[Double] {
  @boundary_element.bem_solve(matrix, rhs)
}

///|
pub fn bem_error(exact : Array[Double], approx : Array[Double]) -> Double {
  @boundary_element.bem_error(exact, approx)
}

// ========== level_set ==========

///|
pub fn level_set_sign(phi : Double) -> Int32 {
  @level_set.level_set_sign(phi)
}

///|
pub fn level_set_normal(grad_phi : (Double, Double)) -> (Double, Double) {
  @level_set.level_set_normal(grad_phi)
}

///|
pub fn level_set_curvature(
  grad : (Double, Double),
  hessian : (Double, Double, Double),
) -> Double {
  @level_set.level_set_curvature(grad, hessian)
}

///|
pub fn reinitialize_step(phi : Double, dt : Double, s0 : Int32) -> Double {
  @level_set.reinitialize_step(phi, dt, s0)
}

///|
pub fn level_set_area(phi : Array[Double], dx : Double) -> Double {
  @level_set.level_set_area(phi, dx)
}

// ========== fast_marching ==========

///|
pub fn solve_eikonal_2d(
  u_left : Double,
  u_down : Double,
  f : Double,
  h : Double,
) -> Double {
  @fast_marching.solve_eikonal_2d(u_left, u_down, f, h)
}

///|
pub fn fast_marching_step(
  narrow_band : Array[(Int32, Double)],
  f : Double,
  h : Double,
) -> Array[(Int32, Double)] {
  @fast_marching.fast_marching_step(narrow_band, f, h)
}

///|
pub fn is_far(value : Double) -> Bool {
  @fast_marching.is_far(value)
}

///|
pub fn is_frozen(value : Double) -> Bool {
  @fast_marching.is_frozen(value)
}

// ========== fast_sweeping ==========

///|
pub fn sweep_update(
  u_center : Double,
  u_neighbor1 : Double,
  u_neighbor2 : Double,
  f : Double,
  h : Double,
) -> Double {
  @fast_sweeping.sweep_update(u_center, u_neighbor1, u_neighbor2, f, h)
}

///|
pub fn fast_sweeping_iterate(
  u : Array[Double],
  f : Array[Double],
  h : Double,
  nx : Int32,
  ny : Int32,
) -> Array[Double] {
  @fast_sweeping.fast_sweeping_iterate(u, f, h, nx, ny)
}

///|
pub fn sweeping_converged(
  u_old : Array[Double],
  u_new : Array[Double],
  tol : Double,
) -> Bool {
  @fast_sweeping.sweeping_converged(u_old, u_new, tol)
}

// ========== ray_trace_ops ==========

///|
pub fn reflect(
  incident : (Double, Double, Double),
  normal : (Double, Double, Double),
) -> (Double, Double, Double) {
  @ray_trace_ops.reflect(incident, normal)
}

///|
pub fn refract(
  incident : (Double, Double, Double),
  normal : (Double, Double, Double),
  eta : Double,
) -> (Double, Double, Double) {
  @ray_trace_ops.refract(incident, normal, eta)
}

///|
pub fn fresnel_schlick(cos_theta : Double, f0 : Double) -> Double {
  @ray_trace_ops.fresnel_schlick(cos_theta, f0)
}

///|
pub fn ray_plane_t(
  origin : (Double, Double, Double),
  dir : (Double, Double, Double),
  point : (Double, Double, Double),
  normal : (Double, Double, Double),
) -> Double {
  @ray_trace_ops.ray_plane_t(origin, dir, point, normal)
}

// ========== raster_2d ==========

///|
pub fn bresenham_line(
  x0 : Int32,
  y0 : Int32,
  x1 : Int32,
  y1 : Int32,
) -> Array[(Int32, Int32)] {
  @raster_2d.bresenham_line(x0, y0, x1, y1)
}

///|
pub fn edge_function(
  a : (Double, Double),
  b : (Double, Double),
  c : (Double, Double),
) -> Double {
  @raster_2d.edge_function(a, b, c)
}

///|
pub fn barycentric_coord(
  p : (Double, Double),
  a : (Double, Double),
  b : (Double, Double),
  c : (Double, Double),
) -> (Double, Double, Double) {
  @raster_2d.barycentric_coord(p, a, b, c)
}

///|
pub fn point_in_triangle(
  p : (Double, Double),
  a : (Double, Double),
  b : (Double, Double),
  c : (Double, Double),
) -> Bool {
  @raster_2d.point_in_triangle(p, a, b, c)
}

// ========== gpu_geometry ==========

///|
pub fn morton_code_2d(x : Int32, y : Int32) -> Int32 {
  @gpu_geometry.morton_code_2d(x, y)
}

///|
pub fn hilbert_d2xy(d : Int32, i : Int32) -> (Int32, Int32) {
  @gpu_geometry.hilbert_d2xy(d, i)
}

///|
pub fn vertex_cache_optimize(
  indices : Array[Int32],
  cache_size_ : Int32,
) -> Array[Int32] {
  @gpu_geometry.vertex_cache_optimize(indices, cache_size_)
}

///|
pub fn meshlet_bounds(
  verts : Array[(Double, Double, Double)],
) -> ((Double, Double, Double), Double) {
  @gpu_geometry.meshlet_bounds(verts)
}

// ========== heat_equation ==========

///|
pub fn he_heat_explicit_step(
  u : Array[Double],
  alpha : Double,
  dt : Double,
  dx : Double,
) -> Array[Double] {
  @heat_equation.heat_explicit_step(u, alpha, dt, dx)
}

///|
pub fn heat_steady_state_1d(
  boundary_left : Double,
  boundary_right : Double,
  n : Int32,
) -> Array[Double] {
  @heat_equation.heat_steady_state_1d(boundary_left, boundary_right, n)
}

///|
pub fn heat_analytical_1d(
  x : Double,
  t : Double,
  alpha : Double,
  length : Double,
) -> Double {
  @heat_equation.heat_analytical_1d(x, t, alpha, length)
}

// ========== wave_equation ==========

///|
pub fn we_wave_explicit_step(
  u_prev : Array[Double],
  u_curr : Array[Double],
  c : Double,
  dt : Double,
  dx : Double,
) -> Array[Double] {
  @wave_equation.wave_explicit_step(u_prev, u_curr, c, dt, dx)
}

///|
pub fn we_wave_damping(u : Double, damping : Double, dt : Double) -> Double {
  @wave_equation.wave_damping(u, damping, dt)
}

///|
pub fn we_wave_energy(
  u : Array[Double],
  u_prev : Array[Double],
  dt : Double,
) -> Double {
  @wave_equation.wave_energy(u, u_prev, dt)
}

// ========== poisson_solver ==========

///|
pub fn ps_poisson_jacobi(
  u : Array[Double],
  f : Array[Double],
  h : Double,
) -> Array[Double] {
  @poisson_solver.poisson_jacobi(u, f, h)
}

///|
pub fn poisson_gauss_seidel(
  u : Array[Double],
  f : Array[Double],
  h : Double,
) -> Array[Double] {
  @poisson_solver.poisson_gauss_seidel(u, f, h)
}

///|
pub fn ps_poisson_residual(
  u : Array[Double],
  f : Array[Double],
  h : Double,
) -> Double {
  @poisson_solver.poisson_residual(u, f, h)
}

// ========== navier_stokes ==========

///|
pub fn ns_ns_advection(
  u : Array[Double],
  v : Array[Double],
  dx : Double,
  dy : Double,
) -> Array[Double] {
  @navier_stokes.ns_advection(u, v, dx, dy)
}

///|
pub fn ns_diffusion(
  u : Array[Double],
  nu : Double,
  dx : Double,
) -> Array[Double] {
  @navier_stokes.ns_diffusion(u, nu, dx)
}

///|
pub fn ns_pressure_gradient(p : Array[Double], dx : Double) -> Array[Double] {
  @navier_stokes.ns_pressure_gradient(p, dx)
}

///|
pub fn ns_reynolds_number(
  rho : Double,
  v : Double,
  length : Double,
  mu : Double,
) -> Double {
  @navier_stokes.ns_reynolds_number(rho, v, length, mu)
}

// ========== advection_solver ==========

///|
pub fn as_upwind_advection(
  u : Array[Double],
  c : Double,
  dt : Double,
  dx : Double,
) -> Array[Double] {
  @advection_solver.upwind_advection(u, c, dt, dx)
}

///|
pub fn lax_friedrichs(
  u : Array[Double],
  c : Double,
  dt : Double,
  dx : Double,
) -> Array[Double] {
  @advection_solver.lax_friedrichs(u, c, dt, dx)
}

///|
pub fn lax_wendroff(
  u : Array[Double],
  c : Double,
  dt : Double,
  dx : Double,
) -> Array[Double] {
  @advection_solver.lax_wendroff(u, c, dt, dx)
}

// ========== diffusion_solver ==========

///|
pub fn crank_nicolson_coef(d : Double, dt : Double, dx : Double) -> Double {
  @diffusion_solver.crank_nicolson_coef(d, dt, dx)
}

///|
pub fn ds_diffusion_2d_step(
  field : Array[Array[Double]],
  d : Double,
  dt : Double,
  dx : Double,
  dy : Double,
) -> Array[Array[Double]] {
  @diffusion_solver.diffusion_2d_step(field, d, dt, dx, dy)
}

///|
pub fn ds_diffusion_stability_check(
  d : Double,
  dt : Double,
  dx : Double,
) -> Bool {
  @diffusion_solver.diffusion_stability_check(d, dt, dx)
}

// ========== geometric_algebra ==========

///|
pub type Multivector = @geometric_algebra.Multivector

///|
pub fn multivector_new(
  scalar : Double,
  e1 : Double,
  e2 : Double,
  e12 : Double,
) -> Multivector {
  @geometric_algebra.Multivector::new(scalar, e1, e2, e12)
}

///|
pub fn multivector_add(
  self_val : Multivector,
  other : Multivector,
) -> Multivector {
  @geometric_algebra.Multivector::add(self_val, other)
}

///|
pub fn multivector_mul(
  self_val : Multivector,
  other : Multivector,
) -> Multivector {
  @geometric_algebra.Multivector::mul(self_val, other)
}

///|
pub fn multivector_reverse(self_val : Multivector) -> Multivector {
  @geometric_algebra.Multivector::reverse(self_val)
}

///|
pub fn multivector_norm(self_val : Multivector) -> Double {
  @geometric_algebra.Multivector::norm(self_val)
}

///|
pub fn ga_rotor(angle : Double) -> Multivector {
  @geometric_algebra.rotor(angle)
}

///|
pub fn ga_rotate_vector(
  vx : Double,
  vy : Double,
  angle : Double,
) -> (Double, Double) {
  @geometric_algebra.rotate_vector(vx, vy, angle)
}

// ========== discrete_diff_geom ==========

///|
pub fn discrete_connection(edges : Array[Double]) -> Double {
  @discrete_diff_geom.discrete_connection(edges)
}

///|
pub fn ddg_holonomy(angles : Array[Double]) -> Double {
  @discrete_diff_geom.holonomy(angles)
}

///|
pub fn ddg_parallel_transport(
  vx : Double,
  vy : Double,
  angle : Double,
) -> (Double, Double) {
  @discrete_diff_geom.parallel_transport(vx, vy, angle)
}

///|
pub fn discrete_curvature2d(angles : Array[Double]) -> Double {
  @discrete_diff_geom.discrete_curvature2d(angles)
}

///|
pub fn gauss_map_normals(angles : Array[Double]) -> Array[Double] {
  @discrete_diff_geom.gauss_map_normals(angles)
}

// ========== knot_theory ==========

///|
pub fn crossing_number(crossings : Array[Int32]) -> Int32 {
  @knot_theory.crossing_number(crossings)
}

///|
pub fn writhe(signs : Array[Int32]) -> Int32 {
  @knot_theory.writhe(signs)
}

///|
pub fn jones_unknot(t : Double) -> Double {
  @knot_theory.jones_unknot(t)
}

///|
pub fn jones_trefoil(t : Double) -> Double {
  @knot_theory.jones_trefoil(t)
}

///|
pub fn jones_figure8(t : Double) -> Double {
  @knot_theory.jones_figure8(t)
}

///|
pub fn linking_number(
  loop1 : Array[(Double, Double, Double)],
  loop2 : Array[(Double, Double, Double)],
) -> Int32 {
  @knot_theory.linking_number(loop1, loop2)
}

///|
pub fn unknotting_number(genus : Int32) -> Int32 {
  @knot_theory.unknotting_number(genus)
}

// ========== geom_arrangement ==========

///|
pub fn line_arrangement_count(n : Int32) -> Int32 {
  @geom_arrangement.line_arrangement_count(n)
}

///|
pub fn ga_line_intersection(
  a1 : Double,
  b1 : Double,
  c1 : Double,
  a2 : Double,
  b2 : Double,
  c2 : Double,
) -> (Double, Double) {
  @geom_arrangement.line_intersection(a1, b1, c1, a2, b2, c2)
}

///|
pub fn ga_zone_complexity(n : Int32) -> Int32 {
  @geom_arrangement.zone_complexity(n)
}

///|
pub fn arrangement_faces(n : Int32) -> Int32 {
  @geom_arrangement.arrangement_faces(n)
}

///|
pub fn hyperplane_arrangement_regions(n : Int32, d : Int32) -> Int32 {
  @geom_arrangement.hyperplane_arrangement_regions(n, d)
}

///|
pub fn is_simple_arrangement(slopes : Array[Double]) -> Bool {
  @geom_arrangement.is_simple_arrangement(slopes)
}

// ========== exact_pred ==========

///|
pub fn ep_exact_orientation(
  x_a : Double,
  y_a : Double,
  x_b : Double,
  y_b : Double,
  x_c : Double,
  y_c : Double,
) -> Int32 {
  @exact_pred.exact_orientation(x_a, y_a, x_b, y_b, x_c, y_c)
}

///|
pub fn ep_exact_incircle(
  ax : Double,
  ay : Double,
  bx : Double,
  by : Double,
  cx : Double,
  cy : Double,
  dx : Double,
  dy : Double,
) -> Int32 {
  @exact_pred.exact_incircle(ax, ay, bx, by, cx, cy, dx, dy)
}

///|
pub fn exact_left_of_line(
  px : Double,
  py : Double,
  ax : Double,
  ay : Double,
  bx : Double,
  by : Double,
) -> Bool {
  @exact_pred.exact_left_of_line(px, py, ax, ay, bx, by)
}

///|
pub fn ep_exact_collinear(
  ax : Double,
  ay : Double,
  bx : Double,
  by : Double,
  cx : Double,
  cy : Double,
) -> Bool {
  @exact_pred.exact_collinear(ax, ay, bx, by, cx, cy)
}

// ========== robust_arith ==========

///|
pub fn two_sum(a : Double, b : Double) -> (Double, Double) {
  @robust_arith.two_sum(a, b)
}

///|
pub fn two_prod(a : Double, b : Double) -> (Double, Double) {
  @robust_arith.two_prod(a, b)
}

///|
pub fn fast_two_sum(a : Double, b : Double) -> (Double, Double) {
  @robust_arith.fast_two_sum(a, b)
}

///|
pub fn grow_expansion(e : Array[Double], b : Double) -> Array[Double] {
  @robust_arith.grow_expansion(e, b)
}

///|
pub fn expansion_sum(e : Array[Double]) -> Double {
  @robust_arith.expansion_sum(e)
}

// ========== filtered_pred ==========

///|
pub fn static_filter_bound(coords : Array[Double]) -> Double {
  @filtered_pred.static_filter_bound(coords)
}

///|
pub fn fp_filtered_orientation(
  ax : Double,
  ay : Double,
  bx : Double,
  by : Double,
  cx : Double,
  cy : Double,
) -> Int32 {
  @filtered_pred.filtered_orientation(ax, ay, bx, by, cx, cy)
}

///|
pub fn dynamic_filter(a : Double, b : Double, eps : Double) -> Bool {
  @filtered_pred.dynamic_filter(a, b, eps)
}

///|
pub fn filter_result(det : Double, bound : Double) -> Int32 {
  @filtered_pred.filter_result(det, bound)
}

// ========== interval_arith ==========

///|
pub type GeoInterval = @interval_arith.GeoInterval

///|
pub fn geo_interval_new(center : Double, radius : Double) -> GeoInterval {
  @interval_arith.GeoInterval::new(center, radius)
}

///|
pub fn geo_interval_add(
  self_val : GeoInterval,
  other : GeoInterval,
) -> GeoInterval {
  @interval_arith.GeoInterval::add(self_val, other)
}

///|
pub fn geo_interval_sub(
  self_val : GeoInterval,
  other : GeoInterval,
) -> GeoInterval {
  @interval_arith.GeoInterval::sub(self_val, other)
}

///|
pub fn geo_interval_mul(
  self_val : GeoInterval,
  other : GeoInterval,
) -> GeoInterval {
  @interval_arith.GeoInterval::mul(self_val, other)
}

///|
pub fn geo_interval_contains(self_val : GeoInterval, val : Double) -> Bool {
  @interval_arith.GeoInterval::contains(self_val, val)
}

///|
pub fn geo_interval_overlaps(
  self_val : GeoInterval,
  other : GeoInterval,
) -> Bool {
  @interval_arith.GeoInterval::overlaps(self_val, other)
}

// ========== adaptive_pred ==========

///|
pub fn adaptive_orient2d(
  ax : Double,
  ay : Double,
  bx : Double,
  by : Double,
  cx : Double,
  cy : Double,
) -> Int32 {
  @adaptive_pred.adaptive_orient2d(ax, ay, bx, by, cx, cy)
}

///|
pub fn adaptive_incircle(
  ax : Double,
  ay : Double,
  bx : Double,
  by : Double,
  cx : Double,
  cy : Double,
  dx : Double,
  dy : Double,
) -> Int32 {
  @adaptive_pred.adaptive_incircle(ax, ay, bx, by, cx, cy, dx, dy)
}

///|
pub fn precision_level(det : Double, bound : Double) -> Int32 {
  @adaptive_pred.precision_level(det, bound)
}

// ========== expansion_arith ==========

///|
pub fn scale_expansion(e : Array[Double], b : Double) -> Array[Double] {
  @expansion_arith.scale_expansion(e, b)
}

///|
pub fn compress_expansion(e : Array[Double]) -> Array[Double] {
  @expansion_arith.compress_expansion(e)
}

///|
pub fn expansion_length(e : Array[Double]) -> Int32 {
  @expansion_arith.expansion_length(e)
}

///|
pub fn expansion_norm(e : Array[Double]) -> Double {
  @expansion_arith.expansion_norm(e)
}

///|
pub fn expansion_negate(e : Array[Double]) -> Array[Double] {
  @expansion_arith.expansion_negate(e)
}

// ========== robust_inter ==========

///|
pub fn robust_segment_intersect(
  a1x : Double,
  a1y : Double,
  a2x : Double,
  a2y : Double,
  b1x : Double,
  b1y : Double,
  b2x : Double,
  b2y : Double,
) -> (Double, Double, Bool) {
  @robust_inter.robust_segment_intersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y)
}

///|
pub fn robust_line_line(
  a1 : Double,
  b1 : Double,
  c1 : Double,
  a2 : Double,
  b2 : Double,
  c2 : Double,
) -> (Double, Double, Bool) {
  @robust_inter.robust_line_line(a1, b1, c1, a2, b2, c2)
}

///|
pub fn robust_point_on_segment(
  px : Double,
  py : Double,
  ax : Double,
  ay : Double,
  bx : Double,
  by : Double,
) -> Bool {
  @robust_inter.robust_point_on_segment(px, py, ax, ay, bx, by)
}

// ========== robust_orient ==========

///|
pub fn robust_orient2d(
  ax : Double,
  ay : Double,
  bx : Double,
  by : Double,
  cx : Double,
  cy : Double,
) -> Int32 {
  @robust_orient.robust_orient2d(ax, ay, bx, by, cx, cy)
}

///|
pub fn robust_orient3d(
  ax : Double,
  ay : Double,
  az : Double,
  bx : Double,
  by : Double,
  bz : Double,
  cx : Double,
  cy : Double,
  cz : Double,
  dx : Double,
  dy : Double,
  dz : Double,
) -> Int32 {
  @robust_orient.robust_orient3d(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz)
}

///|
pub fn robust_sign(val : Double, tol : Double) -> Int32 {
  @robust_orient.robust_sign(val, tol)
}

///|
pub fn robust_compare(a : Double, b : Double, tol : Double) -> Int32 {
  @robust_orient.robust_compare(a, b, tol)
}

// ========== isoperimetric ==========

///|
pub fn isoperimetric_ratio(perimeter : Double, area : Double) -> Double {
  @isoperimetric.isoperimetric_ratio(perimeter, area)
}

///|
pub fn isoperimetric_deficit(perimeter : Double, area : Double) -> Double {
  @isoperimetric.isoperimetric_deficit(perimeter, area)
}

///|
pub fn circle_area_from_perimeter(p : Double) -> Double {
  @isoperimetric.circle_area_from_perimeter(p)
}

///|
pub fn circle_perimeter_from_area(a : Double) -> Double {
  @isoperimetric.circle_perimeter_from_area(a)
}

///|
pub fn optimal_shape_area(perimeter : Double) -> Double {
  @isoperimetric.optimal_shape_area(perimeter)
}

///|
pub fn is_isoperimetric_optimal(perimeter : Double, area : Double) -> Bool {
  @isoperimetric.is_isoperimetric_optimal(perimeter, area)
}

// ========== geom_prob ==========

///|
pub fn buffon_needle_probability(
  needle_length : Double,
  line_spacing : Double,
) -> Double {
  @geom_prob.buffon_needle_probability(needle_length, line_spacing)
}

///|
pub fn bertrand_probability(mode : Int32) -> Double {
  @geom_prob.bertrand_probability(mode)
}

///|
pub fn random_chord_length(radius : Double) -> Double {
  @geom_prob.random_chord_length(radius)
}

///|
pub fn geometric_probability_hit(
  area_target : Double,
  area_total : Double,
) -> Double {
  @geom_prob.geometric_probability_hit(area_target, area_total)
}

///|
pub fn expected_distance_unit_square() -> Double {
  @geom_prob.expected_distance_unit_square()
}

///|
pub fn coverage_probability(n : Int32, area_ratio : Double) -> Double {
  @geom_prob.coverage_probability(n, area_ratio)
}

// ========== random_geom_graph ==========

///|
pub fn connectivity_threshold(n : Int32, area : Double) -> Double {
  @random_geom_graph.connectivity_threshold(n, area)
}

///|
pub fn percolation_threshold_2d() -> Double {
  @random_geom_graph.percolation_threshold_2d()
}

///|
pub fn coverage_threshold(n : Int32, area : Double) -> Double {
  @random_geom_graph.coverage_threshold(n, area)
}

///|
pub fn expected_degree(n : Int32, radius : Double, area : Double) -> Double {
  @random_geom_graph.expected_degree(n, radius, area)
}

///|
pub fn isolation_probability(
  n : Int32,
  radius : Double,
  area : Double,
) -> Double {
  @random_geom_graph.isolation_probability(n, radius, area)
}

// ========== geom_hash ==========

///|
pub fn hash_point_2d(
  x : Double,
  y : Double,
  grid_size : Double,
) -> (Int32, Int32) {
  @geom_hash.hash_point_2d(x, y, grid_size)
}

///|
pub fn hash_basis_invariant(
  p1x : Double,
  p1y : Double,
  p2x : Double,
  p2y : Double,
  p3x : Double,
  p3y : Double,
) -> (Double, Double) {
  @geom_hash.hash_basis_invariant(p1x, p1y, p2x, p2y, p3x, p3y)
}

///|
pub fn hash_key(x : Double, y : Double, bins : Int32) -> Int32 {
  @geom_hash.hash_key(x, y, bins)
}

///|
pub fn similarity_score(h1 : Array[Int32], h2 : Array[Int32]) -> Double {
  @geom_hash.similarity_score(h1, h2)
}

// ========== fractal_gen ==========

///|
pub fn mandelbrot_escape(cx : Double, cy : Double, max_iter : Int32) -> Int32 {
  @fractal_gen.mandelbrot_escape(cx, cy, max_iter)
}

///|
pub fn julia_escape(
  zx : Double,
  zy : Double,
  cx : Double,
  cy : Double,
  max_iter : Int32,
) -> Int32 {
  @fractal_gen.julia_escape(zx, zy, cx, cy, max_iter)
}

///|
pub fn ifs_contractive_factor(scales : Array[Double]) -> Double {
  @fractal_gen.ifs_contractive_factor(scales)
}

///|
pub fn fractal_dimension_box(counts : Array[(Double, Int32)]) -> Double {
  @fractal_gen.fractal_dimension_box(counts)
}

///|
pub fn koch_curve_length(iteration : Int32, base_length : Double) -> Double {
  @fractal_gen.koch_curve_length(iteration, base_length)
}

///|
/// Arc length of cubic Bezier. / 三次贝塞尔曲线弧长。
pub fn bezier3_length(b : Bezier3) -> Double {
  @bezier.Bezier3::length(b)
}

///|
/// Bounding box of cubic Bezier. / 三次贝塞尔曲线包围盒。
pub fn bezier3_bbox(b : Bezier3) -> (Double, Double, Double, Double) {
  @bezier.Bezier3::bbox(b)
}

///|
/// Subdivide cubic Bezier at t. / 细分三次贝塞尔曲线。
pub fn bezier3_subdivide(b : Bezier3, t : Double) -> (Bezier3, Bezier3) {
  @bezier.Bezier3::subdivide(b, t)
}
// ---------------------------------------------------------------------------
// fitting: geometric fitting / 几何拟合
// ---------------------------------------------------------------------------

///|
/// Line fit result. / 直线拟合结果。
pub type LineFit = @fitting.LineFit

///|
/// Circle fit result. / 圆拟合结果。
pub type CircleFit = @fitting.CircleFit

///|
/// Least-squares line fit. / 最小二乘直线拟合。
pub fn fit_line(points : Array[Point2D]) -> LineFit? {
  @fitting.fit_line(points)
}

///|
/// Orthogonal distance regression line fit. / 正交距离回归直线拟合。
pub fn fit_line_orthogonal(
  points : Array[Point2D],
) -> (Double, Double, Double)? {
  @fitting.fit_line_orthogonal(points)
}

///|
/// Least-squares circle fit. / 最小二乘圆拟合。
pub fn fit_circle(points : Array[Point2D]) -> CircleFit? {
  @fitting.fit_circle(points)
}

///|
/// Centroid of a point set. / 点集质心。
pub fn centroid(points : Array[Point2D]) -> Point2D? {
  @fitting.centroid(points)
}

// ---------------------------------------------------------------------------
// sweep_line: segment intersection / 线段相交检测
// ---------------------------------------------------------------------------

///|
/// Check if any pair of segments intersects. / 检测是否有任何线段对相交。
pub fn has_any_intersection(segments : Array[Segment]) -> Bool {
  @sweep_line.has_any_intersection(segments)
}

///|
/// Find all intersecting pairs. / 找出所有相交线段对。
pub fn find_all_intersections(
  segments : Array[Segment],
) -> Array[(Int32, Int32)] {
  @sweep_line.find_all_intersections(segments)
}

///|
/// Count intersecting pairs. / 计数相交线段对。
pub fn count_intersections(segments : Array[Segment]) -> Int32 {
  @sweep_line.count_intersections(segments)
}

///|
/// Find all intersection points. / 找出所有线段交点。
pub fn find_intersection_points(
  segments : Array[Segment],
) -> Array[(Int32, Int32, Point2D)] {
  @sweep_line.find_intersection_points(segments)
}

///|
/// Check if segments form a simple polygon. / 检测线段是否构成简单多边形。
pub fn is_simple_polygon_chain(segments : Array[Segment]) -> Bool {
  @sweep_line.is_simple_polygon_chain(segments)
}

// ---------------------------------------------------------------------------
// convex_polygon: convex polygon ops / 凸多边形操作
// ---------------------------------------------------------------------------

///|
/// Support function value. / 支持函数值。
pub fn support_function(poly : Polygon, dir : Point2D) -> Double {
  @convex_polygon.support_function(poly, dir)
}

///|
/// Extreme point index in a direction. / 沿方向的极点索引。
pub fn extreme_point(poly : Polygon, dir : Point2D) -> Int32 {
  @convex_polygon.extreme_point(poly, dir)
}

///|
/// O(log n) point-in-convex-polygon test. / O(log n) 凸多边形点包含检测。
pub fn point_in_convex_polygon(poly : Polygon, p : Point2D) -> Bool {
  @convex_polygon.point_in_convex_polygon(poly, p)
}

///|
/// Tangent indices from external point. / 外部点到凸多边形的切线索引。
pub fn tangent_from_point(poly : Polygon, p : Point2D) -> (Int32, Int32) {
  @convex_polygon.tangent_from_point(poly, p)
}

///|
/// Check if two convex polygons intersect (SAT). / 检测两凸多边形是否相交(分离轴定理)。
pub fn convex_polygons_intersect(poly1 : Polygon, poly2 : Polygon) -> Bool {
  @convex_polygon.convex_polygons_intersect(poly1, poly2)
}

///|
/// Distance from point to convex polygon. / 点到凸多边形距离。
pub fn point_to_convex_polygon_distance(poly : Polygon, p : Point2D) -> Double {
  @convex_polygon.point_to_convex_polygon_distance(poly, p)
}
// ---------------------------------------------------------------------------
// vector: vector operations / 向量运算
// ---------------------------------------------------------------------------

///|
/// Normalize a 2D vector to unit length. / 2D向量归一化。
pub fn vec_normalize(v : Point2D) -> Point2D {
  @vector.normalize(v)
}

///|
/// Reflect vector v across normal n. / 向量 v 关于法线 n 反射。
pub fn vec_reflect(v : Point2D, n : Point2D) -> Point2D {
  @vector.reflect(v, n)
}

///|
/// Project vector v onto vector u. / 向量 v 投影到向量 u。
pub fn vec_project(v : Point2D, u : Point2D) -> Point2D {
  @vector.project(v, u)
}

///|
/// Linear interpolation between a and b. / 线性插值。
pub fn vec_lerp(a : Point2D, b : Point2D, t : Double) -> Point2D {
  @vector.lerp(a, b, t)
}

///|
/// Perpendicular vector (rotated 90° CCW). / 垂直向量(逆时针旋转90°)。
pub fn vec_perp(v : Point2D) -> Point2D {
  @vector.perp(v)
}

///|
/// Vector length. / 向量长度。
pub fn vec_length(v : Point2D) -> Double {
  @vector.length(v)
}

///|
/// Angle between two vectors in radians. / 两向量夹角(弧度)。
pub fn vec_angle_between(a : Point2D, b : Point2D) -> Double {
  @vector.angle_between(a, b)
}

///|
/// Reject component of v along u. / 拒绝分量。
pub fn vec_reject(v : Point2D, u : Point2D) -> Point2D {
  @vector.reject(v, u)
}

// ---------------------------------------------------------------------------
// matrix: 2x2 matrix / 2x2 矩阵
// ---------------------------------------------------------------------------

///|
/// 2x2 matrix type. / 2x2 矩阵类型。
pub type Mat2 = @matrix.Mat2

///|
/// Construct a 2x2 matrix. / 构造 2x2 矩阵。
pub fn mat2_new(a11 : Double, a12 : Double, a21 : Double, a22 : Double) -> Mat2 {
  @matrix.Mat2::new(a11, a12, a21, a22)
}

///|
/// Identity matrix. / 单位矩阵。
pub fn mat2_identity() -> Mat2 {
  @matrix.Mat2::identity()
}

///|
/// Circle. / 圆。
pub type Circle = @core.Circle

///|
/// Axis-aligned rectangle. / 轴对齐矩形。
pub type Rectangle = @core.Rectangle

///|
/// Orientation enum. / 方向枚举。
pub type Orientation = @core.Orientation

///|
/// Triangle index triple for triangulation. / 三角剖分索引三元组。
pub type TriangleIdx = @triangulation.TriangleIdx

///|
/// Default epsilon for geometry comparisons. / 几何比较的默认精度。
pub let default_eps : Double = @core.default_eps

// ---------------------------------------------------------------------------
// core: utility functions / 核心工具函数
// ---------------------------------------------------------------------------

///|
/// Determinant. / 行列式。
pub fn mat2_det(m : Mat2) -> Double {
  @matrix.Mat2::det(m)
}

///|
/// Matrix multiplication. / 矩阵乘法。
pub fn mat2_mul(m : Mat2, other : Mat2) -> Mat2 {
  @matrix.Mat2::mul(m, other)
}

///|
/// Apply matrix to a 2D point. / 矩阵作用于点。
pub fn mat2_transform(m : Mat2, p : Point2D) -> Point2D {
  @matrix.Mat2::transform(m, p)
}

///|
/// Inverse matrix. Returns None if singular. / 逆矩阵。奇异返回 None。
pub fn mat2_inverse(m : Mat2) -> Mat2? {
  @matrix.Mat2::inverse(m)
}

///|
/// Rotation matrix. / 旋转矩阵。
pub fn mat2_rotation(angle : Double) -> Mat2 {
  @matrix.Mat2::rotation(angle)
}

///|
/// Scaling matrix. / 缩放矩阵。
pub fn mat2_scaling(sx : Double, sy : Double) -> Mat2 {
  @matrix.Mat2::scaling(sx, sy)
}

///|
/// Trace of the matrix. / 矩阵的迹。
pub fn mat2_trace(m : Mat2) -> Double {
  @matrix.Mat2::trace(m)
}

// ---------------------------------------------------------------------------
// angle: angle utilities / 角度工具
// ---------------------------------------------------------------------------

///|
/// Degrees to radians. / 角度转弧度。
pub fn deg_to_rad(deg : Double) -> Double {
  @angle.deg_to_rad(deg)
}

///|
/// Radians to degrees. / 弧度转角度。
pub fn rad_to_deg(rad : Double) -> Double {
  @angle.rad_to_deg(rad)
}

///|
/// Normalize angle to [0, 2π). / 归一化角度到 [0, 2π)。
pub fn normalize_angle(angle : Double) -> Double {
  @angle.normalize_angle(angle)
}

///|
/// Normalize angle to [-π, π). / 归一化角度到 [-π, π)。
pub fn normalize_angle_signed(angle : Double) -> Double {
  @angle.normalize_angle_signed(angle)
}

///|
/// Angular difference (b - a) normalized to [-π, π]. / 角差归一化到 [-π, π]。
pub fn angle_diff(a : Double, b : Double) -> Double {
  @angle.angle_diff(a, b)
}

///|
/// Bisector angle of two angles. / 两角平分线角度。
pub fn angle_bisector(a : Double, b : Double) -> Double {
  @angle.bisector(a, b)
}

///|
/// Check if angle c is between a and b (CCW). / 检查角度 c 是否在 a 和 b 之间(逆时针)。
pub fn angle_is_between(a : Double, c : Double, b : Double) -> Bool {
  @angle.is_between(a, c, b)
}

// ---------------------------------------------------------------------------
// constants: geometric constants / 几何常数
// ---------------------------------------------------------------------------

///|
/// Pi. / 圆周率。
pub let pi : Double = @constants.pi

///|
/// 2 * Pi. / 2倍圆周率。
pub let two_pi : Double = @constants.two_pi

///|
/// Pi / 2. / 半圆周率。
pub let half_pi : Double = @constants.half_pi

///|
/// Pi / 4. / 四分之一圆周率。
pub let quarter_pi : Double = @constants.quarter_pi

///|
/// Euler's number. / 自然常数。
pub let euler_e : Double = @constants.e

///|
/// Square root of 2. / 根号2。
pub let sqrt2 : Double = @constants.sqrt2

///|
/// Square root of 3. / 根号3。
pub let sqrt3 : Double = @constants.sqrt3

///|
/// Golden ratio. / 黄金比例。
pub let golden_ratio : Double = @constants.golden_ratio

///|
/// Degrees to radians factor. / 角度转弧度因子。
pub let deg2rad : Double = @constants.deg2rad

///|
/// Radians to degrees factor. / 弧度转角度因子。
pub let rad2deg : Double = @constants.rad2deg

///|
/// Epsilon for geometric comparisons. / 几何比较精度。
pub let geom_eps : Double = @constants.eps

// ---------------------------------------------------------------------------
// interval: interval operations / 区间运算
// ---------------------------------------------------------------------------

///|
/// Closed interval type. / 闭区间类型。
pub type Interval = @interval.Interval

///|
/// Construct an interval. / 构造区间。
pub fn interval_new(lo : Double, hi : Double) -> Interval {
  @interval.Interval::new(lo, hi)
}

///|
/// Check if value is in the interval. / 检查值是否在区间内。
pub fn interval_contains(i : Interval, x : Double) -> Bool {
  @interval.Interval::contains(i, x)
}

///|
/// Intersection of two intervals. / 两区间交集。
pub fn interval_intersect(a : Interval, b : Interval) -> Interval? {
  @interval.Interval::intersect(a, b)
}

///|
/// Union of two overlapping intervals. / 两区间并集。
pub fn interval_union(a : Interval, b : Interval) -> Interval {
  @interval.Interval::union(a, b)
}

///|
/// Length of the interval. / 区间长度。
pub fn interval_length(i : Interval) -> Double {
  @interval.Interval::length(i)
}

///|
/// Midpoint of the interval. / 区间中点。
pub fn interval_midpoint(i : Interval) -> Double {
  @interval.Interval::midpoint(i)
}

///|
/// Check if two intervals overlap. / 检查两区间是否重叠。
pub fn interval_overlaps(a : Interval, b : Interval) -> Bool {
  @interval.Interval::overlaps(a, b)
}

///|
/// Check if interval a contains interval b. / 检查区间 a 是否包含区间 b。
pub fn interval_contains_interval(a : Interval, b : Interval) -> Bool {
  @interval.Interval::contains_interval(a, b)
}
// ---------------------------------------------------------------------------
// aabb_tree: AABB tree / AABB 树
// ---------------------------------------------------------------------------

///|
/// AABB tree node type. / AABB 树节点类型。
pub type AABBNode = @aabb_tree.AABBNode

///|
/// Build an AABB tree from rectangles. / 由矩形数组构建 AABB 树。
pub fn build_aabb_tree(rects : Array[Rectangle]) -> Array[AABBNode] {
  @aabb_tree.build_aabb_tree(rects)
}

///|
/// Query overlapping rectangle indices. / 查询重叠矩形索引。
pub fn query_aabb(nodes : Array[AABBNode], query : Rectangle) -> Array[Int32] {
  @aabb_tree.query_aabb(nodes, query)
}

///|
/// Query rectangle indices containing a point. / 查询包含点的矩形索引。
pub fn query_point_aabb(nodes : Array[AABBNode], p : Point2D) -> Array[Int32] {
  @aabb_tree.query_point_aabb(nodes, p)
}

///|
/// Count leaf nodes. / 统计叶子节点数。
pub fn count_leaves(nodes : Array[AABBNode]) -> Int32 {
  @aabb_tree.count_leaves(nodes)
}

// ---------------------------------------------------------------------------
// hash: geometric hashing / 几何哈希
// ---------------------------------------------------------------------------

///|
/// Grid cell index of a 2D point. / 二维点网格单元索引。
pub fn cell_index(p : Point2D, cell_size : Double) -> (Int32, Int32) {
  @hash.cell_index(p, cell_size)
}

///|
/// Grid cell index of a 3D point. / 三维点网格单元索引。
pub fn cell_index_3d(p : Point3D, cell_size : Double) -> (Int32, Int32, Int32) {
  @hash.cell_index_3d(p, cell_size)
}

///|
/// Hash a 2D point to table index. / 二维点哈希到表索引。
pub fn cell_hash(p : Point2D, cell_size : Double, table_size : Int32) -> Int32 {
  @hash.cell_hash(p, cell_size, table_size)
}

///|
/// Hash a 3D point to table index. / 三维点哈希到表索引。
pub fn cell_hash_3d(
  p : Point3D,
  cell_size : Double,
  table_size : Int32,
) -> Int32 {
  @hash.cell_hash_3d(p, cell_size, table_size)
}

///|
/// Combine two hash values. / 合并两个哈希值。
pub fn hash_combine(a : Int32, b : Int32) -> Int32 {
  @hash.hash_combine(a, b)
}

///|
/// Cell indices of segment endpoints. / 线段端点单元索引。
pub fn segment_cells(
  seg : Segment,
  cell_size : Double,
) -> ((Int32, Int32), (Int32, Int32)) {
  @hash.segment_cells(seg, cell_size)
}

///|
/// Hash a segment to table index. / 线段哈希到表索引。
pub fn segment_hash(
  seg : Segment,
  cell_size : Double,
  table_size : Int32,
) -> Int32 {
  @hash.segment_hash(seg, cell_size, table_size)
}

// ---------------------------------------------------------------------------
// compare: comparison predicates / 比较谓词
// ---------------------------------------------------------------------------

///|
/// Robust orientation test. / 鲁棒方向判定。
pub fn robust_orientation(a : Point2D, b : Point2D, c : Point2D) -> Int32 {
  @compare.robust_orientation(a, b, c)
}

///|
/// Robust left turn test. / 鲁棒左转判定。
pub fn robust_left_turn(a : Point2D, b : Point2D, c : Point2D) -> Bool {
  @compare.robust_left_turn(a, b, c)
}

///|
/// Robust right turn test. / 鲁棒右转判定。
pub fn robust_right_turn(a : Point2D, b : Point2D, c : Point2D) -> Bool {
  @compare.robust_right_turn(a, b, c)
}

///|
/// Robust collinearity test. / 鲁棒共线判定。
pub fn robust_collinear(
  a : Point2D,
  b : Point2D,
  c : Point2D,
  eps : Double,
) -> Bool {
  @compare.robust_collinear(a, b, c, eps)
}

///|
/// Lexicographic comparison of points. / 点的字典序比较。
pub fn compare_points(a : Point2D, b : Point2D) -> Int32 {
  @compare.compare_points(a, b)
}

///|
/// Compare segments by start point. / 按起点比较线段。
pub fn compare_segments(s1 : Segment, s2 : Segment) -> Int32 {
  @compare.compare_segments(s1, s2)
}

///|
/// Lexicographic less-than. / 字典序小于。
pub fn less_than(a : Point2D, b : Point2D) -> Bool {
  @compare.less_than(a, b)
}

///|
/// Check if two points are equal within epsilon. / 检查两点是否在精度内相等。
pub fn points_equal(a : Point2D, b : Point2D, eps : Double) -> Bool {
  @compare.points_equal(a, b, eps)
}

// ---------------------------------------------------------------------------
// ray: ray operations / 射线运算
// ---------------------------------------------------------------------------

///|
/// Ray type. / 射线类型。
pub type Ray = @ray.Ray

///|
/// Construct a ray. / 构造射线。
pub fn ray_new(origin : Point2D, dir : Point2D) -> Ray {
  @ray.Ray::new(origin, dir)
}

///|
/// Construct a ray from two points. / 由两点构造射线。
pub fn ray_from_points(origin : Point2D, through : Point2D) -> Ray {
  @ray.Ray::from_points(origin, through)
}

///|
/// Evaluate ray at parameter t. / 计算射线上参数 t 处的点。
pub fn ray_eval(r : Ray, t : Double) -> Point2D {
  @ray.Ray::eval(r, t)
}

///|
/// Ray-segment intersection. / 射线与线段交点。
pub fn ray_segment_intersect(r : Ray, seg : Segment) -> Point2D? {
  @ray.ray_segment_intersect(r, seg)
}

///|
/// Ray-line intersection. / 射线与直线交点。
pub fn ray_line_intersect(r : Ray, line : Line) -> Point2D? {
  @ray.ray_line_intersect(r, line)
}

///|
/// Ray-polygon boundary intersections. / 射线与多边形边界交点。
pub fn ray_polygon_intersect(r : Ray, poly : Polygon) -> Array[Point2D] {
  @ray.ray_polygon_intersect(r, poly)
}

///|
/// Check if ray origin is inside polygon. / 检查射线起点是否在多边形内。
pub fn ray_polygon_contains(r : Ray, poly : Polygon) -> Bool {
  @ray.ray_polygon_contains(r, poly)
}

// ---------------------------------------------------------------------------
// plane: 3D plane operations / 三维平面
// ---------------------------------------------------------------------------

///|
/// Check if two doubles are approximately equal. / 检查两浮点数是否近似相等。
pub fn approx_eq(a : Double, b : Double, eps : Double) -> Bool {
  @core.approx_eq(a, b, eps)
}

///|
/// Cross product of vectors OA and OB. / 向量 OA 和 OB 的叉积。
pub fn turn(o : Point2D, a : Point2D, b : Point2D) -> Double {
  @core.turn(o, a, b)
}

///|
/// Minimum distance from a point to a set of points. / 点到点集的最小距离。
pub fn min_dist_to_set(p : Point2D, set : Array[Point2D]) -> Double {
  @core.min_dist_to_set(p, set)
}

// ---------------------------------------------------------------------------
// hull: convex hull / 凸包
// ---------------------------------------------------------------------------

///|
/// Orientation of three points. / 三点方向判定。
pub fn ccw(a : Point2D, b : Point2D, c : Point2D) -> Orientation {
  @hull.ccw(a, b, c)
}

///|
/// Convex hull via Andrew's monotone chain. / Andrew 单调链凸包。
pub fn convex_hull_andrew(points : Array[Point2D]) -> Array[Point2D] {
  @hull.convex_hull_andrew(points)
}

///|
/// Convex hull via Graham scan. / Graham 扫描凸包。
pub fn convex_hull_graham(points : Array[Point2D]) -> Array[Point2D] {
  @hull.convex_hull_graham(points)
}

// ---------------------------------------------------------------------------
// polygon: polygon operations / 多边形操作
// ---------------------------------------------------------------------------

///|
/// 3D plane type. / 三维平面类型。
pub type Plane = @plane.Plane

///|
/// Plane from normal and point. / 由法向量和点构造平面。
pub fn plane_from_normal_point(normal : Point3D, point : Point3D) -> Plane {
  @plane.Plane::from_normal_point(normal, point)
}

///|
/// Plane from three points. / 由三点构造平面。
pub fn plane_from_three_points(a : Point3D, b : Point3D, c : Point3D) -> Plane {
  @plane.Plane::from_three_points(a, b, c)
}

///|
/// Signed distance from point to plane. / 点到平面有符号距离。
pub fn plane_distance(plane : Plane, p : Point3D) -> Double {
  @plane.Plane::distance(plane, p)
}

///|
/// Check if point is on plane. / 检查点是否在平面上。
pub fn plane_contains(plane : Plane, p : Point3D, eps : Double) -> Bool {
  @plane.Plane::contains(plane, p, eps)
}

///|
/// Plane-line intersection. / 平面与直线交点。
pub fn plane_line_intersect(
  plane : Plane,
  origin : Point3D,
  dir : Point3D,
) -> Point3D? {
  @plane.Plane::line_intersect(plane, origin, dir)
}

///|
/// Normalize plane normal. / 归一化平面法向量。
pub fn plane_normalize(plane : Plane) -> Plane {
  @plane.Plane::normalize(plane)
}

///|
/// Project point onto plane. / 将点投影到平面。
pub fn plane_project(plane : Plane, p : Point3D) -> Point3D {
  @plane.Plane::project(plane, p)
}
// ---------------------------------------------------------------------------
// kdtree: k-d tree / K-d 树
// ---------------------------------------------------------------------------

///|
/// K-d tree node type. / K-d 树节点类型。
pub type KDNode = @kdtree.KDNode

///|
/// Build a k-d tree. / 构建 k-d 树。
pub fn build_kdtree(points : Array[Point2D]) -> Array[KDNode] {
  @kdtree.build_kdtree(points)
}

///|
/// Nearest neighbor search. / 最近邻搜索。
pub fn kdtree_nearest(
  nodes : Array[KDNode],
  query : Point2D,
) -> (Int32, Double)? {
  @kdtree.kdtree_nearest(nodes, query)
}

///|
/// Range query in k-d tree. / K-d 树范围查询。
pub fn kdtree_range_query(
  nodes : Array[KDNode],
  rect : Rectangle,
) -> Array[Int32] {
  @kdtree.kdtree_range_query(nodes, rect)
}

// ---------------------------------------------------------------------------
// quadtree: quadtree / 四叉树
// ---------------------------------------------------------------------------

///|
/// Quadtree node type. / 四叉树节点类型。
pub type QuadNode = @quadtree.QuadNode

///|
/// Build a quadtree. / 构建四叉树。
pub fn build_quadtree(
  points : Array[Point2D],
  bounds : Rectangle,
) -> Array[QuadNode] {
  @quadtree.build_quadtree(points, bounds)
}

///|
/// Range query in quadtree. / 四叉树范围查询。
pub fn quadtree_range_query(
  nodes : Array[QuadNode],
  rect : Rectangle,
) -> Array[Int32] {
  @quadtree.quadtree_range_query(nodes, rect)
}

///|
/// Count points in quadtree. / 统计四叉树点数。
pub fn quadtree_count(nodes : Array[QuadNode]) -> Int32 {
  @quadtree.quadtree_count(nodes)
}

// ---------------------------------------------------------------------------
// grid_index: uniform grid / 均匀网格
// ---------------------------------------------------------------------------

///|
/// Grid index type. / 网格索引类型。
pub type GridIndex = @grid_index.GridIndex

///|
/// Build a grid index. / 构建网格索引。
pub fn build_grid_index(
  points : Array[Point2D],
  cell_size : Double,
) -> GridIndex {
  @grid_index.build_grid_index(points, cell_size)
}

///|
/// Query points within radius. / 查询半径内的点。
pub fn grid_query_radius(
  grid : GridIndex,
  center : Point2D,
  radius : Double,
) -> Array[Int32] {
  @grid_index.grid_query_radius(grid, center, radius)
}

///|
/// Query points within rectangle. / 查询矩形内的点。
pub fn grid_query_rect(grid : GridIndex, rect : Rectangle) -> Array[Int32] {
  @grid_index.grid_query_rect(grid, rect)
}

///|
/// Query points in a grid cell. / 查询网格单元内的点。
pub fn grid_query_cell(grid : GridIndex, p : Point2D) -> Array[Int32] {
  @grid_index.grid_query_cell(grid, p)
}

///|
/// Number of points in grid. / 网格中的点数。
pub fn grid_size(grid : GridIndex) -> Int32 {
  @grid_index.grid_size(grid)
}

// ---------------------------------------------------------------------------
// range_tree: range tree / 范围树
// ---------------------------------------------------------------------------

///|
/// Range tree type. / 范围树类型。
pub type RangeTree = @range_tree.RangeTree

///|
/// Build a range tree. / 构建范围树。
pub fn build_range_tree(points : Array[Point2D]) -> RangeTree {
  @range_tree.build_range_tree(points)
}

///|
/// Orthogonal range query. / 正交范围查询。
pub fn range_query(
  tree : RangeTree,
  x_lo : Double,
  x_hi : Double,
  y_lo : Double,
  y_hi : Double,
) -> Array[Int32] {
  @range_tree.range_query(tree, x_lo, x_hi, y_lo, y_hi)
}

///|
/// Query by x-range. / 按 x 范围查询。
pub fn range_query_x(
  tree : RangeTree,
  x_lo : Double,
  x_hi : Double,
) -> Array[Int32] {
  @range_tree.range_query_x(tree, x_lo, x_hi)
}

///|
/// Query by y-range. / 按 y 范围查询。
pub fn range_query_y(
  tree : RangeTree,
  y_lo : Double,
  y_hi : Double,
) -> Array[Int32] {
  @range_tree.range_query_y(tree, y_lo, y_hi)
}

///|
/// Number of points in tree. / 范围树中的点数。
pub fn range_tree_size(tree : RangeTree) -> Int32 {
  @range_tree.range_tree_size(tree)
}

// ---------------------------------------------------------------------------
// sort_search: sorted array search / 有序数组搜索
// ---------------------------------------------------------------------------

///|
/// Binary search. / 二分查找。
pub fn binary_search(arr : Array[Double], target : Double) -> Int32? {
  @sort_search.binary_search(arr, target)
}

///|
/// Lower bound. / 下界。
pub fn lower_bound(arr : Array[Double], target : Double) -> Int32 {
  @sort_search.lower_bound(arr, target)
}

///|
/// Upper bound. / 上界。
pub fn upper_bound(arr : Array[Double], target : Double) -> Int32 {
  @sort_search.upper_bound(arr, target)
}

///|
/// Remove duplicates from sorted array. / 去重有序数组。
pub fn unique_sorted(arr : Array[Double]) -> Array[Double] {
  @sort_search.unique_sorted(arr)
}

///|
/// Check if array is sorted. / 检查数组是否有序。
pub fn is_sorted(arr : Array[Double]) -> Bool {
  @sort_search.is_sorted(arr)
}

///|
/// K-th smallest element. / 第 k 小元素。
pub fn kth_element(arr : Array[Double], k : Int32) -> Double? {
  @sort_search.kth_element(arr, k)
}

///|
/// Merge two sorted arrays. / 合并两个有序数组。
pub fn merge_sorted(a : Array[Double], b : Array[Double]) -> Array[Double] {
  @sort_search.merge_sorted(a, b)
}

// ---------------------------------------------------------------------------
// bucket_pr: bucket PR k-d tree / 桶 PR k-d 树
// ---------------------------------------------------------------------------

///|
/// Bucket PR node type. / 桶 PR 节点类型。
pub type BucketPRNode = @bucket_pr.BucketPRNode

///|
/// Build a bucket PR k-d tree. / 构建桶 PR k-d 树。
pub fn build_bucket_pr(
  points : Array[Point2D],
  bucket_size : Int32,
) -> Array[BucketPRNode] {
  @bucket_pr.build_bucket_pr(points, bucket_size)
}

///|
/// Nearest neighbor in bucket PR tree. / 桶 PR 树最近邻。
pub fn bucket_pr_nearest(
  nodes : Array[BucketPRNode],
  points : Array[Point2D],
  query : Point2D,
) -> (Int32, Double)? {
  @bucket_pr.bucket_pr_nearest(nodes, points, query)
}

///|
/// Count points in bucket PR tree. / 统计桶 PR 树点数。
pub fn bucket_pr_count(nodes : Array[BucketPRNode]) -> Int32 {
  @bucket_pr.bucket_pr_count(nodes)
}

// ---------------------------------------------------------------------------
// spatial_hash: spatial hash table / 空间哈希表
// ---------------------------------------------------------------------------

///|
/// Spatial hash type. / 空间哈希类型。
pub type SpatialHash = @spatial_hash.SpatialHash

///|
/// Build a spatial hash. / 构建空间哈希。
pub fn build_spatial_hash(
  points : Array[Point2D],
  cell_size : Double,
) -> SpatialHash {
  @spatial_hash.build_spatial_hash(points, cell_size)
}

///|
/// Query points within radius. / 查询半径内的点。
pub fn spatial_hash_query_radius(
  hash : SpatialHash,
  center : Point2D,
  radius : Double,
) -> Array[Int32] {
  @spatial_hash.spatial_hash_query_radius(hash, center, radius)
}

///|
/// Query points within rectangle. / 查询矩形内的点。
pub fn spatial_hash_query_rect(
  hash : SpatialHash,
  rect : Rectangle,
) -> Array[Int32] {
  @spatial_hash.spatial_hash_query_rect(hash, rect)
}

///|
/// Query nearby points. / 查询邻近点。
pub fn spatial_hash_nearby(hash : SpatialHash, p : Point2D) -> Array[Int32] {
  @spatial_hash.spatial_hash_nearby(hash, p)
}

///|
/// Number of points. / 点数。
pub fn spatial_hash_size(hash : SpatialHash) -> Int32 {
  @spatial_hash.spatial_hash_size(hash)
}

// ---------------------------------------------------------------------------
// bvh: bounding volume hierarchy / 层次包围体
// ---------------------------------------------------------------------------

///|
/// BVH node type. / BVH 节点类型。
pub type BVHNode = @bvh.BVHNode

///|
/// Build a BVH. / 构建 BVH。
pub fn build_bvh(rects : Array[Rectangle]) -> Array[BVHNode] {
  @bvh.build_bvh(rects)
}

///|
/// Query overlapping rectangles. / 查询重叠矩形。
pub fn bvh_query(nodes : Array[BVHNode], rect : Rectangle) -> Array[Int32] {
  @bvh.bvh_query(nodes, rect)
}

///|
/// Query rectangles containing a point. / 查询包含点的矩形。
pub fn bvh_query_point(nodes : Array[BVHNode], p : Point2D) -> Array[Int32] {
  @bvh.bvh_query_point(nodes, p)
}

///|
/// Count leaf nodes. / 统计叶子节点数。
pub fn bvh_count_leaves(nodes : Array[BVHNode]) -> Int32 {
  @bvh.bvh_count_leaves(nodes)
}
// ---------------------------------------------------------------------------
// half_plane: half-plane intersection / 半平面交
// ---------------------------------------------------------------------------

///|
/// Half-plane type. / 半平面类型。
pub type HalfPlane = @half_plane.HalfPlane

///|
/// Construct a half-plane. / 构造半平面。
pub fn half_plane_new(a : Double, b : Double, c : Double) -> HalfPlane {
  @half_plane.HalfPlane::new(a, b, c)
}

///|
/// Check if point is in half-plane. / 检查点是否在半平面内。
pub fn half_plane_contains(hp : HalfPlane, p : Point2D) -> Bool {
  @half_plane.HalfPlane::contains(hp, p)
}

///|
/// Intersection of half-planes. / 半平面交。
pub fn half_plane_intersect(planes : Array[HalfPlane]) -> Array[Point2D] {
  @half_plane.half_plane_intersect(planes)
}

// ---------------------------------------------------------------------------
// convex_clip: convex polygon clipping / 凸多边形裁剪
// ---------------------------------------------------------------------------

///|
/// Clip convex polygon by a line. / 用直线裁剪凸多边形。
pub fn clip_convex_by_line(poly : Polygon, line : Line) -> Array[Point2D] {
  @convex_clip.clip_convex_by_line(poly, line)
}

///|
/// Clip convex polygon by half-plane. / 用半平面裁剪凸多边形。
pub fn clip_convex_by_half_plane(
  poly : Polygon,
  a : Double,
  b : Double,
  c : Double,
) -> Array[Point2D] {
  @convex_clip.clip_convex_by_half_plane(poly, a, b, c)
}

///|
/// Area of convex polygon from vertex array. / 凸多边形面积。
pub fn convex_area(vertices : Array[Point2D]) -> Double {
  @convex_clip.convex_area(vertices)
}

// ---------------------------------------------------------------------------
// convex_sum: point set operations / 点集运算
// ---------------------------------------------------------------------------

///|
/// All pairwise sums of two point sets. / 两个点集的成对和。
pub fn point_set_sum(
  p1 : Array[Point2D],
  p2 : Array[Point2D],
) -> Array[Point2D] {
  @convex_sum.point_set_sum(p1, p2)
}

///|
/// All pairwise differences. / 两个点集的成对差。
pub fn point_set_difference(
  p1 : Array[Point2D],
  p2 : Array[Point2D],
) -> Array[Point2D] {
  @convex_sum.point_set_difference(p1, p2)
}

///|
/// Centroid of a point set. / 点集质心。
pub fn point_set_centroid(points : Array[Point2D]) -> Point2D? {
  @convex_sum.point_set_centroid(points)
}

// ---------------------------------------------------------------------------
// polar_dual: polar duality / 极对偶
// ---------------------------------------------------------------------------

///|
/// Polar dual of a point. / 点的极对偶。
pub fn polar_dual_point(p : Point2D) -> Point2D {
  @polar_dual.polar_dual_point(p)
}

///|
/// Polar dual of a convex polygon. / 凸多边形的极对偶。
pub fn polar_dual(poly : Polygon) -> Array[Point2D] {
  @polar_dual.polar_dual(poly)
}

///|
/// Check if origin is inside polygon. / 检查原点是否在多边形内。
pub fn origin_inside(poly : Polygon) -> Bool {
  @polar_dual.origin_inside(poly)
}

// ---------------------------------------------------------------------------
// linear_prog: 2D linear programming / 二维线性规划
// ---------------------------------------------------------------------------

///|
/// LP result type. / 线性规划结果类型。
pub type LPResult = @linear_prog.LPResult

///|
/// Solve 2D LP. / 求解二维线性规划。
pub fn linear_program_2d(
  constraints : Array[(Double, Double, Double)],
  cx : Double,
  cy : Double,
) -> LPResult? {
  @linear_prog.linear_program_2d(constraints, cx, cy)
}

///|
/// Signed area of a polygon. / 多边形有符号面积。
pub fn polygon_signed_area(poly : Polygon) -> Double {
  @polygon.polygon_signed_area(poly)
}

///|
/// Absolute area of a polygon. / 多边形绝对面积。
pub fn polygon_area(poly : Polygon) -> Double {
  @polygon.polygon_area(poly)
}

///|
/// Perimeter of a polygon. / 多边形周长。
pub fn polygon_perimeter(poly : Polygon) -> Double {
  @polygon.polygon_perimeter(poly)
}

///|
/// Centroid of a polygon. / 多边形质心。
pub fn polygon_centroid(poly : Polygon) -> Point2D {
  @polygon.polygon_centroid(poly)
}

///|
/// Orientation of a polygon (CW/CCW/Collinear). / 多边形方向。
pub fn polygon_orientation(poly : Polygon) -> Orientation {
  @polygon.polygon_orientation(poly)
}

///|
/// Whether a polygon is convex. / 多边形是否为凸。
pub fn is_convex(poly : Polygon) -> Bool {
  @polygon.is_convex(poly)
}

///|
/// Point-in-polygon test (ray casting). / 点是否在多边形内。
pub fn point_in_polygon(p : Point2D, poly : Polygon) -> Bool {
  @polygon.point_in_polygon(p, poly)
}

///|
/// Check if constraints are feasible. / 检查约束是否可行。
pub fn is_feasible(constraints : Array[(Double, Double, Double)]) -> Bool {
  @linear_prog.is_feasible(constraints)
}

// ---------------------------------------------------------------------------
// convex_hull3d: 3D convex hull / 三维凸包
// ---------------------------------------------------------------------------

///|
/// 3D hull face type. / 三维凸包面类型。
pub type HullFace = @convex_hull3d.HullFace

///|
/// Compute 3D convex hull. / 三维凸包。
pub fn convex_hull_3d(points : Array[Point3D]) -> Array[HullFace] {
  @convex_hull3d.convex_hull_3d(points)
}

///|
/// Volume of 3D convex hull. / 三维凸包体积。
pub fn hull_volume(points : Array[Point3D], faces : Array[HullFace]) -> Double {
  @convex_hull3d.hull_volume(points, faces)
}

// ---------------------------------------------------------------------------
// support: support functions / 支持函数
// ---------------------------------------------------------------------------

///|
/// Support point index in a direction. / 支持点索引。
pub fn support_point_set(points : Array[Point2D], dir : Point2D) -> Int32? {
  @support.support_point_set(points, dir)
}

///|
/// Support point of a circle. / 圆的支持点。
pub fn support_circle(
  center : Point2D,
  radius : Double,
  dir : Point2D,
) -> Point2D {
  @support.support_circle(center, radius, dir)
}

///|
/// Width in a direction. / 方向宽度。
pub fn width_in_direction(points : Array[Point2D], dir : Point2D) -> Double {
  @support.width_in_direction(points, dir)
}

// ---------------------------------------------------------------------------
// separating: separating axis / 分离轴
// ---------------------------------------------------------------------------

///|
/// Find separating axis. / 寻找分离轴。
pub fn find_separating_axis(poly1 : Polygon, poly2 : Polygon) -> Line? {
  @separating.find_separating_axis(poly1, poly2)
}

///|
/// Separating distance. / 分离距离。
pub fn separating_distance(poly1 : Polygon, poly2 : Polygon) -> Double {
  @separating.separating_distance(poly1, poly2)
}

///|
/// Check if two convex polygons are separated. / 检查两凸多边形是否分离。
pub fn are_separated(poly1 : Polygon, poly2 : Polygon) -> Bool {
  @separating.are_separated(poly1, poly2)
}
// ---------------------------------------------------------------------------
// polygon_offset: polygon offset / 多边形偏移
// ---------------------------------------------------------------------------

///|
/// Offset a polygon outward by a distance. / 将多边形向外偏移指定距离。
pub fn polygon_offset_outward(
  poly : Array[Point2D],
  dist : Double,
) -> Array[Point2D] {
  @polygon_offset.polygon_offset_outward(poly, dist)
}

///|
/// Offset a polygon inward by a distance. / 将多边形向内偏移指定距离。
pub fn polygon_offset_inward(
  poly : Array[Point2D],
  dist : Double,
) -> Array[Point2D] {
  @polygon_offset.polygon_offset_inward(poly, dist)
}

///|
/// Compute offset polygon area (Steiner formula). / 使用 Steiner 公式计算偏移面积。
pub fn polygon_offset_area(poly : Array[Point2D], dist : Double) -> Double {
  @polygon_offset.polygon_offset_area(poly, dist)
}

///|
/// Check if offset polygon is valid. / 检查偏移多边形是否有效。
pub fn polygon_offset_valid(poly : Array[Point2D], dist : Double) -> Bool {
  @polygon_offset.polygon_offset_valid(poly, dist)
}

// ---------------------------------------------------------------------------
// polygon_holes: polygon with holes / 带孔多边形
// ---------------------------------------------------------------------------

///|
/// Polygon with holes type. / 带孔多边形类型。
pub type PolygonWithHoles = @polygon_holes.PolygonWithHoles

///|
/// Create a polygon with holes. / 创建带孔多边形。
pub fn polygon_with_holes_new(
  outer : Array[Point2D],
  holes : Array[Array[Point2D]],
) -> PolygonWithHoles {
  @polygon_holes.polygon_with_holes_new(outer, holes)
}

///|
/// Area of polygon with holes. / 带孔多边形面积。
pub fn polygon_with_holes_area(p : PolygonWithHoles) -> Double {
  @polygon_holes.polygon_with_holes_area(p)
}

///|
/// Check if point is in polygon with holes. / 检查点是否在带孔多边形内。
pub fn polygon_with_holes_contains(p : PolygonWithHoles, pt : Point2D) -> Bool {
  @polygon_holes.polygon_with_holes_contains(p, pt)
}

///|
/// Perimeter of polygon with holes. / 带孔多边形周长。
pub fn polygon_with_holes_perimeter(p : PolygonWithHoles) -> Double {
  @polygon_holes.polygon_with_holes_perimeter(p)
}

///|
/// Count holes. / 计算孔数。
pub fn polygon_with_holes_count(p : PolygonWithHoles) -> Int32 {
  @polygon_holes.polygon_with_holes_count(p)
}

// ---------------------------------------------------------------------------
// visibility: visibility polygon / 可见性多边形
// ---------------------------------------------------------------------------

///|
/// Check if two points are mutually visible. / 检查两点是否互相可见。
pub fn is_visible(poly : Array[Point2D], from : Point2D, to : Point2D) -> Bool {
  @visibility.is_visible(poly, from, to)
}

///|
/// Visibility polygon from a point in convex polygon. / 凸多边形内一点的可见多边形。
pub fn visibility_polygon_convex(
  poly : Array[Point2D],
  pt : Point2D,
) -> Array[Point2D] {
  @visibility.visibility_polygon_convex(poly, pt)
}

///|
/// Visibility polygon (general). / 可见多边形(通用)。
pub fn visibility_polygon(
  poly : Array[Point2D],
  pt : Point2D,
) -> Array[Point2D] {
  @visibility.visibility_polygon(poly, pt)
}

///|
/// Count visible vertices. / 计算可见顶点数。
pub fn visible_vertex_count(poly : Array[Point2D], pt : Point2D) -> Int32 {
  @visibility.visible_vertex_count(poly, pt)
}

// ---------------------------------------------------------------------------
// art_gallery: art gallery problem / 美术馆问题
// ---------------------------------------------------------------------------

///|
/// Upper bound on guards (floor(n/3)). / 守卫数上界。
pub fn art_gallery_guard_count(n : Int32) -> Int32 {
  @art_gallery.art_gallery_guard_count(n)
}

///|
/// Place guards at vertices. / 在顶点放置守卫。
pub fn art_gallery_place_guards(poly : Array[Point2D]) -> Array[Point2D] {
  @art_gallery.art_gallery_place_guards(poly)
}

///|
/// Check if guards cover all vertices. / 检查守卫是否覆盖所有顶点。
pub fn art_gallery_covers_vertices(
  poly : Array[Point2D],
  guards : Array[Point2D],
) -> Bool {
  @art_gallery.art_gallery_covers_vertices(poly, guards)
}

///|
/// Estimate guard count. / 估计守卫数。
pub fn art_gallery_estimate(poly : Array[Point2D]) -> Int32 {
  @art_gallery.art_gallery_estimate(poly)
}

// ---------------------------------------------------------------------------
// polygon_kernel: polygon kernel / 多边形核
// ---------------------------------------------------------------------------

///|
/// Compute polygon kernel. / 计算多边形核。
pub fn polygon_kernel(poly : Array[Point2D]) -> Array[Point2D] {
  @polygon_kernel.polygon_kernel(poly)
}

///|
/// Check if polygon is star-shaped. / 检查多边形是否为星形。
pub fn is_star_shaped(poly : Array[Point2D]) -> Bool {
  @polygon_kernel.is_star_shaped(poly)
}

///|
/// Kernel area. / 核面积。
pub fn polygon_kernel_area(poly : Array[Point2D]) -> Double {
  @polygon_kernel.polygon_kernel_area(poly)
}

///|
/// Find a point in the kernel. / 在核中找一点。
pub fn kernel_point(poly : Array[Point2D]) -> Point2D? {
  @polygon_kernel.kernel_point(poly)
}

// ---------------------------------------------------------------------------
// convex_decomp: convex decomposition / 凸分解
// ---------------------------------------------------------------------------

///|
/// Check if polygon is convex. / 检查多边形是否为凸。
pub fn is_convex_polygon(poly : Array[Point2D]) -> Bool {
  @convex_decomp.is_convex_polygon(poly)
}

///|
/// Decompose polygon into convex pieces. / 分解为凸块。
pub fn convex_decomposition(poly : Array[Point2D]) -> Array[Array[Point2D]] {
  @convex_decomp.convex_decomposition(poly)
}

///|
/// Count convex pieces. / 凸块数量。
pub fn convex_decomp_count(poly : Array[Point2D]) -> Int32 {
  @convex_decomp.convex_decomp_count(poly)
}

///|
/// Lower bound on convex pieces. / 凸块下界。
pub fn convex_decomp_lower_bound(poly : Array[Point2D]) -> Int32 {
  @convex_decomp.convex_decomp_lower_bound(poly)
}

///|
/// Total area of convex pieces. / 凸块总面积。
pub fn convex_decomp_area(poly : Array[Point2D]) -> Double {
  @convex_decomp.convex_decomp_area(poly)
}

// ---------------------------------------------------------------------------
// polygon_symmetry: symmetry detection / 对称性检测
// ---------------------------------------------------------------------------

///|
/// Check reflection symmetry. / 检查反射对称。
pub fn has_reflection_symmetry(
  poly : Array[Point2D],
  axis_angle : Double,
) -> Bool {
  @polygon_symmetry.has_reflection_symmetry(poly, axis_angle)
}

///|
/// Check rotational symmetry. / 检查旋转对称。
pub fn has_rotation_symmetry(poly : Array[Point2D], order : Int32) -> Bool {
  @polygon_symmetry.has_rotation_symmetry(poly, order)
}

///|
/// Find rotational symmetry order. / 求旋转对称阶。
pub fn polygon_symmetry_order(poly : Array[Point2D]) -> Int32 {
  @polygon_symmetry.polygon_symmetry_order(poly)
}

///|
/// Check any symmetry. / 检查任何对称性。
pub fn has_any_symmetry(poly : Array[Point2D]) -> Bool {
  @polygon_symmetry.has_any_symmetry(poly)
}

// ---------------------------------------------------------------------------
// polygon_cover: polygon covering / 多边形覆盖
// ---------------------------------------------------------------------------

///|
/// Cover by rectangles. / 矩形覆盖。
pub fn cover_by_rectangles(poly : Array[Point2D]) -> Array[Rectangle] {
  @polygon_cover.cover_by_rectangles(poly)
}

///|
/// Cover by triangles. / 三角形覆盖。
pub fn cover_by_triangles(poly : Array[Point2D]) -> Array[Triangle] {
  @polygon_cover.cover_by_triangles(poly)
}

///|
/// Rectangle cover area. / 矩形覆盖面积。
pub fn cover_area_rectangles(poly : Array[Point2D]) -> Double {
  @polygon_cover.cover_area_rectangles(poly)
}

///|
/// Triangle cover area. / 三角形覆盖面积。
pub fn cover_area_triangles(poly : Array[Point2D]) -> Double {
  @polygon_cover.cover_area_triangles(poly)
}

// ---------------------------------------------------------------------------
// ear_clip: ear clipping triangulation / 耳裁剪三角剖分
// ---------------------------------------------------------------------------

///|
/// Check if vertex is an ear. / 检查顶点是否为耳。
pub fn is_ear(poly : Array[Point2D], indices : Array[Int32], i : Int32) -> Bool {
  @ear_clip.is_ear(poly, indices, i)
}

///|
/// Find an ear vertex. / 找耳顶点。
pub fn find_ear(poly : Array[Point2D], indices : Array[Int32]) -> Int32? {
  @ear_clip.find_ear(poly, indices)
}

///|
/// Triangulate via ear clipping. / 耳裁剪三角剖分。
pub fn ear_clip_triangulate(
  poly : Array[Point2D],
) -> Array[(Int32, Int32, Int32)] {
  @ear_clip.ear_clip_triangulate(poly)
}

///|
/// Count ear clip triangles. / 耳裁剪三角形数。
pub fn ear_clip_count(poly : Array[Point2D]) -> Int32 {
  @ear_clip.ear_clip_count(poly)
}

///|
/// Ear clip total area. / 耳裁剪总面积。
pub fn ear_clip_area(poly : Array[Point2D]) -> Double {
  @ear_clip.ear_clip_area(poly)
}

// ---------------------------------------------------------------------------
// monotone: monotone polygon triangulation / 单调多边形三角剖分
// ---------------------------------------------------------------------------

///|
/// Check if polygon is y-monotone. / 检查多边形是否 y-单调。
pub fn is_y_monotone(poly : Array[Point2D]) -> Bool {
  @monotone.is_y_monotone(poly)
}

///|
/// Check if polygon is x-monotone. / 检查多边形是否 x-单调。
pub fn is_x_monotone(poly : Array[Point2D]) -> Bool {
  @monotone.is_x_monotone(poly)
}

///|
/// Triangulate y-monotone polygon. / 三角剖分 y-单调多边形。
pub fn triangulate_monotone(
  poly : Array[Point2D],
) -> Array[(Int32, Int32, Int32)] {
  @monotone.triangulate_monotone(poly)
}

///|
/// Count monotone triangles. / 单调三角剖分三角形数。
pub fn monotone_triangulate_count(poly : Array[Point2D]) -> Int32 {
  @monotone.monotone_triangulate_count(poly)
}
// ---------------------------------------------------------------------------
// catmull_rom: Catmull-Rom spline / Catmull-Rom 样条
// ---------------------------------------------------------------------------

///|
/// Evaluate Catmull-Rom spline at t. / 计算 Catmull-Rom 样条在 t 处的值。
pub fn catmull_rom_eval(
  p0 : Point2D,
  p1 : Point2D,
  p2 : Point2D,
  p3 : Point2D,
  t : Double,
) -> Point2D {
  @catmull_rom.catmull_rom_eval(p0, p1, p2, p3, t)
}

///|
/// Simplify polygon (Douglas-Peucker). / 多边形简化(Douglas-Peucker)。
pub fn simplify_polygon(poly : Polygon, epsilon : Double) -> Array[Point2D] {
  @polygon.simplify_polygon(poly, epsilon)
}

// ---------------------------------------------------------------------------
// intersect: intersection / 相交
// ---------------------------------------------------------------------------

///|
/// Whether two segments intersect. / 两线段是否相交。
pub fn segments_intersect(s1 : Segment, s2 : Segment) -> Bool {
  @intersect.segments_intersect(s1, s2)
}

///|
/// Intersection point of two segments (None if no intersection). / 两线段交点。
pub fn segment_intersection(s1 : Segment, s2 : Segment) -> Point2D? {
  @intersect.segment_intersection(s1, s2)
}

///|
/// Intersection of a line and a segment. / 直线与线段交点。
pub fn line_segment_intersection(line : Line, seg : Segment) -> Point2D? {
  @intersect.line_segment_intersection(line, seg)
}

// ---------------------------------------------------------------------------
// nearest: closest pair / 最近点对
// ---------------------------------------------------------------------------

///|
/// Closest pair of points (divide & conquer, O(n log n)). / 最近点对。
pub fn closest_pair(points : Array[Point2D]) -> (Point2D, Point2D, Double)? {
  @nearest.closest_pair(points)
}

// ---------------------------------------------------------------------------
// boolean: polygon boolean operations / 多边形布尔运算
// ---------------------------------------------------------------------------

///|
/// Clip polygon against a rectangle (Sutherland-Hodgman). / 矩形裁剪多边形。
pub fn clip_polygon(poly : Polygon, clip_rect : Rectangle) -> Array[Point2D] {
  @boolean.clip_polygon(poly, clip_rect)
}

///|
/// Generate Catmull-Rom spline points. / 生成 Catmull-Rom 样条点。
pub fn catmull_rom_points(
  cps : Array[Point2D],
  num_segments : Int32,
) -> Array[Point2D] {
  @catmull_rom.catmull_rom_points(cps, num_segments)
}

///|
/// Catmull-Rom derivative at t. / Catmull-Rom 样条导数。
pub fn catmull_rom_derivative(
  p0 : Point2D,
  p1 : Point2D,
  p2 : Point2D,
  p3 : Point2D,
  t : Double,
) -> Point2D {
  @catmull_rom.catmull_rom_derivative(p0, p1, p2, p3, t)
}

// ---------------------------------------------------------------------------
// hermite: Hermite spline / Hermite 样条
// ---------------------------------------------------------------------------

///|
/// Evaluate Hermite spline at t. / 计算 Hermite 样条在 t 处的值。
pub fn hermite_eval(
  p0 : Point2D,
  p1 : Point2D,
  m0 : Point2D,
  m1 : Point2D,
  t : Double,
) -> Point2D {
  @hermite.hermite_eval(p0, p1, m0, m1, t)
}

///|
/// Generate Hermite spline points. / 生成 Hermite 样条点。
pub fn hermite_points(
  pts : Array[Point2D],
  tans : Array[Point2D],
  num_segments : Int32,
) -> Array[Point2D] {
  @hermite.hermite_points(pts, tans, num_segments)
}

///|
/// Hermite spline derivative. / Hermite 样条导数。
pub fn hermite_derivative(
  p0 : Point2D,
  p1 : Point2D,
  m0 : Point2D,
  m1 : Point2D,
  t : Double,
) -> Point2D {
  @hermite.hermite_derivative(p0, p1, m0, m1, t)
}

///|
/// Cardinal spline tangents. / Cardinal 样条切线。
pub fn cardinal_tangents(
  pts : Array[Point2D],
  tension : Double,
) -> Array[Point2D] {
  @hermite.cardinal_tangents(pts, tension)
}

// ---------------------------------------------------------------------------
// bspline: B-spline / B样条
// ---------------------------------------------------------------------------

///|
/// B-spline basis function. / B样条基函数。
pub fn bspline_basis(
  degree : Int32,
  knots : Array[Double],
  i : Int32,
  t : Double,
) -> Double {
  @bspline.bspline_basis(degree, knots, i, t)
}

///|
/// Evaluate B-spline at t. / 计算 B样条在 t 处的值。
pub fn bspline_eval(
  cps : Array[Point2D],
  degree : Int32,
  knots : Array[Double],
  t : Double,
) -> Point2D {
  @bspline.bspline_eval(cps, degree, knots, t)
}

///|
/// Uniform knot vector. / 均匀节点向量。
pub fn uniform_knots(n : Int32, degree : Int32) -> Array[Double] {
  @bspline.uniform_knots(n, degree)
}

///|
/// Generate B-spline points. / 生成 B样条点。
pub fn bspline_points(
  cps : Array[Point2D],
  degree : Int32,
  num_samples : Int32,
) -> Array[Point2D] {
  @bspline.bspline_points(cps, degree, num_samples)
}

// ---------------------------------------------------------------------------
// lagrange: Lagrange interpolation / Lagrange 插值
// ---------------------------------------------------------------------------

///|
/// Evaluate Lagrange interpolation at x. / 在 x 处计算 Lagrange 插值。
pub fn lagrange_eval(
  xs : Array[Double],
  ys : Array[Double],
  x : Double,
) -> Double {
  @lagrange.lagrange_eval(xs, ys, x)
}

///|
/// Lagrange basis polynomial. / Lagrange 基多项式。
pub fn lagrange_basis(xs : Array[Double], i : Int32, x : Double) -> Double {
  @lagrange.lagrange_basis(xs, i, x)
}

///|
/// Lagrange interpolate 2D points. / Lagrange 插值2D点。
pub fn lagrange_interpolate(pts : Array[Point2D], x : Double) -> Double {
  @lagrange.lagrange_interpolate(pts, x)
}

///|
/// Check distinct nodes. / 检查节点互异。
pub fn lagrange_nodes_distinct(xs : Array[Double]) -> Bool {
  @lagrange.lagrange_nodes_distinct(xs)
}

// ---------------------------------------------------------------------------
// spline: spline utilities / 样条工具
// ---------------------------------------------------------------------------

///|
/// Spline total length. / 样条总长度。
pub fn spline_length(pts : Array[Point2D]) -> Double {
  @spline.spline_length(pts)
}

///|
/// Spline curvature at point i. / 样条在点 i 处曲率。
pub fn spline_curvature(pts : Array[Point2D], i : Int32) -> Double {
  @spline.spline_curvature(pts, i)
}

///|
/// Spline curvature profile. / 样条曲率分布。
pub fn spline_curvature_profile(pts : Array[Point2D]) -> Array[Double] {
  @spline.spline_curvature_profile(pts)
}

///|
/// Spline total curvature. / 样条总曲率。
pub fn spline_total_curvature(pts : Array[Point2D]) -> Double {
  @spline.spline_total_curvature(pts)
}

///|
/// Max curvature point. / 最大曲率点。
pub fn spline_max_curvature_point(pts : Array[Point2D]) -> Int32? {
  @spline.spline_max_curvature_point(pts)
}

// ---------------------------------------------------------------------------
// curve_arc: arc length / 弧长
// ---------------------------------------------------------------------------

///|
/// Total arc length. / 总弧长。
pub fn arc_length(pts : Array[Point2D]) -> Double {
  @curve_arc.arc_length(pts)
}

///|
/// Arc length at parameter t. / 参数 t 处弧长。
pub fn arc_length_at(pts : Array[Point2D], t : Double) -> Double {
  @curve_arc.arc_length_at(pts, t)
}

///|
/// Reparameterize by arc length. / 按弧长重参数化。
pub fn arc_length_parametrize(
  pts : Array[Point2D],
  num_samples : Int32,
) -> Array[Point2D] {
  @curve_arc.arc_length_parametrize(pts, num_samples)
}

///|
/// Arc length to parameter. / 弧长转参数。
pub fn arc_length_to_param(pts : Array[Point2D], s : Double) -> Double {
  @curve_arc.arc_length_to_param(pts, s)
}

// ---------------------------------------------------------------------------
// curve_intersect: curve intersection / 曲线相交
// ---------------------------------------------------------------------------

///|
/// Check if two segments cross. / 检查两线段相交。
pub fn segments_cross(
  p1 : Point2D,
  p2 : Point2D,
  p3 : Point2D,
  p4 : Point2D,
) -> Bool {
  @curve_intersect.segments_cross(p1, p2, p3, p4)
}

///|
/// Check polyline self-intersection. / 检查折线自相交。
pub fn curve_self_intersect(pts : Array[Point2D]) -> Bool {
  @curve_intersect.curve_self_intersect(pts)
}

///|
/// Count self-intersections. / 自相交计数。
pub fn curve_self_intersect_count(pts : Array[Point2D]) -> Int32 {
  @curve_intersect.curve_self_intersect_count(pts)
}

///|
/// Check if two curves intersect. / 检查两曲线相交。
pub fn curves_intersect(c1 : Array[Point2D], c2 : Array[Point2D]) -> Bool {
  @curve_intersect.curves_intersect(c1, c2)
}

// ---------------------------------------------------------------------------
// polyline: polyline operations / 折线操作
// ---------------------------------------------------------------------------

///|
/// Polyline length. / 折线长度。
pub fn polyline_length(pts : Array[Point2D]) -> Double {
  @polyline.polyline_length(pts)
}

///|
/// Simplify polyline (Douglas-Peucker). / 简化折线。
pub fn polyline_simplify(pts : Array[Point2D], eps : Double) -> Array[Point2D] {
  @polyline.polyline_simplify(pts, eps)
}

///|
/// Subdivide polyline segment. / 细分折线段。
pub fn polyline_subdivide(
  pts : Array[Point2D],
  idx : Int32,
  t : Double,
) -> Array[Point2D] {
  @polyline.polyline_subdivide(pts, idx, t)
}

///|
/// Polyline segment count. / 折线段数。
pub fn polyline_segment_count(pts : Array[Point2D]) -> Int32 {
  @polyline.polyline_segment_count(pts)
}

// ---------------------------------------------------------------------------
// arc_length: arc length utilities / 弧长工具
// ---------------------------------------------------------------------------

///|
/// Single segment arc length. / 单线段弧长。
pub fn arc_length_segment(p1 : Point2D, p2 : Point2D) -> Double {
  @arc_length.arc_length_segment(p1, p2)
}

///|
/// Total arc length. / 总弧长。
pub fn arc_length_total(pts : Array[Point2D]) -> Double {
  @arc_length.arc_length_total(pts)
}

///|
/// Cumulative arc lengths. / 累积弧长。
pub fn arc_length_cumulative(pts : Array[Point2D]) -> Array[Double] {
  @arc_length.arc_length_cumulative(pts)
}

///|
/// Average segment length. / 平均线段长度。
pub fn arc_length_average(pts : Array[Point2D]) -> Double {
  @arc_length.arc_length_average(pts)
}

///|
/// Max segment length. / 最大线段长度。
pub fn arc_length_max_segment(pts : Array[Point2D]) -> Double {
  @arc_length.arc_length_max_segment(pts)
}

// ---------------------------------------------------------------------------
// curvature: curvature computation / 曲率计算
// ---------------------------------------------------------------------------

///|
/// Curvature at middle point. / 中间点曲率。
pub fn curvature_at(p1 : Point2D, p2 : Point2D, p3 : Point2D) -> Double {
  @curvature.curvature_at(p1, p2, p3)
}

///|
/// Signed curvature. / 有符号曲率。
pub fn curvature_signed(p1 : Point2D, p2 : Point2D, p3 : Point2D) -> Double {
  @curvature.curvature_signed(p1, p2, p3)
}

///|
/// Curvature profile. / 曲率分布。
pub fn curvature_profile(pts : Array[Point2D]) -> Array[Double] {
  @curvature.curvature_profile(pts)
}

///|
/// Radius of curvature. / 曲率半径。
pub fn curvature_radius(p1 : Point2D, p2 : Point2D, p3 : Point2D) -> Double {
  @curvature.curvature_radius(p1, p2, p3)
}

///|
/// Total curvature. / 总曲率。
pub fn curvature_total(pts : Array[Point2D]) -> Double {
  @curvature.curvature_total(pts)
}
// ---------------------------------------------------------------------------
// hausdorff: Hausdorff distance / Hausdorff 距离
// ---------------------------------------------------------------------------

///|
pub fn hausdorff_directed(a : Array[Point2D], b : Array[Point2D]) -> Double {
  @hausdorff.hausdorff_directed(a, b)
}

///|
pub fn hausdorff_distance(a : Array[Point2D], b : Array[Point2D]) -> Double {
  @hausdorff.hausdorff_distance(a, b)
}

///|
pub fn hausdorff_within(
  a : Array[Point2D],
  b : Array[Point2D],
  eps : Double,
) -> Bool {
  @hausdorff.hausdorff_within(a, b, eps)
}

///|
pub fn partial_hausdorff(
  a : Array[Point2D],
  b : Array[Point2D],
  k : Int32,
) -> Double {
  @hausdorff.partial_hausdorff(a, b, k)
}

// ---------------------------------------------------------------------------
// frechet: Fréchet distance / Fréchet 距离
// ---------------------------------------------------------------------------

///|
pub fn frechet_distance(c1 : Array[Point2D], c2 : Array[Point2D]) -> Double {
  @frechet.frechet_distance(c1, c2)
} ///|

///|
pub fn frechet_within(
  c1 : Array[Point2D],
  c2 : Array[Point2D],
  eps : Double,
) -> Bool {
  @frechet.frechet_within(c1, c2, eps)
}

///|
pub fn frechet_point_distance(p1 : Point2D, p2 : Point2D) -> Double {
  @frechet.frechet_point_distance(p1, p2)
}

// ---------------------------------------------------------------------------
// chamfer: Chamfer distance / Chamfer 距离
// ---------------------------------------------------------------------------

///|
pub fn chamfer_directed(a : Array[Point2D], b : Array[Point2D]) -> Double {
  @chamfer.chamfer_directed(a, b)
}

///|
pub fn chamfer_distance(a : Array[Point2D], b : Array[Point2D]) -> Double {
  @chamfer.chamfer_distance(a, b)
}

///|
pub fn chamfer_squared_directed(
  a : Array[Point2D],
  b : Array[Point2D],
) -> Double {
  @chamfer.chamfer_squared_directed(a, b)
}

///|
pub fn chamfer_rms(a : Array[Point2D], b : Array[Point2D]) -> Double {
  @chamfer.chamfer_rms(a, b)
}

// ---------------------------------------------------------------------------
// emd: Earth Mover's Distance / EMD 距离
// ---------------------------------------------------------------------------

///|
pub fn emd_1d(a : Array[Double], b : Array[Double]) -> Double {
  @emd.emd_1d(a, b)
} ///|

///|
pub fn emd_uniform(a : Array[Point2D], b : Array[Point2D]) -> Double {
  @emd.emd_uniform(a, b)
}

///|
pub fn emd_weighted(
  pos : Array[Double],
  wa : Array[Double],
  wb : Array[Double],
) -> Double {
  @emd.emd_weighted(pos, wa, wb)
}

// ---------------------------------------------------------------------------
// bottleneck: bottleneck matching / 瓶颈匹配
// ---------------------------------------------------------------------------

///|
pub fn bottleneck_distance(a : Array[Point2D], b : Array[Point2D]) -> Double {
  @bottleneck.bottleneck_distance(a, b)
}

///|
pub fn bottleneck_within(
  a : Array[Point2D],
  b : Array[Point2D],
  t : Double,
) -> Bool {
  @bottleneck.bottleneck_within(a, b, t)
}

///|
pub fn bottleneck_match(
  a : Array[Point2D],
  b : Array[Point2D],
) -> Array[(Int32, Int32, Double)] {
  @bottleneck.bottleneck_match(a, b)
}

///|
pub fn bottleneck_max(a : Array[Point2D], b : Array[Point2D]) -> Double {
  @bottleneck.bottleneck_max(a, b)
}

// ---------------------------------------------------------------------------
// pmatch: point matching / 点匹配
// ---------------------------------------------------------------------------

///|
pub fn point_match(
  a : Array[Point2D],
  b : Array[Point2D],
  t : Double,
) -> Array[(Int32, Int32)] {
  @pmatch.point_match(a, b, t)
} ///|

///|
pub fn match_count(a : Array[Point2D], b : Array[Point2D], t : Double) -> Int32 {
  @pmatch.match_count(a, b, t)
}

///|
pub fn match_ratio(
  a : Array[Point2D],
  b : Array[Point2D],
  t : Double,
) -> Double {
  @pmatch.match_ratio(a, b, t)
}

///|
pub fn unmatched_a(a : Array[Point2D], b : Array[Point2D], t : Double) -> Int32 {
  @pmatch.unmatched_a(a, b, t)
}

///|
pub fn unmatched_b(a : Array[Point2D], b : Array[Point2D], t : Double) -> Int32 {
  @pmatch.unmatched_b(a, b, t)
}

// ---------------------------------------------------------------------------
// dtw: dynamic time warping / DTW
// ---------------------------------------------------------------------------

///|
pub fn dtw_distance(c1 : Array[Point2D], c2 : Array[Point2D]) -> Double {
  @dtw.dtw_distance(c1, c2)
}

///|
pub fn dtw_windowed(
  c1 : Array[Point2D],
  c2 : Array[Point2D],
  w : Int32,
) -> Double {
  @dtw.dtw_windowed(c1, c2, w)
}

///|
pub fn dtw_normalized(c1 : Array[Point2D], c2 : Array[Point2D]) -> Double {
  @dtw.dtw_normalized(c1, c2)
}

// ---------------------------------------------------------------------------
// metric_tree: metric tree / 度量树
// ---------------------------------------------------------------------------///|

///|
/// Intersection of two polygons. / 两多边形交集。
pub fn polygon_intersection(subject : Polygon, clip : Polygon) -> Polygon? {
  @boolean.polygon_intersection(subject, clip)
}

///|
/// Union area of two polygons. / 两多边形并集面积。
pub fn polygon_union_area(p1 : Polygon, p2 : Polygon) -> Double {
  @boolean.polygon_union_area(p1, p2)
}

///|
/// Difference area of two polygons. / 两多边形差集面积。
pub fn polygon_difference_area(p1 : Polygon, p2 : Polygon) -> Double {
  @boolean.polygon_difference_area(p1, p2)
}

// ---------------------------------------------------------------------------
// triangulation: Delaunay / Voronoi / 三角剖分
// ---------------------------------------------------------------------------

///|
/// Delaunay triangulation. / Delaunay 三角剖分。
pub fn delaunay_triangulation(points : Array[Point2D]) -> Array[TriangleIdx] {
  @triangulation.delaunay_triangulation(points)
}

///|
/// Voronoi diagram from Delaunay. / 由 Delaunay 构造 Voronoi 图。
pub fn voronoi_diagram(
  points : Array[Point2D],
) -> (Array[Point2D], Array[(Int32, Int32)]) {
  @triangulation.voronoi_diagram(points)
}

// ---------------------------------------------------------------------------
// transform: affine transforms / 仿射变换
// ---------------------------------------------------------------------------

///|
/// Translate a point. / 平移点。
pub fn translate(p : Point2D, dx : Double, dy : Double) -> Point2D {
  @transform.translate(p, dx, dy)
}

///|
/// Translate an array of points. / 平移点数组。
pub fn translate_points(
  points : Array[Point2D],
  dx : Double,
  dy : Double,
) -> Array[Point2D] {
  @transform.translate_points(points, dx, dy)
}

///|
pub type MetricNode = @metric_tree.MetricNode

///|
pub fn build_metric_tree(pts : Array[Point2D]) -> MetricNode? {
  @metric_tree.build_metric_tree(pts)
}

///|
pub fn metric_tree_query(
  node : MetricNode?,
  q : Point2D,
  r : Double,
) -> Array[Point2D] {
  @metric_tree.metric_tree_query(node, q, r)
}

///|
pub fn metric_tree_count(node : MetricNode?) -> Int32 {
  @metric_tree.metric_tree_count(node)
}

///|
pub fn metric_tree_nearest(node : MetricNode?, q : Point2D) -> Point2D? {
  @metric_tree.metric_tree_nearest(node, q)
}

// ---------------------------------------------------------------------------
// dcel: doubly connected edge list / 双向连接边表
// ---------------------------------------------------------------------------

///|
pub type HalfEdge = @dcel.HalfEdge

///|

///|
pub type DcelFace = @dcel.Face

///|
pub type DCEL = @dcel.DCEL

///|
pub fn dcel_new() -> DCEL {
  @dcel.DCEL::new()
}

///|
pub fn dcel_add_vertex(d : DCEL, p : Point2D) -> Int32 {
  @dcel.DCEL::add_vertex(d, p)
}

///|
pub fn dcel_add_edge(d : DCEL, from : Int32, to : Int32) -> Int32 {
  @dcel.DCEL::add_edge(d, from, to)
}

///|
pub fn dcel_add_face(d : DCEL, outer : Int32) -> Int32 {
  @dcel.DCEL::add_face(d, outer)
}

///|
pub fn dcel_set_next(d : DCEL, he : Int32, next : Int32) -> Unit {
  @dcel.DCEL::set_next(d, he, next)
}

///|
pub fn dcel_set_face(d : DCEL, he : Int32, face : Int32) -> Unit {
  @dcel.DCEL::set_face(d, he, face)
} ///|

///|
pub fn dcel_vertex_count(d : DCEL) -> Int32 {
  @dcel.DCEL::vertex_count(d)
}

///|
pub fn dcel_edge_count(d : DCEL) -> Int32 {
  @dcel.DCEL::edge_count(d)
}

///|
pub fn dcel_face_count(d : DCEL) -> Int32 {
  @dcel.DCEL::face_count(d)
}

///|
pub fn dcel_trace_face(d : DCEL, start_he : Int32) -> Array[Int32] {
  @dcel.DCEL::trace_face(d, start_he)
}

///|
pub fn dcel_from_polygon(d : DCEL, poly : Polygon) -> DCEL {
  @dcel.DCEL::from_polygon(d, poly)
}

// ---------------------------------------------------------------------------
// arrangement: line segment arrangement / 线段排列
// ---------------------------------------------------------------------------

///|
pub type ArrangementVertex = @arrangement.ArrangementVertex

///|

///|
pub type Arrangement = @arrangement.Arrangement

///|
pub fn build_arrangement(segs : Array[Segment]) -> Arrangement {
  @arrangement.build_arrangement(segs)
}

///|
pub fn arrangement_vertices(arr : Arrangement) -> Array[ArrangementVertex] {
  @arrangement.arrangement_vertices(arr)
}

///|
pub fn arrangement_intersection_count(arr : Arrangement) -> Int32 {
  @arrangement.arrangement_intersection_count(arr)
}

///|
pub fn arrangement_edge_count(arr : Arrangement) -> Int32 {
  @arrangement.arrangement_edge_count(arr)
}

///|
pub fn arrangement_face_count(arr : Arrangement) -> Int32 {
  @arrangement.arrangement_face_count(arr)
}

// ---------------------------------------------------------------------------
// planar_graph: planar graph / 平面图
// ---------------------------------------------------------------------------

///|
pub type PlanarEdge = @planar_graph.PlanarEdge

///|

///|
pub type PlanarGraph = @planar_graph.PlanarGraph

///|
pub fn planar_graph_new() -> PlanarGraph {
  @planar_graph.PlanarGraph::new()
}

///|
pub fn planar_graph_add_vertex(g : PlanarGraph, p : Point2D) -> Int32 {
  @planar_graph.PlanarGraph::add_vertex(g, p)
}

///|
pub fn planar_graph_add_edge(g : PlanarGraph, from : Int32, to : Int32) -> Unit {
  @planar_graph.PlanarGraph::add_edge(g, from, to)
}

///|
pub fn planar_graph_vertex_count(g : PlanarGraph) -> Int32 {
  @planar_graph.PlanarGraph::vertex_count(g)
}

///|
pub fn planar_graph_edge_count(g : PlanarGraph) -> Int32 {
  @planar_graph.PlanarGraph::edge_count(g)
}

///|
pub fn planar_graph_is_planar(g : PlanarGraph) -> Bool {
  @planar_graph.PlanarGraph::is_planar(g)
}

///|
pub fn planar_graph_degree(g : PlanarGraph, v : Int32) -> Int32 {
  @planar_graph.PlanarGraph::degree(g, v)
} ///|

///|
pub fn planar_graph_neighbors(g : PlanarGraph, v : Int32) -> Array[Int32] {
  @planar_graph.PlanarGraph::neighbors(g, v)
}

///|
pub fn planar_graph_is_connected(g : PlanarGraph) -> Bool {
  @planar_graph.PlanarGraph::is_connected(g)
}

///|
pub fn planar_graph_face_count(g : PlanarGraph) -> Int32 {
  @planar_graph.PlanarGraph::face_count(g)
}

///|
pub fn planar_graph_from_polygon(
  g : PlanarGraph,
  poly : Polygon,
) -> PlanarGraph {
  @planar_graph.PlanarGraph::from_polygon(g, poly)
}

// ---------------------------------------------------------------------------
// face_extract: face extraction / 面提取
// ---------------------------------------------------------------------------

///|
pub type ExtractFace = @face_extract.Face

///|
pub fn extract_faces(
  verts : Array[Point2D],
  edges : Array[(Int32, Int32)],
) -> Array[ExtractFace] {
  @face_extract.extract_faces(verts, edges)
}

///|
pub fn face_area(f : ExtractFace) -> Double {
  @face_extract.face_area(f)
} ///|

///|
pub fn face_count(faces : Array[ExtractFace]) -> Int32 {
  @face_extract.face_count(faces)
}

// ---------------------------------------------------------------------------
// overlay: planar subdivision overlay / 平面细分叠加
// ---------------------------------------------------------------------------

///|
pub type OverlayResult = @overlay.OverlayResult

///|
pub fn overlay(s1 : Array[Segment], s2 : Array[Segment]) -> OverlayResult {
  @overlay.overlay(s1, s2)
}

///|
pub fn overlay_vertex_count(r : OverlayResult) -> Int32 {
  @overlay.overlay_vertex_count(r)
}

///|
pub fn overlay_edge_count(r : OverlayResult) -> Int32 {
  @overlay.overlay_edge_count(r)
}

///|
pub fn overlay_vertices(r : OverlayResult) -> Array[Point2D] {
  @overlay.overlay_vertices(r)
}

///|
pub fn overlay_edges(r : OverlayResult) -> Array[(Int32, Int32)] {
  @overlay.overlay_edges(r)
}

// ---------------------------------------------------------------------------
// euler_tour: Euler tour / 欧拉回路
// ---------------------------------------------------------------------------///|

///|
pub type EulerTour = @euler_tour.EulerTour

///|
pub fn build_euler_tour(
  n : Int32,
  adj : Array[Array[Int32]],
  root : Int32,
) -> EulerTour {
  @euler_tour.build_euler_tour(n, adj, root)
}

///|
pub fn euler_tour_sequence(t : EulerTour) -> Array[Int32] {
  @euler_tour.euler_tour_sequence(t)
}

///|
pub fn euler_tour_depths(t : EulerTour) -> Array[Int32] {
  @euler_tour.euler_tour_depths(t)
}

///|
pub fn euler_tour_length(t : EulerTour) -> Int32 {
  @euler_tour.euler_tour_length(t)
}

///|
pub fn euler_tour_first_occurrence(t : EulerTour, v : Int32) -> Int32 {
  @euler_tour.euler_tour_first_occurrence(t, v)
}

///|
pub fn euler_tour_lca(t : EulerTour, u : Int32, v : Int32) -> Int32 {
  @euler_tour.euler_tour_lca(t, u, v)
} ///|

///|
pub fn euler_tour_is_valid(t : EulerTour) -> Bool {
  @euler_tour.euler_tour_is_valid(t)
}

// ---------------------------------------------------------------------------
// trapezoidal: trapezoidal decomposition / 梯形分解
// ---------------------------------------------------------------------------

///|
pub type Trapezoid = @trapezoidal.Trapezoid

///|
pub type TrapezoidalMap = @trapezoidal.TrapezoidalMap

///|
pub fn build_trapezoidal_map(segs : Array[Segment]) -> TrapezoidalMap {
  @trapezoidal.build_trapezoidal_map(segs)
}

///|
pub fn trapezoidal_locate(m : TrapezoidalMap, p : Point2D) -> Int32 {
  @trapezoidal.trapezoidal_locate(m, p)
}

///|
pub fn trapezoidal_count(m : TrapezoidalMap) -> Int32 {
  @trapezoidal.trapezoidal_count(m)
}

///|
pub fn trapezoidal_all(m : TrapezoidalMap) -> Array[Trapezoid] {
  @trapezoidal.trapezoidal_all(m)
} ///|

///|
pub fn trapezoidal_above_segment(s : Segment, p : Point2D) -> Bool {
  @trapezoidal.trapezoidal_above_segment(s, p)
}

///|
pub fn trapezoidal_expected_count(m : TrapezoidalMap) -> Int32 {
  @trapezoidal.trapezoidal_expected_count(m)
}

// ---------------------------------------------------------------------------
// zone: zone theorem / 区域定理
// ---------------------------------------------------------------------------

///|
pub type Zone = @zone.Zone

///|
pub fn compute_zone(line : Line, segs : Array[Segment]) -> Zone {
  @zone.compute_zone(line, segs)
}

///|
pub fn zone_crossed_count(z : Zone) -> Int32 {
  @zone.zone_crossed_count(z)
}

///|
pub fn zone_entry_points(z : Zone) -> Array[Point2D] {
  @zone.zone_entry_points(z)
}

///|
pub fn zone_crossed_faces(z : Zone) -> Array[Int32] {
  @zone.zone_crossed_faces(z)
} ///|
/// Rotate a point around the origin. / 绕原点旋转点。

///|
pub fn rotate(p : Point2D, angle : Double) -> Point2D {
  @transform.rotate(p, angle)
}

///|
/// Rotate a point around a center. / 绕中心点旋转。
pub fn rotate_around(p : Point2D, center : Point2D, angle : Double) -> Point2D {
  @transform.rotate_around(p, center, angle)
}

///|
/// Rotate an array of points around a center. / 绕中心点旋转点数组。
pub fn rotate_points(
  points : Array[Point2D],
  center : Point2D,
  angle : Double,
) -> Array[Point2D] {
  @transform.rotate_points(points, center, angle)
}

///|
/// Scale a point. / 缩放点。
pub fn scale(p : Point2D, sx : Double, sy : Double) -> Point2D {
  @transform.scale(p, sx, sy)
}

///|
/// Scale a point relative to a center. / 相对中心点缩放。
pub fn scale_around(
  p : Point2D,
  center : Point2D,
  sx : Double,
  sy : Double,
) -> Point2D {
  @transform.scale_around(p, center, sx, sy)
}

///|
/// Affine transform: (x,y) -> (a*x+b*y+c, d*x+e*y+f). / 仿射变换。
pub fn affine_transform(
  p : Point2D,
  a : Double,
  b : Double,
  c : Double,
  d : Double,
  e : Double,
  f : Double,
) -> Point2D {
  @transform.affine_transform(p, a, b, c, d, e, f)
}

///|
/// Affine transform on an array of points. / 对点数组应用仿射变换。
pub fn affine_transform_points(
  points : Array[Point2D],
  a : Double,
  b : Double,
  c : Double,
  d : Double,
  e : Double,
  f : Double,
) -> Array[Point2D] {
  @transform.affine_transform_points(points, a, b, c, d, e, f)
}

///|
pub fn zone_complexity(z : Zone) -> Int32 {
  @zone.zone_complexity(z)
}

///|
pub fn zone_complexity_bound(n : Int32) -> Int32 {
  @zone.zone_complexity_bound(n)
}

// ---------------------------------------------------------------------------
// project3d: 3D projection / 三维投影
// ---------------------------------------------------------------------------

///|
pub fn orthographic(p : Point3D) -> Point2D {
  @project3d.orthographic(p)
}

///|
pub fn perspective_project(p : Point3D, f : Double) -> Point2D? {
  @project3d.perspective_project(p, f)
}

///|
pub fn orthographic_batch(pts : Array[Point3D]) -> Array[Point2D] {
  @project3d.orthographic_batch(pts)
}

///|
pub fn perspective_batch(pts : Array[Point3D], f : Double) -> Array[Point2D] {
  @project3d.perspective_batch(pts, f)
}

///|
pub fn project_to_plane(p : Point3D, normal : Point3D, d : Double) -> Point3D {
  @project3d.project_to_plane(p, normal, d)
} ///|

///|
pub fn isometric(p : Point3D) -> Point2D {
  @project3d.isometric(p)
}

///|
pub fn oblique(p : Point3D, alpha : Double, beta : Double) -> Point2D {
  @project3d.oblique(p, alpha, beta)
}

// ---------------------------------------------------------------------------
// homography: 3x3 projective transform / 单应变换
// ---------------------------------------------------------------------------

///|
pub type Homography = @homography.Homography

///|
pub fn homography_identity() -> Homography {
  @homography.Homography::identity()
}

///|
pub fn homography_from_array(h : Array[Double]) -> Homography {
  @homography.Homography::from_array(h)
}

///|
pub fn homography_apply(m : Homography, p : Point2D) -> Point2D? {
  @homography.Homography::apply(m, p)
}

///|
pub fn homography_compose(m1 : Homography, m2 : Homography) -> Homography {
  @homography.Homography::compose(m1, m2)
} ///|

///|
pub fn homography_apply_batch(
  m : Homography,
  pts : Array[Point2D],
) -> Array[Point2D] {
  @homography.Homography::apply_batch(m, pts)
}

///|
pub fn homography_determinant(m : Homography) -> Double {
  @homography.Homography::determinant(m)
}

// ---------------------------------------------------------------------------
// perspective: perspective transform / 透视变换
// ---------------------------------------------------------------------------

///|
pub type Perspective = @perspective.Perspective

///|
pub fn perspective_new(
  f : Double,
  cx : Double,
  cy : Double,
  n : Double,
  fr : Double,
) -> Perspective {
  @perspective.Perspective::new(f, cx, cy, n, fr)
}

///|
pub fn perspective_project_3d(p : Perspective, pt : Point3D) -> Point2D? {
  @perspective.Perspective::project(p, pt)
}

///|
pub fn perspective_unproject(p : Perspective, pt : Point2D) -> Point3D {
  @perspective.Perspective::unproject(p, pt)
}

///|
pub fn perspective_depth(p : Perspective, pt : Point3D) -> Double {
  @perspective.Perspective::depth(p, pt)
} ///|

///|
pub fn perspective_fov(p : Perspective, w : Double) -> Double {
  @perspective.Perspective::fov(p, w)
}

///|
pub fn focal_from_fov(fov : Double, w : Double) -> Double {
  @perspective.focal_from_fov(fov, w)
}

// ---------------------------------------------------------------------------
// stereographic: stereographic projection / 球极投影
// ---------------------------------------------------------------------------

///|
pub fn stereographic_from_sphere(p : Point3D, r : Double) -> Point2D? {
  @stereographic.stereographic_from_sphere(p, r)
}

///|
pub fn stereographic_to_sphere(p : Point2D, r : Double) -> Point3D {
  @stereographic.stereographic_to_sphere(p, r)
}

///|
pub fn stereographic_from_south(p : Point3D, r : Double) -> Point2D? {
  @stereographic.stereographic_from_south(p, r)
}

///|
pub fn on_sphere(p : Point3D, r : Double) -> Bool {
  @stereographic.on_sphere(p, r)
}

///|
pub fn stereographic_scale(p : Point3D, r : Double) -> Double {
  @stereographic.stereographic_scale(p, r)
}

// ---------------------------------------------------------------------------
// affine2: 2D affine transform / 二维仿射变换
// ---------------------------------------------------------------------------///|

///|
pub type Affine2 = @affine2.Affine2

///|
pub fn affine2_identity() -> Affine2 {
  @affine2.Affine2::identity()
}

///|
pub fn affine2_translation(tx : Double, ty : Double) -> Affine2 {
  @affine2.Affine2::translation(tx, ty)
}

///|
pub fn affine2_scale(sx : Double, sy : Double) -> Affine2 {
  @affine2.Affine2::scale(sx, sy)
}

///|
pub fn affine2_shear(shx : Double, shy : Double) -> Affine2 {
  @affine2.Affine2::shear(shx, shy)
}

///|
pub fn affine2_apply(m : Affine2, p : Point2D) -> Point2D {
  @affine2.Affine2::apply(m, p)
}

///|
pub fn affine2_compose(m1 : Affine2, m2 : Affine2) -> Affine2 {
  @affine2.Affine2::compose(m1, m2)
} ///|

///|
pub fn affine2_determinant(m : Affine2) -> Double {
  @affine2.Affine2::determinant(m)
}

///|
pub fn affine2_inverse(m : Affine2) -> Affine2? {
  @affine2.Affine2::inverse(m)
}

///|
pub fn affine2_apply_batch(m : Affine2, pts : Array[Point2D]) -> Array[Point2D] {
  @affine2.Affine2::apply_batch(m, pts)
}

// ---------------------------------------------------------------------------
// rigid: rigid transform / 刚体变换
// ---------------------------------------------------------------------------

///|
pub type Rigid = @rigid.Rigid

///|
pub fn rigid_identity() -> Rigid {
  @rigid.Rigid::identity()
}

///|
pub fn rigid_translation(tx : Double, ty : Double) -> Rigid {
  @rigid.Rigid::translation(tx, ty)
}

///|
pub fn rigid_rotation(angle : Double) -> Rigid {
  @rigid.Rigid::rotation(angle)
} ///|

///|
pub fn rigid_apply(r : Rigid, p : Point2D) -> Point2D {
  @rigid.Rigid::apply(r, p)
}

///|
pub fn rigid_compose(r1 : Rigid, r2 : Rigid) -> Rigid {
  @rigid.Rigid::compose(r1, r2)
}

///|
pub fn rigid_inverse(r : Rigid) -> Rigid {
  @rigid.Rigid::inverse(r)
}

///|
pub fn rigid_apply_batch(r : Rigid, pts : Array[Point2D]) -> Array[Point2D] {
  @rigid.Rigid::apply_batch(r, pts)
}

///|
pub fn rigid_from_correspondence(
  s1 : Point2D,
  d1 : Point2D,
  s2 : Point2D,
  d2 : Point2D,
) -> Rigid {
  @rigid.Rigid::from_correspondence(s1, d1, s2, d2)
}

// ---------------------------------------------------------------------------
// similarity: similarity transform / 相似变换
// ---------------------------------------------------------------------------

///|
pub type Similarity = @similarity.Similarity

///|
pub fn similarity_identity() -> Similarity {
  @similarity.Similarity::identity()
} ///|

///|
pub fn similarity_scaling(s : Double) -> Similarity {
  @similarity.Similarity::scaling(s)
}

///|
pub fn similarity_rotation(angle : Double) -> Similarity {
  @similarity.Similarity::rotation(angle)
}

///|
pub fn similarity_translation(tx : Double, ty : Double) -> Similarity {
  @similarity.Similarity::translation(tx, ty)
}

///|
pub fn similarity_apply(s : Similarity, p : Point2D) -> Point2D {
  @similarity.Similarity::apply(s, p)
}

///|
pub fn similarity_compose(s1 : Similarity, s2 : Similarity) -> Similarity {
  @similarity.Similarity::compose(s1, s2)
}

///|
pub fn similarity_inverse(s : Similarity) -> Similarity? {
  @similarity.Similarity::inverse(s)
}

///|
pub fn similarity_apply_batch(
  s : Similarity,
  pts : Array[Point2D],
) -> Array[Point2D] {
  @similarity.Similarity::apply_batch(s, pts)
} ///|

///|
pub fn similarity_from_correspondence(
  s1 : Point2D,
  d1 : Point2D,
  s2 : Point2D,
  d2 : Point2D,
) -> Similarity {
  @similarity.Similarity::from_correspondence(s1, d1, s2, d2)
}

// ---------------------------------------------------------------------------
// inversion: geometric inversion / 几何反演
// ---------------------------------------------------------------------------

///|
pub type Inversion = @inversion.Inversion

///|
pub fn inversion_new(center : Point2D, r : Double) -> Inversion {
  @inversion.Inversion::new(center, r)
}

///|
pub fn inversion_apply(inv : Inversion, p : Point2D) -> Point2D? {
  @inversion.Inversion::apply(inv, p)
}

///|
pub fn inversion_apply_batch(
  inv : Inversion,
  pts : Array[Point2D],
) -> Array[Point2D] {
  @inversion.Inversion::apply_batch(inv, pts)
}

///|
pub fn inversion_power(inv : Inversion, p : Point2D) -> Double {
  @inversion.Inversion::power(inv, p)
}

///|
pub fn inversion_is_inside(inv : Inversion, p : Point2D) -> Bool {
  @inversion.Inversion::is_inside(inv, p)
} ///|

///|
pub fn inversion_is_on_circle(inv : Inversion, p : Point2D) -> Bool {
  @inversion.Inversion::is_on_circle(inv, p)
}

///|
pub fn inversion_invert_line(
  inv : Inversion,
  a : Double,
  b : Double,
  c : Double,
) -> Circle? {
  @inversion.Inversion::invert_line(inv, a, b, c)
}

// ---------------------------------------------------------------------------
// mesh_data: 3D triangle mesh / 三维三角网格
// ---------------------------------------------------------------------------

///|
pub type MeshFace = @mesh_data.MeshFace

///|
pub type Mesh = @mesh_data.Mesh

///|
pub fn mesh_new() -> Mesh {
  @mesh_data.Mesh::new()
}

///|
pub fn mesh_add_vertex(m : Mesh, p : Point3D) -> Int32 {
  @mesh_data.Mesh::add_vertex(m, p)
}

///|
pub fn mesh_add_face(m : Mesh, v0 : Int32, v1 : Int32, v2 : Int32) -> Unit {
  @mesh_data.Mesh::add_face(m, v0, v1, v2)
} ///|
/// Mirror across x-axis. / 关于 x 轴镜像。

///|
pub fn mirror_x(p : Point2D) -> Point2D {
  @transform.mirror_x(p)
}

///|
/// Mirror across y-axis. / 关于 y 轴镜像。
pub fn mirror_y(p : Point2D) -> Point2D {
  @transform.mirror_y(p)
}

///|
/// Mirror through origin. / 关于原点镜像。
pub fn mirror_origin(p : Point2D) -> Point2D {
  @transform.mirror_origin(p)
}

///|
/// Mirror across a line. / 关于直线镜像。
pub fn mirror_line(p : Point2D, line : Line) -> Point2D {
  @transform.mirror_line(p, line)
}

///|
/// Shear transform. / 剪切变换。
pub fn shear(p : Point2D, kx : Double, ky : Double) -> Point2D {
  @transform.shear(p, kx, ky)
}

// ---------------------------------------------------------------------------
// distance: distance computations / 距离计算
// ---------------------------------------------------------------------------

///|
/// Distance from a point to a segment. / 点到线段距离。
pub fn point_to_segment_distance(p : Point2D, seg : Segment) -> Double {
  @distance.point_to_segment_distance(p, seg)
}

///|
/// Distance from a point to a polygon. / 点到多边形距离。
pub fn point_to_polygon_distance(p : Point2D, poly : Polygon) -> Double {
  @distance.point_to_polygon_distance(p, poly)
}

///|
pub fn mesh_vertex_count(m : Mesh) -> Int32 {
  @mesh_data.Mesh::vertex_count(m)
}

///|
pub fn mesh_face_count(m : Mesh) -> Int32 {
  @mesh_data.Mesh::face_count(m)
}

///|
pub fn mesh_edge_count(m : Mesh) -> Int32 {
  @mesh_data.Mesh::edge_count(m)
}

///|
pub fn mesh_bounding_box(m : Mesh) -> (Point3D, Point3D) {
  @mesh_data.Mesh::bounding_box(m)
}

///|
pub fn mesh_tetrahedron(
  a : Point3D,
  b : Point3D,
  c : Point3D,
  d : Point3D,
) -> Mesh {
  @mesh_data.Mesh::tetrahedron(a, b, c, d)
}

// ---------------------------------------------------------------------------
// mesh_simplify: mesh simplification / 网格简化
// ---------------------------------------------------------------------------

///|
pub fn simplify_by_edge_length(m : Mesh, t : Double) -> Mesh {
  @mesh_simplify.simplify_by_edge_length(m, t)
}

///|
pub fn edge_collapse_cost(m : Mesh, v0 : Int32, v1 : Int32) -> Double {
  @mesh_simplify.edge_collapse_cost(m, v0, v1)
} ///|

///|
pub fn collapsible_edges(m : Mesh, t : Double) -> Int32 {
  @mesh_simplify.collapsible_edges(m, t)
}

///|
pub fn simplification_ratio(o : Mesh, s : Mesh) -> Double {
  @mesh_simplify.simplification_ratio(o, s)
}

// ---------------------------------------------------------------------------
// mesh_smooth: mesh smoothing / 网格平滑
// ---------------------------------------------------------------------------

///|
pub fn laplacian_smooth(m : Mesh, l : Double) -> Mesh {
  @mesh_smooth.laplacian_smooth(m, l)
}

///|
pub fn laplacian_smooth_iter(m : Mesh, l : Double, i : Int32) -> Mesh {
  @mesh_smooth.laplacian_smooth_iter(m, l, i)
}

///|
pub fn taubin_smooth(m : Mesh, l : Double, mu : Double) -> Mesh {
  @mesh_smooth.taubin_smooth(m, l, mu)
}

///|
pub fn smooth_displacement(o : Mesh, s : Mesh) -> Double {
  @mesh_smooth.smooth_displacement(o, s)
}

// ---------------------------------------------------------------------------
// mesh_normal: mesh normals / 网格法向量
// ---------------------------------------------------------------------------

///|
pub fn face_normal(m : Mesh, fi : Int32) -> Point3D {
  @mesh_normal.face_normal(m, fi)
} ///|

///|
pub fn normalize3d(v : Point3D) -> Point3D {
  @mesh_normal.normalize(v)
}

///|
pub fn vertex_normal(m : Mesh, vi : Int32) -> Point3D {
  @mesh_normal.vertex_normal(m, vi)
}

///|
pub fn all_face_normals(m : Mesh) -> Array[Point3D] {
  @mesh_normal.all_face_normals(m)
}

///|
pub fn all_vertex_normals(m : Mesh) -> Array[Point3D] {
  @mesh_normal.all_vertex_normals(m)
}

///|
pub fn mesh_face_area(m : Mesh, fi : Int32) -> Double {
  @mesh_normal.face_area(m, fi)
}

// ---------------------------------------------------------------------------
// mesh_subdiv: mesh subdivision / 网格细分
// ---------------------------------------------------------------------------

///|
pub fn loop_subdivide(m : Mesh) -> Mesh {
  @mesh_subdiv.loop_subdivide(m)
}

///|
pub fn edge_bisection(m : Mesh) -> Mesh {
  @mesh_subdiv.edge_bisection(m)
} ///|

///|
pub fn catmull_clark_subdivide(m : Mesh) -> Mesh {
  @mesh_subdiv.catmull_clark_subdivide(m)
}

///|
pub fn subdivided_face_count(m : Mesh) -> Int32 {
  @mesh_subdiv.subdivided_face_count(m)
}

// ---------------------------------------------------------------------------
// euler_char: Euler characteristic / 欧拉示性数
// ---------------------------------------------------------------------------

///|
pub fn euler_characteristic(m : Mesh) -> Int32 {
  @euler_char.euler_characteristic(m)
}

///|
pub fn surface_genus(m : Mesh) -> Int32 {
  @euler_char.surface_genus(m)
}

///|
pub fn is_sphere(m : Mesh) -> Bool {
  @euler_char.is_sphere(m)
}

///|
pub fn is_torus(m : Mesh) -> Bool {
  @euler_char.is_torus(m)
}

///|
pub fn euler_from_counts(v : Int32, e : Int32, f : Int32) -> Int32 {
  @euler_char.euler_from_counts(v, e, f)
} ///|

///|
pub fn betti_0(m : Mesh) -> Int32 {
  @euler_char.betti_0(m)
}

///|
pub fn is_manifold(m : Mesh) -> Bool {
  @euler_char.is_manifold(m)
}

// ---------------------------------------------------------------------------
// optim: geometric optimization / 几何优化
// ---------------------------------------------------------------------------

///|
pub fn smallest_enclosing_circle(pts : Array[Point2D]) -> Circle {
  @optim.smallest_enclosing_circle(pts)
}

///|
pub fn min_area_rect(pts : Array[Point2D]) -> Rectangle {
  @optim.min_area_rect(pts)
}

///|
pub fn optim_centroid(pts : Array[Point2D]) -> Point2D {
  @optim.centroid(pts)
}

///|
pub fn closest_to_centroid(pts : Array[Point2D]) -> Point2D? {
  @optim.closest_to_centroid(pts)
}

// ---------------------------------------------------------------------------
// random_gen: random generation / 随机生成
// ---------------------------------------------------------------------------

///|

///|
pub type Rng = @random_gen.Rng

///|
pub fn rng_new(seed : UInt32) -> Rng {
  @random_gen.Rng::new(seed)
}

///|
pub fn rng_next_uint(r : Rng) -> UInt32 {
  @random_gen.Rng::next_uint(r)
}

///|
pub fn rng_next_double(r : Rng) -> Double {
  @random_gen.Rng::next_double(r)
}

///|
pub fn rng_point2d(
  r : Rng,
  xlo : Double,
  xhi : Double,
  ylo : Double,
  yhi : Double,
) -> Point2D {
  @random_gen.Rng::point2d(r, xlo, xhi, ylo, yhi)
}

///|
pub fn rng_random_points(
  r : Rng,
  n : Int32,
  xlo : Double,
  xhi : Double,
  ylo : Double,
  yhi : Double,
) -> Array[Point2D] {
  @random_gen.Rng::random_points(r, n, xlo, xhi, ylo, yhi)
}

///|
pub fn rng_random_convex_polygon(
  r : Rng,
  n : Int32,
  radius : Double,
) -> Array[Point2D] {
  @random_gen.Rng::random_convex_polygon(r, n, radius)
}

// ---------------------------------------------------------------------------
// sampling: geometric sampling / 几何采样
// ---------------------------------------------------------------------------

///|
pub fn grid_sample(
  xlo : Double,
  xhi : Double,
  ylo : Double,
  yhi : Double,
  nx : Int32,
  ny : Int32,
) -> Array[Point2D] {
  @sampling.grid_sample(xlo, xhi, ylo, yhi, nx, ny)
} ///|

///|
pub fn circle_sample(c : Point2D, r : Double, n : Int32) -> Array[Point2D] {
  @sampling.circle_sample(c, r, n)
}

///|
pub fn circle_interior_sample(
  c : Point2D,
  r : Double,
  n : Int32,
) -> Array[Point2D] {
  @sampling.circle_interior_sample(c, r, n)
}

///|
pub fn poisson_disk_sample(
  xlo : Double,
  xhi : Double,
  ylo : Double,
  yhi : Double,
  md : Double,
) -> Array[Point2D] {
  @sampling.poisson_disk_sample(xlo, xhi, ylo, yhi, md)
}

///|
pub fn segment_sample(p1 : Point2D, p2 : Point2D, n : Int32) -> Array[Point2D] {
  @sampling.segment_sample(p1, p2, n)
}

///|
pub fn halton_sample(bx : Int32, by : Int32, n : Int32) -> Array[Point2D] {
  @sampling.halton_sample(bx, by, n)
}

// ---------------------------------------------------------------------------
// svg_out: SVG output / SVG 输出
// ---------------------------------------------------------------------------

///|
pub type SvgSettings = @svg_out.SvgSettings

///|
pub fn svg_settings_default() -> SvgSettings {
  @svg_out.SvgSettings::default()
} ///|

///|
pub fn svg_header(s : SvgSettings) -> String {
  @svg_out.svg_header(s)
}

///|
pub fn svg_footer() -> String {
  @svg_out.svg_footer()
}

///|
pub fn svg_circle(c : Circle, s : SvgSettings) -> String {
  @svg_out.svg_circle(c, s)
}

///|
pub fn svg_polygon(pts : Array[Point2D], s : SvgSettings) -> String {
  @svg_out.svg_polygon(pts, s)
}

///|
pub fn svg_line(p1 : Point2D, p2 : Point2D, s : SvgSettings) -> String {
  @svg_out.svg_line(p1, p2, s)
}

///|
pub fn svg_document(polys : Array[Array[Point2D]], s : SvgSettings) -> String {
  @svg_out.svg_document(polys, s)
}

// ---------------------------------------------------------------------------
// json_out: JSON output / JSON 输出
// ---------------------------------------------------------------------------

///|
pub fn point2d_to_json(p : Point2D) -> String {
  @json_out.point2d_to_json(p)
} ///|

///|
pub fn point3d_to_json(p : Point3D) -> String {
  @json_out.point3d_to_json(p)
}

///|
pub fn segment_to_json(s : Segment) -> String {
  @json_out.segment_to_json(s)
}

///|
pub fn circle_to_json(c : Circle) -> String {
  @json_out.circle_to_json(c)
}

///|
pub fn rectangle_to_json(r : Rectangle) -> String {
  @json_out.rectangle_to_json(r)
}

///|
pub fn polygon_to_json(p : Polygon) -> String {
  @json_out.polygon_to_json(p)
}

///|
pub fn points_to_json(pts : Array[Point2D]) -> String {
  @json_out.points_to_json(pts)
}

///|
pub fn triangle_to_json(t : Triangle) -> String {
  @json_out.triangle_to_json(t)
} ///|

///|
pub fn scene_to_json(
  pts : Array[Point2D],
  segs : Array[Segment],
  circs : Array[Circle],
) -> String {
  @json_out.scene_to_json(pts, segs, circs)
}
// ---------------------------------------------------------------------------
// convex_hull_approx: Approximate convex hull / 近似凸包
// ---------------------------------------------------------------------------

///|
pub fn approx_convex_hull(
  points : Array[Point2D],
  grid_size : Int32,
) -> Array[Point2D] {
  @convex_hull_approx.approx_convex_hull(points, grid_size)
}

///|
pub fn approx_hull_area(points : Array[Point2D]) -> Double {
  @convex_hull_approx.approx_hull_area(points)
}

///|
pub fn approx_hull_perimeter(points : Array[Point2D]) -> Double {
  @convex_hull_approx.approx_hull_perimeter(points)
}

///|
pub fn approx_error_bound(points : Array[Point2D], grid_size : Int32) -> Double {
  @convex_hull_approx.approx_error_bound(points, grid_size)
}

// ---------------------------------------------------------------------------
// convex_hull_dynamic: Dynamic convex hull / 动态凸包
// ---------------------------------------------------------------------------

///|
pub type DynamicHull = @convex_hull_dynamic.DynamicHull

///|
pub fn dynamic_hull_new() -> DynamicHull {
  @convex_hull_dynamic.DynamicHull::new()
} ///|
/// Minimum distance between two segments. / 两线段最小距离。

///|
pub fn segment_to_segment_distance(s1 : Segment, s2 : Segment) -> Double {
  @distance.segment_to_segment_distance(s1, s2)
}

///|
/// Minimum distance between two polygons. / 两多边形最小距离。
pub fn polygon_to_polygon_distance(p1 : Polygon, p2 : Polygon) -> Double {
  @distance.polygon_to_polygon_distance(p1, p2)
}

///|
/// Distance from a point to a line. / 点到直线距离。
pub fn point_to_line_distance(p : Point2D, line : Line) -> Double {
  @distance.point_to_line_distance(p, line)
}

// ---------------------------------------------------------------------------
// bounding: bounding volumes / 包围体
// ---------------------------------------------------------------------------

///|
/// Axis-aligned bounding box of points. / 点集轴对齐包围盒。
pub fn aabb(points : Array[Point2D]) -> Rectangle {
  @bounding.aabb(points)
}

///|
/// Axis-aligned bounding box of a polygon. / 多边形轴对齐包围盒。
pub fn aabb_polygon(poly : Polygon) -> Rectangle {
  @bounding.aabb_polygon(poly)
}

///|
/// Minimum-area bounding rectangle (rotating calipers). / 最小面积包围矩形。
pub fn min_area_bounding_rect(
  points : Array[Point2D],
) -> (Double, Double, Double, Double, Double) {
  @bounding.min_area_bounding_rect(points)
}

///|
/// Bounding circle (centroid + max distance). / 包围圆。
pub fn bounding_circle(points : Array[Point2D]) -> (Point2D, Double) {
  @bounding.bounding_circle(points)
}
// ---------------------------------------------------------------------------
// circle_ops: circle intersection / 圆相交
// ---------------------------------------------------------------------------

///|
pub fn dynamic_hull_insert(dh : DynamicHull, p : Point2D) -> Unit {
  @convex_hull_dynamic.DynamicHull::insert(dh, p)
}

///|
pub fn dynamic_hull_get_hull(dh : DynamicHull) -> Array[Point2D] {
  @convex_hull_dynamic.DynamicHull::get_hull(dh)
}

///|
pub fn dynamic_hull_size(dh : DynamicHull) -> Int32 {
  @convex_hull_dynamic.DynamicHull::size(dh)
}

///|
pub fn dynamic_hull_contains(dh : DynamicHull, p : Point2D) -> Bool {
  @convex_hull_dynamic.DynamicHull::contains(dh, p)
}

// ---------------------------------------------------------------------------
// convex_layers: Convex layers (onion decomposition) / 凸包层次(洋葱分解)
// ---------------------------------------------------------------------------

///|
pub fn convex_layers(points : Array[Point2D]) -> Array[Array[Point2D]] {
  @convex_layers.convex_layers(points)
}

///|
pub fn layer_count(points : Array[Point2D]) -> Int32 {
  @convex_layers.layer_count(points)
}

///|
pub fn outermost_layer(points : Array[Point2D]) -> Array[Point2D] {
  @convex_layers.outermost_layer(points)
}

// ---------------------------------------------------------------------------
// concave_hull: Concave hull / 凹包
// ---------------------------------------------------------------------------///|

///|
pub fn concave_hull(points : Array[Point2D], k : Int32) -> Array[Point2D] {
  @concave_hull.concave_hull(points, k)
}

///|
pub fn concave_hull_default(points : Array[Point2D]) -> Array[Point2D] {
  @concave_hull.concave_hull_default(points)
}

// ---------------------------------------------------------------------------
// convex_width: Convex polygon width / 凸多边形宽度
// ---------------------------------------------------------------------------

///|
pub fn convex_width(poly : Polygon) -> Double {
  @convex_width.convex_width(poly)
}

///|
pub fn convex_max_width(poly : Polygon) -> Double {
  @convex_width.convex_max_width(poly)
}

///|
pub fn convex_aspect_ratio(poly : Polygon) -> Double {
  @convex_width.convex_aspect_ratio(poly)
}

// ---------------------------------------------------------------------------
// convex_diameter: Convex polygon diameter / 凸多边形直径
// ---------------------------------------------------------------------------

///|
pub fn convex_diameter(poly : Polygon) -> Double {
  @convex_diameter.convex_diameter(poly)
}

///|
pub fn convex_diameter_pair(poly : Polygon) -> (Point2D, Point2D) {
  @convex_diameter.convex_diameter_pair(poly)
} ///|

///|
pub fn convex_radius_lower_bound(poly : Polygon) -> Double {
  @convex_diameter.convex_radius_lower_bound(poly)
}

///|
pub fn antipodal_pairs(poly : Polygon) -> Array[(Int32, Int32)] {
  @convex_diameter.antipodal_pairs(poly)
}

// ---------------------------------------------------------------------------
// convex_center: Convex polygon centers / 凸多边形中心
// ---------------------------------------------------------------------------

///|
pub fn convex_centroid(poly : Polygon) -> Point2D {
  @convex_center.convex_centroid(poly)
}

///|
pub fn chebyshev_center(poly : Polygon) -> Point2D {
  @convex_center.chebyshev_center(poly)
}

///|
pub fn bbox_center(poly : Polygon) -> Point2D {
  @convex_center.bbox_center(poly)
}

///|
pub fn vertex_center(poly : Polygon) -> Point2D {
  @convex_center.vertex_center(poly)
}

///|
pub fn inradius(poly : Polygon) -> Double {
  @convex_center.inradius(poly)
}

// ---------------------------------------------------------------------------
// convex_intersection: Convex polygon intersection / 凸多边形交集
// ---------------------------------------------------------------------------///|

///|
pub fn convex_polygon_intersection(
  poly1 : Polygon,
  poly2 : Polygon,
) -> Array[Point2D] {
  @convex_intersection.convex_polygon_intersection(poly1, poly2)
}

///|
pub fn convex_intersects(poly1 : Polygon, poly2 : Polygon) -> Bool {
  @convex_intersection.convex_polygons_intersect(poly1, poly2)
}

///|
pub fn intersection_area(poly1 : Polygon, poly2 : Polygon) -> Double {
  @convex_intersection.intersection_area(poly1, poly2)
}
// ---------------------------------------------------------------------------
// polygon_skeleton: Straight skeleton / 直骨架
// ---------------------------------------------------------------------------

///|
pub fn straight_skeleton(poly : Polygon) -> Array[Segment] {
  @polygon_skeleton.straight_skeleton(poly)
}

///|
pub fn skeleton_faces(poly : Polygon) -> Array[Array[Point2D]] {
  @polygon_skeleton.skeleton_faces(poly)
}

// ---------------------------------------------------------------------------
// polygon_medial: Medial axis / 中轴线
// ---------------------------------------------------------------------------

///|
pub fn medial_axis(poly : Polygon, resolution : Int32) -> Array[Segment] {
  @polygon_medial.medial_axis(poly, resolution)
}

///|
pub fn medial_axis_points(poly : Polygon, n_samples : Int32) -> Array[Point2D] {
  @polygon_medial.medial_axis_points(poly, n_samples)
}

// ---------------------------------------------------------------------------
// polygon_simplify: Polygon simplification / 多边形简化
// ---------------------------------------------------------------------------///|

///|
pub fn simplify_topology_preserve(
  pts : Array[Point2D],
  eps : Double,
) -> Array[Point2D] {
  @polygon_simplify.simplify_topology_preserve(pts, eps)
}

///|
pub fn simplify_visvalingam(
  pts : Array[Point2D],
  target_count : Int32,
) -> Array[Point2D] {
  @polygon_simplify.simplify_visvalingam(pts, target_count)
}

///|
pub fn douglas_peucker(pts : Array[Point2D], eps : Double) -> Array[Point2D] {
  @polygon_simplify.douglas_peucker(pts, eps)
}

// ---------------------------------------------------------------------------
// polygon_round: Polygon corner rounding / 多边形圆角化
// ---------------------------------------------------------------------------

///|
pub fn round_polygon(
  pts : Array[Point2D],
  radius : Double,
  segments : Int32,
) -> Array[Point2D] {
  @polygon_round.round_polygon(pts, radius, segments)
}

///|
pub fn round_corner(
  p1 : Point2D,
  p2 : Point2D,
  p3 : Point2D,
  radius : Double,
  segments : Int32,
) -> Array[Point2D] {
  @polygon_round.round_corner(p1, p2, p3, radius, segments)
}

// ---------------------------------------------------------------------------
// polygon_evolve: Curve shortening flow / 曲率流
// ---------------------------------------------------------------------------

///|
pub fn curve_shortening_flow(
  pts : Array[Point2D],
  steps : Int32,
  dt : Double,
) -> Array[Array[Point2D]] {
  @polygon_evolve.curve_shortening_flow(pts, steps, dt)
}

///|
pub fn evolve_step(pts : Array[Point2D], dt : Double) -> Array[Point2D] {
  @polygon_evolve.evolve_step(pts, dt)
} ///|

///|
pub fn flow_perimeters(
  pts : Array[Point2D],
  steps : Int32,
  dt : Double,
) -> Array[Double] {
  @polygon_evolve.flow_perimeters(pts, steps, dt)
}

///|
pub fn flow_areas(
  pts : Array[Point2D],
  steps : Int32,
  dt : Double,
) -> Array[Double] {
  @polygon_evolve.flow_areas(pts, steps, dt)
}

// ---------------------------------------------------------------------------
// polygon_morph: Polygon morphing / 多边形变形
// ---------------------------------------------------------------------------

///|
pub fn morph(
  pts1 : Array[Point2D],
  pts2 : Array[Point2D],
  t : Double,
) -> Array[Point2D] {
  @polygon_morph.morph(pts1, pts2, t)
}

///|
pub fn morph_sequence(
  pts1 : Array[Point2D],
  pts2 : Array[Point2D],
  n_steps : Int32,
) -> Array[Array[Point2D]] {
  @polygon_morph.morph_sequence(pts1, pts2, n_steps)
}

///|
pub fn best_alignment(pts1 : Array[Point2D], pts2 : Array[Point2D]) -> Int32 {
  @polygon_morph.best_alignment(pts1, pts2)
}

///|
pub fn morph_aligned(
  pts1 : Array[Point2D],
  pts2 : Array[Point2D],
  t : Double,
) -> Array[Point2D] {
  @polygon_morph.morph_aligned(pts1, pts2, t)
}

// ---------------------------------------------------------------------------
// polygon_decomp_opt: Optimal convex decomposition / 最优凸分解
// ---------------------------------------------------------------------------

///|
pub fn optimal_convex_decomp(pts : Array[Point2D]) -> Array[Array[Point2D]] {
  @polygon_decomp_opt.optimal_convex_decomp(pts)
} ///|

///|
pub fn decomp_count(pts : Array[Point2D]) -> Int32 {
  @polygon_decomp_opt.decomp_count(pts)
}

///|
pub fn is_convex_check(pts : Array[Point2D]) -> Bool {
  @polygon_decomp_opt.is_convex_polygon(pts)
}

// ---------------------------------------------------------------------------
// polygon_triangulate_fast: Fast triangulation / 快速三角剖分
// ---------------------------------------------------------------------------

///|
pub fn fast_triangulate(pts : Array[Point2D]) -> Array[(Int32, Int32, Int32)] {
  @polygon_triangulate_fast.fast_triangulate(pts)
}

///|
pub fn fast_triangulate_points(
  pts : Array[Point2D],
) -> Array[(Point2D, Point2D, Point2D)] {
  @polygon_triangulate_fast.fast_triangulate_points(pts)
}

///|
pub fn triangle_count(pts : Array[Point2D]) -> Int32 {
  @polygon_triangulate_fast.triangle_count(pts)
}

///|
pub fn total_triangle_area(pts : Array[Point2D]) -> Double {
  @polygon_triangulate_fast.total_triangle_area(pts)
}
// ---------------------------------------------------------------------------
// rtree: R-tree / R树
// ---------------------------------------------------------------------------

///|

///|
pub type RTree = @rtree.RTree

///|
pub fn rtree_new(max_entries : Int32) -> RTree {
  @rtree.rtree_new(max_entries)
}

///|
pub fn rtree_insert(tree : RTree, p : Point2D) -> Unit {
  @rtree.rtree_insert(tree, p)
}

///|
pub fn rtree_range_query(
  tree : RTree,
  min_x : Double,
  min_y : Double,
  max_x : Double,
  max_y : Double,
) -> Array[Point2D] {
  @rtree.rtree_range_query(tree, min_x, min_y, max_x, max_y)
}

///|
pub fn rtree_size(tree : RTree) -> Int32 {
  @rtree.rtree_size(tree)
}

///|
pub fn rtree_get_all(tree : RTree) -> Array[Point2D] {
  @rtree.rtree_get_all(tree)
}

// ---------------------------------------------------------------------------
// octree: Octree / 八叉树
// ---------------------------------------------------------------------------

///|
pub type OctreeNode = @octree.OctreeNode

///|
pub fn octree_new(
  cx : Double,
  cy : Double,
  cz : Double,
  size : Double,
  capacity : Int32,
  max_depth : Int32,
) -> OctreeNode {
  @octree.octree_new(cx, cy, cz, size, capacity, max_depth)
} ///|

///|
pub fn octree_insert(node : OctreeNode, p : Point3D) -> Unit {
  @octree.octree_insert(node, p)
}

///|
pub fn octree_range_query(
  node : OctreeNode,
  min_x : Double,
  min_y : Double,
  min_z : Double,
  max_x : Double,
  max_y : Double,
  max_z : Double,
) -> Array[Point3D] {
  @octree.octree_range_query(node, min_x, min_y, min_z, max_x, max_y, max_z)
}

///|
pub fn octree_size(node : OctreeNode) -> Int32 {
  @octree.octree_size(node)
}

// ---------------------------------------------------------------------------
// ball_tree: Ball tree / 球树
// ---------------------------------------------------------------------------

///|
pub type BallNode = @ball_tree.BallNode

///|
pub fn ball_tree_build(points : Array[Point2D]) -> BallNode? {
  @ball_tree.ball_tree_build(points)
}

///|
pub fn ball_tree_knn(
  root : BallNode?,
  query : Point2D,
  k : Int32,
) -> Array[Point2D] {
  @ball_tree.ball_tree_knn(root, query, k)
}

///|
pub fn ball_tree_count(root : BallNode?) -> Int32 {
  @ball_tree.ball_tree_count(root)
}

// ---------------------------------------------------------------------------
// vp_tree: Vantage point tree / 基点树
// ---------------------------------------------------------------------------///|

///|
pub type VPNode = @vp_tree.VPNode

///|
pub fn vp_tree_build(points : Array[Point2D]) -> VPNode? {
  @vp_tree.vp_tree_build(points)
}

///|
pub fn vp_tree_knn(
  root : VPNode?,
  query : Point2D,
  k : Int32,
) -> Array[Point2D] {
  @vp_tree.vp_tree_knn(root, query, k)
}

///|
pub fn vp_tree_count(root : VPNode?) -> Int32 {
  @vp_tree.vp_tree_count(root)
}

// ---------------------------------------------------------------------------
// cover_tree: Cover tree / 覆盖树
// ---------------------------------------------------------------------------

///|
pub type CoverTree = @cover_tree.CoverTree

///|
pub fn cover_tree_build(points : Array[Point2D]) -> CoverTree {
  @cover_tree.cover_tree_build(points)
}

///|
pub fn cover_tree_radius_search(
  tree : CoverTree,
  query : Point2D,
  radius : Double,
) -> Array[Point2D] {
  @cover_tree.cover_tree_radius_search(tree, query, radius)
}

// ========== tolerance ==========

///|
pub type ToleranceCtx = @tolerance.ToleranceCtx

///|
pub fn tolerance_ctx_default() -> ToleranceCtx {
  @tolerance.ToleranceCtx::default()
}

///|
pub fn tolerance_ctx_strict() -> ToleranceCtx {
  @tolerance.ToleranceCtx::strict()
}

///|
pub fn tolerance_ctx_loose() -> ToleranceCtx {
  @tolerance.ToleranceCtx::loose()
}

///|
pub fn tolerance_ctx_custom(dist_tol : Double) -> ToleranceCtx {
  @tolerance.ToleranceCtx::custom(dist_tol)
}

///|
pub fn points_coincide(a : Point2D, b : Point2D, tol : ToleranceCtx) -> Bool {
  @tolerance.points_coincide(a, b, tol)
}

///|
pub fn points_collinear(
  a : Point2D,
  b : Point2D,
  c : Point2D,
  tol : ToleranceCtx,
) -> Bool {
  @tolerance.points_collinear(a, b, c, tol)
}

///|
pub fn orient_with_tol(
  a : Point2D,
  b : Point2D,
  c : Point2D,
  tol : ToleranceCtx,
) -> Int32 {
  @tolerance.orient_with_tol(a, b, c, tol)
}

///|
pub fn is_degenerate_triangle_tol(
  a : Point2D,
  b : Point2D,
  c : Point2D,
  tol : ToleranceCtx,
) -> Bool {
  @tolerance.is_degenerate_triangle(a, b, c, tol)
}

///|
pub fn vectors_parallel(
  v1x : Double,
  v1y : Double,
  v2x : Double,
  v2y : Double,
  tol : ToleranceCtx,
) -> Bool {
  @tolerance.vectors_parallel(v1x, v1y, v2x, v2y, tol)
}

///|
pub fn vectors_perpendicular(
  v1x : Double,
  v1y : Double,
  v2x : Double,
  v2y : Double,
  tol : ToleranceCtx,
) -> Bool {
  @tolerance.vectors_perpendicular(v1x, v1y, v2x, v2y, tol)
}

///|
pub fn snap_to_zero(value : Double, tol : ToleranceCtx) -> Double {
  @tolerance.snap_to_zero(value, tol)
}

///|
pub fn snap_point(
  p : Point2D,
  reference : Point2D,
  tol : ToleranceCtx,
) -> Point2D {
  @tolerance.snap_point(p, reference, tol)
}

// ========== degenerate ==========

///|
pub type DegenerateType = @degenerate.DegenerateType

///|
pub type DegenerateResult = @degenerate.DegenerateResult

///|
pub fn detect_degenerate_points(
  points : Array[Point2D],
  tol : Double,
) -> Array[DegenerateResult] {
  @degenerate.detect_degenerate_points(points, tol)
}

///|
pub fn detect_degenerate_triangles(
  vertices : Array[Point3D],
  faces : Array[(Int32, Int32, Int32)],
  tol : Double,
) -> Array[DegenerateResult] {
  @degenerate.detect_degenerate_triangles(vertices, faces, tol)
}

///|
pub fn detect_self_intersection(
  points : Array[Point2D],
  tol : Double,
) -> Array[DegenerateResult] {
  @degenerate.detect_self_intersection(points, tol)
}

///|
pub fn detect_small_angles(
  points : Array[Point2D],
  angle_tol : Double,
) -> Array[DegenerateResult] {
  @degenerate.detect_small_angles(points, angle_tol)
}

///|
pub fn remove_coincident_points(
  points : Array[Point2D],
  tol : Double,
) -> Array[Point2D] {
  @degenerate.remove_coincident_points(points, tol)
}

// ========== topology_check ==========

///|
pub type TopologyIssue = @topology_check.TopologyIssue

///|
pub type TopologyResult = @topology_check.TopologyResult

///|
pub fn is_closed_manifold(faces : Array[(Int32, Int32, Int32)]) -> Bool {
  @topology_check.is_closed_manifold(faces)
}

///|
pub fn find_nonmanifold_edges(
  faces : Array[(Int32, Int32, Int32)],
) -> Array[TopologyResult] {
  @topology_check.find_nonmanifold_edges(faces)
}

///|
pub fn find_dangling_edges(
  faces : Array[(Int32, Int32, Int32)],
) -> Array[TopologyResult] {
  @topology_check.find_dangling_edges(faces)
}

///|
pub fn find_isolated_vertices(
  num_vertices : Int32,
  faces : Array[(Int32, Int32, Int32)],
) -> Array[TopologyResult] {
  @topology_check.find_isolated_vertices(num_vertices, faces)
}

///|
pub fn validate_topology(
  num_vertices : Int32,
  faces : Array[(Int32, Int32, Int32)],
) -> Array[TopologyResult] {
  @topology_check.validate_topology(num_vertices, faces)
}

// ========== incremental_delaunay ==========

///|
pub type IncrementalDelaunay = @incremental_delaunay.IncrementalDelaunay

///|
pub fn incremental_delaunay_new() -> IncrementalDelaunay {
  @incremental_delaunay.IncrementalDelaunay::new()
}

///|
pub fn incremental_delaunay_from_points(
  points : Array[Point2D],
) -> IncrementalDelaunay {
  @incremental_delaunay.IncrementalDelaunay::from_points(points)
}

///|
pub fn incremental_delaunay_insert(
  d : IncrementalDelaunay,
  p : Point2D,
) -> Unit {
  @incremental_delaunay.IncrementalDelaunay::insert(d, p)
}

///|
pub fn incremental_delaunay_remove(
  d : IncrementalDelaunay,
  index : Int32,
) -> Unit {
  @incremental_delaunay.IncrementalDelaunay::remove(d, index)
}

///|
pub fn incremental_delaunay_triangles(
  d : IncrementalDelaunay,
) -> Array[(Int32, Int32, Int32)] {
  @incremental_delaunay.IncrementalDelaunay::get_triangles(d)
}

///|
pub fn incremental_delaunay_vertices(d : IncrementalDelaunay) -> Array[Point2D] {
  @incremental_delaunay.IncrementalDelaunay::get_vertices(d)
}

// ========== geom_error ==========

///|
pub type GeomError = @geom_error.GeomError

///|
pub fn geom_error_to_message(err : GeomError) -> String {
  @geom_error.GeomError::to_message(err)
}