fixed concave hull ordering
This commit is contained in:
parent
6c215809fb
commit
7e8b5f217e
1 changed files with 48 additions and 37 deletions
85
src/lib.rs
85
src/lib.rs
|
|
@ -467,51 +467,62 @@ impl Xenobalanus {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Order the hull edge indices to form a continuous path
|
// Order the hull edge indices to form a continuous path
|
||||||
let ordered_indices = self.order_hull_edges(hull_edge_indices)?;
|
let ordered_indices = self.ordered_vertices(hull_edge_indices)?;
|
||||||
|
|
||||||
Ok(ordered_indices)
|
Ok(ordered_indices)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to order hull edges into a continuous path.
|
/// Attempts to order hull edges into a continuous path.
|
||||||
pub fn order_hull_edges(&self, hull_edge_indices: Vec<(usize, usize)>) -> Result<Vec<usize>, &'static str> {
|
fn ordered_vertices(&self, edges: Vec<(usize, usize)>) -> Result<Vec<usize>, &'static str> {
|
||||||
if hull_edge_indices.is_empty() {
|
let mut graph = HashMap::new();
|
||||||
return Err("No edges provided.");
|
// Create the graph and track degrees
|
||||||
|
for (a, b) in &edges {
|
||||||
|
graph.entry(*a).or_insert_with(HashSet::new).insert(*b);
|
||||||
|
graph.entry(*b).or_insert_with(HashSet::new).insert(*a);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut visited: HashSet<usize> = HashSet::new();
|
// Verify the graph's conditions for an Eulerian path
|
||||||
let mut ordered_point_indices: Vec<usize> = Vec::new();
|
let mut odd_degree_vertices = vec![];
|
||||||
|
for (&vertex, neighbors) in &graph {
|
||||||
// Initialize with the first edge's indices
|
if neighbors.len() % 2 != 0 {
|
||||||
let (start_idx, mut current_idx) = hull_edge_indices[0];
|
odd_degree_vertices.push(vertex);
|
||||||
ordered_point_indices.push(start_idx);
|
}
|
||||||
visited.insert(start_idx);
|
}
|
||||||
|
if odd_degree_vertices.len() > 2 {
|
||||||
while visited.len() < hull_edge_indices.len() + 1 {
|
return Err("Graph cannot have more than two vertices of odd degree");
|
||||||
let mut found_next = false;
|
}
|
||||||
|
|
||||||
for &(p1_idx, p2_idx) in &hull_edge_indices {
|
// Choose a start vertex
|
||||||
if p1_idx == current_idx && !visited.contains(&p2_idx) {
|
let start = if !odd_degree_vertices.is_empty() {
|
||||||
ordered_point_indices.push(p2_idx);
|
odd_degree_vertices[0]
|
||||||
visited.insert(p2_idx);
|
} else {
|
||||||
current_idx = p2_idx;
|
*graph.keys().next().ok_or("Graph is empty")?
|
||||||
found_next = true;
|
};
|
||||||
break;
|
|
||||||
} else if p2_idx == current_idx && !visited.contains(&p1_idx) {
|
let mut stack = vec![start];
|
||||||
ordered_point_indices.push(p1_idx);
|
let mut path = Vec::new(); // This will store the path of vertices
|
||||||
visited.insert(p1_idx);
|
let mut visited_edges = HashSet::new(); // To track visited edges
|
||||||
current_idx = p1_idx;
|
|
||||||
found_next = true;
|
while let Some(node) = stack.pop() {
|
||||||
break;
|
path.push(node); // Add vertex to the path
|
||||||
|
if let Some(neighbors) = graph.get_mut(&node) {
|
||||||
|
for &next in neighbors.clone().iter() {
|
||||||
|
// Ensure each edge is traversed exactly once
|
||||||
|
if !visited_edges.contains(&(node, next)) && !visited_edges.contains(&(next, node)) {
|
||||||
|
visited_edges.insert((node, next));
|
||||||
|
visited_edges.insert((next, node)); // Mark edge as visited in both directions
|
||||||
|
stack.push(next); // Visit next vertex
|
||||||
|
break; // Break after pushing one neighbor to ensure we follow one continuous path
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !found_next {
|
|
||||||
return Err("Failed to order all concave hull vertices into a continuous path.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert indices to Points
|
// Check if all edges were visited
|
||||||
Ok(hull_edge_indices.iter().map(|&(start_idx, _)| start_idx).collect())
|
if visited_edges.len() / 2 != edges.len() {
|
||||||
|
return Err("Graph is not Eulerian: no path uses all edges exactly once");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue