1use super::*;
2
3#[derive(Deserialize)]
4pub(crate) struct TangentLoftRequest {
5 pub(crate) sections: Vec<Vec<NurbsCurve>>,
6 pub(crate) start_direction: Vec3,
7 pub(crate) end_direction: Vec3,
8}
9
10#[wasm_bindgen]
11pub fn loft_profile_brep_closed_json(request_json: &str) -> Result<String, JsValue> {
12 let request: LoftBrepRequest = json_in(request_json)?;
13 let solid = loft_profile_brep_closed(&request.sections).map_err(javascript_refusal)?;
14 json_out(&solid)
15}
16
17#[wasm_bindgen]
18pub fn loft_profile_brep_closed_buffer(request_json: &str) -> Result<WasmSolidBuffer, JsValue> {
19 let request: LoftBrepRequest = json_in(request_json)?;
20 let solid = loft_profile_brep_closed(&request.sections).map_err(javascript_refusal)?;
21 solid_buffer(&solid, "{}".into())
22}
23
24#[wasm_bindgen]
25pub fn loft_profile_brep_tangent_json(request_json: &str) -> Result<String, JsValue> {
26 let request: TangentLoftRequest = json_in(request_json)?;
27 let solid = loft_profile_brep_tangent(
28 &request.sections,
29 request.start_direction,
30 request.end_direction,
31 )
32 .map_err(javascript_refusal)?;
33 json_out(&solid)
34}
35
36#[wasm_bindgen]
37pub fn loft_profile_brep_tangent_buffer(request_json: &str) -> Result<WasmSolidBuffer, JsValue> {
38 let request: TangentLoftRequest = json_in(request_json)?;
39 let solid = loft_profile_brep_tangent(
40 &request.sections,
41 request.start_direction,
42 request.end_direction,
43 )
44 .map_err(javascript_refusal)?;
45 solid_buffer(&solid, "{}".into())
46}
47
48#[wasm_bindgen]
49pub fn loft_profile_brep_guided_buffer(request_json: &str) -> Result<WasmSolidBuffer, JsValue> {
50 let request: GuidedLoftRequest = json_in(request_json)?;
51 let solid = guided_loft_dispatch(&request).map_err(javascript_refusal)?;
52 solid_buffer(&solid, "{}".into())
53}
54
55#[wasm_bindgen]
56pub fn sweep_profile_along_path_json(request_json: &str) -> Result<String, JsValue> {
57 let request: SweepRequest = json_in(request_json)?;
58 let solid = sweep_profile_along_path(&request.profile, &request.path, request.name.as_deref())
59 .map_err(javascript_refusal)?;
60 json_out(&solid)
61}
62
63#[wasm_bindgen]
64pub fn sweep_profile_along_path_buffer(request_json: &str) -> Result<WasmSolidBuffer, JsValue> {
65 let request: SweepRequest = json_in(request_json)?;
66 let solid = sweep_profile_along_path(&request.profile, &request.path, request.name.as_deref())
67 .map_err(javascript_refusal)?;
68 solid_buffer(&solid, "{}".into())
69}
70
71#[derive(Deserialize)]
72pub(crate) struct TwistedSweepRequest {
73 pub(crate) profile: Vec<NurbsCurve>,
74 pub(crate) path: NurbsCurve,
75 pub(crate) twist_angle: f64,
77 #[serde(default)]
78 pub(crate) name: Option<String>,
79}
80
81#[wasm_bindgen]
82pub fn sweep_profile_twisted_json(request_json: &str) -> Result<String, JsValue> {
83 let request: TwistedSweepRequest = json_in(request_json)?;
84 let solid = sweep_profile_twisted(
85 &request.profile,
86 &request.path,
87 request.twist_angle,
88 request.name.as_deref(),
89 )
90 .map_err(javascript_refusal)?;
91 json_out(&solid)
92}
93
94#[wasm_bindgen]
95pub fn sweep_profile_twisted_buffer(request_json: &str) -> Result<WasmSolidBuffer, JsValue> {
96 let request: TwistedSweepRequest = json_in(request_json)?;
97 let solid = sweep_profile_twisted(
98 &request.profile,
99 &request.path,
100 request.twist_angle,
101 request.name.as_deref(),
102 )
103 .map_err(javascript_refusal)?;
104 solid_buffer(&solid, "{}".into())
105}
106
107#[wasm_bindgen]
108pub fn sweep_profile_helix_json(request_json: &str) -> Result<String, JsValue> {
109 let request: HelixSweepRequest = json_in(request_json)?;
110 let solid = sweep_profile_helix(
111 &request.profile,
112 request.axis_origin,
113 request.axis_direction,
114 request.helix_radius,
115 request.pitch,
116 request.turns,
117 request.name.as_deref(),
118 )
119 .map_err(javascript_refusal)?;
120 json_out(&solid)
121}
122
123#[wasm_bindgen]
124pub fn sweep_profile_helix_buffer(request_json: &str) -> Result<WasmSolidBuffer, JsValue> {
125 let request: HelixSweepRequest = json_in(request_json)?;
126 let solid = sweep_profile_helix(
127 &request.profile,
128 request.axis_origin,
129 request.axis_direction,
130 request.helix_radius,
131 request.pitch,
132 request.turns,
133 request.name.as_deref(),
134 )
135 .map_err(javascript_refusal)?;
136 solid_buffer(&solid, "{}".into())
137}
138
139#[wasm_bindgen]
140pub fn transform_brep_json(request_json: &str) -> Result<String, JsValue> {
141 let request: TransformBrepRequest = json_in(request_json)?;
142 let transform = AffineTransform::new(request.matrix).map_err(javascript_error)?;
143 let solid = transform_brep(&request.solid, transform, request.reverse_orientation)
144 .map_err(javascript_error)?;
145 json_out(&solid)
146}
147
148#[wasm_bindgen]
149pub fn mirror_brep_json(request_json: &str) -> Result<String, JsValue> {
150 let request: MirrorBrepRequest = json_in(request_json)?;
151 let solid = mirror_brep(&request.solid, request.plane_point, request.plane_normal)
152 .map_err(javascript_error)?;
153 json_out(&solid)
154}
155
156#[wasm_bindgen]
157pub fn mirror_brep_buffer(request_json: &str) -> Result<WasmSolidBuffer, JsValue> {
158 let request: MirrorBrepRequest = json_in(request_json)?;
159 let solid = mirror_brep(&request.solid, request.plane_point, request.plane_normal)
160 .map_err(javascript_error)?;
161 solid_buffer(&solid, "{}".into())
162}
163
164#[wasm_bindgen]
168pub fn split_solid_by_plane_json(request_json: &str) -> Result<String, JsValue> {
169 let request: SplitByPlaneRequest = json_in(request_json)?;
170 let (below, above) =
171 split_solid_by_plane(&request.solid, request.plane_point, request.plane_normal)
172 .map_err(javascript_error)?;
173 let result = serde_json::json!({ "below": below, "above": above });
174 json_out(&result)
175}
176
177#[wasm_bindgen]
183pub fn split_solid_by_surface_json(request_json: &str) -> Result<String, JsValue> {
184 let request: SplitBySurfaceRequest = json_in(request_json)?;
185 let pieces = split_solid_by_surface(&request.solid, &request.tool).map_err(javascript_error)?;
186 let result = serde_json::json!({ "pieces": pieces });
187 json_out(&result)
188}
189
190#[wasm_bindgen]
196pub fn split_solid_by_face_surface_json(request_json: &str) -> Result<String, JsValue> {
197 let request: SplitByFaceSurfaceRequest = json_in(request_json)?;
198 let pieces =
199 split_solid_by_face_surface(&request.solid, &request.surface).map_err(javascript_error)?;
200 let result = serde_json::json!({ "pieces": pieces });
201 json_out(&result)
202}
203
204#[wasm_bindgen]
205pub fn solid_mass_properties_json(solid_json: &str) -> Result<String, JsValue> {
206 let solid: BrepSolid = json_in(solid_json)?;
207 let properties = solid_mass_properties(&solid).map_err(javascript_error)?;
208 json_out(&properties)
209}
210
211#[wasm_bindgen]
212pub fn solid_mass_properties_full_json(solid_json: &str) -> Result<String, JsValue> {
213 let solid: BrepSolid = json_in(solid_json)?;
214 let properties = solid_mass_properties_full(&solid).map_err(javascript_error)?;
215 json_out(&properties)
216}
217
218#[wasm_bindgen]
219pub fn face_metrics_json(face_json: &str) -> Result<String, JsValue> {
220 let face: FaceRecord = json_in(face_json)?;
221 let metrics = FaceMetrics {
222 parameter_space_area: parameter_space_area(&face).map_err(javascript_error)?,
223 area: face_area(&face).map_err(javascript_error)?,
224 volume_contribution: face_volume_contribution(&face).map_err(javascript_error)?,
225 trim_polygons: trim_polygons(&face).map_err(javascript_error)?,
226 };
227 json_out(&metrics)
228}
229
230#[wasm_bindgen]
231pub fn tessellate_face_json(request_json: &str) -> Result<String, JsValue> {
232 let request: TessellateFaceRequest = json_in(request_json)?;
233 let mesh = tessellate_face(
234 &request.face,
235 TessellationOptions {
236 slabs_per_span_u: request.slabs_per_span_u,
237 steps_per_span_v: request.steps_per_span_v,
238 },
239 request.face.id as u32,
240 )
241 .map_err(javascript_error)?;
242 json_out(&mesh)
243}
244
245#[wasm_bindgen]
246pub fn tessellate_brep_json(request_json: &str) -> Result<String, JsValue> {
247 let request: TessellateBrepRequest = json_in(request_json)?;
248 let mesh = tessellate_brep(
249 &request.solid,
250 TessellationOptions {
251 slabs_per_span_u: request.slabs_per_span_u,
252 steps_per_span_v: request.steps_per_span_v,
253 },
254 )
255 .map_err(javascript_error)?;
256 json_out(&mesh)
257}
258
259#[wasm_bindgen]
260pub fn classify_points_json(request_json: &str) -> Result<String, JsValue> {
261 let request: ClassifyPointsRequest = json_in(request_json)?;
262 let classifications = request
263 .points
264 .into_iter()
265 .map(|point| classify_point(point, &request.solid, request.tolerance))
266 .collect::<Result<Vec<_>, _>>()
267 .map_err(javascript_error)?;
268 json_out(&classifications)
269}
270
271#[wasm_bindgen]
272pub fn arrange_segments_json(request_json: &str) -> Result<String, JsValue> {
273 let request: ArrangeSegmentsRequest = json_in(request_json)?;
274 let regions =
275 arrange_segments(&request.segments, request.tolerance).map_err(javascript_error)?;
276 json_out(®ions)
277}
278
279#[wasm_bindgen]
280pub fn build_pcurve_json(request_json: &str) -> Result<String, JsValue> {
281 let request: BuildPcurveRequest = json_in(request_json)?;
282 let pcurve =
283 build_pcurve_on_surface(&request.surface, &request.curve).map_err(javascript_error)?;
284 json_out(&pcurve)
285}
286
287#[wasm_bindgen]
288pub fn build_imprints_json(request_json: &str) -> Result<String, JsValue> {
289 let request: BuildImprintsRequest = json_in(request_json)?;
290 let result = build_imprints(&request.solid_a, &request.solid_b, &request.options)
291 .map_err(javascript_refusal)?;
292 json_out(&result)
293}
294
295#[wasm_bindgen]
296pub fn apply_edge_splits_json(request_json: &str) -> Result<String, JsValue> {
297 let request: ApplyEdgeSplitsRequest = json_in(request_json)?;
298 let result = apply_edge_splits(&request.solid, request.operand, &request.imprint)
299 .map_err(javascript_refusal)?;
300 json_out(&result)
301}
302
303#[wasm_bindgen]
304pub fn fragment_faces_json(request_json: &str) -> Result<String, JsValue> {
305 let request: FragmentFacesRequest = json_in(request_json)?;
306 let result = fragment_solid(&request.solid, request.operand, &request.imprint)
307 .map_err(javascript_refusal)?;
308 json_out(&result)
309}
310
311#[wasm_bindgen]
312pub fn boolean_brep_json(request_json: &str) -> Result<String, JsValue> {
313 let request: BooleanRequest = json_in(request_json)?;
314 let result = boolean_operation(
315 &request.first,
316 &request.second,
317 request.operation,
318 &request.options,
319 )
320 .map_err(javascript_refusal)?;
321 json_out(&result)
322}
323
324#[wasm_bindgen]
325pub fn boolean_brep_diagnostics_json(request_json: &str) -> Result<String, JsValue> {
326 let request: BooleanRequest = json_in(request_json)?;
327 let result = boolean_operation_with_diagnostics(
328 &request.first,
329 &request.second,
330 request.operation,
331 &request.options,
332 )
333 .map_err(javascript_refusal)?;
334 json_out(&result)
335}
336
337#[wasm_bindgen]
338pub fn offset_surface_json(request_json: &str) -> Result<String, JsValue> {
339 let request: OffsetSurfaceRequest = json_in(request_json)?;
340 let surface = offset_surface(&request.face, request.distance, request.planar_extension)
341 .map_err(javascript_refusal)?;
342 json_out(&surface)
343}
344
345#[derive(Deserialize)]
346pub(crate) struct SolveAssemblyRequest {
347 pub(crate) bodies: Vec<AssemblyBody>,
348 pub(crate) mates: Vec<AssemblyMate>,
349 #[serde(default)]
350 pub(crate) options: AssemblySolveOptions,
351}
352
353#[wasm_bindgen]
354pub fn solve_assembly_json(request_json: &str) -> Result<String, JsValue> {
355 let request: SolveAssemblyRequest = json_in(request_json)?;
356 let solution = solve_assembly(&request.bodies, &request.mates, &request.options)
357 .map_err(javascript_error)?;
358 json_out(&solution)
359}
360
361#[derive(Deserialize)]
362pub(crate) struct SegmentMeshRequest {
363 pub(crate) positions: Vec<f64>,
365 #[serde(default)]
367 pub(crate) indices: Vec<u32>,
368 #[serde(default)]
369 pub(crate) options: SegmentOptions,
370}
371
372#[wasm_bindgen]
373pub fn segment_mesh_faces_json(request_json: &str) -> Result<String, JsValue> {
374 let request: SegmentMeshRequest = json_in(request_json)?;
375 let segmentation = segment_mesh_faces(&request.positions, &request.indices, &request.options)
376 .map_err(javascript_error)?;
377 json_out(&segmentation)
378}
379
380#[wasm_bindgen]
381pub fn mesh_regions_to_brep_json(request_json: &str) -> Result<String, JsValue> {
382 let request: SegmentMeshRequest = json_in(request_json)?;
383 let solid = mesh_regions_to_brep(&request.positions, &request.indices, &request.options)
384 .map_err(javascript_error)?;
385 json_out(&solid)
386}
387
388#[wasm_bindgen]
389pub fn mesh_regions_to_brep_buffer(request_json: &str) -> Result<WasmSolidBuffer, JsValue> {
390 let request: SegmentMeshRequest = json_in(request_json)?;
391 let solid = mesh_regions_to_brep(&request.positions, &request.indices, &request.options)
392 .map_err(javascript_error)?;
393 solid_buffer(&solid, "{}".into())
394}
395
396#[derive(Deserialize)]
397pub(crate) struct ThickenSheetRequest {
398 pub(crate) surface: NurbsSurface,
400 pub(crate) thickness: f64,
402 #[serde(default)]
404 pub(crate) symmetric: bool,
405}
406
407#[wasm_bindgen]
408pub fn thicken_face_sheet_json(request_json: &str) -> Result<String, JsValue> {
409 let request: ThickenSheetRequest = json_in(request_json)?;
410 let bodies = thicken_face_sheet(&request.surface, request.thickness, request.symmetric)
411 .map_err(javascript_refusal)?;
412 json_out(&bodies)
413}
414
415#[wasm_bindgen]
416pub fn thicken_face_sheet_buffer(request_json: &str) -> Result<WasmSolidBuffer, JsValue> {
417 let request: ThickenSheetRequest = json_in(request_json)?;
418 let bodies = thicken_face_sheet(&request.surface, request.thickness, request.symmetric)
419 .map_err(javascript_refusal)?;
420 solid_buffer(single_body(&bodies, "thicken_face_sheet")?, "{}".into())
421}
422
423#[derive(Deserialize)]
424pub(crate) struct ThickenTrimmedSheetRequest {
425 pub(crate) surface: NurbsSurface,
426 pub(crate) loops: Vec<Vec<NurbsCurve>>,
429 pub(crate) thickness: f64,
430 #[serde(default)]
431 pub(crate) symmetric: bool,
432}
433
434#[wasm_bindgen]
435pub fn thicken_trimmed_sheet_json(request_json: &str) -> Result<String, JsValue> {
436 let request: ThickenTrimmedSheetRequest = json_in(request_json)?;
437 let bodies = thicken_trimmed_sheet(
438 &request.surface,
439 &request.loops,
440 request.thickness,
441 request.symmetric,
442 )
443 .map_err(javascript_refusal)?;
444 json_out(&bodies)
445}
446
447#[wasm_bindgen]
448pub fn thicken_trimmed_sheet_buffer(request_json: &str) -> Result<WasmSolidBuffer, JsValue> {
449 let request: ThickenTrimmedSheetRequest = json_in(request_json)?;
450 let bodies = thicken_trimmed_sheet(
451 &request.surface,
452 &request.loops,
453 request.thickness,
454 request.symmetric,
455 )
456 .map_err(javascript_refusal)?;
457 solid_buffer(single_body(&bodies, "thicken_trimmed_sheet")?, "{}".into())
458}
459
460fn single_body<'a>(bodies: &'a [BrepSolid], operation: &str) -> Result<&'a BrepSolid, JsValue> {
468 match bodies {
469 [body] => Ok(body),
470 _ => Err(javascript_error(format!(
471 "{operation}: the selected trim thickens into {} bodies and this buffer carries one \
472 — call {operation}_json, which returns them all",
473 bodies.len()
474 ))),
475 }
476}
477
478#[wasm_bindgen]
479pub fn offset_face_carrier_json(request_json: &str) -> Result<String, JsValue> {
480 let request: OffsetFaceCarrierRequest = json_in(request_json)?;
481 let carrier = offset_face_carrier(
482 &request.solid,
483 request.face_id,
484 request.distance,
485 request.planar_extension,
486 )
487 .map_err(javascript_refusal)?;
488 json_out(&carrier)
489}
490
491#[wasm_bindgen]
492pub fn offset_shell_json(request_json: &str) -> Result<String, JsValue> {
493 let request: OffsetShellRequest = json_in(request_json)?;
494 let result = offset_shell(&request.solid, &request.opening_face_ids, request.distance)
495 .map_err(javascript_refusal)?;
496 json_out(&result)
497}
498
499#[wasm_bindgen]
500pub fn offset_shell_diagnostics_json(request_json: &str) -> Result<String, JsValue> {
501 let request: OffsetShellDiagnosticsRequest = json_in(request_json)?;
502 let result = offset_shell_with_diagnostics(
503 &request.solid,
504 &request.opening_face_ids,
505 request.distance,
506 request.tolerances,
507 )
508 .map_err(javascript_refusal)?;
509 json_out(&result)
510}
511
512#[wasm_bindgen]
513pub fn export_step_json(request_json: &str) -> Result<String, JsValue> {
514 let request: ExportStepRequest = json_in(request_json)?;
515 export_step(
516 &request.solids,
517 &request.name,
518 &request.unit,
519 &request.timestamp,
520 )
521 .map_err(javascript_error)
522}
523
524#[wasm_bindgen]
525pub fn merge_curve_continuations_json(request_json: &str) -> Result<String, JsValue> {
526 let request: CoalesceRequest = json_in(request_json)?;
527 let solid = merge_curve_continuation_edges(&request.solid, request.tolerance)
528 .map_err(|refusal| javascript_error(refusal.message))?;
529 json_out(&solid)
530}
531
532#[wasm_bindgen]
533pub fn solve_sketch_json(request_json: &str) -> Result<String, JsValue> {
534 solve_sketch_from_json(request_json).map_err(javascript_error)
535}