1use crate::{
2 make_cylinder_surface, make_line, make_plane, KernelTolerances, NurbsCurve, NurbsSurface, Vec2,
3 Vec3, Vec4,
4};
5use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet};
6use serde::{Deserialize, Serialize};
7
8#[derive(Clone, Debug, Deserialize, Serialize)]
9pub struct VertexRecord {
10 pub id: u64,
11 pub point: Vec3,
12}
13
14#[derive(Clone, Debug, Deserialize, Serialize)]
15pub struct EdgeRecord {
16 pub id: u64,
17 pub curve: NurbsCurve,
18 pub t0: f64,
19 pub t1: f64,
20 pub start_vertex_id: u64,
21 pub end_vertex_id: u64,
22 #[serde(default)]
23 pub degenerate: bool,
24 #[serde(default, skip_serializing_if = "Option::is_none")]
27 pub name: Option<String>,
28}
29
30#[derive(Clone, Debug, Deserialize, Serialize)]
31pub struct CoedgeRecord {
32 pub id: u64,
33 pub edge_id: u64,
34 pub forward: bool,
35 pub pcurve: NurbsCurve,
36}
37
38#[derive(Clone, Debug, Deserialize, Serialize)]
39pub struct LoopRecord {
40 pub id: u64,
41 pub coedges: Vec<CoedgeRecord>,
42}
43
44#[derive(Clone, Debug, Deserialize, Serialize)]
45pub struct FaceRecord {
46 pub id: u64,
47 pub surface: NurbsSurface,
48 pub same_sense: bool,
49 pub loops: Vec<LoopRecord>,
50 #[serde(default, skip_serializing_if = "Option::is_none")]
53 pub name: Option<String>,
54}
55
56#[derive(Clone, Debug, Deserialize, Serialize)]
57pub struct ShellRecord {
58 pub id: u64,
59 pub faces: Vec<FaceRecord>,
60}
61
62#[derive(Clone, Debug, Deserialize, Serialize)]
63pub struct BrepSolid {
64 pub id: u64,
65 pub vertices: Vec<VertexRecord>,
66 pub edges: Vec<EdgeRecord>,
67 pub shells: Vec<ShellRecord>,
68 #[serde(default)]
69 pub genus: i64,
70}
71
72#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
82#[serde(tag = "name", rename_all = "snake_case")]
83pub enum IssueKind {
84 CurveVertexGap { at_start: bool },
86 OpenEdge,
88 OverUsedEdge,
90 GenusMismatch,
92 #[default]
93 Other,
94}
95
96#[derive(Clone, Debug, Deserialize, Serialize)]
97pub struct ValidationIssue {
98 pub severity: &'static str,
99 #[serde(default)]
100 pub kind: IssueKind,
101 pub message: String,
102}
103
104impl ValidationIssue {
105 fn error(message: impl Into<String>) -> Self {
106 Self::error_kind(IssueKind::Other, message)
107 }
108
109 fn error_kind(kind: IssueKind, message: impl Into<String>) -> Self {
110 Self {
111 severity: "error",
112 kind,
113 message: message.into(),
114 }
115 }
116
117 fn warning(message: impl Into<String>) -> Self {
118 Self {
119 severity: "warning",
120 kind: IssueKind::Other,
121 message: message.into(),
122 }
123 }
124}
125
126#[derive(Clone, Debug, Serialize)]
127pub struct ValidationReport {
128 pub issues: Vec<ValidationIssue>,
129 pub wire_warnings: Vec<ValidationIssue>,
130 pub max_pcurve_error: f64,
131}
132
133#[path = "topology/queries.rs"]
134mod queries;
135pub(crate) use queries::{nearest_edge, edge_endpoint_alignment, coedge_neighbor_endpoints, edge_use_counts};
136
137#[path = "topology/seam.rs"]
138mod seam;
139#[path = "topology/validate.rs"]
140mod validate;
141#[path = "topology/primitives.rs"]
142mod primitives;
143pub use seam::{
146 analyze_doubly_periodic_seam_band, loop_seam_offsets, seam_band_uv_polygon, seam_band_uv_polygon_with,
147};
148pub(crate) use seam::doubly_periodic_has_only_collapsed_loops;
149pub(crate) use validate::adaptive_coedge_error;
150pub use primitives::{make_box_brep, make_cylinder_brep, make_pyramid_brep};
151
152