コード例 #1
0
        private List <CPoint> GetCptLtFromTinAdvanced(ITinAdvanced2 ptinadvanced2, bool blnDataArea = true)
        {
            var ITinNodeLt = GetITinNodeLt(ptinadvanced2, blnDataArea);
            var CptLt      = new List <CPoint>(ITinNodeLt.Count);

            foreach (var ptinNode in ITinNodeLt)
            {
                CptLt.Add(new CPoint(ptinNode));
            }
            return(CptLt);
        }
コード例 #2
0
        private List <CEdge> GetCEdgeLtFromTinAdvanced(ITinAdvanced2 ptinadvanced2, bool blnDataArea = true)
        {
            var ITinEdgeLt = GenerateITinEdgeLt(blnDataArea);
            var CEdgeLt    = new List <CEdge>(ITinEdgeLt.Count);

            foreach (var ptinEdge in ITinEdgeLt)
            {
                CEdgeLt.Add(new CEdge(ptinEdge));
            }
            return(CEdgeLt);
        }
コード例 #3
0
        //根据创建的点要素做tin
        public void CreatTINs()
        {
            Type factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.FileGDBWorkspaceFactory");
            IWorkspaceFactory workspaceFactory = (IWorkspaceFactory)Activator.CreateInstance(factoryType);

            Workspace = workspaceFactory.OpenFromFile(workspacepath, 0);
            IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)Workspace;

            //new tin 的范围
            tin = new TinClass();
            tin.Init(tinpath);
            IEnvelope EnvO = tin.Extent;
            IEnvelope Env  = new EnvelopeClass();

            Env.XMax = EnvO.XMax + 10;
            Env.YMax = EnvO.YMax + 10;
            Env.ZMax = EnvO.ZMax + 100;
            Env.XMin = EnvO.XMin + 10;
            Env.YMin = EnvO.YMin + 10;
            Env.ZMin = EnvO.ZMin + 100;

            // Instantiate a new empty TIN.
            ITinEdit[] TinEdit   = new ITinEdit[SurfaceCount + 1];
            object     overwrite = true;

            for (int i = 0; i < SurfaceCount + 1; i++)
            {
                TinEdit[i] = new TinClass();
                TinEdit[i].InitNew(Env);
                TinEdit[i].SaveAs(OutTinPath + "_" + i, ref overwrite);
            }

            IFeatureClass[] ISOpointFeatureClass = new IFeatureClass[SurfaceCount + 1];
            for (int i = 0; i < SurfaceCount + 1; i++)
            {
                ISOpointFeatureClass[i] = featureWorkspace.OpenFeatureClass("Node_" + i);
                IGeometryCollection MultipointGeometryCollection = new MultipointClass();
                MakeZAware(MultipointGeometryCollection as IGeometry);
                for (int p = 0; p < NodeCount - 4; p++)
                {
                    IPoint onePoint = ISOpointFeatureClass[i].GetFeature(p + 1).Shape as IPoint;
                    MakeZAware(onePoint);
                    MultipointGeometryCollection.AddGeometry(onePoint);
                }
                (TinEdit[i] as ITinEdit2).SetToConstrainedDelaunay();
                TinEdit[i].AddShapeZ(MultipointGeometryCollection as IGeometry, esriTinSurfaceType.esriTinMassPoint, 0, _missing);
                TinEdit[i].Save();
            }
        }
コード例 #4
0
        //曲率熵
        //参数已排序
        public static double Entropy(ITinNode ENode, double[] ECurvature, ITinAdvanced2 Etin)
        {
            //曲率值绝对值化
            int ELength = ECurvature.Length;

            double[] AbsE = new double[ELength];
            for (int i = 0; i < ELength; i++)
            {
                AbsE[i] = Math.Abs(ECurvature[i]);
            }
            //得到该点某曲率绝对值
            int    u  = MNodeLocation(ENode);
            double Ki = AbsE[u];
            //得到一阶领域点曲率绝对值
            ITinNodeArray ENodeArray = GetIncidentNodes(ENode, VectorModel.NodeRange);
            int           ENodeCount = ENodeArray.Count;

            double[] Kj = new double[ENodeCount];
            for (int i = 0; i < ENodeCount; i++)
            {
                ITinNode ENearNode = ENodeArray.get_Element(i);
                int      v         = MNodeLocation(ENearNode);
                Kj[i] = AbsE[v];
            }
            double KSum = Ki;

            for (int i = 0; i < ENodeCount; i++)
            {
                KSum = KSum + Kj[i];
            }
            double Pi = Ki / KSum;

            double[] Pj = new double[ENodeCount];
            for (int i = 0; i < ENodeCount; i++)
            {
                Pj[i] = Kj[i] / KSum;
            }
            double Hi = -Pi *Math.Log(Pi, 2);

            for (int i = 0; i < ENodeCount; i++)
            {
                Hi = Hi - Pj[i] * Math.Log(Pj[i], 2);
            }
            return(Hi);
        }
コード例 #5
0
        public List <ITinEdge> GenerateITinEdgeLt(bool blnDataArea = true)
        {
            ITinAdvanced2 ptinadvanced2 = _pTinAdvanced2;
            var           ITinEdgeLt    = new List <ITinEdge>(ptinadvanced2.EdgeCount);

            for (int i = 0; i < ptinadvanced2.EdgeCount; i++)
            {
                ITinEdge ptinedge = ptinadvanced2.GetEdge(i + 1);
                if (blnDataArea == true)
                {
                    if (ptinedge.IsInsideDataArea)
                    {
                        ITinEdgeLt.Add(ptinedge);
                    }
                }
                else
                {
                    ITinEdgeLt.Add(ptinedge);
                }
            }
            _pTinEdgeLt = ITinEdgeLt;
            return(ITinEdgeLt);
        }
コード例 #6
0
        private List <ITinNode> GetITinNodeLt(ITinAdvanced2 ptinadvanced2, bool blnDataArea = true)
        {
            var ITinNodeLt = new List <ITinNode>(ptinadvanced2.NodeCount);

            for (int i = 0; i < ptinadvanced2.NodeCount; i++)
            {
                var ptinnode = ptinadvanced2.GetNode(i + 1);

                if (blnDataArea == true)
                {
                    if (ptinnode.IsInsideDataArea)
                    {
                        ITinNodeLt.Add(ptinnode);
                    }
                }
                else
                {
                    ITinNodeLt.Add(ptinnode);
                }
            }
            //_pTinEdgeLt = ITinEdgeLt;
            return(ITinNodeLt);
        }
コード例 #7
0
        public void GetTinData(int TinID)
        {
            Type factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.FileGDBWorkspaceFactory");
            IWorkspaceFactory workspaceFactory = (IWorkspaceFactory)Activator.CreateInstance(factoryType);

            Workspace = workspaceFactory.OpenFromFile(workSpacePath, 0);
            // Open an existing TIN, edit the following path as appropriate.
            tinU = new TinClass();
            tinU.Init(UpSurfacePath + TinID);
            tinD = new TinClass();
            tinD.Init(DownSurfacePath + TinID);
            tinUmax = new TinClass();
            tinUmax.Init(maxUpSurfacePath);
            tinDmin = new TinClass();
            tinDmin.Init(minDownSurfacePath);
            IEnvelope EnvelopeU = tinUmax.Extent;
            IEnvelope EnvelopeD = tinDmin.Extent;
            double    MZMax     = EnvelopeU.ZMax;
            double    MZMin     = EnvelopeD.ZMin;

            XMin       = EnvelopeU.XMin;
            XMax       = EnvelopeU.XMax;
            YMin       = EnvelopeU.YMin;
            YMax       = EnvelopeU.YMax;
            ZMax       = MZMax + AddBoundry;
            ZMin       = MZMin - AddBoundry;
            RowCount   = (int)((XMax - XMin + 0.5 * RasterSize) / RasterSize) + 1;
            Llength    = XMax - XMin;
            Wlength    = YMax - YMin;
            Hlength    = ZMax - ZMin;
            BoxVolume  = Llength * Wlength * Hlength;
            NodeCount  = tinDmin.NodeCount;
            orderNodeU = new ITinNode[NodeCount];
            orderNodeD = new ITinNode[NodeCount];
            TINID      = TinID;
        }
コード例 #8
0
        /// <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;
        }
コード例 #9
0
        public void CreateNode()
        {
            Type factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.FileGDBWorkspaceFactory");
            IWorkspaceFactory workspaceFactory = (IWorkspaceFactory)Activator.CreateInstance(factoryType);

            Workspace = workspaceFactory.OpenFromFile(workspacepath, 0);
            // Open an existing TIN, edit the following path as appropriate.
            tin = new TinClass();
            tin.Init(tinpath);
            Borehole = new StreamWriter(boreholepath);
            //得到和tin网直接相关的数据
            IEnvelope Envelope = tin.Extent;

            XMin = Envelope.XMin;
            XMax = Envelope.XMax;
            YMin = Envelope.YMin;
            YMax = Envelope.YMax;
            //列数
            RowCount  = (int)((XMax - XMin + 0.5 * RasterSize) / RasterSize) + 1;
            NodeCount = tin.NodeCount;
            //钻孔总点数
            DenseCount = (int)HalfBoreLength * 2 * density;

            //点间距
            Double Dstep = 1.0 / density;

            OSNodes  = new ITinNode[NodeCount];
            OSPoints = new IPoint[NodeCount];
            for (int i = 4; i < NodeCount; i++)
            {
                //得到按序排列的初始曲面节点
                ITinNode OSNode = tin.GetNode(i + 1);
                int      v      = (int)((OSNode.X - (XMin - (RasterSize / 2))) / RasterSize) + RowCount * (int)((OSNode.Y - (YMin - (RasterSize / 2))) / (RasterSize));
                OSNodes[v]  = OSNode;
                OSPoints[v] = new PointClass();
                MakeZAware(OSPoints[v]);
                OSNode.QueryAsPoint(OSPoints[v]);
            }

            //一根中心在原点的密集点柱
            double Zinitial = 0;
            double Zlow     = Zinitial - HalfBoreLength;

            DensePoints = new IPoint[DenseCount];
            for (int j = 0; j < DenseCount; j++)
            {
                double thisZ         = Zlow + j * Dstep;
                IPoint OneDensePoint = new PointClass();
                MakeZAware(OneDensePoint);
                OneDensePoint.X = 0;
                OneDensePoint.Y = 0;
                OneDensePoint.Z = thisZ;
                DensePoints[j]  = OneDensePoint;
            }

            //得到揭露Fd的钻孔编号的索引
            string[] XYLine = File.ReadAllLines(XYpath);
            BoreCount = XYLine.Length;
            BoreXY    = new double[BoreCount, 2];
            int l = 0;

            for (int j = 0; j < BoreCount; j++)
            {
                string   m      = XYLine[j];
                string   M      = new System.Text.RegularExpressions.Regex("[\\s]+").Replace(m, " ");
                string[] mArray = M.Split(' ');
                BoreXY[j, 0] = Convert.ToDouble(mArray[2]);
                BoreXY[j, 1] = Convert.ToDouble(mArray[1]);
                string ChangA = Convert.ToString(mArray[0]);
                //if ((ChangA == SelectBore1) || (ChangA == SelectBore2) || (ChangA == SelectBore3))
                if ((ChangA == SelectBore1))
                {
                    boreLocationChangeA[l] = j;
                    l++;
                }
            }
        }
コード例 #10
0
        public void DEMToTIN(IRaster iRaster, string tinFileName)
        {
            try
            {
                //***************生成TIN模型*********************************************
                IGeoDataset           pGeoData   = iRaster as IGeoDataset;
                IEnvelope             pExtent    = pGeoData.Extent;
                IRasterBandCollection pRasBC     = iRaster as IRasterBandCollection;
                IRasterBand           pRasBand   = pRasBC.Item(0);
                IRawPixels            pRawPixels = pRasBand as IRawPixels;
                IRasterProps          pProps     = pRawPixels as IRasterProps;
                int    iWid       = pProps.Width;
                int    iHei       = pProps.Height;
                double w          = iWid / 1000.0f;
                double h          = iHei / 1000.0f;
                IPnt   pBlockSize = new DblPntClass();
                bool   IterationFlag;

                if (w < 1 && h < 1) //横纵都小于1000个像素
                {
                    pBlockSize.X  = iWid;
                    pBlockSize.Y  = iHei;
                    IterationFlag = false;
                }
                else
                {
                    pBlockSize.X  = 1001.0f;
                    pBlockSize.Y  = 1001.0f;
                    IterationFlag = true;
                }
                double cellsize = 0.0f;             //栅格大小

                IPnt pPnt1 = pProps.MeanCellSize(); //栅格平均大小
                cellsize = pPnt1.X;
                ITinEdit pTinEdit = new TinClass() as ITinEdit;
                pTinEdit.InitNew(pExtent);
                ISpatialReference pSpatial = pGeoData.SpatialReference;
                pExtent.SpatialReference = pSpatial;
                IPnt pOrigin           = new DblPntClass();
                IPnt pPixelBlockOrigin = new DblPntClass();
                //栅格左上角像素中心坐标
                double bX = pBlockSize.X;
                double bY = pBlockSize.Y;
                pBlockSize.SetCoords(bX, bY);
                IPixelBlock   pPixelBlock   = pRawPixels.CreatePixelBlock(pBlockSize);
                object        nodata        = pProps.NoDataValue; //无值标记
                ITinAdvanced2 pTinNodeCount = pTinEdit as ITinAdvanced2;
                int           nodeCount     = pTinNodeCount.NodeCount;
                object        vtMissing     = Type.Missing;
                object        vPixels       = null; //格子
                double        m_zTolerance  = 0;
                if (!IterationFlag)                 //当为一个处理单元格子时;(w < 1 && h < 1) //横纵都小于1000个像素
                {
                    pPixelBlockOrigin.SetCoords(0.0f, 0.0f);
                    pRawPixels.Read(pPixelBlockOrigin, pPixelBlock);
                    vPixels = pPixelBlock.get_SafeArray(0);
                    double xMin = pExtent.XMin;
                    double yMax = pExtent.YMax;
                    pOrigin.X = xMin + cellsize / 2;
                    pOrigin.Y = yMax - cellsize / 2;
                    bX        = pOrigin.X;
                    bY        = pOrigin.Y;
                    pTinEdit.AddFromPixelBlock(bX, bY, cellsize, cellsize, nodata, vPixels, m_zTolerance, ref vtMissing, out vtMissing);
                }
                else //当有多个处理单元格时,依次循环处理每个单元格
                {
                    int i = 0, j = 0, count = 0;
                    int FirstGoNodeCount = 0;

                    //while (nodeCount != FirstGoNodeCount)
                    //{
                    count++;
                    nodeCount = pTinNodeCount.NodeCount;
                    int bwidth = 0; int bheight = 0;
                    //依次循环处理
                    for (i = 0; i < (int)h + 1; i++)
                    {
                        if (i < (int)h)
                        {
                            bheight = 1000;
                        }
                        else
                        {
                            bheight = iHei - 1000 * i;
                        }
                        for (j = 0; j < (int)w + 1; j++)
                        {
                            if (j < (int)w)
                            {
                                bwidth = 1000;
                            }
                            else
                            {
                                bwidth = iWid - 1000 * j;
                            }
                            pBlockSize.SetCoords(bwidth, bheight);
                            pPixelBlock = pRawPixels.CreatePixelBlock(pBlockSize);


                            double bX1, bY1, xMin1, yMax1;
                            bX1 = pBlockSize.X;
                            bY1 = pBlockSize.Y;
                            pPixelBlockOrigin.SetCoords(j * 1000, i * 1000);

                            pRawPixels.Read(pPixelBlockOrigin, pPixelBlock);
                            vPixels = pPixelBlock.get_SafeArray(0);
                            xMin1   = pExtent.XMin;
                            yMax1   = pExtent.YMax;
                            //bX1 = pBlockSize.X;
                            //bY1 = pBlockSize.Y;
                            pOrigin.X = xMin1 + j * 1000 * cellsize + cellsize / 2.0f;
                            pOrigin.Y = yMax1 - i * 1000 * cellsize - cellsize / 2.0f;
                            bX1       = pOrigin.X;
                            bY1       = pOrigin.Y;
                            pTinEdit.AddFromPixelBlock(bX1, bY1, cellsize, cellsize, nodata, vPixels, m_zTolerance, ref vtMissing, out vtMissing);
                            FirstGoNodeCount = pTinNodeCount.NodeCount;
                        }
                    }
                    //}
                }
                //保存TIN文件
                pTinEdit.SaveAs(tinFileName, ref vtMissing);
                pTinEdit.StopEditing(true);
                m_pTin = pTinEdit as ITin;
                MessageBox.Show("转换成功!");
            }
            catch (SystemException e)
            {
                MessageBox.Show(e.Message);
            }
        }
コード例 #11
0
        public void Execute(IArray paramvalues, ITrackCancel trackcancel, IGPEnvironmentManager envMgr, IGPMessages message)
        {
            // Get Parameters
            IGPParameter3 inputParameter   = (IGPParameter3)paramvalues.get_Element(0);
            IGPParameter3 polygonParameter = (IGPParameter3)paramvalues.get_Element(1);
            IGPParameter3 outputParameter  = (IGPParameter3)paramvalues.get_Element(2);
            IGPParameter3 fieldParameter   = (IGPParameter3)paramvalues.get_Element(3);

            // UnPackGPValue. This ensures you get the value from either the dataelement or GpVariable (ModelBuilder)
            IGPValue inputParameterValue   = m_GPUtilities.UnpackGPValue(inputParameter);
            IGPValue polygonParameterValue = m_GPUtilities.UnpackGPValue(polygonParameter);
            IGPValue outputParameterValue  = m_GPUtilities.UnpackGPValue(outputParameter);
            IGPValue fieldParameterValue   = m_GPUtilities.UnpackGPValue(fieldParameter);

            // Decode Input Feature Layers
            IFeatureClass inputFeatureClass;
            IFeatureClass polygonFeatureClass;

            IQueryFilter inputFeatureClassQF;
            IQueryFilter polygonFeatureClassQF;

            m_GPUtilities.DecodeFeatureLayer(inputParameterValue, out inputFeatureClass, out inputFeatureClassQF);
            m_GPUtilities.DecodeFeatureLayer(polygonParameterValue, out polygonFeatureClass, out polygonFeatureClassQF);

            if (inputFeatureClass == null)
            {
                message.AddError(2, "Could not open input dataset.");
                return;
            }

            if (polygonFeatureClass == null)
            {
                message.AddError(2, "Could not open clipping polygon dataset.");
                return;
            }

            if (polygonFeatureClass.FeatureCount(null) > 1)
            {
                message.AddWarning("Clipping polygon feature class contains more than one feature.");
            }

            // Create the Geoprocessor
            Geoprocessor gp = new Geoprocessor();

            // Create Output Polygon Feature Class
            CreateFeatureclass cfc      = new CreateFeatureclass();
            IName               name    = m_GPUtilities.CreateFeatureClassName(outputParameterValue.GetAsText());
            IDatasetName        dsName  = name as IDatasetName;
            IFeatureClassName   fcName  = dsName as IFeatureClassName;
            IFeatureDatasetName fdsName = fcName.FeatureDatasetName as IFeatureDatasetName;

            // Check if output is in a FeatureDataset or not. Set the output path parameter for CreateFeatureClass tool.
            if (fdsName != null)
            {
                cfc.out_path = fdsName;
            }
            else
            {
                cfc.out_path = dsName.WorkspaceName.PathName;
            }

            // Set the output Coordinate System for CreateFeatureClass tool.
            // ISpatialReference3 sr = null;
            IGPEnvironment env = envMgr.FindEnvironment("outputCoordinateSystem");

            // Same as Input
            if (env.Value.IsEmpty())
            {
                IGeoDataset ds = inputFeatureClass as IGeoDataset;
                cfc.spatial_reference = ds.SpatialReference as ISpatialReference3;
            }
            // Use the environment setting
            else
            {
                IGPCoordinateSystem cs = env.Value as IGPCoordinateSystem;
                cfc.spatial_reference = cs.SpatialReference as ISpatialReference3;
            }

            // Remaining properties for Create Feature Class Tool
            cfc.out_name      = dsName.Name;
            cfc.geometry_type = "POLYGON";

            // Execute Geoprocessor
            gp.Execute(cfc, null);

            // Get Unique Field
            int    iField      = inputFeatureClass.FindField(fieldParameterValue.GetAsText());
            IField uniqueField = inputFeatureClass.Fields.get_Field(iField);

            // Extract Clipping Polygon Geometry
            IFeature polygonFeature  = polygonFeatureClass.GetFeature(0);
            IPolygon clippingPolygon = (IPolygon)polygonFeature.Shape;

            // Spatial Filter
            ISpatialFilter spatialFilter = new SpatialFilterClass();

            spatialFilter.Geometry   = polygonFeature.ShapeCopy;
            spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains;

            // Debug Message
            message.AddMessage("Generating TIN...");

            // Create TIN
            ITinEdit tinEdit = new TinClass();

            // Advanced TIN Functions
            ITinAdvanced2 tinAdv = (ITinAdvanced2)tinEdit;

            try
            {
                // Initialize New TIN
                IGeoDataset gds = inputFeatureClass as IGeoDataset;
                tinEdit.InitNew(gds.Extent);

                // Add Mass Points to TIN
                tinEdit.StartEditing();
                tinEdit.AddFromFeatureClass(inputFeatureClass, spatialFilter, uniqueField, uniqueField, esriTinSurfaceType.esriTinMassPoint);
                tinEdit.Refresh();

                // Get TIN Nodes
                ITinNodeCollection tinNodeCollection = (ITinNodeCollection)tinEdit;

                // Report Node Count
                message.AddMessage("Input Node Count: " + inputFeatureClass.FeatureCount(null).ToString());
                message.AddMessage("TIN Node Count: " + tinNodeCollection.NodeCount.ToString());

                // Open Output Feature Class
                IFeatureClass outputFeatureClass = m_GPUtilities.OpenFeatureClassFromString(outputParameterValue.GetAsText());

                // Debug Message
                message.AddMessage("Generating Polygons...");

                // Create Voronoi Polygons
                tinNodeCollection.ConvertToVoronoiRegions(outputFeatureClass, null, clippingPolygon, "", "");

                // Release COM Objects
                tinEdit.StopEditing(false);
                System.Runtime.InteropServices.Marshal.ReleaseComObject(tinNodeCollection);
                System.Runtime.InteropServices.Marshal.ReleaseComObject(tinEdit);
            }
            catch (Exception ex)
            {
                message.AddError(2, ex.Message);
            }
        }