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 }; } } }