1use serde::{Deserialize, Serialize};
2use wasm_bindgen::prelude::*;
3
4#[wasm_bindgen(typescript_custom_section)]
5const TS_APPEND_CONTENT: &str = r#"
6export interface ProtocolConfig {
7 max_parts: number;
8 max_vertices_per_part: number;
9 min_edge_length_squared: bigint;
10 min_compactness_ppm: bigint;
11 area_divisor: bigint;
12}
13
14export type PolygonRing = bigint[];
15export type PolygonParts = PolygonRing[];
16
17export type DecomposeStrategy =
18 | "AlreadyConvex"
19 | "ExactPartition"
20 | "Bayazit"
21 | "EarClipMerge"
22 | { Rotation: { offset: number; inner: DecomposeStrategy } };
23
24export type DecomposeOutcome =
25 | { Success: { part_count: number } }
26 | { "TooManyParts": { count: number } }
27 | { ValidationFailed: { errors: string[] } }
28 | { AlgorithmFailed: { error: string } };
29
30export interface DecomposeAttempt {
31 strategy: DecomposeStrategy;
32 rotation: number;
33 outcome: DecomposeOutcome;
34}
35
36export interface DecomposeResult {
37 parts: PolygonParts;
38 steiner_points: PolygonRing;
39 strategy: DecomposeStrategy;
40 trace?: DecomposeAttempt[];
41}
42
43export interface ValidationCheck {
44 name: string;
45 passed: boolean;
46 detail: string;
47 severity: "ok" | "warn" | "error";
48}
49
50export interface ValidationReport {
51 checks: ValidationCheck[];
52 valid: boolean;
53 error_count: number;
54 warn_count: number;
55 original_twice_area: string;
56 parts_twice_area_sum: string;
57 part_areas: string[];
58}
59
60export interface IndexPair {
61 a_index: number;
62 b_index: number;
63}
64
65export type TopologyError =
66 | { NotConnected: { disconnected_parts: number[] } }
67 | { HasHoles: { boundary_components: number } }
68 | { VertexOnlyContact: { part_a: number; part_b: number } }
69 | { UnsupportedContact: { part_a: number; part_b: number; reason: string } }
70 | { "TooManyParts": { count: number; max: number } }
71 | { NotCompact: { compactness_ppm: bigint; min_ppm: bigint } };
72
73export function area_display_from_twice_area(twice_area: string, config?: ProtocolConfig | null): bigint;
74export function areas_conserved_values(original: string, part_areas: string[]): boolean;
75export function bayazit_decompose_polygon(ring_flat: BigInt64Array, allow_steiner: boolean): PolygonParts;
76export function collect_steiner_points(ring_flat: BigInt64Array, parts_flat: PolygonParts): PolygonRing;
77export function contains_polygon(outer_parts_flat: PolygonParts, inner_parts_flat: PolygonParts): boolean;
78export function decompose_polygon(ring_flat: BigInt64Array, allow_steiner: boolean, collect_trace?: boolean | null, minimize_parts?: boolean | null, config?: ProtocolConfig | null): DecomposeResult;
79export function ear_clip_triangulate_polygon(ring_flat: BigInt64Array): PolygonParts;
80export function ensure_ccw(ring_flat: BigInt64Array): PolygonRing;
81export function exact_partition_only_original_vertices(ring_flat: BigInt64Array, parts_flat: PolygonParts): boolean;
82export function exact_vertex_partition_polygon(ring_flat: BigInt64Array): PolygonParts;
83export function find_overlapping_parts(a_parts_flat: PolygonParts, b_parts_flat: PolygonParts): IndexPair[];
84export function merge_convex_pair(a_flat: BigInt64Array, b_flat: BigInt64Array): PolygonRing | undefined;
85export function normalize_polygon(ring_flat: BigInt64Array): PolygonRing | undefined;
86export function optimize_partition(parts_flat: PolygonParts): PolygonParts;
87export function parts_overlap(a_parts_flat: PolygonParts, b_parts_flat: PolygonParts): boolean;
88export function point_inside_any_part(parts_flat: PolygonParts, x: bigint, y: bigint): boolean;
89export function remove_collinear(ring_flat: BigInt64Array): PolygonRing;
90export function rotate_polygon(ring_flat: BigInt64Array, start: number): PolygonRing;
91export function validate_compactness(twice_area: string, perimeter: string, config?: ProtocolConfig | null): string | undefined;
92export function validate_decomposition(ring_flat: BigInt64Array, parts_flat: PolygonParts, config?: ProtocolConfig | null): ValidationReport;
93export function validate_edge_lengths(ring_flat: BigInt64Array, config?: ProtocolConfig | null): string | undefined;
94export function validate_multipart_topology(parts_flat: PolygonParts, allow_vertex_contact?: boolean | null, config?: ProtocolConfig | null): TopologyError | undefined;
95export function validate_part(ring_flat: BigInt64Array, config?: ProtocolConfig | null): string | undefined;
96"#;
97
98#[derive(Serialize, Deserialize)]
99pub struct WasmDecomposeResult {
100 pub parts: Vec<Vec<i64>>,
101 pub steiner_points: Vec<i64>,
102 pub strategy: crate::types::Strategy,
103 #[serde(skip_serializing_if = "Option::is_none")]
104 pub trace: Option<Vec<crate::types::Attempt>>,
105}
106
107#[derive(Serialize, Deserialize)]
108pub struct WasmIndexPair {
109 pub a_index: usize,
110 pub b_index: usize,
111}