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); }
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); }
//根据创建的点要素做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(); } }
//曲率熵 //参数已排序 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); }
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); }
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); }
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; }
/// <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; }
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++; } } }
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); } }
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); } }