Skip to content

Commit

Permalink
Move update metrics out of app.rs
Browse files Browse the repository at this point in the history
  • Loading branch information
basyniae committed Oct 26, 2024
1 parent 60a7af2 commit bccff16
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 103 deletions.
110 changes: 19 additions & 91 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,16 @@ use eframe::emath::Align;
use mlua::Lua;

use crate::app::data_structures::sampled_parameters::SampledParameters;
use crate::app::math::exact_squircle_bounds::exact_squircle_bounds;
use crate::app::math::square_max::square_max;
use crate::app::sampling::{SampleCombineMethod, SampleDistributeMethod};
use crate::app::ui_layer_navigation::ui_layer_navigation;
use crate::app::ui_sampling::ui_sampling;
use crate::app::ui_viewport::ui_viewport;
use crate::app::update_logic::{blocks_update, parameters_update, sampling_points_update};
use crate::app::update_metrics::update_metrics;
use data_structures::blocks::Blocks;
use data_structures::layer_config::LayerConfig;
use data_structures::zvec::ZVec;
use lua_field::LuaField;
use math::convex_hull::get_convex_hull;
use metrics::boundary_3d::boundary_3d;

mod colors;
mod data_structures;
Expand All @@ -36,6 +33,7 @@ mod ui_options;
mod ui_sampling;
mod ui_viewport;
mod update_logic;
mod update_metrics;

pub struct App {
// Layer management
Expand Down Expand Up @@ -469,95 +467,25 @@ impl eframe::App for App {

if self.recompute_metrics {
self.recompute_metrics = false;

// update 2d spatial metrics
self.interior_2d = self
.stack_blocks
.get(self.current_layer)
.unwrap()
.get_interior();
self.boundary_2d = Blocks::new(
// boundary is in all but not in interior (so all && interior.not())
self.stack_blocks
.get(self.current_layer)
.unwrap()
.blocks
.iter()
.zip(self.interior_2d.blocks.iter())
.map(|(all, interior)| *all && !interior)
.collect(),
self.interior_2d.grid_size,
);
self.complement_2d = self
.stack_blocks
.get(self.current_layer)
.unwrap()
.get_complement();

// update 3d spatial metrics
self.boundary_3d = boundary_3d(
&self.stack_blocks,
update_metrics(
self.current_layer,
self.layer_lowest,
self.layer_highest,
true,
true,
);

self.interior_3d = ZVec::new(
(self.layer_lowest..self.layer_highest)
.map(|layer| {
Blocks::new(
self.boundary_3d
.get(layer)
.unwrap()
.blocks
.iter()
.zip(self.stack_blocks.get(layer).unwrap().blocks)
.map(|(is_bdry, is_block)| is_block && !is_bdry)
.collect(),
self.stack_blocks.get(layer).unwrap().grid_size,
)
})
.collect(),
self.layer_lowest,
);

// update numerical metrics
self.nr_blocks_total = self
.stack_blocks
.get_mut(self.current_layer)
.unwrap()
.get_nr_blocks();
self.nr_blocks_interior = self.interior_2d.get_nr_blocks();
self.nr_blocks_boundary = self.boundary_2d.get_nr_blocks();

self.outer_corners = self
.stack_blocks
.get_mut(self.current_layer)
.unwrap()
.get_outer_corners();
self.convex_hull = get_convex_hull(&self.outer_corners);

self.global_bounding_box = self
.stack_layer_config
.data
.iter()
.map(|g_c| exact_squircle_bounds(g_c, 1.1))
.fold(
[
[f64::INFINITY, f64::INFINITY],
[f64::NEG_INFINITY, f64::NEG_INFINITY],
],
|a, b| square_max(a, b),
);

self.global_bounding_box = square_max(
self.global_bounding_box,
exact_squircle_bounds(
&self.stack_layer_config.get(self.current_layer).unwrap(),
1.1,
),
);
self.stack_blocks.get(self.current_layer).unwrap(),
self.stack_blocks.clone(),
self.stack_layer_config.clone(),
&mut self.nr_blocks_total,
&mut self.nr_blocks_interior,
&mut self.nr_blocks_boundary,
&mut self.boundary_2d,
&mut self.interior_2d,
&mut self.complement_2d,
&mut self.boundary_3d,
&mut self.interior_3d,
&mut self.convex_hull,
&mut self.outer_corners,
&mut self.global_bounding_box,
)
}

// Status bar (bottom)
Expand Down
46 changes: 36 additions & 10 deletions src/app/data_structures/blocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub struct Blocks {
// TODO: make intersect and complement methods for easier computation
// longterm: Symmetry type detection, then build sequences should be within reach
// TODO: make everything use is_block_on_global_coord
/// Getter methods
impl Blocks {
pub fn new(blocks: Vec<bool>, grid_size: usize) -> Self {
Blocks {
Expand Down Expand Up @@ -81,7 +82,10 @@ impl Blocks {

output_vec
}
}

/// Methods for getting metrics
impl Blocks {
/// Get number of blocks
pub fn get_nr_blocks(&self) -> u64 {
(*self.blocks).into_iter().filter(|b| **b).count() as u64
Expand All @@ -90,8 +94,6 @@ impl Blocks {
/// Get (thin-walled) interior, i.e., blocks in self which have no neighbors which share a side
/// with an air block
pub fn get_interior(&self) -> Blocks {
// let mut output_vec = Vec::new();

Blocks::new(
(0..self.grid_size.pow(2))
.map(|i| {
Expand All @@ -102,19 +104,43 @@ impl Blocks {
&& i / self.grid_size != 0
&& i / self.grid_size != self.grid_size - 1
// cannot lie on the boundary of the grid
&& self.blocks[i + 1] == true
&& self.blocks[i - 1] == true
&& self.blocks[i + self.grid_size] == true
&& self.blocks[i - self.grid_size] == true
&& self.blocks[i + 1]
&& self.blocks[i - 1]
&& self.blocks[i + self.grid_size]
&& self.blocks[i - self.grid_size]
// all direct neighbors should also be blocks
})
.collect(),
self.grid_size,
)
}

// todo: make direct methods for layer boundary and interior
/// Complement of blocks (for interiors)
/// Get (thin-walled) boundary
/// (There is the obvious relation of boundary + interior = blocks, but we won't use it)
pub fn get_boundary(&self) -> Blocks {
Blocks::new(
(0..self.grid_size.pow(2))
.map(|i| {
self.blocks[i] == true
// has to be a block
// and (be on the grid boundary or border any non-block)
&& (
i % self.grid_size == 0
|| i % self.grid_size == self.grid_size - 1
|| i / self.grid_size == 0
|| i / self.grid_size == self.grid_size - 1
|| !self.blocks[i + 1]
|| !self.blocks[i - 1]
|| !self.blocks[i + self.grid_size]
|| !self.blocks[i - self.grid_size]
)
})
.collect(),
self.grid_size,
)
}

/// Complement of blocks (for building interiors)
pub fn get_complement(&self) -> Blocks {
Blocks::new(
(0..self.grid_size.pow(2))
Expand Down Expand Up @@ -216,15 +242,15 @@ impl Blocks {

// Returns a (unordered) list of all corners of the blocks (so get_block_coords (±0.5,±0.5))
// which are the corner of exactly 1 block (note that exactly 2 blocks corresponds to a corner
// which is an edge of the whole block structure, and exactly 2 blocks correponds to an inner corner)
// which is an edge of the whole block structure, and exactly 2 blocks corresponds to an inner corner)
// The convex hull only depends on points of this type (so it should be a large reduction).
pub fn get_outer_corners(&self) -> Vec<[f64; 2]> {
// loop over all 2x2s in the grid, which we think of as points between the blocks
// then count the number of blocks

let mut output = vec![];

// For an n×n grid there are (n-1)×(n-1) points inbetween 4 points... (vaguely speaking)
// For an n×n grid there are (n-1)×(n-1) points between 4 points... (vaguely speaking)
for corner_point in 0..self.grid_size.pow(2) {
// Filter out those corner points which don't have a 2×2 around them
// (using bottom right index to match corners to their block)
Expand Down
2 changes: 1 addition & 1 deletion src/app/data_structures/zvec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::collections::VecDeque;
use std::fmt::Debug;

/// Vector whose index is a continuous interval of the integers (Z)
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct ZVec<T> {
pub data: VecDeque<T>,
minimum: isize,
Expand Down
2 changes: 1 addition & 1 deletion src/app/metrics/boundary_3d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub fn boundary_3d(
|| !blocks.blocks[i - 1]
|| !blocks.blocks[i + blocks.grid_size]
|| !blocks.blocks[i - blocks.grid_size]
// top and bottom faces of stack: (
// top and bottom faces of stack:
|| (layer == layer_min && floating_bottom)
|| (layer == layer_max && floating_top)
// vertical boundary: see if 1. the layer above exists, 2. there is no block at the global coords on the layer above
Expand Down
88 changes: 88 additions & 0 deletions src/app/update_metrics.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use crate::app;
use crate::app::data_structures::blocks::Blocks;
use crate::app::data_structures::layer_config::LayerConfig;
use crate::app::data_structures::zvec::ZVec;
use crate::app::math::exact_squircle_bounds::exact_squircle_bounds;
use crate::app::math::square_max::square_max;

pub fn update_metrics(
current_layer: isize,
layer_lowest: isize,
layer_highest: isize,
current_layer_blocks: Blocks,
stack_blocks: ZVec<Blocks>,
stack_layer_config: ZVec<LayerConfig>,

// Metrics
nr_blocks_total: &mut u64,
nr_blocks_interior: &mut u64,
nr_blocks_boundary: &mut u64,
boundary_2d: &mut Blocks,
interior_2d: &mut Blocks,
complement_2d: &mut Blocks,
boundary_3d: &mut ZVec<Blocks>,
interior_3d: &mut ZVec<Blocks>,
convex_hull: &mut Vec<[f64; 2]>,
outer_corners: &mut Vec<[f64; 2]>,

global_bounding_box: &mut [[f64; 2]; 2],
) {
// update 2d spatial metrics
*interior_2d = current_layer_blocks.get_interior();
*boundary_2d = current_layer_blocks.get_boundary();
*complement_2d = current_layer_blocks.get_complement();

// update 3d spatial metrics
*boundary_3d = app::metrics::boundary_3d::boundary_3d(
&stack_blocks,
layer_lowest,
layer_highest,
true,
true,
);

// todo: move computation to boundary_3d.rs
*interior_3d = ZVec::new(
(layer_lowest..layer_highest)
.map(|layer| {
Blocks::new(
boundary_3d
.get(layer)
.unwrap()
.blocks
.iter()
.zip(stack_blocks.get(layer).unwrap().blocks)
.map(|(is_bdry, is_block)| is_block && !is_bdry)
.collect(),
stack_blocks.get(layer).unwrap().grid_size,
)
})
.collect(),
layer_lowest,
);

// update numerical metrics
*nr_blocks_total = current_layer_blocks.get_nr_blocks();
*nr_blocks_interior = interior_2d.get_nr_blocks();
*nr_blocks_boundary = boundary_2d.get_nr_blocks();

*outer_corners = current_layer_blocks.get_outer_corners();
*convex_hull = app::math::convex_hull::get_convex_hull(&outer_corners);

*global_bounding_box = stack_layer_config
.data
.iter()
.map(|g_c| exact_squircle_bounds(g_c, 1.1))
.fold(
[
[f64::INFINITY, f64::INFINITY],
[f64::NEG_INFINITY, f64::NEG_INFINITY],
],
|a, b| square_max(a, b),
);

*global_bounding_box = square_max(
*global_bounding_box,
exact_squircle_bounds(&stack_layer_config.get(current_layer).unwrap(), 1.1),
);
}

0 comments on commit bccff16

Please sign in to comment.