计算两个矢量图层之间的几何差异

问题描述 投票:0回答:1

下面的

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(())
    }
}


rust geometry geospatial gdal geo
1个回答
0
投票

解决方案是使用

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)
中。

© www.soinside.com 2019 - 2024. All rights reserved.