using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using KGIS.Framework.AE;
using KGIS.Framework.AE.ExtensionMethod;
using KGIS.Framework.Utils;
using KGIS.Framework.Utils.ExtensionMethod;
using System;
using System.Collections.Generic;
using System.Data;
using System.Runtime.InteropServices;
namespace Kingo.PluginServiceInterface.Helper
{
    /// 
    /// AE开发公共类
    /// 
    public static class AECommonHelper
    {
        public static DataTable GetTableByFeatureClass(IFeatureClass featureClass, IQueryFilter queryFilter = null)
        {
            DataTable dataTable = new DataTable();
            ITable tableTemp = featureClass as ITable;
            int fieldCount = tableTemp.Fields.FieldCount;
            try
            {
                for (int i = 0; i < fieldCount; i++)
                {
                    IField field = tableTemp.Fields.Field[i];
                    dataTable.Columns.Add(field.Name, GetSystemType(field.Type));
                }
                ICursor cursor = tableTemp.Search(queryFilter, true);
                IRow row = null;
                while ((row = cursor.NextRow()) != null)
                {
                    DataRow dataRow = dataTable.NewRow();
                    for (int i = 0; i < fieldCount; i++)
                    {
                        object value = row.Value[i];
                        dataRow[i] = value;
                    }
                    dataTable.Rows.Add(dataRow);
                }
                if (cursor != null)
                    Marshal.ReleaseComObject(cursor);
            }
            catch (Exception ex)
            {
                LogAPI.Debug("GetTableByFeatureClass异常:" + ex.Message);
                LogAPI.Debug("GetTableByFeatureClass异常:" + ex.StackTrace);
            }
            return dataTable;
        }
        private static Type GetSystemType(esriFieldType fieldType)
        {
            switch (fieldType)
            {
                case esriFieldType.esriFieldTypeSmallInteger:
                case esriFieldType.esriFieldTypeInteger:
                    return typeof(int);
                case esriFieldType.esriFieldTypeSingle:
                    return typeof(float);
                case esriFieldType.esriFieldTypeDouble:
                    return typeof(double);
                case esriFieldType.esriFieldTypeDate:
                    return typeof(DateTime);
                default:
                    return typeof(string);
            }
        }
        /// 
        /// 设置数据库容差
        /// 
        /// 
        /// 
        /// 
        public static void SetGeoDatasetSpatialReference(IWorkspace pWS, ISpatialReference pSR, double pTolerance)
        {
            try
            {
                //KGIS.Framework.AE.GeoDBAPI.SetGeoDatasetSpatialReference(pWS, pSR, pTolerance);
                if (pSR != null)
                {
                    ISpatialReferenceResolution toleranceResolution = pSR as ISpatialReferenceResolution;
                    //toleranceResolution.ConstructFromHorizon();
                    //toleranceResolution.SetDefaultXYResolution();
                    toleranceResolution.set_XYResolution(true, 0.00005);
                    if (pSR is ISpatialReferenceTolerance tolerance)
                    {
                        tolerance.XYTolerance = pTolerance;
                        tolerance.ZTolerance = pTolerance;
                        tolerance.MTolerance = pTolerance;
                    }
                }
                IEnumDataset pEnumDataset = pWS.Datasets[esriDatasetType.esriDTFeatureDataset];
                IDataset ds = null;
                if (pEnumDataset != null)
                {
                    while ((ds = pEnumDataset.Next()) != null)
                    {
                        if (ds is IGeoDataset)
                        {
                            if ((ds as IGeoDataset).SpatialReference != pSR)
                                (ds as IGeoDatasetSchemaEdit).AlterSpatialReference(pSR);
                        }
                    }
                }
                pEnumDataset = pWS.Datasets[ESRI.ArcGIS.Geodatabase.esriDatasetType.esriDTFeatureClass];
                if (pEnumDataset == null)
                {
                    return;
                }
                while ((ds = pEnumDataset.Next()) != null)
                {
                    if (ds is IGeoDataset)
                    {
                        if ((ds as IGeoDataset).SpatialReference != pSR)
                            (ds as IGeoDatasetSchemaEdit).AlterSpatialReference(pSR);
                    }
                }
                try
                {
                    pWS.ExecuteSQL(string.Format("UPDATE GDB_SpatialRefs SET XYUnits = 20000 ,XYTolerance = {0}", pTolerance));
                }
                catch (Exception ex)
                {
                    throw new Exception("设置坐标参考坐标精度和容差异常:" + ex.Message);
                }
            }
            catch (Exception ex)
            {
                throw new Exception("设置坐标参考坐标精度和容差异常:" + ex.Message);
            }
        }
        #region GetPolygonFromWkt
        /// 
        /// 从Wkt获取多边形
        /// 
        /// 
        /// 
        public static IGeometry GetPolygonFromWkt(string pointsStr)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(pointsStr))
                    return null;
                if (!pointsStr.StartsWith("POLYGON") && !pointsStr.StartsWith("MULTIPOLYGON"))
                    pointsStr = DispalySQ_Click(pointsStr);
                //OSGeo.OGR.Ogr.RegisterAll();
                IGeometry geometry = new PolygonClass();
                OSGeo.OGR.Geometry rstGeometry = OSGeo.OGR.Geometry.CreateFromWkt(pointsStr);
                byte[] geometryBytes = new byte[rstGeometry.WkbSize()];
                rstGeometry.ExportToWkb(geometryBytes);
                IGeometryFactory3 factory = new GeometryEnvironment() as IGeometryFactory3;
                int bytesLen = geometryBytes.Length;
                factory.CreateGeometryFromWkbVariant(geometryBytes, out geometry, out bytesLen);
                double area = (geometry as IArea).Area;
                IPolygon polygon = geometry as IPolygon;
                if (area < 0)
                {
                    polygon.ReverseOrientation();
                }
                polygon.Close();
                ITopologicalOperator pBoundaryTop = polygon as ITopologicalOperator;
                pBoundaryTop.Simplify();
                return geometry;
            }
            catch (Exception ex)
            {
                LogAPI.Debug("GetPolygonFromWkt异常:" + ex.Message);
                return null;
            }
        }
        private static string DispalySQ_Click(string Coord)
        {
            string SQstring = Coord.Replace('\r', ' ').ToTrim();
            if (!string.IsNullOrWhiteSpace(SQstring))
            {
                string[] rings = SQstring.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
                string coord = string.Empty;
                if (rings.Length == 1)
                {
                    foreach (var geoRing in rings)
                    {
                        string strGeo = geoRing.Replace('\r', ' ').ToTrim();
                        if (strGeo.Split(new char[] { ';' }).Length < 10)
                            strGeo = geoRing.Replace(";", ",");
                        if (strGeo.Contains(";"))
                        {
                            coord = string.Format("POLYGON((");
                            string[] ps = strGeo.TrimEnd(';').Split(';');
                            foreach (var item in ps)
                            {
                                coord += item.Replace('\r', ' ').Replace(',', ' ') + ",";
                            }
                        }
                        else
                        {
                            coord = string.Format("POLYGON((");
                            coord += strGeo;
                        }
                        coord = coord.TrimEnd(',');
                        coord += "))";
                    }
                    return coord;
                }
                else if (rings.Length > 1)
                {
                    coord = "MULTIPOLYGON(";
                    foreach (var ring in rings)
                    {
                        string Temp_Coordinate = string.Empty;
                        string[] points = ring.TrimEnd(';').Split(';');
                        string strRing = "((";
                        if (points.Length == 1)
                        {
                            strRing += points[0];
                        }
                        else
                        {
                            foreach (var item in points)
                            {
                                strRing += item.Replace(',', ' ') + ",";
                            }
                        }
                        char[] charsToTrim = { ',' };
                        strRing = strRing.TrimEnd(charsToTrim);
                        strRing = strRing.ToTrim();
                        strRing = strRing.TrimEnd(charsToTrim);
                        strRing += ")),";
                        coord += strRing;
                    }
                    coord = coord.TrimEnd(',');
                    coord += ")";
                }
                return coord;
                //AreaEnvOfeat(ConvertWKTToIGeometry(SQstring));
            }
            return string.Empty;
        }
        //public static IGeometry GetPolygonFromWkt(string pointsStr)
        //{
        //    IGeometry geometry = new PolygonClass();
        //    OSGeo.OGR.Geometry rstGeometry = OSGeo.OGR.Geometry.CreateFromWkt(pointsStr);
        //    byte[] geometryBytes = new byte[rstGeometry.WkbSize()];
        //    rstGeometry.ExportToWkb(geometryBytes);
        //    IGeometryFactory3 factory = new GeometryEnvironment() as IGeometryFactory3;
        //    int bytesLen = geometryBytes.Length;
        //    factory.CreateGeometryFromWkbVariant(geometryBytes, out geometry, out bytesLen);
        //    return geometry;
        //}
        //public static IGeometry GetPolygonFromWkt(string pointsStr)
        //{
        //    try
        //    {
        //        IGeometry geometry = new PolygonClass();
        //        OSGeo.OGR.Geometry rstGeometry = OSGeo.OGR.Geometry.CreateFromWkt(pointsStr);
        //        byte[] geometryBytes = new byte[rstGeometry.WkbSize()];
        //        rstGeometry.ExportToWkb(geometryBytes);
        //        IGeometryFactory3 factory = new GeometryEnvironment() as IGeometryFactory3;
        //        int bytesLen = geometryBytes.Length;
        //        factory.CreateGeometryFromWkbVariant(geometryBytes, out geometry, out bytesLen);
        //        IPolygon polygon = geometry as IPolygon;
        //        polygon.Close();
        //        ITopologicalOperator pBoundaryTop = polygon as ITopologicalOperator;
        //        pBoundaryTop.Simplify();
        //        return geometry;
        //    }
        //    catch (Exception ex)
        //    {
        //        LogAPI.Debug("GetPolygonFromWkt获取图形异常:" + ex);
        //        throw ex;
        //    }
        //}
        #endregion
        #region 要素存在尖锐角和局部狭长图形(即不允许存在一个角度小于10度,或局部图形狭长的情况)
        public static bool SharpAngleDataCheck(IGeometry geometry, ref List pointList, ref double angle)
        {
            if (geometry == null || geometry.IsEmpty)
            {
                return false; // 或者抛出一个异常,取决于你的错误处理策略
            }
            try
            {
                angle = GetMinAngle(geometry, ref pointList); // 获取图形的最小角度
                if (angle < 10) return true;
                ITopologicalOperator topo = geometry as ITopologicalOperator;
                if (topo == null)
                {
                    // 记录日志并返回false或抛出异常
                    LogAPI.Debug("几何对象不支持ITopologicalOperator接口。");
                    return false;
                }
                IPolyline line1 = topo.Boundary as IPolyline;
                if (line1 == null)
                {
                    // 记录日志并返回false或抛出异常
                    LogAPI.Debug("几何对象的边界不是IPolyline类型。");
                    return false;
                }
                double length1 = line1.Length; // 原始图形的周长
                int pointCount1 = (geometry as IPointCollection).PointCount;
                if (geometry.GeometryType != esriGeometryType.esriGeometryPolygon) return false;
                // 确保负缓冲值不超过几何体的最小尺寸
                IArea area = geometry as IArea;
                double bufferValue = -0.05;
                if (area != null && Math.Abs(bufferValue) > Math.Sqrt(area.Area))
                {
                    bufferValue = -Math.Sqrt(area.Area) / 2; // 动态调整缓冲值
                }
                IGeometry geo = topo.Buffer(bufferValue);
                if (geo == null || geo.IsEmpty)
                {
                    return false; // 或者抛出一个异常
                }
                ITopologicalOperator topo2 = geo as ITopologicalOperator;
                if (topo2 == null)
                {
                    // 记录日志并返回false或抛出异常
                    LogAPI.Debug("缓冲后的几何对象不支持ITopologicalOperator接口。");
                    return false;
                }
                IPolyline line2 = topo2.Boundary as IPolyline;
                if (line2 == null)
                {
                    // 记录日志并返回false或抛出异常
                    LogAPI.Debug("缓冲后的几何对象的边界不是IPolyline类型。");
                    return false;
                }
                double length2 = line2.Length; // 向内缓冲后的图形的周长
                double delta_length = length1 - length2; // 周长差
                double avg_halfangle = 180 * (pointCount1 - 1 - 2) / (pointCount1 - 1) / 2; // 平均
                double conner_normal_length = 2 * 0.05 / Math.Tan(avg_halfangle * (Math.PI / 180));
                return (delta_length > 8 * conner_normal_length * (pointCount1 - 1)) || angle < 10;
            }
            catch (Exception ex)
            {
                LogAPI.Debug("SharpAngleDataCheck数据检查时发生异常,异常信息如下:");
                LogAPI.Debug(ex);
                // 可以选择重新抛出异常,让调用者处理
                // throw;
                return false; // 或者根据你的错误处理策略返回一个特定的值
            }
        }
        public static bool SharpAngleDataCheck(IGeometry geometry, ref IPoint point, ref IPolyline polyline)
        {
            bool isSharpAngle = false;
            try
            {
                if (geometry == null) return isSharpAngle;
                double angle = GetMinAngle(geometry, ref point, ref polyline);//获取图形的最小角度
                ITopologicalOperator topo = geometry as ITopologicalOperator;
                IPolyline line1 = topo.Boundary as IPolyline;
                double length1 = line1.Length;//原始图形的周长
                int pointCount1 = (geometry as IPointCollection).PointCount;
                IGeometry geo = topo.Buffer(-0.05);
                ITopologicalOperator topo2 = geo as ITopologicalOperator;
                IPolyline line2 = topo2.Boundary as IPolyline;
                double length2 = line2.Length;//向内缓冲后的图形的周长
                double delta_length = length1 - length2;//周长差
                double avg_halfangle = 180 * (pointCount1 - 1 - 2) / (pointCount1 - 1) / 2;//平均
                double conner_normal_length = 2 * 0.05 / Math.Tan(avg_halfangle * (Math.PI / 180));
                if ((delta_length > 8 * conner_normal_length * (pointCount1 - 1)) || angle < 10)
                {
                    if ((delta_length > 8 * conner_normal_length * (pointCount1 - 1)) && angle < 10)
                        return true;
                    else if (delta_length > 8 * conner_normal_length * (pointCount1 - 1))
                        return true;
                    else if (angle < 10)
                        return true;
                }
                //if (topo != null)
                //    Marshal.ReleaseComObject(topo);
                //if (line1 != null)
                //    Marshal.ReleaseComObject(line1);
                //if (topo2 != null)
                //    Marshal.ReleaseComObject(topo2);
                //if (line2 != null)
                //    Marshal.ReleaseComObject(line2);
                //if (geo != null)
                //    Marshal.ReleaseComObject(geo);
            }
            catch (Exception ex)
            {
                LogAPI.Debug("数据检查时发生异常,异常信息如下:");
                LogAPI.Debug(ex);
            }
            finally
            {
                //GC.Collect();
            }
            return isSharpAngle;
        }
        public static double GetMinAngle(IGeometry pGeo, ref IPoint point, ref IPolyline polyline)
        {
            double result = -1;
            IPolygon4 poly4 = null;
            ITopologicalOperator topo = null;
            GeometryBag geoBag = null;
            IGeometryCollection geoCollection = null;
            try
            {
                if (pGeo == null || pGeo.IsEmpty)
                    return result;
                poly4 = pGeo as IPolygon4;
                topo = poly4 as ITopologicalOperator;
                topo?.Simplify();
                geoBag = poly4.ExteriorRingBag as GeometryBag;
                if (geoBag == null) return result;
                geoCollection = geoBag as IGeometryCollection;
                List rings = new List();
                for (int j = 0; j < geoCollection.GeometryCount; j++)
                {
                    IGeometry geo = geoCollection.get_Geometry(j);
                    rings.Add(geo);
                    //内环图形
                    IGeometryBag InteriorBag = (pGeo as IPolygon4).get_InteriorRingBag(geo as IRing);
                    if (InteriorBag != null)
                    {
                        IGeometryCollection InteriorRingGeometryCollection = InteriorBag as IGeometryCollection;
                        for (int IR = 0; IR < InteriorRingGeometryCollection.GeometryCount; IR++)
                        {
                            rings.Add(InteriorRingGeometryCollection.get_Geometry(IR));
                        }
                    }
                }
                foreach (IGeometry ring in rings)
                {
                    if (ring.IsEmpty) continue;
                    IPointCollection points = ring as IPointCollection;
                    int num = points.PointCount - 1;
                    for (int i = 0; i < num; i++)
                    {
                        IPoint p1 = null;
                        IPoint p2 = points.get_Point(i);
                        IPoint p3 = null;
                        if (i == 0)
                        {
                            p1 = points.get_Point(num - 1);
                            p3 = points.get_Point(i + 1);
                        }
                        else if (i == num - 1)
                        {
                            p1 = points.get_Point(i - 1);
                            p3 = points.get_Point(0);
                        }
                        else
                        {
                            p1 = points.get_Point(i - 1);
                            p3 = points.get_Point(i + 1);
                        }
                        if ((p2.X == p1.X && p2.Y == p1.Y) || (p2.X == p3.X && p2.Y == p3.Y))
                            continue;
                        double angle = GetAngle(p2, p1, p3);
                        if (result == -1)
                        {
                            result = angle;
                        }
                        else
                        {
                            if (result > angle)
                            {
                                result = angle;
                                point = p3;
                                point.SpatialReference = p1.SpatialReference;
                                polyline = (IPolyline)new PolylineClass();
                                polyline.SpatialReference = p1.SpatialReference;
                                polyline.FromPoint = p1;
                                polyline.ToPoint = p2;
                            }
                        }
                        //Marshal.ReleaseComObject(p1);
                        //Marshal.ReleaseComObject(p2);
                        //Marshal.ReleaseComObject(p3);
                    }
                    //Marshal.ReleaseComObject(ring);
                }
            }
            catch (Exception ex)
            {
                LogAPI.Debug("获取最小角度异常:" + ex);
                throw ex;
            }
            finally
            {
                //if (poly4 != null)
                //    Marshal.ReleaseComObject(poly4);
                //if (topo != null)
                //    Marshal.ReleaseComObject(topo);
                //if (geoBag != null)
                //    Marshal.ReleaseComObject(geoBag);
                //if (geoCollection != null)
                //    Marshal.ReleaseComObject(geoCollection);
            }
            return result;
        }
        /// 
        /// 获取最小角度
        /// 
        /// 
        /// 
        public static double GetMinAngle(IGeometry pGeo, ref List pointlist)
        {
            double result = -1;
            IPolygon4 poly4 = null;
            ITopologicalOperator topo = null;
            GeometryBag geoBag = null;
            IGeometryCollection geoCollection = null;
            pointlist = new List();
            try
            {
                if (pGeo == null || pGeo.IsEmpty)
                    return result;
                poly4 = pGeo as IPolygon4;
                topo = poly4 as ITopologicalOperator;
                topo?.Simplify();
                geoBag = poly4.ExteriorRingBag as GeometryBag;
                if (geoBag == null) return result;
                geoCollection = geoBag as IGeometryCollection;
                List rings = new List();
                for (int j = 0; j < geoCollection.GeometryCount; j++)
                {
                    IGeometry geo = geoCollection.get_Geometry(j);
                    rings.Add(geo);
                    //内环图形
                    IGeometryBag InteriorBag = (pGeo as IPolygon4).get_InteriorRingBag(geo as IRing);
                    if (InteriorBag != null)
                    {
                        IGeometryCollection InteriorRingGeometryCollection = InteriorBag as IGeometryCollection;
                        for (int IR = 0; IR < InteriorRingGeometryCollection.GeometryCount; IR++)
                        {
                            rings.Add(InteriorRingGeometryCollection.get_Geometry(IR));
                        }
                    }
                }
                foreach (IGeometry ring in rings)
                {
                    if (ring.IsEmpty) continue;
                    IPointCollection points = ring as IPointCollection;
                    int num = points.PointCount - 1;
                    for (int i = 0; i < num; i++)
                    {
                        IPoint p1 = null;
                        IPoint p2 = points.get_Point(i);
                        IPoint p3 = null;
                        if (i == 0)
                        {
                            p1 = points.get_Point(num - 1);
                            p3 = points.get_Point(i + 1);
                        }
                        else if (i == num - 1)
                        {
                            p1 = points.get_Point(i - 1);
                            p3 = points.get_Point(0);
                        }
                        else
                        {
                            p1 = points.get_Point(i - 1);
                            p3 = points.get_Point(i + 1);
                        }
                        if ((p2.X == p1.X && p2.Y == p1.Y) || (p2.X == p3.X && p2.Y == p3.Y) || (p1.X == p3.X && p1.Y == p3.Y))
                            continue;
                        double angle = GetAngle(p2, p1, p3);
                        if (double.IsNaN(angle)) continue;
                        if (result == -1)
                        {
                            result = angle;
                            pointlist.Add(p1);
                            pointlist.Add(p2);
                            pointlist.Add(p3);
                        }
                        else
                        {
                            if (double.IsNaN(result))
                            {
                                result = angle;
                            }
                            if (result > angle)
                            {
                                result = angle;
                                if (pointlist.Count > 0) pointlist.Clear();
                                pointlist.Add(p1);
                                pointlist.Add(p2);
                                pointlist.Add(p3);
                            }
                        }
                        //Marshal.ReleaseComObject(p1);
                        //Marshal.ReleaseComObject(p2);
                        //Marshal.ReleaseComObject(p3);
                    }
                    //Marshal.ReleaseComObject(ring);
                }
            }
            catch (Exception ex)
            {
                LogAPI.Debug("获取最小角度异常:" + ex);
                throw ex;
            }
            finally
            {
                //if (poly4 != null)
                //    Marshal.ReleaseComObject(poly4);
                //if (topo != null)
                //    Marshal.ReleaseComObject(topo);
                //if (geoBag != null)
                //    Marshal.ReleaseComObject(geoBag);
                //if (geoCollection != null)
                //    Marshal.ReleaseComObject(geoCollection);
            }
            return result;
        }
        /// 
        /// 计算角度
        /// 
        /// 
        /// 
        /// 
        /// 
        public static double GetAngle(IPoint cenPoint, IPoint firstPoint, IPoint secondPoint)
        {
            double ma_x = firstPoint.X - cenPoint.X;
            double ma_y = firstPoint.Y - cenPoint.Y;
            double mb_x = secondPoint.X - cenPoint.X;
            double mb_y = secondPoint.Y - cenPoint.Y;
            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);
            if (ma_val * mb_val == 0)
            {
                return -1;
            }
            double cosM = v1 / (ma_val * mb_val);
            double angleAMB = Math.Acos(cosM) * 180 / Math.PI;
            return angleAMB;
        }
        #endregion
        #region Passive_Sharp_Repair
        /// 
        /// 构成尖锐角较短的边与较长的边做垂线,构成一个直角三角形,将直角三角形擦除
        /// 
        /// 
        /// 
        /// 
        /// 
        public static IGeometry Passive_Sharp_Repair(IGeometry geometry)
        {
            List pointList = null;
            double angle1 = 0;
            try
            {
                //检查图形是否为尖锐角
                if (AECommonHelper.SharpAngleDataCheck(geometry, ref pointList, ref angle1))
                {
                    if (angle1 > 10)
                    {
                        return geometry;
                    }//仅修复图形为尖锐角的
                    if (pointList != null && pointList.Count == 3)
                    {
                        //构成尖锐角的两条边
                        IPoint pointmax = pointList[0];
                        IPolyline polylinemax = new PolylineClass();
                        polylinemax.FromPoint = pointList[0];
                        polylinemax.ToPoint = pointList[1];
                        IPoint pointmin = pointList[2];
                        IPolyline polylinemin = new PolylineClass();
                        polylinemin.FromPoint = pointList[2];
                        polylinemin.ToPoint = pointList[1];
                        IPolyline polyline_vertical = null;//获取较短的边做垂线
                        if (polylinemax.Length < polylinemin.Length)
                        {
                            IPolyline temppolylinemin = new PolylineClass();
                            temppolylinemin = polylinemax;
                            polylinemax = polylinemin;
                            polylinemin = temppolylinemin;
                            IPoint temppoint = new PointClass();
                            temppoint = pointmax;
                            pointmax = pointmin;
                            pointmin = temppoint;
                        }
                        polyline_vertical = GetPerpendicularLine(polylinemin, true, polylinemin.Length);
                        IPointCollection pPointCol = polyline_vertical as IPointCollection;
                        IPoint fPoint = new PointClass();
                        IPoint ePoint = new PointClass();
                        object missing2 = Type.Missing;
                        polyline_vertical.QueryPoint(esriSegmentExtension.esriExtendAtFrom, -1 * polylinemin.Length, false, fPoint);
                        pPointCol.InsertPoints(0, 1, ref fPoint);
                        polyline_vertical.QueryPoint(esriSegmentExtension.esriExtendAtTo, polylinemin.Length + polylinemin.Length, false, ePoint);
                        pPointCol.AddPoint(ePoint, ref missing2, ref missing2);
                        IPolyline polyline = pPointCol as IPolyline;
                        ITopologicalOperator topo = polyline_vertical as ITopologicalOperator;
                        IGeometry extendgeo = topo.Intersect(polylinemax, esriGeometryDimension.esriGeometry0Dimension);
                        IPoint point = null;
                        if (extendgeo.GeometryType == esriGeometryType.esriGeometryPoint)
                        {
                            point = extendgeo as IPoint;
                        }
                        else
                        {
                            if (extendgeo.GeometryType == esriGeometryType.esriGeometryMultipoint)
                            {
                                IPointCollection pointCollection = extendgeo as IPointCollection;
                                if (pointCollection.PointCount > 0)
                                {
                                    point = pointCollection.get_Point(0);
                                }
                                else
                                {
                                    point = pointmax;
                                }
                            }
                        }
                        List points1 = new List();
                        IGeometry geometry1 = null;
                        if (true)
                        {
                            IPoint minCenterPoint = getLineCenterPoint(polylinemin);
                            IPoint maxCenterPoint = getLineCenterPoint(polylinemax);
                            points1 = new List() { maxCenterPoint, pointList[1], minCenterPoint };
                            geometry1 = GenerateGeometryFromPoints(points1);
                        }
                        else
                        {
                            points1 = new List() { point, pointList[1], pointmin };
                            geometry1 = GenerateGeometryFromPoints(points1);
                        }
                        geometry1.SpatialReference = geometry.SpatialReference;
                        if (geometry1 == null || geometry1.IsEmpty)
                        {   //仅四个点的图斑修复异常
                            return geometry;
                        }
                        else if (!geometry1.IsEmpty && geometry1.GetEllipseArea() > 30)
                        {
                            geometry1 = AECommonHelper.IndentationGeometry(geometry, geometry1, 30);
                        }
                        else if (!geometry1.IsEmpty && geometry1.GetEllipseArea() < 0.01)
                        {
                            geometry1 = AECommonHelper.ExpandableGeometry(geometry, geometry1, 0.01);
                        }
                        geometry = FeatureAPI.Difference(geometry, geometry1);
                        if (geometry != null && !geometry.IsEmpty && AECommonHelper.SharpAngleDataCheck(geometry, ref pointList, ref angle1))
                        {
                            geometry = Passive_Sharp_Repair(geometry);
                        }
                        else
                        {
                            return geometry;
                        }
                    }
                }
                else
                {
                    return geometry;
                }
                return geometry;
            }
            catch (Exception ex)
            {
                return geometry;
            }
        }
        public static IPoint getLineCenterPoint(IPolyline pPolyline)
        {
            double d = pPolyline.Length;
            IPoint pPoint = new PointClass();
            pPolyline.QueryPoint(esriSegmentExtension.esriNoExtension, d / 1.2, false, pPoint);
            return pPoint;
        }
        /// 
        /// 获取尖锐角顶点位置外扩一段距离的垂线
        /// 
        /// 
        /// clockwise顺时针 true为顺时针/false为逆时针
        /// 
        private static IPolyline GetPerpendicularLine(IPolyline baseLine, bool clockwise, double length = 1)
        {
            // 获取baseLine的第一个点作为起点
            IPoint startPoint = baseLine.FromPoint;
            if (!startPoint.IsEmpty)
            {
                // 获取非起点的任一点
                IPoint endPoint = baseLine.ToPoint;
                // 计算向量
                double vectorX = endPoint.X - startPoint.X;
                double vectorY = endPoint.Y - startPoint.Y;
                // 旋转90度得到垂直向量
                double perpendicularX = 0;
                double perpendicularY = 0;
                if (clockwise)
                {
                    perpendicularX = -vectorY;
                    perpendicularY = vectorX;
                }
                else
                {
                    perpendicularX = vectorY;
                    perpendicularY = -vectorX;
                }
                perpendicularX *= length / Math.Sqrt(perpendicularX * perpendicularX + perpendicularY * perpendicularY);
                perpendicularY *= length / Math.Sqrt(perpendicularX * perpendicularX + perpendicularY * perpendicularY);
                // 计算垂直线的终点
                IPoint perpendicularEndPoint = new PointClass();
                perpendicularEndPoint.X = startPoint.X + perpendicularX;
                perpendicularEndPoint.Y = startPoint.Y + perpendicularY;
                // 创建并返回垂直线
                IPolyline perpendicularLine = new PolylineClass();
                IPointCollection pointCollection = perpendicularLine as IPointCollection;
                pointCollection.AddPoint(startPoint);
                pointCollection.AddPoint(perpendicularEndPoint);
                return perpendicularLine;
            }
            return null;
        }
        /// 
        /// 根据点集合生成图形
        /// 
        /// 
        /// 
        private static IGeometry GenerateGeometryFromPoints(List Points)
        {
            try
            {
                Ring ring = new RingClass();
                object missing = Type.Missing;
                IPointCollection pointCollection2 = new MultipointClass();
                if (Points != null && Points.Count == 3)
                {
                    if (Points[0] != null && Points[1] != null && Points[2] != null)//Points中不为空
                    {
                        pointCollection2.AddPoint(Points[0]);
                        pointCollection2.AddPoint(Points[1]);
                        pointCollection2.AddPoint(Points[2]);
                    }
                }
                ring.AddPointCollection(pointCollection2);
                IGeometryCollection pointPolygon = new PolygonClass();
                pointPolygon.AddGeometry(ring as IGeometry, ref missing, ref missing);
                IPolygon polyGonGeo = pointPolygon as IPolygon;
                //polyGonGeo.Close();
                polyGonGeo.SimplifyPreserveFromTo();
                return polyGonGeo as IGeometry;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion
        #region 图形操作类
        /// 
        /// 图斑外扩至“ExpandableArea”平
        /// 
        /// 参考图形
        /// 向参考图形内扩图斑
        /// 外扩至面积
        /// 
        public static IGeometry ExpandableGeometry(IGeometry geometryBG, IGeometry Insergeometry, double ExpandableArea = 30)
        {
            IGeometry TempInsergeometry = null;
            try
            {
                IGeometry geometry = null;
                ITopologicalOperator topo = Insergeometry as ITopologicalOperator;
                double WKArea = 0;
                double WKBoundary = 0.1;
                while (WKArea <= ExpandableArea)
                {
                    geometry = topo.Buffer(WKBoundary);
                    geometry = GeometryConvertHelper.ConvertWKTToIGeometry(GeometryConvertHelper.ConvertIGeoemtryToWKT(geometry));
                    TempInsergeometry = FeatureAPI.InterSect(geometryBG, geometry);
                    WKArea = TempInsergeometry.GetEllipseArea();
                    WKBoundary += 0.1;
                }
                if (geometry != null) Marshal.ReleaseComObject(geometry);
                return TempInsergeometry;
            }
            catch (Exception ex)
            {   //防止抛出异常
                LogAPI.Debug("ExpandableGeometry执行异常:" + ex.Message + ex.StackTrace);
                return TempInsergeometry ?? Insergeometry;
            }
        }
        /// 
        /// 图斑内陷至“ExpandableArea”平
        /// 
        /// 参考图形
        /// 向参考图形内扩图斑
        /// 内陷至面积
        /// 
        public static IGeometry IndentationGeometry(IGeometry geometryBG, IGeometry Insergeometry, double ExpandableArea = 30)
        {
            IGeometry geometry = EraseGeometry(geometryBG, Insergeometry);
            if (geometry.IsEmpty || geometry.GetEllipseArea() == 0)
            {
                return Insergeometry;
            }
            IGeometry TempInsergeometry = null;
            ITopologicalOperator topo = geometry as ITopologicalOperator;
            double WKArea = Insergeometry.GetEllipseArea().ToDouble(2);
            double WKBoundary = 0.1;
            while (WKArea > ExpandableArea)
            {
                geometry = topo.Buffer(WKBoundary);
                geometry = GeometryConvertHelper.ConvertWKTToIGeometry(GeometryConvertHelper.ConvertIGeoemtryToWKT(geometry));
                TempInsergeometry = FeatureAPI.Difference(Insergeometry, geometry);
                WKArea = TempInsergeometry.GetEllipseArea();
                WKBoundary += 0.2;
            }
            if (geometry != null) Marshal.ReleaseComObject(geometry);
            return TempInsergeometry;
        }
        /// 
        /// 图形操作
        /// 
        /// 被擦除项
        /// 擦除项
        /// 
        public static IGeometry EraseGeometry(IGeometry pGeo1, IGeometry pGeo2)
        {
            try
            {
                IGeometry geometTemp = FeatureAPI.InterSect(pGeo1, pGeo2);
                if (pGeo1 == null || pGeo2 == null || geometTemp == null || geometTemp.IsEmpty)
                {
                    return null;
                }
                if (pGeo1 is ITopologicalOperator topologicalOperator)
                {
                    topologicalOperator.Simplify();
                    IGeometry geometry = FeatureAPI.Difference(pGeo1, geometTemp);
                    (geometry as ITopologicalOperator).Simplify();
                    return geometry;
                }
                return null;
            }
            catch (Exception)
            {
                throw;
            }
        }
        #endregion
        #region 复制IFeature属性
        /// 
        /// 同图层图斑属性赋值
        /// 
        /// 
        /// 
        public static void CopyFeatureAtt(this IFeature tFeature, IFeature sFeature)
        {
            try
            {
                for (int i = 0; i < sFeature.Class.Fields.FieldCount; i++)
                {
                    IField field = sFeature.Class.Fields.Field[i];
                    if (!field.Editable || field.Name.ToUpper().Contains("SHAPE")) continue;
                    if (tFeature.Class.FindField(field.Name) != -1)
                        tFeature.Value[tFeature.Class.FindField(field.Name)] = sFeature.Value[i];
                }
            }
            catch (Exception ex)
            {
                LogAPI.Debug("CopyFeatureAtt执行异常:" + ex.Message);
            }
        }
        public static void CopyFeatureAtt_1(this IFeature tFeature, IFeature sFeature)
        {
            try
            {
                for (int i = 0; i < tFeature.Class.Fields.FieldCount; i++)
                {
                    IField field = tFeature.Class.Fields.Field[i];
                    if (!field.Editable || field.Name.ToUpper().Contains("SHAPE")) continue;
                    if (sFeature.Class.FindField(field.Name + "_1") != -1)
                        tFeature.Value[i] = sFeature.Value[sFeature.Class.FindField(field.Name + "_1")];
                }
            }
            catch (Exception ex)
            {
                LogAPI.Debug(ex.Message);
            }
        }
        /// 
        /// 通过基础库图斑赋值过程数据变更前属性
        /// 
        /// 
        /// 
        public static void AssignBGQFeatureAtt(this IFeature tFeature, IFeature sFeature)
        {
            try
            {
                for (int i = 0; i < sFeature.Class.Fields.FieldCount; i++)
                {
                    IField field = sFeature.Class.Fields.Field[i];
                    if (!field.Editable || field.Name.ToUpper().Contains("SHAPE")) continue;
                    if (tFeature.Class.FindField("BGQ" + field.Name) != -1)
                        tFeature.Value[tFeature.Class.FindField("BGQ" + field.Name)] = sFeature.Value[i];
                }
            }
            catch (Exception ex)
            {
                LogAPI.Debug("AssignBGQFeatureAtt执行异常:" + ex.Message);
            }
        }
        /// 
        /// 通过更新层/基础库图斑赋值过程数据变更后属性
        /// 
        /// 
        /// 
        public static void AssignBGHFeatureAtt(this IFeature tFeature, IFeature sFeature)
        {
            try
            {
                for (int i = 0; i < sFeature.Class.Fields.FieldCount; i++)
                {
                    IField field = sFeature.Class.Fields.Field[i];
                    if (!field.Editable || field.Name.ToUpper().Contains("SHAPE")) continue;
                    if (tFeature.Class.FindField("BGH" + field.Name) != -1)
                        tFeature.Value[tFeature.Class.FindField("BGH" + field.Name)] = sFeature.Value[i];
                }
            }
            catch (Exception ex)
            {
                LogAPI.Debug("AssignBGHFeatureAtt执行异常:" + ex.Message);
            }
        }
        #endregion
    }
}