simplification

This commit is contained in:
randogoth 2024-03-19 11:23:57 +02:00
parent 708ac7f409
commit 92d7a755d5

View file

@ -15,9 +15,9 @@ struct Edge(usize, usize);
#[derive(Debug)] #[derive(Debug)]
struct TriangleData { struct TriangleData {
index: usize, index: usize,
vertices: Vec<usize>,
area: Option<f32>, area: Option<f32>,
terminal_edge: Option<Edge>, terminal_edge: Option<Edge>
third_vertex: Option<usize>
} }
#[derive(Debug)] #[derive(Debug)]
@ -43,6 +43,9 @@ impl GeometryData {
let point_b: Point<f32> = points[tri_idx[1]]; let point_b: Point<f32> = points[tri_idx[1]];
let point_c: Point<f32> = points[tri_idx[2]]; let point_c: Point<f32> = points[tri_idx[2]];
let mut vertices = vec![tri_idx[0], tri_idx[1], tri_idx[2]];
vertices.sort_unstable();
// Temporarily store edges_with_lengths for sorting and determining the terminal_edge. // Temporarily store edges_with_lengths for sorting and determining the terminal_edge.
let mut edges_with_lengths_temp = [ let mut edges_with_lengths_temp = [
(Edge(min(tri_idx[0], tri_idx[1]), max(tri_idx[0], tri_idx[1])), point_a.euclidean_distance(&point_b)), (Edge(min(tri_idx[0], tri_idx[1]), max(tri_idx[0], tri_idx[1])), point_a.euclidean_distance(&point_b)),
@ -54,11 +57,6 @@ impl GeometryData {
edges_with_lengths_temp.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap()); edges_with_lengths_temp.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap());
let terminal_edge: Option<Edge> = edges_with_lengths_temp.first().map(|(edge, _)| *edge); let terminal_edge: Option<Edge> = edges_with_lengths_temp.first().map(|(edge, _)| *edge);
// Determine the third vertex
let third_vertex: Option<usize> = tri_idx.iter().find(|&&idx| {
idx != terminal_edge.unwrap().0 && idx != terminal_edge.unwrap().1
}).copied();
let area: Option<f32> = if types == 0 || types == 2 { let area: Option<f32> = if types == 0 || types == 2 {
Some(Polygon::new(LineString::from(vec![ Some(Polygon::new(LineString::from(vec![
(point_a.x(), point_a.y()), (point_a.x(), point_a.y()),
@ -88,9 +86,9 @@ impl GeometryData {
if types == 0 || types == 2 { if types == 0 || types == 2 {
self.triangles.push(TriangleData { self.triangles.push(TriangleData {
index, index,
vertices,
area, area,
terminal_edge, terminal_edge
third_vertex
}); });
} }
} }
@ -153,7 +151,7 @@ fn delfin(
geometry_data: &GeometryData, geometry_data: &GeometryData,
min_area: f32, min_area: f32,
min_distance: f32, min_distance: f32,
) -> Vec<Vec<HashSet<usize>>> { ) -> Vec<Vec<Vec<usize>>> {
// Sort all triangles by the longest terminal edge // Sort all triangles by the longest terminal edge
let triangles_sorted: Vec<(usize, f32)> = geometry_data.triangles.iter() let triangles_sorted: Vec<(usize, f32)> = geometry_data.triangles.iter()
@ -269,69 +267,28 @@ fn delfin(
area_z_score >= min_area && poly_set.len() >= 3 area_z_score >= min_area && poly_set.len() >= 3
}); });
void_polygons.iter().map(|triangle_set| { let void_polygons_vertices: Vec<Vec<Vec<usize>>> = void_polygons.into_iter().map(|triangle_set: HashSet<usize>| {
triangle_set.iter().map(|&triangle_index| { triangle_set.into_iter().map(|triangle_index| {
let triangle = &geometry_data.triangles[triangle_index]; // Directly retrieve the vertices of the triangle
let mut vertices = HashSet::new(); geometry_data.triangles[triangle_index].vertices.clone()
if let Some(terminal_edge) = triangle.terminal_edge {
vertices.insert(terminal_edge.0);
vertices.insert(terminal_edge.1);
}
if let Some(third_vertex) = triangle.third_vertex {
vertices.insert(third_vertex);
}
vertices
}) })
.collect::<Vec<HashSet<usize>>>() // Collecting into Vec<Vec<usize>>, each inner Vec<usize> represents a triangle's vertices
.collect::<Vec<Vec<usize>>>()
}) })
.collect() // Collect each void area's vertex sets into the final Vec
.collect::<Vec<Vec<Vec<usize>>>>();
} // Return the transformed structure
void_polygons_vertices
// Function to recursively expand clusters
fn expand_cluster(
vertex_idx: usize,
visited: &mut HashSet<usize>,
cluster: &mut HashSet<usize>,
geometry_data: &GeometryData,
mean_edge_length: f32,
std_edge_length: f32,
max_closeness: f32,
) {
visited.insert(vertex_idx);
if let Some(neighbors) = geometry_data.vertex_connections.get(&vertex_idx) {
for &neighbor_idx in neighbors {
if visited.contains(&neighbor_idx) {
continue;
}
let edge = Edge(min(vertex_idx, neighbor_idx), max(vertex_idx, neighbor_idx));
if let Some(&length) = geometry_data.edge_lengths.get(&edge) {
let z_score: f32 = (length - mean_edge_length) / std_edge_length;
if z_score <= max_closeness {
cluster.insert(neighbor_idx);
expand_cluster(
neighbor_idx,
visited,
cluster,
geometry_data,
mean_edge_length,
std_edge_length,
max_closeness,
);
}
}
}
}
} }
fn dtscan( fn dtscan(
geometry_data: &GeometryData, geometry_data: &GeometryData,
min_pts: usize, min_pts: usize,
max_closeness: f32, max_closeness: f32,
) -> Vec<HashSet<usize>> { ) -> Vec<Vec<usize>> {
let mut clusters: Vec<HashSet<usize>> = Vec::new(); let mut clusters: Vec<Vec<usize>> = Vec::new();
let mut visited: HashSet<usize> = HashSet::new(); let mut visited: HashSet<usize> = HashSet::new();
let edge_lengths_values: Vec<f32> = geometry_data.edge_lengths.values().cloned().collect(); let edge_lengths_values: Vec<f32> = geometry_data.edge_lengths.values().cloned().collect();
let (mean_edge_length, std_edge_length) = mean_std(edge_lengths_values); let (mean_edge_length, std_edge_length) = mean_std(edge_lengths_values);
@ -349,23 +306,39 @@ fn dtscan(
false false
} }
}) { }) {
let mut cluster: HashSet<usize> = HashSet::new(); let mut cluster: Vec<usize> = Vec::new();
expand_cluster( let mut to_expand: Vec<usize> = vec![vertex_idx];
vertex_idx,
&mut visited, while let Some(current_vertex) = to_expand.pop() {
&mut cluster, if !visited.insert(current_vertex) {
geometry_data, continue;
mean_edge_length, }
std_edge_length,
max_closeness, cluster.push(current_vertex);
);
clusters.push(cluster); // Add neighbors that are within max_closeness to to_expand
geometry_data.vertex_connections.get(&current_vertex).map(|neighbors: &HashSet<usize>| {
for &neighbor in neighbors {
if let Some(&length) = geometry_data.edge_lengths.get(&Edge(min(current_vertex, neighbor), max(current_vertex, neighbor))) {
let z_score = (length - mean_edge_length) / std_edge_length;
if z_score <= max_closeness && !visited.contains(&neighbor) {
to_expand.push(neighbor);
}
}
}
});
}
if !cluster.is_empty() {
clusters.push(cluster); // Add the constructed cluster to the list of clusters
}
} }
} }
clusters clusters
} }
fn improbability_z_score(total_area: f32, total_dots: u32, sub_area: f32, sub_dots: u32) -> f32 { fn improbability_z_score(total_area: f32, total_dots: u32, sub_area: f32, sub_dots: u32) -> f32 {
// expected dots for the area under a Complete Spatial Randomness scenario // expected dots for the area under a Complete Spatial Randomness scenario
let csr_lambda: f32 = total_dots as f32 - ( sub_area / total_area); let csr_lambda: f32 = total_dots as f32 - ( sub_area / total_area);
@ -401,7 +374,7 @@ fn main() {
// Execute delfin function with the generated GeometryData // Execute delfin function with the generated GeometryData
start = Instant::now(); start = Instant::now();
let void_polygons: Vec<Vec<HashSet<usize>>> = delfin(&geometry_data, min_area, min_distance); let void_polygons: Vec<Vec<Vec<usize>>> = delfin(&geometry_data, min_area, min_distance);
duration = start.elapsed(); duration = start.elapsed();
println!("Found {:#?} Voids using {:#?} bytes of RAM in: {:#?}", void_polygons.len(), mem::size_of_val(&void_polygons), duration); println!("Found {:#?} Voids using {:#?} bytes of RAM in: {:#?}", void_polygons.len(), mem::size_of_val(&void_polygons), duration);
@ -410,6 +383,7 @@ fn main() {
let clusters = dtscan(&geometry_data, min_pts, max_closeness); let clusters = dtscan(&geometry_data, min_pts, max_closeness);
duration = start.elapsed(); duration = start.elapsed();
println!("Found {:#?} Attractors using {:#?} bytes of RAM in: {:#?}", clusters.len(), mem::size_of_val(&clusters), duration); println!("Found {:#?} Attractors using {:#?} bytes of RAM in: {:#?}", clusters.len(), mem::size_of_val(&clusters), duration);
println!("{:?}", void_polygons);
println!("{:?}", clusters);
} }