1use egui::{Align2, Color32, FontFamily, FontId, Pos2, Stroke, Ui};
9use rstar::AABB;
10use std::convert::{From, Into};
11use std::ops::{Add, Div, DivAssign, Mul, MulAssign, Sub};
12use std::time::Instant;
13
14#[derive(Copy, Clone, Debug, PartialEq)]
33pub struct RawPoint {
34 pub components: [f32; 2],
36}
37
38impl RawPoint {
39 pub fn new(x: f32, y: f32) -> Self {
41 Self { components: [x, y] }
42 }
43}
44
45impl rstar::Point for RawPoint {
46 type Scalar = f32;
47 const DIMENSIONS: usize = 2;
48
49 fn generate(mut generator: impl FnMut(usize) -> Self::Scalar) -> Self {
50 let mut components = [0.0; 2];
51 for (i, component) in components.iter_mut().enumerate() {
52 *component = generator(i);
53 }
54 Self { components }
55 }
56
57 fn nth(&self, index: usize) -> Self::Scalar {
58 self.components[index]
59 }
60
61 fn nth_mut(&mut self, index: usize) -> &mut Self::Scalar {
62 &mut self.components[index]
63 }
64}
65
66impl Default for RawPoint {
67 fn default() -> Self {
68 Self::new(0.00, 0.00)
69 }
70}
71
72impl Mul<i64> for RawPoint {
73 type Output = Self;
74
75 fn mul(self, rhs: i64) -> Self::Output {
76 Self {
77 components: [
78 self.components[0] * rhs as f32,
79 self.components[1] * rhs as f32,
80 ],
81 }
82 }
83}
84
85impl Mul<i32> for RawPoint {
86 type Output = Self;
87
88 fn mul(self, rhs: i32) -> Self::Output {
89 Self {
90 components: [
91 self.components[0] * rhs as f32,
92 self.components[1] * rhs as f32,
93 ],
94 }
95 }
96}
97
98impl Mul<u64> for RawPoint {
99 type Output = Self;
100
101 fn mul(self, rhs: u64) -> Self::Output {
102 Self {
103 components: [
104 self.components[0] * rhs as f32,
105 self.components[1] * rhs as f32,
106 ],
107 }
108 }
109}
110
111impl Mul<u32> for RawPoint {
112 type Output = Self;
113
114 fn mul(self, rhs: u32) -> Self::Output {
115 Self {
116 components: [
117 self.components[0] * rhs as f32,
118 self.components[1] * rhs as f32,
119 ],
120 }
121 }
122}
123
124impl Mul<f32> for RawPoint {
125 type Output = Self;
126
127 fn mul(self, rhs: f32) -> Self::Output {
128 Self {
129 components: [self.components[0] * rhs, self.components[1] * rhs],
130 }
131 }
132}
133
134impl MulAssign<i64> for RawPoint {
135 fn mul_assign(&mut self, rhs: i64) {
136 self.components[0] = self.components[0] * rhs as f32;
137 self.components[1] = self.components[1] * rhs as f32;
138 }
139}
140
141impl MulAssign<i32> for RawPoint {
142 fn mul_assign(&mut self, rhs: i32) {
143 self.components[0] = self.components[0] * rhs as f32;
144 self.components[1] = self.components[1] * rhs as f32;
145 }
146}
147
148impl MulAssign<u64> for RawPoint {
149 fn mul_assign(&mut self, rhs: u64) {
150 self.components[0] = self.components[0] * rhs as f32;
151 self.components[1] = self.components[1] * rhs as f32;
152 }
153}
154
155impl MulAssign<u32> for RawPoint {
156 fn mul_assign(&mut self, rhs: u32) {
157 self.components[0] = self.components[0] * rhs as f32;
158 self.components[1] = self.components[1] * rhs as f32;
159 }
160}
161
162impl MulAssign<f32> for RawPoint {
163 fn mul_assign(&mut self, rhs: f32) {
164 self.components[0] = self.components[0] * rhs;
165 self.components[1] = self.components[1] * rhs;
166 }
167}
168
169impl Div<i64> for RawPoint {
170 type Output = Self;
171
172 fn div(self, rhs: i64) -> Self::Output {
173 Self {
174 components: [
175 self.components[0] / rhs as f32,
176 self.components[1] / rhs as f32,
177 ],
178 }
179 }
180}
181
182impl Div<i32> for RawPoint {
183 type Output = Self;
184
185 fn div(self, rhs: i32) -> Self::Output {
186 Self {
187 components: [
188 self.components[0] / rhs as f32,
189 self.components[1] / rhs as f32,
190 ],
191 }
192 }
193}
194
195impl Div<u64> for RawPoint {
196 type Output = Self;
197
198 fn div(self, rhs: u64) -> Self::Output {
199 Self {
200 components: [
201 self.components[0] / rhs as f32,
202 self.components[1] / rhs as f32,
203 ],
204 }
205 }
206}
207
208impl Div<u32> for RawPoint {
209 type Output = Self;
210
211 fn div(self, rhs: u32) -> Self::Output {
212 Self {
213 components: [
214 self.components[0] / rhs as f32,
215 self.components[1] / rhs as f32,
216 ],
217 }
218 }
219}
220
221impl Div<f32> for RawPoint {
222 type Output = Self;
223
224 fn div(self, rhs: f32) -> Self::Output {
225 Self {
226 components: [self.components[0] / rhs, self.components[1] / rhs],
227 }
228 }
229}
230
231impl DivAssign<i64> for RawPoint {
232 fn div_assign(&mut self, rhs: i64) {
233 self.components[0] = self.components[0] / rhs as f32;
234 self.components[1] = self.components[1] / rhs as f32;
235 }
236}
237
238impl DivAssign<i32> for RawPoint {
239 fn div_assign(&mut self, rhs: i32) {
240 self.components[0] = self.components[0] / rhs as f32;
241 self.components[1] = self.components[1] / rhs as f32;
242 }
243}
244
245impl DivAssign<u64> for RawPoint {
246 fn div_assign(&mut self, rhs: u64) {
247 self.components[0] = self.components[0] / rhs as f32;
248 self.components[1] = self.components[1] / rhs as f32;
249 }
250}
251
252impl DivAssign<u32> for RawPoint {
253 fn div_assign(&mut self, rhs: u32) {
254 self.components[0] = self.components[0] / rhs as f32;
255 self.components[1] = self.components[1] / rhs as f32;
256 }
257}
258
259impl DivAssign<f32> for RawPoint {
260 fn div_assign(&mut self, rhs: f32) {
261 self.components[0] = self.components[0] / rhs;
262 self.components[1] = self.components[1] / rhs;
263 }
264}
265
266impl Add<RawPoint> for RawPoint {
267 type Output = RawPoint;
268 fn add(self, rhs: RawPoint) -> Self::Output {
269 Self {
270 components: [
271 self.components[0] + rhs.components[0],
272 self.components[1] + rhs.components[1],
273 ],
274 }
275 }
276}
277
278impl Sub<RawPoint> for RawPoint {
279 type Output = RawPoint;
280 fn sub(self, rhs: RawPoint) -> Self::Output {
281 Self {
282 components: [
283 self.components[0] - rhs.components[0],
284 self.components[1] - rhs.components[1],
285 ],
286 }
287 }
288}
289
290impl Add<&RawPoint> for RawPoint {
291 type Output = RawPoint;
292 fn add(self, rhs: &RawPoint) -> Self::Output {
293 Self {
294 components: [
295 self.components[0] + rhs.components[0],
296 self.components[1] + rhs.components[1],
297 ],
298 }
299 }
300}
301
302impl Sub<&RawPoint> for RawPoint {
303 type Output = RawPoint;
304 fn sub(self, rhs: &RawPoint) -> Self::Output {
305 Self {
306 components: [
307 self.components[0] - rhs.components[0],
308 self.components[1] - rhs.components[1],
309 ],
310 }
311 }
312}
313
314impl From<[f32; 2]> for RawPoint {
315 fn from(value: [f32; 2]) -> Self {
316 Self { components: value }
317 }
318}
319
320impl From<Pos2> for RawPoint {
321 fn from(value: Pos2) -> Self {
322 Self {
323 components: [value.x, value.y],
324 }
325 }
326}
327
328impl From<[i64; 2]> for RawPoint {
329 fn from(value: [i64; 2]) -> Self {
330 Self {
331 components: [value[0] as f32, value[1] as f32],
332 }
333 }
334}
335
336impl From<[i32; 2]> for RawPoint {
337 fn from(value: [i32; 2]) -> Self {
338 Self {
339 components: [value[0] as f32, value[1] as f32],
340 }
341 }
342}
343
344impl From<[i16; 2]> for RawPoint {
345 fn from(value: [i16; 2]) -> Self {
346 Self {
347 components: [value[0] as f32, value[1] as f32],
348 }
349 }
350}
351
352impl From<[i8; 2]> for RawPoint {
353 fn from(value: [i8; 2]) -> Self {
354 Self {
355 components: [value[0] as f32, value[1] as f32],
356 }
357 }
358}
359
360impl From<RawPoint> for [f32; 2] {
361 fn from(val: RawPoint) -> Self {
362 [val.components[0], val.components[1]]
363 }
364}
365
366impl From<RawPoint> for Pos2 {
367 fn from(val: RawPoint) -> Self {
368 Pos2::from(val.components)
369 }
370}
371
372#[derive(Copy, Clone, Debug)]
374pub struct RawLine {
375 pub points: [RawPoint; 2],
377}
378
379impl RawLine {
380 pub fn new(a: RawPoint, b: RawPoint) -> Self {
382 Self { points: [a, b] }
383 }
384
385 pub fn distance(self) -> f32 {
387 let x = self.points[0].components[0] - self.points[1].components[0];
388 let y = self.points[0].components[1] - self.points[1].components[1];
389 (x.powi(2) + y.powi(2)).sqrt()
390 }
391
392 pub fn midpoint(self) -> RawPoint {
394 let x = (self.points[0].components[0] + self.points[1].components[0]) / 2.0;
395 let y = (self.points[0].components[1] + self.points[1].components[1]) / 2.0;
396 RawPoint::new(x, y)
397 }
398
399 pub fn distance_to_point(self, point: RawPoint) -> f32 {
417 let [a, b] = self.points;
418 let ab = b - a;
419 let ap = point - a;
420 let len_sq = ab.components[0].powi(2) + ab.components[1].powi(2);
421 if len_sq == 0.0 {
422 return (ap.components[0].powi(2) + ap.components[1].powi(2)).sqrt();
424 }
425 let t = ((ap.components[0] * ab.components[0] + ap.components[1] * ab.components[1])
426 / len_sq)
427 .clamp(0.0, 1.0);
428 let closest = a + ab * t;
429 let d = point - closest;
430 (d.components[0].powi(2) + d.components[1].powi(2)).sqrt()
431 }
432}
433
434impl From<RawLine> for [Pos2; 2] {
435 fn from(val: RawLine) -> Self {
436 let position1 = val.points[0].into();
437 let position2 = val.points[1].into();
438 [position1, position2]
439 }
440}
441
442impl From<[[i64; 2]; 2]> for RawLine {
443 fn from(value: [[i64; 2]; 2]) -> Self {
444 Self {
445 points: [RawPoint::from(value[0]), RawPoint::from(value[1])],
446 }
447 }
448}
449
450#[derive(Clone, Debug)]
457pub struct MapStyle {
458 pub border: Option<Stroke>,
460 pub line: Option<Stroke>,
462 pub fill_color: Color32,
464 pub text_color: Color32,
466 pub font: Option<FontId>,
468 pub background_color: Color32,
470 pub alert_color: Color32,
472}
473
474impl MapStyle {
475 pub fn new() -> Self {
477 MapStyle {
478 border: None,
479 line: None,
480 fill_color: Color32::TRANSPARENT,
481 text_color: Color32::TRANSPARENT,
482 font: None,
483 background_color: Color32::TRANSPARENT,
484 alert_color: Color32::TRANSPARENT,
485 }
486 }
487}
488
489impl Default for MapStyle {
490 fn default() -> Self {
491 MapStyle::new()
492 }
493}
494
495impl MapStyle {
496 fn scaled(mut self, factor: f32) -> Self {
499 if let Some(border) = self.border.as_mut() {
500 border.width *= factor;
501 }
502 if let Some(line) = self.line.as_mut() {
503 line.width *= factor;
504 }
505 if let Some(font) = self.font.as_mut() {
506 font.size *= factor;
507 }
508 self
509 }
510}
511
512impl Mul<i64> for MapStyle {
513 type Output = Self;
514
515 fn mul(self, rhs: i64) -> Self::Output {
516 self.scaled(rhs as f32)
517 }
518}
519
520impl Mul<i32> for MapStyle {
521 type Output = Self;
522
523 fn mul(self, rhs: i32) -> Self::Output {
524 self.scaled(rhs as f32)
525 }
526}
527
528impl Mul<f32> for MapStyle {
529 type Output = Self;
530
531 fn mul(self, rhs: f32) -> Self::Output {
532 self.scaled(rhs)
533 }
534}
535
536impl Mul<f64> for MapStyle {
537 type Output = Self;
538
539 fn mul(self, rhs: f64) -> Self::Output {
540 self.scaled(rhs as f32)
541 }
542}
543
544impl Div<i64> for MapStyle {
545 type Output = Self;
546
547 fn div(self, rhs: i64) -> Self::Output {
548 self.scaled(1.0 / rhs as f32)
549 }
550}
551
552impl Div<i32> for MapStyle {
553 type Output = Self;
554
555 fn div(self, rhs: i32) -> Self::Output {
556 self.scaled(1.0 / rhs as f32)
557 }
558}
559
560impl Div<f32> for MapStyle {
561 type Output = Self;
562
563 fn div(self, rhs: f32) -> Self::Output {
564 self.scaled(1.0 / rhs)
565 }
566}
567
568impl Div<f64> for MapStyle {
569 type Output = Self;
570
571 fn div(self, rhs: f64) -> Self::Output {
572 self.scaled(1.0 / rhs as f32)
573 }
574}
575
576#[derive(Clone, Debug)]
580pub struct MapLabel {
581 pub text: String,
583 pub center: Pos2,
585}
586
587impl Default for MapLabel {
588 fn default() -> Self {
589 MapLabel::new()
590 }
591}
592
593impl MapLabel {
594 pub fn new() -> Self {
596 MapLabel {
597 text: String::new(),
598 center: Pos2::new(0.00, 0.00),
599 }
600 }
601}
602
603#[derive(Clone, Copy, Debug, PartialEq)]
619pub struct MapSegment {
620 pub id: (usize, usize),
623 pub point1: [f32; 2],
625 pub point2: [f32; 2],
627}
628
629impl MapSegment {
630 pub fn new(id: (usize, usize), point1: [f32; 2], point2: [f32; 2]) -> Self {
632 Self { id, point1, point2 }
633 }
634
635 pub(crate) fn raw_line(&self) -> RawLine {
638 RawLine::new(RawPoint::from(self.point1), RawPoint::from(self.point2))
639 }
640}
641
642impl rstar::RTreeObject for MapSegment {
643 type Envelope = AABB<[f32; 2]>;
644
645 fn envelope(&self) -> Self::Envelope {
646 AABB::from_corners(
647 [
648 self.point1[0].min(self.point2[0]),
649 self.point1[1].min(self.point2[1]),
650 ],
651 [
652 self.point1[0].max(self.point2[0]),
653 self.point1[1].max(self.point2[1]),
654 ],
655 )
656 }
657}
658
659#[derive(Clone, Debug, PartialEq)]
682pub struct MapPoint {
683 pub coords: [f32; 2],
685 pub id: usize,
687 pub name: Option<String>,
689 pub connections: Vec<(usize, usize)>,
699}
700
701impl MapPoint {
702 pub fn new(id: usize, coords: [f32; 2]) -> MapPoint {
704 MapPoint {
705 coords,
706 id,
707 connections: Vec::new(),
708 name: None,
709 }
710 }
711
712 pub fn get_id(&self) -> usize {
714 self.id
715 }
716
717 pub fn get_name(&self) -> String {
719 self.name.clone().unwrap_or_default()
720 }
721
722 pub fn set_name(&mut self, value: String) {
724 self.name = Some(value);
725 }
726}
727
728impl From<std::collections::hash_map::OccupiedEntry<'_, usize, MapPoint>> for MapPoint {
729 fn from(value: std::collections::hash_map::OccupiedEntry<'_, usize, MapPoint>) -> Self {
730 let k = value.get();
731 k.clone()
732 }
733}
734
735#[derive(Clone)]
736pub(crate) struct MapBounds {
737 pub min: RawPoint,
738 pub max: RawPoint,
739 pub pos: RawPoint,
740 pub dist: f32,
741}
742
743impl MapBounds {
744 pub fn new() -> Self {
745 MapBounds {
746 min: RawPoint::default(),
747 max: RawPoint::default(),
748 pos: RawPoint::default(),
749 dist: 0.0,
750 }
751 }
752}
753
754impl Default for MapBounds {
755 fn default() -> Self {
756 MapBounds::new()
757 }
758}
759
760pub(crate) struct TextSettings {
761 pub position: RawPoint,
762 pub anchor: Align2,
763 pub text: String,
764 pub size: f32,
765 pub family: FontFamily,
766 pub text_color: Color32,
767}
768
769#[derive(Clone, Debug)]
776pub struct MapSettings {
777 pub max_zoom: f32,
779 pub min_zoom: f32,
781 pub line_visible_zoom: f32,
783 pub label_visible_zoom: f32,
787 pub node_text_visibility: VisibilitySetting,
789 pub styles: Vec<MapStyle>,
792}
793
794impl MapSettings {
795 pub fn new() -> Self {
801 MapSettings {
802 max_zoom: 0.0,
803 min_zoom: 0.0,
804 line_visible_zoom: 0.0,
805 label_visible_zoom: 0.0,
806 node_text_visibility: VisibilitySetting::Always,
807 styles: vec![MapStyle::new()],
808 }
809 }
810}
811
812impl Default for MapSettings {
813 fn default() -> Self {
817 let mut obj = MapSettings {
818 max_zoom: 2.0,
819 min_zoom: 0.1,
820 line_visible_zoom: 0.2,
821 label_visible_zoom: 0.58,
822 node_text_visibility: VisibilitySetting::Always,
823 styles: Vec::new(),
824 };
825
826 obj.styles.push(MapStyle {
828 border: Some(egui::Stroke {
829 width: 2.0,
830 color: Color32::from_rgb(216, 142, 58),
831 }),
832 line: Some(egui::Stroke {
833 width: 2.0,
834 color: Color32::DARK_RED,
835 }),
836 fill_color: Color32::from_rgb(216, 142, 58),
837 text_color: Color32::DARK_GREEN,
838 font: Some(FontId::new(12.00, FontFamily::Proportional)),
839 background_color: Color32::WHITE,
840 alert_color: Color32::from_rgb(246, 30, 131),
841 });
842
843 obj.styles.push(MapStyle {
845 border: Some(egui::Stroke {
846 width: 2.0,
847 color: Color32::GOLD,
848 }),
849 line: Some(egui::Stroke {
850 width: 2.0,
851 color: Color32::LIGHT_RED,
852 }),
853 fill_color: Color32::GOLD,
854 text_color: Color32::LIGHT_GREEN,
855 font: Some(FontId::new(12.00, FontFamily::Proportional)),
856 background_color: Color32::DARK_GRAY,
857 alert_color: Color32::from_rgb(128, 12, 67),
858 });
859 obj
860 }
861}
862
863#[derive(Clone, Debug, PartialEq)]
865pub enum VisibilitySetting {
866 Hidden,
868 Hover,
870 Always,
872}
873
874pub trait ContextMenuManager {
893 fn ui(&self, ui: &mut Ui);
895}
896
897pub trait NodeTemplate {
993 fn node_ui(&self, ui: &mut Ui, _viewport_position: Pos2, _zoom: f32, _point: &MapPoint);
999
1000 fn selection_ui(&self, ui: &mut Ui, _viewport_position: Pos2, _zoom: f32);
1005
1006 fn notification_ui(
1014 &self,
1015 ui: &mut Ui,
1016 _viewport_position: Pos2,
1017 _zoom: f32,
1018 initial_time: Instant,
1019 color: Color32,
1020 ) -> bool;
1021
1022 fn marker_ui(&self, ui: &mut Ui, _viewport_position: Pos2, _zoom: f32);
1029}
1030
1031#[cfg(test)]
1032mod tests {
1033 use super::*;
1034 use std::collections::HashMap;
1035
1036 #[test]
1039 fn raw_point_new() {
1040 let p = RawPoint::new(3.5, -2.0);
1041 assert_eq!(p.components, [3.5, -2.0]);
1042 }
1043
1044 #[test]
1047 fn map_segment_new_computes_tight_aabb() {
1048 let seg = MapSegment::new((1, 2), [10.0, -5.0], [-2.0, 7.0]);
1049 assert_eq!(seg.id, (1, 2));
1050 let envelope: AABB<[f32; 2]> = rstar::RTreeObject::envelope(&seg);
1051 assert_eq!(envelope.lower(), [-2.0, -5.0]);
1052 assert_eq!(envelope.upper(), [10.0, 7.0]);
1053 assert_eq!(seg.raw_line().points[0].components, [10.0, -5.0]);
1054 assert_eq!(seg.raw_line().points[1].components, [-2.0, 7.0]);
1055 }
1056
1057 #[test]
1058 fn map_segment_envelope_returns_its_aabb() {
1059 let seg = MapSegment::new((1, 2), [0.0, 0.0], [4.0, 2.0]);
1060 let envelope: AABB<[f32; 2]> = rstar::RTreeObject::envelope(&seg);
1061 assert_eq!(envelope.lower(), [0.0, 0.0]);
1062 assert_eq!(envelope.upper(), [4.0, 2.0]);
1063 }
1064
1065 #[test]
1066 fn map_segment_degenerate_line_has_point_aabb() {
1067 let seg = MapSegment::new((1, 2), [3.0, 3.0], [3.0, 3.0]);
1069 let envelope: AABB<[f32; 2]> = rstar::RTreeObject::envelope(&seg);
1070 assert_eq!(envelope.lower(), [3.0, 3.0]);
1071 assert_eq!(envelope.upper(), [3.0, 3.0]);
1072 }
1073
1074 #[test]
1075 fn raw_point_default() {
1076 let p = RawPoint::default();
1077 assert_eq!(p.components, [0.0, 0.0]);
1078 }
1079
1080 #[test]
1081 fn raw_point_mul_i64() {
1082 let p = RawPoint::new(2.0, -3.0) * 3i64;
1083 assert_eq!(p.components, [6.0, -9.0]);
1084 }
1085
1086 #[test]
1087 fn raw_point_mul_i32() {
1088 let p = RawPoint::new(2.0, -3.0) * 3i32;
1089 assert_eq!(p.components, [6.0, -9.0]);
1090 }
1091
1092 #[test]
1093 fn raw_point_mul_u64() {
1094 let p = RawPoint::new(2.0, -3.0) * 3u64;
1095 assert_eq!(p.components, [6.0, -9.0]);
1096 }
1097
1098 #[test]
1099 fn raw_point_mul_u32() {
1100 let p = RawPoint::new(2.0, -3.0) * 3u32;
1101 assert_eq!(p.components, [6.0, -9.0]);
1102 }
1103
1104 #[test]
1105 fn raw_point_mul_f32() {
1106 let p = RawPoint::new(2.0, -3.0) * 0.5f32;
1107 assert_eq!(p.components, [1.0, -1.5]);
1108 }
1109
1110 #[test]
1111 fn raw_point_mul_assign_i64() {
1112 let mut p = RawPoint::new(2.0, -3.0);
1113 p *= 3i64;
1114 assert_eq!(p.components, [6.0, -9.0]);
1115 }
1116
1117 #[test]
1118 fn raw_point_mul_assign_i32() {
1119 let mut p = RawPoint::new(2.0, -3.0);
1120 p *= 3i32;
1121 assert_eq!(p.components, [6.0, -9.0]);
1122 }
1123
1124 #[test]
1125 fn raw_point_mul_assign_u64() {
1126 let mut p = RawPoint::new(2.0, -3.0);
1127 p *= 3u64;
1128 assert_eq!(p.components, [6.0, -9.0]);
1129 }
1130
1131 #[test]
1132 fn raw_point_mul_assign_u32() {
1133 let mut p = RawPoint::new(2.0, -3.0);
1134 p *= 3u32;
1135 assert_eq!(p.components, [6.0, -9.0]);
1136 }
1137
1138 #[test]
1139 fn raw_point_mul_assign_f32() {
1140 let mut p = RawPoint::new(2.0, -3.0);
1141 p *= 0.5f32;
1142 assert_eq!(p.components, [1.0, -1.5]);
1143 }
1144
1145 #[test]
1146 fn raw_point_div_i64() {
1147 let p = RawPoint::new(6.0, -9.0) / 3i64;
1148 assert_eq!(p.components, [2.0, -3.0]);
1149 }
1150
1151 #[test]
1152 fn raw_point_div_i32() {
1153 let p = RawPoint::new(6.0, -9.0) / 3i32;
1154 assert_eq!(p.components, [2.0, -3.0]);
1155 }
1156
1157 #[test]
1158 fn raw_point_div_u64() {
1159 let p = RawPoint::new(6.0, -9.0) / 3u64;
1160 assert_eq!(p.components, [2.0, -3.0]);
1161 }
1162
1163 #[test]
1164 fn raw_point_div_u32() {
1165 let p = RawPoint::new(6.0, -9.0) / 3u32;
1166 assert_eq!(p.components, [2.0, -3.0]);
1167 }
1168
1169 #[test]
1170 fn raw_point_div_f32() {
1171 let p = RawPoint::new(1.0, -1.5) / 0.5f32;
1172 assert_eq!(p.components, [2.0, -3.0]);
1173 }
1174
1175 #[test]
1176 fn raw_point_div_assign_i64() {
1177 let mut p = RawPoint::new(6.0, -9.0);
1178 p /= 3i64;
1179 assert_eq!(p.components, [2.0, -3.0]);
1180 }
1181
1182 #[test]
1183 fn raw_point_div_assign_i32() {
1184 let mut p = RawPoint::new(6.0, -9.0);
1185 p /= 3i32;
1186 assert_eq!(p.components, [2.0, -3.0]);
1187 }
1188
1189 #[test]
1190 fn raw_point_div_assign_u64() {
1191 let mut p = RawPoint::new(6.0, -9.0);
1192 p /= 3u64;
1193 assert_eq!(p.components, [2.0, -3.0]);
1194 }
1195
1196 #[test]
1197 fn raw_point_div_assign_u32() {
1198 let mut p = RawPoint::new(6.0, -9.0);
1199 p /= 3u32;
1200 assert_eq!(p.components, [2.0, -3.0]);
1201 }
1202
1203 #[test]
1204 fn raw_point_div_assign_f32() {
1205 let mut p = RawPoint::new(1.0, -1.5);
1206 p /= 0.5f32;
1207 assert_eq!(p.components, [2.0, -3.0]);
1208 }
1209
1210 #[test]
1211 fn raw_point_add() {
1212 let a = RawPoint::new(1.0, 2.0);
1213 let b = RawPoint::new(3.0, -4.0);
1214 let c = a + b;
1215 assert_eq!(c.components, [4.0, -2.0]);
1216 }
1217
1218 #[test]
1219 fn raw_point_sub() {
1220 let a = RawPoint::new(1.0, 2.0);
1221 let b = RawPoint::new(3.0, -4.0);
1222 let c = a - b;
1223 assert_eq!(c.components, [-2.0, 6.0]);
1224 }
1225
1226 #[test]
1227 #[allow(clippy::op_ref)] fn raw_point_add_ref() {
1229 let a = RawPoint::new(1.0, 2.0);
1230 let b = RawPoint::new(3.0, -4.0);
1231 let c = a + &b;
1232 assert_eq!(c.components, [4.0, -2.0]);
1233 assert_eq!(b.components, [3.0, -4.0]);
1235 }
1236
1237 #[test]
1238 #[allow(clippy::op_ref)] fn raw_point_sub_ref() {
1240 let a = RawPoint::new(1.0, 2.0);
1241 let b = RawPoint::new(3.0, -4.0);
1242 let c = a - &b;
1243 assert_eq!(c.components, [-2.0, 6.0]);
1244 assert_eq!(b.components, [3.0, -4.0]);
1245 }
1246
1247 #[test]
1248 fn raw_point_from_f32_array() {
1249 let p = RawPoint::from([1.5f32, -2.5f32]);
1250 assert_eq!(p.components, [1.5, -2.5]);
1251 }
1252
1253 #[test]
1254 fn raw_point_from_i64_array() {
1255 let p = RawPoint::from([3i64, -4i64]);
1256 assert_eq!(p.components, [3.0, -4.0]);
1257 }
1258
1259 #[test]
1260 fn raw_point_from_i32_array() {
1261 let p = RawPoint::from([3i32, -4i32]);
1262 assert_eq!(p.components, [3.0, -4.0]);
1263 }
1264
1265 #[test]
1266 fn raw_point_from_i16_array() {
1267 let p = RawPoint::from([3i16, -4i16]);
1268 assert_eq!(p.components, [3.0, -4.0]);
1269 }
1270
1271 #[test]
1272 fn raw_point_from_i8_array() {
1273 let p = RawPoint::from([3i8, -4i8]);
1274 assert_eq!(p.components, [3.0, -4.0]);
1275 }
1276
1277 #[test]
1278 fn raw_point_from_pos2() {
1279 let p = RawPoint::from(Pos2::new(7.0, 8.0));
1280 assert_eq!(p.components, [7.0, 8.0]);
1281 }
1282
1283 #[test]
1284 fn raw_point_into_f32_array() {
1285 let arr: [f32; 2] = RawPoint::new(7.0, 8.0).into();
1286 assert_eq!(arr, [7.0, 8.0]);
1287 }
1288
1289 #[test]
1290 fn raw_point_into_pos2() {
1291 let pos: Pos2 = RawPoint::new(7.0, 8.0).into();
1292 assert_eq!(pos, Pos2::new(7.0, 8.0));
1293 }
1294
1295 #[test]
1298 fn raw_line_new() {
1299 let a = RawPoint::new(1.0, 2.0);
1300 let b = RawPoint::new(3.0, 4.0);
1301 let line = RawLine::new(a, b);
1302 assert_eq!(line.points[0].components, [1.0, 2.0]);
1303 assert_eq!(line.points[1].components, [3.0, 4.0]);
1304 }
1305
1306 #[test]
1307 fn raw_line_distance() {
1308 let line = RawLine::new(RawPoint::new(0.0, 0.0), RawPoint::new(3.0, 4.0));
1310 assert_eq!(line.distance(), 5.0);
1311 }
1312
1313 #[test]
1314 fn raw_line_distance_zero() {
1315 let line = RawLine::new(RawPoint::new(2.0, 2.0), RawPoint::new(2.0, 2.0));
1316 assert_eq!(line.distance(), 0.0);
1317 }
1318
1319 #[test]
1320 fn raw_line_midpoint() {
1321 let line = RawLine::new(RawPoint::new(0.0, 0.0), RawPoint::new(4.0, 6.0));
1322 let mid = line.midpoint();
1323 assert_eq!(mid.components, [2.0, 3.0]);
1324 }
1325
1326 #[test]
1327 fn raw_line_distance_to_point_on_segment() {
1328 let line = RawLine::new(RawPoint::new(0.0, 0.0), RawPoint::new(10.0, 0.0));
1329 assert_eq!(line.distance_to_point(RawPoint::new(5.0, 3.0)), 3.0);
1330 assert_eq!(line.distance_to_point(RawPoint::new(5.0, 0.0)), 0.0);
1331 }
1332
1333 #[test]
1334 fn raw_line_distance_to_point_beyond_endpoints() {
1335 let line = RawLine::new(RawPoint::new(0.0, 0.0), RawPoint::new(10.0, 0.0));
1336 assert_eq!(line.distance_to_point(RawPoint::new(14.0, 0.0)), 4.0);
1338 assert_eq!(line.distance_to_point(RawPoint::new(-3.0, -4.0)), 5.0);
1339 }
1340
1341 #[test]
1342 fn raw_line_distance_to_point_degenerate_segment() {
1343 let line = RawLine::new(RawPoint::new(1.0, 1.0), RawPoint::new(1.0, 1.0));
1344 assert_eq!(line.distance_to_point(RawPoint::new(4.0, 5.0)), 5.0);
1345 }
1346
1347 #[test]
1348 fn raw_line_into_pos2_array() {
1349 let line = RawLine::new(RawPoint::new(1.0, 2.0), RawPoint::new(3.0, 4.0));
1350 let arr: [Pos2; 2] = line.into();
1351 assert_eq!(arr, [Pos2::new(1.0, 2.0), Pos2::new(3.0, 4.0)]);
1352 }
1353
1354 #[test]
1355 fn raw_line_from_i64_arrays() {
1356 let line = RawLine::from([[1i64, 2i64], [3i64, 4i64]]);
1357 assert_eq!(line.points[0].components, [1.0, 2.0]);
1358 assert_eq!(line.points[1].components, [3.0, 4.0]);
1359 }
1360
1361 fn full_style() -> MapStyle {
1364 MapStyle {
1365 border: Some(Stroke::new(2.0, Color32::RED)),
1366 line: Some(Stroke::new(4.0, Color32::BLUE)),
1367 fill_color: Color32::GREEN,
1368 text_color: Color32::WHITE,
1369 font: Some(FontId::new(10.0, FontFamily::Proportional)),
1370 background_color: Color32::BLACK,
1371 alert_color: Color32::YELLOW,
1372 }
1373 }
1374
1375 #[test]
1376 fn map_style_new() {
1377 let s = MapStyle::new();
1378 assert!(s.border.is_none());
1379 assert!(s.line.is_none());
1380 assert!(s.font.is_none());
1381 assert_eq!(s.fill_color, Color32::TRANSPARENT);
1382 assert_eq!(s.text_color, Color32::TRANSPARENT);
1383 assert_eq!(s.background_color, Color32::TRANSPARENT);
1384 assert_eq!(s.alert_color, Color32::TRANSPARENT);
1385 }
1386
1387 #[test]
1388 fn map_style_default_equals_new() {
1389 let s = MapStyle::default();
1390 assert!(s.border.is_none());
1391 assert!(s.line.is_none());
1392 assert!(s.font.is_none());
1393 }
1394
1395 #[test]
1396 fn map_style_mul_i64() {
1397 let s = full_style() * 2i64;
1398 assert_eq!(s.border.unwrap().width, 4.0);
1399 assert_eq!(s.line.unwrap().width, 8.0);
1400 assert_eq!(s.font.unwrap().size, 20.0);
1401 }
1402
1403 #[test]
1404 fn map_style_mul_i32() {
1405 let s = full_style() * 2i32;
1406 assert_eq!(s.border.unwrap().width, 4.0);
1407 assert_eq!(s.line.unwrap().width, 8.0);
1408 assert_eq!(s.font.unwrap().size, 20.0);
1409 }
1410
1411 #[test]
1412 fn map_style_mul_f32() {
1413 let s = full_style() * 0.5f32;
1414 assert_eq!(s.border.unwrap().width, 1.0);
1415 assert_eq!(s.line.unwrap().width, 2.0);
1416 assert_eq!(s.font.unwrap().size, 5.0);
1417 }
1418
1419 #[test]
1420 fn map_style_mul_f64() {
1421 let s = full_style() * 0.5f64;
1422 assert_eq!(s.border.unwrap().width, 1.0);
1423 assert_eq!(s.line.unwrap().width, 2.0);
1424 assert_eq!(s.font.unwrap().size, 5.0);
1425 }
1426
1427 #[test]
1428 fn map_style_div_i64() {
1429 let s = full_style() / 2i64;
1430 assert_eq!(s.border.unwrap().width, 1.0);
1431 assert_eq!(s.line.unwrap().width, 2.0);
1432 assert_eq!(s.font.unwrap().size, 5.0);
1433 }
1434
1435 #[test]
1436 fn map_style_div_i32() {
1437 let s = full_style() / 2i32;
1438 assert_eq!(s.border.unwrap().width, 1.0);
1439 assert_eq!(s.line.unwrap().width, 2.0);
1440 assert_eq!(s.font.unwrap().size, 5.0);
1441 }
1442
1443 #[test]
1444 fn map_style_div_f32() {
1445 let s = full_style() / 0.5f32;
1446 assert_eq!(s.border.unwrap().width, 4.0);
1447 assert_eq!(s.line.unwrap().width, 8.0);
1448 assert_eq!(s.font.unwrap().size, 20.0);
1449 }
1450
1451 #[test]
1452 fn map_style_div_f64() {
1453 let s = full_style() / 0.5f64;
1454 assert_eq!(s.border.unwrap().width, 4.0);
1455 assert_eq!(s.line.unwrap().width, 8.0);
1456 assert_eq!(s.font.unwrap().size, 20.0);
1457 }
1458
1459 #[test]
1462 fn map_label_new() {
1463 let l = MapLabel::new();
1464 assert_eq!(l.text, String::new());
1465 assert_eq!(l.center, Pos2::new(0.0, 0.0));
1466 }
1467
1468 #[test]
1469 fn map_label_default_equals_new() {
1470 let l = MapLabel::default();
1471 assert_eq!(l.text, String::new());
1472 assert_eq!(l.center, Pos2::new(0.0, 0.0));
1473 }
1474
1475 #[test]
1478 fn map_point_new() {
1479 let p = MapPoint::new(42, [1.0, 2.0]);
1480 assert_eq!(p.get_id(), 42);
1481 assert_eq!(p.coords, [1.0, 2.0]);
1482 assert!(p.connections.is_empty());
1483 assert_eq!(p.name, None);
1484 assert_eq!(p.get_name(), String::new());
1485 }
1486
1487 #[test]
1488 fn map_point_set_and_get_name() {
1489 let mut p = MapPoint::new(1, [0.0, 0.0]);
1490 p.set_name("Jita".to_string());
1491 assert_eq!(p.name, Some("Jita".to_string()));
1492 assert_eq!(p.get_name(), "Jita");
1493 }
1494
1495 #[test]
1496 fn map_point_from_occupied_entry() {
1497 let mut map: HashMap<usize, MapPoint> = HashMap::new();
1498 let mut original = MapPoint::new(7, [5.0, 6.0]);
1499 original.set_name("Amarr".to_string());
1500 map.insert(7, original);
1501
1502 use std::collections::hash_map::Entry;
1503 if let Entry::Occupied(entry) = map.entry(7) {
1504 let cloned = MapPoint::from(entry);
1505 assert_eq!(cloned.get_id(), 7);
1506 assert_eq!(cloned.get_name(), "Amarr");
1507 assert_eq!(cloned.coords, [5.0, 6.0]);
1508 } else {
1509 panic!("se esperaba una entrada ocupada");
1510 }
1511 }
1512
1513 #[test]
1516 fn map_bounds_new() {
1517 let b = MapBounds::new();
1518 assert_eq!(b.min.components, [0.0, 0.0]);
1519 assert_eq!(b.max.components, [0.0, 0.0]);
1520 assert_eq!(b.pos.components, [0.0, 0.0]);
1521 assert_eq!(b.dist, 0.0);
1522 }
1523
1524 #[test]
1525 fn map_bounds_default_equals_new() {
1526 let b = MapBounds::default();
1527 assert_eq!(b.dist, 0.0);
1528 assert_eq!(b.pos.components, [0.0, 0.0]);
1529 }
1530
1531 #[test]
1534 fn map_settings_new() {
1535 let s = MapSettings::new();
1536 assert_eq!(s.max_zoom, 0.0);
1537 assert_eq!(s.min_zoom, 0.0);
1538 assert_eq!(s.line_visible_zoom, 0.0);
1539 assert_eq!(s.label_visible_zoom, 0.0);
1540 assert_eq!(s.node_text_visibility, VisibilitySetting::Always);
1541 assert_eq!(s.styles.len(), 1);
1542 }
1543
1544 #[test]
1545 fn map_settings_default() {
1546 let s = MapSettings::default();
1547 assert_eq!(s.max_zoom, 2.0);
1548 assert_eq!(s.min_zoom, 0.1);
1549 assert_eq!(s.line_visible_zoom, 0.2);
1550 assert_eq!(s.label_visible_zoom, 0.58);
1551 assert_eq!(s.node_text_visibility, VisibilitySetting::Always);
1552 assert_eq!(s.styles.len(), 2);
1554 assert_eq!(s.styles[0].background_color, Color32::WHITE);
1556 assert!(s.styles[0].border.is_some());
1557 assert!(s.styles[0].line.is_some());
1558 assert!(s.styles[0].font.is_some());
1559 assert_eq!(s.styles[1].background_color, Color32::DARK_GRAY);
1561 assert!(s.styles[1].border.is_some());
1562 assert!(s.styles[1].line.is_some());
1563 assert!(s.styles[1].font.is_some());
1564 }
1565
1566 #[test]
1569 fn visibility_setting_equality() {
1570 assert_eq!(VisibilitySetting::Hidden, VisibilitySetting::Hidden);
1571 assert_eq!(VisibilitySetting::Hover, VisibilitySetting::Hover);
1572 assert_eq!(VisibilitySetting::Always, VisibilitySetting::Always);
1573 assert_ne!(VisibilitySetting::Hidden, VisibilitySetting::Hover);
1574 assert_ne!(VisibilitySetting::Hover, VisibilitySetting::Always);
1575 assert_ne!(VisibilitySetting::Hidden, VisibilitySetting::Always);
1576 }
1577}