use serde::{Serialize, Deserialize};
use stormath::{
spatial_vector::SpatialVector,
type_aliases::Float
};
#[derive(Debug, Clone)]
pub struct LineCoordinates {
pub chord: Float,
pub thickness: Float,
pub span: Float,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct SpanLine {
pub start_point: SpatialVector,
pub end_point: SpatialVector
}
impl SpanLine {
pub fn relative_vector(&self) -> SpatialVector {
self.end_point - self.start_point
}
pub fn length(&self) -> Float {
self.relative_vector().length()
}
pub fn direction(&self) -> SpatialVector {
self.relative_vector().normalize()
}
pub fn as_array(&self) -> [SpatialVector; 2] {
[self.start_point, self.end_point]
}
pub fn ctrl_point(&self) -> SpatialVector {
0.5 * (self.start_point + self.end_point)
}
pub fn distance(&self, point: SpatialVector) -> Float {
let relative_vector = self.relative_vector();
let start_to_point = point - self.start_point;
let end_to_point = point - self.end_point;
if start_to_point.dot(relative_vector) <= 0.0 {
start_to_point.length()
} else if end_to_point.dot(relative_vector) >= 0.0 {
end_to_point.length()
} else {
relative_vector.cross(start_to_point).length() / relative_vector.length()
}
}
pub fn line_coordinates(&self, point: SpatialVector, chord_vector: SpatialVector) -> LineCoordinates {
let translated_point = point - self.ctrl_point();
let span_direction = self.relative_vector().normalize();
let chord_direction = chord_vector.normalize();
let thickness_direction = span_direction.cross(chord_direction);
LineCoordinates {
chord: translated_point.dot(chord_direction),
thickness: translated_point.dot(thickness_direction),
span: translated_point.dot(span_direction)
}
}
}