1use serde::{Deserialize, Serialize};
2use wasm_bindgen::prelude::*;
3
4pub mod panic_hook;
9
10#[path = "geometry/tolerance.rs"]
11mod tolerance;
12pub use tolerance::{
13 curve_model_scale, model_scale, report_scale_migration, solid_model_scale, solid_scale,
14 offset_construction_band, vertex_tolerance_from_edges, KernelTolerances,
15 MeasuredTolerance, OFFSET_CONSTRUCTION_FLOOR, OFFSET_CONSTRUCTION_REL,
16 VERTEX_MATCH_FLOOR, VOLUME_DRIFT_ABS, VOLUME_DRIFT_REL,
17};
18#[path = "geometry/entity_tolerance.rs"]
23mod entity_tolerance;
24pub use entity_tolerance::{EntityTolerances, EDGE_CAP_FRACTION, VERTEX_CAP_FRACTION};
25#[path = "props/diagnostics.rs"]
26mod diagnostics;
27pub use diagnostics::{
28 DiagnosticEvent, DiagnosticSeverity, KernelDiagnostics, KernelOutcome, KernelRefusal, KernelStage,
29 OrRefuse, RefusalClass,
30};
31#[path = "geometry/polygon.rs"]
32mod polygon;
33#[path = "geometry/curve.rs"]
34mod curve;
35pub use curve::{
36 make_arc, make_circle, make_hyperbola, make_line, make_parabola, uniform_clamped_knots,
37 KnotVector, NurbsCurve, Vec4, KNOT_DEDUP_EPS, KNOT_IDENTITY_TOL,
38};
39#[path = "blending/blend/mod.rs"]
40mod blend;
41pub use blend::{
42 blend_closed_edge, blend_edge_variable, blend_open_edge, blend_smooth_chain,
43 round_convex_corner,
44};
45#[path = "blending/fillet.rs"]
46mod fillet;
47pub use fillet::{
48 chamfer_edge, chamfer_edge_angle, chamfer_edge_asymmetric, chamfer_edges_angle,
49 chamfer_edges_asymmetric, fillet_edge, fillet_edges, fillet_edges_reported,
50 fillet_edges_variable, fillet_edges_variable_law, fillet_edges_variable_vertex_radii,
51 BlendSelection,
52};
53#[path = "blending/law.rs"]
54mod law;
55pub use law::{LawSegment, RadiusLaw};
56#[path = "geometry/fit.rs"]
57mod fit;
58pub use fit::{
59 fit_polyline, fit_polyline_at, interpolate_curve, interpolate_curve_closed,
60 interpolate_curve_local, interpolate_curve_thinned, interpolate_curve_with_end_tangents,
61 simplify_polyline, simplify_polyline_indices, solve_banded, solve_dense, PolylineFit,
62 PolylineFitExit, PolylineFitLedger, PolylineFitReport, PolylineFitScope, MAX_FIT_STATIONS,
63};
64#[path = "geometry/image_curve.rs"]
65mod image_curve;
66pub use image_curve::{affine_image_curve, image_curve, image_curve_pair, ImageCurve, ImageCurveTier};
67#[path = "geometry/surface.rs"]
68mod surface;
69pub use surface::{
70 carrier_preview_patch, make_cone_surface, make_cylinder_surface, make_extrusion, make_plane,
71 make_revolution, make_sphere_surface, make_sphere_surface_framed, make_torus_surface,
72 ExtendRefusal, NurbsSurface, SurfaceSide, WeightSite, MAXIMUM_FOLD_ANGLE,
73 MAXIMUM_GROWTH_RATIO,
74};
75#[path = "geometry/coons.rs"]
76mod coons;
77pub use coons::{
78 coons_bilinear, coons_bilinear_reported, coons_with_ribbons, CompatWork, CoonsRefusal,
79 CoonsReport, RibbonReport,
80};
81#[path = "geometry/gordon.rs"]
82mod gordon;
83pub use gordon::{gordon_surface, gordon_surface_reported, GordonRefusal, GordonReport};
84#[path = "geometry/analytic_surface.rs"]
85mod analytic_surface;
86pub use analytic_surface::{
87 circle_angle_to_parameter, intersect_analytic_pair, plane_ruled_section_arc,
88 revolution_structure, AnalyticSurface, RevolutionFrame, RevolutionStructure,
89};
90pub(crate) use analytic_surface::{
91 intersect_analytic_pair_with, ruled_gate, ruled_gate_census, RuledGate,
92};
93#[path = "geometry/sphere_chart.rs"]
94mod sphere_chart;
95pub use sphere_chart::{
96 canonicalize_points, chart_grid_divisions, chart_grid_parameters, corner_index,
97 cube_edge_corner, cube_edge_divisions, cube_edge_index, cube_edge_parameters,
98 cube_edge_parts, Chart, ChartSegment, ChartSide, SphereAtlas,
99 SphericalRegion, CHART_COUNT, CUBE_CORNER_COUNT, CUBE_EDGE_COUNT,
100};
101#[path = "brep/solid_codec.rs"]
102mod solid_codec;
103pub use solid_codec::{decode_solid, encode_solid, SolidNames, SOLID_CODEC_VERSION};
104#[path = "brep/topology.rs"]
105mod topology;
106pub use topology::{
107 make_box_brep, make_cylinder_brep, make_pyramid_brep, BrepSolid, FaceRecord, IssueKind,
108 ValidationReport,
109};
110#[path = "brep/soundness.rs"]
111mod soundness;
112pub use soundness::{
113 face_self_intersections, loop_self_crossings, shell_vector_areas, solid_connectivity,
114 solid_euler, solid_self_intersections, ConnectivityReport, CrossingConfirmation, EulerReport,
115 FaceCrossing, FaceFold, FaceVectorArea,
116 LoopCrossing, LoopCrossingReport, SelfIntersectionOptions, SelfIntersectionReport,
117 ClosureReading, ShellConnectivity, ShellVectorArea, VectorAreaReport,
118};
119#[path = "brep/topology_arena.rs"]
120mod topology_arena;
121pub use topology_arena::{
122 ArenaCoedge, ArenaEdge, ArenaFace, ArenaLoop, ArenaShell, ArenaVertex, CoedgeId, EdgeId,
123 FaceId, LoopId, ShellId, TopologyArena, VertexId,
124};
125#[path = "brep/analytic_topology.rs"]
126mod analytic_topology;
127pub use analytic_topology::{
128 make_cone_brep, make_sphere_brep, make_sphere_brep_framed, make_torus_brep,
129};
130#[path = "construction/sweep_topology.rs"]
131mod sweep_topology;
132pub use sweep_topology::{
133 extrude_profile_brep, extrude_profile_brep_draft, fit_helix_curve, helix_sample_points,
134 profile_anchor, rib_from_profile, sweep_bend_profile, sweep_closure, BendStation,
135 JointContinuity, PathJoint, SweepClosure,
136 RibExtrusion, RibNames, SweepPath, MAX_JOINT_TANGENT_BREAK, SWEEP_TIGHT_BEND_REFUSAL,
137 SWEEP_TWIST_CLOSURE_REFUSAL,
138 build_swept_envelope, recognize_swept_envelope, swept_envelope_volume, SweptEnvelope,
139 SWEEP_ENVELOPE_REFUSAL, sweep_envelope_bodies,
140 sweep_profile_along_chain, sweep_profile_along_chain_with_stations, sweep_profile_along_path,
141 sweep_profile_along_path_anchored,
142 sweep_profile_helix,
143 sweep_profile_twisted, sweep_profile_twisted_anchored, ProfileAnchor, SectionPlacement,
144};
145#[path = "construction/revolve_topology.rs"]
146mod revolve_topology;
147pub use revolve_topology::{revolve_profile_brep, revolve_profile_brep_named};
148#[path = "construction/loft_topology.rs"]
149mod loft_topology;
150pub use loft_topology::{
151 loft_profile_brep, loft_profile_brep_closed, loft_profile_brep_guided,
152 loft_profile_brep_guided_frame, loft_profile_brep_tangent,
153};
154pub(crate) use loft_topology::loft_profile_brep_closed_shifted;
155#[path = "brep/transform_topology.rs"]
156mod transform_topology;
157pub use transform_topology::{mirror_brep, transform_brep, AffineTransform};
158#[path = "edit/split.rs"]
159mod split;
160pub use split::{
161 split_solid_by_face_surface, split_solid_by_plane, split_solid_by_surface, SplitSurface,
162};
163#[path = "props/mass_properties.rs"]
164mod mass_properties;
165pub use mass_properties::{
166 curve_arc_length, edge_arc_length, face_area, face_boundary_length, face_volume_contribution,
167 face_set_identity, mass_caller, parameter_space_area, solid_edge_length_total,
168 solid_mass_properties,
169 solid_mass_properties_full, solid_signed_volume, trim_polygons, DensityMassProperties,
170 FaceSetIdentity, FullMassProperties, MassCaller, MassProperties,
171};
172#[path = "meshing/tessellation.rs"]
173mod tessellation;
174pub use tessellation::{tessellate_brep, tessellate_face, TessellationOptions};
175#[path = "meshing/watertight_tessellation/mod.rs"]
176mod watertight_tessellation;
177pub use watertight_tessellation::{
178 sample_edge_polylines, sample_edges_encoded, tessellate_brep_watertight,
179 tessellate_brep_watertight_face_stride, tessellate_brep_watertight_face_stride_with_samples,
180};
181#[path = "feature_pipeline/mod.rs"]
186mod feature_pipeline;
187pub use feature_pipeline::execute_history_json;
188pub use feature_pipeline::{first_reference_name, reference_names};
189pub use feature_pipeline::face_transform_pivot;
193pub use feature_pipeline::{
196 clear_history_cache, execute_history, execute_history_observed, AddedSolid, Axis,
197 ComponentRecord, FeatureDescriptor, FeatureResult, Frame, HistoryProgress, HistoryRequest,
198 HistoryResult, PortKind, PortRecord, ProfileLoop, ScenePoint, SketchProfile,
199};
200pub use feature_pipeline::wire_harness::{
204 bundle_diameter, Attachment as SplineAttachment, BundleStatus, PortSide, RouteResult,
205 RouteStatus,
206 WireHarnessBundle, WireHarnessConnection,
207 WireHarnessEndpoint, WireHarnessReport, WireHarnessState, BUNDLE_SOLID_PREFIX,
208 WIRE_HARNESS_FEATURE_ID, WIRE_HARNESS_FEATURE_TYPE,
209};
210pub use feature_pipeline::part_pins::{
215 declarations as declared_ports, declared_endpoints as declared_point_endpoints,
216 declared_points, endpoint_occurrence, follow_pin_edit, follow_point_edit, pin_labels,
217 pin_point_report, pins,
218 point_renames, port_group_for_unit, resolve_component_pin, resolve_part_pin,
219 unit_count as symbol_unit_count, unit_groups, DeclaredPin, DeclaredPoint, PinPoint,
220 PinPointChange, PinPointProblem, PinPointReport, PointRenames, DEFAULT_PORT_NAME,
221 DEFAULT_PORT_PURPOSE, PADS_BLOCK, SYMBOL_BLOCK,
222};
223pub use feature_pipeline::ports::{
228 address as port_address, document_is_boundary, seat_of as port_seat_of, seat_point,
229 seat_vector, seated_direction, split_address, unit_map, unseat_point, unseat_vector,
230 world_seat, PortDeclaration, PortPoint, PortPointRow, PortSeat, PortsReport, UnitProblem,
231 BOUNDARY_KEY, PORTS_BLOCK, PORTS_FEATURE_ID, PORTS_FEATURE_TYPE,
232};
233pub use feature_pipeline::pmi::{
237 clamp_text_size, format_dimension, format_number, pmi_schema_catalogue, pmi_type,
238 resolve_state as pmi_resolve_state, FcfFrame, PmiAnnotation, PmiAnnotationReport, PmiCamera,
239 PmiDisplay, PmiGeometry, PmiPlane, PmiProjection, PmiReport, PmiState, PmiStatus, PmiTypeDef, PmiView,
240 PmiViewReport, ToleranceBlock, ToleranceMode, PMI_TYPES,
241};
242pub use feature_pipeline::pmi::layout::{present as pmi_present, LayoutStyle as PmiLayoutStyle, Presentation as PmiPresentation};
243pub use feature_pipeline::pmi::annotations::fcf::{characteristic as pmi_characteristic, Characteristic as PmiCharacteristic, CHARACTERISTICS as PMI_CHARACTERISTICS};
244pub use feature_pipeline::assign_sketch_loop_ids;
248pub use feature_pipeline::{flat_pattern_dxf, flat_pattern_svg, is_sheet_metal_handle};
250pub use feature_pipeline::{native_import_payload, native_import_payload_with_appearance};
254pub use feature_pipeline::IsolatedSceneMetadata;
257pub use feature_pipeline::scene_metadata_colors_json;
260pub use feature_pipeline::{
263 add_part_to_library, add_part_to_library_impl, install_parts_library, missing_library_parts,
264 parts_library_json, parts_library_map, parts_library_revision, refresh_library_entry,
265 refresh_library_entry_impl, same_build, stable_json_hash, PartsLibraryEntry, PartsLibraryMap,
266};
267pub use feature_pipeline::assembly::{
270 assembly_add_constraint_json, assembly_apply_document_json,
271 assembly_apply_inferred_constraints_json, assembly_dof_json,
272 assembly_infer_constraints_json, assembly_inferable_types_json,
273 assembly_move_constraint_json, assembly_overlay_json, assembly_pose_updates_json,
274 assembly_remove_constraint_json, assembly_run_solve_json,
275 assembly_set_constraint_enabled_json, assembly_set_constraint_open_json,
276 assembly_state_json, assembly_statuses_json, assembly_update_constraint_json,
277 constraint_schema_catalogue,
278 assembly_add_constraint_impl, assembly_apply_document_impl, assembly_move_constraint_impl,
281 assembly_remove_constraint_impl, assembly_run_solve_impl,
282 assembly_set_constraint_enabled_impl, assembly_set_constraint_open_impl,
283 assembly_update_constraint_impl,
284};
285pub use feature_pipeline::{AssemblyState, ConstraintEntry};
286pub use feature_pipeline::assembly::transform_to_pose_params;
289pub use feature_pipeline::feature_schema_catalogue;
292pub use feature_pipeline::feature_hidden_params;
295pub use feature_pipeline::assembly::{constraint_type, ConstraintTypeDef, CONSTRAINT_TYPES};
298pub use feature_pipeline::{feature_context_applicable, SelectionProbe};
299pub use feature_pipeline::Env;
305
306pub fn eval_expression(
311 expressions: &str,
312 configurator_json: &serde_json::Value,
313 source: &str,
314) -> Result<f64, String> {
315 Env::build(expressions, configurator_json).and_then(|env| env.eval(source))
316}
317
318#[cfg(feature = "wasm-threads")]
325pub use wasm_bindgen_rayon::init_thread_pool;
326#[path = "geometry/projection.rs"]
327mod projection;
328pub use projection::{
329 project_point_to_curve, project_point_to_surface, project_point_to_surface_seeded,
330 CurveProjection, SurfaceProjection,
331};
332#[doc(hidden)]
333pub use projection::{
334 project_point_to_surface_basin_census, project_point_to_surface_general_lanes, BasinCensus,
335 GlobalStats,
336};
337#[path = "intersect/curve_surface_intersection.rs"]
338mod curve_surface_intersection;
339pub use curve_surface_intersection::{intersect_curve_surface, CurveSurfaceIntersection};
340#[path = "intersect/curve_curve_intersection.rs"]
341mod curve_curve_intersection;
342pub use curve_curve_intersection::{intersect_curves, CurveCurveIntersection};
343#[path = "intersect/surface_surface_intersection.rs"]
344mod surface_surface_intersection;
345pub use surface_surface_intersection::{
346 intersect_surfaces, intersect_surfaces_supplemental, SurfaceIntersectionCurve,
347 SurfaceIntersectionOptions,
348};
349pub(crate) use surface_surface_intersection::TRANSVERSE_SEED_CROSS;
350#[path = "brep/classification.rs"]
351mod classification;
352pub use classification::{
353 classify_point, containment_lane, horizon_cross_frame, parameter_point_in_face,
354 trim_sample_count, trim_station, ContainmentLane, PointClass, PointClassification,
355 PolygonClass, SolidClassifier, COVERING_RIM_STRIP_SWITCH, HORIZON_CONTAINMENT_SWITCH,
356 HORIZON_CROSS_FRAME_SWITCH, HORIZON_SINGLE_LOOP_SWITCH, NO_SPHERE_CHART_TRIM_SWITCH,
357 SEAM_BAND_MERGED_SWITCH,
358};
359#[doc(hidden)]
360pub use classification::parameter_point_in_face_scan;
361#[path = "geometry/spatial.rs"]
362mod spatial;
363pub use spatial::{Aabb, Bvh};
364#[path = "brep/pair_classification.rs"]
365mod pair_classification;
366pub use pair_classification::{
367 classify_surface_pair, classify_surface_pair_cached, SurfaceClassifyData,
368 SurfacePairClassification, SurfacePairRelation,
369};
370#[path = "intersect/arrangement.rs"]
371mod arrangement;
372pub use arrangement::{
373 arrange_segments, point_in_polygon, segment_intersection, ArrangementPiece, ArrangementRegion,
374 CycleUse, Segment2, Vec2,
375};
376#[path = "geometry/pcurve.rs"]
377mod pcurve;
378pub use pcurve::{
379 build_pcurve_on_surface, build_pcurve_on_surface_marched, build_pcurve_on_surface_range,
380 build_pcurve_on_surface_range_dense, build_pcurve_on_surface_stations, fit_pcurve_on_surface,
381 fit_pcurve_on_surface_marched, PcurveFit, PcurveFitExit, PcurveFitLedger, PcurveFitReport,
382 PcurveFitScope,
383};
384#[path = "csg/imprint.rs"]
385mod imprint;
386pub use imprint::{
387 build_imprints, EdgeSplitRecord, FaceImprints, FaceKey, FacePcurve, ImprintOptions,
388 ImprintPieceRecord, ImprintResultRecord, ImprintVertex,
389};
390#[path = "csg/edge_split.rs"]
391mod edge_split;
392pub use edge_split::{apply_edge_splits, apply_edge_splits_with_map};
393#[path = "csg/fragment.rs"]
394mod fragment;
395pub use fragment::{
396 fragment_face, fragment_solid, FaceFragmentRecord, FragmentCoedge, FragmentEdgeSource,
397 FragmentLoop,
398};
399#[path = "csg/boolean/mod.rs"]
400mod boolean;
401pub use boolean::{
402 boolean_operation, boolean_operation_nary, boolean_operation_with_diagnostics, boolean_split_operands,
403 BooleanOperation, BooleanOptions,
404};
405#[path = "csg/oracle.rs"]
406mod oracle;
407pub use oracle::{
408 boolean_residual_fusables, boolean_semantic_disagreement, boolean_semantic_disagreement_nary,
409 OracleReport, ResidualFusable, ResidualKind, SemanticDisagreement, DISAGREEMENT_THRESHOLD,
410};
411#[path = "healing/heal.rs"]
412mod heal;
413#[path = "healing/accept.rs"]
419mod accept;
420pub use accept::{
421 accept_sound, accept_sound_against, resolve_face_crossing, resolve_face_crossing_between,
422 take_crossing_repairs,
423 CrossingRepairRecord,
424};
425#[path = "offset/point.rs"]
430mod offset_point;
431pub use offset_point::{OffsetEvaluator, OffsetNormal, OffsetSample};
432#[path = "offset/analytic_pair.rs"]
439mod offset_analytic_pair;
440#[path = "offset/retrim.rs"]
447mod offset_retrim;
448#[path = "offset/reintersect.rs"]
456mod offset_reintersect;
457#[path = "offset/measure.rs"]
467mod offset_measure;
468pub use offset_measure::{
469 measure_edge_against_pcurve_image, measure_surface_fit_against_pointwise_offset,
470 span_midpoint_error, vertex_endpoint_gap,
471};
472#[path = "offset/offset.rs"]
473mod offset;
474pub use offset::{
475 offset_face_carrier, offset_face_carrier_measured, offset_face_carrier_sided, offset_surface,
476 offset_surface_measured, offset_surface_measured_sided, CarrierDeviation, CarrierExtension,
477 MeasuredOffsetSurface, OffsetFaceCarrier, OffsetSurfaceLane,
478};
479#[path = "offset/regularity.rs"]
485mod offset_regularity;
486#[path = "offset/fold_locus.rs"]
492mod offset_fold_locus;
493#[path = "offset/carve.rs"]
499mod offset_carve;
500#[path = "offset/thicken.rs"]
501mod thicken;
502pub use thicken::{thicken_face_sheet, thicken_trimmed_sheet};
503#[path = "healing/coalesce.rs"]
504mod coalesce;
505pub use coalesce::{concatenate_exact_curve_pieces, merge_curve_continuation_edges};
506#[path = "healing/face_merge.rs"]
507mod face_merge;
508#[allow(dead_code)]
511#[path = "healing/faceted_repair.rs"]
512mod faceted_repair;
513pub use face_merge::{merge_same_surface_faces, merge_same_surface_faces_excluding};
514pub use faceted_repair::{mesh_to_faceted_brep, repair_triangle_soup, MeshRepairReport};
515#[path = "offset/offset_shell.rs"]
516mod offset_shell;
517pub use offset_shell::{
518 offset_shell, offset_shell_with_diagnostics, OffsetFaceRole, OffsetShellFaceImageRecord,
519 OffsetShellResultRecord,
520};
521#[path = "io/step_matrix.rs"]
522mod step_matrix;
523#[path = "io/step.rs"]
524mod step;
525pub use step::{
526 assembly_export_tree, audit_step_manifold, audit_step_pcurves, export_step,
527 export_step_assembly, export_step_assembly_report, export_step_report,
528 export_step_report_named, Mat4, StepAssemblyExport, StepColors, StepExportOccurrence,
529 StepExportProduct, StepExportReport, StepPmi, PART_ATTRIBUTES, PART_NUMBER,
530};
531#[path = "io/appearance.rs"]
535mod appearance;
536pub use appearance::{BodyAppearance, ImportedColor, COLOR_METADATA_KEY};
537#[path = "io/step_import/mod.rs"]
538mod step_import;
539pub use step_import::{
540 import_step, import_step_report, import_step_trim_readings, import_step_with_appearance,
541 occurrence_ref_parts, read_step_assembly, read_step_pmi, rewrite_occurrence_refs,
542 StepAssembly, StepBodyTrimReadings, StepEdgeReading, StepFaceReading, StepImportReport,
543 StepOccurrence, StepProduct, StepSuppliedTrim, StepTrimReadings, OCCURRENCE_REF_PREFIX,
544 STATED_PRECISION_INCONSISTENCY_RATIO,
545};
546#[doc(hidden)]
548pub fn io_step_text_for_tests(value: &str) -> String {
549 step::pmi::step_text(value)
550}
551#[doc(hidden)]
552pub fn io_step_decode_text_for_tests(value: &str) -> String {
553 step_import::decode_step_text_for_tests(value)
554}
555#[path = "io/iges/mod.rs"]
556mod iges;
557pub use iges::{export_iges, import_iges};
558#[path = "io/mesh_io.rs"]
559mod mesh_io;
560pub use mesh_io::{
561 read_binary_stl, read_obj, write_binary_stl, write_obj, ObjReadResult, StlReadResult,
562};
563#[path = "io/three_mf/mod.rs"]
569mod three_mf;
570pub use three_mf::{
571 read_3mf, ThreeMfError, ThreeMfInstance, ThreeMfMesh, ThreeMfReadResult, ThreeMfUnit,
572};
573#[path = "io/glb.rs"]
577mod glb;
578pub use glb::{write_glb, GlbReport, GlbSolid, GlbUpAxis, GLB_MAGIC};
579#[path = "io/snapshot.rs"]
583mod snapshot;
584pub use snapshot::{
585 restore_solids, snapshot_resident_solids, snapshot_solids, RestoredSnapshot, RestoredSolid,
586 SNAPSHOT_FORMAT_VERSION,
587};
588#[path = "solvers/linear_algebra.rs"]
589mod solver_linear_algebra;
590#[path = "solvers/sketch_solver.rs"]
591mod sketch_solver;
592pub use sketch_solver::{
593 sketch_id_key, solve_sketch, solve_sketch_from_json, SketchSolverSettings, SolveSketchRequest,
594};
595#[path = "solvers/assembly_solver.rs"]
596mod assembly_solver;
597pub use assembly_solver::{
598 solve_assembly, AssemblyBody, AssemblyMate, AssemblySolution, AssemblySolveOptions, BodyPose,
599 MateAlign, MateAxis, MateKind, MatePlane, MateResidualReport, SolveStrategy,
600};
601#[path = "solvers/assembly_resolve.rs"]
605mod assembly_resolve;
606pub use assembly_resolve::{
607 is_component_reference, resolve_component_point, resolve_edge_selection,
608 resolve_face_selection, resolve_named_selection, resolve_vertex_selection,
609 split_component_namespace, ResolveError, SelectionGeometry,
610};
611#[path = "edit/direct_edit.rs"]
612mod direct_edit;
613pub use direct_edit::{
614 delete_face_and_heal, delete_faces_and_heal, move_faces, offset_freeform_face,
615 offset_revolution_face, offset_ruled_face, offset_sphere_face, offset_torus_face,
616 recut_moved_planes, recut_moved_planes_rigid, resolve_face_by_point, rotate_faces,
617 route_reading, RouteReading,
618};
619#[path = "healing/sew.rs"]
620mod sew;
621pub use sew::{sew_solid, split_pinched_vertices, SewReport};
622#[path = "meshing/mesh_weld.rs"]
623mod mesh_weld;
624#[path = "meshing/mesh_segment.rs"]
625mod mesh_segment;
626pub use mesh_segment::{
627 mesh_regions_to_brep, segment_mesh_faces, MeshRegion, MeshSegmentation, RegionCarrier,
628 SegmentOptions, UNASSIGNED_REGION,
629};
630
631#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize)]
632pub struct Vec3 {
633 pub x: f64,
634 pub y: f64,
635 pub z: f64,
636}
637
638impl Vec3 {
639 pub fn new(x: f64, y: f64, z: f64) -> Self {
640 Self { x, y, z }
641 }
642 pub fn sub(self, rhs: Self) -> Self {
643 Self::new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z)
644 }
645 pub fn add(self, rhs: Self) -> Self {
646 Self::new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z)
647 }
648 pub fn scale(self, factor: f64) -> Self {
649 Self::new(self.x * factor, self.y * factor, self.z * factor)
650 }
651 pub fn cross(self, rhs: Self) -> Self {
652 Self::new(
653 self.y * rhs.z - self.z * rhs.y,
654 self.z * rhs.x - self.x * rhs.z,
655 self.x * rhs.y - self.y * rhs.x,
656 )
657 }
658 pub fn dot(self, rhs: Self) -> f64 {
659 self.x * rhs.x + self.y * rhs.y + self.z * rhs.z
660 }
661 pub fn length(self) -> f64 {
662 self.dot(self).sqrt()
663 }
664 pub fn length_squared(self) -> f64 {
665 self.dot(self)
666 }
667 pub fn normalized(self) -> Result<Self, String> {
668 let length = self.length();
669 if length <= 1e-12 {
670 return Err("Vec3.normalized: zero-length vector".into());
671 }
672 Ok(self.scale(1.0 / length))
673 }
674 pub fn perpendicular(self) -> Result<Self, String> {
675 let x = self.x.abs();
676 let y = self.y.abs();
677 let z = self.z.abs();
678 let axis = if x <= y && x <= z {
679 Self::new(1.0, 0.0, 0.0)
680 } else if y <= z {
681 Self::new(0.0, 1.0, 0.0)
682 } else {
683 Self::new(0.0, 0.0, 1.0)
684 };
685 self.cross(axis).normalized()
686 }
687}
688
689#[derive(Clone, Debug, Default, Deserialize, Serialize)]
690pub struct Mesh {
691 pub positions: Vec<f64>,
692 pub normals: Vec<f64>,
693 pub indices: Vec<u32>,
694 pub face_ids: Vec<u32>,
695}
696
697impl Mesh {
698 fn push_vertex(&mut self, point: Vec3, normal: Vec3) -> u32 {
699 self.positions.extend([point.x, point.y, point.z]);
700 self.normals.extend([normal.x, normal.y, normal.z]);
701 (self.positions.len() / 3 - 1) as u32
702 }
703
704 fn quad(&mut self, points: [Vec3; 4], normal: Vec3, face_id: u32) {
705 let base = self.push_vertex(points[0], normal);
706 for point in points.iter().skip(1) {
707 self.push_vertex(*point, normal);
708 }
709 self.indices
710 .extend([base, base + 1, base + 2, base, base + 2, base + 3]);
711 self.face_ids.extend([face_id, face_id]);
712 }
713
714 pub fn signed_volume(&self) -> f64 {
715 self.indices
716 .chunks_exact(3)
717 .map(|tri| {
718 let point = |index: u32| {
719 let i = index as usize * 3;
720 Vec3::new(
721 self.positions[i],
722 self.positions[i + 1],
723 self.positions[i + 2],
724 )
725 };
726 point(tri[0]).dot(point(tri[1]).cross(point(tri[2]))) / 6.0
727 })
728 .sum()
729 }
730
731 pub fn validate(&self) -> Result<(), String> {
732 if self.positions.len() % 3 != 0 || self.normals.len() != self.positions.len() {
733 return Err("invalid vertex or normal buffer".into());
734 }
735 self.validate_geometry()
736 }
737
738 pub fn validate_geometry(&self) -> Result<(), String> {
743 if self.positions.len() % 3 != 0 {
744 return Err("invalid vertex buffer".into());
745 }
746 if self.indices.len() % 3 != 0 {
747 return Err("index buffer is not triangular".into());
748 }
749 let count = self.positions.len() / 3;
750 if self.indices.iter().any(|index| *index as usize >= count) {
751 return Err("index outside vertex buffer".into());
752 }
753 if !self.positions.iter().all(|value| value.is_finite()) {
754 return Err("non-finite vertex".into());
755 }
756 Ok(())
757 }
758}
759
760pub fn make_box(size_x: f64, size_y: f64, size_z: f64) -> Mesh {
761 let x = size_x.abs();
762 let y = size_y.abs();
763 let z = size_z.abs();
764 let p = [
765 Vec3::new(0.0, 0.0, 0.0),
766 Vec3::new(x, 0.0, 0.0),
767 Vec3::new(x, y, 0.0),
768 Vec3::new(0.0, y, 0.0),
769 Vec3::new(0.0, 0.0, z),
770 Vec3::new(x, 0.0, z),
771 Vec3::new(x, y, z),
772 Vec3::new(0.0, y, z),
773 ];
774 let mut mesh = Mesh::default();
775 mesh.quad([p[0], p[3], p[2], p[1]], Vec3::new(0.0, 0.0, -1.0), 0);
776 mesh.quad([p[4], p[5], p[6], p[7]], Vec3::new(0.0, 0.0, 1.0), 1);
777 mesh.quad([p[0], p[1], p[5], p[4]], Vec3::new(0.0, -1.0, 0.0), 2);
778 mesh.quad([p[3], p[7], p[6], p[2]], Vec3::new(0.0, 1.0, 0.0), 3);
779 mesh.quad([p[0], p[4], p[7], p[3]], Vec3::new(-1.0, 0.0, 0.0), 4);
780 mesh.quad([p[1], p[2], p[6], p[5]], Vec3::new(1.0, 0.0, 0.0), 5);
781 mesh
782}
783
784pub fn make_cylinder(radius: f64, height: f64, segments: usize) -> Mesh {
785 let radius = radius.abs();
786 let height = height.abs();
787 let segments = segments.max(3);
788 let mut mesh = Mesh::default();
789 for i in 0..segments {
790 let a = std::f64::consts::TAU * i as f64 / segments as f64;
791 let b = std::f64::consts::TAU * (i + 1) as f64 / segments as f64;
792 let (sa, ca) = a.sin_cos();
793 let (sb, cb) = b.sin_cos();
794 let pa = Vec3::new(radius * ca, 0.0, -radius * sa);
795 let pb = Vec3::new(radius * cb, 0.0, -radius * sb);
796 let ta = Vec3::new(pa.x, height, pa.z);
797 let tb = Vec3::new(pb.x, height, pb.z);
798 mesh.quad(
799 [pa, pb, tb, ta],
800 Vec3::new((ca + cb) * 0.5, 0.0, -(sa + sb) * 0.5),
801 0,
802 );
803 let bottom = mesh.push_vertex(Vec3::default(), Vec3::new(0.0, -1.0, 0.0));
804 let bi = mesh.push_vertex(pb, Vec3::new(0.0, -1.0, 0.0));
805 let bj = mesh.push_vertex(pa, Vec3::new(0.0, -1.0, 0.0));
806 mesh.indices.extend([bottom, bi, bj]);
807 mesh.face_ids.push(1);
808 let top = mesh.push_vertex(Vec3::new(0.0, height, 0.0), Vec3::new(0.0, 1.0, 0.0));
809 let ti = mesh.push_vertex(ta, Vec3::new(0.0, 1.0, 0.0));
810 let tj = mesh.push_vertex(tb, Vec3::new(0.0, 1.0, 0.0));
811 mesh.indices.extend([top, ti, tj]);
812 mesh.face_ids.push(2);
813 }
814 mesh
815}
816
817
818mod abi;
819pub use abi::*;
820