ITopological Operator, Intermittent COMException on Union

3672
9
04-06-2010 09:51 AM
DavidPlume1
New Contributor III
Hi Everyone, I'm getting intermittent errors on calls to the Union function for ITopologicalOperator.

The Error looks like this:

Error Source System.Runtime.InteropServices.COMException (0x80040218): Exception from HRESULT: 0x80040218   at ESRI.ArcGIS.Geometry.ITopologicalOperator.Union(IGeometry other)

Any ideas would be appreciated, I've found minimal info about this problem on the forums and documents online.

Thanks
David


The code looks like this:

              '  Now work the geometry...

                Dim pNewPolyline As ESRI.ArcGIS.Geometry.IPolyline
                pNewPolyline = Nothing

                Dim pFeature As ESRI.ArcGIS.Geodatabase.IFeature

                Dim pTopoOp As ESRI.ArcGIS.Geometry.ITopologicalOperator5 = Nothing
                pComReleaser.ManageLifetime(pTopoOp)

                Dim pNewFeature As ESRI.ArcGIS.Geodatabase.IFeature = Nothing
              
                '  Featureset contains two or more sector line
                '  features that have the same assignment and belong
                '  to the same perimeter polygon.  Merge their shapes
                '  to create as single geometry from them.

                '  Get the feature metadata from the first feature.
                '  it will be used to populate metadata on the resulting
                '  feature.  Since all the line features are associated
                '  with the same polygon, they should all have the
                '  same metadata.

                Dim pMetadata As FIMTExtensionNET.clsFIMTMetadataNET
                pMetadata = Nothing

                FeatureSet.Reset()
                pFeature = FeatureSet.Next

                Do While Not pFeature Is Nothing

                    If pMetadata Is Nothing Then
                        pMetadata = New FIMTExtensionNET.clsFIMTMetadataNET
                        pMetadata.GetFeatureMetaData(pFeature)
                    End If

                    If pNewPolyline Is Nothing Then
                        pNewPolyline = pFeature.ShapeCopy
                        pTopoOp = CType(pNewPolyline, ESRI.ArcGIS.Geometry.ITopologicalOperator5)
                    Else
                        pNewPolyline = pTopoOp.Union(pFeature.ShapeCopy)  '<<<<<<<<<<<<<<<<<<<<< Where the Exception is thrown.
                        pTopoOp = CType(pNewPolyline, ESRI.ArcGIS.Geometry.ITopologicalOperator5)
                        pTopoOp.Simplify()
                    End If

                    pFeature = FeatureSet.Next

                Loop
9 Replies
KirkKuykendall
Occasional Contributor III
Try simplifying the geometry before passing it as an arg to Union.
0 Kudos
DavidPlume1
New Contributor III
Hi Kirk, 

Thanks, that may have worked.   For the sake of the thread here's what I've tried: 

I spoke with ESRI yesterday via an incident and they thought I should try to replace  explicitly set a variable = pFeature.ShapeCopy and use that value in the arguments to pTopoOp.Union().  The problem persisted after that. 

I then implemented your recommendation and so far things seem to be working.  The troubling thing about this error is how it is intermittent so I can't yet say for sure but things look good so far.

For the sake of the thread, here is the code as it stands now:


               '  Now work the geometry...

                Dim pNewPolyline As ESRI.ArcGIS.Geometry.IPolyline = Nothing
                Dim pOtherPolyline As ESRI.ArcGIS.Geometry.IPolyline = Nothing

                Dim pFeature As ESRI.ArcGIS.Geodatabase.IFeature

                Dim pTopoOp As ESRI.ArcGIS.Geometry.ITopologicalOperator5 = Nothing
                pComReleaser.ManageLifetime(pTopoOp)

                Dim pNewFeature As ESRI.ArcGIS.Geodatabase.IFeature = Nothing
              
                '  Featureset contains two or more sector line
                '  features that have the same assignment and belong
                '  to the same perimeter polygon.  Merge their shapes
                '  to create as single geometry from them.

                '  Get the feature metadata from the first feature.
                '  it will be used to populate metadata on the resulting
                '  feature.  Since all the line features are associated
                '  with the same polygon, they should all have the
                '  same metadata.

                Dim pMetadata As FIMTExtensionNET.clsFIMTMetadataNET
                pMetadata = Nothing

                FeatureSet.Reset()
                pFeature = FeatureSet.Next

                Do While Not pFeature Is Nothing

                    If pMetadata Is Nothing Then
                        pMetadata = New FIMTExtensionNET.clsFIMTMetadataNET
                        pMetadata.GetFeatureMetaData(pFeature)
                    End If

                    If pNewPolyline Is Nothing Then
                        pNewPolyline = pFeature.ShapeCopy
                        pTopoOp = CType(pNewPolyline, ESRI.ArcGIS.Geometry.ITopologicalOperator5)
                    Else
                        pOtherPolyline = pFeature.ShapeCopy  ' This didn't seem to help....
                        pTopoOp.Simplify()                            ' This may have solved the prob.

                        pNewPolyline = pTopoOp.Union(pOtherPolyline)

                        'pNewPolyline = pTopoOp.Union(pFeature.ShapeCopy) 'OLD CODE

                        pTopoOp = CType(pNewPolyline, ESRI.ArcGIS.Geometry.ITopologicalOperator5)

                        'pTopoOp.Simplify() 'OLD CODE

                    End If

                    'pTopoOp.Simplify() 'OLD CODE
                    pFeature = FeatureSet.Next

                Loop
0 Kudos
KirkKuykendall
Occasional Contributor III
I think you should set ITopologicalOperator2.IsKnownSimple_2 to false before calling Simplify().

(ESRI sure needs to simplify this process of simplification).

Also, I've had issues with Union for polygons that contain circulararc segments.  The workaround was to call IPolyCurve.Densify.  Doesn't seem like this should pertain to polylines, but might be worth trying.
0 Kudos
DavidPlume1
New Contributor III
Thanks again Kirk, I've added your recommended code with good success.  I've run through the problem scenario about 10-15 times with no COM Exception thrown.  We might be there!
0 Kudos
DavidPlume1
New Contributor III
For those who are interested, a bit more information:

If one cannot ensure that the polyline created is not simple then we need to call the simplify method. A geometry is not simple when it does not meet the all the constraints associated with them. The following documentation explains how the simplify method simplifies the geometry.

http://resources.esri.com/help/9.3/ArcGISDesktop/com/samples/Geometry/e7840a7a-f228-46d2-9c45-81dd55...

http://resources.esri.com/help/9.3/ArcGISDesktop/ArcObjects/esriGeometry/Geometry_overview.htm

http://resources.esri.com/help/9.3/ArcGISDesktop/ArcObjects/esriGeometry/ITopologicalOperator_Simpli...
0 Kudos
BenStewart
New Contributor III
I'm having similar problems, but with the ItopologicalOperator intersect. I have tried the suggestions here about simplification, which helped, but, in the end, the code still errors with an unknown COMException.

The basic idea is to find the distance to the nearest line feature in a single direction. This is accomplished by creating a line segment from the starting point to another point 10000000m away along the direction specified and intersecting with the line feature class. The distance to all intersections is calculated, and the minimum is stored.

The code will work for about 3000 features then crash, when I restart it works for the feature it crashed on (it only processes features not processed yet). Any suggestions would be welcomed.


           'Set these values at the start
            Dim azimuthField, distanceField As Long
            azimuthField = form.inputField
            distanceField = form.OutputField

            ' Get map object
            Dim mxd As IMxDocument
            Dim map As IMap
            mxd = CType(m_application.Document, IMxDocument)
            map = mxd.FocusMap

            'Get feature classes, first is points, then borders
            Dim ptLayer As IFeatureLayer
            Dim borderLayer As IFeatureLayer

            Dim ptClass As IFeatureClass
            Dim borderClass As IFeatureClass

            ptLayer = form.InputLayer
            ptClass = ptLayer.FeatureClass

            borderLayer = form.BorderLayer
            borderClass = borderLayer.FeatureClass

            ' loop through each point feature

            Dim featCur As IFeatureCursor
            ' This is a search to ensure that only non-processed features are processed
            Dim filt As IQueryFilter = New QueryFilter()
            Dim f As IField = ptClass.Fields.Field(distanceField)
            filt.WhereClause = f.Name + " = 0"
            featCur = ptClass.Update(filt, True)

            Dim feat As IFeature
            feat = featCur.NextFeature()

            Dim pt As IPoint

            Dim azimuth, dist, i As Double ' This will store the azimuth direction
            Dim maxDist As Double
            Dim tempSegs As ISegmentCollection = New Polyline()
            Dim tempSegsGeog As IGeometry
            Dim tempFeat As IFeature
            Dim topo As ITopologicalOperator5
            Dim prox As IProximityOperator
            Dim geomTemp As IGeometry

            maxDist = 100000000
            Try
                While Not feat Is Nothing
                    maxDist = 100000000
                    pt = feat.ShapeCopy
                    azimuth = CDbl(feat.Value(azimuthField))
                    Dim tempLine As ILine
                    ' This function creates the temporary line feature used to intersect
                    tempLine = createTempLine(pt, CDbl(azimuth))

                    'The line needs to be wrapped in a polyline to fit in the spatial filter
                    If tempSegs.SegmentCount > 0 Then
                        For i = 0 To tempSegs.SegmentCount - 1
                            tempSegs.RemoveSegments(i, 1, False)
                        Next
                    End If

                    tempSegs.AddSegment(tempLine)
                    tempSegsGeog = tempSegs
                    tempSegsGeog.SpatialReference = feat.Shape.SpatialReference

                    Dim spatial As ISpatialFilter = New SpatialFilter()
                    spatial.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects
                    spatial.Geometry = tempSegs

                    ' A spatial query is used to get the intersetion points, I thought this is where the memeory leak was happening, but I don't think so anymore (after examining the call stack
                    Dim tempFeatCur As IFeatureCursor = borderClass.Search(spatial, True)
                    tempFeat = tempFeatCur.NextFeature()

                    While Not tempFeat Is Nothing
                        topo = tempFeat.Shape
                        topo.IsKnownSimple_2 = False
                        topo.Simplify() ' attempt to fix intermitent error following http://forums.arcgis.com/threads/1992-ITopological-Operator-Intermittent-COMException-on-Union
                        'This is where the error is occuring, at least it is for the first time
                        geomTemp = topo.Intersect(tempSegsGeog, esriGeometryDimension.esriGeometry0Dimension)
                        prox = geomTemp
                        dist = prox.ReturnDistance(pt)
                        If dist < maxDist Then
                            maxDist = dist
                        End If
                        tempFeat = tempFeatCur.NextFeature()
                    End While

                    System.Runtime.InteropServices.Marshal.ReleaseComObject(tempFeatCur)
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(tempLine)

                    feat.Value(distanceField) = maxDist
                    featCur.UpdateFeature(feat)

                    feat = featCur.NextFeature()

                End While
            Catch ex As System.Runtime.InteropServices.COMException
                System.Windows.Forms.MessageBox.Show(ex.Message)
            End Try
            System.Windows.Forms.MessageBox.Show("Finished Calculating Distances")
        End If
0 Kudos
KirkKuykendall
Occasional Contributor III
You might try calling IGeometry.SnapToSpatialReference before simplifying.

Also, intersect can flake out with nonlinear segments, so maybe call IPolyCurve.Densify before Intersect.
0 Kudos
DavidPlume1
New Contributor III
Hi Everyone,

For the sake of completion in this thread, we solved our particular problem by simplifying all of the input features and by simplifying the resulting feature on each iteration of the while loop:

           Dim pNewFeature As ESRI.ArcGIS.Geodatabase.IFeature = Nothing
            Dim pNewPolyline As ESRI.ArcGIS.Geometry.IPolyline = Nothing
            Dim pOtherPolyline As ESRI.ArcGIS.Geometry.IPolyline = Nothing
            Dim pTopoOp As ESRI.ArcGIS.Geometry.ITopologicalOperator5 = Nothing
            Dim pFeature As ESRI.ArcGIS.Geodatabase.IFeature = Nothing

            '  Featureset contains two or more sector line
            '  features that have the same assignment and belong
            '  to the same perimeter polygon.  Merge their shapes
            '  to create as single geometry from them.

            '  Get the feature metadata from the first feature.
            '  it will be used to populate metadata on the resulting
            '  feature.  Since all the line features are associated
            '  with the same polygon, they should all have the
            '  same metadata.

            Dim pMetadata As FIMTExtensionNET.clsFIMTMetadataNET
            pMetadata = Nothing

            FeatureSet.Reset()
            pFeature = FeatureSet.Next

            Do While Not pFeature Is Nothing

                If pMetadata Is Nothing Then
                    pMetadata = New FIMTExtensionNET.clsFIMTMetadataNET
                    pMetadata.GetFeatureMetaData(pFeature)
                End If

                If pNewPolyline Is Nothing Then

                    pNewPolyline = pFeature.ShapeCopy
                    pTopoOp = CType(pNewPolyline, ESRI.ArcGIS.Geometry.ITopologicalOperator5)
                    pTopoOp.IsKnownSimple_2 = False '051710
                    pTopoOp.Simplify() '051710

                Else

                    pOtherPolyline = pFeature.ShapeCopy

                    'Simplify the just obtained OtherPolyLine
                    pTopoOp = CType(pOtherPolyline, ESRI.ArcGIS.Geometry.ITopologicalOperator5) '051710
                    pTopoOp.IsKnownSimple_2 = False
                    pTopoOp.Simplify()

                    'Reset the pTopoOp to pNewPolyLine in prep for the union
                    pTopoOp = CType(pNewPolyline, ESRI.ArcGIS.Geometry.ITopologicalOperator5)
                    pNewPolyline = pTopoOp.Union(pOtherPolyline)

                    'Simplify the resulting New Line
                    pTopoOp = CType(pNewPolyline, ESRI.ArcGIS.Geometry.ITopologicalOperator5)
                    pTopoOp.IsKnownSimple_2 = False
                    pTopoOp.Simplify()

                End If

                pFeature = FeatureSet.Next

            Loop


I hope this is helpful.
D
0 Kudos
DuncanHornby
MVP Notable Contributor
All,

Very useful thread this, it saved me!

I was getting the same COM error, found this thread, implemented Simplify and IsKnownSimple_2 but was still getting the error. I eventually solved it by adding a SimplifyNetwork of my polylines that I was attempting to do the Symmetrical difference on. So for the record my full code snippet is:

pPolylineStart.SimplifyNetwork()
pPolylineTest.SimplifyNetwork()
pTopoOp = pPolylineTest
pTopoOp.IsKnownSimple_2 =False
pTopoOp.Simplify()
pPolyline = pTopoOp.SymmetricalDifference(pPolylineStart)


Thanks

Duncan
0 Kudos