Skip to main content

Mesh

Struct Mesh 

Source
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

Source

pub fn validate(&self) -> Result<(), MapError>

Source

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> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

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
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more