年度变更建库软件5.0版本
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

399 lines
17 KiB

4 months ago
using System;
using System.Runtime.InteropServices;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using OSGeo.OGR;
/*
* Model
* Description
* Author:
* Finished2017124
*/
namespace Kingo.RuleCheck.CheckHelper
{
/// <summary>
/// 生成要素五要素帮助类:周长面积比,最小角度,长轴和短轴比,质心坐标,椭球面积
/// </summary>
public class GenerateAttributeHelper
{
/// <summary>
/// 检查国家标准数据库面图层是否存在五要素字段,不存在则创建
/// </summary>
/// <param name="databaseType"></param>
/// <param name="connect"></param>
public static void CheckExtFiled(IFeatureClass pFeatureClass)
{
try
{
IClass pClass = pFeatureClass as IClass;
if (pFeatureClass.Fields.FindField("MinAngle_Extra") < 0)
{
IField field = new FieldClass();
IFieldEdit2 fieldEdit2 = field as IFieldEdit2;
fieldEdit2.Type_2 = esriFieldType.esriFieldTypeDouble;
fieldEdit2.Name_2 = "MinAngle_Extra";
pClass.AddField(field);
}
if (pFeatureClass.Fields.FindField("CenterPointX_Extra") < 0)
{
IField field = new FieldClass();
IFieldEdit2 fieldEdit2 = field as IFieldEdit2;
fieldEdit2.Type_2 = esriFieldType.esriFieldTypeDouble;
fieldEdit2.Name_2 = "CenterPointX_Extra";
pClass.AddField(field);
}
if (pFeatureClass.Fields.FindField("CenterPointY_Extra") < 0)
{
IField field = new FieldClass();
IFieldEdit2 fieldEdit2 = field as IFieldEdit2;
fieldEdit2.Type_2 = esriFieldType.esriFieldTypeDouble;
fieldEdit2.Name_2 = "CenterPointY_Extra";
pClass.AddField(field);
}
if (pFeatureClass.Fields.FindField("CKB_Extra") < 0)
{
IField field = new FieldClass();
IFieldEdit2 fieldEdit2 = field as IFieldEdit2;
fieldEdit2.Type_2 = esriFieldType.esriFieldTypeDouble;
fieldEdit2.Name_2 = "CKB_Extra";
pClass.AddField(field);
}
if (pFeatureClass.Fields.FindField("MJZCB_Extra") < 0)
{
IField field = new FieldClass();
IFieldEdit2 fieldEdit2 = field as IFieldEdit2;
fieldEdit2.Type_2 = esriFieldType.esriFieldTypeDouble;
fieldEdit2.Name_2 = "MJZCB_Extra";
pClass.AddField(field);
}
if (pFeatureClass.Fields.FindField("MJ_EXTRA") < 0)
{
IField field = new FieldClass();
IFieldEdit2 fieldEdit2 = field as IFieldEdit2;
fieldEdit2.Type_2 = esriFieldType.esriFieldTypeDouble;
fieldEdit2.Name_2 = "MJ_EXTRA";
pClass.AddField(field);
}
if (pFeatureClass.Fields.FindField("ZC_EXTRA") < 0)
{
IField field = new FieldClass();
IFieldEdit2 fieldEdit2 = field as IFieldEdit2;
fieldEdit2.Type_2 = esriFieldType.esriFieldTypeDouble;
fieldEdit2.Name_2 = "ZC_EXTRA";
pClass.AddField(field);
}
if (pFeatureClass.Fields.FindField("PointCount") < 0)
{
IField field = new FieldClass();
IFieldEdit2 fieldEdit2 = field as IFieldEdit2;
fieldEdit2.Type_2 = esriFieldType.esriFieldTypeInteger;
fieldEdit2.Name_2 = "PointCount";
pClass.AddField(field);
}
}
catch (Exception ex)
{
throw new Exception("新建五要素字段异常:" + ex.Message.ToString());
}
}
/// <summary>
/// 设置要素属性值(地类图斑属性继承)
/// </summary>
/// <param name="pFeatureClass">要赋值的图层</param>
/// <param name="pFeature">是否覆盖原有值:如果五要素字段有值,是否覆盖</param>
public static void SetFeatureAttribute(IFeatureClass pFeatureClass, bool isCoverData = true)
{
if (pFeatureClass == null)
return;
IFeature pFeature = null;
IFeatureCursor pCursor = null;
//DataSource ds = null;
//Layer layer = null;
try
{
//周长
double zc = 0;
//面积
double mj = 0;
int mj_extraFieldID = pFeatureClass.FindField("MJ_EXTRA");
int zc_extraFieldID = pFeatureClass.FindField("ZC_EXTRA");
int centerpointx_extraFieldID = pFeatureClass.FindField("CenterPointX_Extra");
int centerpointy_extraFieldID = pFeatureClass.FindField("CenterPointY_Extra");
int ckb_extraFieldID = pFeatureClass.FindField("CKB_Extra");
int mjzcb_extraFieldID = pFeatureClass.FindField("MJZCB_Extra");
int minangle_extraFieldID = pFeatureClass.FindField("MinAngle_Extra");
int pointcount_extraFieldID = pFeatureClass.FindField("PointCount");
int count = 0;
if (isCoverData)
{
count = pFeatureClass.FeatureCount(null);
pCursor = pFeatureClass.Search(null, true);
}
else
{
IQueryFilter pQueryFilter = new QueryFilter()
{
WhereClause = " MJ_EXTRA IS NULL OR ZC_EXTRA IS NULL OR CenterPointX_Extra IS NULL OR CenterPointY_Extra IS NULL OR CKB_Extra IS NULL OR MJZCB_Extra IS NULL OR MinAngle_Extra IS NULL"
};
pCursor = pFeatureClass.Search(pQueryFilter, true);
count = pFeatureClass.FeatureCount(pQueryFilter);
}
if (count <= 0)
{
return;
}
#region gdal计算最小角度 RegisterAll();
//RegisterAll();
//ds = Ogr.Open(Env.Instance.Project.GetProjMDBPath(), 0);
//if (ds != null && ds.GetLayerCount() >= 0)
//{
// OSGeo.OGR.Envelope envelope = new OSGeo.OGR.Envelope();
// layer = ds.GetLayerByName((pFeatureClass as FeatureClass).BrowseName);
// layer.GetExtent(envelope, 1);
//}
#endregion
while ((pFeature = pCursor.NextFeature()) != null)
{
if (pFeature.Shape == null || pFeature.Shape.IsEmpty)
{
continue;
}
try
{
//pFeature.Shape.SpatialReference = Env.Instance.KMap.GetMap().SpatialReference;
//图斑面积赋值(计算图斑椭球面积)
mj = RuleCommon.GetArea(pFeature.ShapeCopy);
pFeature.set_Value(mj_extraFieldID, mj);
//周长
ITopologicalOperator topo = pFeature.ShapeCopy as ITopologicalOperator;
IPolyline line = topo.Boundary as IPolyline;
zc = line.Length;
pFeature.set_Value(zc_extraFieldID, zc);
//IArea area = pFeature.ShapeCopy as IArea;
////质心坐标X
//pFeature.set_Value(centerpointx_extraFieldID, area.LabelPoint.X);
////质心坐标Y
//pFeature.set_Value(centerpointy_extraFieldID, area.LabelPoint.X);
//长宽比
IEnvelope env = pFeature.ShapeCopy.Envelope;
if (env.Width > env.Height)
{
pFeature.set_Value(ckb_extraFieldID, env.Width / (env.Height == 0D ? 1D : env.Height));
}
else
{
pFeature.set_Value(ckb_extraFieldID, env.Height / (env.Width == 0D ? 1D : env.Width));
}
//周长面积比
pFeature.set_Value(mjzcb_extraFieldID, mj / (zc == 0D ? 1D : zc));
string jsonGeometry = string.Empty;
double angle = CommonHelper.GetMinAngle(pFeature.ShapeCopy, out jsonGeometry);
//if (layer != null && angle <= 0)
//{
// OSGeo.OGR.Feature feature = layer.GetFeature(pFeature.OID);
// if (feature != null)
// {
// //最小角度
// angle = ConvertWkt(feature.GetGeometryRef());
// }
//}
pFeature.set_Value(minangle_extraFieldID, angle);
//设置点数量
pFeature.set_Value(pointcount_extraFieldID, (pFeature.ShapeCopy as IPointCollection).PointCount);
pFeature.Store();
}
catch (Exception ex)
{
throw ex;
}
}
}
catch (Exception ex)
{
throw new Exception("设置要素属性异常:" + ex.Message);
}
finally
{
//if (ds != null)
//{
// ds.Dispose();
// ds = null;
//}
//if (layer != null)
//{
// layer.Dispose();
//}
if (pFeature != null)
{
pFeature = null;
}
if (pCursor != null)
{
Marshal.ReleaseComObject(pCursor);
}
}
}
private static void RegisterAll()
{
// 注册所有的驱动
Ogr.RegisterAll();
// 为了支持中文路径,请添加下面这句代码
OSGeo.GDAL.Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");
// 为了使属性表字段支持中文,请添加下面这句
//Gdal.SetConfigOption("SHAPE_ENCODING", "NO");
}
/// <summary>
/// 获取要素最小角度
/// </summary>
/// <param name="geometry"></param>
/// <returns></returns>
private static double ConvertWkt(Geometry geometry)
{
double rstAngle = -1;
try
{
string wkt = "";
geometry.ExportToWkt(out wkt);
if (wkt.StartsWith("POLYGON"))
{
string wktN = wkt.Replace("POLYGON ((", "").Replace("))", "");
string[] strs = wktN.Replace("),(", "@").Split('@');
for (int i = 0; i < strs.Length; i++)
{
string[] strsP = strs[i].Split(',');
for (int j = 0; j < strsP.Length - 1; j++)
{
string[] strF = null;
string[] strC = strsP[j].ToString().Split(' ');
string[] strS = null;
if (j == 0)
{
strF = strsP[strsP.Length - 2].ToString().Split(' ');
strS = strsP[j + 1].ToString().Split(' ');
}
else if (j == strsP.Length - 2)
{
strF = strsP[j - 1].ToString().Split(' ');
strS = strsP[strsP.Length - 1].ToString().Split(' ');
}
else
{
strF = strsP[j - 1].ToString().Split(' ');
strS = strsP[j + 1].ToString().Split(' ');
}
double angle = GetAngle(Convert.ToDouble(strC[0]), Convert.ToDouble(strC[1]), Convert.ToDouble(strF[0]), Convert.ToDouble(strF[1]), Convert.ToDouble(strS[0]), Convert.ToDouble(strS[1]));
if (rstAngle == -1)
{
rstAngle = angle;
}
else if (rstAngle > angle)
{
rstAngle = angle;
}
}
}
}
}
catch
{
}
return rstAngle;
}
#region 计算面要素最小夹角
/// <summary>
/// 获取最小夹角
/// </summary>
/// <param name="geometry"></param>
/// <returns></returns>
public static double GetMinAngle(ESRI.ArcGIS.Geometry.IGeometry geometry)
{
ESRI.ArcGIS.Geometry.IGeometryFactory3 factory = new ESRI.ArcGIS.Geometry.GeometryEnvironment() as ESRI.ArcGIS.Geometry.IGeometryFactory3;
byte[] b = factory.CreateWkbVariantFromGeometry(geometry) as byte[];
Geometry gdalGeometry = Geometry.CreateFromWkb(b);
return GetAngle(gdalGeometry);
}
public static double GetAngle(Geometry geometry)
{
string wkt = "";
geometry.ExportToWkt(out wkt);
double rstAngle = -1;
double sumAngle = 0;
if (wkt.StartsWith("POLYGON"))
{
//StringBuilder sb = new StringBuilder("POLYGON (");
string wktN = wkt.Replace("POLYGON ((", "").Replace("))", "");
string[] strs = wktN.Replace("),(", "@").Split('@');
for (int i = 0; i < strs.Length; i++)
{
string[] strsP = strs[i].Split(',');
for (int j = 0; j < strsP.Length; j++)
{
string[] strF = strsP[j].ToString().Split(' ');
string[] strC = null;
string[] strS = null;
if (j == strsP.Length - 2)
{
strC = strsP[j + 1].ToString().Split(' ');
strS = strsP[0].ToString().Split(' ');
if (strC[0] == strS[0] && strC[1] == strS[1])
{
strS = strsP[1].ToString().Split(' ');
}
}
else if (j == strsP.Length - 1)
{
strC = strsP[0].ToString().Split(' ');
strS = strsP[1].ToString().Split(' ');
continue;
}
else
{
strC = strsP[j + 1].ToString().Split(' ');
strS = strsP[j + 2].ToString().Split(' ');
}
double angle = GetAngle(Convert.ToDouble(strC[0]), Convert.ToDouble(strC[1]), Convert.ToDouble(strF[0]), Convert.ToDouble(strF[1]), Convert.ToDouble(strS[0]), Convert.ToDouble(strS[1]));
sumAngle += angle;
if (rstAngle == -1)
{
rstAngle = angle;
}
else
{
if (angle < rstAngle)
{
rstAngle = angle;
}
}
}
}
return rstAngle;
}
return 0;
}
public static double GetAngle(double cenX, double cenY, double firstX, double firstY, double secondX, double secondY)
{
double ma_x = firstX - cenX;
double ma_y = firstY - cenY;
double mb_x = secondX - cenX;
double mb_y = secondY - cenY;
double v1 = (ma_x * mb_x) + (ma_y * mb_y);
double ma_val = Math.Sqrt(ma_x * ma_x + ma_y * ma_y);
double mb_val = Math.Sqrt(mb_x * mb_x + mb_y * mb_y);
double cosM = v1 / (ma_val * mb_val);
double angleAMB = Math.Acos(cosM) * 180 / Math.PI;
return angleAMB;
}
#endregion
}
}