DayDreamInGIS 之 ArcGIS Pro二次开发 锐角检查

news2024/11/26 20:41:13

功能:检查图斑中所有的夹角,如果为锐角,在单独的标记图层中标记。生成的结果放在默认gdb中,以 图层名_锐角检查 的方式命名

大体实现方式:遍历图层中的所有要素(多部件要素分别处理),对每个夹角进行判断。

具体功能与ArcMap中锐角检查工具类似

DayDreamInGIS数据处理工具 V1.1.5_beta 锐角检查工具源码与解析_daydreamingistool-CSDN博客

工具界面:

(使用prowindow,样式确实更和谐)

界面代码:

<controls:ProWindow x:Class="DayDreamInGISTool.CornerCheck.CornerCheckWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:controls="clr-namespace:ArcGIS.Desktop.Framework.Controls;assembly=ArcGIS.Desktop.Framework"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:extensions="clr-namespace:ArcGIS.Desktop.Extensions;assembly=ArcGIS.Desktop.Extensions"
        mc:Ignorable="d"
        Title="锐角检查" Width="500" Height="200" 
        WindowStartupLocation="CenterOwner"
    >
    <controls:ProWindow.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <extensions:DesignOnlyResourceDictionary Source="pack://application:,,,/ArcGIS.Desktop.Framework;component\Themes\Default.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </controls:ProWindow.Resources>
    <Grid Margin="5">
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="90"></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <Label VerticalAlignment="Center" HorizontalAlignment="Right">图层</Label>
            <ComboBox Grid.Column="1" Name="cmbLayer" VerticalAlignment="Center" Height="27"></ComboBox>
        </Grid>
        <Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="90"></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <Label VerticalAlignment="Center" HorizontalAlignment="Right">角度阈值(度)</Label>
            <TextBox Grid.Column="1" Name="txtYuzhi" VerticalAlignment="Center" Height="27" Text="10"></TextBox>
        </Grid>
        <Grid Grid.Row="2">
            <Grid.ColumnDefinitions>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <Button Width="140" Height="35" Name="btnOK" Click="btnOK_Click">确定</Button>
            <Button Width="140" Height="35" Grid.Column="1" Name="btnCancel" Click="btnCancel_Click">取消</Button>
        </Grid>
    </Grid>
</controls:ProWindow>

界面交互代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using ArcGIS.Core.Data;
using ArcGIS.Desktop.Framework.Threading.Tasks;
using ArcGIS.Desktop.Mapping;
using RGeometry=ArcGIS.Core.Geometry;
using GISCommonHelper;
using ArcGIS.Core.Geometry;
using ArcGIS.Desktop.Core;
using ArcGIS.Core.Data.DDL;
using ArcGIS.Desktop.Editing;
using ArcGIS.Core.Data.Exceptions;
using ArcGIS.Core.Internal.CIM;

namespace DayDreamInGISTool.CornerCheck
{
    /// <summary>
    /// Interaction logic for CornerCheckWindow.xaml
    /// </summary>
    public partial class CornerCheckWindow : ArcGIS.Desktop.Framework.Controls.ProWindow
    {
        private FeatureLayer player;

        private double yuzhi;

        public CornerCheckWindow()
        {
            InitializeComponent();
            try
            {
                var map = MapView.Active.Map;
                cmbLayer.setLyrlist<FeatureLayer>(map, (o, e) =>
                {
                    if (cmbLayer.SelectedIndex != -1)
                    {
                        Player = this.cmbLayer.SelectedValue as FeatureLayer;
                    }
                });
            }
            catch (Exception)
            {

                
            }
            
        }

        public FeatureLayer Player { get => player; set => player = value; }
        public double Yuzhi { get => yuzhi; set => yuzhi = value; }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = false;
        }

        private void btnOK_Click(object sender, RoutedEventArgs e)
        {
            if (this.cmbLayer.SelectedIndex == -1)
            {
                MessageBox.Show("请设置图层");
                return;
            }

            if(double.TryParse(txtYuzhi.Text,out yuzhi))
            {

            }
            else
            {
                MessageBox.Show("阈值必须为数字");
                return;
            }

            this.DialogResult = true;
        }
    }
}

核心逻辑代码,放在ProWindow的showButton中。

using ArcGIS.Core.CIM;
using ArcGIS.Core.Data;
using ArcGIS.Core.Data.DDL;
using ArcGIS.Core.Data.Exceptions;
using ArcGIS.Core.Geometry;
using ArcGIS.Desktop.Catalog;
using ArcGIS.Desktop.Core;
using ArcGIS.Desktop.Editing;
using ArcGIS.Desktop.Extensions;
using ArcGIS.Desktop.Framework;
using ArcGIS.Desktop.Framework.Contracts;
using ArcGIS.Desktop.Framework.Dialogs;
using ArcGIS.Desktop.Framework.Threading.Tasks;
using ArcGIS.Desktop.Layouts;
using ArcGIS.Desktop.Mapping;
using GISCommonHelper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;

namespace DayDreamInGISTool.CornerCheck
{
    internal class ShowCornerCheckWindow : Button
    {

        private CornerCheckWindow _cornercheckwindow = null;

        private FeatureClass resultFtCls = null;
        string orignoidfdnm = "Orign_OId";  //源oid
        string corneranglefdnm = "CornerAngle";  //夹角
        string targetanglefdnm = "Angle";  //指向角
        string summaryfdnm = "Summary";  //其他说明

        private FeatureLayer pftlyr;
        private double yuzhi;

        ProgressDialog progDlg = null;
        CancelableProgressorSource progSrc = null;

        protected override void OnClick()
        {
            //already open?
            if (_cornercheckwindow != null)
                return;
            _cornercheckwindow = new CornerCheckWindow();
            _cornercheckwindow.Owner = FrameworkApplication.Current.MainWindow;
            //_cornercheckwindow.Closed += (o, e) => { _cornercheckwindow = null; };
            //_cornercheckwindow.Show();
            //uncomment for modal
            try
            {
                progDlg = new ProgressDialog($"锐角检查中...", "取消", 100, true);

                bool? res = _cornercheckwindow.ShowDialog();
                if (res.Value)
                {
                    yuzhi = _cornercheckwindow.Yuzhi;
                    pftlyr = _cornercheckwindow.Player;
                    //{pftlyr.GetDefinition().Name} 
                    progDlg.Show();
                    
                    progSrc = new CancelableProgressorSource(progDlg);
                    execute();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("发生未知异常_"+ex.Message);
                
            }
            finally
            {
                if (progDlg != null)
                {
                    progDlg.Hide();
                    progDlg.Dispose();
                }
                _cornercheckwindow = null;
            }
        }

        private void execute()
        {
            //暂时不做进度条
            QueuedTask.Run(() =>
            {
                long ftcount=pftlyr.GetFeatureClass().GetCount();
                progSrc.Progressor.Max = (uint)ftcount;

                resultFtCls = createResultFtCls();

                FeatureClass ftcls = pftlyr.GetFeatureClass();
                using (RowCursor cursor = ftcls.Search())
                {
                    EditOperation editOperation = new EditOperation();

                    while (cursor.MoveNext())
                    {
                        using (Feature feature = cursor.Current as Feature)
                        {
                            long oid = feature.GetObjectID();
                            Geometry geo = feature.GetShape();
                            if (geo.GeometryType == ArcGIS.Core.Geometry.GeometryType.Polygon)
                            {
                                var polygon = geo as Polygon;
                                check(polygon, oid, editOperation);
                            }
                            progSrc.Progressor.Value++;
                            progSrc.Message = $"要素:{oid} 检查完成";
                        }
                    }
                    string message = "";

                    try
                    {
                        // 执行编辑操作
                        bool creationResult = editOperation.Execute();
                        
                        // 如果操作失败,存储错误消息
                        if (!creationResult) { message = editOperation.ErrorMessage; }
                    }
                    catch (GeodatabaseException exObj)
                    {
                        // 如果出现地理数据库异常,存储异常消息
                        message = exObj.Message;
                        throw;
                    }
                }

            },progSrc.Progressor);
        }

        private void check(Polygon polygon, long oid, EditOperation editOperation)
        {
            //多部件要素,每个部分单独处理
            var list = GeometryEngine.Instance.MultipartToSinglePart(polygon);
            foreach (var item in list)
            {
                CornerAngleCheck(item as Polygon, yuzhi, oid, editOperation);
            }
        }

        private void CornerAngleCheck(Polygon pPolygon, double tolerance, long oid, EditOperation editOperation)
        {
            var pntCol = pPolygon.Points;
            for (int i = 0; i < pntCol.Count - 1; i++)  //循环,多边形的点首尾相接,最后一个点不用核查
            {
                MapPoint currentpnt = pntCol[i];
                MapPoint prePoint = null;
                MapPoint nextPoint = null;
                if (i == 0)
                {
                    prePoint = pntCol[pntCol.Count - 2];  //获取倒数第二个点,即为肉眼意义上的前一个点
                }
                else
                {
                    prePoint = pntCol[i - 1];
                }

                if (i == pntCol.Count - 2)
                {
                    nextPoint = pntCol[0];
                }
                else
                {
                    nextPoint = pntCol[i + 1];
                }

                double ca = calcCornerAngle(currentpnt, prePoint, nextPoint);
                double aindegredd = GISCommonHelper.MathHelper.Radian2Degree(ca);
                double d1 = GISCommonHelper.GeometryHelper.getDistance(currentpnt, prePoint);
                double d2 = GISCommonHelper.GeometryHelper.getDistance(currentpnt, nextPoint);

                //定位点距离大致算
                double dis = (d1 + d2) / 5.0;  //平均边长的十分之一处
                //生成定位点
                MapPoint pc = GeometryEngine.Instance.ConstructPointFromAngleDistance(currentpnt, GISCommonHelper.GeometryHelper.getAngle(currentpnt, prePoint) + ca / 2.0, dis);

                if (aindegredd <= tolerance)
                {
                    editOperation.Callback(context => {
                        using RowBuffer rowBuffer = resultFtCls.CreateRowBuffer();
                        rowBuffer[orignoidfdnm] = oid;
                        rowBuffer[corneranglefdnm] = aindegredd;
                        //rowBuffer[targetanglefdnm] = 0;  //指向角度
                        //构建线
                        Polyline pln = GISCommonHelper.GeometryHelper.getPolyline(pc, currentpnt, MapView.Active.Map.SpatialReference);
                        rowBuffer[resultFtCls.GetDefinition().GetShapeField()] = pln;

                        using Feature feature = resultFtCls.CreateRow(rowBuffer);
                        context.Invalidate(feature);
                    }, resultFtCls);
                }
                else
                {
                    //非锐角
                }
            }
        }

        /// <summary>
        /// 计算夹角 返回结果弧度
        /// </summary>
        /// <param name="cPnt">顶点</param>
        /// <param name="p1">起点</param>
        /// <param name="p2">结点</param>
        /// <returns>弧度</returns>
        public double calcCornerAngle(MapPoint cPnt, MapPoint p1, MapPoint p2)
        {
            double a1 = GISCommonHelper.GeometryHelper.getAngle(cPnt, p1);
            double a2 = GISCommonHelper.GeometryHelper.getAngle(cPnt, p2);
            double a = a2 - a1;
            if (a < 0)
            {
                a = a + Math.PI * 2;
            }

            return a;
        }

        string ruijiaojcfcname = "锐角检查";

        /// <summary>
        /// 创建结果要素类 默认
        /// </summary>
        /// <returns></returns>
        private FeatureClass createResultFtCls()
        {
            ruijiaojcfcname = $"{pftlyr.GetDefinition().Name}_锐角检查";
            var sr = pftlyr.GetFeatureClass().GetDefinition().GetSpatialReference();
            //在当前数据库中创建
            var DefaultGDB = Project.Current.DefaultGeodatabasePath;
            using (Geodatabase gdb = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(DefaultGDB))))
            {
                bool isexist = gdb.FeatureClassExists(ruijiaojcfcname);
                //如果存在,则先删除
                if (isexist)
                {
                    var dr=MessageBox.Show("工作空间已经存在锐角检查数据集,是否删除?", "提示", System.Windows.MessageBoxButton.YesNo);

                    if(dr== System.Windows.MessageBoxResult.Yes)
                    {
                        //删除已有
                        var featureclass = gdb.OpenDataset<FeatureClass>(ruijiaojcfcname);
                        FeatureClassDescription fdc = new FeatureClassDescription(featureclass.GetDefinition());
                        SchemaBuilder sb3 = new SchemaBuilder(gdb);
                        sb3.Delete(fdc);
                    }
                    else
                    {
                        ruijiaojcfcname = $"锐角检查_{DateTime.Now.GetTimeStamp()}";
                    }
                    progSrc.Progressor.Message = $"创建结果数据集 {ruijiaojcfcname} 完成";
                }

                var hasZ = false;
                var hasM = false;
                var shapeDescription = new ShapeDescription(GeometryType.Polyline, sr)
                {
                    HasM = hasM,
                    HasZ = hasZ
                };
                var f0 = new ArcGIS.Core.Data.DDL.FieldDescription("OBJECTID", FieldType.OID);
                var f1 = new ArcGIS.Core.Data.DDL.FieldDescription(orignoidfdnm, FieldType.Integer);
                var f2 = new ArcGIS.Core.Data.DDL.FieldDescription(corneranglefdnm, FieldType.Double);
                var f3 = new ArcGIS.Core.Data.DDL.FieldDescription(targetanglefdnm, FieldType.Double);
                var f4 = new ArcGIS.Core.Data.DDL.FieldDescription(summaryfdnm, FieldType.String);
                f4.Length = 80;
                var fieldDescriptions = new List<ArcGIS.Core.Data.DDL.FieldDescription>()
                {
                    f0,f1,f2,f3,f4
                };

                //创建FeatureClassDescription
                var fcDescription = new FeatureClassDescription(ruijiaojcfcname, fieldDescriptions, shapeDescription);
                //创建SchemaBuilder
                SchemaBuilder sb = new SchemaBuilder(gdb);
                sb.Create(fcDescription);
                bool success = sb.Build();
                var featureclass2 = gdb.OpenDataset<FeatureClass>(ruijiaojcfcname); ;  //再次打开

                //添加图层
                Uri uu = featureclass2.GetPath();
                var layer = LayerFactory.Instance.CreateLayer(uu, MapView.Active.Map, 0, ruijiaojcfcname);

                return featureclass2;
            }

        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1511544.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis核心数据结构之压缩列表(二)

压缩列表 压缩列表节点的构成 encoding 节点的encoding属性记录了节点的content属性所保存数据的类型及长度: 1.一字节、两字节或者五字节长&#xff0c;值得最高位为00、01或者10的是字节数组编码:这种编码表示节点的content属性保存着字节数组&#xff0c;数组的长度由编…

MachineSink - 优化阅读笔记

注&#xff1a;该优化与全局子表达式消除刚好是相反的过程&#xff0c;具体该不该做这个优化得看代价模型算出来的结果(有采样文件指导算得会更准确) 该优化过程将指令移动到后继基本块中&#xff0c;以便它们不会在不需要其结果的路径上执行。 该优化过程并非旨在替代或完全…

Huggingface中Transformer模型使用

一、Huggingface介绍 1、Huggingface定位 NLP自从Transformer模型出现后&#xff0c;处理方式有大统一的趋势&#xff0c;首先回答几个基础问题&#xff1a; 1、自然语言处理究竟要做一件什么事呢&#xff1f;自然语言处理最终解决的是分类问题&#xff0c;但是它不仅仅输出…

基于单片机的智能小车泊车系统设计

摘 要:随着信息技术的进步,汽车逐渐朝着安全、智能方向发展,智能泊车系统的出现不仅能帮助人们更加快速、安全地完成泊车操作,而且适用于狭小空间的泊车操作,降低驾驶员泊车负担,减轻泊车交通事故发生率。文章基于单片机设计自动泊车系统,以单片机为核心来实现信息收集及…

洛谷P6022快乐水

他来到了一家商店门前。 这家商店为了吸引顾客来买快乐水&#xff0c;搞了这么一个活动&#xff1a;「55 个瓶盖换一瓶快乐水」。于是&#xff0c;人们纷纷来他的店里买快乐水。 买完快乐水&#xff0c;他想到了一个问题&#xff1a; 如果一瓶快乐水有m 个附属品&#xff0c…

Java线程的6种状态

线程在生命周期中并不是固定处于某一个状态而是随着代码的执行在不同状态之间切换。 NEW&#xff1a;初始状态&#xff0c;线程被创建出来但没有被调用start()RUNNABLE&#xff1a;运行状态&#xff0c;线程被调用了start()等待运行的状态BLOCKED&#xff1a;阻塞状态&#xf…

uview upicker时间选择器(附Demo)

目录 前言正文 前言 uniapp时间选择器&#xff0c;是upicker&#xff0c;与微信小程序还是有些区别 补充官网的基本知识&#xff1a;uview官网 官网的展示例子如下&#xff1a;&#xff08;但是没Demo&#xff09; 正文 通过上面的展示图&#xff0c;复刻一个类似Demo图&am…

15双体系Java学习之数组的声明和创建

数组的声明 ★小贴士 可以使用int[] a;或者int a[];建议使用第一种风格&#xff0c;因为它将元素类型int[]&#xff08;整型数组&#xff09;与变量名清晰分开了。 在Java中声明数组时不能指定其长度。这种定义是非法的&#xff1a;int a[5]; 注意&#xff1a;上图显示的内存…

学习数据节构和算法的第15天

单链表的实现 链表的基本结构 #pragma once #include<stdio.h> typedf int SLTDataType; typedy struct SListNode {SLTDataType data;struct SListNode*next; }SLTNode;void Slisprint(SLTNode*phead);打印链表 #include<stdio.h> void SListPrint(SLTNode*phe…

【LeetCode】升级打怪之路 Day 18:二叉树题型 —— 树的深度、高度、路经

今日题目&#xff1a; 104. 二叉树的最大深度111. 二叉树的最小深度110. 平衡二叉树257. 二叉树的所有路径112. 路径总和 目录 Problem 1&#xff1a;树的深度LC 104. 二叉树的最大深度 【easy】LC 111. 二叉树的最小深度 【易错】 Problem 2&#xff1a;树的高度LC 110. 平衡二…

嵌入式系统软件及操作系统

0、前言 本专栏为个人备考软考嵌入式系统设计师的复习笔记&#xff0c;未经本人许可&#xff0c;请勿转载&#xff0c;如发现本笔记内容的错误还望各位不吝赐教&#xff08;笔记内容可能有误怕产生错误引导&#xff09;。 考查选择题为多&#xff1a;嵌入式系统软件特点是什么…

解决Klipper下位机ID获取失败问题

使用硬件&#xff1a; 上位机&#xff1a;必趣派&#xff0c;版本CB1_Debian11_Klipper_kernel5.16_20230303 下位机&#xff1a;八爪鱼STM32F407 问题&#xff1a;上位机获取下位机ID失败。 解决&#xff1a;调试过程中&#xff0c;发现上位机和下位机之间没有物理连接&…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:Stepper)

步骤导航器组件&#xff0c;适用于引导用户按照步骤完成任务的导航场景。 说明&#xff1a; 该组件从API Version 8开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 仅能包含子组件StepperItem。 接口 Stepper(value?: { index?…

2021年江苏省职业院校技能大赛高职组 “信息安全管理与评估”赛项任务书

2021年江苏省职业院校技能大赛高职组 “信息安全管理与评估”赛项任务书 一、赛项时间&#xff1a;二、赛项信息三、竞赛内容&#xff1a;第一阶段任务书&#xff08;300分&#xff09;任务1&#xff1a;网络平台搭建&#xff08;60分&#xff09;任务2&#xff1a;网络安全设备…

AI 技术:改变世界的力量

人工智能&#xff08;AI&#xff09;是当今科技领域最热门的话题之一&#xff0c;它已经成为推动社会进步和经济发展的重要力量。AI 技术的应用范围非常广泛&#xff0c;从智能手机、自动驾驶汽车到医疗保健、金融服务等领域&#xff0c;都可以看到 AI 的身影。 那么&#xff0…

GIS学习笔记(四):GIS数据可视化综合(矢量数据)

矢量数据 arcgis的主要可视化工具&#xff1a;属性 符号系统 符号系统 按类别 这里不会涉及到数字的大小因素&#xff0c;只是按照字符的分类去做可视化 “唯一值”的含义 “建筑年代”字段共有10个年份&#xff0c;一个年份也许有多个数据( eg.1990年的建筑有20个)&…

JavaWeb——013SpringBootWeb综合案例(事务管理、AOP)

事务&AOP 目录 事务&AOP1. 事务管理1.1 事务回顾1.2 Spring事务管理1.2.1 案例1.2.2 原因分析1.2.3 Transactional注解 1.3 事务进阶1.3.1 rollbackFor1.3.3 propagation1.3.3.1 介绍1.3.3.2 案例 2. AOP基础2.1 AOP概述2.2 AOP快速入门2.3 AOP核心概念 3. AOP进阶3.1 …

传统SessionID,Cookie方式与SringSecurity+JWT验证方式

在Spring Boot框架中&#xff0c;可以使用Spring Session来处理会话管理。Spring Session允许开发者在不同的存储后端&#xff08;如Redis、数据库等&#xff09;之间共享和管理会话状态。通过Spring Session&#xff0c;开发者可以轻松地实现会话管理、会话失效以及跨多个节点…

使用函数返回值的循环、使用带返回值的函数

本文参考C Primer Plus进行C语言学习 文章目录 使用函数返回值的循环使用带返回值的函数 一.使用函数返回值的循环 #include<stdio.h> double power(double n,int p); int main() {double x,xpow;int exp;printf("Enter a number and the posotive integer power&…