///|
pub fn pose_rotation_error(a : @core.Mat3, b : @core.Mat3) -> Double {
let relative = a.mul(b.transpose())
let trace = relative.m00 + relative.m11 + relative.m22
let cosine = (trace - 1.0) / 2.0
@math.acos(@core.clamp_unit(cosine))
}
///|
pub fn pose_translation_error(
a : @camera.CameraPose,
b : @camera.CameraPose,
) -> Double {
a.camera_center().minus(b.camera_center()).norm()
}
///|
pub fn pose_error(
a : @camera.CameraPose,
b : @camera.CameraPose,
) -> (Double, Double) {
(
pose_rotation_error(a.rotation(), b.rotation()),
pose_translation_error(a, b),
)
}
///|
pub fn baseline_length(
left : @camera.CameraPose,
right : @camera.CameraPose,
) -> Double {
left.camera_center().minus(right.camera_center()).norm()
}
///|
pub fn baseline_is_usable(
left : @camera.CameraPose,
right : @camera.CameraPose,
minimum? : Double = 0.000001,
) -> Bool {
baseline_length(left, right) >= minimum
}
///|
pub fn depth_statistics(
points : ArrayView[@core.Point3],
) -> (@core.Point3, Double) raise @core.GeometryError {
if points.length() == 0 {
raise @core.GeometryError::NotEnoughPoints("depth statistics need points")
}
let values : Array[Double] = []
for p in points {
if p.z <= 0.0 {
raise @core.GeometryError::DegenerateInput("point depth is not positive")
}
values.push(p.z)
}
(
@core.Point3::new(
x=@core.mean(values),
y=@core.median(values),
z=@core.max_error(values),
),
@core.variance(values),
)
}
///|
pub fn positive_depth_mask(points : ArrayView[@core.Point3]) -> Array[Bool] {
let result : Array[Bool] = []
for p in points {
result.push(p.z > 0.0)
}
result
}