From 2f63c86891f413ff08fa60ad44bb082ddac79fb1 Mon Sep 17 00:00:00 2001
From: HuangXingZhi <3134723314@qq.com>
Date: Wed, 30 Jul 2025 23:50:30 +0800
Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=82=B9=E7=BA=BF=E9=9D=A2?=
=?UTF-8?q?=E7=AE=80=E5=8D=95=E7=AC=A6=E5=8F=B7=E7=B3=BB=E7=BB=9F=E8=AE=BE?=
=?UTF-8?q?=E7=BD=AE=E7=9A=84MCP?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
client/tool/ArcGisProSymbology.cs | 250 ++++++++++++++++++++++++++++++
host/McpServerList.cs | 31 ++--
ui/dockpane/TestDockpane.xaml | 6 +-
ui/dockpane/TestDockpane.xaml.cs | 7 +
4 files changed, 280 insertions(+), 14 deletions(-)
create mode 100644 client/tool/ArcGisProSymbology.cs
diff --git a/client/tool/ArcGisProSymbology.cs b/client/tool/ArcGisProSymbology.cs
new file mode 100644
index 0000000..94e24a3
--- /dev/null
+++ b/client/tool/ArcGisProSymbology.cs
@@ -0,0 +1,250 @@
+using ArcGIS.Core.CIM;
+using ArcGIS.Core.Data;
+using ArcGIS.Desktop.Core;
+using ArcGIS.Desktop.Framework.Threading.Tasks;
+using ArcGIS.Desktop.Mapping;
+using LinkToolAddin.server;
+using ModelContextProtocol.Server;
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace LinkToolAddin.client.tool
+{
+ public class ArcGisProSymbology
+ {
+ ///
+ /// 将 System.Drawing.Color 转换为 CIMColor(支持 RGB 和透明度)
+ ///
+ private static CIMColor ColorToCIMColor(int r, int g, int b, double alpha =0)
+ {
+ return ColorFactory.Instance.CreateRGBColor(r, g, b);
+ }
+
+ ///
+ /// 构造点符号引用(封装 SymbolFactory 调用)
+ ///
+ private static CIMSymbolReference GetPointSymbolRef(int r, int g, int b, float size)
+ {
+ CIMColor color = ColorToCIMColor(r, g, b);
+ CIMPointSymbol symbol = SymbolFactory.Instance.ConstructPointSymbol(color, size);
+ return symbol.MakeSymbolReference();
+ }
+
+ ///
+ /// 构造线符号引用
+ ///
+ private static CIMSymbolReference GetLineSymbolRef(int r, int g, int b, float width)
+ {
+ CIMColor color = ColorToCIMColor(r, g, b);
+
+ // 手动创建线符号图层
+ CIMSolidStroke stroke = new CIMSolidStroke
+ {
+ Color = color,
+ Width = width,
+ CapStyle = LineCapStyle.Round, // 端点样式:圆头
+ JoinStyle = LineJoinStyle.Round, // 连接处样式:圆角
+ Enable = true // 必须启用!
+ };
+
+ // 创建线符号并设置图层
+ CIMLineSymbol symbol = new CIMLineSymbol
+ {
+ SymbolLayers = new CIMSymbolLayer[] { stroke }
+ };
+
+ return symbol.MakeSymbolReference();
+ }
+
+ ///
+ /// 构造面符号引用(填充 + 轮廓)
+ ///
+ private static CIMSymbolReference GetPolygonSymbolRef(
+ int fillR, int fillG, int fillB,
+ int outlineR, int outlineG, int outlineB,
+ float outlineWidth)
+ {
+ // 填充图层
+ CIMSolidFill fillLayer = new CIMSolidFill
+ {
+ Color = ColorToCIMColor(fillR, fillG, fillB)
+ };
+
+ // 轮廓图层
+ CIMSolidStroke outlineLayer = new CIMSolidStroke
+ {
+ Color = ColorToCIMColor(outlineR, outlineG, outlineB),
+ Width = outlineWidth,
+ JoinStyle = LineJoinStyle.Round//圆角
+ };
+
+ CIMPolygonSymbol polygonSymbol = new CIMPolygonSymbol
+ {
+ SymbolLayers = new CIMSymbolLayer[] { fillLayer, outlineLayer }
+ };
+
+ return polygonSymbol.MakeSymbolReference();
+ }
+
+ // ==================== 工具方法 ====================
+
+ [McpServerTool, Description("可以通过调用 ArcGIS Pro 的符号系统,设置点图层的符号颜色和大小。" +
+ "此工具将分析要素数据特征与当前地图布局,智能生成符合视觉美学原则的点状符号。" +
+ "传入参数必须包括红(R)、绿(G)、蓝(B)三种颜色分量(0-255)、符号尺寸(单位:点)以及目标图层名称。" +
+ "系统在设置过程中综合考虑颜色对比度、符号可辨性、形状匹配度及整体地图协调性等因素," +
+ "动态调整或创建新的符号配置,避免视觉拥挤或信息弱化问题。" +
+ "最终输出一个优化后的点符号系统配置,可直接应用于指定的点要素图层,显著提升地图的视觉层次感与信息传达效率。" +
+ "适用于城市位置、监测站点、兴趣点(POI)等点状地理要素的可视化表达场景。")]
+ public static async Task SetPointColor(string r, string g, string b, string layerName, string size)
+ {
+ return await SetSymbolAsync(layerName, esriGeometryType.esriGeometryPoint, () =>
+ {
+ return GetPointSymbolRef(int.Parse(r), int.Parse(g), int.Parse(b), float.Parse(size));
+ }, "点符号");
+ }
+
+ [McpServerTool, Description("可以通过调用 ArcGIS Pro 的符号系统,设置线图层的符号颜色和宽度。" +
+ "此工具将分析要素数据和当前地图布局,智能选择或生成符合视觉美学原则的线符号。" +
+ "传入参数必须包括 RGB 三种颜色分量、线符号宽度以及目标图层名称。" +
+ "系统会综合考虑颜色对比度、线型协调性、地图整体可读性等因素,动态调整或创建新的符号配置。" +
+ "最终输出一个优化后的线符号系统,可直接应用于指定的线要素图层,显著提升地图的视觉表达效果与信息传达清晰度。" +
+ "适用于道路、河流、边界等线状要素的符号化场景。")]
+ public static async Task SetLineColor(string r, string g, string b, string layerName, string width)
+ {
+
+ return await SetSymbolAsync(layerName, esriGeometryType.esriGeometryPolyline, () =>
+ {
+ return GetLineSymbolRef(int.Parse(r), int.Parse(g), int.Parse(b), float.Parse(width));
+ }, "线符号");
+ }
+
+ [McpServerTool, Description("设置面图层的填充颜色、轮廓颜色和轮廓宽度。" +
+ "此工具将调用 ArcGIS Pro 符号系统,智能生成符合视觉美学的面符号。" +
+ "传入参数包括:填充颜色的RGB值、轮廓颜色的RGB值、轮廓宽度、图层名称。" +
+ "最终将优化后的符号应用于指定的面要素图层,提升地图可视化效果。")]
+ public static async Task SetPolygonColor(string fillR, string fillG, string fillB,
+ string outlineR, string outlineG, string outlineB, string outlineWidth, string layerName)
+ {
+ return await SetSymbolAsync(layerName, esriGeometryType.esriGeometryPolygon, () =>
+ {
+ return GetPolygonSymbolRef(int.Parse(fillR), int.Parse(fillG), int.Parse(fillB), int.Parse(outlineR), int.Parse(outlineG), int.Parse(outlineB), float.Parse(outlineWidth));
+ }, "面符号");
+ }
+
+ ///
+ /// 通用符号设置逻辑(封装重复代码)
+ ///
+ private async static Task SetSymbolAsync(
+ string layerName,
+ esriGeometryType expectedType,
+ Func symbolFactory,
+ string symbolTypeName)
+ {
+ try
+ {
+ Map map = MapView.Active?.Map;
+ if (map == null)
+ {
+ return new JsonRpcErrorEntity
+ {
+ Error = new Error
+ {
+ Code = "404",
+ Message = "当前没有激活的地图"
+ }
+ };
+ }
+
+ FeatureLayer featureLayer = map.GetLayersAsFlattenedList()
+ .OfType()
+ .FirstOrDefault(l => l.Name == layerName);
+
+ if (featureLayer == null)
+ {
+ return(new JsonRpcErrorEntity
+ {
+ Error = new Error
+ {
+ Code = "404",
+ Message = $"找不到名为 '{layerName}' 的图层"
+ }
+ });
+ }
+
+ if (featureLayer.ShapeType != expectedType)
+ {
+ return(new JsonRpcErrorEntity
+ {
+ Error = new Error
+ {
+ Code = "400",
+ Message = $"指定图层 '{layerName}' 不是{symbolTypeName}图层"
+ }
+ });
+ }
+
+ CIMRenderer renderer = null;
+
+ await QueuedTask.Run(async () =>
+ {
+ renderer = featureLayer.GetRenderer();
+ });
+ CIMSimpleRenderer simpleRenderer = renderer as CIMSimpleRenderer;
+ if (simpleRenderer == null)
+ {
+ return(new JsonRpcErrorEntity
+ {
+ Error = new Error
+ {
+ Code = "400",
+ Message = $"图层 '{layerName}' 的渲染器不是简单渲染器,无法设置"
+ }
+ });
+ }
+
+ await QueuedTask.Run(async () =>
+ {
+ CIMSymbolReference symbolRef = symbolFactory();
+ simpleRenderer.Symbol = symbolRef;
+ featureLayer.SetRenderer(renderer);
+ });
+
+ return (new JsonRpcSuccessEntity
+ {
+ Result = $"{symbolTypeName}设置成功",
+ Id = GetIdForType(expectedType)
+ });
+ }
+ catch (Exception ex)
+ {
+ // 捕获 QueuedTask 外层异常(如线程中断等)
+ return new JsonRpcErrorEntity
+ {
+ Error = new Error
+ {
+ Code = "500",
+ Message = $"任务执行失败: {ex.Message}"
+ }
+ };
+ }
+ }
+
+ ///
+ /// 根据几何类型返回对应的 ID(用于兼容原逻辑)
+ ///
+ private static int GetIdForType(esriGeometryType type)
+ {
+ return type switch
+ {
+ esriGeometryType.esriGeometryPoint => 1,
+ esriGeometryType.esriGeometryPolyline => 2,
+ esriGeometryType.esriGeometryPolygon => 3,
+ _ => 0
+ };
+ }
+ }
+}
\ No newline at end of file
diff --git a/host/McpServerList.cs b/host/McpServerList.cs
index 0d94479..ea97c4d 100644
--- a/host/McpServerList.cs
+++ b/host/McpServerList.cs
@@ -29,6 +29,13 @@ public class McpServerList
Description = "可以调用arcgis的地理处理工具或执行python代码等",
IsActive = true
});
+ servers.Add("ArcGisProSymbology", new InnerMcpServer
+ {
+ Name = "ArcGisProSymbology",
+ Type = "inner",
+ Description = "可以调用arcgis的符号系统进行简单符号设置",
+ IsActive = true
+ });
servers.Add("KnowledgeBase", new InnerMcpServer
{
Name = "KnowledgeBase",
@@ -37,18 +44,18 @@ public class McpServerList
// "有地理信息的相关案例步骤参考以及Arcgis Pro的工具详细信息",
IsActive = true
});
- servers.Add("filesystem", new StdioMcpServer()
- {
- Name = "filesystem",
- Type = "stdio",
- Command = "npx",
- Args = new List()
- {
- "-y",
- "@modelcontextprotocol/server-filesystem",
- "F:\\secondsemester\\linktool\\test\\LinkTool0607\\LinkTool0607.gdb"
- }
- });
+ //servers.Add("filesystem", new StdioMcpServer()
+ //{
+ // Name = "filesystem",
+ // Type = "stdio",
+ // Command = "npx",
+ // Args = new List()
+ // {
+ // "-y",
+ // "@modelcontextprotocol/server-filesystem",
+ // "F:\\secondsemester\\linktool\\test\\LinkTool0607\\LinkTool0607.gdb"
+ // }
+ //});
// servers.Add("fetch", new StdioMcpServer()
// {
// Name = "fetch",
diff --git a/ui/dockpane/TestDockpane.xaml b/ui/dockpane/TestDockpane.xaml
index 0306e36..a6e64ed 100644
--- a/ui/dockpane/TestDockpane.xaml
+++ b/ui/dockpane/TestDockpane.xaml
@@ -26,7 +26,8 @@
-
+
+
@@ -43,5 +44,6 @@
-
+
+
\ No newline at end of file
diff --git a/ui/dockpane/TestDockpane.xaml.cs b/ui/dockpane/TestDockpane.xaml.cs
index 5985146..873bda2 100644
--- a/ui/dockpane/TestDockpane.xaml.cs
+++ b/ui/dockpane/TestDockpane.xaml.cs
@@ -320,5 +320,12 @@ namespace LinkToolAddin.ui.dockpane
"LandUse_2005_Copy", "30");
log.Info("finish");
}
+
+ private async void TestSymbology_Click(object sender, RoutedEventArgs e)
+ {
+ //await ArcGisProSymbology.SetPointColor(115, 174, 82, "population_XYTableToPoint", 10);
+ //await ArcGisProSymbology.SetLineColor(29,141,213,"testline",50);
+ //await ArcGisProSymbology.SetPolygonColor(149, 2, 8, 255, 153, 0, 30, "county111_popul");
+ }
}
}