Skip to content

Commit

Permalink
refactor!(core): update the builder structure API (#296)
Browse files Browse the repository at this point in the history
* restructure builder

* fix errors

* other fixes
  • Loading branch information
imrn99 authored Mar 6, 2025
1 parent 3687a7c commit 8c241c2
Show file tree
Hide file tree
Showing 19 changed files with 112 additions and 114 deletions.
8 changes: 4 additions & 4 deletions benches/benches/core/cmap2/basic_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ fn get_sparse_map(n_square: usize) -> CMap2<FloatType> {

fn get_empty_map(n_squares: usize) -> (CMap2<FloatType>, usize) {
(
CMapBuilder::default().build().unwrap(),
CMapBuilder::from_n_darts(0).build().unwrap(),
n_squares.pow(2) * 4,
)
}
Expand Down Expand Up @@ -85,9 +85,9 @@ fn insert_dart_full(map: &mut CMap2<FloatType>) -> DartIdType {
}

#[library_benchmark]
#[bench::small(&mut CMapBuilder::default().n_darts(16_usize.pow(2) * 4).build().unwrap())]
#[bench::medium(&mut CMapBuilder::default().n_darts(64_usize.pow(2) * 4).build().unwrap())]
#[bench::large(&mut CMapBuilder::default().n_darts(256_usize.pow(2) * 4).build().unwrap())]
#[bench::small(&mut CMapBuilder::from_n_darts(16_usize.pow(2) * 4).build().unwrap())]
#[bench::medium(&mut CMapBuilder::from_n_darts(64_usize.pow(2) * 4).build().unwrap())]
#[bench::large(&mut CMapBuilder::from_n_darts(256_usize.pow(2) * 4).build().unwrap())]
fn remove_dart(map: &mut CMap2<FloatType>) {
map.remove_free_dart(5);
black_box(map);
Expand Down
3 changes: 1 addition & 2 deletions benches/benches/core/cmap2/constructors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ fn get_map(n_square: usize) -> CMap2<FloatType> {
#[benches::with_setup(args = [16, 32, 64, 128, 256, 512])]
fn new(n_squares: usize) -> CMap2<FloatType> {
black_box(
CMapBuilder::default()
.n_darts(n_squares.pow(2) * 4)
CMapBuilder::from_n_darts(n_squares.pow(2) * 4)
.build()
.unwrap(),
)
Expand Down
6 changes: 2 additions & 4 deletions benches/benches/core/cmap2/link_and_sew.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,13 @@ fn get_map(n_square: usize) -> CMap2<FloatType> {
}

fn get_link_map(n_square: usize) -> CMap2<FloatType> {
CMapBuilder::default()
.n_darts(n_square.pow(2) * 4)
CMapBuilder::from_n_darts(n_square.pow(2) * 4)
.build()
.unwrap()
}

fn get_sew_map(n_square: usize) -> CMap2<FloatType> {
let map = CMapBuilder::default()
.n_darts(n_square.pow(2) * 4)
let map = CMapBuilder::from_n_darts(n_square.pow(2) * 4)
.build()
.unwrap();
map.force_write_vertex(4, (0.0, 0.0));
Expand Down
4 changes: 2 additions & 2 deletions benches/benches/triangulate/quads.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use honeycomb_benches::utils::FloatType;
const PATH: &str = "../examples/quads.vtk";

fn fan_bench() -> Result<(), TriangulateError> {
let mut map: CMap2<FloatType> = CMapBuilder::default().vtk_file(PATH).build().unwrap();
let mut map: CMap2<FloatType> = CMapBuilder::from_vtk_file(PATH).build().unwrap();

// prealloc darts
let faces: Vec<_> = map.iter_faces().collect();
Expand Down Expand Up @@ -43,7 +43,7 @@ fn fan_bench() -> Result<(), TriangulateError> {
}

fn earclip_bench() -> Result<(), TriangulateError> {
let mut map: CMap2<FloatType> = CMapBuilder::default().vtk_file(PATH).build().unwrap();
let mut map: CMap2<FloatType> = CMapBuilder::from_vtk_file(PATH).build().unwrap();

// prealloc darts
let faces: Vec<_> = map.iter_faces().collect();
Expand Down
4 changes: 2 additions & 2 deletions benches/src/cut_edges.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ pub fn bench_cut_edges<T: CoordsFloat>(args: CutEdgesArgs) -> CMap2<T> {
let input_hash = hash_file(input_map).expect("E: could not compute input hash"); // file id for posterity

let mut map: CMap2<T> = if input_map.ends_with(".cmap") {
CMapBuilder::default().cmap_file(input_map).build().unwrap()
CMapBuilder::from_cmap_file(input_map).build().unwrap()
} else if input_map.ends_with(".vtk") {
CMapBuilder::default().vtk_file(input_map).build().unwrap()
CMapBuilder::from_vtk_file(input_map).build().unwrap()
} else {
panic!(
"E: Unknown file format; only .cmap or .vtk files are supported for map initialization"
Expand Down
4 changes: 3 additions & 1 deletion benches/src/grid_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ pub fn bench_generate_2d_grid<T: CoordsFloat>(args: Generate2dGridArgs) -> CMap2
.len_per_cell_y(T::from(args.ly).unwrap())
.split_quads(args.split.is_some_and(|s| s == Split::Uniform));

let mut map = CMapBuilder::from(descriptor).build().unwrap();
let mut map = CMapBuilder::from_grid_descriptor(descriptor)
.build()
.unwrap();

if args.split.is_some_and(|s| s == Split::Random) {
// fixed probability and seed value from the original binary
Expand Down
4 changes: 2 additions & 2 deletions benches/src/shift.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ pub fn bench_shift<T: CoordsFloat>(args: ShiftArgs) -> CMap2<T> {
let input_map = args.input.to_str().unwrap();
let input_hash = hash_file(input_map).unwrap();
let map: CMap2<T> = if input_map.ends_with(".cmap") {
CMapBuilder::default().cmap_file(input_map).build().unwrap()
CMapBuilder::from_cmap_file(input_map).build().unwrap()
} else if input_map.ends_with(".vtk") {
CMapBuilder::default().vtk_file(input_map).build().unwrap()
CMapBuilder::from_vtk_file(input_map).build().unwrap()
} else {
panic!(
"E: Unknown file format; only .cmap or .vtk files are supported for map initialization"
Expand Down
2 changes: 1 addition & 1 deletion examples/examples/io/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ fn main() {
let args: Vec<String> = env::args().collect();

if let Some(path) = args.get(1) {
let map: CMap2<f32> = match CMapBuilder::default().vtk_file(path).build() {
let map: CMap2<f32> = match CMapBuilder::from_vtk_file(path).build() {
Ok(cmap) => cmap,
Err(e) => panic!("Error while building map: {e:?}"),
};
Expand Down
21 changes: 10 additions & 11 deletions examples/examples/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,16 @@ use honeycomb_render::App;
fn main() {
// build a simple 4 by 4 grid at origin (1.5, 1.5)

let map = CMapBuilder::default()
.grid_descriptor(
GridDescriptor::default()
.origin(Vertex2(1.5, 1.5))
.n_cells_x(4)
.n_cells_y(4)
.len_per_cell_x(1.)
.len_per_cell_y(1.),
)
.build()
.unwrap();
let map = CMapBuilder::from_grid_descriptor(
GridDescriptor::default()
.origin(Vertex2(1.5, 1.5))
.n_cells_x(4)
.n_cells_y(4)
.len_per_cell_x(1.)
.len_per_cell_y(1.),
)
.build()
.unwrap();

// create the render app, add the map to it, and run the app

Expand Down
4 changes: 1 addition & 3 deletions honeycomb-core/src/attributes/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,7 @@ impl AttributeBind for Color {
#[test]
fn temperature_map() {
// build the map
let builder = CMapBuilder::default()
.n_darts(6)
.add_attribute::<Temperature>();
let builder = CMapBuilder::from_n_darts(6).add_attribute::<Temperature>();
let map: CMap2<f64> = builder.build().unwrap();

map.force_link::<2>(1, 2).unwrap();
Expand Down
126 changes: 65 additions & 61 deletions honeycomb-core/src/cmap/builder/structure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,52 +62,47 @@ pub enum BuilderError {
/// # fn main() -> Result<(), BuilderError> {
/// use honeycomb_core::cmap::{CMap2, CMapBuilder};
///
/// let builder = CMapBuilder::default().n_darts(10);
/// let builder = CMapBuilder::from_n_darts(10);
/// let map: CMap2<f64> = builder.build()?;
///
/// assert_eq!(map.n_darts(), 11); // 10 + null dart = 11
///
/// # Ok(())
/// # }
/// ```
#[derive(Default)]
pub struct CMapBuilder<T>
where
T: CoordsFloat,
{
pub(super) cmap_file: Option<CMapFile>,
pub(super) vtk_file: Option<Vtk>,
pub(super) grid_descriptor: Option<GridDescriptor<T>>,
pub(super) attributes: AttrStorageManager,
pub(super) n_darts: usize,
pub(super) coordstype: std::marker::PhantomData<T>,
builder_kind: BuilderType<T>,
attributes: AttrStorageManager,
}

// --- `From` impls & predefinite values

impl<T: CoordsFloat> From<GridDescriptor<T>> for CMapBuilder<T> {
fn from(value: GridDescriptor<T>) -> Self {
CMapBuilder {
grid_descriptor: Some(value),
..Default::default()
}
}
enum BuilderType<T: CoordsFloat> {
CMap(CMapFile),
FreeDarts(usize),
Grid(GridDescriptor<T>),
Vtk(Vtk),
}

/// # Regular methods
impl<T: CoordsFloat> CMapBuilder<T> {
/// Set the number of dart that the created map will contain.
#[must_use = "unused builder object"]
pub fn n_darts(mut self, n_darts: usize) -> Self {
self.n_darts = n_darts;
self
pub fn from_n_darts(n_darts: usize) -> Self {
Self {
builder_kind: BuilderType::FreeDarts(n_darts),
attributes: AttrStorageManager::default(),
}
}

/// Set the [`GridDescriptor`] that will be used when building the map.
#[must_use = "unused builder object"]
pub fn grid_descriptor(mut self, grid_descriptor: GridDescriptor<T>) -> Self {
self.grid_descriptor = Some(grid_descriptor);
self
pub fn from_grid_descriptor(grid_descriptor: GridDescriptor<T>) -> Self {
Self {
builder_kind: BuilderType::Grid(grid_descriptor),
attributes: AttrStorageManager::default(),
}
}

/// Set the `cmap` file that will be used when building the map.
Expand All @@ -116,14 +111,17 @@ impl<T: CoordsFloat> CMapBuilder<T> {
///
/// This function may panic if the file cannot be loaded, or basic section parsing fails.
#[must_use = "unused builder object"]
pub fn cmap_file(mut self, file_path: impl AsRef<std::path::Path> + std::fmt::Debug) -> Self {
pub fn from_cmap_file(file_path: impl AsRef<std::path::Path> + std::fmt::Debug) -> Self {
let mut f = File::open(file_path).expect("E: could not open specified file");
let mut buf = String::new();
f.read_to_string(&mut buf)
.expect("E: could not read content from file");
let cmap_file = CMapFile::try_from(buf).unwrap();
self.cmap_file = Some(cmap_file);
self

Self {
builder_kind: BuilderType::CMap(cmap_file),
attributes: AttrStorageManager::default(),
}
}

/// Set the VTK file that will be used when building the map.
Expand All @@ -132,11 +130,14 @@ impl<T: CoordsFloat> CMapBuilder<T> {
///
/// This function may panic if the file cannot be loaded.
#[must_use = "unused builder object"]
pub fn vtk_file(mut self, file_path: impl AsRef<std::path::Path> + std::fmt::Debug) -> Self {
pub fn from_vtk_file(file_path: impl AsRef<std::path::Path> + std::fmt::Debug) -> Self {
let vtk_file =
Vtk::import(file_path).unwrap_or_else(|e| panic!("E: failed to load file: {e:?}"));
self.vtk_file = Some(vtk_file);
self

Self {
builder_kind: BuilderType::Vtk(vtk_file),
attributes: AttrStorageManager::default(),
}
}

/// Add the attribute `A` to the attributes the created map will contain.
Expand All @@ -153,7 +154,7 @@ impl<T: CoordsFloat> CMapBuilder<T> {
/// and [here](https://doc.rust-lang.org/rust-by-example/generics/new_types.html)
#[must_use = "unused builder object"]
pub fn add_attribute<A: AttributeBind + 'static>(mut self) -> Self {
self.attributes.add_storage::<A>(self.n_darts);
self.attributes.add_storage::<A>(1);
self
}

Expand All @@ -170,29 +171,24 @@ impl<T: CoordsFloat> CMapBuilder<T> {
///
/// This method may panic if type casting goes wrong during parameters parsing.
pub fn build(self) -> Result<CMap2<T>, BuilderError> {
if let Some(cfile) = self.cmap_file {
// build from our custom format
return super::io::build_2d_from_cmap_file(cfile, self.attributes);
match self.builder_kind {
BuilderType::CMap(cfile) => super::io::build_2d_from_cmap_file(cfile, self.attributes),
BuilderType::FreeDarts(n_darts) => Ok(CMap2::new_with_undefined_attributes(
n_darts,
self.attributes,
)),
BuilderType::Grid(gridb) => {
let split = gridb.split_quads;
gridb.parse_2d().map(|(origin, ns, lens)| {
if split {
super::grid::build_2d_splitgrid(origin, ns, lens, self.attributes)
} else {
super::grid::build_2d_grid(origin, ns, lens, self.attributes)
}
})
}
BuilderType::Vtk(vfile) => super::io::build_2d_from_vtk(vfile, self.attributes),
}
if let Some(vfile) = self.vtk_file {
// build from vtk
return super::io::build_2d_from_vtk(vfile, self.attributes);
}
if let Some(gridb) = self.grid_descriptor {
// build from grid descriptor
let split = gridb.split_quads;
return gridb.parse_2d().map(|(origin, ns, lens)| {
if split {
super::grid::build_2d_splitgrid(origin, ns, lens, self.attributes)
} else {
super::grid::build_2d_grid(origin, ns, lens, self.attributes)
}
});
}
Ok(CMap2::new_with_undefined_attributes(
self.n_darts,
self.attributes,
))
}
}

Expand All @@ -215,10 +211,14 @@ impl<T: CoordsFloat> CMapBuilder<T> {
/// ![`CMAP2_GRID`](https://lihpc-computational-geometry.github.io/honeycomb/user-guide/images/bg_grid.svg)
#[must_use = "unused builder object"]
pub fn unit_grid(n_square: usize) -> Self {
GridDescriptor::default()
.n_cells([n_square; 3])
.len_per_cell([T::one(); 3])
.into()
Self {
builder_kind: BuilderType::Grid(
GridDescriptor::default()
.n_cells([n_square; 3])
.len_per_cell([T::one(); 3]),
),
attributes: AttrStorageManager::default(),
}
}

/// Create a [`CMapBuilder`] with a predefinite [`GridDescriptor`] value.
Expand All @@ -239,10 +239,14 @@ impl<T: CoordsFloat> CMapBuilder<T> {
/// ![`CMAP2_GRID`](https://lihpc-computational-geometry.github.io/honeycomb/user-guide/images/bg_grid_tri.svg)
#[must_use = "unused builder object"]
pub fn unit_triangles(n_square: usize) -> Self {
GridDescriptor::default()
.n_cells([n_square; 3])
.len_per_cell([T::one(); 3])
.split_quads(true)
.into()
Self {
builder_kind: BuilderType::Grid(
GridDescriptor::default()
.n_cells([n_square; 3])
.len_per_cell([T::one(); 3])
.split_quads(true),
),
attributes: AttrStorageManager::default(),
}
}
}
6 changes: 4 additions & 2 deletions honeycomb-core/src/cmap/builder/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::cmap::{CMap2, CMapBuilder, DartIdType, GridDescriptor, OrbitPolicy};

#[test]
fn example_test() {
let builder = CMapBuilder::default().n_darts(10);
let builder = CMapBuilder::from_n_darts(10);
let cmap: CMap2<f64> = builder.build().unwrap();
assert_eq!(cmap.n_darts(), 11);
}
Expand Down Expand Up @@ -115,7 +115,9 @@ fn square_cmap2_correctness() {
let descriptor = GridDescriptor::default()
.n_cells([2, 2, 2])
.len_per_cell([1., 1., 1.]);
let cmap: CMap2<f64> = CMapBuilder::from(descriptor).build().unwrap();
let cmap: CMap2<f64> = CMapBuilder::from_grid_descriptor(descriptor)
.build()
.unwrap();

// hardcoded because using a generic loop & dim would just mean
// reusing the same pattern as the one used during construction
Expand Down
2 changes: 1 addition & 1 deletion honeycomb-core/src/cmap/dim2/structure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ use super::CMAP2_BETA;
/// };
///
/// // build a triangle (A)
/// let mut map: CMap2<f64> = CMapBuilder::default().n_darts(3).build().unwrap(); // three darts
/// let mut map: CMap2<f64> = CMapBuilder::from_n_darts(3).build().unwrap(); // three darts
/// map.force_link::<1>(1, 2); // beta1(1) = 2 & beta0(2) = 1
/// map.force_link::<1>(2, 3); // beta1(2) = 3 & beta0(3) = 2
/// map.force_link::<1>(3, 1); // beta1(3) = 1 & beta0(1) = 3
Expand Down
Loading

0 comments on commit 8c241c2

Please sign in to comment.