How do you use Clip in .NET 10.3 ArcObjects? (c#)

6212
3
Jump to solution
03-24-2015 08:10 AM
KennethLathan
New Contributor II

Hi all,

I am grabbing a bunch of polygon features (footprints) from a mosaic dataset and I want to clip them and re-add them to the database. I'm getting the records with a Search Cursor within an edit session. So far that part is working just fine, I can update the table fields and Store them back to the db.

I'm running into trouble when I try to clip the features. I cannot seem to get the parameters right. It complains with every kind of output I've tried. Ideally I'd output back to the original input feature, but failing that I'd like to output to memory. I tried creating a memory workspace, but I don't know how to get the results of the clip into it. Has anyone ever done anything similar? The documentation on using geoprocessor in ArcObjects doesn't seem very clear.

It seems funny it's so incredibly easy to do what I want in ArcMap 10.3 and it's so hard programmatically. I can start an edit session, select my records, select my clipping feature, and hit the Clip in the Editor menu, and boom... done. But it doesn't seem like the Editor clip method is exposed in ArcObjects.

Thanks!

-Ken

0 Kudos
1 Solution

Accepted Solutions
KenBuja
MVP Honored Contributor

This is how I have use the Clip geoprocessing tool in a VB.NET project

pClippedFClass = Clip(pAggregatedMPAFClass, pAnalysisExtentFClass, pResultsWS.PathName & "\AllMPAsClipped")

which uses a bunch of functions to create the in memory feature class and clip the data.

    Public Function Clip(ByVal pInFClass As ESRI.ArcGIS.Geodatabase.IFeatureClass, ByVal pClipFClass As ESRI.ArcGIS.Geodatabase.IFeatureClass, ByVal OutputName As String) As ESRI.ArcGIS.Geodatabase.IFeatureClass

        Dim Clipper As New ESRI.ArcGIS.AnalysisTools.Clip

        Dim Result As ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult2

        Try

            Using releaser As New ESRI.ArcGIS.ADF.ComReleaser

                releaser.ManageLifetime(Clipper)

                Clipper.in_features = pInFClass

                Clipper.clip_features = pClipFClass

                Clipper.out_feature_class = OutputName

                Result = RunTool(Clipper, Nothing)

                If Result Is Nothing Then

                    System.Windows.Forms.MessageBox.Show("Could not clip dataset")

                    Return Nothing

                End If

                Return ReturnObjectfromResult(Result, "Feature Class")

            End Using

        Catch ex As Exception

            System.Windows.Forms.MessageBox.Show(ex.ToString, "Clip error")

            Return Nothing

        End Try

    End Function   

   

    Friend Function ReturnObjectfromResult(ByVal result As ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult2, ByVal Type As String) As Object

        Dim GPVal As ESRI.ArcGIS.Geodatabase.IGPValue

        Dim InMemFC As String

        Dim GPUtil As ESRI.ArcGIS.Geoprocessing.IGPUtilities3 = New ESRI.ArcGIS.Geoprocessing.GPUtilities

        Try

            GPVal = result.GetOutput(0)

            InMemFC = GPVal.GetAsText()

            Select Case Type

                Case "Feature Class"

                    Return GPUtil.OpenFeatureClassFromString(InMemFC)

                Case "Table"

                    Return GPUtil.OpenTableFromString(InMemFC)

            End Select

        Catch ex As Exception

            System.Windows.Forms.MessageBox.Show(ex.ToString, "Return FeatureClass error")

            Return Nothing

        End Try

    End Function

    Private Sub ReturnMessages(ByVal pResult As ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult2, ByVal Title As String)

        Dim ErrorMessage As String

        If pResult.MessageCount > 0 Then

            For Count As Integer = 0 To pResult.MessageCount - 1

                ErrorMessage += pResult.GetMessage(Count)

            Next

        End If

        System.Windows.Forms.MessageBox.Show(ErrorMessage, Title)

    End Sub

   

    Friend Function RunTool(ByVal Process As ESRI.ArcGIS.Geoprocessor.IGPProcess, ByVal TC As ESRI.ArcGIS.esriSystem.ITrackCancel2) As ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult2

        Dim Result As ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult2

        Try

            Result = CType(Globals.GP.Execute(Process, Nothing), ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult2)

            If Result.Status <> ESRI.ArcGIS.esriSystem.esriJobStatus.esriJobSucceeded Then ReturnMessages(Result, "Geoprocessing Error")

            Globals.GP.ClearMessages()

        Catch ex As Exception

            ReturnMessages(Result, "Fail")

            System.Windows.Forms.MessageBox.Show(ex.ToString, "Run Geoprocessor")

        End Try

        Return Result

    End Function

View solution in original post

3 Replies
KenBuja
MVP Honored Contributor

This is how I have use the Clip geoprocessing tool in a VB.NET project

pClippedFClass = Clip(pAggregatedMPAFClass, pAnalysisExtentFClass, pResultsWS.PathName & "\AllMPAsClipped")

which uses a bunch of functions to create the in memory feature class and clip the data.

    Public Function Clip(ByVal pInFClass As ESRI.ArcGIS.Geodatabase.IFeatureClass, ByVal pClipFClass As ESRI.ArcGIS.Geodatabase.IFeatureClass, ByVal OutputName As String) As ESRI.ArcGIS.Geodatabase.IFeatureClass

        Dim Clipper As New ESRI.ArcGIS.AnalysisTools.Clip

        Dim Result As ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult2

        Try

            Using releaser As New ESRI.ArcGIS.ADF.ComReleaser

                releaser.ManageLifetime(Clipper)

                Clipper.in_features = pInFClass

                Clipper.clip_features = pClipFClass

                Clipper.out_feature_class = OutputName

                Result = RunTool(Clipper, Nothing)

                If Result Is Nothing Then

                    System.Windows.Forms.MessageBox.Show("Could not clip dataset")

                    Return Nothing

                End If

                Return ReturnObjectfromResult(Result, "Feature Class")

            End Using

        Catch ex As Exception

            System.Windows.Forms.MessageBox.Show(ex.ToString, "Clip error")

            Return Nothing

        End Try

    End Function   

   

    Friend Function ReturnObjectfromResult(ByVal result As ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult2, ByVal Type As String) As Object

        Dim GPVal As ESRI.ArcGIS.Geodatabase.IGPValue

        Dim InMemFC As String

        Dim GPUtil As ESRI.ArcGIS.Geoprocessing.IGPUtilities3 = New ESRI.ArcGIS.Geoprocessing.GPUtilities

        Try

            GPVal = result.GetOutput(0)

            InMemFC = GPVal.GetAsText()

            Select Case Type

                Case "Feature Class"

                    Return GPUtil.OpenFeatureClassFromString(InMemFC)

                Case "Table"

                    Return GPUtil.OpenTableFromString(InMemFC)

            End Select

        Catch ex As Exception

            System.Windows.Forms.MessageBox.Show(ex.ToString, "Return FeatureClass error")

            Return Nothing

        End Try

    End Function

    Private Sub ReturnMessages(ByVal pResult As ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult2, ByVal Title As String)

        Dim ErrorMessage As String

        If pResult.MessageCount > 0 Then

            For Count As Integer = 0 To pResult.MessageCount - 1

                ErrorMessage += pResult.GetMessage(Count)

            Next

        End If

        System.Windows.Forms.MessageBox.Show(ErrorMessage, Title)

    End Sub

   

    Friend Function RunTool(ByVal Process As ESRI.ArcGIS.Geoprocessor.IGPProcess, ByVal TC As ESRI.ArcGIS.esriSystem.ITrackCancel2) As ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult2

        Dim Result As ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult2

        Try

            Result = CType(Globals.GP.Execute(Process, Nothing), ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult2)

            If Result.Status <> ESRI.ArcGIS.esriSystem.esriJobStatus.esriJobSucceeded Then ReturnMessages(Result, "Geoprocessing Error")

            Globals.GP.ClearMessages()

        Catch ex As Exception

            ReturnMessages(Result, "Fail")

            System.Windows.Forms.MessageBox.Show(ex.ToString, "Run Geoprocessor")

        End Try

        Return Result

    End Function

View solution in original post

KennethLathan
New Contributor II

Thanks Ken! That definitely helps. Still having trouble with the input though. It seems like the clip geoprocessing tool only wants to take a FeatureClass as input. I am trying to grab a subset of features from an SDE database with a query. Do you happen to know of an easy way to input this into the clip tool?

Thanks,

-Ken

0 Kudos
KenBuja
MVP Honored Contributor

One thing I did was to create an array of features that I put into an in-memory feature class to be used in the Clip function.

pClippedFClass = Clip(CreateInMemoryFeatures(SubsetArray, "tempComparisonAOI", pFClass), pAnalysisExtentFClass, "in_memory\tempClip")

The array is built using this code

pFCursor = pFClass.Search(pQFilter, False)

pFeature = pFCursor.NextFeature

Counter = 0

ReDim SubsetArray(pFClass.FeatureCount(pQFilter) - 1)

Do Until pFeature Is Nothing

    SubsetArray(Counter) = pFeature

    Counter += 1

    pFeature = pFCursor.NextFeature

Loop

These are the utility functions I used to build the in-memory feature class

Public Function CreateInMemoryFeatures(ByVal FeatureArray() As ESRI.ArcGIS.Geodatabase.IFeature, ByVal Name As String, ByVal pFeatureClass As ESRI.ArcGIS.Geodatabase.IFeatureClass) As ESRI.ArcGIS.Geodatabase.IFeatureClass

        Dim pFClass As ESRI.ArcGIS.Geodatabase.IFeatureClass

        Dim pBuffer As ESRI.ArcGIS.Geodatabase.IFeatureBuffer

        Dim pFCursor As ESRI.ArcGIS.Geodatabase.IFeatureCursor

        Try

            pFClass = CreateInMemoryFeatureClass(Name, pFeatureClass)

            If pFClass Is Nothing Then Return Nothing

            pBuffer = pFClass.CreateFeatureBuffer

            pFCursor = pFClass.Insert(True)

            For Each pFeature As ESRI.ArcGIS.Geodatabase.IFeature In FeatureArray

                For i As Integer = 0 To pFeature.Fields.FieldCount - 1

                    If pBuffer.Fields.Field(i).Type <> ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeOID Then pBuffer.Value(i) = pFeature.Value(i)

                Next

                pFCursor.InsertFeature(pBuffer)

            Next

            pFCursor.Flush()

        Catch ex As Exception

            System.Windows.Forms.MessageBox.Show(ex.ToString, "Create InMemory Feature error")

        Finally

            Release(pFCursor)

        End Try

        Return pFClass

    End Function

    Private Function CreateInMemoryFeatureClass(ByVal Name As String, ByVal pTemplateFClass As ESRI.ArcGIS.Geodatabase.IFeatureClass) As ESRI.ArcGIS.Geodatabase.IFeatureClass

        Dim CreateFC As New ESRI.ArcGIS.DataManagementTools.CreateFeatureclass

        Dim ShapeType As String

        Dim dataset As ESRI.ArcGIS.Geodatabase.IDataset

        Dim Result As ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult2

        Dim Path As String

        Try

            Using releaser As New ESRI.ArcGIS.ADF.ComReleaser

                releaser.ManageLifetime(CreateFC)

                Select Case pTemplateFClass.ShapeType

                    Case ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPoint

                        ShapeType = "Point"

                    Case ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolyline

                        ShapeType = "Line"

                    Case ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolygon

                        ShapeType = "Polygon"

                    Case Else

                        Return Nothing

                End Select

                dataset = pTemplateFClass

                Path = dataset.Workspace.PathName & "\" & dataset.Name

                If dataset.Workspace.WorkspaceFactory.WorkspaceType = ESRI.ArcGIS.Geodatabase.esriWorkspaceType.esriFileSystemWorkspace Then

                    If TypeOf dataset.Workspace.WorkspaceFactory Is ESRI.ArcGIS.DataSourcesFile.ShapefileWorkspaceFactory Then

                        Path = Path & ".shp"

                    End If

                End If

                If InStr(Path, "InMemory") <> 0 Then Path = Nothing

                Dim pSR As ESRI.ArcGIS.Geometry.ISpatialReference3 = GetSpatialReferenceFromDataset(pTemplateFClass)

                CreateFC.out_path = "in_memory"

                CreateFC.out_name = Name

                CreateFC.geometry_type = ShapeType

                CreateFC.template = Path

                CreateFC.spatial_reference = GetSpatialReferenceFromDataset(pTemplateFClass)

                Result = RunTool(CreateFC, Nothing)

                If Result Is Nothing Then

                    System.Windows.Forms.MessageBox.Show("Could not create InMemory dataset")

                    Return Nothing

                End If

                Return ReturnObjectfromResult(Result, "Feature Class")

            End Using

        Catch ex As Exception

            System.Windows.Forms.MessageBox.Show(ex.ToString, "Create InMemory Featureclass error")

            Return Nothing

        End Try

    End Function