1 use libc::c_int;
2 use std::ffi::{CString, CStr};
3 use std::ptr;
4 use std::str::FromStr;
5 use utils::{_string, _last_null_pointer_err, _last_cpl_err};
6 use gdal_sys::{self, CPLErr, OGRCoordinateTransformationH, OGRErr, OGRSpatialReferenceH};
7 
8 use errors::*;
9 
10 pub struct CoordTransform{
11     inner: OGRCoordinateTransformationH,
12     from: String,
13     to: String,
14 }
15 
16 impl Drop for CoordTransform {
drop(&mut self)17     fn drop(&mut self) {
18         unsafe { gdal_sys::OCTDestroyCoordinateTransformation(self.inner) };
19         self.inner = ptr::null_mut();
20     }
21 }
22 
23 impl CoordTransform {
new(sp_ref1: &SpatialRef, sp_ref2: &SpatialRef) -> Result<CoordTransform>24     pub fn new(sp_ref1: &SpatialRef, sp_ref2: &SpatialRef) -> Result<CoordTransform> {
25         let c_obj = unsafe { gdal_sys::OCTNewCoordinateTransformation(sp_ref1.0, sp_ref2.0) };
26         if c_obj.is_null() {
27             Err(_last_null_pointer_err("OCTNewCoordinateTransformation"))?;
28         }
29         Ok(CoordTransform{
30             inner: c_obj,
31             from: sp_ref1.authority().or_else(|_| sp_ref1.to_proj4())?,
32             to: sp_ref2.authority().or_else(|_| sp_ref2.to_proj4())?
33         })
34     }
35 
transform_coords(&self, x: &mut [f64], y: &mut [f64], z: &mut [f64]) -> Result<()>36     pub fn transform_coords(&self, x: &mut [f64], y: &mut [f64], z: &mut [f64]) -> Result<()> {
37         let nb_coords = x.len();
38         assert_eq!(nb_coords, y.len());
39         let ret_val = unsafe {
40             gdal_sys::OCTTransform(
41                 self.inner,
42                 nb_coords as c_int,
43                 x.as_mut_ptr(),
44                 y.as_mut_ptr(),
45                 z.as_mut_ptr(),
46             ) == 1
47         };
48 
49         if ret_val {
50             Ok(())
51         } else {
52             let err = _last_cpl_err(CPLErr::CE_Failure);
53             let msg = if let ErrorKind::CplError{msg, ..} = err {
54                 if msg.trim().is_empty() {
55                     None
56                 } else {
57                     Some(msg)
58                 }
59             } else {
60                 Err(err)?
61             };
62             Err(ErrorKind::InvalidCoordinateRange{from: self.from.clone(), to: self.to.clone(), msg})?
63         }
64     }
65 
66     #[deprecated(since = "0.3.1", note = "use `transform_coords` instead")]
transform_coord(&self, x: &mut [f64], y: &mut [f64], z: &mut [f64])67     pub fn transform_coord(&self, x: &mut [f64], y: &mut [f64], z: &mut [f64]){
68         self.transform_coords(x, y, z).expect("Coordinate transform failed")
69     }
70 
to_c_hct(&self) -> OGRCoordinateTransformationH71     pub fn to_c_hct(&self) -> OGRCoordinateTransformationH {
72         self.inner
73     }
74 }
75 
76 #[derive(Debug)]
77 pub struct SpatialRef(OGRSpatialReferenceH);
78 
79 impl Drop for SpatialRef {
drop(&mut self)80     fn drop(&mut self){
81         unsafe { gdal_sys::OSRRelease(self.0)};
82         self.0 = ptr::null_mut();
83     }
84 }
85 
86 impl Clone for SpatialRef {
clone(&self) -> SpatialRef87     fn clone(&self) -> SpatialRef {
88         let n_obj = unsafe { gdal_sys::OSRClone(self.0)};
89         SpatialRef(n_obj)
90     }
91 }
92 
93 impl PartialEq for SpatialRef {
eq(&self, other: &SpatialRef) -> bool94     fn eq(&self, other: &SpatialRef) -> bool {
95         unsafe { gdal_sys::OSRIsSame(self.0, other.0) == 1 }
96     }
97 }
98 
99 impl SpatialRef {
new() -> Result<SpatialRef>100     pub fn new() -> Result<SpatialRef> {
101         let c_obj = unsafe { gdal_sys::OSRNewSpatialReference(ptr::null()) };
102         if c_obj.is_null() {
103             Err(_last_null_pointer_err("OSRNewSpatialReference"))?;
104         }
105         Ok(SpatialRef(c_obj))
106     }
107 
from_definition(definition: &str) -> Result<SpatialRef>108     pub fn from_definition(definition: &str) -> Result<SpatialRef> {
109         let c_obj = unsafe { gdal_sys::OSRNewSpatialReference(ptr::null()) };
110         if c_obj.is_null() {
111             Err(_last_null_pointer_err("OSRNewSpatialReference"))?;
112         }
113         let rv = unsafe { gdal_sys::OSRSetFromUserInput(c_obj, CString::new(definition)?.as_ptr()) };
114         if rv != OGRErr::OGRERR_NONE {
115             Err(ErrorKind::OgrError{err: rv, method_name: "OSRSetFromUserInput"})?;
116         }
117         Ok(SpatialRef(c_obj))
118     }
119 
from_wkt(wkt: &str) -> Result<SpatialRef>120     pub fn from_wkt(wkt: &str) -> Result<SpatialRef> {
121         let c_str = CString::new(wkt)?;
122         let c_obj = unsafe { gdal_sys::OSRNewSpatialReference(c_str.as_ptr()) };
123         if c_obj.is_null() {
124             Err(_last_null_pointer_err("OSRNewSpatialReference"))?;
125         }
126         Ok(SpatialRef(c_obj))
127     }
128 
from_epsg(epsg_code: u32) -> Result<SpatialRef>129     pub fn from_epsg(epsg_code: u32) -> Result<SpatialRef> {
130         let null_ptr = ptr::null_mut();
131         let c_obj = unsafe { gdal_sys::OSRNewSpatialReference(null_ptr) };
132         let rv = unsafe { gdal_sys::OSRImportFromEPSG(c_obj, epsg_code as c_int) };
133         if rv != OGRErr::OGRERR_NONE {
134             Err(ErrorKind::OgrError{err: rv, method_name: "OSRImportFromEPSG"})?
135         } else {
136             Ok(SpatialRef(c_obj))
137         }
138     }
139 
from_proj4(proj4_string: &str) -> Result<SpatialRef>140     pub fn from_proj4(proj4_string: &str) -> Result<SpatialRef> {
141         let c_str = CString::new(proj4_string)?;
142         let null_ptr = ptr::null_mut();
143         let c_obj = unsafe { gdal_sys::OSRNewSpatialReference(null_ptr) };
144         let rv = unsafe { gdal_sys::OSRImportFromProj4(c_obj, c_str.as_ptr()) };
145         if rv != OGRErr::OGRERR_NONE {
146             Err(ErrorKind::OgrError{err: rv, method_name: "OSRImportFromProj4"})?
147         } else {
148             Ok(SpatialRef(c_obj))
149         }
150     }
151 
from_esri(esri_wkt: &str) -> Result<SpatialRef>152     pub fn from_esri(esri_wkt: &str) -> Result<SpatialRef> {
153         let c_str = CString::new(esri_wkt)?;
154         let mut ptrs = vec![c_str.as_ptr() as *mut i8, ptr::null_mut()];
155         let null_ptr = ptr::null_mut();
156         let c_obj = unsafe { gdal_sys::OSRNewSpatialReference(null_ptr) };
157         let rv = unsafe { gdal_sys::OSRImportFromESRI(c_obj, ptrs.as_mut_ptr()) };
158         if rv != OGRErr::OGRERR_NONE {
159             Err(ErrorKind::OgrError{err: rv, method_name: "OSRImportFromESRI"})?
160         } else {
161             Ok(SpatialRef(c_obj))
162         }
163     }
164 
from_c_obj(c_obj: OGRSpatialReferenceH) -> Result<SpatialRef>165     pub fn from_c_obj(c_obj: OGRSpatialReferenceH) -> Result<SpatialRef> {
166         let mut_c_obj = unsafe { gdal_sys::OSRClone(c_obj) };
167         if mut_c_obj.is_null() {
168            Err(_last_null_pointer_err("OSRClone"))?
169         } else {
170             Ok(SpatialRef(mut_c_obj))
171         }
172     }
173 
to_wkt(&self) -> Result<String>174     pub fn to_wkt(&self) -> Result<String> {
175         let mut c_wkt = ptr::null_mut();
176         let rv = unsafe { gdal_sys::OSRExportToWkt(self.0, &mut c_wkt) };
177         if rv != OGRErr::OGRERR_NONE {
178             Err(ErrorKind::OgrError{err: rv, method_name: "OSRExportToWkt"})?
179         } else {
180             Ok(_string(c_wkt))
181         }
182     }
183 
morph_to_esri(&self) -> Result<()>184     pub fn morph_to_esri(&self) -> Result<()> {
185         let rv = unsafe { gdal_sys::OSRMorphToESRI(self.0) };
186         if rv != OGRErr::OGRERR_NONE {
187             Err(ErrorKind::OgrError{err: rv, method_name: "OSRMorphToESRI"})?;
188         }
189         Ok(())
190     }
191 
to_pretty_wkt(&self) -> Result<String>192     pub fn to_pretty_wkt(&self) -> Result<String> {
193         let mut c_wkt = ptr::null_mut();
194         let rv = unsafe { gdal_sys::OSRExportToPrettyWkt(self.0, &mut c_wkt, false as c_int) };
195         if rv != OGRErr::OGRERR_NONE {
196             Err(ErrorKind::OgrError{err: rv, method_name: "OSRExportToPrettyWkt"})?
197         } else {
198             Ok(_string(c_wkt))
199         }
200     }
201 
to_xml(&self) -> Result<String>202     pub fn to_xml(&self) -> Result<String> {
203         let mut c_raw_xml = ptr::null_mut();
204         let rv = unsafe { gdal_sys::OSRExportToXML(self.0, &mut c_raw_xml, ptr::null()) };
205         if rv != OGRErr::OGRERR_NONE {
206             Err(ErrorKind::OgrError{err: rv, method_name: "OSRExportToXML"})?
207         } else {
208             Ok(_string(c_raw_xml))
209         }
210     }
211 
to_proj4(&self) -> Result<String>212     pub fn to_proj4(&self) -> Result<String> {
213         let mut c_proj4str = ptr::null_mut();
214         let rv = unsafe { gdal_sys::OSRExportToProj4(self.0, &mut c_proj4str) };
215         if rv != OGRErr::OGRERR_NONE {
216             Err(ErrorKind::OgrError{err: rv, method_name: "OSRExportToProj4"}.into())
217         } else {
218             Ok(_string(c_proj4str))
219         }
220     }
221 
auth_name(&self) -> Result<String>222     pub fn auth_name(&self) -> Result<String> {
223         let c_ptr = unsafe { gdal_sys::OSRGetAuthorityName(self.0, ptr::null()) };
224         if c_ptr.is_null() {
225             Err(_last_null_pointer_err("SRGetAuthorityName"))?
226         } else {
227             Ok(_string(c_ptr))
228         }
229     }
230 
auth_code(&self) -> Result<i32>231     pub fn auth_code(&self) -> Result<i32> {
232         let c_ptr = unsafe { gdal_sys::OSRGetAuthorityCode(self.0, ptr::null()) };
233         if c_ptr.is_null() {
234             Err(_last_null_pointer_err("OSRGetAuthorityCode"))?;
235         }
236         let c_str = unsafe { CStr::from_ptr(c_ptr) };
237         let epsg = i32::from_str(c_str.to_str()?);
238         match epsg {
239             Ok(n) => Ok(n),
240             Err(_) => Err(ErrorKind::OgrError{err: OGRErr::OGRERR_UNSUPPORTED_SRS, method_name: "OSRGetAuthorityCode"})?
241         }
242     }
243 
authority(&self) -> Result<String>244     pub fn authority(&self) -> Result<String> {
245         let c_ptr = unsafe { gdal_sys::OSRGetAuthorityName(self.0, ptr::null()) };
246         if c_ptr.is_null() {
247             Err(_last_null_pointer_err("SRGetAuthorityName"))?;
248         }
249         let name = unsafe { CStr::from_ptr(c_ptr) }.to_str()?;
250         let c_ptr = unsafe { gdal_sys::OSRGetAuthorityCode(self.0, ptr::null()) };
251         if c_ptr.is_null() {
252             Err(_last_null_pointer_err("OSRGetAuthorityCode"))?;
253         }
254         let code = unsafe { CStr::from_ptr(c_ptr) }.to_str()?;
255         Ok(format!("{}:{}", name, code))
256     }
257 
auto_identify_epsg(&mut self) -> Result<()>258     pub fn auto_identify_epsg(&mut self) -> Result<()> {
259         let rv = unsafe { gdal_sys::OSRAutoIdentifyEPSG(self.0) };
260         if rv != OGRErr::OGRERR_NONE {
261             Err(ErrorKind::OgrError{err: rv, method_name: "OSRAutoIdentifyEPSG"})?
262         } else {
263             Ok(())
264         }
265     }
266 
267     // TODO: should this take self instead of &self?
to_c_hsrs(&self) -> OGRSpatialReferenceH268     pub fn to_c_hsrs(&self) -> OGRSpatialReferenceH {
269         self.0
270     }
271 }
272