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