ExecuteIntersectionQuery freezes application

Topics: SharpMap Project, WinForms Controls
Feb 1, 2010 at 11:13 PM
I am using ExecuteIntersectionQuery in a C# forms project to select features on an existing layer. When I run the project and click on the map the application freezes. No error message is displayed. Using a break point I can verify that the point pt and the vector layer vl are properly assigned. Here the code:
 
private void MapBox_MouseClick(object sender, MouseEventArgs e)
{
    SharpMap.Data.FeatureDataSet ds = new SharpMap.Data.FeatureDataSet();
    SharpMap.Layers.VectorLayer vl;
    SharpMap.Geometries.Point pt = _sharpMap.ImageToWorld(new System.Drawing.PointF(e.X, e.Y));
    vl = _sharpMap.Layers[0] as SharpMap.Layers.VectorLayer;
    vl.DataSource.Open();
    vl.DataSource.ExecuteIntersectionQuery(pt, ds);
    vl.DataSource.Close();
    if
(ds.Tables.Count > 0)
    {
        SharpMap.Layers.VectorLayer laySelected = new SharpMap.Layers.VectorLayer("Selection");
        laySelected.DataSource = new SharpMap.Data.Providers.GeometryProvider(ds.Tables[0]);
        laySelected.Style.Fill = new System.Drawing.SolidBrush(System.Drawing.Color.Firebrick);
        _sharpMap.Layers.Insert(1, laySelected);
    }
}
 
I am using these dlls:
 
SharpMap.dll - 0.9.3582.17966
SharpMap.Extensions.dll - 0.9.3582.17967
gdal_csharp - 1.0.3462.17845
GeoAPI.dll - 1.1.0.0
NetTopologySuite.dll - 1.7.3.36606
All other dlls that come with fwtools are in my bin directory
 
Any ideas? Your quick reply is much appreciated.
Coordinator
Feb 2, 2010 at 6:47 PM

Hello dev123,

did you use precompiled binaries or did you compile sharpmap yourself from the repository at here at codeplex?
If not, please do so and see if the problem persists.

If not it would be nice to know what kind of data you are querying (provider)

cheers

FObermaier

Feb 3, 2010 at 11:16 PM
Edited Feb 4, 2010 at 10:14 PM

Hi FObermaier

I have had to resort to GetIntersectingFeaturesUsingFilterDelegate in order to get true intersection testing. Three problems when I run it;

1.) I have changed return type of GetIntersectingFeaturesUsingFilterDelegate to FeatureDataSet because that is what I need to create a results layer. At return featureDataSet it now complains "Specified method is not supported" at SharpMap.Data.FeatureDataTable.get_Rows.

2.) The resulting FeatureDataSet is empty. Is this because I am passing it a SharpMap.Geometries.Point not a BoundingBox?

3.) Function GetIntersectingFeaturesUsingFilterDelegate says that "shapefile.close" is not a valid method. Inner exception says it is also from "Specified method is not supported" at SharpMap.Data.FeatureDataTable.get_Rows.

public FeatureDataSet GetIntersectingFeaturesUsingFilterDelegate(string pathToShapefile, SharpMap.Geometries.Geometry testGeometry)
        //public FeatureDataTable GetIntersectingFeaturesUsingFilterDelegate(string pathToShapefile, SharpMap.Geometries.Geometry testGeometry)
        {
            //create a new shapefile provider
            using (ShapeFile shapefile = new ShapeFile(pathToShapefile))
            {
                //create an nts GeometryFactory
                GisSharpBlog.NetTopologySuite.Geometries.GeometryFactory geometryFactory = new GisSharpBlog.NetTopologySuite.Geometries.GeometryFactory();
                //convert the testGeometry into the equivalent NTS geometry
                GisSharpBlog.NetTopologySuite.Geometries.Geometry testGeometryAsNtsGeom =
                    GeometryConverter.ToNTSGeometry(testGeometry, geometryFactory);
                //set the shapefile providers' FilterDelegate property to a new anonymous method
                //this delegate method will be called for each potential row
                shapefile.FilterDelegate = delegate(FeatureDataRow featureDataRow)
                {
                    //get the geometry from the featureDataRow
                    SharpMap.Geometries.Geometry rowGeometry = featureDataRow.Geometry;
                    //convert it to the equivalent NTS geometry
                    GisSharpBlog.NetTopologySuite.Geometries.Geometry
                        compareGeometryAsNtsGeometry =
                            GeometryConverter.ToNTSGeometry(rowGeometry,
                                                            geometryFactory);
                    //do the test. Note that the testGeometryAsNtsGeometry is available here because it is
                    //declared in the same scope as the anonymous method.
                    bool intersects = testGeometryAsNtsGeom.Intersects(compareGeometryAsNtsGeometry);
                    //return the result
                    return intersects;
                };
                //create a new FeatureDataSet
                FeatureDataSet featureDataSet = new FeatureDataSet();
                //open the shapefile
                shapefile.Open();
                //call ExecuteIntersectionQuery. The FilterDelegate will be used to limit the result set
                shapefile.ExecuteIntersectionQuery(testGeometry, featureDataSet);
                //close the shapefile
             shapefile.Close();
                //return the populated FeatureDataTable
                return featureDataSet;
                //return featureDataSet.Tables[0];
            }
        }

 

Thanks

Coordinator
Feb 4, 2010 at 10:57 AM

Hello dev123,

I don't see anything wrong with the code you posted, for me it compiled and worked allright.

There was a bug in the ExecuteIntersectionQuery(Geometry testGeometry, FeatureDataSet featureDataSet) function,
which I fixed.

I suppose you should be all set if you get the latest source and compile SharpMap yourself.

Hth

FObermaier

Feb 5, 2010 at 4:42 AM

Hi FObermaier

No joy yet. I went and downloaded everything again to make sure I have latest versions (or at least those that come with current packages):

GeoAPI.dll 1.0.0.0
NetTopologySuite.dll 1.7.3.30582
ProjNet.dll 1.0.2794.16965
SharpMap.dll 0.9.3575.26255
SharpMap.Extensions.dll 0.9.3575.26260

Here the calling code:

SharpMap.Data.FeatureDataSet fds = new SharpMap.Data.FeatureDataSet();
SharpMap.Geometries.Point p = _sharpMap.ImageToWorld(new System.Drawing.PointF(e.X, e.Y));
TrueIntersectionTestingWithNTS trueint = new TrueIntersectionTestingWithNTS();
fds = trueint.GetIntersectingFeaturesUsingFilterDelegate(LayerStructure[0]._ShapeFile, p);

And your slightly adapted true intersection testing:

 

//This example requires references to
//SharpMap.dll (or project)
//SharpMap.Extensions.dll (or project)
//NetTopologySuite.dll (from the ExternalReferences directory)
//GeoAPI.dll (from the ExternalReferences directory)
using SharpMap.Converters.NTS;
using SharpMap.Data;
using SharpMap.Data.Providers;

namespace Csiro.Mse.UI.Forms.Controls
{
    /// <summary>

    /// Contains two methods for doing true intersection testing on geometries using NetTopologySuite

    /// </summary>

    public class TrueIntersectionTestingWithNTS
    {
        /// <summary>

        /// This method returns a FeatureDataTable containing all the rows from the shapefile that intersect the testGeometry.

        /// The ShapeFile.ExecuteIntersectionQuery method only tests bounding boxes so we use the FilterDelegate property to add a true

        /// intersection test using NetTopologySuite

        /// </summary>

        /// <param name="pathToShapefile">The path to the shapefile</param>

        /// <param name="testGeometry">The geometry that we want to test against</param>

        /// <returns></returns>

        public FeatureDataSet GetIntersectingFeaturesUsingFilterDelegate(string pathToShapefile, SharpMap.Geometries.Geometry testGeometry)
        //public FeatureDataTable GetIntersectingFeaturesUsingFilterDelegate(string pathToShapefile, SharpMap.Geometries.Geometry testGeometry)
        {
            //create a new shapefile provider
            using (ShapeFile shapefile = new ShapeFile(pathToShapefile))
            {
                //create an nts GeometryFactory
                GisSharpBlog.NetTopologySuite.Geometries.GeometryFactory geometryFactory = new GisSharpBlog.NetTopologySuite.Geometries.GeometryFactory();
                //convert the testGeometry into the equivalent NTS geometry
                GisSharpBlog.NetTopologySuite.Geometries.Geometry testGeometryAsNtsGeom =
                    GeometryConverter.ToNTSGeometry(testGeometry, geometryFactory);
                //set the shapefile providers' FilterDelegate property to a new anonymous method
                //this delegate method will be called for each potential row
                shapefile.FilterDelegate = delegate(FeatureDataRow featureDataRow)
                {
                    //get the geometry from the featureDataRow
                    SharpMap.Geometries.Geometry rowGeometry = featureDataRow.Geometry;
                    //convert it to the equivalent NTS geometry
                    GisSharpBlog.NetTopologySuite.Geometries.Geometry
                        compareGeometryAsNtsGeometry =
                            GeometryConverter.ToNTSGeometry(rowGeometry,
                                                            geometryFactory);
                    //do the test. Note that the testGeometryAsNtsGeometry is available here because it is
                    //declared in the same scope as the anonymous method.
                    bool intersects = testGeometryAsNtsGeom.Intersects(compareGeometryAsNtsGeometry);
                    //return the result
                    return intersects;
                };
                //create a new FeatureDataSet
                FeatureDataSet featureDataSet = new FeatureDataSet();
                //open the shapefile
                shapefile.Open();
                //call ExecuteIntersectionQuery. The FilterDelegate will be used to limit the result set
                shapefile.ExecuteIntersectionQuery(testGeometry, featureDataSet);
                //close the shapefile
                shapefile.Close();
                //return the populated FeatureDataTable
                return featureDataSet;
                //return featureDataSet.Tables[0];
            }
        }
        /// <summary>

        /// This method takes a pre-populated FeatureDataTable and removes rows that do not truly intersect testGeometry

        /// </summary>

        /// <param name="featureDataTable">The FeatureDataTable instance to filter</param>

        /// <param name="testGeometry">the geometry to compare against</param>

        public void PostFilterExistingFeatureDataTable(FeatureDataTable featureDataTable, SharpMap.Geometries.Geometry testGeometry)
        {
            //first we create a new GeometryFactory.
            GisSharpBlog.NetTopologySuite.Geometries.GeometryFactory geometryFactory = new GisSharpBlog.NetTopologySuite.Geometries.GeometryFactory();
            //then we convert the testGeometry into the equivalent NTS geometry
            GisSharpBlog.NetTopologySuite.Geometries.Geometry testGeometryAsNtsGeom =
                GeometryConverter.ToNTSGeometry(testGeometry, geometryFactory);
            //now we loop backwards through the FeatureDataTable
            for (int i = featureDataTable.Rows.Count - 1; i > -1; i--)
            {
                //we get each row
                FeatureDataRow featureDataRow = featureDataTable.Rows[i] as FeatureDataRow;
                //and get the rows' geometry
                SharpMap.Geometries.Geometry compareGeometry = featureDataRow.Geometry;
                //convert the rows' geometry into the equivalent NTS geometry
                GisSharpBlog.NetTopologySuite.Geometries.Geometry compareGeometryAsNts =
                    GeometryConverter.ToNTSGeometry(compareGeometry, geometryFactory);
                //now test for intesection (note other operations such as Contains, Within, Disjoint etc can all be done the same way)
                bool intersects = testGeometryAsNtsGeom.Intersects(compareGeometryAsNts);
                //if it doesn't intersect remove the row.
                if (!intersects)
                    featureDataTable.Rows.RemoveAt(i);
            }
        }

    }
}

 

When I run it and click a feature I get "Object reference not set to an instance of an object" at line shapefile.close (green above) (btw, gray code is not accessed). It seems that featureDataRow is empty eventhough I clicked on an object.

I am using this for an important application (seriously) and need to get it to work very soon. I appreciate your quick reply.

Thanks
dev123

 

Coordinator
Feb 5, 2010 at 7:39 AM

Hi dev123,

just to make sure:

You need to compile SharpMap yourself, do *NOT* use the binaries from the download tab.

Could you post a full stack trace.

FObermaier