1
Fork 0

extracted points_in_range to trait

This commit is contained in:
Andy Killorin 2023-11-04 16:53:44 -05:00
parent dc35cddb79
commit 5bb70ee2f8
No known key found for this signature in database
GPG key ID: 8CB11B45B690DC2A
2 changed files with 48 additions and 44 deletions

View file

@ -4,7 +4,7 @@ use std::sync::Mutex;
use nalgebra::Vector3; use nalgebra::Vector3;
use scad::*; use scad::*;
use constants::*; use constants::*;
use selig::Airfoil; use selig::Span;
use selig::SeligFile; use selig::SeligFile;
use selig::Point; use selig::Point;
use std::ops::Range; use std::ops::Range;
@ -21,13 +21,13 @@ fn main() {
// cambered airfoil, used in the wing // cambered airfoil, used in the wing
let wing_airfoil: SeligFile = SeligFile::parse(include_str!("../ag24.dat")); 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!("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)); //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 points = wing_airfoil.get_points()[0..80].to_vec();
let perimeter = points.perimiter(); let perimeter = points.length();
let span = points_in_range(&Vec::from(points.to_vec()), perimeter * 0.4.. perimeter); let span = points.to_vec().points_in_range(perimeter * 0.4.. perimeter);
let points = scad::PolygonParameters::new(span); let points = scad::PolygonParameters::new(span);
register_part(scad!(Polygon(points))); register_part(scad!(Polygon(points)));
@ -172,7 +172,7 @@ fn topspar_negative(airfoil: &SeligFile, chord: f32, range: Range<f32>) -> ScadO
let points = &points[0.. points.len() / 2]; let points = &points[0.. points.len() / 2];
let perimeter = span_length(points); 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); let mut mask = scad!(Union);
@ -290,37 +290,6 @@ fn topwing_spar(aerofoil: &SeligFile, struts: usize, length: f32, chord: f32, ta
wing wing
} }
pub fn points_in_range(input: &Vec<Point>, range: Range<f32>) -> Vec<Point> {
let mut last_point: Option<Point> = None;
let mut distance: f32 = 0.0;
let mut points: Vec<Point> = 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 { fn span_length(points: &[Point]) -> f32 {
let mut last_point: Option<Point> = None; let mut last_point: Option<Point> = None;
let mut distance: f32 = 0.0; let mut distance: f32 = 0.0;

View file

@ -6,11 +6,12 @@ use std::ops::Index;
use nalgebra::Vector2; use nalgebra::Vector2;
pub type Point = Vector2<f32>; pub type Point = Vector2<f32>;
pub type Airfoil = Vec<Point>;
pub struct SeligFile { pub struct SeligFile {
name: String, name: String,
description: Option<String>, description: Option<String>,
data: Vec<Point>, data: Airfoil,
} }
impl SeligFile { impl SeligFile {
@ -35,7 +36,7 @@ impl SeligFile {
} }
} }
pub fn get_points(&self) -> &Vec<Point> { pub fn get_points(&self) -> &Airfoil {
&self.data &self.data
} }
@ -49,12 +50,16 @@ impl SeligFile {
} }
pub trait Airfoil { pub trait Span {
fn perimiter(&self) -> f32; /// 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<f32>) -> Self;
} }
impl Airfoil for Vec<Point> { impl Span for Airfoil {
fn perimiter(&self) -> f32 { fn length(&self) -> f32 {
let points = self; let points = self;
let mut last_point: Option<Point> = None; let mut last_point: Option<Point> = None;
let mut distance: f32 = 0.0; let mut distance: f32 = 0.0;
@ -66,17 +71,47 @@ impl Airfoil for Vec<Point> {
} }
distance distance
} }
fn points_in_range(&self, range: Range<f32>) -> Self {
let mut last_point: Option<Point> = None;
let mut distance: f32 = 0.0;
let mut points: Vec<Point> = 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)] #[cfg(test)]
mod tests { mod tests {
use super::{Airfoil, SeligFile}; use super::{Span, SeligFile};
#[test] #[test]
fn full_perimiter() { fn full_perimiter() {
let airfoil = SeligFile::parse(include_str!("../ag24.dat")); let airfoil = SeligFile::parse(include_str!("../ag24.dat"));
let airfoil = airfoil.get_points(); 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());
} }
} }