Another project
1use serde::{Deserialize, Serialize};
2
3use crate::{EdgeLabel, FaceLabel, Plane3, Point3, Result, TypesError, UnitVec3, VertexLabel};
4
5#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
6#[serde(deny_unknown_fields)]
7pub struct FaceFingerprint {
8 pub plane: Plane3,
9 pub centroid: Point3,
10}
11
12impl core::fmt::Display for FaceFingerprint {
13 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
14 write!(f, "face@{}", self.centroid)
15 }
16}
17
18#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
19#[serde(deny_unknown_fields)]
20pub struct EdgeFingerprint {
21 pub sample: Point3,
22 pub direction: UnitVec3,
23}
24
25impl core::fmt::Display for EdgeFingerprint {
26 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
27 write!(f, "edge@{}", self.sample)
28 }
29}
30
31#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
32#[serde(deny_unknown_fields)]
33pub struct VertexFingerprint {
34 pub point: Point3,
35}
36
37impl core::fmt::Display for VertexFingerprint {
38 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
39 write!(f, "vertex@{}", self.point)
40 }
41}
42
43#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
44pub enum EntityFingerprint {
45 Face(FaceFingerprint),
46 Edge(EdgeFingerprint),
47 Vertex(VertexFingerprint),
48}
49
50impl core::fmt::Display for EntityFingerprint {
51 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
52 match self {
53 Self::Face(g) => g.fmt(f),
54 Self::Edge(g) => g.fmt(f),
55 Self::Vertex(g) => g.fmt(f),
56 }
57 }
58}
59
60#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
61pub enum EntityRef {
62 Face(FaceLabel, FaceFingerprint),
63 Edge(EdgeLabel, EdgeFingerprint),
64 Vertex(VertexLabel, VertexFingerprint),
65}
66
67impl EntityRef {
68 #[must_use]
69 pub fn fingerprint(self) -> EntityFingerprint {
70 match self {
71 Self::Face(_, g) => EntityFingerprint::Face(g),
72 Self::Edge(_, g) => EntityFingerprint::Edge(g),
73 Self::Vertex(_, g) => EntityFingerprint::Vertex(g),
74 }
75 }
76}
77
78impl core::fmt::Display for EntityRef {
79 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
80 match self {
81 Self::Face(label, _) => label.fmt(f),
82 Self::Edge(label, _) => label.fmt(f),
83 Self::Vertex(label, _) => label.fmt(f),
84 }
85 }
86}
87
88#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
89#[serde(deny_unknown_fields)]
90pub struct FaceRef {
91 pub label: FaceLabel,
92 pub fingerprint: FaceFingerprint,
93}
94
95impl FaceRef {
96 #[must_use]
97 pub const fn new(label: FaceLabel, fingerprint: FaceFingerprint) -> Self {
98 Self { label, fingerprint }
99 }
100
101 #[must_use]
102 pub const fn entity_ref(self) -> EntityRef {
103 EntityRef::Face(self.label, self.fingerprint)
104 }
105}
106
107impl core::fmt::Display for FaceRef {
108 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
109 self.label.fmt(f)
110 }
111}
112
113#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
114#[serde(try_from = "f64", into = "f64")]
115pub struct MatchScore(f64);
116
117impl MatchScore {
118 pub fn new(value: f64) -> Result<Self> {
119 if value.is_finite() && (0.0..=1.0).contains(&value) {
120 Ok(Self(value))
121 } else {
122 Err(TypesError::MatchScoreOutOfRange(value))
123 }
124 }
125
126 #[must_use]
127 pub const fn value(self) -> f64 {
128 self.0
129 }
130}
131
132impl TryFrom<f64> for MatchScore {
133 type Error = TypesError;
134 fn try_from(value: f64) -> Result<Self> {
135 Self::new(value)
136 }
137}
138
139impl From<MatchScore> for f64 {
140 fn from(score: MatchScore) -> Self {
141 score.0
142 }
143}
144
145impl core::fmt::Display for MatchScore {
146 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
147 write!(f, "score={}", self.0)
148 }
149}
150
151#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
152#[serde(deny_unknown_fields)]
153pub enum Resolution<Id> {
154 Resolved(Id),
155 Repaired { id: Id, score: MatchScore },
156 Dangling { last_known: EntityRef },
157}
158
159impl<Id> Resolution<Id> {
160 #[must_use]
161 pub fn id(self) -> Option<Id> {
162 match self {
163 Self::Resolved(id) | Self::Repaired { id, .. } => Some(id),
164 Self::Dangling { .. } => None,
165 }
166 }
167
168 #[must_use]
169 pub fn map<U>(self, f: impl FnOnce(Id) -> U) -> Resolution<U> {
170 match self {
171 Self::Resolved(id) => Resolution::Resolved(f(id)),
172 Self::Repaired { id, score } => Resolution::Repaired { id: f(id), score },
173 Self::Dangling { last_known } => Resolution::Dangling { last_known },
174 }
175 }
176
177 #[must_use]
178 pub const fn is_dangling(&self) -> bool {
179 matches!(self, Self::Dangling { .. })
180 }
181}