diff --git a/src/proj.rs b/src/proj.rs index 5f80cc5f..1cc1213d 100644 --- a/src/proj.rs +++ b/src/proj.rs @@ -8,7 +8,7 @@ use proj_sys::{ proj_create, proj_create_crs_to_crs, proj_destroy, proj_errno_string, proj_get_area_of_use, proj_grid_cache_set_enable, proj_info, proj_normalize_for_visualization, proj_pj_info, proj_trans, proj_trans_array, PJconsts, PJ_AREA, PJ_CONTEXT, PJ_COORD, PJ_DIRECTION_PJ_FWD, - PJ_DIRECTION_PJ_INV, PJ_INFO, PJ_LP, PJ_XY, + PJ_DIRECTION_PJ_INV, PJ_INFO, PJ_LPZT, PJ_XYZT, }; use std::{ ffi, @@ -673,11 +673,17 @@ impl Proj { // This signals that we wish to project geodetic coordinates. // For conversion (i.e. between projected coordinates) you should use // PJ_XY {x: , y: } - let coords = PJ_LP { lam: c_x, phi: c_y }; + // We also initialize z and t in case libproj tries to read them. + let coords = PJ_LPZT { + lam: c_x, + phi: c_y, + z: 0.0, + t: f64::INFINITY, + }; unsafe { proj_errno_reset(self.c_proj); // PJ_DIRECTION_* determines a forward or inverse projection - let trans = proj_trans(self.c_proj, inv, PJ_COORD { lp: coords }); + let trans = proj_trans(self.c_proj, inv, PJ_COORD { lpzt: coords }); // output of coordinates uses the PJ_XY struct new_x = trans.xy.x; new_y = trans.xy.y; @@ -738,10 +744,19 @@ impl Proj { let new_x; let new_y; let err; - let coords = PJ_XY { x: c_x, y: c_y }; + + // This doesn't seem strictly correct, but if we set PJ_XY or PJ_LP here, the + // other two values remain uninitialized and we can't be sure that libproj + // doesn't try to read them. proj_trans_generic does the same thing. + let xyzt = PJ_XYZT { + x: c_x, + y: c_y, + z: 0.0, + t: f64::INFINITY, + }; unsafe { proj_errno_reset(self.c_proj); - let trans = proj_trans(self.c_proj, PJ_DIRECTION_PJ_FWD, PJ_COORD { xy: coords }); + let trans = proj_trans(self.c_proj, PJ_DIRECTION_PJ_FWD, PJ_COORD { xyzt }); new_x = trans.xy.x; new_y = trans.xy.y; err = proj_errno(self.c_proj); @@ -860,7 +875,12 @@ impl Proj { let c_x: c_double = point.x().to_f64().ok_or(ProjError::FloatConversion)?; let c_y: c_double = point.y().to_f64().ok_or(ProjError::FloatConversion)?; Ok(PJ_COORD { - xy: PJ_XY { x: c_x, y: c_y }, + xyzt: PJ_XYZT { + x: c_x, + y: c_y, + z: 0.0, + t: f64::INFINITY, + }, }) }) .collect::, ProjError>>()?; @@ -1152,11 +1172,11 @@ mod test { fn test_conversion() { // Generated by PROJ by specifying "from" and "to" EPSG codes and calling def() let projstring = " - proj=pipeline step proj=unitconvert xy_in=us-ft - xy_out=m step inv proj=lcc lat_0=32.1666666666667 - lon_0=-116.25 lat_1=33.8833333333333 lat_2=32.7833333333333 - x_0=2000000.0001016 y_0=500000.0001016 ellps=GRS80 step proj=lcc lat_0=32.1666666666667 - lon_0=-116.25 lat_1=33.8833333333333 lat_2=32.7833333333333 x_0=2000000 y_0=500000 + proj=pipeline step proj=unitconvert xy_in=us-ft + xy_out=m step inv proj=lcc lat_0=32.1666666666667 + lon_0=-116.25 lat_1=33.8833333333333 lat_2=32.7833333333333 + x_0=2000000.0001016 y_0=500000.0001016 ellps=GRS80 step proj=lcc lat_0=32.1666666666667 + lon_0=-116.25 lat_1=33.8833333333333 lat_2=32.7833333333333 x_0=2000000 y_0=500000 ellps=GRS80 "; let nad83_m = Proj::new(projstring).unwrap();