public static bool IsCutValid(List <CPoint> cptlt, CEdgeGrid pEdgeGrid,
                                      double dblThreshold, out int intIndexMaxDis)
        {
            var tplWithinTDis = IsWithinTDis(cptlt, dblThreshold);

            intIndexMaxDis = tplWithinTDis.Item2;
            if (tplWithinTDis.Item1 == false)
            {
                return(false);
            }

            //if the baseline is outside of the polygon, then the baseline is not a valid choice
            throw new ArgumentException(
                      "IsClockwise is not helpful. instead test if the edge between the two edges. see CCptbCtgl");
            if (CGeoFunc.IsClockwise(cptlt, false) == false)
            {
                return(false);
            }

            var cedgebaseline = new CEdge(cptlt[0], cptlt.Last());
            //we don't test the four edges
            var IgnoreCEdgeSS = new SortedSet <CEdge>
            {
                cedgebaseline.FrCpt.InCEdge,
                cedgebaseline.FrCpt.OutCEdge,
                cedgebaseline.ToCpt.InCEdge,
                cedgebaseline.ToCpt.OutCEdge
            };
            var blnIntersect = pEdgeGrid.BlnIntersect(cedgebaseline, true, true, true, IgnoreCEdgeSS);

            return(!blnIntersect);
        }
        /// <summary>
        /// we can improve by saving a pEdgeGrid for every orginal cpg; ********************************
        /// for the EnlargedCEdgeHS, we make another pEdgeGrid ********************************
        /// </summary>
        /// <param name="cptlt"></param>
        /// <param name="OriginalCEdgeLt"></param>
        /// <param name="EnlargedCEdgeHS"></param>
        /// <param name="dblThreshold"></param>
        /// <returns></returns>
        private static IEnumerable <CPoint> ImaiIriSimplifyAccordExistEdges(List <CPoint> cptlt,
                                                                            List <CEdge> OriginalCEdgeLt, HashSet <CEdge> EnlargedCEdgeHS, double dblThreshold)
        {
            if (cptlt.Count <= 1)
            {
                throw new ArgumentOutOfRangeException("There is no points for simplification!");
            }
            else if (cptlt.Count == 2)
            {
                yield return(cptlt[0]);

                yield return(cptlt[1]);
            }
            else
            {
                var allcedgelt = new List <CEdge>(OriginalCEdgeLt);
                allcedgelt.AddRange(EnlargedCEdgeHS);
                var pEdgeGrid = new CEdgeGrid(allcedgelt);

                var CNodeLt = new List <CNode>(cptlt.Count);
                CNodeLt.EveryElementNew();
                CNodeLt.SetIndexID();
                for (int i = 0; i < cptlt.Count - 1; i++)
                {
                    CNodeLt[i].NbrCNodeLt = new List <CGeometry.CNode>();
                    CNodeLt[i].NbrCNodeLt.Add(CNodeLt[i + 1]);
                    for (int j = i + 2; j < cptlt.Count; j++)
                    {
                        var subcptlt = cptlt.GetRange(i, j - i + 1);
                        int intIndexMaxdis;
                        if (IsCutValid(subcptlt, pEdgeGrid, dblThreshold, out intIndexMaxdis))
                        {
                            CNodeLt[i].NbrCNodeLt.Add(CNodeLt[j]);
                        }
                    }
                }

                CImaiIriSimplify.BFS(CNodeLt[0], CNodeLt.Last());
                var currentCNode = CNodeLt[0];
                while (currentCNode != null)
                {
                    yield return(cptlt[currentCNode.indexID]);

                    currentCNode = currentCNode.NextCNode;
                }
            }
        }
        ////*******************check the codes below***************************
        ////****************** should we keep at least three points?
        /// <summary>
        /// for an exterior ring, cptlt should be clockwise; for a hole, cptlt should be counter clockwise
        /// </summary>
        private static IEnumerable <CPoint> DPSimplifyAccordExistEdges(List <CPoint> cptlt,
                                                                       List <CEdge> OriginalCEdgeLt, HashSet <CEdge> EnlargedCEdgeHS, double dblThreshold)
        {
            if (cptlt.Count <= 1)
            {
                throw new ArgumentOutOfRangeException("There is no points for simplification!");
            }
            else if (cptlt.Count == 2)
            {
                yield return(cptlt[0]);

                yield return(cptlt[1]);
            }
            else
            {
                var allcedgelt = new List <CEdge>(OriginalCEdgeLt);
                allcedgelt.AddRange(EnlargedCEdgeHS);
                var pEdgeGrid = new CEdgeGrid(allcedgelt);

                var IndexSk = new Stack <CValPair <int, int> >();
                IndexSk.Push(new CValPair <int, int>(0, cptlt.Count - 1));

                do
                {
                    var StartEndVP = IndexSk.Pop();

                    var subcptlt = cptlt.GetRange(StartEndVP.val1, StartEndVP.val2 - StartEndVP.val1 + 1);
                    int intIndexMaxdis;
                    if (subcptlt.Count <= 2 || IsCutValid(subcptlt, pEdgeGrid, dblThreshold, out intIndexMaxdis))
                    {
                        yield return(cptlt[StartEndVP.val1]);
                    }
                    else
                    {
                        IndexSk.Push(new CValPair <int, int>(intIndexMaxdis + StartEndVP.val1, StartEndVP.val2));
                        IndexSk.Push(new CValPair <int, int>(StartEndVP.val1, intIndexMaxdis + StartEndVP.val1));
                    }
                } while (IndexSk.Count > 0);
                yield return(cptlt.Last());
            }
        }
        public void TopologyCheck()
        {
            var          ParameterInitialize = _ParameterInitialize;
            List <CEdge> pAllReadCEdgeLt     = _AllReadCEdgeLt;

            long lngStartTime = System.Environment.TickCount;

            double dblVerySmall = CConstants.dblVerySmallCoord;

            throw new ArgumentException("consider setting of dblverysmall!");
            for (int i = 0; i < 10; i++)
            {
                CConstants.dblVerySmallCoord = dblVerySmall / Math.Pow(10, i - 5);
                var fEdgeGrid      = new CEdgeGrid(pAllReadCEdgeLt);
                var IntersectionLt = fEdgeGrid.DetectIntersectionsOfExistingEdges(true, true, true);

                foreach (var cedge in pAllReadCEdgeLt)
                {
                    cedge.FrCpt.IntersectionLt = new List <CIntersection>();
                    cedge.ToCpt.IntersectionLt = new List <CIntersection>();

                    cedge.FrCpt.isTraversed = false;
                    cedge.ToCpt.isTraversed = false;
                }

                List <CPoint> CrossCptLt = new List <CPoint>();
                //List<CEdge> OverlapEdgeLt = new List<CEdge>();  //to save memory, we don't record overlap edges anymore, instead, we only record an end of the overlap edge
                List <CPoint> OverlapCptLt = new List <CPoint>();
                foreach (CIntersection pIntersection in IntersectionLt)
                {
                    switch (pIntersection.enumIntersectionType)
                    {
                    case CEnumIntersectionType.NoNo:
                        break;

                    case CEnumIntersectionType.FrFr:
                        pIntersection.CEdge1.FrCpt.IntersectionLt.Add(pIntersection);       //End Intersection
                        pIntersection.CEdge2.FrCpt.IntersectionLt.Add(pIntersection);       //End Intersection
                        break;

                    case CEnumIntersectionType.FrIn:
                        //CrossCptLt.AddLast(pIntersection.IntersectCpt);     //Cross
                        //pIntersection.CEdge1.FrCpt.IntersectionLt.Add(pIntersection);   //we don't want to notice this intersection twice, so we add this intersection to the vertice
                        break;

                    case CEnumIntersectionType.FrTo:
                        pIntersection.CEdge1.FrCpt.IntersectionLt.Add(pIntersection);       //End Intersection
                        pIntersection.CEdge2.ToCpt.IntersectionLt.Add(pIntersection);       //End Intersection
                        break;

                    case CEnumIntersectionType.InFr:
                        //CrossCptLt.AddLast(pIntersection.IntersectCpt);     //Cross
                        //pIntersection.CEdge2.FrCpt.IntersectionLt.Add(pIntersection);   //we don't want to notice this intersection twice, so we add this intersection to the vertice
                        break;

                    case CEnumIntersectionType.InIn:
                        CrossCptLt.Add(pIntersection.IntersectCpt);         //Cross
                        break;

                    case CEnumIntersectionType.InTo:
                        //CrossCptLt.AddLast(pIntersection.IntersectCpt);     //Cross
                        //pIntersection.CEdge2.ToCpt.IntersectionLt.Add(pIntersection);   //we don't want to notice this intersection twice, so we add this intersection to the vertice
                        break;

                    case CEnumIntersectionType.ToFr:
                        pIntersection.CEdge1.ToCpt.IntersectionLt.Add(pIntersection);       //End Intersection
                        pIntersection.CEdge2.FrCpt.IntersectionLt.Add(pIntersection);       //End Intersection
                        break;

                    case CEnumIntersectionType.ToIn:
                        //CrossCptLt.AddLast(pIntersection.IntersectCpt);     //Cross
                        //pIntersection.CEdge1.ToCpt.IntersectionLt.Add(pIntersection);   //we don't want to notice this intersection twice, so we add this intersection to the vertice
                        break;

                    case CEnumIntersectionType.ToTo:
                        pIntersection.CEdge1.ToCpt.IntersectionLt.Add(pIntersection);       //End Intersection
                        pIntersection.CEdge2.ToCpt.IntersectionLt.Add(pIntersection);       //End Intersection
                        break;

                    case CEnumIntersectionType.Overlap:
                        //OverlapEdgeLt.Add(pIntersection.OverlapCEdge);
                        OverlapCptLt.Add(pIntersection.IntersectCpt);
                        //pIntersection.OverlapCEdge.FrCpt.IntersectionLt.Add(pIntersection);   //we don't want to notice this intersection twice, so we add this intersection to the vertice
                        //pIntersection.OverlapCEdge.ToCpt.IntersectionLt.Add(pIntersection);   //we don't want to notice this intersection twice, so we add this intersection to the vertice
                        break;

                    default:
                        break;
                    }
                }
                CConstants.dblVerySmallCoord = dblVerySmall;

                List <CPoint> UnLinkedCptLt = new List <CPoint>();
                foreach (var cedge in pAllReadCEdgeLt)
                {
                    if (cedge.FrCpt.isTraversed == false && cedge.FrCpt.IntersectionLt.Count == 0)
                    {
                        UnLinkedCptLt.Add(cedge.FrCpt);
                    }

                    if (cedge.ToCpt.isTraversed == false && cedge.ToCpt.IntersectionLt.Count == 0)
                    {
                        UnLinkedCptLt.Add(cedge.ToCpt);
                    }

                    cedge.FrCpt.IntersectionLt = null;
                    cedge.ToCpt.IntersectionLt = null;

                    cedge.FrCpt.isTraversed = true;
                    cedge.ToCpt.isTraversed = true;
                }

                IntersectionLt = null;

                CSaveFeature.SaveCGeoEb(UnLinkedCptLt, esriGeometryType.esriGeometryPoint,
                                        "UnLinkedCpt_" + i.ToString() + "__" + UnLinkedCptLt.Count, blnVisible: false);
                CHelpFunc.SetAEGeometryNull(UnLinkedCptLt);

                CSaveFeature.SaveCGeoEb(CrossCptLt, esriGeometryType.esriGeometryPoint,
                                        "Crosses_" + i.ToString() + "__" + CrossCptLt.Count, blnVisible: false);
                CHelpFunc.SetAEGeometryNull(CrossCptLt);

                CSaveFeature.SaveCGeoEb(OverlapCptLt, esriGeometryType.esriGeometryPoint,
                                        "OverlapCpt_" + i.ToString() + "__" + OverlapCptLt.Count, blnVisible: false);
                CHelpFunc.SetAEGeometryNull(OverlapCptLt);
            }

            long lngEndTime = System.Environment.TickCount;                                                            //记录结束时间

            ParameterInitialize.tsslTime.Text = "Running Time: " + Convert.ToString(lngEndTime - lngStartTime) + "ms"; //显示运行时
        }