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.
398 lines
17 KiB
398 lines
17 KiB
using System; |
|
using System.Runtime.InteropServices; |
|
using ESRI.ArcGIS.Geodatabase; |
|
using ESRI.ArcGIS.Geometry; |
|
using OSGeo.OGR; |
|
|
|
/* |
|
* Model:生成要素五要素帮助类 |
|
* Description:生成要素五要素帮助类 |
|
* Author:高山 |
|
* Finished:2017年12月4日 |
|
*/ |
|
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 |
|
} |
|
}
|
|
|