Check if any non-adjacent edges of a ring intersect.
(ring: &[[f64; 2]], label: &str, issues: &mut Vec<String>)
| 151 | |
| 152 | /// Check if any non-adjacent edges of a ring intersect. |
| 153 | fn check_ring_self_intersection(ring: &[[f64; 2]], label: &str, issues: &mut Vec<String>) { |
| 154 | let n = if ring.first() == ring.last() && ring.len() > 1 { |
| 155 | ring.len() - 1 |
| 156 | } else { |
| 157 | ring.len() |
| 158 | }; |
| 159 | |
| 160 | if n < 4 { |
| 161 | return; // Triangle can't self-intersect. |
| 162 | } |
| 163 | |
| 164 | for i in 0..n { |
| 165 | let i_next = (i + 1) % n; |
| 166 | // Only check non-adjacent edges (skip i-1, i, i+1). |
| 167 | for j in (i + 2)..n { |
| 168 | let j_next = (j + 1) % n; |
| 169 | // Skip if edges share a vertex. |
| 170 | if j_next == i { |
| 171 | continue; |
| 172 | } |
| 173 | if segments_intersect(ring[i], ring[i_next], ring[j], ring[j_next]) { |
| 174 | // Check if it's just a shared endpoint (adjacent-ish for closed rings). |
| 175 | let shared_endpoint = ring[i] == ring[j] |
| 176 | || ring[i] == ring[j_next] |
| 177 | || ring[i_next] == ring[j] |
| 178 | || ring[i_next] == ring[j_next]; |
| 179 | if !shared_endpoint { |
| 180 | issues.push(format!( |
| 181 | "{label} has self-intersection at edges {i}-{i_next} and {j}-{j_next}" |
| 182 | )); |
| 183 | return; // One self-intersection is enough to report. |
| 184 | } |
| 185 | } |
| 186 | } |
| 187 | } |
| 188 | } |
| 189 | |
| 190 | #[cfg(test)] |
| 191 | mod tests { |
no test coverage detected