• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

geo-engine / geoengine / 12864373935

20 Jan 2025 08:57AM UTC coverage: 90.007% (-0.6%) from 90.64%
12864373935

Pull #1008

github

web-flow
Merge 7d012d0a9 into de81b44f7
Pull Request #1008: user ctx in ge_test

3691 of 3793 new or added lines in 64 files covered. (97.31%)

786 existing lines in 19 files now uncovered.

127380 of 141522 relevant lines covered (90.01%)

56878.96 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.51
/datatypes/src/spatial_reference.rs
1
use crate::{
2
    error,
3
    operations::reproject::{CoordinateProjection, CoordinateProjector, Reproject},
4
    primitives::AxisAlignedRectangle,
5
    util::Result,
6
};
7
use gdal::spatial_ref::SpatialRef;
8

9
use postgres_types::private::BytesMut;
10

11
use postgres_types::{FromSql, IsNull, ToSql, Type};
12
use proj::Proj;
13
use serde::de::Visitor;
14
use serde::{Deserialize, Deserializer, Serialize, Serializer};
15

16
use snafu::Error;
17
use snafu::ResultExt;
18
use std::str::FromStr;
19
use std::{convert::TryFrom, fmt::Formatter};
20

21
/// A spatial reference authority that is part of a spatial reference definition
22
#[derive(
23
    Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, ToSql, FromSql,
7,432✔
24
)]
25
#[serde(rename_all = "SCREAMING-KEBAB-CASE")]
26
pub enum SpatialReferenceAuthority {
27
    Epsg,
28
    SrOrg,
29
    Iau2000,
30
    Esri,
31
}
32

33
impl std::fmt::Display for SpatialReferenceAuthority {
34
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1,226✔
35
        write!(
1,226✔
36
            f,
1,226✔
37
            "{}",
1,226✔
38
            match self {
1,226✔
39
                SpatialReferenceAuthority::Epsg => "EPSG",
1,215✔
40
                SpatialReferenceAuthority::SrOrg => "SR-ORG",
3✔
41
                SpatialReferenceAuthority::Iau2000 => "IAU2000",
4✔
42
                SpatialReferenceAuthority::Esri => "ESRI",
4✔
43
            }
44
        )
45
    }
1,226✔
46
}
47

48
/// A spatial reference consists of an authority and a code
49
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, ToSql, FromSql)]
4,498✔
50
pub struct SpatialReference {
51
    authority: SpatialReferenceAuthority,
52
    code: u32,
53
}
54

55
impl SpatialReference {
56
    pub fn new(authority: SpatialReferenceAuthority, code: u32) -> Self {
1,698✔
57
        Self { authority, code }
1,698✔
58
    }
1,698✔
59

60
    pub fn authority(&self) -> &SpatialReferenceAuthority {
52✔
61
        &self.authority
52✔
62
    }
52✔
63

64
    pub fn code(self) -> u32 {
52✔
65
        self.code
52✔
66
    }
52✔
67

68
    /// the WGS 84 spatial reference system
69
    pub fn epsg_4326() -> Self {
661✔
70
        Self::new(SpatialReferenceAuthority::Epsg, 4326)
661✔
71
    }
661✔
72

73
    pub fn proj_string(self) -> Result<String> {
546✔
74
        match self.authority {
2✔
75
            SpatialReferenceAuthority::Epsg | SpatialReferenceAuthority::Iau2000 | SpatialReferenceAuthority::Esri => {
76
                Ok(format!("{}:{}", self.authority, self.code))
544✔
77
            }
78
            // poor-mans integration of Meteosat Second Generation 
79
            SpatialReferenceAuthority::SrOrg if self.code == 81 => Ok("+proj=geos +lon_0=0 +h=35785831 +x_0=0 +y_0=0 +ellps=WGS84 +units=m +no_defs +type=crs".to_owned()),
2✔
80
            SpatialReferenceAuthority::SrOrg => {
81
                Err(error::Error::ProjStringUnresolvable { spatial_ref: self })
1✔
82
                //TODO: we might need to look them up somehow! Best solution would be a registry where we can store user definexd srs strings.
83
            }
84
        }
85
    }
546✔
86

87
    /// Return the area of use in EPSG:4326 projection
88
    pub fn area_of_use<A: AxisAlignedRectangle>(self) -> Result<A> {
72✔
89
        let proj_string = match self.proj_string() {
72✔
90
            Ok(s) => s,
72✔
91
            Err(e) => return Err(e),
×
92
        };
93

94
        let proj = Proj::new(&proj_string).ok_or(error::Error::InvalidProjDefinition {
72✔
95
            proj_definition: proj_string.clone(),
72✔
96
        })?;
72✔
97
        let area = proj
72✔
98
            .area_of_use()
72✔
99
            .context(error::ProjInternal)?
72✔
100
            .0
101
            .ok_or(error::Error::NoAreaOfUseDefined { proj_string })?;
72✔
102
        A::from_min_max(
72✔
103
            (area.west, area.south).into(),
72✔
104
            (area.east, area.north).into(),
72✔
105
        )
72✔
106
    }
72✔
107

108
    /// Return the area of use in current projection
109
    pub fn area_of_use_projected<A: AxisAlignedRectangle>(self) -> Result<A> {
28✔
110
        if self == Self::epsg_4326() {
28✔
111
            return self.area_of_use();
24✔
112
        }
4✔
113
        let p = CoordinateProjector::from_known_srs(Self::epsg_4326(), self)?;
4✔
114
        self.area_of_use::<A>()?.reproject(&p)
4✔
115
    }
28✔
116

117
    /// Return the srs-string "authority:code"
118
    #[allow(clippy::trivially_copy_pass_by_ref)]
119
    pub fn srs_string(&self) -> String {
1✔
120
        format!("{}:{}", self.authority, self.code)
1✔
121
    }
1✔
122

123
    /// Compute the bounding box of this spatial reference that is also valid in the `other` spatial reference. Might be None.
124
    #[allow(clippy::trivially_copy_pass_by_ref)]
125
    pub fn area_of_use_intersection<T>(&self, other: &SpatialReference) -> Result<Option<T>>
6✔
126
    where
6✔
127
        T: AxisAlignedRectangle,
6✔
128
    {
6✔
129
        // generate a projector which transforms wgs84 into the projection we want to produce.
130
        let valid_bounds_proj =
6✔
131
            CoordinateProjector::from_known_srs(SpatialReference::epsg_4326(), *self)?;
6✔
132

133
        // transform the bounds of the input srs (coordinates are in wgs84) into the output projection.
134
        // TODO check if  there is a better / smarter way to check if the coordinates are valid.
135
        let area_out = self.area_of_use::<T>()?;
6✔
136
        let area_other = other.area_of_use::<T>()?;
6✔
137

138
        area_out
6✔
139
            .intersection(&area_other)
6✔
140
            .map(|x| x.reproject(&valid_bounds_proj))
6✔
141
            .transpose()
6✔
142
    }
6✔
143
}
144

145
impl std::fmt::Display for SpatialReference {
146
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
673✔
147
        write!(f, "{}:{}", self.authority, self.code)
673✔
148
    }
673✔
149
}
150

151
impl Serialize for SpatialReference {
152
    fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
20✔
153
    where
20✔
154
        S: Serializer,
20✔
155
    {
20✔
156
        serializer.serialize_str(&self.to_string())
20✔
157
    }
20✔
158
}
159

160
/// Helper struct for deserializing a `SpatialReferencce`
161
struct SpatialReferenceDeserializeVisitor;
162

163
impl Visitor<'_> for SpatialReferenceDeserializeVisitor {
164
    type Value = SpatialReference;
165

166
    fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
×
167
        formatter.write_str("a spatial reference in the form authority:code")
×
168
    }
×
169

170
    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
26✔
171
    where
26✔
172
        E: serde::de::Error,
26✔
173
    {
26✔
174
        v.parse().map_err(serde::de::Error::custom)
26✔
175
    }
26✔
176
}
177

178
impl<'de> Deserialize<'de> for SpatialReference {
179
    fn deserialize<D>(deserializer: D) -> Result<Self, <D as Deserializer<'de>>::Error>
26✔
180
    where
26✔
181
        D: Deserializer<'de>,
26✔
182
    {
26✔
183
        deserializer.deserialize_str(SpatialReferenceDeserializeVisitor)
26✔
184
    }
26✔
185
}
186

187
impl FromStr for SpatialReferenceAuthority {
188
    type Err = error::Error;
189

190
    fn from_str(s: &str) -> Result<Self, Self::Err> {
965✔
191
        Ok(match s {
965✔
192
            "EPSG" => SpatialReferenceAuthority::Epsg,
965✔
193
            "SR-ORG" => SpatialReferenceAuthority::SrOrg,
201✔
194
            "IAU2000" => SpatialReferenceAuthority::Iau2000,
200✔
195
            "ESRI" => SpatialReferenceAuthority::Esri,
199✔
196
            _ => {
197
                return Err(error::Error::InvalidSpatialReferenceString {
2✔
198
                    spatial_reference_string: s.into(),
2✔
199
                })
2✔
200
            }
201
        })
202
    }
965✔
203
}
204

205
impl FromStr for SpatialReference {
206
    type Err = error::Error;
207

208
    fn from_str(s: &str) -> Result<Self, Self::Err> {
154✔
209
        let mut split = s.split(':');
154✔
210

154✔
211
        match (split.next(), split.next(), split.next()) {
154✔
212
            (Some(authority), Some(code), None) => Ok(Self::new(
154✔
213
                authority.parse()?,
154✔
214
                code.parse::<u32>().context(error::ParseU32)?,
152✔
215
            )),
216
            _ => Err(error::Error::InvalidSpatialReferenceString {
×
217
                spatial_reference_string: s.into(),
×
218
            }),
×
219
        }
220
    }
154✔
221
}
222

223
impl TryFrom<SpatialRef> for SpatialReference {
224
    type Error = error::Error;
225

226
    fn try_from(value: SpatialRef) -> Result<Self, Self::Error> {
931✔
227
        Ok(SpatialReference::new(
931✔
228
            SpatialReferenceAuthority::from_str(&value.auth_name()?)?,
931✔
229
            value.auth_code()? as u32,
811✔
230
        ))
231
    }
931✔
232
}
233

234
impl TryFrom<SpatialReference> for SpatialRef {
235
    type Error = error::Error;
236

237
    fn try_from(value: SpatialReference) -> Result<Self, Self::Error> {
48✔
238
        if value.authority == SpatialReferenceAuthority::Epsg {
48✔
239
            return SpatialRef::from_epsg(value.code).context(error::Gdal);
48✔
240
        }
×
241

×
242
        // TODO: support other projections reliably
×
243

×
244
        SpatialRef::from_proj4(&value.proj_string()?).context(error::Gdal)
×
245
    }
48✔
246
}
247

248
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
249
pub enum SpatialReferenceOption {
250
    SpatialReference(SpatialReference),
251
    Unreferenced,
252
}
253

254
impl SpatialReferenceOption {
255
    pub fn is_spatial_ref(self) -> bool {
4✔
256
        match self {
4✔
257
            SpatialReferenceOption::SpatialReference(_) => true,
2✔
258
            SpatialReferenceOption::Unreferenced => false,
2✔
259
        }
260
    }
4✔
261

262
    pub fn is_unreferenced(self) -> bool {
2✔
263
        !self.is_spatial_ref()
2✔
264
    }
2✔
265
}
266

267
impl ToSql for SpatialReferenceOption {
268
    fn to_sql(&self, ty: &Type, out: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>>
442✔
269
    where
442✔
270
        Self: Sized,
442✔
271
    {
442✔
272
        match self {
442✔
273
            SpatialReferenceOption::SpatialReference(sref) => sref.to_sql(ty, out),
337✔
274
            SpatialReferenceOption::Unreferenced => Ok(IsNull::Yes),
105✔
275
        }
276
    }
442✔
277

278
    fn accepts(ty: &Type) -> bool
247✔
279
    where
247✔
280
        Self: Sized,
247✔
281
    {
247✔
282
        <SpatialReference as ToSql>::accepts(ty)
247✔
283
    }
247✔
284

UNCOV
285
    fn to_sql_checked(
×
UNCOV
286
        &self,
×
UNCOV
287
        ty: &Type,
×
UNCOV
288
        out: &mut BytesMut,
×
UNCOV
289
    ) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
×
UNCOV
290
        match self {
×
UNCOV
291
            SpatialReferenceOption::SpatialReference(sref) => sref.to_sql_checked(ty, out),
×
UNCOV
292
            SpatialReferenceOption::Unreferenced => Ok(IsNull::Yes),
×
293
        }
UNCOV
294
    }
×
295
}
296

297
impl<'a> FromSql<'a> for SpatialReferenceOption {
298
    fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
58✔
299
        Ok(SpatialReferenceOption::SpatialReference(
58✔
300
            SpatialReference::from_sql(ty, raw)?,
58✔
301
        ))
302
    }
58✔
303

304
    fn from_sql_null(_: &Type) -> Result<Self, Box<dyn Error + Sync + Send>> {
53✔
305
        Ok(SpatialReferenceOption::Unreferenced)
53✔
306
    }
53✔
307

308
    fn accepts(ty: &Type) -> bool {
1,428✔
309
        <SpatialReference as FromSql>::accepts(ty)
1,428✔
310
    }
1,428✔
311
}
312

313
impl std::fmt::Display for SpatialReferenceOption {
314
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
661✔
315
        match self {
661✔
316
            SpatialReferenceOption::SpatialReference(p) => write!(f, "{p}"),
649✔
317
            SpatialReferenceOption::Unreferenced => Ok(()),
12✔
318
        }
319
    }
661✔
320
}
321

322
impl From<SpatialReference> for SpatialReferenceOption {
323
    fn from(spatial_reference: SpatialReference) -> Self {
802✔
324
        Self::SpatialReference(spatial_reference)
802✔
325
    }
802✔
326
}
327

328
impl From<Option<SpatialReference>> for SpatialReferenceOption {
329
    fn from(option: Option<SpatialReference>) -> Self {
5✔
330
        match option {
5✔
331
            Some(p) => SpatialReferenceOption::SpatialReference(p),
4✔
332
            None => SpatialReferenceOption::Unreferenced,
1✔
333
        }
334
    }
5✔
335
}
336

337
impl Serialize for SpatialReferenceOption {
338
    fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
651✔
339
    where
651✔
340
        S: Serializer,
651✔
341
    {
651✔
342
        serializer.serialize_str(&self.to_string())
651✔
343
    }
651✔
344
}
345

346
impl From<SpatialReferenceOption> for Option<SpatialReference> {
347
    fn from(s_ref: SpatialReferenceOption) -> Self {
27✔
348
        match s_ref {
27✔
349
            SpatialReferenceOption::SpatialReference(s) => Some(s),
26✔
350
            SpatialReferenceOption::Unreferenced => None,
1✔
351
        }
352
    }
27✔
353
}
354

355
/// Helper struct for deserializing a `SpatialReferenceOption`
356
struct SpatialReferenceOptionDeserializeVisitor;
357

358
impl Visitor<'_> for SpatialReferenceOptionDeserializeVisitor {
359
    type Value = SpatialReferenceOption;
360

361
    fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
×
362
        formatter.write_str("a spatial reference in the form authority:code")
×
363
    }
×
364

365
    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
51✔
366
    where
51✔
367
        E: serde::de::Error,
51✔
368
    {
51✔
369
        if v.is_empty() {
51✔
370
            return Ok(SpatialReferenceOption::Unreferenced);
7✔
371
        }
44✔
372

373
        let spatial_reference: SpatialReference = v.parse().map_err(serde::de::Error::custom)?;
44✔
374

375
        Ok(spatial_reference.into())
43✔
376
    }
51✔
377
}
378

379
impl<'de> Deserialize<'de> for SpatialReferenceOption {
380
    fn deserialize<D>(deserializer: D) -> Result<Self, <D as Deserializer<'de>>::Error>
51✔
381
    where
51✔
382
        D: Deserializer<'de>,
51✔
383
    {
51✔
384
        deserializer.deserialize_str(SpatialReferenceOptionDeserializeVisitor)
51✔
385
    }
51✔
386
}
387

388
#[cfg(test)]
389
mod tests {
390
    use super::*;
391
    use std::convert::TryInto;
392

393
    #[test]
394
    fn display() {
1✔
395
        assert_eq!(SpatialReferenceAuthority::Epsg.to_string(), "EPSG");
1✔
396
        assert_eq!(SpatialReferenceAuthority::SrOrg.to_string(), "SR-ORG");
1✔
397
        assert_eq!(SpatialReferenceAuthority::Iau2000.to_string(), "IAU2000");
1✔
398
        assert_eq!(SpatialReferenceAuthority::Esri.to_string(), "ESRI");
1✔
399

400
        assert_eq!(
1✔
401
            SpatialReference::new(SpatialReferenceAuthority::Epsg, 4326).to_string(),
1✔
402
            "EPSG:4326"
1✔
403
        );
1✔
404
        assert_eq!(
1✔
405
            SpatialReference::new(SpatialReferenceAuthority::SrOrg, 1).to_string(),
1✔
406
            "SR-ORG:1"
1✔
407
        );
1✔
408
        assert_eq!(
1✔
409
            SpatialReference::new(SpatialReferenceAuthority::Iau2000, 4711).to_string(),
1✔
410
            "IAU2000:4711"
1✔
411
        );
1✔
412
        assert_eq!(
1✔
413
            SpatialReference::new(SpatialReferenceAuthority::Esri, 42).to_string(),
1✔
414
            "ESRI:42"
1✔
415
        );
1✔
416
    }
1✔
417

418
    #[test]
419
    fn serialize_json() {
1✔
420
        assert_eq!(
1✔
421
            serde_json::to_string(&SpatialReference::new(
1✔
422
                SpatialReferenceAuthority::Epsg,
1✔
423
                4326
1✔
424
            ))
1✔
425
            .unwrap(),
1✔
426
            "\"EPSG:4326\""
1✔
427
        );
1✔
428
        assert_eq!(
1✔
429
            serde_json::to_string(&SpatialReference::new(SpatialReferenceAuthority::SrOrg, 1))
1✔
430
                .unwrap(),
1✔
431
            "\"SR-ORG:1\""
1✔
432
        );
1✔
433
        assert_eq!(
1✔
434
            serde_json::to_string(&SpatialReference::new(
1✔
435
                SpatialReferenceAuthority::Iau2000,
1✔
436
                4711
1✔
437
            ))
1✔
438
            .unwrap(),
1✔
439
            "\"IAU2000:4711\""
1✔
440
        );
1✔
441
        assert_eq!(
1✔
442
            serde_json::to_string(&SpatialReference::new(SpatialReferenceAuthority::Esri, 42))
1✔
443
                .unwrap(),
1✔
444
            "\"ESRI:42\""
1✔
445
        );
1✔
446
    }
1✔
447

448
    #[test]
449
    fn deserialize_json() {
1✔
450
        assert_eq!(
1✔
451
            SpatialReference::new(SpatialReferenceAuthority::Epsg, 4326),
1✔
452
            serde_json::from_str("\"EPSG:4326\"").unwrap()
1✔
453
        );
1✔
454
        assert_eq!(
1✔
455
            SpatialReference::new(SpatialReferenceAuthority::SrOrg, 1),
1✔
456
            serde_json::from_str("\"SR-ORG:1\"").unwrap()
1✔
457
        );
1✔
458
        assert_eq!(
1✔
459
            SpatialReference::new(SpatialReferenceAuthority::Iau2000, 4711),
1✔
460
            serde_json::from_str("\"IAU2000:4711\"").unwrap()
1✔
461
        );
1✔
462
        assert_eq!(
1✔
463
            SpatialReference::new(SpatialReferenceAuthority::Esri, 42),
1✔
464
            serde_json::from_str("\"ESRI:42\"").unwrap()
1✔
465
        );
1✔
466

467
        assert!(serde_json::from_str::<SpatialReference>("\"foo:bar\"").is_err());
1✔
468
    }
1✔
469

470
    #[test]
471
    fn spatial_reference_option_serde() {
1✔
472
        assert_eq!(
1✔
473
            serde_json::to_string(&SpatialReferenceOption::SpatialReference(
1✔
474
                SpatialReference::new(SpatialReferenceAuthority::Epsg, 4326)
1✔
475
            ))
1✔
476
            .unwrap(),
1✔
477
            "\"EPSG:4326\""
1✔
478
        );
1✔
479

480
        assert_eq!(
1✔
481
            serde_json::to_string(&SpatialReferenceOption::Unreferenced).unwrap(),
1✔
482
            "\"\""
1✔
483
        );
1✔
484

485
        assert_eq!(
1✔
486
            SpatialReferenceOption::SpatialReference(SpatialReference::new(
1✔
487
                SpatialReferenceAuthority::Epsg,
1✔
488
                4326
1✔
489
            )),
1✔
490
            serde_json::from_str("\"EPSG:4326\"").unwrap()
1✔
491
        );
1✔
492

493
        assert_eq!(
1✔
494
            SpatialReferenceOption::Unreferenced,
1✔
495
            serde_json::from_str("\"\"").unwrap()
1✔
496
        );
1✔
497

498
        assert!(serde_json::from_str::<SpatialReferenceOption>("\"foo:bar\"").is_err());
1✔
499
    }
1✔
500

501
    #[test]
502
    fn is_spatial_ref() {
1✔
503
        let s_ref = SpatialReferenceOption::from(SpatialReference::epsg_4326());
1✔
504
        assert!(s_ref.is_spatial_ref());
1✔
505
        assert!(!s_ref.is_unreferenced());
1✔
506
    }
1✔
507

508
    #[test]
509
    fn is_unreferenced() {
1✔
510
        let s_ref = SpatialReferenceOption::Unreferenced;
1✔
511
        assert!(s_ref.is_unreferenced());
1✔
512
        assert!(!s_ref.is_spatial_ref());
1✔
513
    }
1✔
514

515
    #[test]
516
    fn from_option_some() {
1✔
517
        let s_ref: SpatialReferenceOption = Some(SpatialReference::epsg_4326()).into();
1✔
518
        assert_eq!(
1✔
519
            s_ref,
1✔
520
            SpatialReferenceOption::SpatialReference(SpatialReference::epsg_4326())
1✔
521
        );
1✔
522
    }
1✔
523

524
    #[test]
525
    fn from_option_none() {
1✔
526
        let s_ref: SpatialReferenceOption = None.into();
1✔
527
        assert_eq!(s_ref, SpatialReferenceOption::Unreferenced);
1✔
528
    }
1✔
529

530
    #[test]
531
    fn into_option_some() {
1✔
532
        let s_ref: Option<SpatialReference> =
1✔
533
            SpatialReferenceOption::SpatialReference(SpatialReference::epsg_4326()).into();
1✔
534
        assert_eq!(s_ref, Some(SpatialReference::epsg_4326()));
1✔
535
    }
1✔
536

537
    #[test]
538
    fn into_option_none() {
1✔
539
        let s_ref: Option<SpatialReference> = SpatialReferenceOption::Unreferenced.into();
1✔
540
        assert_eq!(s_ref, None);
1✔
541
    }
1✔
542

543
    #[test]
544
    fn proj_string() {
1✔
545
        assert_eq!(
1✔
546
            SpatialReference::new(SpatialReferenceAuthority::Epsg, 4326)
1✔
547
                .proj_string()
1✔
548
                .unwrap(),
1✔
549
            "EPSG:4326"
1✔
550
        );
1✔
551
        assert_eq!(
1✔
552
            SpatialReference::new(SpatialReferenceAuthority::SrOrg, 81).proj_string().unwrap(),
1✔
553
            "+proj=geos +lon_0=0 +h=35785831 +x_0=0 +y_0=0 +ellps=WGS84 +units=m +no_defs +type=crs"
1✔
554
        );
1✔
555
        assert_eq!(
1✔
556
            SpatialReference::new(SpatialReferenceAuthority::Iau2000, 4711)
1✔
557
                .proj_string()
1✔
558
                .unwrap(),
1✔
559
            "IAU2000:4711"
1✔
560
        );
1✔
561
        assert_eq!(
1✔
562
            SpatialReference::new(SpatialReferenceAuthority::Esri, 42)
1✔
563
                .proj_string()
1✔
564
                .unwrap(),
1✔
565
            "ESRI:42"
1✔
566
        );
1✔
567
        assert!(SpatialReference::new(SpatialReferenceAuthority::SrOrg, 1)
1✔
568
            .proj_string()
1✔
569
            .is_err());
1✔
570
    }
1✔
571

572
    #[test]
573
    fn spatial_reference_to_gdal_spatial_ref_epsg() {
1✔
574
        let spatial_reference = SpatialReference::epsg_4326();
1✔
575
        let gdal_sref: SpatialRef = spatial_reference.try_into().unwrap();
1✔
576

1✔
577
        assert_eq!(gdal_sref.auth_name().unwrap(), "EPSG");
1✔
578
        assert_eq!(gdal_sref.auth_code().unwrap(), 4326);
1✔
579
    }
1✔
580
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc