下面的
difference
函数计算两个向量层之间的布尔差,依赖于两个私有函数difference_recursive
和inner_difference_recursive
。如何删除重复的代码以将这两个函数合并为一个递归函数?
difference_recursive
和inner_difference_recursive
之间的区别是:
input_geom
参数类型分别是引用 (&Geometry
) 和拥有数据 (Geometry
)。Some(input_geom.clone)
或 Some(input_geom)
。我发布了另一个问题,我试图将问题提炼为一般情况。
进一步解释一下,第一次调用递归函数时,
input_geom
参数由返回引用的FeatureIterator
提供。尝试取消引用 FeatureIterator
返回的引用会产生编译器错误 cannot move out of *input_geom which is behind a shared reference
。对于后续调用递归函数,参数是 difference
函数的结果,该函数返回拥有的数据。
use gdal::vector::{FeatureIterator, Geometry, LayerAccess};
fn difference_recursive(input_geom: &Geometry, mut features: FeatureIterator) -> Option<Geometry> {
match features.next() {
None => Some(input_geom.clone()),
Some(feature) => match feature.geometry() {
None => Some(input_geom.clone()),
Some(overlay_geom) => match input_geom.difference(overlay_geom) {
None => None,
Some(output_geom) => inner_difference_recursive(output_geom, features),
},
},
}
}
fn inner_difference_recursive(
input_geom: Geometry,
mut features: FeatureIterator,
) -> Option<Geometry> {
match features.next() {
None => Some(input_geom),
Some(feature) => match feature.geometry() {
None => Some(input_geom),
Some(overlay_geom) => match input_geom.difference(overlay_geom) {
None => None,
Some(output_geom) => inner_difference_recursive(output_geom, features),
},
},
}
}
pub fn difference(
input: gdal::Dataset,
overlay: gdal::Dataset,
output_filename: &str,
) -> Result<(), String> {
// Setup input layer
let mut input_layers_iter = input.layers();
let mut input_layer = match input_layers_iter.next() {
Some(input_layer) => input_layer,
None => return Err("No input layer".to_string()),
};
// Setup overlay layer
let mut overlay_layers_iter = overlay.layers();
let mut overlay_layer = match overlay_layers_iter.next() {
Some(overlay_layer) => overlay_layer,
None => return Err("No overlay error".to_string()),
};
// Setup output layer
let driver = input.driver();
let mut layer_options = gdal::vector::LayerOptions::default();
let srs = input_layer.spatial_ref();
layer_options.srs = srs.as_ref();
let mut output_datasest = match driver.create_vector_only(output_filename) {
Ok(ds) => ds,
Err(_) => return Err("Failed to createt output layer dataset".to_string()),
};
let mut output_layer = match output_datasest.create_layer(layer_options) {
Ok(layer) => layer,
Err(_) => return Err("Failed to create output layer".to_string()),
};
// Iterate over input layer features
for input_feature in input_layer.features() {
if let Some(input_geom) = input_feature.geometry() {
if let Some(output_geom) = difference_recursive(input_geom, overlay_layer.features()) {
let _result = output_layer.create_feature(output_geom);
}
}
}
// Save data
if let Err(_) = output_datasest.flush_cache() {
Err("Error saving data.".to_string())
} else {
Ok(())
}
}
解决方案是使用
Cow
:
pub fn difference_recursive<'a>(
input_geom: Cow<'a, Geometry>,
mut features: FeatureIterator,
) -> Option<Geometry> {
match features.next() {
None => Some(input_geom.into_owned()),
Some(feature) => match feature.geometry() {
None => Some(input_geom.into_owned()),
Some(overlay_geom) => match input_geom.difference(overlay_geom) {
None => None,
Some(output_geom) => difference_recursive(Cow::Owned(output_geom), features),
},
},
}
}
对函数的原始调用然后通过
Cow
将输入包装在 Cow::Borrowed(input_geom)
中。