///|
pub struct Vector2 {
x : Double
y : Double
} derive(Debug, Eq)
///|
pub fn Vector2::new(x : Double, y : Double) -> Vector2 {
{ x, y }
}
///|
pub fn Vector2::zero() -> Vector2 {
{ x: 0.0, y: 0.0 }
}
///|
pub fn Vector2::add(self : Vector2, other : Vector2) -> Vector2 {
{ x: self.x + other.x, y: self.y + other.y }
}
///|
pub fn Vector2::sub(self : Vector2, other : Vector2) -> Vector2 {
{ x: self.x - other.x, y: self.y - other.y }
}
///|
pub fn Vector2::scale(self : Vector2, factor : Double) -> Vector2 {
{ x: self.x * factor, y: self.y * factor }
}
///|
pub fn Vector2::dot(self : Vector2, other : Vector2) -> Double {
self.x * other.x + self.y * other.y
}
///|
pub fn Vector2::length_squared(self : Vector2) -> Double {
self.dot(self)
}
///|
pub fn Vector2::length(self : Vector2) -> Double {
self.length_squared().sqrt()
}
///|
pub fn Vector2::normalize(self : Vector2) -> Vector2 {
let length = self.length()
if length == 0.0 {
Vector2::zero()
} else {
self.scale(1.0 / length)
}
}
///|
pub struct ProjectedDimension {
name : String
vector : Vector2
tolerance : Double
} derive(Debug)
///|
pub fn ProjectedDimension::new(
name : String,
vector : Vector2,
tolerance : Double,
) -> ProjectedDimension {
if tolerance < 0.0 {
abort("tolerance must be non-negative")
}
{ name, vector, tolerance }
}
///|
pub struct ProjectedResult {
nominal : Vector2
lower_x : Double
upper_x : Double
lower_y : Double
upper_y : Double
radial_tolerance : Double
sensitivity : Array[(String, Double)]
} derive(Debug)
///|
pub fn project_chain(dimensions : Array[ProjectedDimension]) -> ProjectedResult {
if dimensions.length() == 0 {
abort("a projected chain must not be empty")
}
let mut nominal = Vector2::zero()
let mut variance = 0.0
let mut x_span = 0.0
let mut y_span = 0.0
for dimension in dimensions {
nominal = nominal.add(dimension.vector)
variance += dimension.tolerance * dimension.tolerance
x_span += dimension.vector.x.abs() * dimension.tolerance
y_span += dimension.vector.y.abs() * dimension.tolerance
}
let sensitivities = dimensions.map(d => (d.name, d.tolerance))
{
nominal,
lower_x: nominal.x - x_span,
upper_x: nominal.x + x_span,
lower_y: nominal.y - y_span,
upper_y: nominal.y + y_span,
radial_tolerance: variance.sqrt(),
sensitivity: sensitivities,
}
}
///|
pub fn project_direction(angle_radians : Double) -> Vector2 {
{ x: @math.cos(angle_radians), y: @math.sin(angle_radians) }
}
///|
pub fn project_signed(value : Double, angle_radians : Double) -> Vector2 {
project_direction(angle_radians).scale(value)
}