ThinkGeo.com    |     Documentation    |     Premium Support

Error on multipolygon selection

Hello everyone,


 


For my application, I have the possibility to select a multipolygon but I reach an exception when I try to do it.


 


This is my multipolygon :



 


When I use this code, it reach an exception :  



private void winformsMap1_Click(object sender, MapClickWinformsMapEventArgs e)
{
    InMemoryFeatureLayer layer = GetLayer(item.Text);

    layer.Open();
    Collection<Feature> selectedFeatures = layer.QueryTools.GetFeaturesContaining(e.WorldLocation, columns);
    layer.Close();

    ......
}


 


This is the exception (reach with this => e.WorldLocation) :



And the detail :


GisSharpBlog.NetTopologySuite.Geometries.TopologyException was unhandled

  Message="side location conflict [ (-43.9453125, -24.9850769042969, NaN) ]"

  Source="NetTopologySuite"

  StackTrace:

       at GisSharpBlog.NetTopologySuite.GeometriesGraph.EdgeEndStar.PropagateSideLabels(Int32 geomIndex)

       at GisSharpBlog.NetTopologySuite.GeometriesGraph.EdgeEndStar.ComputeLabelling(GeometryGraph[] geom)

       at GisSharpBlog.NetTopologySuite.Operation.Relate.RelateComputer.LabelNodeEdges()

       at GisSharpBlog.NetTopologySuite.Operation.Relate.RelateComputer.ComputeIM()

       at GisSharpBlog.NetTopologySuite.Operation.Relate.RelateOp.get_IntersectionMatrix()

       at GisSharpBlog.NetTopologySuite.Operation.Relate.RelateOp.Relate(IGeometry a, IGeometry b)

       at GisSharpBlog.NetTopologySuite.Geometries.Geometry.Relate(IGeometry g)

       at GisSharpBlog.NetTopologySuite.Geometries.Geometry.Contains(IGeometry g)

       at ThinkGeo.MapSuite.Core.BaseShape.ContainsCore(BaseShape targetShape)

       at ThinkGeo.MapSuite.Core.BaseShape.Contains(BaseShape targetShape)

       at ThinkGeo.MapSuite.Core.FeatureSource.x50350872fb80508b(BaseShape xb513c0b05488b8ed, IEnumerable`1 x8ad42fcdfcf2a001)

       at ThinkGeo.MapSuite.Core.FeatureSource.SpatialQueryCore(BaseShape targetShape, QueryType queryType, IEnumerable`1 returningColumnNames)

       at ThinkGeo.MapSuite.Core.FeatureSource.SpatialQuery(BaseShape targetShape, QueryType queryType, IEnumerable`1 returningColumnNames)

       at ThinkGeo.MapSuite.Core.QueryTools.GetFeaturesContaining(BaseShape targetShape, IEnumerable`1 returningColumnNames)

       at TestModuleCartto.Form1.winformsMap1_Click(Object sender, MapClickWinformsMapEventArgs e) in C:\Documents and Settings\Pad.GEO6\Mes documents\Visual Studio 2008\Projects\TestModuleCarto\TestModuleCartto\Form1.cs:line 256

       at ThinkGeo.MapSuite.DesktopEdition.WinformsMap.OnMapClick(MapClickWinformsMapEventArgs e)

       at ThinkGeo.MapSuite.DesktopEdition.WinformsMap.x1e882ae98c96da8b(InteractionArguments x195facd4ef5d753d)

       at ThinkGeo.MapSuite.DesktopEdition.WinformsMap.xfeca3317d3c75bbb(Object xd9272088e65bd176, x6a8380ab1a7ebb4c xc2fd4c0ed406cdb7)

       at ThinkGeo.MapSuite.DesktopEdition.x5cd462d41be2f68a.OnMouseEvent(x6a8380ab1a7ebb4c e)

       at ThinkGeo.MapSuite.DesktopEdition.x5cd462d41be2f68a.x9726bb53ed7f1ead(Object xd9272088e65bd176, EventArgs xc2fd4c0ed406cdb7)

       at System.Windows.Forms.Timer.OnTick(EventArgs e)

       at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)

       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)

       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)

       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)

       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)

       at System.Windows.Forms.Application.Run(Form mainForm)

       at TestModuleCartto.Program.Main() in C:\Documents and Settings\Pad.GEO6\Mes documents\Visual Studio 2008\Projects\TestModuleCarto\TestModuleCartto\Program.cs:line 18

       at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)

       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)

       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()

       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)

       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)

       at System.Threading.ThreadHelper.ThreadStart()

  InnerException: 

 


Is this error came from me ?


Thanks in advance for your answer.



Hi Pierre, 
  
 Thanks for your post. 
  
 It’s awesome you attached the stack trace, because it will be helpful for find the problem, do you notice the line at ThinkGeo.MapSuite.Core.BaseShape.Contains(BaseShape targetShape), so we can simplify the problem to baseShape.Contains(targetShape). Can you do me a favor? When you recreate this exception, the application will stop, at this time, find the line, and record the two shapes, you can use shape.GetWellKnownText() to convert the instance to string, and save it to txt file, and send me the txt file which contains two shapes’ well known text that can recreate the exception. After I test the data I will let you know how to solve the problem. 
  
 Please let me know if I am not very clear. 
  
 Thanks 
 James 


Hi,


 


Sorry but I can get the line. It doesn't appears in the exception details.


I attach the Multipolygon WKT and the targetShape (Point) WKT.


 


Pierre-Antoine



1617-Multipolygon_and_Point_WKT.txt (388 Bytes)

From my research on MultiPolygon, having one of the polygons intersecting another one is not valid.


social.msdn.microsoft.com/Fo...e6c0 


Although, Map Suite allows drawing such a Geometry, it fails when doing a geometric operation such as GetFeaturesContaining. I suggest that in that case, you create a collection of PolygonShapes instead and add them to your InMemoryFeatureLayer. See the code below:


 Also, an other approach when dealing with selfIntersecting MultiPolygonShape is to merge the intersecting polygons into one. Soon, a Code Community project showing how to deal concretely with those cases will be posted.



 MultipolygonShape multiPolygonShape = new MultipolygonShape(multiPolygonShapeWKT);
            PointShape pointShape = new PointShape(pointShapeWKT);

            InMemoryFeatureLayer inMemoryFeatureLayer = new InMemoryFeatureLayer();
            inMemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(150, GeoColor.StandardColors.Red),GeoColor.StandardColors.Black);
            inMemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.CreateSimpleCircleStyle(GeoColor.StandardColors.Green, 12);
            inMemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;


            bool selfIntersected = IsMultiPolygonShapeSelfIntersected(multiPolygonShape);

            if (selfIntersected == true)
            {
                Collection<PolygonShape> polygonShapes = new Collection<PolygonShape>();
                foreach (PolygonShape polygonShape in multiPolygonShape.Polygons)
                {
                    inMemoryFeatureLayer.InternalFeatures.Add(new Feature(polygonShape));
                }
            }
            else
            {
                inMemoryFeatureLayer.InternalFeatures.Add(new Feature(multiPolygonShape));
            }

            LayerOverlay myOverlay = new LayerOverlay();
            myOverlay.Layers.Add("myLayer", inMemoryFeatureLayer);
            winformsMap1.Overlays.Add("MyOverlay", myOverlay);

            inMemoryFeatureLayer.Open();
            Collection<Feature> selectedFeatures = inMemoryFeatureLayer.QueryTools.GetFeaturesContaining(pointShape, ReturningColumnsType.NoColumns);
            inMemoryFeatureLayer.Close();
 //Determines if any any PolygonShape making up the MultiPolygonShape intersect each other.
        private bool IsMultiPolygonShapeSelfIntersected(MultipolygonShape multiPolygonShape)
        {
            bool result = false;
            int i, j;
            for (i = 0; i <= multiPolygonShape.Polygons.Count - 1; i += 1)
            {
                PolygonShape polygonShape = multiPolygonShape.Polygons[i];

                for (j = i + 1; j <= multiPolygonShape.Polygons.Count - 1; j += 1)
                {
                    PolygonShape polygonShape2 = multiPolygonShape.Polygons[j];
                    if (polygonShape.Intersects(polygonShape2))
                    {
                        result = true;
                        break;
                    }
                }
                if (result == true) break;
            }
            return result;
        }


Hello,



Thank you for your answer. It work perfectly.


But in my case, I need to keep a link between the polygons in the multipolygon. If I choose one of them, all the polygons must be selected. It works perfectly when 2 polygons don't intersects.


For the moment, I'm going to forbid a multipolygon which contains 2 or more intersected polygons.



Thanks again.



I am glad you have a solution working for you.

I let you know that today a new project in the Code Community related to your case has been posted. It shows the two different approaches when dealing with a self intersecting Multi Polygon.

 


code.thinkgeo.com/projects/show/intersectmultipoly