pub struct Mesh {
pub cells: Vec<Cell>,
pub faces: Vec<Face>,
pub corners: Vec<Corner>,
}Expand description
Oriented native mesh incidence. Face endpoint order is not a spatial sort key.
Fields§
§cells: Vec<Cell>§faces: Vec<Face>§corners: Vec<Corner>Implementations§
Source§impl Mesh
impl Mesh
pub fn validate(&self) -> Result<(), MapError>
Sourcepub fn reconstruct(
&self,
wse: &[f32],
plot_tolerance: f32,
pool: &ThreadPool,
) -> Result<Reconstruction, MapError>
pub fn reconstruct( &self, wse: &[f32], plot_tolerance: f32, pool: &ThreadPool, ) -> Result<Reconstruction, MapError>
Examples found in repository?
examples/sloping_components.rs (line 103)
57fn main() -> Result<(), Box<dyn Error>> {
58 let args: Vec<_> = std::env::args().collect();
59 let path = args
60 .get(1)
61 .ok_or("Expected a native component JSON receipt")?;
62 let threads: usize = args.get(2).map_or(Ok(1), |v| v.parse())?;
63 if !(1..=64).contains(&threads) {
64 return Err("threads must be 1..64".into());
65 }
66 let input: Receipt = serde_json::from_reader(BufReader::new(File::open(path)?))?;
67 let mesh = Mesh {
68 cells: input
69 .cells
70 .iter()
71 .map(|c| Cell {
72 minimum: c.minimum_elevation,
73 virtual_cell: c.virtual_cell,
74 })
75 .collect(),
76 faces: input
77 .faces
78 .iter()
79 .map(|f| Face {
80 cells: f.cells,
81 vertices: f.vertices,
82 minimum: f.minimum_elevation,
83 perimeter: f.perimeter,
84 application: f.application,
85 })
86 .collect(),
87 corners: input
88 .vertices
89 .iter()
90 .map(|v| Corner {
91 point: v.point,
92 faces: v.faces.clone(),
93 ccw: v.ccw.clone(),
94 cw: v.cw.clone(),
95 })
96 .collect(),
97 };
98 let pool = rayon::ThreadPoolBuilder::new()
99 .num_threads(threads)
100 .build()?;
101 let values: Vec<_> = input.cells.iter().map(|c| c.wse).collect();
102 let started = Instant::now();
103 let output = mesh.reconstruct(&values, input.min_ws_plot_tolerance, &pool)?;
104 let seconds = started.elapsed().as_secs_f64();
105 let mut face_mismatches = 0;
106 let mut connection_mismatches = 0;
107 let mut corner_mismatches = 0;
108 let mut local_mismatches = 0;
109 let mut weight_mismatches = 0;
110 let mut paint_mismatches = 0;
111 let mut first = Vec::new();
112 for (i, (actual, expected)) in output.faces.iter().zip(&input.faces).enumerate() {
113 for side in 0..2 {
114 if actual.values[side].to_bits() != expected.values[side].to_bits() {
115 face_mismatches += 1;
116 if first.len() < 10 {
117 first.push(format!(
118 "face {i} side {side}: {} != {}",
119 actual.values[side], expected.values[side]
120 ));
121 }
122 }
123 }
124 if format!("{:?}", actual.connection) != expected.connection {
125 connection_mismatches += 1;
126 }
127 }
128 for (i, (actual, expected)) in output.corners.iter().zip(&input.vertices).enumerate() {
129 if actual.len() != expected.values.len() {
130 return Err("native corner dimension mismatch".into());
131 }
132 for (j, (&a, &b)) in actual.iter().zip(&expected.values).enumerate() {
133 if a.to_bits() != b.to_bits() {
134 corner_mismatches += 1;
135 if first.len() < 10 {
136 first.push(format!("corner {i} slot {j}: {a} != {b}"));
137 }
138 }
139 }
140 }
141 for (i, cell) in input.cells.iter().enumerate() {
142 for (slot, &face_id) in cell.faces.iter().enumerate() {
143 let face = &input.faces[face_id];
144 let vertex = if face.cells[0] == i {
145 face.prev_a
146 } else {
147 face.next_a
148 };
149 let incident = input.vertices[vertex]
150 .faces
151 .iter()
152 .position(|&f| f == face_id)
153 .ok_or("local face not incident to vertex")?;
154 if output.corners[vertex][incident].to_bits() != cell.corner_values[slot].to_bits() {
155 local_mismatches += 1;
156 }
157 }
158 }
159 for sample in &input.pixel_samples {
160 let cell = &input.cells[sample.cell];
161 let vertices: Vec<_> = cell
162 .faces
163 .iter()
164 .map(|&f| {
165 let face = &input.faces[f];
166 if face.cells[0] == sample.cell {
167 face.prev_a
168 } else {
169 face.next_a
170 }
171 })
172 .collect();
173 let points = vertices.iter().map(|&v| input.vertices[v].point).collect();
174 let stencil = PolygonStencil::new(points)?;
175 let mut scratch = WeightScratch::new(vertices.len());
176 let weights = stencil.weights(sample.point, &mut scratch)?;
177 for (&a, &b) in weights.iter().zip(&sample.weights) {
178 if a.to_bits() != b.to_bits() {
179 weight_mismatches += 1;
180 }
181 }
182 let local: Vec<_> = vertices
183 .iter()
184 .zip(&cell.faces)
185 .map(|(&vertex, &face)| {
186 let incident = input.vertices[vertex]
187 .faces
188 .iter()
189 .position(|&f| f == face)
190 .unwrap();
191 output.corners[vertex][incident]
192 })
193 .collect();
194 let value = paint_corner_values(weights, &local)?;
195 if value.to_bits() != sample.wse.to_bits() {
196 paint_mismatches += 1;
197 if first.len() < 10 {
198 first.push(format!(
199 "pixel cell {}: {value} != {}",
200 sample.cell, sample.wse
201 ));
202 }
203 }
204 }
205 println!(
206 "{}",
207 serde_json::json!({
208 "threads": threads, "cells": input.cells.len(), "faces": input.faces.len(),
209 "corners": input.vertices.len(), "seconds": seconds,
210 "face_value_mismatches": face_mismatches, "connection_mismatches": connection_mismatches,
211 "corner_value_mismatches": corner_mismatches, "cell_corner_mismatches": local_mismatches,
212 "pixel_samples": input.pixel_samples.len(), "weight_mismatches": weight_mismatches,
213 "paint_mismatches": paint_mismatches,
214 "first_mismatches": first,
215 "scope": "native Max-profile face and corner reconstruction, not raster qualification",
216 })
217 );
218 if face_mismatches
219 + connection_mismatches
220 + corner_mismatches
221 + local_mismatches
222 + weight_mismatches
223 + paint_mismatches
224 != 0
225 {
226 return Err("sloping component parity failed".into());
227 }
228 Ok(())
229}Auto Trait Implementations§
impl Freeze for Mesh
impl RefUnwindSafe for Mesh
impl Send for Mesh
impl Sync for Mesh
impl Unpin for Mesh
impl UnsafeUnpin for Mesh
impl UnwindSafe for Mesh
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
Converts
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
Converts
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more