rstar/primitives/
geom_with_data.rs1use crate::envelope::Envelope;
2use crate::object::PointDistance;
3use crate::{object::RTreeObject, point::Point};
4
5#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
33#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
34pub struct GeomWithData<R: RTreeObject, T> {
35 geom: R,
36 pub data: T,
38}
39
40impl<R: RTreeObject, T> RTreeObject for GeomWithData<R, T> {
41 type Envelope = R::Envelope;
42
43 fn envelope(&self) -> Self::Envelope {
44 self.geom.envelope()
45 }
46}
47
48impl<R: PointDistance, T> PointDistance for GeomWithData<R, T> {
49 fn distance_2(
50 &self,
51 point: &<Self::Envelope as Envelope>::Point,
52 ) -> <<Self::Envelope as Envelope>::Point as Point>::Scalar {
53 self.geom.distance_2(point)
54 }
55
56 fn contains_point(&self, p: &<Self::Envelope as Envelope>::Point) -> bool {
57 self.geom.contains_point(p)
58 }
59
60 fn distance_2_if_less_or_equal(
61 &self,
62 point: &<Self::Envelope as Envelope>::Point,
63 max_distance_2: <<Self::Envelope as Envelope>::Point as Point>::Scalar,
64 ) -> Option<<<Self::Envelope as Envelope>::Point as Point>::Scalar> {
65 self.geom.distance_2_if_less_or_equal(point, max_distance_2)
66 }
67}
68
69impl<R: RTreeObject, T> GeomWithData<R, T> {
70 pub fn new(geom: R, data: T) -> Self {
72 Self { geom, data }
73 }
74
75 pub fn geom(&self) -> &R {
77 &self.geom
78 }
79}
80
81#[cfg(test)]
82mod test {
83 use super::GeomWithData;
84 use crate::object::PointDistance;
85
86 use approx::*;
87
88 use crate::{primitives::Line, RTree};
89
90 #[test]
91 fn container_in_rtree() {
92 let line_1 = GeomWithData::new(Line::new([0.0, 0.0], [1.0, 1.0]), ());
93 let line_2 = GeomWithData::new(Line::new([0.0, 0.0], [-1.0, 1.0]), ());
94 let tree = RTree::bulk_load(vec![line_1, line_2]);
95
96 assert!(tree.contains(&line_1));
97 }
98
99 #[test]
100 fn container_edge_distance() {
101 let edge = GeomWithData::new(Line::new([0.5, 0.5], [0.5, 2.0]), 1usize);
102
103 assert_abs_diff_eq!(edge.distance_2(&[0.5, 0.5]), 0.0);
104 assert_abs_diff_eq!(edge.distance_2(&[0.0, 0.5]), 0.5 * 0.5);
105 assert_abs_diff_eq!(edge.distance_2(&[0.5, 1.0]), 0.0);
106 assert_abs_diff_eq!(edge.distance_2(&[0.0, 0.0]), 0.5);
107 assert_abs_diff_eq!(edge.distance_2(&[0.0, 1.0]), 0.5 * 0.5);
108 assert_abs_diff_eq!(edge.distance_2(&[1.0, 1.0]), 0.5 * 0.5);
109 assert_abs_diff_eq!(edge.distance_2(&[1.0, 3.0]), 0.5 * 0.5 + 1.0);
110 }
111
112 #[test]
113 fn container_length_2() {
114 let line = GeomWithData::new(Line::new([1, -1], [5, 5]), 1usize);
115
116 assert_eq!(line.geom().length_2(), 16 + 36);
117 }
118
119 #[test]
120 fn container_nearest_neighbour() {
121 let mut lines = RTree::new();
122 lines.insert(GeomWithData::new(
123 Line::new([0.0, 0.0], [1.0, 1.0]),
124 "Line A",
125 ));
126 lines.insert(GeomWithData::new(
127 Line::new([0.0, 0.0], [-1.0, 1.0]),
128 "Line B",
129 ));
130 let my_location = [0.0, 0.0];
131 let place = lines.nearest_neighbor(&my_location).unwrap();
133
134 assert_eq!(place.data, "Line A");
135 }
136}