///|
/// Baseline statistics for view-center distances.
pub(all) struct BaselineStatistics {
count : Int
mean : Double
minimum : Double
maximum : Double
rms : Double
} derive(Debug, Eq)
///|
pub fn baseline_statistics(baselines : ArrayView[Double]) -> BaselineStatistics {
if baselines.length() == 0 {
return { count: 0, mean: 0.0, minimum: 0.0, maximum: 0.0, rms: 0.0 }
}
let mut sum = 0.0
let mut square = 0.0
let mut minimum = baselines[0]
let mut maximum = baselines[0]
for baseline in baselines {
sum += baseline
square += baseline * baseline
minimum = minimum.min(baseline)
maximum = maximum.max(baseline)
}
{
count: baselines.length(),
mean: sum / baselines.length().to_double(),
minimum,
maximum,
rms: (square / baselines.length().to_double()).sqrt(),
}
}
///|
pub fn baseline_valid_ratio(
baselines : ArrayView[Double],
minimum : Double,
) -> Double {
if baselines.length() == 0 {
0.0
} else {
let mut count = 0
for baseline in baselines {
if baseline >= minimum {
count += 1
}
}
count.to_double() / baselines.length().to_double()
}
}
///|
pub fn baseline_pairwise_centers(
centers : ArrayView[@core.Point3],
) -> Array[Double] {
let result : Array[Double] = []
for i in 0.. Array[(Int, Int)] {
let result : Array[(Int, Int)] = []
for i in 0..= minimum {
result.push((i, j))
}
}
}
result
}
///|
pub fn baseline_condition_score(
statistics : BaselineStatistics,
target : Double,
) -> Double {
if target <= 0.0 || statistics.count == 0 {
0.0
} else {
(statistics.mean / target).min(1.0).max(0.0)
}
}
///|
pub fn baseline_is_degenerate(
statistics : BaselineStatistics,
tolerance : Double,
) -> Bool {
statistics.count == 0 || statistics.maximum - statistics.minimum <= tolerance
}
///|
pub fn camera_center_distances(
centers : ArrayView[@core.Point3],
) -> Array[Double] {
let result : Array[Double] = []
if centers.length() < 2 {
return result
}
for i in 0..<(centers.length() - 1) {
result.push(centers[i].minus(centers[i + 1]).norm())
}
result
}
///|
pub fn camera_path_length(centers : ArrayView[@core.Point3]) -> Double {
let mut result = 0.0
for distance in camera_center_distances(centers) {
result += distance
}
result
}
///|
pub fn camera_path_turn_angles(
centers : ArrayView[@core.Point3],
) -> Array[Double] raise @core.GeometryError {
let result : Array[Double] = []
if centers.length() < 3 {
return result
}
for i in 1..<(centers.length() - 1) {
let first = centers[i].minus(centers[i - 1]).normalize()
let second = centers[i + 1].minus(centers[i]).normalize()
let cosine = first.dot(second).max(-1.0).min(1.0)
result.push(@math.acos(cosine))
}
result
}