Skip to content

Commit

Permalink
remove need for clone to find nearest
Browse files Browse the repository at this point in the history
  • Loading branch information
Quba1 committed Feb 3, 2024
1 parent 5f69b52 commit f3a26be
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 101 deletions.
4 changes: 2 additions & 2 deletions src/codes_handle/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,12 +283,12 @@ mod tests {

// Now unwrap and access the first and only element of resulting vector
// Find nearest modifies internal KeyedMessage fields so we need mutable reference
let level = &mut level[0];
let level = &level[0];

println!("{:?}", level.read_key("shortName"));

// Get the four nearest gridpoints of Reykjavik
let nearest_gridpoints = level.find_nearest(64.13, -21.89).unwrap();
let nearest_gridpoints = level.codes_nearest()?.find_nearest(64.13, -21.89).unwrap();

// Print value and distance of the nearest gridpoint
println!(
Expand Down
108 changes: 9 additions & 99 deletions src/codes_handle/keyed_message/mod.rs
Original file line number Diff line number Diff line change
@@ -1,83 +1,29 @@
mod iterator;
mod nearest;
mod read;
mod write;

use eccodes_sys::codes_nearest;
use log::warn;
use std::ptr::null_mut;

use crate::{
codes_handle::KeyedMessage,
errors::CodesError,
intermediate_bindings::{
codes_grib_nearest_delete, codes_grib_nearest_find, codes_grib_nearest_new,
codes_handle_clone, codes_handle_delete, codes_keys_iterator_delete,
codes_grib_nearest_new, codes_handle_clone, codes_handle_delete, codes_keys_iterator_delete,
},
};

use super::{KeysIteratorFlags, NearestGridpoint};
use super::{CodesNearest, KeysIteratorFlags};

impl KeyedMessage {
fn nearest_handle(&mut self) -> Result<*mut codes_nearest, CodesError> {
if let Some(nrst) = self.nearest_handle {
Ok(nrst)
} else {
let nrst;
pub fn codes_nearest(&self) -> Result<CodesNearest, CodesError> {
let nearest_handle = unsafe { codes_grib_nearest_new(self.message_handle)? };

unsafe {
nrst = codes_grib_nearest_new(self.message_handle)?;
}

self.nearest_handle = Some(nrst);

Ok(nrst)
}
}

///Function to get four [`NearestGridpoint`]s of a point represented by requested coordinates.
///
///The inputs are latitude and longitude of requested point in respectively degrees north and
///degreed east.
///
///In the output gridpoints, the value field refers to parameter held by the `KeyedMessage`
///for which the function is called in adequate units,
///coordinates are in degrees north/east,
///and distance field represents the distance between requested point and output point in kilometers.
///
///### Example
///
///```
///# use eccodes::codes_handle::{ProductKind, CodesHandle, KeyedMessage, KeysIteratorFlags};
///# use std::path::Path;
///# use eccodes::codes_handle::KeyType::Str;
///# use eccodes::FallibleIterator;
///let file_path = Path::new("./data/iceland.grib");
///let product_kind = ProductKind::GRIB;
///
///let mut handle = CodesHandle::new_from_file(file_path, product_kind).unwrap();
///let mut msg = handle.next().unwrap().unwrap();
///
///
///let out = msg.find_nearest(64.13, -21.89).unwrap();
///```
///
///### Errors
///
///This function returns [`CodesInternal`](crate::errors::CodesInternal) when
///one of ecCodes function returns the non-zero code.
pub fn find_nearest(
&mut self,
lat: f64,
lon: f64,
) -> Result<[NearestGridpoint; 4], CodesError> {
let nrst = self.nearest_handle()?;
let output_points;

unsafe {
output_points = codes_grib_nearest_find(self.message_handle, nrst, lat, lon)?;
}

Ok(output_points)
Ok(CodesNearest {
nearest_handle,
parent_message: self,
})
}
}

Expand Down Expand Up @@ -115,19 +61,6 @@ impl Drop for KeyedMessage {
///In case of corrupt pointer segmentation fault will occur.
///The pointers are cleared at the end of drop as they are not functional despite the result of delete functions.
fn drop(&mut self) {
if let Some(nrst) = self.nearest_handle {
unsafe {
codes_grib_nearest_delete(nrst).unwrap_or_else(|error| {
warn!(
"codes_grib_nearest_delete() returned an error: {:?}",
&error
);
});
}
}

self.nearest_handle = Some(null_mut());

if let Some(kiter) = self.keys_iterator {
unsafe {
codes_keys_iterator_delete(kiter).unwrap_or_else(|error| {
Expand Down Expand Up @@ -220,27 +153,4 @@ mod tests {

Ok(())
}

#[test]
fn find_nearest() -> Result<()> {
let file_path1 = Path::new("./data/iceland.grib");
let file_path2 = Path::new("./data/iceland-surface.grib");
let product_kind = ProductKind::GRIB;

let mut handle1 = CodesHandle::new_from_file(file_path1, product_kind).unwrap();
let msg1 = handle1.next()?.unwrap();
let out1 = msg1.clone().find_nearest(64.13, -21.89).unwrap();

let mut handle2 = CodesHandle::new_from_file(file_path2, product_kind).unwrap();
let msg2 = handle2.next()?.unwrap();
let out2 = msg2.clone().find_nearest(64.13, -21.89).unwrap();

assert!(out1[0].value > 10000.0);
assert!(out2[3].index == 551);
assert!(out1[1].lat == 64.0);
assert!(out2[2].lon == -21.75);
assert!(out1[0].distance > 15.0);

Ok(())
}
}
107 changes: 107 additions & 0 deletions src/codes_handle/keyed_message/nearest.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
use std::ptr::null_mut;

use log::warn;

use crate::{
codes_handle::CodesNearest,
intermediate_bindings::{codes_grib_nearest_delete, codes_grib_nearest_find},
CodesError, NearestGridpoint,
};

impl CodesNearest<'_> {
///Function to get four [`NearestGridpoint`]s of a point represented by requested coordinates.
///
///The inputs are latitude and longitude of requested point in respectively degrees north and
///degreed east.
///
///In the output gridpoints, the value field refers to parameter held by the `KeyedMessage`
///for which the function is called in adequate units,
///coordinates are in degrees north/east,
///and distance field represents the distance between requested point and output point in kilometers.
///
///### Example
///
///```
///# use eccodes::codes_handle::{ProductKind, CodesHandle, KeyedMessage, KeysIteratorFlags};
///# use std::path::Path;
///# use eccodes::codes_handle::KeyType::Str;
///# use eccodes::FallibleIterator;
///let file_path = Path::new("./data/iceland.grib");
///let product_kind = ProductKind::GRIB;
///
///let mut handle = CodesHandle::new_from_file(file_path, product_kind).unwrap();
///let mut msg = handle.next().unwrap().unwrap();
///
///
///let out = msg.find_nearest(64.13, -21.89).unwrap();
///```
///
///### Errors
///
///This function returns [`CodesInternal`](crate::errors::CodesInternal) when
///one of ecCodes function returns the non-zero code.
pub fn find_nearest(&self, lat: f64, lon: f64) -> Result<[NearestGridpoint; 4], CodesError> {
let output_points;

unsafe {
output_points = codes_grib_nearest_find(
self.parent_message.message_handle,
self.nearest_handle,
lat,
lon,
)?;
}

Ok(output_points)
}
}

impl Drop for CodesNearest<'_> {
fn drop(&mut self) {
unsafe {
codes_grib_nearest_delete(self.nearest_handle).unwrap_or_else(|error| {
warn!(
"codes_grib_nearest_delete() returned an error: {:?}",
&error
);
});
}

self.nearest_handle = null_mut();
}
}

#[cfg(test)]
mod tests {
use std::path::Path;

use anyhow::Result;
use fallible_streaming_iterator::FallibleStreamingIterator;

use crate::{CodesHandle, ProductKind};

#[test]
fn find_nearest() -> Result<()> {
let file_path1 = Path::new("./data/iceland.grib");
let file_path2 = Path::new("./data/iceland-surface.grib");
let product_kind = ProductKind::GRIB;

let mut handle1 = CodesHandle::new_from_file(file_path1, product_kind).unwrap();
let msg1 = handle1.next()?.unwrap();
let nrst1 = msg1.codes_nearest()?;
let out1 = nrst1.find_nearest(64.13, -21.89)?;

let mut handle2 = CodesHandle::new_from_file(file_path2, product_kind).unwrap();
let msg2 = handle2.next()?.unwrap();
let nrst2 = msg2.codes_nearest()?;
let out2 = nrst2.find_nearest(64.13, -21.89)?;

assert!(out1[0].value > 10000.0);
assert!(out2[3].index == 551);
assert!(out1[1].lat == 64.0);
assert!(out2[2].lon == -21.75);
assert!(out1[0].distance > 15.0);

Ok(())
}
}
6 changes: 6 additions & 0 deletions src/codes_handle/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,12 @@ pub enum ProductKind {
GRIB = ProductKind_PRODUCT_GRIB as isize,
}

#[derive(Debug)]
pub struct CodesNearest<'a> {
nearest_handle: *mut codes_nearest,
parent_message: &'a KeyedMessage,
}

///The structure returned by [`KeyedMessage::find_nearest()`].
///Should always be analysed in relation to the coordinates request in `find_nearest()`.
#[derive(Copy, Clone, PartialEq, Debug, Default)]
Expand Down

0 comments on commit f3a26be

Please sign in to comment.