C#将shapefile转换为geojson—通过GDAL
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
C#将shapefile转换为geojson—通过GDAL
最近项⽬上,后台需要将数据处理的结果返回geojson数据的格式,⾃⼰写的拼接geojson⽅法始终存在问题。
⾯太复杂,各种内环外环,⾯的相交等,⽆法完美解析,就采⽤这个办法,直接通过gdal,将结果转换为geojson,再返回,⽤别⼈造好的轮⼦,结实耐⽤。
⼀、下载
这是我下载的版本
解压后找到如下⼏个⽂件
⼆、环境搭建
项⽬中引⽤上⾯8个dll中带csharp后缀的四个类库,如下图所⽰:
将上⾯8个⽂件复制到程序输出⽬录debug下。
⽹上有⽂章说将/bin/gdal204.dll⽂件拷贝到debug⽬录下,我试了试不管⽤,程序启动后,抛异常,找不到类库。
于是将⽬录下所有dll都拷贝到debug下,就没有报错了。
三、代码
转换的代码如下所⽰:
public static bool TranslateShapeFile(string shapefilepath,string geojsonfilepath)
{
bool isok = false;
try
{
LogManager.Write("shapefile⽂件路径:" + shapefilepath);
LogManager.Write("geojson⽂件输出路径:" + geojsonfilepath);
GdalConfiguration.ConfigureGdal();
GdalConfiguration.ConfigureOgr();
if (string.IsNullOrWhiteSpace(shapefilepath) || string.IsNullOrWhiteSpace(geojsonfilepath))
{
LogManager.Write("输⼊参数路径不合法");
return false;
}
OSGeo.GDAL.Gdal.AllRegister();
OSGeo.OGR.Ogr.RegisterAll();
// 为了⽀持中⽂路径,请添加下⾯这句代码
OSGeo.GDAL.Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
// 为了使属性表字段⽀持中⽂,请添加下⾯这句
OSGeo.GDAL.Gdal.SetConfigOption("SHAPE_ENCODING", "");
//打开数据
DataSource ds = Ogr.Open(shapefilepath, 0);
if (ds == null)
{
LogManager.Write("打开⽂件失败!");
return false;
}
Driver dv = Ogr.GetDriverByName("GeoJSON");
if (dv == null)
{
LogManager.Write("打开驱动失败!");
return false;
}
dv.CopyDataSource(ds, geojsonfilepath, null);
isok = true;
}
catch(Exception ex)
{
LogManager.Write("shapefile⽂件读取转换失败!");
LogManager.Write(ex);
}
return isok;
}
代码中有如下两句,是初始化代码,⽹上的教程上⼤多都有了。
我这是VS⾥⾯NuGet添加的gdal引⽤,⾃动添加了这个类,后来发现缺失其他类库,就直接下载了类库。
⾃动⽣成两个⽂件,⼀个C#,⼀个VB版。
可新建类,复制过去即可。
GdalConfiguration.ConfigureGdal();
GdalConfiguration.ConfigureOgr();
C#
/******************************************************************************
*
* Name: GdalConfiguration.cs.pp
* Project: GDAL CSharp Interface
* Purpose: A static configuration utility class to enable GDAL/OGR.
* Author: Felix Obermaier
*
******************************************************************************
* Copyright (c) 2012-2018, Felix Obermaier
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*****************************************************************************/
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using Gdal = OSGeo.GDAL.Gdal;
using Ogr = OSGeo.OGR.Ogr;
namespace Utility.ShapeFileToGeoJson
{
public static partial class GdalConfiguration
{
private static volatile bool _configuredOgr;
private static volatile bool _configuredGdal;
private static volatile bool _usable;
[DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool SetDefaultDllDirectories(uint directoryFlags);
// LOAD_LIBRARY_SEARCH_USER_DIRS | LOAD_LIBRARY_SEARCH_SYSTEM32
private const uint DllSearchFlags = 0x00000400 | 0x00000800;
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool AddDllDirectory(string lpPathName);
///<summary>
/// Construction of Gdal/Ogr
///</summary>
static GdalConfiguration()
{
string executingDirectory = null, gdalPath = null, nativePath = null;
try
{
if (!IsWindows)
{
const string notSet = "_Not_set_";
string tmp = Gdal.GetConfigOption("GDAL_DATA", notSet);
_usable = tmp != notSet;
return;
}
string executingAssemblyFile = new Uri(Assembly.GetExecutingAssembly().GetName().CodeBase).LocalPath; executingDirectory = Path.GetDirectoryName(executingAssemblyFile);
if (string.IsNullOrEmpty(executingDirectory))
throw new InvalidOperationException("cannot get executing directory");
// modify search place and order
SetDefaultDllDirectories(DllSearchFlags);
gdalPath = bine(executingDirectory, "gdal");
nativePath = bine(gdalPath, GetPlatform());
if (!Directory.Exists(nativePath))
throw new DirectoryNotFoundException("GDAL native directory not found at '{nativePath}'");
if (!File.Exists(bine(nativePath, "gdal_wrap.dll")))
throw new FileNotFoundException(
"GDAL native wrapper file not found at");
// Add directories
AddDllDirectory(nativePath);
AddDllDirectory(bine(nativePath, "plugins"));
// Set the additional GDAL environment variables.
string gdalData = bine(gdalPath, "data");
Environment.SetEnvironmentVariable("GDAL_DATA", gdalData);
Gdal.SetConfigOption("GDAL_DATA", gdalData);
string driverPath = bine(nativePath, "plugins");
Environment.SetEnvironmentVariable("GDAL_DRIVER_PATH", driverPath);
Gdal.SetConfigOption("GDAL_DRIVER_PATH", driverPath);
Environment.SetEnvironmentVariable("GEOTIFF_CSV", gdalData);
Gdal.SetConfigOption("GEOTIFF_CSV", gdalData);
string projSharePath = bine(gdalPath, "share");
Environment.SetEnvironmentVariable("PROJ_LIB", projSharePath);
Gdal.SetConfigOption("PROJ_LIB", projSharePath);
_usable = true;
}
catch (Exception e)
{
_usable = false;
//Trace.WriteLine(e, "error");
//Trace.WriteLine($"Executing directory: {executingDirectory}", "error");
//Trace.WriteLine($"gdal directory: {gdalPath}", "error");
//Trace.WriteLine($"native directory: {nativePath}", "error");
//throw;
}
}
///<summary>
/// Gets a value indicating if the GDAL package is set up properly.
///</summary>
public static bool Usable
{
get { return _usable; }
}
///<summary>
/// Method to ensure the static constructor is being called.
///</summary>
///<remarks>Be sure to call this function before using Gdal/Ogr/Osr</remarks>
public static void ConfigureOgr()
{
if (_configuredOgr) return;
// Register drivers
Ogr.RegisterAll();
_configuredOgr = true;
PrintDriversOgr();
}
///<summary>
/// Method to ensure the static constructor is being called.
///</summary>
///<remarks>Be sure to call this function before using Gdal/Ogr/Osr</remarks>
public static void ConfigureGdal()
{
if (!_usable) return;
if (_configuredGdal) return;
// Register drivers
Gdal.AllRegister();
_configuredGdal = true;
PrintDriversGdal();
}
///<summary>
/// Function to determine which platform we're on
///</summary>
private static string GetPlatform()
{
return Environment.Is64BitProcess ? "x64" : "x86";
}
///<summary>
/// Gets a value indicating if we are on a windows platform
///</summary>
private static bool IsWindows
{
get
{
var res = !(Environment.OSVersion.Platform == PlatformID.Unix ||
Environment.OSVersion.Platform == PlatformID.MacOSX);
return res;
}
}
private static void PrintDriversOgr()
{
#if DEBUG
if (_usable)
{
var num = Ogr.GetDriverCount();
for (var i = 0; i < num; i++)
{
var driver = Ogr.GetDriver(i);
Trace.WriteLine("OGR {i}: {driver.GetName()}", "Debug");
}
}
#endif
}
private static void PrintDriversGdal()
{
#if DEBUG
if (_usable)
{
var num = Gdal.GetDriverCount();
for (var i = 0; i < num; i++)
{
var driver = Gdal.GetDriver(i);
Trace.WriteLine("GDAL {i}: {driver.ShortName}-{driver.LongName}");
}
}
#endif
}
}
}
View Code
VB
'******************************************************************************
'*
'* Name: GdalConfiguration.vb.pp
'* Project: GDAL Interface
'* Purpose: A static configuration utility class to enable GDAL/OGR.
'* Author: Felix Obermaier
'*
'******************************************************************************
'* Copyright (c) 2012-2018, Felix Obermaier
'*
'* Permission is hereby granted, free of charge, to any person obtaining a
'* copy of this software and associated documentation files (the "Software"),
'* to deal in the Software without restriction, including without limitation
'* the rights to use, copy, modify, merge, publish, distribute, sublicense,
'* and/or sell copies of the Software, and to permit persons to whom the
'* Software is furnished to do so, subject to the following conditions:
'*
'* The above copyright notice and this permission notice shall be included
'* in all copies or substantial portions of the Software.
'*
'* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
'* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
'* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
'* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER '* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
'* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
'* DEALINGS IN THE SOFTWARE.
'*****************************************************************************/
Option Infer On
Imports System
Imports System.Diagnostics
Imports System.IO
Imports System.Reflection
Imports System.Runtime.InteropServices
Imports Gdal = OSGeo.GDAL.Gdal
Namespace Utility.ShapeFileToGeoJson
''' <summary>
''' Configuration class for GDAL/OGR
''' </summary>
Partial Public Class GdalConfiguration
Private Shared _configuredOgr As Boolean
Private Shared _configuredGdal As Boolean
Private Shared _usable As Boolean
<DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
Public Shared Function SetDefaultDllDirectories(ByVal directoryFlags As UInteger) As Boolean
End Function
' LOAD_LIBRARY_SEARCH_USER_DIRS | LOAD_LIBRARY_SEARCH_SYSTEM32
Private Const DllSearchFlags As UInteger = &H400 Or &H800
<DllImport("kernel32.dll", CharSet:=CharSet.Unicode, SetLastError:=True)>
Public Shared Function AddDllDirectory(ByVal lpPathName As String) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
''' <summary>
''' Construction of Gdal/Ogr
''' </summary>
Shared Sub New()
Dim nativePath As String = Nothing
Dim executingDirectory As String = Nothing
Dim gdalPath As String = Nothing
Try
If Not IsWindows Then
Const notSet As String = "_Not_set_"
Dim tmp As String = Gdal.GetConfigOption("GDAL_DATA", notSet)
_usable = (tmp <> notSet)
Return
End If
Dim executingAssemblyFile As String = New Uri(Assembly.GetExecutingAssembly.GetName.CodeBase).LocalPath
executingDirectory = Path.GetDirectoryName(executingAssemblyFile)
If String.IsNullOrEmpty(executingDirectory) Then
Throw New InvalidOperationException("cannot get executing directory")
End If
SetDefaultDllDirectories(DllSearchFlags)
gdalPath = bine(executingDirectory, "gdal")
nativePath = bine(gdalPath, GetPlatform())
If Not Directory.Exists(nativePath) Then
Throw New DirectoryNotFoundException($"GDAL native directory not found at '{nativePath}'")
End If
If Not File.Exists(bine(nativePath, "gdal_wrap.dll")) Then
Throw New FileNotFoundException($"GDAL native wrapper file not found at '{bine(nativePath, ", gdal_wrap.dll, ")}'") End If
AddDllDirectory(nativePath)
AddDllDirectory(bine(nativePath, "plugins"))
' Set the additional GDAL environment variables.
Dim gdalData As String = bine(gdalPath, "data")
Environment.SetEnvironmentVariable("GDAL_DATA", gdalData)
Gdal.SetConfigOption("GDAL_DATA", gdalData)
Dim driverPath As String = bine(nativePath, "plugins")
Environment.SetEnvironmentVariable("GDAL_DRIVER_PATH", driverPath)
Gdal.SetConfigOption("GDAL_DRIVER_PATH", driverPath)
Environment.SetEnvironmentVariable("GEOTIFF_CSV", gdalData)
Gdal.SetConfigOption("GEOTIFF_CSV", gdalData)
Dim projSharePath As String = bine(gdalPath, "share")
Environment.SetEnvironmentVariable("PROJ_LIB", projSharePath)
Gdal.SetConfigOption("PROJ_LIB", projSharePath)
_usable = True
Catch e As Exception
_usable = False
Trace.WriteLine(e, "error")
Trace.WriteLine($"Executing directory: {executingDirectory}", "error")
Trace.WriteLine($"gdal directory: {gdalPath}", "error")
Trace.WriteLine($"native directory: {nativePath}", "error")
'throw;
End Try
End Sub
''' <summary>
''' Gets a value indicating if the GDAL package is set up properly.
''' </summary>
Public Shared ReadOnly Property Usable As Boolean
Get
Return _usable
End Get
End Property
''' <summary>
''' Method to ensure the static constructor is being called.
''' </summary>
''' <remarks>Be sure to call this function before using Gdal/Ogr/Osr</remarks>
Public Shared Sub ConfigureOgr()
If Not _usable Then
Return
End If
If _configuredOgr Then
Return
End If
' Register drivers
Ogr.RegisterAll()
_configuredOgr = True
PrintDriversOgr()
End Sub
''' <summary>
''' Method to ensure the static constructor is being called.
''' </summary>
''' <remarks>Be sure to call this function before using Gdal/Ogr/Osr</remarks>
Public Shared Sub ConfigureGdal()
If Not _usable Then
Return
End If
If _configuredGdal Then
Return
End If
Gdal.AllRegister()
_configuredGdal = True
PrintDriversGdal()
End Sub
''' <summary>
''' Function to determine which platform we're on
''' </summary>
Private Shared Function GetPlatform() As String
If (Environment.Is64BitProcess) Then Return "x64"
Return "x86"
End Function
''' <summary>
''' Gets a value indicating if we are on a windows platform
''' </summary>
Private Shared ReadOnly Property IsWindows As Boolean
Get
Dim res = Not ((Environment.OSVersion.Platform = PlatformID.Unix) _
OrElse (Environment.OSVersion.Platform = PlatformID.MacOSX)) Return res
End Get
End Property
Private Shared Sub PrintDriversOgr()
#If (DEBUG) Then
If _usable Then
Dim num = Ogr.GetDriverCount
Dim i = 0
Do While (i < num)
Dim driver = Ogr.GetDriver(i)
Trace.WriteLine($"OGR {i}: {driver.GetName()}", "Debug")
i = (i + 1)
Loop
End If
#End If
End Sub
Private Shared Sub PrintDriversGdal()
#If (DEBUG) Then
If _usable Then
Dim num = Gdal.GetDriverCount
Dim i = 0
Do While (i < num)
Dim driver = Gdal.GetDriver(i)
Trace.WriteLine($"GDAL {i}: {driver.ShortName}-{driver.LongName}")
i = (i + 1)
Loop
End If
#End If
End Sub
End Class
End Namespace
View Code
记录⼀下!。