1use crate::math::{calc_distance, VERTEX_DIST_EPSILON};
10
11pub const QUICK_SORT_THRESHOLD: usize = 9;
18
19pub fn quick_sort<T, F>(arr: &mut [T], less: &F)
26where
27 T: Copy,
28 F: Fn(&T, &T) -> bool,
29{
30 if arr.len() < 2 {
31 return;
32 }
33
34 let mut stack = [0i32; 80];
35 let mut top: usize = 0;
36 let mut limit = arr.len() as i32;
37 let mut base = 0i32;
38
39 loop {
40 let len = limit - base;
41
42 if len > QUICK_SORT_THRESHOLD as i32 {
43 let pivot = base + len / 2;
44 arr.swap(base as usize, pivot as usize);
45
46 let mut i = base + 1;
47 let mut j = limit - 1;
48
49 if less(&arr[j as usize], &arr[i as usize]) {
51 arr.swap(j as usize, i as usize);
52 }
53 if less(&arr[base as usize], &arr[i as usize]) {
54 arr.swap(base as usize, i as usize);
55 }
56 if less(&arr[j as usize], &arr[base as usize]) {
57 arr.swap(j as usize, base as usize);
58 }
59
60 loop {
61 loop {
62 i += 1;
63 if !less(&arr[i as usize], &arr[base as usize]) {
64 break;
65 }
66 }
67 loop {
68 j -= 1;
69 if !less(&arr[base as usize], &arr[j as usize]) {
70 break;
71 }
72 }
73 if i > j {
74 break;
75 }
76 arr.swap(i as usize, j as usize);
77 }
78
79 arr.swap(base as usize, j as usize);
80
81 if j - base > limit - i {
83 stack[top] = base;
84 stack[top + 1] = j;
85 base = i;
86 } else {
87 stack[top] = i;
88 stack[top + 1] = limit;
89 limit = j;
90 }
91 top += 2;
92 } else {
93 let mut j = base;
95 let mut i = j + 1;
96 while i < limit {
97 while j >= base && less(&arr[(j + 1) as usize], &arr[j as usize]) {
98 arr.swap((j + 1) as usize, j as usize);
99 if j == base {
100 break;
101 }
102 j -= 1;
103 }
104 i += 1;
105 j = i - 1;
106 }
107
108 if top > 0 {
109 top -= 2;
110 base = stack[top];
111 limit = stack[top + 1];
112 } else {
113 break;
114 }
115 }
116 }
117}
118
119pub fn remove_duplicates<T, F>(arr: &mut [T], equal: &F) -> usize
124where
125 T: Copy,
126 F: Fn(&T, &T) -> bool,
127{
128 if arr.len() < 2 {
129 return arr.len();
130 }
131 let mut j = 1usize;
132 for i in 1..arr.len() {
133 if !equal(&arr[i], &arr[i - 1]) {
134 arr[j] = arr[i];
135 j += 1;
136 }
137 }
138 j
139}
140
141pub fn invert_container<T>(arr: &mut [T]) {
144 arr.reverse();
145}
146
147pub fn binary_search_pos<T, V, F>(arr: &[T], val: &V, less: &F) -> usize
152where
153 F: Fn(&V, &T) -> bool,
154{
155 if arr.is_empty() {
156 return 0;
157 }
158
159 let mut beg = 0usize;
160 let mut end = arr.len() - 1;
161
162 if less(val, &arr[0]) {
163 return 0;
164 }
165 if !less(val, &arr[end]) {
169 return end + 1;
170 }
171
172 while end - beg > 1 {
173 let mid = (end + beg) >> 1;
174 if less(val, &arr[mid]) {
175 end = mid;
176 } else {
177 beg = mid;
178 }
179 }
180 end
181}
182
183#[derive(Debug, Clone, Copy)]
194pub struct VertexDist {
195 pub x: f64,
196 pub y: f64,
197 pub dist: f64,
198}
199
200impl VertexDist {
201 pub fn new(x: f64, y: f64) -> Self {
202 Self { x, y, dist: 0.0 }
203 }
204
205 pub fn calc_dist(&mut self, val: &VertexDist) -> bool {
209 self.dist = calc_distance(self.x, self.y, val.x, val.y);
210 let ret = self.dist > VERTEX_DIST_EPSILON;
211 if !ret {
212 self.dist = 1.0 / VERTEX_DIST_EPSILON;
213 }
214 ret
215 }
216}
217
218#[derive(Debug, Clone, Copy)]
221pub struct VertexDistCmd {
222 pub x: f64,
223 pub y: f64,
224 pub dist: f64,
225 pub cmd: u32,
226}
227
228impl VertexDistCmd {
229 pub fn new(x: f64, y: f64, cmd: u32) -> Self {
230 Self {
231 x,
232 y,
233 dist: 0.0,
234 cmd,
235 }
236 }
237
238 pub fn calc_dist(&mut self, val: &VertexDistCmd) -> bool {
240 self.dist = calc_distance(self.x, self.y, val.x, val.y);
241 let ret = self.dist > VERTEX_DIST_EPSILON;
242 if !ret {
243 self.dist = 1.0 / VERTEX_DIST_EPSILON;
244 }
245 ret
246 }
247}
248
249pub struct VertexSequence {
262 vertices: Vec<VertexDist>,
263}
264
265impl VertexSequence {
266 pub fn new() -> Self {
267 Self {
268 vertices: Vec::new(),
269 }
270 }
271
272 pub fn size(&self) -> usize {
273 self.vertices.len()
274 }
275
276 pub fn is_empty(&self) -> bool {
277 self.vertices.is_empty()
278 }
279
280 pub fn add(&mut self, val: VertexDist) {
288 if self.vertices.len() > 1 {
289 let len = self.vertices.len();
290 let last = self.vertices[len - 1];
291 let keep = self.vertices[len - 2].calc_dist(&last);
292 if !keep {
293 self.vertices.pop();
294 }
295 }
296 self.vertices.push(val);
297 }
298
299 pub fn modify_last(&mut self, val: VertexDist) {
301 self.vertices.pop();
302 self.add(val);
303 }
304
305 pub fn close(&mut self, closed: bool) {
309 while self.vertices.len() > 1 {
313 let len = self.vertices.len();
314 let last = self.vertices[len - 1]; let keep = self.vertices[len - 2].calc_dist(&last); if keep {
317 break;
318 }
319 let t = self.vertices[self.vertices.len() - 1];
320 self.vertices.pop();
321 self.modify_last(t);
322 }
323
324 if closed {
325 while self.vertices.len() > 1 {
326 let len = self.vertices.len();
327 let first = self.vertices[0]; let keep = self.vertices[len - 1].calc_dist(&first); if keep {
331 break;
332 }
333 self.vertices.pop();
334 }
335 }
336 }
337
338 pub fn remove_all(&mut self) {
339 self.vertices.clear();
340 }
341
342 pub fn clear(&mut self) {
343 self.vertices.clear();
344 }
345
346 pub fn remove_last(&mut self) {
349 self.vertices.pop();
350 }
351
352 pub fn prev(&self, idx: usize) -> &VertexDist {
355 let len = self.vertices.len();
356 &self.vertices[(idx + len - 1) % len]
357 }
358
359 pub fn curr(&self, idx: usize) -> &VertexDist {
362 &self.vertices[idx]
363 }
364
365 pub fn next(&self, idx: usize) -> &VertexDist {
368 let len = self.vertices.len();
369 &self.vertices[(idx + 1) % len]
370 }
371
372 pub fn as_slice(&self) -> &[VertexDist] {
374 &self.vertices
375 }
376
377 pub fn as_mut_slice(&mut self) -> &mut [VertexDist] {
379 &mut self.vertices
380 }
381}
382
383impl Default for VertexSequence {
384 fn default() -> Self {
385 Self::new()
386 }
387}
388
389impl core::ops::Index<usize> for VertexSequence {
390 type Output = VertexDist;
391
392 fn index(&self, i: usize) -> &VertexDist {
393 &self.vertices[i]
394 }
395}
396
397impl core::ops::IndexMut<usize> for VertexSequence {
398 fn index_mut(&mut self, i: usize) -> &mut VertexDist {
399 &mut self.vertices[i]
400 }
401}
402
403pub fn shorten_path(vs: &mut VertexSequence, s: f64, closed: u32) {
411 if s > 0.0 && vs.size() > 1 {
412 let mut s = s;
413 let mut n = vs.size() as i32 - 2;
414 while n > 0 {
415 let d = vs[n as usize].dist;
416 if d > s {
417 break;
418 }
419 vs.remove_last();
420 s -= d;
421 n -= 1;
422 }
423 if vs.size() < 2 {
424 vs.remove_all();
425 } else {
426 let n = vs.size() - 1;
427 let prev_dist = vs[n - 1].dist;
428 let d = (prev_dist - s) / prev_dist;
429 let prev_x = vs[n - 1].x;
430 let prev_y = vs[n - 1].y;
431 let last_x = vs[n].x;
432 let last_y = vs[n].y;
433 vs[n].x = prev_x + (last_x - prev_x) * d;
434 vs[n].y = prev_y + (last_y - prev_y) * d;
435 let last_copy = vs[n];
437 if !vs.as_mut_slice()[n - 1].calc_dist(&last_copy) {
438 vs.remove_last();
439 }
440 vs.close(closed != 0);
441 }
442 }
443}
444
445#[cfg(test)]
450mod tests {
451 use super::*;
452
453 #[test]
454 fn test_quick_sort_basic() {
455 let mut arr = [5, 3, 8, 1, 9, 2, 7, 4, 6, 0];
456 quick_sort(&mut arr, &|a: &i32, b: &i32| *a < *b);
457 assert_eq!(arr, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
458 }
459
460 #[test]
461 fn test_quick_sort_already_sorted() {
462 let mut arr = [0, 1, 2, 3, 4];
463 quick_sort(&mut arr, &|a: &i32, b: &i32| *a < *b);
464 assert_eq!(arr, [0, 1, 2, 3, 4]);
465 }
466
467 #[test]
468 fn test_quick_sort_reverse() {
469 let mut arr = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0];
470 quick_sort(&mut arr, &|a: &i32, b: &i32| *a < *b);
471 assert_eq!(arr, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
472 }
473
474 #[test]
475 fn test_quick_sort_empty_and_single() {
476 let mut empty: [i32; 0] = [];
477 quick_sort(&mut empty, &|a: &i32, b: &i32| *a < *b);
478
479 let mut single = [42];
480 quick_sort(&mut single, &|a: &i32, b: &i32| *a < *b);
481 assert_eq!(single, [42]);
482 }
483
484 #[test]
485 fn test_quick_sort_small_partition() {
486 let mut arr = [5, 3, 1, 4, 2];
488 quick_sort(&mut arr, &|a: &i32, b: &i32| *a < *b);
489 assert_eq!(arr, [1, 2, 3, 4, 5]);
490 }
491
492 #[test]
493 fn test_quick_sort_large() {
494 let mut arr: Vec<i32> = (0..100).rev().collect();
495 quick_sort(&mut arr, &|a: &i32, b: &i32| *a < *b);
496 let expected: Vec<i32> = (0..100).collect();
497 assert_eq!(arr, expected);
498 }
499
500 #[test]
501 fn test_remove_duplicates() {
502 let mut arr = [1, 1, 2, 3, 3, 3, 4, 5, 5];
503 let n = remove_duplicates(&mut arr, &|a: &i32, b: &i32| *a == *b);
504 assert_eq!(n, 5);
505 assert_eq!(&arr[..n], &[1, 2, 3, 4, 5]);
506 }
507
508 #[test]
509 fn test_remove_duplicates_no_dups() {
510 let mut arr = [1, 2, 3, 4, 5];
511 let n = remove_duplicates(&mut arr, &|a: &i32, b: &i32| *a == *b);
512 assert_eq!(n, 5);
513 }
514
515 #[test]
516 fn test_remove_duplicates_all_same() {
517 let mut arr = [1, 1, 1, 1];
518 let n = remove_duplicates(&mut arr, &|a: &i32, b: &i32| *a == *b);
519 assert_eq!(n, 1);
520 }
521
522 #[test]
523 fn test_invert_container() {
524 let mut arr = [1, 2, 3, 4, 5];
525 invert_container(&mut arr);
526 assert_eq!(arr, [5, 4, 3, 2, 1]);
527 }
528
529 #[test]
530 fn test_binary_search_pos() {
531 let arr = [10, 20, 30, 40, 50];
532 assert_eq!(binary_search_pos(&arr, &0, &|a: &i32, b: &i32| *a < *b), 0);
533 assert_eq!(binary_search_pos(&arr, &25, &|a: &i32, b: &i32| *a < *b), 2);
534 assert_eq!(binary_search_pos(&arr, &60, &|a: &i32, b: &i32| *a < *b), 5);
535 }
536
537 #[test]
538 fn test_vertex_dist_coincident() {
539 let mut v1 = VertexDist::new(1.0, 2.0);
540 let v2 = VertexDist::new(1.0, 2.0);
541 assert!(!v1.calc_dist(&v2));
542 assert_eq!(v1.dist, 1.0 / VERTEX_DIST_EPSILON);
543 }
544
545 #[test]
546 fn test_vertex_dist_non_coincident() {
547 let mut v1 = VertexDist::new(0.0, 0.0);
548 let v2 = VertexDist::new(3.0, 4.0);
549 assert!(v1.calc_dist(&v2));
550 assert!((v1.dist - 5.0).abs() < 1e-10);
551 }
552
553 #[test]
554 fn test_vertex_sequence_basic() {
555 let mut seq = VertexSequence::new();
556 seq.add(VertexDist::new(0.0, 0.0));
557 seq.add(VertexDist::new(1.0, 0.0));
558 seq.add(VertexDist::new(2.0, 0.0));
559 assert_eq!(seq.size(), 3);
560 }
561
562 #[test]
563 fn test_vertex_sequence_removes_coincident() {
564 let mut seq = VertexSequence::new();
565 seq.add(VertexDist::new(0.0, 0.0));
566 seq.add(VertexDist::new(1.0, 0.0));
567 seq.add(VertexDist::new(1.0, 0.0));
569 assert_eq!(seq.size(), 3);
571 seq.add(VertexDist::new(2.0, 0.0));
573 assert_eq!(seq.size(), 3); }
575
576 #[test]
577 fn test_vertex_sequence_close() {
578 let mut seq = VertexSequence::new();
579 seq.add(VertexDist::new(0.0, 0.0));
580 seq.add(VertexDist::new(1.0, 0.0));
581 seq.add(VertexDist::new(0.0, 0.0)); seq.close(true);
584 assert_eq!(seq.size(), 2);
585 }
586
587 #[test]
588 fn test_vertex_sequence_prev_curr_next() {
589 let mut seq = VertexSequence::new();
590 seq.add(VertexDist::new(0.0, 0.0));
591 seq.add(VertexDist::new(1.0, 0.0));
592 seq.add(VertexDist::new(2.0, 0.0));
593
594 assert_eq!(seq.curr(1).x, 1.0);
596 assert_eq!(seq.next(2).x, 0.0);
598 assert_eq!(seq.prev(0).x, 2.0);
600 assert_eq!(seq.prev(2).x, 1.0);
602 }
603
604 #[test]
605 fn test_vertex_sequence_remove_last() {
606 let mut seq = VertexSequence::new();
607 seq.add(VertexDist::new(0.0, 0.0));
608 seq.add(VertexDist::new(1.0, 0.0));
609 seq.add(VertexDist::new(2.0, 0.0));
610 seq.remove_last();
611 assert_eq!(seq.size(), 2);
612 assert_eq!(seq[1].x, 1.0);
613 }
614
615 #[test]
616 fn test_shorten_path_basic() {
617 let mut seq = VertexSequence::new();
618 seq.add(VertexDist::new(0.0, 0.0));
619 seq.add(VertexDist::new(10.0, 0.0));
620 seq.add(VertexDist::new(20.0, 0.0));
621 seq.close(false);
623
624 shorten_path(&mut seq, 5.0, 0);
626 assert!(seq.size() >= 2);
627 let last = seq[seq.size() - 1];
629 assert!(last.x < 20.0, "Last x={} should be < 20", last.x);
630 }
631
632 #[test]
633 fn test_shorten_path_zero() {
634 let mut seq = VertexSequence::new();
635 seq.add(VertexDist::new(0.0, 0.0));
636 seq.add(VertexDist::new(10.0, 0.0));
637 seq.close(false);
638
639 shorten_path(&mut seq, 0.0, 0);
641 assert_eq!(seq.size(), 2);
642 }
643
644 #[test]
645 fn test_shorten_path_exceeds_length() {
646 let mut seq = VertexSequence::new();
647 seq.add(VertexDist::new(0.0, 0.0));
648 seq.add(VertexDist::new(10.0, 0.0));
649 seq.close(false);
650
651 shorten_path(&mut seq, 100.0, 0);
653 assert_eq!(seq.size(), 2);
655 assert!(
657 seq[1].x < 0.0,
658 "Last vertex x={} should be negative (overshot)",
659 seq[1].x
660 );
661 }
662
663 #[test]
664 fn test_shorten_path_removes_segment() {
665 let mut seq = VertexSequence::new();
666 seq.add(VertexDist::new(0.0, 0.0));
667 seq.add(VertexDist::new(5.0, 0.0));
668 seq.add(VertexDist::new(10.0, 0.0));
669 seq.add(VertexDist::new(20.0, 0.0));
670 seq.close(false);
671
672 shorten_path(&mut seq, 12.0, 0);
674 assert!(seq.size() >= 2);
676 let last = seq[seq.size() - 1];
677 assert!(last.x < 20.0, "Last x={} should be < 20", last.x);
679 }
680}