起因:最初采用SDE和pgsql11开发,后因数据库升级到pgsql14,sde因和pgsql版本不般配,无法导入要素数据和显示数据,数据库升级又是必然,所以只能另外找解决方案。
参考资料:Spatial Database for Postgres and ArcGis users: how to choose
附加:zigGis, GDAL。传说中的zigGis相当牛,能直接将postgis中的GIS类型显示到ArcGis的控件中,但是版本又比较复杂,也有可能会设计到版本不般配问题,后期我再看看这方面的知识体系。
Pgsql+postgis使用:PostgreSQL+PostGIS的使用(转载) - 无痕客 - 博客园
PostGIS教程一:PostGIS介绍 - 知乎
实现步骤:
在postgis中提供很多函数将wkb转成它的geometry类型,同样也有将geometry转成binary的函数。当然更兴奋的是ArcGis中有针对标准wkb的转换,这样一来,可想而知,这个方案是行的通的。
第一步:从postgreSQL中通过postgis读取GIS数据显示在AxMapControl中
1. C# 连接数据库pg
注意点: 要注意的是因为ArcEngine中对wkb的支持是byte[]之间的转换,所以在进行数据库取数据时用postgis的这个函数将GIS数据转成byte[],这样写 asbinary(the_geom)
2. 将得到的byte[](也就是wkb数据)通过ArcEngine的接口得到IGeometry,如下所示:
IGeometryFactory3 factory = new GeometryEnvironment() as IGeometryFactory3;
factory.CreateGeometryFromWkbVariant(wkb, out geom, out countin);
3. 将 IGeometry 显示在AxMapControl中。
第二步:将上一步从pg中显示出来的GIS数据进行相应的修改后保存回pg中
1. 修改指定的要素后通过 geometry得到wkb
要对修改操作进行保存,就需要将指定的要素中的geometry再次转回wkb然后通过sql语句修改pg中的指定记录即可,思路很简单,问题在于拼接SQL字符串上面,因为arcengine通过geometry得到的仍然是一个byte[],这个东西是没办法拼到sql语句中的。
2. 用到的ArcEngine接口如下:
IGeometryFactory3 factory = new GeometryEnvironment() as IGeometryFactory3;
byte[] geoBytes = factory.CreateWkbVariantFromGeometry(geometry) as byte[];
3. 拼接SQL时要将上面的byte[]数组转码
其实postgis处理存到pg中的是一长串的16进制字符串,相信大家打开数据库能看到,要想拼接好SQL串就得这样来一下:geomfromwkb(decode('" + geoByteStr + "', 'hex'))其中的geoByteStr是byte[]转成16进制的字串
上面两步已走通,是完全可以实现的,这样做的话,数据表我们也能自行定义,操作GIS数据,属性等,更灵活。
完整代码
一、读取数据库代码并且显示
private void pgsql加载非SDEToolStripMenuItem_Click(object sender, EventArgs e)
{
Byte[] bytes = PgsqlHelper.executeRouteQueryOne("select st_asbinary(st_union(geom)) as route from public.gis_osm_railways_free_1 where name='京沪线'");
IGeometry geom = null;
int countin;
IGeometryFactory3 factory = new GeometryEnvironment() as IGeometryFactory3;
factory.CreateGeometryFromWkbVariant(bytes, out geom, out countin);
IMap pMap = axMapControl1.Map;
IActiveView pActiveView = pMap as IActiveView;
IGraphicsContainer pGraphicsContainer = pMap as IGraphicsContainer;
IPolyline pLine = (IPolyline)geom;
geometry = geom;
ILineElement pLineElement = new LineElementClass();
//pLineElement.Symbol = pLineSym;
//添加geom
pElement = pLineElement as IElement;
pElement.Geometry = pLine;
pGraphicsContainer.AddElement(pElement, 0);
axMapControl1.FullExtent = pElement.Geometry.Envelope;
axMapControl1.Refresh();
}
二、编辑Geometry之后再保存进入数据库
private void apgsql保存非sdeToolStripMenuItem_Click(object sender, EventArgs e)
{
IGeometryFactory3 factory = new GeometryEnvironment() as IGeometryFactory3;
byte[] geoBytes = factory.CreateWkbVariantFromGeometry(geometry) as byte[];
string sss = ToHexStrFromByte(geoBytes);
string sql = @"insert into geomfromwkb(decode('" + geoBytes + "', 'hex'))";
string sql1 = @"INSERT INTO public.gis_osm_railways_free_1(
osm_id, code, fclass, name, layer, bridge, tunnel, geom)
VALUES ( '444', 4444, '3333', '333', 3 ,'3', '3' ,ST_GeomFromText('st_astext(geomfromwkb(decode('" + sss + "', 'hex')))',4326));";
PgsqlHelper.ExecuteQuery(sql1);
}
public string ToHexStrFromByte( byte[] byteDatas)
{
StringBuilder builder = new StringBuilder();
for (int i = 0; i < byteDatas.Length; i++)
{
builder.Append(string.Format("{0:X2}", byteDatas[i]));
}
return builder.ToString().Trim();
}
资料
读取pgsql数据库文章来源:https://www.toymoban.com/news/detail-469285.html
namespace WHUGIS.Classes
{
class DAO
{
private static string connectionString = "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=GIS_engine;";
public DAO()
{
}
public static Byte[] executeRouteQuery(string sqlstr)
{
NpgsqlConnection sqlConn = new NpgsqlConnection(connectionString);
try
{
sqlConn.Open();
NpgsqlCommand objCommand = new NpgsqlCommand(sqlstr, sqlConn);
Byte[] routeWKB = (byte[])objCommand.ExecuteScalar();
return routeWKB;
}
catch(Exception ee)
{
MessageBox.Show(ee.Message);
return null;
}
finally
{
sqlConn.Close();
}
}
}
}
ArcgisEngine Igeometry和WKB转换文章来源地址https://www.toymoban.com/news/detail-469285.html
using System;
using System.Collections.Generic;
using System.Text;
using GisSharpBlog.NetTopologySuite.IO;
using ESRI.ArcGIS.Geometry;
namespace Utils
{
/// <summary>
/// This class is used to convert a GeoAPI Geometry to ESRI and vice-versa.
/// It can also convert a ESRI Geometry to WKB/WKT and vice-versa.
/// </summary>
public static class Converters
{
public static byte[] ConvertGeometryToWKB(IGeometry geometry)
{
IWkb wkb = geometry as IWkb;
ITopologicalOperator oper = geometry as ITopologicalOperator;
oper.Simplify();
IGeometryFactory3 factory = new GeometryEnvironment() as IGeometryFactory3;
byte[] b = factory.CreateWkbVariantFromGeometry(geometry) as byte[];
return b;
}
public static byte[] ConvertWKTToWKB(string wkt)
{
WKBWriter writer = new WKBWriter();
WKTReader reader = new WKTReader();
return writer.Write(reader.Read(wkt));
}
public static string ConvertWKBToWKT(byte[] wkb)
{
WKTWriter writer = new WKTWriter();
WKBReader reader = new WKBReader();
return writer.Write(reader.Read(wkb));
}
public static string ConvertGeometryToWKT(IGeometry geometry)
{
byte[] b = ConvertGeometryToWKB(geometry);
WKBReader reader = new WKBReader();
GeoAPI.Geometries.IGeometry g = reader.Read(b);
WKTWriter writer = new WKTWriter();
return writer.Write(g);
}
public static IGeometry ConvertWKTToGeometry(string wkt)
{
byte[] wkb = ConvertWKTToWKB(wkt);
return ConvertWKBToGeometry(wkb);
}
public static IGeometry ConvertWKBToGeometry(byte[] wkb)
{
IGeometry geom;
int countin = wkb.GetLength(0);
IGeometryFactory3 factory = new GeometryEnvironment() as IGeometryFactory3;
factory.CreateGeometryFromWkbVariant(wkb, out geom, out countin);
return geom;
}
public static IGeometry ConvertGeoAPIToESRI(GeoAPI.Geometries.IGeometry geometry)
{
WKBWriter writer = new WKBWriter();
byte[] bytes = writer.Write(geometry);
return ConvertWKBToGeometry(bytes);
}
public static GeoAPI.Geometries.IGeometry ConvertESRIToGeoAPI(IGeometry geometry)
{
byte[] wkb = ConvertGeometryToWKB(geometry);
WKBReader reader = new WKBReader();
return reader.Read(wkb);
}
}
}
到了这里,关于Arcgis10.2+pgsql14开发(非SDE版本)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!