前言:我们项目上最近有个需求,要把shp文件导入到我们的webgis系统中来,展示在前端的网页上。如果是任意的shp想展示在webgis中,我们就使用postgresql提供的ogr2ogr工具,直接将shp转为geojson,数据传给前端就行了。但是现在我们的shp是有固定格式的,我们的数据库中也有对应格式的表,因此问题就转变为了,将shp导入我们的表中。
shp文件导入postgresql使用的是shp2pgsql工具,这个工具的使用方法网上的文章非常多,我们在这里就不过多介绍。我们在这里主要讨论的是,我们的shp文件是国家2000坐标系,采用的是高斯投影,即投影坐标系。而我们要在web页面上使用展示地图的话,必须将其转为 WGS84 Web Mercator投影(3857)或者WGS84(4326),我们系统使用的是后者,因此我们需要将投影坐标系转为地理坐标系。这就复杂了,涉及到七参数的转换。
最初我们是想用proj.4进行转换,然而查看了相关的接口后,觉得太复杂,要传的参数太多,很乱,舍弃了。于是我们转向了用python来实现这一功能。arcgis的toolbox工具中的投影工具不就可以完成这个功能吗?并且工具运行完成了以后,还可以拿到工具对应的python代码。这就方便了,我们直接让C#来调用一下这个python代码不就行了吗?于是,本着talk is cheap,show me the code的原则,我们开始撸起袖子码代码。
思路:首先我们要拿到arcgis中的python代码,然后改造,生成我们的python文件,用C#代码调用python.exe去执行这个文件,拿到结果。我们的目标shp的名字就在源文件的名字的后面加个4326,和源文件存储在同一个地方。
C# Code
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
/// /// 将shp从CGCS2000高斯投影坐标为WGS84地理坐标 /// /// /// [HttpPost] public IActionResult ConvertCoor2WGS84( string sourceShpPath) { //1.shp转featureClass sourceShpPath = @ "D:\test\test.shp" ; sourceShpPath = sourceShpPath.Replace( "\" , "/" ); string goalShpPath = (Path.GetDirectoryName(sourceShpPath) + "\" + Path.GetFileNameWithoutExtension(sourceShpPath) + "4326.shp" ).Replace( "\" , "/" ); string pyCommand = "# encoding=utf8\r\n" + "import sys\r\n" + "import arcpy\r\n" + "reload(sys)\r\n" + "sys.setdefaultencoding('utf8')\r\n" + $ "arcpy.Project_management('{sourceShpPath}', '{goalShpPath}', " GEOGCS[ 'GCS_WGS_1984' ,DATUM[ 'D_WGS_1984' ,SPHEROID[ 'WGS_1984' , 6378137 . 0 , 298 . 257223563 ]],PRIMEM[ 'Greenwich' , 0 . 0 ],UNIT[ 'Degree' , 0 . 0174532925199433 ],METADATA[ 'World' ,- 180 . 0 ,- 90 . 0 , 180 . 0 , 90 . 0 , 0 . 0 , 0 . 0174532925199433 , 0 . 0 , 1262 ]]\ ", 'CGCS2000_WGS84', " PROJCS[ 'CGCS2000_GK_CM_117E' ,GEOGCS[ 'GCS_China_Geodetic_Coordinate_System_2000' ,DATUM[ 'D_China_2000' ,SPHEROID[ 'CGCS2000' , 6378137 . 0 , 298 . 257222101 ]],PRIMEM[ 'Greenwich' , 0 . 0 ],UNIT[ 'Degree' , 0 . 0174532925199433 ]],PROJECTION[ 'Gauss_Kruger' ],PARAMETER[ 'False_Easting' , 500000 . 0 ],PARAMETER[ 'False_Northing' , 0 . 0 ],PARAMETER[ 'Central_Meridian' , 117 . 0 ],PARAMETER[ 'Scale_Factor' , 1 . 0 ],PARAMETER[ 'Latitude_Of_Origin' , 0 . 0 ],UNIT[ 'Meter' , 1 . 0 ]]\ ")" ; string res2000_84res=GeoConvertMethods.RunPy(pyCommand); return Ok(); } /// /// 执行python /// /// /// public static string RunPy( string pyCommand) { string res = "" ; using (Process p = new Process()) { //.NET Core不支持gbk和gb2312,这里需要处理一下 Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); Console.InputEncoding = Encoding.UTF8; //创建py文件 string pyPath = "Upload\\PyFiles\" + Guid.NewGuid() + ".py" ; flag = Save(pyPath, pyCommand); if (!flag) throw new Exception( "创建python文件失败!" ); p.StartInfo.Arguments = pyPath; p.StartInfo.FileName = GetPythonPath(); if (p.StartInfo.FileName== "" ) throw new Exception( "未找到python.exe!" ); p.StartInfo.UseShellExecute = false ; //是否使用操作系统shell启动 p.StartInfo.RedirectStandardInput = true ; //接受来自调用程序的输入信息 p.StartInfo.RedirectStandardOutput = true ; //由调用程序获取输出信息 p.StartInfo.RedirectStandardError = true ; //重定向标准错误输出 p.StartInfo.CreateNoWindow = true ; //不显示程序窗口 p.Start(); //启动程序 p.WaitForExit(); //等待程序执行完退出进程 //获取cmd窗口的输出信息 string s = p.StandardOutput.ReadToEnd(); //获取错误信息 string error = p.StandardError.ReadToEnd(); byte [] bytes = Encoding.GetEncoding( "GB2312" ).GetBytes(s); res = Encoding.UTF8.GetString(bytes); p.Close(); } return res; } /// /// 获取python所在路径 /// /// public static string GetPythonPath() { string path = "" ; string [] directories = Directory.GetDirectories( "C:" ); foreach (var item in directories) { if (item.Contains( "Python" )) { string [] files=Directory.GetFiles(item, "*.exe" , SearchOption.AllDirectories); foreach (var file in files) { if (file.EndsWith( "python.exe" )) { return file; } } } } return path; } /// /// 创建文件 /// /// 文件路径 /// 文件内容 public static bool Save( string path, string str) { string s = path.Substring( 0 , path.LastIndexOf( '\\' )); Directory.CreateDirectory(s); //如果文件夹不存在就创建它 FileStream fs = new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite); byte [] data = System.Text.Encoding.Default.GetBytes(str); //开始写入 fs.Write(data, 0 , data.Length); //清空缓冲区、关闭流 fs.Flush(); fs.Close(); return true ; } |
结果1:我们生成的python代码
Python Code
1
2 3 4 5 6 7 |
# encoding=utf8
import sys import arcpy reload (sys) sys.setdefaultencoding( 'utf8' ) arcpy.Project_management( 'D:/test/test.shp' , 'D:/test/test4326.shp' , "GEOGCS['GCS_WGS_1984',DATUM['D_WGS_1984',SPHEROID['WGS_1984',6378137.0,298.257223563]],PRIMEM['Greenwich',0.0],UNIT['Degree',0.0174532925199433],METADATA['World',-180.0,-90.0,180.0,90.0,0.0,0.0174532925199433,0.0,1262]]" , 'CGCS2000_WGS84' , "PROJCS['CGCS2000_GK_CM_117E',GEOGCS['GCS_China_Geodetic_Coordinate_System_2000',DATUM['D_China_2000',SPHEROID['CGCS2000',6378137.0,298.257222101]],PRIMEM['Greenwich',0.0],UNIT['Degree',0.0174532925199433]],PROJECTION['Gauss_Kruger'],PARAMETER['False_Easting',500000.0],PARAMETER['False_Northing',0.0],PARAMETER['Central_Meridian',117.0],PARAMETER['Scale_Factor',1.0],PARAMETER['Latitude_Of_Origin',0.0],UNIT['Meter',1.0]]" ) |
结果2:我们转换好的python文件
结语:最近落下了好几篇博文没发,今天刚好记录下吧。本次的教程就分享到这里,下次再会。。。。