From 5bb70ee2f8ac679d6afe467a689d62331988cd25 Mon Sep 17 00:00:00 2001 From: Andy Killorin <37423245+Speedy6451@users.noreply.github.com> Date: Sat, 4 Nov 2023 16:53:44 -0500 Subject: [PATCH] extracted points_in_range to trait --- src/main.rs | 41 +++++------------------------------------ src/selig.rs | 51 +++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 48 insertions(+), 44 deletions(-) diff --git a/src/main.rs b/src/main.rs index eaed1b3..b9c01a2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,7 @@ use std::sync::Mutex; use nalgebra::Vector3; use scad::*; use constants::*; -use selig::Airfoil; +use selig::Span; use selig::SeligFile; use selig::Point; use std::ops::Range; @@ -21,13 +21,13 @@ fn main() { // cambered airfoil, used in the wing let wing_airfoil: SeligFile = SeligFile::parse(include_str!("../ag24.dat")); - println!("name {}, perim {}", wing_airfoil.get_name(), wing_airfoil.get_points().perimiter()); + println!("name {}, perim {}", wing_airfoil.get_name(), wing_airfoil.get_points().length()); println!("desc {}", wing_airfoil.get_description().clone().unwrap_or("no desc".to_string())); //println!("span {:?}", points_in_range(wing_airfoil.get_points()[0..80], 0.0..1.0)); let points = wing_airfoil.get_points()[0..80].to_vec(); - let perimeter = points.perimiter(); - let span = points_in_range(&Vec::from(points.to_vec()), perimeter * 0.4.. perimeter); + let perimeter = points.length(); + let span = points.to_vec().points_in_range(perimeter * 0.4.. perimeter); let points = scad::PolygonParameters::new(span); register_part(scad!(Polygon(points))); @@ -172,7 +172,7 @@ fn topspar_negative(airfoil: &SeligFile, chord: f32, range: Range) -> ScadO let points = &points[0.. points.len() / 2]; let perimeter = span_length(points); - let span = points_in_range(&points.deref().to_vec(), perimeter * (1.0-range.end) .. perimeter * (1.0-range.start)); + let span = points.to_vec().points_in_range(perimeter * (1.0-range.end) .. perimeter * (1.0-range.start)); let mut mask = scad!(Union); @@ -290,37 +290,6 @@ fn topwing_spar(aerofoil: &SeligFile, struts: usize, length: f32, chord: f32, ta wing } - -pub fn points_in_range(input: &Vec, range: Range) -> Vec { - let mut last_point: Option = None; - let mut distance: f32 = 0.0; - let mut points: Vec = Vec::new(); - for point in input { - if let Some(last) = last_point { - let span: f32 = (last - point).magnitude(); - match (range.contains(&distance), range.contains(&(distance+span))) { - (true, true) => { // fully within span - points.push(point.clone()); - }, - (false, true) => { // entering span - let undershoot = distance - range.start; - let part_out = (span - undershoot) / span; - points.push(last.lerp(&point, part_out)); - }, - (true, false) => { // exiting span - let overshoot = range.end - distance; - let part_in = (span - overshoot) / span; - points.push(last.lerp(&point, part_in)); - }, - _ => {}, - } - distance += span; - } - last_point = Some(point.clone()); - } - points -} - fn span_length(points: &[Point]) -> f32 { let mut last_point: Option = None; let mut distance: f32 = 0.0; diff --git a/src/selig.rs b/src/selig.rs index 713ac0d..42634a8 100644 --- a/src/selig.rs +++ b/src/selig.rs @@ -6,11 +6,12 @@ use std::ops::Index; use nalgebra::Vector2; pub type Point = Vector2; +pub type Airfoil = Vec; pub struct SeligFile { name: String, description: Option, - data: Vec, + data: Airfoil, } impl SeligFile { @@ -35,7 +36,7 @@ impl SeligFile { } } - pub fn get_points(&self) -> &Vec { + pub fn get_points(&self) -> &Airfoil { &self.data } @@ -49,12 +50,16 @@ impl SeligFile { } -pub trait Airfoil { - fn perimiter(&self) -> f32; +pub trait Span { + /// Sum of the distances between all the points in the span + fn length(&self) -> f32; + /// A new span with points along the existing span + /// The range is in terms of distance along the span, not indexes + fn points_in_range(&self, range: Range) -> Self; } -impl Airfoil for Vec { - fn perimiter(&self) -> f32 { +impl Span for Airfoil { + fn length(&self) -> f32 { let points = self; let mut last_point: Option = None; let mut distance: f32 = 0.0; @@ -66,17 +71,47 @@ impl Airfoil for Vec { } distance } + + fn points_in_range(&self, range: Range) -> Self { + let mut last_point: Option = None; + let mut distance: f32 = 0.0; + let mut points: Vec = Vec::new(); + for point in self { + if let Some(last) = last_point { + let span: f32 = (last - point).magnitude(); + match (range.contains(&distance), range.contains(&(distance+span))) { + (true, true) => { // fully within span + points.push(point.clone()); + }, + (false, true) => { // entering span + let undershoot = distance - range.start; + let part_out = (span - undershoot) / span; + points.push(last.lerp(&point, part_out)); + }, + (true, false) => { // exiting span + let overshoot = range.end - distance; + let part_in = (span - overshoot) / span; + points.push(last.lerp(&point, part_in)); + }, + _ => {}, + } + distance += span; + } + last_point = Some(point.clone()); + } + points + } } #[cfg(test)] mod tests { - use super::{Airfoil, SeligFile}; + use super::{Span, SeligFile}; #[test] fn full_perimiter() { let airfoil = SeligFile::parse(include_str!("../ag24.dat")); let airfoil = airfoil.get_points(); - assert_ne!(airfoil.perimiter(), airfoil[0..80].to_vec().perimiter()); + assert_ne!(airfoil.length(), airfoil[0..80].to_vec().length()); } }