use super::tapered_end_to_edge::tapered_end_to_edge_collision;
use crate::geo::ConvertTo;
use crate::meshanalyzer::SearchResult;
use crate::prelude::MaximumTracker;
use crate::probe::xy_distance_to_line_squared;
use crate::probe::{PlaneMetadata, QueryParameters, TriangleMetadata};
use crate::{HronnError, is_inside_2d_triangle};
use vector_traits::prelude::{GenericVector3, HasXYZ};
#[derive(Debug, Clone, Copy)]
pub(crate) struct ConeProperties<T: GenericVector3> {
pub radius: T::Scalar,
pub height: T::Scalar,
pub r_sq: T::Scalar,
pub slope: T::Scalar,
}
impl<T: GenericVector3> ConeProperties<T> {
pub fn new(radius: T::Scalar, height: T::Scalar) -> Self {
Self {
radius,
height,
slope: height / radius,
r_sq: radius * radius,
}
}
}
pub(crate) fn shared_tapered_precompute_logic<T: GenericVector3, MESH: HasXYZ + ConvertTo<T>>(
vertices: &[MESH],
indices: &[u32],
probe_radius: T::Scalar,
slope: T::Scalar,
) -> Result<Vec<TriangleMetadata<T, MESH>>, HronnError> {
indices
.as_ref()
.chunks(3)
.map(|triangle| {
TriangleMetadata::<T, MESH>::new_for_tapered_nose(
probe_radius,
slope,
vertices[triangle[0] as usize].to(),
vertices[triangle[1] as usize].to(),
vertices[triangle[2] as usize].to(),
)
})
.collect::<Result<Vec<_>, HronnError>>()
}
pub(crate) fn tapered_compute_collision<T: GenericVector3 + Sized, MESH: HasXYZ + ConvertTo<T>>(
qp: &QueryParameters<'_, T, MESH>,
site_index: u32,
center: T::Vector2,
mt: &mut MaximumTracker<SearchResult<T>>,
) {
let cone_prop = ConeProperties::new(qp.probe_radius, qp.probe_height);
let triangle_index = site_index * 3;
let p0 = qp.vertices[qp.indices[triangle_index as usize] as usize].to();
let p1 = qp.vertices[qp.indices[(triangle_index + 1) as usize] as usize].to();
let p2 = qp.vertices[qp.indices[(triangle_index + 2) as usize] as usize].to();
let plane_meta = &qp.meta_data[site_index as usize].plane;
if let Some(PlaneMetadata {
pft,
translated_triangle: [p0_t, p1_t, p2_t],
..
}) = plane_meta
{
if is_inside_2d_triangle(center, *p0_t, *p1_t, *p2_t) {
mt.insert(SearchResult::new(site_index, pft.compute_z(center)));
return;
}
}
if true {
tapered_end_to_edge_collision::<T>(
xy_distance_to_line_squared(center, p0, p1),
cone_prop,
site_index,
mt,
);
tapered_end_to_edge_collision::<T>(
xy_distance_to_line_squared(center, p1, p2),
cone_prop,
site_index,
mt,
);
tapered_end_to_edge_collision::<T>(
xy_distance_to_line_squared(center, p2, p0),
cone_prop,
site_index,
mt,
);
}
}