public void SaveDataAreaITinEdgeLt(string strName)
        {
            var ITinEdgeLt = _pTinEdgeLt;
            var CEdgeLt    = new List <CEdge>(ITinEdgeLt.Count);

            foreach (var pTinEdge in ITinEdgeLt)
            {
                CEdgeLt.Add(new CEdge(pTinEdge));
            }

            CSaveFeature.SaveCEdgeEb(CEdgeLt, "TIN_" + strName);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="ConstraintCpllt"></param>
        /// <param name="KnownCEdgeLt"></param>
        /// <param name="strIdentity"></param>
        /// <param name="blnSave"></param>
        /// <remarks>If the "data area" is not set deliberately, then ArcEngine will set a default "data area".
        /// The default data area excludes super edges and super nodes</remarks>
        public void Triangulate(List <CPolyline> ConstraintCpllt = null, List <CEdge> KnownCEdgeLt = null,
                                string strIdentity = "", bool blnSave = false)
        {
            var cpg = _CPg;

            //cpg.pPolygon = null;


            cpg.JudgeAndSetPolygon();
            IPointCollection4 pCol = cpg.pPolygon as IPointCollection4;
            int intCount           = pCol.PointCount;
            var pEnv = cpg.pPolygon.Envelope;

            ITinEdit TinEdit = new TinClass();

            TinEdit.InitNew(pEnv);
            ITinEdit2 TinEdit2 = TinEdit as ITinEdit2;

            TinEdit2.SetToConstrainedDelaunay();  //this must be done before adding any feature
            var             pTinAdvanced2   = TinEdit as ITinAdvanced2;
            ITinFeatureEdit pTinFeatureEdit = TinEdit as ITinFeatureEdit;

            cpg.JudgeAndSetZToZero();  //we need z coordinate to construct triangulation
            pTinFeatureEdit.AddPolygonZ(cpg.pPolygon, esriTinEdgeType.esriTinHardEdge, 1, 1, 1, null);

            if (ConstraintCpllt != null)
            {
                foreach (var cpl in ConstraintCpllt)
                {
                    cpl.JudgeAndSetPolyline();
                    cpl.JudgeAndSetZToZero();
                    pTinFeatureEdit.AddPolylineZ(cpl.pPolyline, esriTinEdgeType.esriTinHardEdge, 1, 1, null);
                }
            }
            _pTinAdvanced2 = pTinAdvanced2;

            //we are not allowed to use AddShapeZ.
            //it will report that there is no Z value in the shape, even we already set Z value to 0
            //The reason may be that we actually need polyhedron
            //TinEdit.AddShapeZ((IGeometry)cpg.pPolygon, esriTinSurfaceType.esriTinHardClip, 0);
            //********************************************
            //this function set the "data area" of the TIN,
            //we avoid to use this function because it may introduce new points
            //the new poins can be very close to the original points
            //TinEdit.AddShape((IGeometry)cpg.pPolygon, esriTinSurfaceType.esriTinHardClip, 0);
            //TinEdit.Refresh();


            if (pTinAdvanced2.DataNodeCount != this.CptLt.Count)
            {
                //Usually, KnownCEdgeLt saves all the constraints for the triangulation
                CSaveFeature.SaveCEdgeEb(KnownCEdgeLt, "KnownCEdgeLt" + strIdentity);
                CSaveFeature.SaveCptEb(this.CptLt, "CptLtForKnownCEdgeLt" + strIdentity);

                var NodeCptLt = GetCptLtFromTinAdvanced(pTinAdvanced2, true);
                CSaveFeature.SaveCptEb(NodeCptLt, "TinNode" + strIdentity);
                //var TinCEdgeLt= get
                var ExtraNodeCptLt = new List <CPoint>(pTinAdvanced2.DataNodeCount - this.CptLt.Count);
                foreach (var nodeCpt in NodeCptLt)
                {
                    if (this.CptSD.ContainsKey(nodeCpt) == false)
                    {
                        ExtraNodeCptLt.Add(nodeCpt);
                    }
                }
                CSaveFeature.SaveCptEb(ExtraNodeCptLt, "ExtraNodeCptLt" + strIdentity);

                var TinCEdgeLt = GetCEdgeLtFromTinAdvanced(pTinAdvanced2);
                CSaveFeature.SaveCEdgeEb(TinCEdgeLt, "TinCEdgeLt" + strIdentity);

                throw new ArgumentException("the numbers of points should be the same!");
            }
            this.CptLt.SetIndexID();


            var ITinEdgeLt = GenerateITinEdgeLt();
            var tincedgeSS = new SortedSet <CEdge>(new CCmpEdge_CptGID_BothDirections());
            var tincedgelt = new List <CEdge>();

            if (KnownCEdgeLt != null)
            {
                tincedgeSS = new SortedSet <CEdge>(KnownCEdgeLt, new CCmpEdge_CptGID_BothDirections());
                tincedgelt.AddRange(KnownCEdgeLt);
            }

            cpg.SetAxisAngleAndReverseLt();
            var cptSD = this.CptSD;

            foreach (var tinedge in ITinEdgeLt)
            {
                //there are always a pair of edges between a pair of triangles, but we only need one edge.
                //So we reverse some edges than we can delete one edge of each pair
                var pFrNode = tinedge.FromNode;
                var pToNode = tinedge.ToNode;

                CPoint frcpt, tocpt;
                FindCorrCptInSDByTinNode(pFrNode, cptSD, out frcpt);
                FindCorrCptInSDByTinNode(pToNode, cptSD, out tocpt);

                CEdge newCEdge;
                if (frcpt.indexID < tocpt.indexID)
                {
                    newCEdge = new CEdge(frcpt, tocpt);
                }
                else if (frcpt.indexID > tocpt.indexID)
                {
                    newCEdge = new CEdge(tocpt, frcpt);
                }
                else
                {
                    throw new ArgumentException("should not happen!");
                }

                //test if the new edge is outside the boundary polygon (cpg)
                if (newCEdge.FrCpt.indexID < cpg.CEdgeLt.Count)
                {
                    //the new edge starts from a point which constitues the boundary polygon (cpg)
                    newCEdge.SetAxisAngle();
                    if (CGeoFunc.IsInbetween_Counterclockwise(cpg.AxisAngleLt[newCEdge.FrCpt.indexID],
                                                              newCEdge.dblAxisAngle, cpg.ReverseAxisAngleLt[newCEdge.FrCpt.indexID]) == false)
                    {
                        //the new edge is outside the boundary polygon (cpg)
                        continue;
                    }
                }

                //add the new edge if the edge is not added yet
                if (tincedgeSS.Add(newCEdge))
                {
                    this.NewCEdgeLt.Add(newCEdge);
                    tincedgelt.Add(newCEdge);
                }
            }

            if (blnSave == true)
            {
                CSaveFeature.SaveCEdgeEb(tincedgelt, "tincedgelt" + strIdentity, blnVisible: false);
            }

            this.CEdgeLt = tincedgelt;
        }