1use super::functions::*;
7use super::functions::{FaceId, HalfEdgeId, Point3, VertexId};
8
9#[derive(Debug, Clone)]
11pub struct VoronoiCell2D {
12 pub site: usize,
14 pub circumcenters: Vec<Point2>,
16}
17#[derive(Debug, Clone)]
19pub struct ArrangementFace {
20 pub vertex_indices: Vec<usize>,
22}
23#[derive(Debug, Clone, Default)]
27pub struct LineArrangement {
28 pub lines: Vec<Line2D>,
30 pub vertices: Vec<ArrangementVertex>,
32}
33impl LineArrangement {
34 pub fn build(lines: &[Line2D]) -> Self {
38 let n = lines.len();
39 let mut vertices: Vec<ArrangementVertex> = Vec::new();
40 let merge_eps = 1e-9;
41 for i in 0..n {
42 for j in (i + 1)..n {
43 if let Some(pt) = line_intersect_2d(&lines[i], &lines[j]) {
44 let existing = vertices
45 .iter_mut()
46 .find(|v| v.point.dist_sq(pt) < merge_eps);
47 if let Some(v) = existing {
48 if !v.line_indices.contains(&i) {
49 v.line_indices.push(i);
50 }
51 if !v.line_indices.contains(&j) {
52 v.line_indices.push(j);
53 }
54 } else {
55 vertices.push(ArrangementVertex {
56 point: pt,
57 line_indices: vec![i, j],
58 });
59 }
60 }
61 }
62 }
63 Self {
64 lines: lines.to_vec(),
65 vertices,
66 }
67 }
68 pub fn num_vertices(&self) -> usize {
70 self.vertices.len()
71 }
72 pub fn euler_face_count(&self) -> usize {
77 let n = self.lines.len();
78 n * (n - 1) / 2 + n + 1
79 }
80 pub fn vertices_on_line(&self, line_idx: usize) -> Vec<usize> {
82 let mut idxs: Vec<usize> = self
83 .vertices
84 .iter()
85 .enumerate()
86 .filter(|(_, v)| v.line_indices.contains(&line_idx))
87 .map(|(i, _)| i)
88 .collect();
89 let l = &self.lines[line_idx];
90 let dir = Point2::new(-l.b, l.a);
91 idxs.sort_by(|&a, &b| {
92 let ta = dir.dot(self.vertices[a].point);
93 let tb = dir.dot(self.vertices[b].point);
94 ta.partial_cmp(&tb).unwrap_or(std::cmp::Ordering::Equal)
95 });
96 idxs
97 }
98}
99#[derive(Debug, Clone)]
101pub struct HEFace {
102 pub half_edge: HalfEdgeId,
104}
105#[derive(Debug, Clone)]
107pub struct HalfEdge {
108 pub origin: VertexId,
110 pub twin: HalfEdgeId,
112 pub next: HalfEdgeId,
114 pub prev: HalfEdgeId,
116 pub face: Option<FaceId>,
118}
119#[derive(Debug, Clone, Default)]
125pub struct VisibilityGraph {
126 pub nodes: Vec<Point2>,
128 pub edges: Vec<Vec<usize>>,
130}
131impl VisibilityGraph {
132 pub fn build(obstacles: &[Obstacle2D]) -> Self {
134 let mut nodes: Vec<Point2> = Vec::new();
135 for obs in obstacles {
136 for &v in &obs.vertices {
137 nodes.push(v);
138 }
139 }
140 let all_edges: Vec<(Point2, Point2)> = obstacles.iter().flat_map(|o| o.edges()).collect();
141 let n = nodes.len();
142 let mut edges = vec![Vec::new(); n];
143 for i in 0..n {
144 for j in 0..n {
145 if i == j {
146 continue;
147 }
148 if segment_visible(nodes[i], nodes[j], &all_edges) {
149 edges[i].push(j);
150 }
151 }
152 }
153 Self { nodes, edges }
154 }
155 pub fn add_query_point(&mut self, pt: Point2, obstacles: &[Obstacle2D]) {
157 let all_edges: Vec<(Point2, Point2)> = obstacles.iter().flat_map(|o| o.edges()).collect();
158 let n = self.nodes.len();
159 let new_id = n;
160 self.nodes.push(pt);
161 self.edges.push(Vec::new());
162 for i in 0..n {
163 if segment_visible(pt, self.nodes[i], &all_edges) {
164 self.edges[new_id].push(i);
165 self.edges[i].push(new_id);
166 }
167 }
168 }
169 pub fn num_nodes(&self) -> usize {
171 self.nodes.len()
172 }
173 pub fn shortest_path(&self, src: usize, dst: usize) -> Option<Vec<usize>> {
175 use std::cmp::Reverse;
176 use std::collections::BinaryHeap;
177 let n = self.nodes.len();
178 let mut dist = vec![f64::INFINITY; n];
179 let mut prev = vec![usize::MAX; n];
180 dist[src] = 0.0;
181 let mut heap: BinaryHeap<Reverse<(u64, usize)>> = BinaryHeap::new();
182 heap.push(Reverse((0, src)));
183 while let Some(Reverse((d_raw, u))) = heap.pop() {
184 let d = d_raw as f64 / 1e9;
185 if d > dist[u] + 1e-12 {
186 continue;
187 }
188 if u == dst {
189 break;
190 }
191 for &v in &self.edges[u] {
192 let nd = dist[u] + self.nodes[u].dist(self.nodes[v]);
193 if nd < dist[v] - 1e-12 {
194 dist[v] = nd;
195 prev[v] = u;
196 heap.push(Reverse(((nd * 1e9) as u64, v)));
197 }
198 }
199 }
200 if dist[dst].is_infinite() {
201 return None;
202 }
203 let mut path = Vec::new();
204 let mut cur = dst;
205 while cur != usize::MAX {
206 path.push(cur);
207 cur = prev[cur];
208 }
209 path.reverse();
210 Some(path)
211 }
212}
213#[derive(Debug, Clone)]
215pub struct HEVertex {
216 pub position: Point3,
218 pub half_edge: Option<HalfEdgeId>,
220}
221#[derive(Debug, Clone, Copy)]
223pub struct Line2D {
224 pub a: f64,
226 pub b: f64,
228 pub c: f64,
230}
231impl Line2D {
232 pub fn through(p: Point2, q: Point2) -> Self {
234 let a = q.y - p.y;
235 let b = p.x - q.x;
236 let c = a * p.x + b * p.y;
237 Self { a, b, c }
238 }
239 pub fn signed_dist(&self, p: Point2) -> f64 {
241 let norm = (self.a * self.a + self.b * self.b).sqrt();
242 if norm < 1e-15 {
243 return 0.0;
244 }
245 (self.a * p.x + self.b * p.y - self.c) / norm
246 }
247 pub fn side(&self, p: Point2) -> f64 {
250 self.a * p.x + self.b * p.y - self.c
251 }
252}
253#[derive(Debug, Clone)]
257pub struct Trapezoid {
258 pub x_left: f64,
260 pub x_right: f64,
262 pub bottom_seg: usize,
264 pub top_seg: usize,
266 pub face: Option<usize>,
268}
269#[derive(Debug, Clone, Copy, PartialEq, Eq)]
271pub struct DelaunayTri {
272 pub a: usize,
274 pub b: usize,
276 pub c: usize,
278}
279impl DelaunayTri {
280 pub fn new(a: usize, b: usize, c: usize) -> Self {
282 Self { a, b, c }
283 }
284}
285#[derive(Debug, Clone, Copy)]
287pub struct Segment2D {
288 pub left: Point2,
290 pub right: Point2,
292}
293impl Segment2D {
294 pub fn new(a: Point2, b: Point2) -> Self {
296 if a.x <= b.x {
297 Self { left: a, right: b }
298 } else {
299 Self { left: b, right: a }
300 }
301 }
302 pub fn y_at(&self, x: f64) -> Option<f64> {
304 let dx = self.right.x - self.left.x;
305 if dx.abs() < 1e-15 {
306 return None;
307 }
308 let t = (x - self.left.x) / dx;
309 if !(0.0..=1.0).contains(&t) {
310 return None;
311 }
312 Some(self.left.y + t * (self.right.y - self.left.y))
313 }
314}
315#[derive(Debug, Clone, Default)]
321pub struct SlabPointLocator {
322 pub slab_xs: Vec<f64>,
324 pub slab_segments: Vec<Vec<usize>>,
328 pub segments: Vec<Segment2D>,
330 pub slab_faces: Vec<Vec<Option<usize>>>,
333}
334impl SlabPointLocator {
335 pub fn build(segments: &[Segment2D], _face_labels: &[Option<usize>]) -> Self {
339 let mut xs: Vec<f64> = Vec::new();
340 for s in segments {
341 xs.push(s.left.x);
342 xs.push(s.right.x);
343 }
344 xs.sort_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal));
345 xs.dedup_by(|a, b| (*a - *b).abs() < 1e-12);
346 let n_slabs = if xs.len() >= 2 { xs.len() - 1 } else { 0 };
347 let mut slab_segments = vec![Vec::new(); n_slabs];
348 let mut slab_faces = vec![Vec::new(); n_slabs];
349 for slab_i in 0..n_slabs {
350 let x_mid = (xs[slab_i] + xs[slab_i + 1]) / 2.0;
351 let mut active: Vec<(f64, usize)> = segments
352 .iter()
353 .enumerate()
354 .filter_map(|(idx, s)| s.y_at(x_mid).map(|y| (y, idx)))
355 .collect();
356 active.sort_by(|a, b| b.0.partial_cmp(&a.0).unwrap_or(std::cmp::Ordering::Equal));
357 slab_segments[slab_i] = active.iter().map(|(_, idx)| *idx).collect();
358 slab_faces[slab_i] = active.iter().map(|_| None).collect();
359 }
360 Self {
361 slab_xs: xs,
362 slab_segments,
363 segments: segments.to_vec(),
364 slab_faces,
365 }
366 }
367 pub fn locate(&self, p: Point2) -> Option<usize> {
370 let slab_i = self
371 .slab_xs
372 .partition_point(|&x| x <= p.x)
373 .saturating_sub(1);
374 if slab_i >= self.slab_segments.len() {
375 return None;
376 }
377 for &seg_idx in &self.slab_segments[slab_i] {
378 if let Some(y) = self.segments[seg_idx].y_at(p.x)
379 && y >= p.y
380 {
381 return Some(seg_idx);
382 }
383 }
384 None
385 }
386}
387#[derive(Debug, Clone)]
389pub struct ConvexFace3D {
390 pub verts: [usize; 3],
392 pub normal: Point3,
394}
395#[derive(Debug, Clone)]
397pub struct ArrangementVertex {
398 pub point: Point2,
400 pub line_indices: Vec<usize>,
402}
403#[derive(Debug, Clone)]
405pub struct Obstacle2D {
406 pub vertices: Vec<Point2>,
408}
409impl Obstacle2D {
410 pub fn new(vertices: Vec<Point2>) -> Self {
412 Self { vertices }
413 }
414 pub fn edges(&self) -> Vec<(Point2, Point2)> {
416 let n = self.vertices.len();
417 (0..n)
418 .map(|i| (self.vertices[i], self.vertices[(i + 1) % n]))
419 .collect()
420 }
421}
422#[derive(Debug, Clone, Copy, PartialEq)]
424pub struct Point2 {
425 pub x: f64,
427 pub y: f64,
429}
430impl Point2 {
431 pub fn new(x: f64, y: f64) -> Self {
433 Self { x, y }
434 }
435 pub fn scale(self, t: f64) -> Self {
437 Self::new(self.x * t, self.y * t)
438 }
439 pub fn cross(self, other: Self) -> f64 {
441 self.x * other.y - self.y * other.x
442 }
443 pub fn dot(self, other: Self) -> f64 {
445 self.x * other.x + self.y * other.y
446 }
447 pub fn dist_sq(self, other: Self) -> f64 {
449 let d = self - other;
450 d.dot(d)
451 }
452 pub fn dist(self, other: Self) -> f64 {
454 self.dist_sq(other).sqrt()
455 }
456 pub fn cross2(p0: Self, p1: Self, p2: Self) -> f64 {
458 (p1 - p0).cross(p2 - p0)
459 }
460}
461impl std::ops::Sub for Point2 {
462 type Output = Self;
463 fn sub(self, other: Self) -> Self {
464 Self::new(self.x - other.x, self.y - other.y)
465 }
466}
467impl std::ops::Add for Point2 {
468 type Output = Self;
469 fn add(self, other: Self) -> Self {
470 Self::new(self.x + other.x, self.y + other.y)
471 }
472}
473#[derive(Debug, Clone, Default)]
477pub struct HalfEdgeMesh {
478 pub half_edges: Vec<HalfEdge>,
480 pub vertices: Vec<HEVertex>,
482 pub faces: Vec<HEFace>,
484}
485impl HalfEdgeMesh {
486 pub fn new() -> Self {
488 Self::default()
489 }
490 pub fn add_vertex(&mut self, pos: Point3) -> VertexId {
492 let id = self.vertices.len();
493 self.vertices.push(HEVertex {
494 position: pos,
495 half_edge: None,
496 });
497 id
498 }
499 pub fn add_triangle(&mut self, v0: VertexId, v1: VertexId, v2: VertexId) -> FaceId {
504 let face_id = self.faces.len();
505 let he0 = self.half_edges.len();
506 let he1 = he0 + 1;
507 let he2 = he0 + 2;
508 self.half_edges.push(HalfEdge {
509 origin: v0,
510 twin: usize::MAX,
511 next: he1,
512 prev: he2,
513 face: Some(face_id),
514 });
515 self.half_edges.push(HalfEdge {
516 origin: v1,
517 twin: usize::MAX,
518 next: he2,
519 prev: he0,
520 face: Some(face_id),
521 });
522 self.half_edges.push(HalfEdge {
523 origin: v2,
524 twin: usize::MAX,
525 next: he0,
526 prev: he1,
527 face: Some(face_id),
528 });
529 self.faces.push(HEFace { half_edge: he0 });
530 if self.vertices[v0].half_edge.is_none() {
531 self.vertices[v0].half_edge = Some(he0);
532 }
533 if self.vertices[v1].half_edge.is_none() {
534 self.vertices[v1].half_edge = Some(he1);
535 }
536 if self.vertices[v2].half_edge.is_none() {
537 self.vertices[v2].half_edge = Some(he2);
538 }
539 face_id
540 }
541 pub fn face_vertices(&self, fid: FaceId) -> Vec<VertexId> {
543 let start = self.faces[fid].half_edge;
544 let mut verts = Vec::new();
545 let mut cur = start;
546 loop {
547 verts.push(self.half_edges[cur].origin);
548 cur = self.half_edges[cur].next;
549 if cur == start {
550 break;
551 }
552 }
553 verts
554 }
555 pub fn vertex_faces(&self, vid: VertexId) -> Vec<FaceId> {
557 let start_he = match self.vertices[vid].half_edge {
558 Some(h) => h,
559 None => return vec![],
560 };
561 let mut faces = Vec::new();
562 let mut cur = start_he;
563 loop {
564 if let Some(f) = self.half_edges[cur].face {
565 faces.push(f);
566 }
567 let twin = self.half_edges[cur].twin;
568 if twin == usize::MAX {
569 break;
570 }
571 cur = self.half_edges[twin].next;
572 if cur == start_he {
573 break;
574 }
575 }
576 faces
577 }
578 pub fn build_twin_links(&mut self) {
580 use std::collections::HashMap;
581 let n = self.half_edges.len();
582 let mut edge_map: HashMap<(usize, usize), usize> = HashMap::new();
583 for i in 0..n {
584 let origin = self.half_edges[i].origin;
585 let dest = self.half_edges[self.half_edges[i].next].origin;
586 edge_map.insert((origin, dest), i);
587 }
588 for i in 0..n {
589 let origin = self.half_edges[i].origin;
590 let dest = self.half_edges[self.half_edges[i].next].origin;
591 if let Some(&twin) = edge_map.get(&(dest, origin)) {
592 self.half_edges[i].twin = twin;
593 }
594 }
595 }
596 pub fn num_faces(&self) -> usize {
598 self.faces.len()
599 }
600 pub fn num_vertices(&self) -> usize {
602 self.vertices.len()
603 }
604 pub fn face_normal(&self, fid: FaceId) -> Point3 {
606 let verts = self.face_vertices(fid);
607 if verts.len() < 3 {
608 return [0.0; 3];
609 }
610 let p0 = self.vertices[verts[0]].position;
611 let p1 = self.vertices[verts[1]].position;
612 let p2 = self.vertices[verts[2]].position;
613 let e1 = sub3(p1, p0);
614 let e2 = sub3(p2, p0);
615 normalize3(cross3(e1, e2))
616 }
617 pub fn face_centroid(&self, fid: FaceId) -> Point3 {
619 let verts = self.face_vertices(fid);
620 let n = verts.len() as f64;
621 let mut acc = [0.0f64; 3];
622 for vid in &verts {
623 let p = self.vertices[*vid].position;
624 acc[0] += p[0];
625 acc[1] += p[1];
626 acc[2] += p[2];
627 }
628 [acc[0] / n, acc[1] / n, acc[2] / n]
629 }
630}
631#[derive(Debug, Clone)]
633pub struct ConvexHull3D {
634 pub vertices: Vec<Point3>,
636 pub faces: Vec<ConvexFace3D>,
638}
639impl ConvexHull3D {
640 pub fn volume(&self) -> f64 {
642 let mut vol = 0.0f64;
643 for face in &self.faces {
644 let a = self.vertices[face.verts[0]];
645 let b = self.vertices[face.verts[1]];
646 let c = self.vertices[face.verts[2]];
647 vol += dot3(a, cross3(b, c));
648 }
649 (vol / 6.0).abs()
650 }
651 pub fn surface_area(&self) -> f64 {
653 let mut area = 0.0f64;
654 for face in &self.faces {
655 let a = self.vertices[face.verts[0]];
656 let b = self.vertices[face.verts[1]];
657 let c = self.vertices[face.verts[2]];
658 let ab = sub3(b, a);
659 let ac = sub3(c, a);
660 area += 0.5 * mag3(cross3(ab, ac));
661 }
662 area
663 }
664}
665#[derive(Debug, Clone)]
667pub struct ArtGalleryResult {
668 pub guards: Vec<usize>,
670 pub covered: Vec<bool>,
673}