Mouse click coordinates incorrectly converted

Topics: SharpMap v0.9 / v1.x, Web Controls
Jun 17, 2011 at 8:04 AM
Edited Jun 17, 2011 at 8:16 AM

I am using Sharpmap v 0.9

I want to select a polygon in my shapefile based on user click. on my web page. When I click on the map, it should select the polygon where the point exists & change its fillcolor to red.

When I click on large polygons at the center of the polygon, everything is fine.

On smaller polygons, or if I click close to the borders, the neighboring polygons are also selected. What am I doing wrong?

//Set coordinates of the map to where the client clicked
SharpMap.Geometries.Point ClickPnt = myMap.ImageToWorld(new System.Drawing.PointF(e.X, e.Y));

SharpMap.Data.FeatureDataSet ds = new SharpMap.Data.FeatureDataSet();

//Open the District layer to add territory selections
SharpMap.Layers.VectorLayer myLayer = this.myMap.GetLayerByName("Districts") as SharpMap.Layers.VectorLayer; 
if (!myLayer.DataSource.IsOpen)
 myLayer.DataSource.Open();

//Execute click-query
myLayer.DataSource.ExecuteIntersectionQuery(ClickPnt, ds);

if (ds.Tables.Count > 0) //We have a result, bind to gridview
{
 GV_ClickResults.DataSource = ds.Tables[0];
 GV_ClickResults.DataBind();

 //Add clicked features to a selection layer
 SharpMap.Layers.VectorLayer laySelected = new SharpMap.Layers.VectorLayer("Selection");
 laySelected.DataSource = new GeometryProvider(ds.Tables[0]);
 laySelected.Style.Fill = new System.Drawing.SolidBrush(System.Drawing.Color.Red);
 myMap.Layers.Add(laySelected);
}


Coordinator
Jun 17, 2011 at 8:43 AM

By default SharpMap only does intersection testing against the bounding boxes of the object.

You need to use NetTopologySuite (or SharpMap.SqlServerSpatialObjects) to do true intersection testing.

Hth FObermaier

Jun 17, 2011 at 10:48 PM
Edited Jun 18, 2011 at 7:58 AM

Thanks for the reply.

I am using the release version on SharpMAp 0.9.

1.  I will need NetTopologySuite.dll & GeoAPI.dll. Do I need SharpMap.Extensions.dll also?

2 .Do I need any other .CS files to be used in App_Code directory

3. Where can I get the dlls from?

 I picked up NetTopologySuite.dll  & GeoAP.dll from sharpmap-89801\Trunk\ExternalReferences. I did add references to the 2 dlls.

 I keep getting an error "The type or namespace name 'NTS' does not exist in the namespace 'SharpMap.Converters' (are you missing an assembly reference?)  

I even tried the 1.8 binaries from http://code.google.com/p/nettopologysuite/. Same error!

Here are my current references:

GeoAPI => 1.2.0.0
NetTopology Suite => 1.8.0.0
SharpMap => 0.9.3946.23110

Systen.Core, System.Data.DataSetExtensions, System.Web.Extensions, System.XML.Linq => GAC 3.5.0.0

In my Default.ASPX, I added the line  using SharpMap.Converters.NTS;

 

What am I missing?

 

 

Jun 20, 2011 at 6:51 AM
Edited Jun 20, 2011 at 7:15 AM

Used the Trunk and compiled it. Used all the dlls from the BIN directory. Now I can see Sharpmap.converter.NTS.

Thanks for your help!

Intersection is working correctly now!

Jul 13, 2011 at 11:49 AM

I updated the code to include

//Execute click-query
myLayer.DataSource.ExecuteIntersectionQuery(ClickPnt, ds);

if (ds.Tables.Count > 0) //We have a result 
{
//Filter out the extra polygons to get the true intersection
PostFilterExistingFeatureDataTable(ds.Tables[0], ClickPnt);
GV_ClickResults.DataSource = ds.Tables[0]; GV_ClickResults.DataBind(); ...............
This code works well when my Shapefiles have only polygons. When the Shapefiles has "MultiPolygons", I cannot get the correct Intersection.
Is there anything else I need to do when the shapefile has "MultiPolygons"
Is there a tool, that I can use to convert the MutiPolygons to simple polygons?


        
    
Coordinator
Jul 13, 2011 at 12:03 PM

what is incorrect about the result you get? Do you get the whole MultiPolygon instead of just that polygon of the multipolygon that intersects?.

In that case you need to split up your multipolygon into its components and do intersectiontest with each

Hth FObermaier

Jul 13, 2011 at 11:35 PM
Edited Jul 13, 2011 at 11:46 PM

My map has several districts. Each time I click insde a Polygon, only that district should be selected. Its color changes & it is saved to a SQL database.

1. When it has a Mutipolygon, several polygons (in different areas of the map) are getting selecting.
2. I am unable to save to the SQL database. I get an error System.InvalidCastException: Unable to cast object of type 'SharpMap.Geometries.MultiPolygon' to type 'SharpMap.Geometries.Polygon'
3. My Gridview cannot show the Data fileds (District Name) - Instead it just puts "School District Not Defined" This error comes from the ShapeFile as I have not used this type of message anywhere in my code.

How can I break the MultiPolygon into Polygons? It will be nice if this can be done in the code as I have over 200 shapefiles.

I got my Shapefile from this location : ftp://ftp2.census.gov/geo/tiger/TIGER2010/UNSD/2010/tl_2010_04_unsd10.zip

Here's my Map Before Selection &   After Selection

Coordinator
Jul 14, 2011 at 1:08 AM

You should be able to take individual geometries out of a geometry collection within Sql Server using STNumGeometries and  STGeometryN see http://msdn.microsoft.com/en-us/library/bb933910.aspx and http://msdn.microsoft.com/en-us/library/bb933831.aspx

hth jd

Jul 14, 2011 at 7:58 AM
Edited Jul 14, 2011 at 7:58 AM

I am sorry. maybe I mislead by using the SQL.

The issue is with the Shapefile. The ShapeFile has MutiPolygons. I need a way to select a single polygon on the map. Note I am reading from the shapefiles. not from SQlServer.

How can I break the MultiPolygon into Polygons?

Coordinator
Jul 14, 2011 at 8:13 AM

You can iterate over the multipolygon's Polygon entries. Sth like this

FeatureDataRow fdr;

if (fdr.Geometry is MultiPolygon)
{
    foreach (var polygon in ((MultiPolygon)fdr.Geometry).Polygons)
    {
         ...
    }
}
else if (fdr.Geometry is Polygon)
{
    ...
}
else
    throw new Exception("Invalid geometry type");

Hth FObermaier

 

Jul 14, 2011 at 9:35 AM
Edited Jul 14, 2011 at 9:58 AM

I am still lost. With above code I can iterate through the set the polygons, but  how to find the polygon I clicked on so I can get its feature set?

			PostFilterExistingFeatureDataTable(ds.Tables[0], ClickPnt);

			FeatureDataRow fdr = ds.Tables[0][0];
			if (fdr.Geometry is SharpMap.Geometries.MultiPolygon)
			{
				foreach (var polygon in ((SharpMap.Geometries.MultiPolygon)fdr.Geometry).Polygons)
				{
					//if (polygon.Intersects(ClickPnt)) //Intersects(Geometry) is not implemented, tried .Contains too - no luck
					//	break;
				}
			}
Coordinator
Jul 14, 2011 at 9:48 AM

you need to do that in the postfilterexistingfeaturedatatable function and replace the featuredatarows geometry with the intersecting polygon.

Hth FObermaier