• 【ArcGIS Pro二次开发】(65):进出平衡SHP转TXT、TXT转SHP


    最近一个小伙伴提了这么一个需求,需要把TXT和SHP进行互转。

    这种TXT文件其实遇到了好几个版本,都有一点小差异。之前已经做过一个TXT转SHP的工具,但好像不适用。于是针对这个版本,做了互转的2个工具。


    【SHP转TXT】

    一、要实现的功能

     

    如上图所示,在【数据处理】组—【TXT相关】面板下,点击【进出平衡@SHP转TXT】工具。

    在弹出的工具框中,分别输入参数:

    1、输入SHP文件所在的文件夹

    2、输入TXT文件所在的文件夹。

    3、这里不用填写,会自动列出【1】中所有的shp要素,不想转换的可以点复选框取消。

    4、选择地块名称和地块用途,对应的字段值会写入TXT文件中。

    生成结果如下:


    二、实现流程

    核心代码直接贴上,注释已经写得比较清楚了。

    需要注意的是,这里获取要素的点集信息,我采取了通过要素的JSON文本来截取的做法,原因是不知道怎么用API来获取,所以用了这么个取巧的方法,以后要是学会了再改吧。这也是无奈之举,要学的东西还很多。

    1. foreach (string fullPath in list_shpPath)
    2. {
    3. // 初始化写入txt的内容
    4. string txt_all = "[地块坐标]" + "\r";
    5. string shp_name = fullPath[(fullPath.LastIndexOf(@"\") + 1)..]; // 获取要素名
    6. string shp_path = fullPath[..(fullPath.LastIndexOf(@"\"))]; // 获取shp名
    7. // 打开shp
    8. FileSystemConnectionPath fileConnection = new FileSystemConnectionPath(new Uri(shp_path), FileSystemDatastoreType.Shapefile);
    9. using FileSystemDatastore shapefile = new FileSystemDatastore(fileConnection);
    10. // 获取FeatureClass
    11. FeatureClass featureClass = shapefile.OpenDataset(shp_name);
    12. using (RowCursor rowCursor = featureClass.Search())
    13. {
    14. int featureIndex = 1;
    15. while (rowCursor.MoveNext())
    16. {
    17. using (Feature feature = rowCursor.Current as Feature)
    18. {
    19. // 获取地块名称,地块性质
    20. Row row = feature as Row;
    21. string ft_name = "";
    22. string ft_type = "";
    23. var areaName = row[field_mc];
    24. var areaType = row[field_yt];
    25. if (areaName != null) { ft_name = areaName.ToString(); }
    26. if (areaType != null) { ft_type = areaType.ToString(); }
    27. // 获取面要素的JSON文字
    28. Geometry polygon = feature.GetShape();
    29. string js = polygon.ToJson().ToString();
    30. // 解析JSON文字
    31. // 取坐标点文字
    32. string cod = js[(js.IndexOf("[[[") + 3)..js.IndexOf("]]]")];
    33. // 坐标点列表
    34. List<string> list_xy = cod.Split("]]").ToList();
    35. for (int i = 0; i < list_xy.Count; i++)
    36. {
    37. // 坐标行
    38. List<string> xy_detils = list_xy[i].Replace(",[[", "").Split("],[").ToList();
    39. // 加一行title
    40. int count = xy_detils.Count; // 点的个数
    41. string title = $"{count},{ft_name},面,{ft_type},@ " + "\r";
    42. txt_all += title;
    43. for (int j = 0; j < xy_detils.Count; j++)
    44. {
    45. // 点序号
    46. int index = j + 1;
    47. if (index == xy_detils.Count) { index = 1; }
    48. // XY坐标点
    49. string x = Math.Round(double.Parse(xy_detils[j].Split(",")[0]), 4).ToString();
    50. string y = Math.Round(double.Parse(xy_detils[j].Split(",")[1]), 4).ToString();
    51. // 加入文本
    52. txt_all += $"J{index},{featureIndex},{x},{y}\r";
    53. }
    54. }
    55. }
    56. featureIndex++;
    57. }
    58. }
    59. // 写入txt文件
    60. string txtPath = @$"{folder_txt}\{shp_name.Replace(".shp", "")}.txt";
    61. if (File.Exists(txtPath))
    62. {
    63. File.Delete(txtPath);
    64. }
    65. File.WriteAllText(txtPath, txt_all);
    66. }

    【TXT转SHP】

    一、要实现的功能

     

    如上图所示,在【数据处理】组—【TXT相关】面板下,点击【进出平衡@TXT转SHP】工具。

    在弹出的工具框中,分别输入参数:

    1、输入TXT文件所在的文件夹。

    2、输入SHP文件所在的文件夹。

    3、选择正确的坐标系。

    4、这里不用填写,会自动列出【1】中所有的TXT文件,不想转换的可以点复选框取消。

    生成结果如下:


    二、实现流程

    TXT转SHP之前已经已经写过一篇文章,可以参看:

    【ArcGIS Pro二次开发】(41):勘测定界txt文件转数据库(批量)icon-default.png?t=N7T8https://blog.csdn.net/xcc34452366/article/details/131309938不过文章中用的TXT文件和今天这个有些不同,代码也就不一样,但思路是一致的。

    这里只放核心代码,代码中用到一些自定义方法和之前是一样的引用,就不再一一放上:

    1. foreach (string txtPath in list_txtPath)
    2. {
    3. string shp_name = txtPath[(txtPath.LastIndexOf(@"\") + 1)..].Replace(".txt", ""); // 获取要素名
    4. pw.AddProcessMessage(@$"创建要素:{shp_name}", 10, time_base, Brushes.Black);
    5. // 创建一个空要素
    6. Arcpy.CreateFeatureclass(shpPath, shp_name, "POLYGON", spatial_reference);
    7. // 新建字段
    8. Arcpy.AddField(@$"{shpPath}\{shp_name}.shp", "地块名称", "TEXT");
    9. Arcpy.AddField(@$"{shpPath}\{shp_name}.shp", "地块性质", "TEXT");
    10. // 打开shp
    11. FileSystemConnectionPath fileConnection = new FileSystemConnectionPath(new Uri(shpPath), FileSystemDatastoreType.Shapefile);
    12. using FileSystemDatastore shapefile = new FileSystemDatastore(fileConnection);
    13. // 获取FeatureClass
    14. FeatureClass featureClass = shapefile.OpenDataset(shp_name);
    15. // 预设文本内容
    16. string text = "";
    17. // 获取txt文件的编码方式
    18. Encoding encoding = ToolManager.GetEncodingType(txtPath);
    19. // 读取【ANSI和UTF-8】的不同+++++++(ANSI为0,UTF-8为3)
    20. // 我也不知道具体原理,只是找出差异点作个判断,以后再来解决这个问题------
    21. int encoding_index = int.Parse(encoding.Preamble.ToString().Substring(encoding.Preamble.ToString().Length - 2, 1));
    22. if (encoding_index == 0) // ANSI编码的情况
    23. {
    24. Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
    25. using (StreamReader sr = new StreamReader(txtPath, Encoding.GetEncoding("GBK"))) { text = sr.ReadToEnd(); }
    26. }
    27. else if (encoding_index == 3) // UTF8编码的情况
    28. {
    29. using (StreamReader sr = new StreamReader(txtPath, Encoding.UTF8)) { text = sr.ReadToEnd(); }
    30. }
    31. // 文本中的【@】符号放前
    32. string updata_text = ChangeSymbol(text);
    33. // 获取要素txt列表的地块标记
    34. List<string> Parts = GetParts(updata_text);
    35. for (int i = 0; i < Parts.Count; i++)
    36. {
    37. // 地块编号、地块性质
    38. string dkmc = "";
    39. string dkxz = "";
    40. // 根据换行符分解坐标点文本
    41. List<string> lines = Parts[i].Split("@").ToList();
    42. // 创建空坐标点集合
    43. var vertices_list = new List>();
    44. for (int j = 1; j < lines.Count; j++)
    45. {
    46. var vertices = new List();
    47. vertices_list.Add(vertices);
    48. }
    49. // 构建坐标点集合
    50. for (int k = 1; k < lines.Count; k++)
    51. {
    52. List<string> list_point = lines[k].Split("\r").ToList();
    53. foreach (var point in list_point)
    54. {
    55. if (!point.Contains(",")) // 跳过无坐标部份的文本
    56. {
    57. continue;
    58. }
    59. else if (!point.StartsWith("J")) // 名称、地块编号、功能文本
    60. {
    61. dkmc = point.Split(",")[1];
    62. dkxz = point.Split(",")[3];
    63. }
    64. else // 点坐标文本
    65. {
    66. double lat = double.Parse(point.Split(",")[2]); // 经度
    67. double lng = double.Parse(point.Split(",")[3]); // 纬度
    68. vertices_list[k - 1].Add(new Coordinate2D(lat, lng)); // 加入坐标点集合
    69. }
    70. }
    71. }
    72. /// 构建面要素
    73. // 创建编辑操作对象
    74. EditOperation editOperation = new EditOperation();
    75. editOperation.Callback(context =>
    76. {
    77. // 获取要素定义
    78. FeatureClassDefinition featureClassDefinition = featureClass.GetDefinition();
    79. // 创建RowBuffer
    80. using RowBuffer rowBuffer = featureClass.CreateRowBuffer();
    81. // 写入字段值
    82. rowBuffer["地块名称"] = dkmc;
    83. rowBuffer["地块性质"] = dkxz;
    84. PolygonBuilderEx pb = new PolygonBuilderEx(vertices_list[0]);
    85. // 如果有空洞,则添加内部Polygon
    86. if (vertices_list.Count > 1)
    87. {
    88. for (int i = 0; i < vertices_list.Count - 1; i++)
    89. {
    90. pb.AddPart(vertices_list[i + 1]);
    91. }
    92. }
    93. // 给新添加的行设置形状
    94. rowBuffer[featureClassDefinition.GetShapeField()] = pb.ToGeometry();
    95. // 在表中创建新行
    96. using Feature feature = featureClass.CreateRow(rowBuffer);
    97. context.Invalidate(feature); // 标记行为无效状态
    98. }, featureClass);
    99. // 执行编辑操作
    100. editOperation.Execute();
    101. }
    102. // 保存编辑
    103. Project.Current.SaveEditsAsync();
    104. }

    三、工具文件分享

    我把工具都集合成工具箱,不再单独放单个工具,可以到这里下载完整工具箱,会不断更新:

    【ArcGIS Pro二次开发】:CC工具箱icon-default.png?t=N7T8https://blog.csdn.net/xcc34452366/article/details/131506345PS:可以直接点击...bin\Debug\net6.0-windows\下的.esriAddinX文件直接安装。

  • 相关阅读:
    工作记录之策略模式
    基于matlab实现的中点放炮各类地震波时距曲线程序
    表单识别(五)——票据识别-论文研读:基于深度学习的票据识别系统设计与实现,卞飞飞(上)
    GAN学习:运行ESTRNN
    CSS3多列(详解网页多列布局应用)
    西方经济学第四章
    MyBatis-Plus--在xml中使用wrapper的方法
    【微信小程序】利用云函数获取小程序码(二维码)并上传到对象存储和获取临时图片url链接
    湖南互联网医院|湖南互联网医院牌照办理流程及材料
    多账户管理最全面的解决方案
  • 原文地址:https://blog.csdn.net/xcc34452366/article/details/132617882