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 { /// /// 生成要素五要素帮助类:周长面积比,最小角度,长轴和短轴比,质心坐标,椭球面积 /// public class GenerateAttributeHelper { /// /// 检查国家标准数据库面图层是否存在五要素字段,不存在则创建 /// /// /// 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()); } } /// /// 设置要素属性值(地类图斑属性继承) /// /// 要赋值的图层 /// 是否覆盖原有值:如果五要素字段有值,是否覆盖 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"); } /// /// 获取要素最小角度 /// /// /// 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 计算面要素最小夹角 /// /// 获取最小夹角 /// /// /// 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 } }