-
-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
✨ Get affine transformation from GeoTIFF #8
Conversation
Implement transform method in CogReader struct to get affine transformation matrix from GeoTIFF via ModelPixelScaleTag and ModelTiepointTag. Added a unit test to check that the x/y pixel size and top left origin pixel coordinates is correct.
Explicitly mentioning the internal fields of the AffineTransform struct, specifically the pixel resolution, rotation and origin, and included a reference to the GeoTIFF standard. Also renamed origin_x/origin_y to x_origin/y_origin.
Supposed to be parsed from the ModelTransformationTag, but haven't found a sample GeoTIFF online with non-zero rotation to implement this properly with a unit test, so marking as unimplemented for now.
/// - <https://docs.ogc.org/is/19-008r4/19-008r4.html#_coordinate_transformations> | ||
fn transform(&mut self) -> TiffResult<AffineTransform<f64>> { | ||
// Get x and y axis rotation (not yet implemented) | ||
let (x_rotation, y_rotation): (f64, f64) = | ||
match self.decoder.get_tag_f64_vec(Tag::ModelTransformationTag) { | ||
Ok(_model_transformation) => unimplemented!("Non-zero rotation is not handled yet"), | ||
Err(_) => (0.0, 0.0), | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note to future self (or someone else), find a GeoTIFF with non-zero rotation values and implement this properly.
// Get pixel size in x and y direction | ||
let pixel_scale: Vec<f64> = self.decoder.get_tag_f64_vec(Tag::ModelPixelScaleTag)?; | ||
let [x_scale, y_scale, _z_scale] = pixel_scale[0..3] else { | ||
return Err(TiffError::FormatError(TiffFormatError::InvalidTag)); | ||
}; | ||
|
||
// Get x and y coordinates of upper left pixel | ||
let tie_points: Vec<f64> = self.decoder.get_tag_f64_vec(Tag::ModelTiepointTag)?; | ||
let [_i, _j, _k, x_origin, y_origin, _z_origin] = tie_points[0..6] else { | ||
return Err(TiffError::FormatError(TiffFormatError::InvalidTag)); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tried a few different ways to convert the Vec to an array (e.g. following https://stackoverflow.com/questions/29570607/is-there-a-good-way-to-convert-a-vect-to-an-array), but couldn't quite get it to work, and the code was very messy. The code here works, but might silently handle cases where pixel_scale.len() > 3
or tie_points.len() > 6
incorrectly, rather than raising an error, so should come back and refactor this sometime.
Implement transform method in CogReader struct to get affine transformation matrix from GeoTIFF via ModelPixelScaleTag and ModelTiepointTag.
Uses the
AffineTransform
struct from thegeo
crate. Note that the fields in the struct (a, b, xoff, c, d, yoff) are not made public, but it might be useful if it was!TODO:
transform
method moreInvalidTag
isn't too descriptive, but good enough 🤞)TODO in the future:
References: