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