Skip to content

Commit

Permalink
Add centroid face selector
Browse files Browse the repository at this point in the history
Signed-off-by: Dimitris Zervas <dzervas@dzervas.gr>
  • Loading branch information
dzervas committed Jun 8, 2024
1 parent 9e4f65c commit f0040cd
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 21 deletions.
4 changes: 3 additions & 1 deletion packages/cadmium/benches/faceselector-report/draw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ use cadmium::isketch::face::FaceSelector;
use cadmium::project::Project;
use cadmium::IDType;

use crate::FaceSelectorType;

pub const COLORS: [&str; 6] = ["#FF0000", "#00FF00", "#0000FF", "#FFFF00", "#FF00FF", "#00FFFF"];

pub fn draw_sketch_faces<T: FaceSelector + std::fmt::Debug>(p: &mut Project, selector: &Box<T>, sketch_id: IDType, name: String) {
pub fn draw_sketch_faces(p: &mut Project, selector: &FaceSelectorType, sketch_id: IDType, name: String) {
let wb_ref = p.get_workbench_by_id(0).unwrap();
let wb = wb_ref.borrow();
let sketch_ref = wb.get_sketch_by_id(sketch_id).unwrap();
Expand Down
26 changes: 24 additions & 2 deletions packages/cadmium/benches/faceselector-report/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,25 @@ fn create_project() -> (Project, IDType) {
(p, sketch_id)
}

#[derive(Debug)]
pub enum FaceSelectorType {
ID(cadmium::isketch::face::IDSelector),
Centroid(cadmium::isketch::face::CentroidSelector),
}

impl FaceSelector for FaceSelectorType {
fn get_selected_faces(&self, isketch: &cadmium::isketch::ISketch) -> Vec<cadmium::isketch::face::Face> {
match self {
FaceSelectorType::ID(selector) => selector.get_selected_faces(isketch),
FaceSelectorType::Centroid(selector) => selector.get_selected_faces(isketch),
}
}

fn from_face_ids(_sketch: &cadmium::isketch::ISketch, _ids: Vec<IDType>) -> Self {
unimplemented!()
}
}

fn main() {
// Create report dir
fs::create_dir_all("bench-faceselector-report").unwrap();
Expand All @@ -45,16 +64,19 @@ fn main() {
let (mut p, sketch_id) = create_project();

case_struct.pre_selection(&mut p, sketch_id);
let sketch_ref = p.get_workbench_by_id(0).unwrap().borrow().get_sketch_by_id(sketch_id).unwrap();

let selectors = vec![
Box::new(cadmium::isketch::face::IDSelector::from_face_ids(vec![*index])),
FaceSelectorType::ID(cadmium::isketch::face::IDSelector::from_face_ids(&sketch_ref.borrow(), vec![*index])),
FaceSelectorType::Centroid(cadmium::isketch::face::CentroidSelector::from_face_ids(&sketch_ref.borrow(), vec![*index])),
];

for selector in selectors.iter() {
println!("Drawing faces for selector: {:?}", selector);
let case_name = format!("{:?}", case_struct);
let selector_name_full = format!("{:?}", selector);
let selector_name = selector_name_full.split_once(" ").unwrap().0;
let selector_name_variant = selector_name_full.split_once(" ").unwrap().0;
let selector_name = selector_name_variant.split_once("(").unwrap().1;
let name = format!("{}_{}", selector_name, case_name);
results.push((selector_name.to_string(), case_name.to_string(), name.clone()));

Expand Down
5 changes: 3 additions & 2 deletions packages/cadmium/src/feature/extrusion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ impl Extrusion {
mode: Mode,
) -> Self {
Extrusion {
faces: Selector::from_face_ids(faces),
faces: Selector::from_face_ids(&sketch.clone().borrow(), faces),
sketch,
length,
offset,
Expand Down Expand Up @@ -178,9 +178,10 @@ impl MessageHandler for UpdateFaces {
fn handle_message(&self, workbench_ref: Self::Parent) -> anyhow::Result<Option<IDType>> {
let workbench = workbench_ref.borrow_mut();
let feature_ref = workbench.features.get(&self.extrusion_id).ok_or(anyhow::anyhow!("No feature with ID {} was found", self.extrusion_id))?;
let sketch_ref = workbench.get_sketch_by_id(self.sketch_id)?;
let mut extrusion: RefMut<'_, Extrusion> = RefMut::map(feature_ref.borrow_mut(), |f| f.try_into().unwrap());

extrusion.faces = Selector::from_face_ids(self.faces.clone());
extrusion.faces = Selector::from_face_ids(&sketch_ref.borrow(), self.faces.clone());

Ok(None)
}
Expand Down
73 changes: 57 additions & 16 deletions packages/cadmium/src/isketch/face.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use geo::{Centroid, EuclideanDistance as _};
pub use isotope::decompose::face::Face;
use isotope::primitives::point2::Point2;
use itertools::Itertools;
use serde::{Deserialize, Serialize};

use crate::IDType;
Expand All @@ -12,7 +15,7 @@ pub type Selector = IDSelector;

pub trait FaceSelector {
fn get_selected_faces(&self, isketch: &ISketch) -> Vec<Face>;
fn from_face_ids(ids: Vec<IDType>) -> Self;
fn from_face_ids(sketch: &ISketch, ids: Vec<IDType>) -> Self;
}

/// The most simple selector, just select faces by their ID
Expand All @@ -23,24 +26,62 @@ pub struct IDSelector {
}

impl FaceSelector for IDSelector {
fn get_selected_faces(&self, isketch: &ISketch) -> Vec<Face> {
isketch
.sketch()
.borrow()
.get_merged_faces()
fn get_selected_faces(&self, sketch: &ISketch) -> Vec<Face> {
sketch.get_face_ids(self.ids.clone())
}

fn from_face_ids(_sketch: &ISketch, ids: Vec<IDType>) -> Self {
Self { ids }
}
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CentroidSelector {
pub centroids: Vec<Point2>,
}

impl CentroidSelector {
pub fn get_face_centroid(&self, face: &Face) -> Point2 {
let centroid = face.as_polygon().centroid().unwrap();
Point2::new(centroid.x(), centroid.y())
}
}

impl FaceSelector for CentroidSelector {
fn get_selected_faces(&self, sketch: &ISketch) -> Vec<Face> {
self.centroids
.iter()
.enumerate()
.filter_map(|(id, f)| {
if self.ids.contains(&(id as IDType)) {
Some(f.clone())
} else {
None
}
.filter_map(|c| {
let point = geo::Point::new(c.x(), c.y());
let faces = sketch.faces();
let min = faces
.iter()
.min_by(|a, b| {
let Some(a_centroid) = &a.as_polygon().centroid() else { return std::cmp::Ordering::Greater };
let Some(b_centroid) = &b.as_polygon().centroid() else { return std::cmp::Ordering::Greater };
let a_distance = a_centroid.euclidean_distance(&point);
let b_distance = b_centroid.euclidean_distance(&point);
a_distance.partial_cmp(&b_distance).unwrap()
});

min.cloned()
})
.collect()
.collect_vec()
}

fn from_face_ids(ids: Vec<IDType>) -> Self {
Self { ids }
fn from_face_ids(sketch: &ISketch, ids: Vec<IDType>) -> Self {
Self {
centroids: sketch.get_face_ids(ids)
.iter()
.filter_map(|f| {
// We're straight-up skipping faces without a centroid
if let Some(centroid) = f.as_polygon().centroid() {
Some(Point2::new(centroid.x(), centroid.y()))
} else {
None
}
})
.collect(),
}
}
}
10 changes: 10 additions & 0 deletions packages/cadmium/src/isketch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,16 @@ impl ISketch {
self.sketch.borrow().get_merged_faces()
}

pub fn get_face_ids(&self, ids: Vec<IDType>) -> Vec<Face> {
self.sketch.borrow().get_merged_faces().iter().enumerate().filter_map(|(id, f)| {
if ids.contains(&(id as IDType)) {
Some(f.clone())
} else {
None
}
}).collect()
}

pub fn find_point_ref(&self, x: f64, y: f64) -> Option<Rc<RefCell<ISOPoint2>>> {
self.sketch.borrow().primitives().iter().find_map(|(_, prim)| {
if let PrimitiveCell::Point2(point_ref) = prim {
Expand Down

0 comments on commit f0040cd

Please sign in to comment.