coordinate_transformer/
structure.rs

1#[cfg(feature = "vec-x")]
2use vec_x::VecX;
3
4/// Defines a structure representing each coordinate value.
5/// This reduces the risk of passing wrong arguments to the coordinate conversion function.
6/// It also allows coordinate conversions that must go through latitude and longitude to be done at once.
7///
8/// 各座標値を表す構造体を定義しています。
9/// これを使用することで、座標変換関数に間違った引数を渡すリスクを減らせます。
10/// また、緯度経度を経由しなくてはいけない座標変換を一度にできます。
11
12use crate::{jpr2ll, JprOrigin, ll2jpr, ll2pixel, llz2xyz, pixel2ll, xyz2llz, ZoomLv};
13
14/// structure representing latitude and longitude
15///
16/// 緯度経度を表す構造体
17#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
18pub struct LL {
19    long: f64,
20    lat: f64,
21}
22
23impl LL {
24    ///create a new latitude and longitude
25    ///
26    /// 緯度経度を新しく作成する
27    pub fn new(long: f64, lat: f64) -> Self {
28        Self { long, lat }
29    }
30
31    /// Returns a tuple of (longitude,latitude)
32    ///
33    /// (経度,緯度)をタプルで返す
34    pub fn to_tuple(&self) -> (f64, f64) {
35        (self.long, self.lat)
36    }
37
38    /// Returns an array of [longitude, latitude]
39    ///
40    /// [経度, 緯度]の配列を返す
41    #[cfg(feature = "vec-x")]
42    pub fn to_vec2(&self) -> VecX<f64, 2> {
43        VecX::new([self.long, self.lat])
44    }
45
46    /// Convert to a structure representing JPR coordinates
47    ///
48    /// JPR座標を表す構造体に変換する
49    pub fn to_jpr(&self, origin: JprOrigin) -> JPR {
50        let (y, x) = ll2jpr(self.to_tuple(), origin);
51        JPR::new(y, x, origin)
52    }
53
54    /// Convert to a structure representing pixel coordinates
55    ///
56    /// Pixel座標を表す構造体に変換する
57    pub fn to_pixel(&self, zoom_lv: ZoomLv) -> Pixel {
58        let (x, y) = ll2pixel(self.to_tuple(), zoom_lv);
59        Pixel::new(x, y, zoom_lv)
60    }
61
62    /// Convert to a structure representing Cartesian (EPSG:4979) coordinates
63    ///
64    /// 直交座標系(EPSG:4979)座標を表す構造体に変換する
65    pub fn to_xyz(&self, altitude: f64) -> XYZ {
66        let (x, y, z) = llz2xyz(self.to_tuple(), altitude);
67        XYZ::new(x, y, z)
68    }
69}
70
71/// Convert to a structure representing plane rectangular coordinates
72///
73/// 平面直角座標を表す構造体に変換する
74#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
75pub struct JPR {
76    y: f64,
77    x: f64,
78    origin: JprOrigin,
79}
80
81impl JPR {
82    /// Create a new JPR coordinate
83    ///
84    /// JPR座標を新しく作成する
85    pub fn new(x: f64, y: f64, origin: JprOrigin) -> Self {
86        Self { y, x, origin }
87    }
88
89    /// Returns a tuple of (y, x)
90    ///
91    /// (y, x)をタプルで返す
92    pub fn to_tuple(&self) -> (f64, f64) {
93        (self.y, self.x)
94    }
95
96    /// Returns an array of [y, x]
97    ///
98    /// [y, x]の配列を返す
99    #[cfg(feature = "vec-x")]
100    pub fn to_vec2(&self) -> VecX<f64, 2> {
101        VecX::new([self.y, self.x])
102    }
103
104    /// Convert to a structure representing latitude and longitude
105    ///
106    /// 緯度経度を表す構造体に変換する
107    pub fn to_ll(&self) -> LL {
108        let (long, lat) = jpr2ll(self.to_tuple(), self.origin);
109        LL::new(long, lat)
110    }
111
112    /// Convert to a structure representing pixel coordinates
113    ///
114    /// Pixel座標を表す構造体に変換する
115    pub fn to_pixel(&self, zoom_lv: ZoomLv) -> Pixel {
116        let (x, y) = ll2pixel(self.to_ll().to_tuple(), zoom_lv);
117        Pixel::new(x, y, zoom_lv)
118    }
119
120    /// Convert to a structure representing Cartesian (EPSG:4979) coordinates
121    ///
122    /// 直交座標系(EPSG:4979)座標を表す構造体に変換する
123    pub fn to_xyz(&self, altitude: f64) -> XYZ {
124        let (x, y, z) = llz2xyz(self.to_ll().to_tuple(), altitude);
125        XYZ::new(x, y, z)
126    }
127}
128
129/// Structure representing pixel coordinates
130///
131/// ピクセル座標を表す構造体
132#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
133pub struct Pixel {
134    x: u32,
135    y: u32,
136    zoom: ZoomLv,
137}
138
139impl Pixel {
140    /// Create a new pixel coordinate
141    ///
142    /// ピクセル座標を新しく作成する
143    pub fn new(x: u32, y: u32, zoom: ZoomLv) -> Self {
144        Self { x, y, zoom }
145    }
146
147    /// Returns a tuple of (x, y)
148    ///
149    /// (x, y)をタプルで返す
150    pub fn to_tuple(&self) -> (u32, u32) {
151        (self.x, self.y)
152    }
153
154    /// Returns an array of [x, y]
155    ///
156    /// [x, y]の配列を返す
157    #[cfg(feature = "vec-x")]
158    pub fn to_array(&self) -> VecX<u32, 2> {
159        VecX::new([self.x, self.y])
160    }
161
162    /// Convert to a structure representing latitude and longitude
163    ///
164    /// 緯度経度を表す構造体に変換する
165    pub fn to_ll(&self) -> LL {
166        let (long, lat) = pixel2ll(self.to_tuple(), self.zoom);
167        LL::new(long, lat)
168    }
169
170    /// Convert to a structure representing JPR coordinates
171    ///
172    /// 平面直角座標を表す構造体に変換する
173    pub fn to_jpr(&self, origin: JprOrigin) -> JPR {
174        let (y, x) = ll2jpr(self.to_ll().to_tuple(), origin);
175        JPR::new(y, x, origin)
176    }
177
178    /// Convert to a structure representing Cartesian (EPSG:4979) coordinates
179    ///
180    /// 直交座標系(EPSG:4979)座標を表す構造体に変換する
181    pub fn to_xyz(&self, altitude: f64) -> XYZ {
182        let (x, y, z) = llz2xyz(self.to_ll().to_tuple(), altitude);
183        XYZ::new(x, y, z)
184    }
185}
186
187/// Structure with height information added to pixel coordinates
188/// Height is determined according to pixel resolution (m)
189///
190/// ピクセル座標に高さ情報を追加した構造体
191/// 高さはピクセルの分解能(m)に合わせて決定される
192#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
193pub struct Voxel {
194    x: u32,
195    y: u32,
196    z: u32,
197    resolution: f64,
198    zoom_lv: ZoomLv,
199}
200
201impl Voxel {
202    /// Create a new voxel coordinate
203    ///
204    /// Voxel座標を新しく作成する
205    pub fn new(x: u32, y: u32, z: u32, resolution: f64, zoom_lv: ZoomLv) -> Self {
206        Self { x, y, z, resolution, zoom_lv }
207    }
208
209    /// Returns a tuple of (x, y, z)
210    ///
211    /// (x, y, z)をタプルで返す
212    pub fn to_tuple(&self) -> (u32, u32, u32) {
213        (self.x, self.y, self.z)
214    }
215
216    /// Returns an array of [x, y, z]
217    ///
218    /// [x, y, z]の配列を返す
219    #[cfg(feature = "vec-x")]
220    pub fn to_vec3(&self) -> VecX<u32, 3> {
221        VecX::new([self.x, self.y, self.z])
222    }
223
224    /// Returns a tuple of (x, y)
225    ///
226    /// (x, y)をタプルで返す
227    pub fn to_2d_tuple(&self) -> (u32, u32) {
228        (self.x, self.y)
229    }
230
231    /// Returns an array of [x, y]
232    ///
233    /// [x, y]の配列を返す
234    #[cfg(feature = "vec-x")]
235    pub fn to_vec2(&self) -> VecX<u32, 2> {
236        VecX::new([self.x, self.y])
237    }
238
239    /// Convert to a structure representing latitude and longitude
240    ///
241    /// 緯度経度を表す構造体に変換する
242    pub fn to_ll(&self) -> LL {
243        let (long, lat) = pixel2ll(self.to_2d_tuple(), self.zoom_lv);
244        LL::new(long, lat)
245    }
246
247    /// Convert to a structure representing latitude and longitude with altitude (m)
248    ///
249    /// 緯度経度を表す構造体と標高(m)に変換する
250    pub fn to_ll_with_altitude(&self) -> (LL, f64) {
251        let ll = self.to_ll();
252        let altitude = self.z as f64 * self.resolution;
253        (ll, altitude)
254    }
255
256    /// Convert to a structure representing JPR coordinates
257    ///
258    /// 平面直角座標を表す構造体に変換する
259    pub fn to_jpr(&self, origin: JprOrigin) -> JPR {
260        let (y, x) = ll2jpr(self.to_ll().to_tuple(), origin);
261        JPR::new(y, x, origin)
262    }
263
264    /// Convert to a structure representing JPR coordinates with altitude (m)
265    ///
266    /// 平面直角座標を表す構造体と標高(m)に変換する
267    pub fn to_jpr_with_altitude(&self, origin: JprOrigin) -> (JPR, f64) {
268        let (ll, altitude) = self.to_ll_with_altitude();
269        let jpr = ll.to_jpr(origin);
270        (jpr, altitude)
271    }
272
273    /// Convert to a structure representing pixel coordinates
274    ///
275    /// ピクセル座標を表す構造体に変換する
276    pub fn to_pixel(&self) -> Pixel {
277        Pixel::new(self.x, self.y, self.zoom_lv)
278    }
279
280    /// Convert to a structure representing pixel coordinates with altitude (m)
281    ///
282    /// ピクセル座標を表す構造体と標高(m)に変換する
283    pub fn to_pixel_with_altitude(&self) -> (Pixel, f64) {
284        let (ll, altitude) = self.to_ll_with_altitude();
285        let pixel = ll.to_pixel(self.zoom_lv);
286        (pixel, altitude)
287    }
288
289    /// Convert to a structure representing Cartesian (EPSG:4979) coordinates
290    ///
291    /// 直交座標系(EPSG:4979)座標を表す構造体に変換する
292    pub fn to_xyz(&self) -> XYZ {
293        let (x, y, z) = llz2xyz(self.to_ll().to_tuple(), self.z as f64 * self.resolution);
294        XYZ::new(x, y, z)
295    }
296
297    /// Convert to a structure representing Cartesian (EPSG:4979) coordinates with altitude (m)
298    ///
299    /// 直交座標系(EPSG:4979)座標を表す構造体と標高(m)に変換する
300    pub fn to_xyz_with_altitude(&self) -> (XYZ, f64) {
301        let (ll, altitude) = self.to_ll_with_altitude();
302        let xyz = ll.to_xyz(altitude);
303        (xyz, altitude)
304    }
305}
306
307/// Structure representing Cartesian (EPSG:4979) coordinates
308///
309/// 直交座標系(EPSG:4979)座標を表す構造体
310#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
311pub struct XYZ {
312    x: f64,
313    y: f64,
314    z: f64,
315}
316
317impl XYZ {
318    /// Create a new Cartesian (EPSG:4979) coordinate
319    ///
320    /// 直交座標系(EPSG:4979)座標を新しく作成する
321    pub fn new(x: f64, y: f64, z: f64) -> Self {
322        Self { x, y, z }
323    }
324
325    /// Returns a tuple of (x, y, z)
326    ///
327    /// (x, y, z)をタプルで返す
328    pub fn to_tuple(&self) -> (f64, f64, f64) {
329        (self.x, self.y, self.z)
330    }
331
332    /// Returns an array of [x, y, z]
333    ///
334    /// [x, y, z]の配列を返す
335    #[cfg(feature = "vec-x")]
336    pub fn to_vec3(&self) -> VecX<f64, 3> {
337        VecX::new([self.x, self.y, self.z])
338    }
339
340    /// Convert to a structure representing latitude and longitude
341    ///
342    /// 緯度経度を表す構造体に変換する
343    pub fn to_ll(&self) -> LL {
344        let ((long, lat), ..) = xyz2llz(self.to_tuple());
345        LL::new(long, lat)
346    }
347
348    /// Convert to a structure representing latitude and longitude with altitude (m)
349    ///
350    /// 緯度経度を表す構造体と標高(m)に変換する
351    pub fn to_ll_with_altitude(&self) -> (LL, f64) {
352        let ((long, lat), altitude) = xyz2llz(self.to_tuple());
353        (LL::new(long, lat), altitude)
354    }
355
356    /// Convert to a structure representing JPR coordinates
357    ///
358    /// 平面直角座標を表す構造体に変換する
359    pub fn to_jpr(&self, origin: JprOrigin) -> JPR {
360        let (y, x) = ll2jpr(self.to_ll().to_tuple(), origin);
361        JPR::new(y, x, origin)
362    }
363
364    /// Convert to a structure representing JPR coordinates with altitude (m)
365    ///
366    /// 平面直角座標を表す構造体と標高(m)に変換する
367    pub fn to_jpr_with_altitude(&self, origin: JprOrigin) -> (JPR, f64) {
368        let (ll, altitude) = self.to_ll_with_altitude();
369        let jpr = ll.to_jpr(origin);
370        (jpr, altitude)
371    }
372
373    /// Convert to a structure representing pixel coordinates
374    /// ピクセル座標を表す構造体に変換する
375    pub fn to_pixel(&self, zoom_lv: ZoomLv) -> Pixel {
376        let (x, y) = ll2pixel(self.to_ll().to_tuple(), zoom_lv);
377        Pixel::new(x, y, zoom_lv)
378    }
379
380    /// Convert to a structure representing pixel coordinates with altitude (m)
381    ///
382    /// ピクセル座標を表す構造体と標高(m)に変換する
383    pub fn to_pixel_with_altitude(&self, zoom_lv: ZoomLv) -> (Pixel, f64) {
384        let (ll, altitude) = self.to_ll_with_altitude();
385        let pixel = ll.to_pixel(zoom_lv);
386        (pixel, altitude)
387    }
388}
389