SuperMap iObjects .NET 11i 二次开发(十七)—— 叠加分析之擦除

前言

上一篇博文简单介绍了有关叠加分析之合并的相关操作,这个部分主要认识下叠加分析之擦除的相关操作。


一、有关常用类说明

|---------------------|--------------------------------------|
| OverlayAnalyst类 | 叠加分析类。该类用于对输入的两个数据集或记录集之间进行各种叠加分析运算。 |

二、有关常用方法说明

三、界面设计

在原有界面基础上,添加合并相关功能点,如下图所示:

四、功能实现

cs 复制代码
private void 擦除ToolStripMenuItem_Click(object sender, EventArgs e)
{
    try
    {
        // 1. 获取当前选中的数据集节点(需要选择2个:被擦除数据集和擦除数据集)
        List<WorkspaceTreeNodeBase> selectedNodes = new List<WorkspaceTreeNodeBase>();

        // 获取工作空间树中所有选中的节点
        foreach (TreeNode node in D_workspaceControl.WorkspaceTree.SelectedNodes)
        {
            if (node is WorkspaceTreeNodeBase workspaceNode)
            {
                selectedNodes.Add(workspaceNode);
            }
        }

        // 2. 检查是否选择了恰好2个数据集
        if (selectedNodes.Count != 2)
        {
            MessageBox.Show("请选择2个面数据集进行擦除操作!\n\n操作说明:按住Ctrl键选择2个数据集节点(第一个为被擦除数据集,第二个为擦除数据集),然后点击擦除功能。");
            return;
        }

        // 3. 将选中的节点转换为数据集
        List<DatasetVector> selectedDatasets = new List<DatasetVector>();
        List<string> invalidDatasets = new List<string>();

        foreach (WorkspaceTreeNodeBase node in selectedNodes)
        {
            Dataset dataset = D_workspace.Datasources[0].Datasets[node.Text];
            if (dataset == null)
            {
                invalidDatasets.Add(node.Text);
                continue;
            }

            // 检查是否为矢量数据集
            if (!(dataset is DatasetVector))
            {
                invalidDatasets.Add($"{node.Text} (非矢量数据集)");
                continue;
            }

            DatasetVector vectorDataset = (DatasetVector)dataset;

            // 检查是否为面数据集(Erase方法要求)
            if (vectorDataset.Type != DatasetType.Region)
            {
                invalidDatasets.Add($"{node.Text} ({GetDatasetTypeChineseName(vectorDataset.Type)}数据集)");
                continue;
            }

            selectedDatasets.Add(vectorDataset);
        }

        // 4. 检查有效的面数据集数量
        if (selectedDatasets.Count != 2)
        {
            string invalidList = invalidDatasets.Count > 0 ?
                $"\n\n无效的数据集:\n{string.Join("\n", invalidDatasets)}" : "";

            MessageBox.Show($"需要选择2个面数据集进行擦除!当前选择了 {selectedDatasets.Count} 个有效的面数据集。{invalidList}");
            return;
        }

        // 5. 检查所有数据集的投影信息一致性
        PrjCoordSys firstPrj = selectedDatasets[0].PrjCoordSys;
        List<string> inconsistentDatasets = new List<string>();

        for (int i = 1; i < selectedDatasets.Count; i++) // 从第二个开始检查
        {
            if (!IsPrjCoordSysEqual(firstPrj, selectedDatasets[i].PrjCoordSys))
            {
                inconsistentDatasets.Add(selectedDatasets[i].Name);
            }
        }

        if (inconsistentDatasets.Count > 0)
        {
            MessageBox.Show($"数据集投影信息不一致!请确保所有数据集使用相同的投影坐标系。\n" +
                          $"投影不一致的数据集: {string.Join(", ", inconsistentDatasets)}\n" +
                          $"参考投影: {selectedDatasets[0].Name}");
            return;
        }

        // 6. 检查数据集是否都有记录
        List<string> emptyDatasets = new List<string>();
        foreach (DatasetVector dataset in selectedDatasets)
        {
            if (dataset.RecordCount == 0)
            {
                emptyDatasets.Add(dataset.Name);
            }
        }

        if (emptyDatasets.Count > 0)
        {
            MessageBox.Show($"以下数据集没有记录,无法进行擦除:\n{string.Join("\n", emptyDatasets)}");
            return;
        }

        // 7. 设置擦除参数
        DatasetVector sourceDataset = selectedDatasets[0]; // 被擦除数据集
        DatasetVector eraseDataset = selectedDatasets[1];  // 擦除数据集

        OverlayAnalystParameter overlayParameter = new OverlayAnalystParameter();
        overlayParameter.Tolerance = 0.0; // 容限值

        // 合并两个数据集的所有字段名称
        List<string> allFields = new List<string>();

        // 添加源数据集的所有字段
        foreach (SuperMap.Data.FieldInfo field in sourceDataset.FieldInfos)
        {
            allFields.Add(field.Name);
        }

        // 添加擦除数据集的所有字段(避免重复字段)
        foreach (SuperMap.Data.FieldInfo field in eraseDataset.FieldInfos)
        {
            string fieldName = field.Name;

            // 如果字段名已存在,可能需要重命名或跳过
            // 这里简单跳过重复字段名,您可以根据需要调整
            if (!allFields.Contains(fieldName))
            {
                allFields.Add(fieldName);
            }
            else
            {
                // 如果字段名重复,可以添加后缀区分
                // allFields.Add($"{fieldName}_Erase");
            }
        }

        overlayParameter.OperationRetainedFields = allFields.ToArray();


        // 生成唯一的结果数据集名称
        string resultDatasetName = GenerateUniqueDatasetName($"{sourceDataset.Name}_擦除结果");
        Datasource resultDatasource = sourceDataset.Datasource;

        // 8. 先创建结果数据集
        DatasetVectorInfo datasetVectorInfo = new DatasetVectorInfo();
        datasetVectorInfo.Name = resultDatasetName;
        datasetVectorInfo.Type = DatasetType.Region; // 面数据集

        // 创建结果数据集
        DatasetVector resultDataset = resultDatasource.Datasets.Create(datasetVectorInfo) as DatasetVector;
        // 结果数据集和擦除数据集坐标系一致
        resultDataset.PrjCoordSys = sourceDataset.PrjCoordSys;
        if (resultDataset == null)
        {
            MessageBox.Show("创建结果数据集失败!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            return;
        }

        // 9. 显示确认对话框
        StringBuilder confirmMessage = new StringBuilder();
        confirmMessage.AppendLine("将要执行擦除操作:");
        confirmMessage.AppendLine($"  被擦除数据集: {sourceDataset.Name} ({sourceDataset.RecordCount} 条记录)");
        confirmMessage.AppendLine($"  擦除数据集: {eraseDataset.Name} ({eraseDataset.RecordCount} 条记录)");
        confirmMessage.AppendLine();
        confirmMessage.AppendLine($"结果数据集: {resultDatasetName}");
        confirmMessage.AppendLine();
        confirmMessage.AppendLine("擦除操作说明:将第一个数据集中包含在第二个数据集内的对象裁剪并删除。");
        confirmMessage.AppendLine();
        confirmMessage.AppendLine("是否继续执行擦除操作?");

        DialogResult confirmResult = MessageBox.Show(
            confirmMessage.ToString(),
            "确认面数据集擦除",
            MessageBoxButtons.YesNo,
            MessageBoxIcon.Question);

        if (confirmResult != DialogResult.Yes)
        {
            // 取消操作时删除已创建的结果数据集
            resultDatasource.Datasets.Delete(resultDatasetName);
            return;
        }

        // 10. 执行擦除操作(使用图片中的四个参数方法)
        bool eraseSuccess = OverlayAnalyst.Erase(
            sourceDataset,      
            eraseDataset,       
            resultDataset,      
            overlayParameter    
        );

        if (eraseSuccess)
        {
            MessageBox.Show($"面数据集擦除完成!\n" +
                          $"被擦除数据集:{sourceDataset.Name}\n" +
                          $"擦除数据集:{eraseDataset.Name}\n" +
                          $"结果数据集:{resultDatasetName}\n" +
                          $"结果记录数:{resultDataset.RecordCount}",
                          "擦除成功",
                          MessageBoxButtons.OK,
                          MessageBoxIcon.Information);

            // 刷新工作空间树显示新数据集
            D_workspaceControl.WorkspaceTree.Refresh();
        }
        else
        {
            // 擦除失败时删除空的结果数据集
            resultDatasource.Datasets.Delete(resultDatasetName);
            MessageBox.Show("面数据集擦除失败!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show($"面数据集擦除过程中发生错误: {ex.Message}\n\n堆栈跟踪:\n{ex.StackTrace}",
                      "错误",
                      MessageBoxButtons.OK,
                      MessageBoxIcon.Error);
    }
}

private string GenerateUniqueDatasetName(string baseName)
{
    string resultName = baseName;
    int counter = 1;
    while (D_workspace.Datasources[0].Datasets[resultName] != null)
    {
        resultName = $"{baseName}_{counter}";
        counter++;
    }
    return resultName;
}

private string GetDatasetTypeChineseName(DatasetType datasetType)
{
    switch (datasetType)
    {
        case DatasetType.Point: return "点";
        case DatasetType.Line: return "线";
        case DatasetType.Region: return "面";
        default: return datasetType.ToString();
    }
}

五、运行结果


总结

以上就是有关于 SuperMap iObjects 11i .NET 叠加分析之擦除相关操作的一些过程记录,我们下篇博文再见!

相关推荐
学以智用1 小时前
FilterAttribute(ASP.NET Core MVC 过滤器特性)
.net
Jeff-Tsai3 小时前
Day 15:API 契约分层与类型注册表
.net·架构设计·erp·definition-driven
1-1=03 小时前
C# 数据结构和特殊类型
数据结构·c#·.net·.netcore
IT规划师4 小时前
Redis 数据类型全解 - Stream 深度:消费者组、Pending 队列与死信处理(十)
redis·.net
叼烟扛炮13 小时前
[LangChain] 学习笔记(06):突破大模型限制——结构化输出(Structured Output)
windows·笔记·学习·langchain
Thneonl1 天前
桌宠穿透不是一行 SetWindowLong
windows·程序员
Jeff-Tsai1 天前
Day 14:业务对象的扩展点与重写时机
.net·架构设计·erp·definition-driven
IT规划师1 天前
Redis 数据类型全解 - GEO 地理空间:附近的人、外卖、打车——背后原理与精度陷阱(九)
redis·.net
艺杯羹2 天前
Windows原生软件锁设计:从暴力杀进程丢数据到零轮询事件驱动架构
windows·系统架构·开源·开源软件·内存管理·开源协议
追逐时光者2 天前
一款基于 .NET 开源、免费的数据库自治诊断平台
后端·.net