1#![allow(clippy::should_implement_trait)]
6#[allow(unused_imports)]
7use super::functions::*;
8use super::functions::{FaceId, HalfEdgeId, Point3, VertexId};
9#[allow(unused_imports)]
10use super::functions_2::*;
11
12#[derive(Debug, Clone)]
14pub struct VoronoiCell2D {
15 pub site: usize,
17 pub circumcenters: Vec<Point2>,
19}
20#[derive(Debug, Clone)]
22pub struct ArrangementFace {
23 pub vertex_indices: Vec<usize>,
25}
26#[derive(Debug, Clone, Default)]
30pub struct LineArrangement {
31 pub lines: Vec<Line2D>,
33 pub vertices: Vec<ArrangementVertex>,
35}
36impl LineArrangement {
37 pub fn build(lines: &[Line2D]) -> Self {
41 let n = lines.len();
42 let mut vertices: Vec<ArrangementVertex> = Vec::new();
43 let merge_eps = 1e-9;
44 for i in 0..n {
45 for j in (i + 1)..n {
46 if let Some(pt) = line_intersect_2d(&lines[i], &lines[j]) {
47 let existing = vertices
48 .iter_mut()
49 .find(|v| v.point.dist_sq(pt) < merge_eps);
50 if let Some(v) = existing {
51 if !v.line_indices.contains(&i) {
52 v.line_indices.push(i);
53 }
54 if !v.line_indices.contains(&j) {
55 v.line_indices.push(j);
56 }
57 } else {
58 vertices.push(ArrangementVertex {
59 point: pt,
60 line_indices: vec![i, j],
61 });
62 }
63 }
64 }
65 }
66 Self {
67 lines: lines.to_vec(),
68 vertices,
69 }
70 }
71 pub fn num_vertices(&self) -> usize {
73 self.vertices.len()
74 }
75 pub fn euler_face_count(&self) -> usize {
80 let n = self.lines.len();
81 n * (n - 1) / 2 + n + 1
82 }
83 pub fn vertices_on_line(&self, line_idx: usize) -> Vec<usize> {
85 let mut idxs: Vec<usize> = self
86 .vertices
87 .iter()
88 .enumerate()
89 .filter(|(_, v)| v.line_indices.contains(&line_idx))
90 .map(|(i, _)| i)
91 .collect();
92 let l = &self.lines[line_idx];
93 let dir = Point2::new(-l.b, l.a);
94 idxs.sort_by(|&a, &b| {
95 let ta = dir.dot(self.vertices[a].point);
96 let tb = dir.dot(self.vertices[b].point);
97 ta.partial_cmp(&tb).unwrap_or(std::cmp::Ordering::Equal)
98 });
99 idxs
100 }
101}
102#[derive(Debug, Clone)]
104pub struct HEFace {
105 pub half_edge: HalfEdgeId,
107}
108#[derive(Debug, Clone)]
110pub struct HalfEdge {
111 pub origin: VertexId,
113 pub twin: HalfEdgeId,
115 pub next: HalfEdgeId,
117 pub prev: HalfEdgeId,
119 pub face: Option<FaceId>,
121}
122#[derive(Debug, Clone, Default)]
128pub struct VisibilityGraph {
129 pub nodes: Vec<Point2>,
131 pub edges: Vec<Vec<usize>>,
133}
134impl VisibilityGraph {
135 pub fn build(obstacles: &[Obstacle2D]) -> Self {
137 let mut nodes: Vec<Point2> = Vec::new();
138 for obs in obstacles {
139 for &v in &obs.vertices {
140 nodes.push(v);
141 }
142 }
143 let all_edges: Vec<(Point2, Point2)> = obstacles.iter().flat_map(|o| o.edges()).collect();
144 let n = nodes.len();
145 let mut edges = vec![Vec::new(); n];
146 for i in 0..n {
147 for j in 0..n {
148 if i == j {
149 continue;
150 }
151 if segment_visible(nodes[i], nodes[j], &all_edges) {
152 edges[i].push(j);
153 }
154 }
155 }
156 Self { nodes, edges }
157 }
158 pub fn add_query_point(&mut self, pt: Point2, obstacles: &[Obstacle2D]) {
160 let all_edges: Vec<(Point2, Point2)> = obstacles.iter().flat_map(|o| o.edges()).collect();
161 let n = self.nodes.len();
162 let new_id = n;
163 self.nodes.push(pt);
164 self.edges.push(Vec::new());
165 for i in 0..n {
166 if segment_visible(pt, self.nodes[i], &all_edges) {
167 self.edges[new_id].push(i);
168 self.edges[i].push(new_id);
169 }
170 }
171 }
172 pub fn num_nodes(&self) -> usize {
174 self.nodes.len()
175 }
176 pub fn shortest_path(&self, src: usize, dst: usize) -> Option<Vec<usize>> {
178 use std::cmp::Reverse;
179 use std::collections::BinaryHeap;
180 let n = self.nodes.len();
181 let mut dist = vec![f64::INFINITY; n];
182 let mut prev = vec![usize::MAX; n];
183 dist[src] = 0.0;
184 let mut heap: BinaryHeap<Reverse<(u64, usize)>> = BinaryHeap::new();
185 heap.push(Reverse((0, src)));
186 while let Some(Reverse((d_raw, u))) = heap.pop() {
187 let d = d_raw as f64 / 1e9;
188 if d > dist[u] + 1e-12 {
189 continue;
190 }
191 if u == dst {
192 break;
193 }
194 for &v in &self.edges[u] {
195 let nd = dist[u] + self.nodes[u].dist(self.nodes[v]);
196 if nd < dist[v] - 1e-12 {
197 dist[v] = nd;
198 prev[v] = u;
199 heap.push(Reverse(((nd * 1e9) as u64, v)));
200 }
201 }
202 }
203 if dist[dst].is_infinite() {
204 return None;
205 }
206 let mut path = Vec::new();
207 let mut cur = dst;
208 while cur != usize::MAX {
209 path.push(cur);
210 cur = prev[cur];
211 }
212 path.reverse();
213 Some(path)
214 }
215}
216#[derive(Debug, Clone)]
218pub struct HEVertex {
219 pub position: Point3,
221 pub half_edge: Option<HalfEdgeId>,
223}
224#[derive(Debug, Clone, Copy)]
226pub struct Line2D {
227 pub a: f64,
229 pub b: f64,
231 pub c: f64,
233}
234impl Line2D {
235 pub fn through(p: Point2, q: Point2) -> Self {
237 let a = q.y - p.y;
238 let b = p.x - q.x;
239 let c = a * p.x + b * p.y;
240 Self { a, b, c }
241 }
242 pub fn signed_dist(&self, p: Point2) -> f64 {
244 let norm = (self.a * self.a + self.b * self.b).sqrt();
245 if norm < 1e-15 {
246 return 0.0;
247 }
248 (self.a * p.x + self.b * p.y - self.c) / norm
249 }
250 pub fn side(&self, p: Point2) -> f64 {
253 self.a * p.x + self.b * p.y - self.c
254 }
255}
256#[derive(Debug, Clone)]
260pub struct Trapezoid {
261 pub x_left: f64,
263 pub x_right: f64,
265 pub bottom_seg: usize,
267 pub top_seg: usize,
269 pub face: Option<usize>,
271}
272#[derive(Debug, Clone, Copy, PartialEq, Eq)]
274pub struct DelaunayTri {
275 pub a: usize,
277 pub b: usize,
279 pub c: usize,
281}
282impl DelaunayTri {
283 pub fn new(a: usize, b: usize, c: usize) -> Self {
285 Self { a, b, c }
286 }
287}
288#[derive(Debug, Clone, Copy)]
290pub struct Segment2D {
291 pub left: Point2,
293 pub right: Point2,
295}
296impl Segment2D {
297 pub fn new(a: Point2, b: Point2) -> Self {
299 if a.x <= b.x {
300 Self { left: a, right: b }
301 } else {
302 Self { left: b, right: a }
303 }
304 }
305 pub fn y_at(&self, x: f64) -> Option<f64> {
307 let dx = self.right.x - self.left.x;
308 if dx.abs() < 1e-15 {
309 return None;
310 }
311 let t = (x - self.left.x) / dx;
312 if !(0.0..=1.0).contains(&t) {
313 return None;
314 }
315 Some(self.left.y + t * (self.right.y - self.left.y))
316 }
317}
318#[derive(Debug, Clone, Default)]
324pub struct SlabPointLocator {
325 pub slab_xs: Vec<f64>,
327 pub slab_segments: Vec<Vec<usize>>,
331 pub segments: Vec<Segment2D>,
333 pub slab_faces: Vec<Vec<Option<usize>>>,
336}
337impl SlabPointLocator {
338 pub fn build(segments: &[Segment2D], _face_labels: &[Option<usize>]) -> Self {
342 let mut xs: Vec<f64> = Vec::new();
343 for s in segments {
344 xs.push(s.left.x);
345 xs.push(s.right.x);
346 }
347 xs.sort_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal));
348 xs.dedup_by(|a, b| (*a - *b).abs() < 1e-12);
349 let n_slabs = if xs.len() >= 2 { xs.len() - 1 } else { 0 };
350 let mut slab_segments = vec![Vec::new(); n_slabs];
351 let mut slab_faces = vec![Vec::new(); n_slabs];
352 for slab_i in 0..n_slabs {
353 let x_mid = (xs[slab_i] + xs[slab_i + 1]) / 2.0;
354 let mut active: Vec<(f64, usize)> = segments
355 .iter()
356 .enumerate()
357 .filter_map(|(idx, s)| s.y_at(x_mid).map(|y| (y, idx)))
358 .collect();
359 active.sort_by(|a, b| b.0.partial_cmp(&a.0).unwrap_or(std::cmp::Ordering::Equal));
360 slab_segments[slab_i] = active.iter().map(|(_, idx)| *idx).collect();
361 slab_faces[slab_i] = active.iter().map(|_| None).collect();
362 }
363 Self {
364 slab_xs: xs,
365 slab_segments,
366 segments: segments.to_vec(),
367 slab_faces,
368 }
369 }
370 pub fn locate(&self, p: Point2) -> Option<usize> {
373 let slab_i = self
374 .slab_xs
375 .partition_point(|&x| x <= p.x)
376 .saturating_sub(1);
377 if slab_i >= self.slab_segments.len() {
378 return None;
379 }
380 for &seg_idx in &self.slab_segments[slab_i] {
381 if let Some(y) = self.segments[seg_idx].y_at(p.x)
382 && y >= p.y
383 {
384 return Some(seg_idx);
385 }
386 }
387 None
388 }
389}
390#[derive(Debug, Clone)]
392pub struct ConvexFace3D {
393 pub verts: [usize; 3],
395 pub normal: Point3,
397}
398#[derive(Debug, Clone)]
400pub struct ArrangementVertex {
401 pub point: Point2,
403 pub line_indices: Vec<usize>,
405}
406#[derive(Debug, Clone)]
408pub struct Obstacle2D {
409 pub vertices: Vec<Point2>,
411}
412impl Obstacle2D {
413 pub fn new(vertices: Vec<Point2>) -> Self {
415 Self { vertices }
416 }
417 pub fn edges(&self) -> Vec<(Point2, Point2)> {
419 let n = self.vertices.len();
420 (0..n)
421 .map(|i| (self.vertices[i], self.vertices[(i + 1) % n]))
422 .collect()
423 }
424}
425#[derive(Debug, Clone, Copy, PartialEq)]
427pub struct Point2 {
428 pub x: f64,
430 pub y: f64,
432}
433impl Point2 {
434 pub fn new(x: f64, y: f64) -> Self {
436 Self { x, y }
437 }
438 pub fn sub(self, other: Self) -> Self {
440 Self::new(self.x - other.x, self.y - other.y)
441 }
442 pub fn add(self, other: Self) -> Self {
444 Self::new(self.x + other.x, self.y + other.y)
445 }
446 pub fn scale(self, t: f64) -> Self {
448 Self::new(self.x * t, self.y * t)
449 }
450 pub fn cross(self, other: Self) -> f64 {
452 self.x * other.y - self.y * other.x
453 }
454 pub fn dot(self, other: Self) -> f64 {
456 self.x * other.x + self.y * other.y
457 }
458 pub fn dist_sq(self, other: Self) -> f64 {
460 let d = self.sub(other);
461 d.dot(d)
462 }
463 pub fn dist(self, other: Self) -> f64 {
465 self.dist_sq(other).sqrt()
466 }
467 pub fn cross2(p0: Self, p1: Self, p2: Self) -> f64 {
469 p1.sub(p0).cross(p2.sub(p0))
470 }
471}
472#[derive(Debug, Clone, Default)]
476pub struct HalfEdgeMesh {
477 pub half_edges: Vec<HalfEdge>,
479 pub vertices: Vec<HEVertex>,
481 pub faces: Vec<HEFace>,
483}
484impl HalfEdgeMesh {
485 pub fn new() -> Self {
487 Self::default()
488 }
489 pub fn add_vertex(&mut self, pos: Point3) -> VertexId {
491 let id = self.vertices.len();
492 self.vertices.push(HEVertex {
493 position: pos,
494 half_edge: None,
495 });
496 id
497 }
498 pub fn add_triangle(&mut self, v0: VertexId, v1: VertexId, v2: VertexId) -> FaceId {
503 let face_id = self.faces.len();
504 let he0 = self.half_edges.len();
505 let he1 = he0 + 1;
506 let he2 = he0 + 2;
507 self.half_edges.push(HalfEdge {
508 origin: v0,
509 twin: usize::MAX,
510 next: he1,
511 prev: he2,
512 face: Some(face_id),
513 });
514 self.half_edges.push(HalfEdge {
515 origin: v1,
516 twin: usize::MAX,
517 next: he2,
518 prev: he0,
519 face: Some(face_id),
520 });
521 self.half_edges.push(HalfEdge {
522 origin: v2,
523 twin: usize::MAX,
524 next: he0,
525 prev: he1,
526 face: Some(face_id),
527 });
528 self.faces.push(HEFace { half_edge: he0 });
529 if self.vertices[v0].half_edge.is_none() {
530 self.vertices[v0].half_edge = Some(he0);
531 }
532 if self.vertices[v1].half_edge.is_none() {
533 self.vertices[v1].half_edge = Some(he1);
534 }
535 if self.vertices[v2].half_edge.is_none() {
536 self.vertices[v2].half_edge = Some(he2);
537 }
538 face_id
539 }
540 pub fn face_vertices(&self, fid: FaceId) -> Vec<VertexId> {
542 let start = self.faces[fid].half_edge;
543 let mut verts = Vec::new();
544 let mut cur = start;
545 loop {
546 verts.push(self.half_edges[cur].origin);
547 cur = self.half_edges[cur].next;
548 if cur == start {
549 break;
550 }
551 }
552 verts
553 }
554 pub fn vertex_faces(&self, vid: VertexId) -> Vec<FaceId> {
556 let start_he = match self.vertices[vid].half_edge {
557 Some(h) => h,
558 None => return vec![],
559 };
560 let mut faces = Vec::new();
561 let mut cur = start_he;
562 loop {
563 if let Some(f) = self.half_edges[cur].face {
564 faces.push(f);
565 }
566 let twin = self.half_edges[cur].twin;
567 if twin == usize::MAX {
568 break;
569 }
570 cur = self.half_edges[twin].next;
571 if cur == start_he {
572 break;
573 }
574 }
575 faces
576 }
577 pub fn build_twin_links(&mut self) {
579 use std::collections::HashMap;
580 let n = self.half_edges.len();
581 let mut edge_map: HashMap<(usize, usize), usize> = HashMap::new();
582 for i in 0..n {
583 let origin = self.half_edges[i].origin;
584 let dest = self.half_edges[self.half_edges[i].next].origin;
585 edge_map.insert((origin, dest), i);
586 }
587 for i in 0..n {
588 let origin = self.half_edges[i].origin;
589 let dest = self.half_edges[self.half_edges[i].next].origin;
590 if let Some(&twin) = edge_map.get(&(dest, origin)) {
591 self.half_edges[i].twin = twin;
592 }
593 }
594 }
595 pub fn num_faces(&self) -> usize {
597 self.faces.len()
598 }
599 pub fn num_vertices(&self) -> usize {
601 self.vertices.len()
602 }
603 pub fn face_normal(&self, fid: FaceId) -> Point3 {
605 let verts = self.face_vertices(fid);
606 if verts.len() < 3 {
607 return [0.0; 3];
608 }
609 let p0 = self.vertices[verts[0]].position;
610 let p1 = self.vertices[verts[1]].position;
611 let p2 = self.vertices[verts[2]].position;
612 let e1 = sub3(p1, p0);
613 let e2 = sub3(p2, p0);
614 normalize3(cross3(e1, e2))
615 }
616 pub fn face_centroid(&self, fid: FaceId) -> Point3 {
618 let verts = self.face_vertices(fid);
619 let n = verts.len() as f64;
620 let mut acc = [0.0f64; 3];
621 for vid in &verts {
622 let p = self.vertices[*vid].position;
623 acc[0] += p[0];
624 acc[1] += p[1];
625 acc[2] += p[2];
626 }
627 [acc[0] / n, acc[1] / n, acc[2] / n]
628 }
629}
630#[derive(Debug, Clone)]
632pub struct ConvexHull3D {
633 pub vertices: Vec<Point3>,
635 pub faces: Vec<ConvexFace3D>,
637}
638impl ConvexHull3D {
639 pub fn volume(&self) -> f64 {
641 let mut vol = 0.0f64;
642 for face in &self.faces {
643 let a = self.vertices[face.verts[0]];
644 let b = self.vertices[face.verts[1]];
645 let c = self.vertices[face.verts[2]];
646 vol += dot3(a, cross3(b, c));
647 }
648 (vol / 6.0).abs()
649 }
650 pub fn surface_area(&self) -> f64 {
652 let mut area = 0.0f64;
653 for face in &self.faces {
654 let a = self.vertices[face.verts[0]];
655 let b = self.vertices[face.verts[1]];
656 let c = self.vertices[face.verts[2]];
657 let ab = sub3(b, a);
658 let ac = sub3(c, a);
659 area += 0.5 * mag3(cross3(ab, ac));
660 }
661 area
662 }
663}
664#[derive(Debug, Clone)]
666pub struct ArtGalleryResult {
667 pub guards: Vec<usize>,
669 pub covered: Vec<bool>,
672}