leptos_leaflet/components/
bounds.rs1use leaflet::LatLng;
2use leaflet::LatLngBounds;
3
4use super::Position;
5
6#[derive(Debug, Default, Clone, Copy, PartialEq)]
16pub struct Bounds {
17 pub ne_corner: Position,
18 pub sw_corner: Position,
19}
20
21impl Bounds {
22 pub fn new(ne_corner: Position, sw_corner: Position) -> Self {
29 Self {
30 ne_corner,
31 sw_corner,
32 }
33 }
34
35 pub fn get_center(&self) -> Position {
37 Position {
38 lat: (self.ne_corner.lat + self.sw_corner.lat) / 2.0,
39 lng: (self.ne_corner.lng + self.sw_corner.lng) / 2.0,
40 }
41 }
42
43 pub fn get_bottom_left(&self) -> Position {
45 Position::new(self.sw_corner.lat, self.sw_corner.lng)
46 }
47
48 pub fn get_top_right(&self) -> Position {
50 Position::new(self.ne_corner.lat, self.ne_corner.lng)
51 }
52
53 pub fn get_top_left(&self) -> Position {
55 Position::new(self.ne_corner.lat, self.sw_corner.lng)
56 }
57
58 pub fn get_bottom_right(&self) -> Position {
60 Position::new(self.sw_corner.lat, self.ne_corner.lng)
61 }
62
63 pub fn get_size(&self) -> Position {
65 Position {
66 lat: (self.ne_corner.lat - self.sw_corner.lat).abs(),
67 lng: (self.ne_corner.lng - self.sw_corner.lng).abs(),
68 }
69 }
70
71 pub fn contains(&self, position: Position) -> bool {
78 self.sw_corner.lat <= position.lat
79 && self.ne_corner.lat >= position.lat
80 && self.sw_corner.lng <= position.lng
81 && self.ne_corner.lng >= position.lng
82 }
83
84 pub fn intersects(&self, other: Bounds) -> bool {
91 let lat_overlap =
92 self.ne_corner.lat >= other.sw_corner.lat && self.sw_corner.lat <= other.ne_corner.lat;
93 let lng_overlap =
94 self.ne_corner.lng >= other.sw_corner.lng && self.sw_corner.lng <= other.ne_corner.lng;
95
96 lat_overlap && lng_overlap
97 }
98
99 pub fn overlaps(&self, other: Bounds) -> bool {
106 let lat_overlap =
107 self.ne_corner.lat > other.sw_corner.lat && self.sw_corner.lat < other.ne_corner.lat;
108 let lng_overlap =
109 self.ne_corner.lng > other.sw_corner.lng && self.sw_corner.lng < other.ne_corner.lng;
110
111 lat_overlap && lng_overlap
112 }
113
114 pub fn is_valid(&self) -> bool {
116 self.ne_corner.lat <= 90.0
117 && self.ne_corner.lat >= -90.0
118 && self.sw_corner.lat <= 90.0
119 && self.sw_corner.lat >= -90.0
120 && self.ne_corner.lng <= 180.0
121 && self.ne_corner.lng >= -180.0
122 && self.sw_corner.lng <= 180.0
123 && self.sw_corner.lng >= -180.0
124 && self.ne_corner.lat >= self.sw_corner.lat
125 && self.ne_corner.lng >= self.sw_corner.lng
126 }
127
128 pub fn pad(&self, buffer_ratio: f64) -> Bounds {
130 let lat_diff = self.ne_corner.lat - self.sw_corner.lat;
131 let lng_diff = self.ne_corner.lng - self.sw_corner.lng;
132 let lat_pad = lat_diff * buffer_ratio;
133 let lng_pad = lng_diff * buffer_ratio;
134 Bounds {
135 ne_corner: Position::new(self.ne_corner.lat + lat_pad, self.ne_corner.lng - lng_pad),
136 sw_corner: Position::new(self.sw_corner.lat - lat_pad, self.sw_corner.lng + lng_pad),
137 }
138 }
139
140 pub fn equals(&self, other: Bounds) -> bool {
142 self.ne_corner == other.ne_corner && self.sw_corner == other.sw_corner
143 }
144
145 pub fn as_lat_lng_bounds(&self) -> LatLngBounds {
146 LatLngBounds::new(
147 &LatLng::new(self.ne_corner.lat, self.ne_corner.lng),
148 &LatLng::new(self.sw_corner.lat, self.sw_corner.lng),
149 )
150 }
151}
152
153impl From<Bounds> for LatLngBounds {
154 fn from(value: Bounds) -> Self {
155 LatLngBounds::new(
156 &LatLng::new(value.ne_corner.lat, value.ne_corner.lng),
157 &LatLng::new(value.sw_corner.lat, value.sw_corner.lng),
158 )
159 }
160}
161
162impl From<&Bounds> for LatLngBounds {
163 fn from(value: &Bounds) -> Self {
164 LatLngBounds::new(
165 &LatLng::new(value.ne_corner.lat, value.ne_corner.lng),
166 &LatLng::new(value.sw_corner.lat, value.sw_corner.lng),
167 )
168 }
169}