///|
/// Higher-level operations for 2D rails and masks.
pub struct Path2DMetric2 {
length : Double
bounds : Bounds2D
samples : Array[Point2]
average_speed : Double
chord_error : Double
} derive(Debug)
///|
pub fn Path2DMetric2::length(self : Path2DMetric2) -> Double {
self.length
}
///|
pub fn Path2DMetric2::bounds(self : Path2DMetric2) -> Bounds2D {
self.bounds
}
///|
pub fn Path2DMetric2::samples(self : Path2DMetric2) -> Array[Point2] {
self.samples.copy()
}
///|
pub fn Path2DMetric2::average_speed(self : Path2DMetric2) -> Double {
self.average_speed
}
///|
pub fn Path2DMetric2::chord_error(self : Path2DMetric2) -> Double {
self.chord_error
}
///|
pub fn analyze_path2d(path : Path2D, count : Int) -> Path2DMetric2 {
let actual = count.max(2)
let samples = path.polyline(actual)
let mut chord_error = 0.0
for index in 1.. Array[Point2] {
let result : Array[Point2] = []
for distance in distances {
result.push(path.sample_by_distance(distance))
}
result
}
///|
pub fn path2d_tangent_batch(
path : Path2D,
parameters : Array[Double],
) -> Array[Point2] {
let result : Array[Point2] = []
for parameter in parameters {
result.push(point2_normalized(path.tangent(parameter)))
}
result
}
///|
pub fn path2d_normals(path : Path2D, count : Int) -> Array[Point2] {
let result : Array[Point2] = []
let actual = count.max(1)
for index in 0.. Array[Point2] {
let result : Array[Point2] = []
let actual = count.max(1)
for index in 0.. Array[Double] {
let actual = count.max(2)
let result : Array[Double] = []
let step = path.total_length() / (actual - 1).to_double()
for index in 0.. Path2DMetric2 {
analyze_path2d(path, count)
}
///|
pub fn path2d_distance_to_segment(
path : Path2D,
target : Point2,
samples : Int,
) -> Double {
path.project(target, samples_per_segment=samples.max(1)).distance()
}
///|
pub fn path2d_closest_parameter(
path : Path2D,
target : Point2,
samples : Int,
) -> Double {
path.project(target, samples_per_segment=samples.max(1)).parameter()
}
///|
pub fn path2d_split_samples(
path : Path2D,
parameters : Array[Double],
) -> Array[Point2] {
let result : Array[Point2] = []
for parameter in parameters {
result.push(path.sample(parameter))
}
result
}
///|
pub fn path2d_motion_length(
path : Path2D,
start : Double,
end : Double,
samples : Int,
) -> Double {
let actual = samples.max(1)
let mut total = 0.0
let mut previous = path.sample(start)
for index in 1..<=actual {
let current = path.sample(
start + (end - start) * index.to_double() / actual.to_double(),
)
total = total + previous.distance(current)
previous = current
}
total
}
///|
pub fn path2d_curvature_estimate(
path : Path2D,
parameter : Double,
epsilon? : Double = 0.001,
) -> Double {
let step = epsilon.max(0.000000000001)
let left = point2_normalized(path.tangent((parameter - step).max(0.0)))
let right = point2_normalized(path.tangent((parameter + step).min(1.0)))
@math.hypot(right.x() - left.x(), right.y() - left.y()) / (2.0 * step)
}
///|
pub fn path2d_curvature_profile(path : Path2D, count : Int) -> Array[Double] {
let result : Array[Double] = []
let actual = count.max(1)
for index in 0.. Bool {
path.total_length() <= tolerance.abs()
}