ExecuteIntersectionQuery not working with point shp + CharacterPointSymbolizer CustomTheme

Topics: SharpMap v0.9 / v1.x
Sep 11, 2014 at 2:00 PM
On mouse click ExecuteIntersectionQuery not return any point.


Below code used for create vector layer
 public SharpMap.Layers.VectorLayer CreateSiteLayer()
        {          
            SharpMap.Layers.VectorLayer vlay = new SharpMap.Layers.VectorLayer("SiteMap");
            vlay.DataSource = new SharpMap.Data.Providers.ShapeFile(_AppPath + @"Temp\lteSiteMap.shp", true); //(@"D:\ccu.shp", true); 

            vlay.Theme = new SharpMap.Rendering.Thematics.CustomTheme(GetPolygonCustomStyle);       

            DataTable dtLabel = dt.DefaultView.ToTable(true, new string[] { "LAT", "Long", "SiteID" });
            CreateLabelSHP(dtLabel);
            SharpMap.Layers.VectorLayer vlayTemp = new SharpMap.Layers.VectorLayer("SiteLabel");
            vlayTemp.DataSource = new SharpMap.Data.Providers.ShapeFile(_AppPath + @"Temp\SiteLabel.shp", true);
            vlayLabel.DataSource = vlayTemp.DataSource;
            vlayLabel.SRID = 3857;
            vlayLabel.Style.Offset = new PointF(0, -30);
            vlayLabel.LabelColumn = "Data";
            

            var epsg4326 = new CoordinateSystemFactory().CreateFromWkt("GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]]");
            var epsg3785 = new CoordinateSystemFactory().CreateFromWkt(
                "PROJCS[\"Popular Visualisation CRS / Mercator\", " +
                         "GEOGCS[\"Popular Visualisation CRS\", " +
                                 "DATUM[\"Popular Visualisation Datum\", " +
                                         "SPHEROID[\"Popular Visualisation Sphere\", 6378137, 0, AUTHORITY[\"EPSG\",\"7059\"]], " +
                                         "TOWGS84[0, 0, 0, 0, 0, 0, 0], " +
                                         "AUTHORITY[\"EPSG\",\"6055\"]], " +
                                         "PRIMEM[\"Greenwich\", 0, AUTHORITY[\"EPSG\", \"8901\"]], " +
                                         "UNIT[\"degree\", 0.0174532925199433, AUTHORITY[\"EPSG\", \"9102\"]], " +
                                         "AXIS[\"E\", EAST], AXIS[\"N\", NORTH], " +
                                         "AUTHORITY[\"EPSG\",\"4055\"]], " +
                                         "PROJECTION[\"Mercator\"], " +
                                          "PARAMETER[\"False_Easting\", 0], " +
                                          "PARAMETER[\"False_Northing\", 0], " +
                                          "PARAMETER[\"Central_Meridian\", 0], " +
                                          "PARAMETER[\"Latitude_of_origin\", 0], " +
                                          "UNIT[\"metre\", 1, AUTHORITY[\"EPSG\", \"9001\"]], " +
                                          "AXIS[\"East\", EAST], AXIS[\"North\", NORTH], " +
                                          "AUTHORITY[\"EPSG\",\"3785\"]]");
            var ctf = new CoordinateTransformationFactory();
            vlay.CoordinateTransformation = ctf.CreateFromCoordinateSystems(epsg4326, epsg3785);
            vlay.Enabled = true;

            vlayTemp.CoordinateTransformation = ctf.CreateFromCoordinateSystems(epsg4326, epsg3785);
            vlayLabel.CoordinateTransformation = ctf.CreateFromCoordinateSystems(epsg4326, epsg3785);
            vlayLabel.Enabled = true;

            return vlay;
        }
Add Site Vector layer in Mapbox with background layer
private void button2_Click(object sender, EventArgs e)
        {
            
            var layergoogle = new TileLayer(new GoogleTileSource(GoogleMapType.GoogleMap), "googlemaps", Color.Transparent, true,
                                 @"D:\Cache_brutile");

            mapBox1.Map.BackgroundLayer.Clear();
            mapBox1.Map.BackgroundLayer.Add(layergoogle);
           
            mapBox1.Map.Layers.Clear();
            SharpMap.Layers.VectorLayer SiteLayer = CreateSiteLayer();
            mapBox1.Map.Layers.Add(SiteLayer);
            mapBox1.Map.Layers.Add(vlayLabel);
            mapBox1.Map.ZoomToBox(SiteLayer.Envelope);
            mapBox1.Refresh();
            this.mapBox1.ActiveTool = SharpMap.Forms.MapBox.Tools.Pan;     
        }
On mouse click we want to show some info of that point so I have write below code
        private void mapBox1_MouseClick(object sender, MouseEventArgs e)
        {
            GeoAPI.Geometries.IGeometryFactory GFact;
            SharpMap.Data.FeatureDataSet ds = new SharpMap.Data.FeatureDataSet();
            SharpMap.Layers.VectorLayer vl;
            vl = mapBox1.Map.Layers[0] as SharpMap.Layers.VectorLayer;
            GFact = GeoAPI.GeometryServiceProvider.Instance.CreateGeometryFactory(0);
            GeoAPI.Geometries.IPoint pt = GFact.CreatePoint(mapBox1.Map.ImageToWorld(new System.Drawing.PointF(e.X, e.Y)));
            GeoAPI.Geometries.Envelope gmt = new GeoAPI.Geometries.Envelope(mapBox1.Map.ImageToWorld(new System.Drawing.PointF(e.X, e.Y)));
            SharpMap.Data.FeatureDataRow row = FindGeoNearPoint(gmt, vl, pt);
        }

        public SharpMap.Data.FeatureDataRow FindGeoNearPoint(GeoAPI.Geometries.Envelope bbox, SharpMap.Layers.VectorLayer layer, GeoAPI.Geometries.IPoint post)
        {
            bbox.ExpandBy(5d, 5d);
            SharpMap.Data.FeatureDataSet ds = new SharpMap.Data.FeatureDataSet();
            layer.DataSource.Open();
            layer.DataSource.ExecuteIntersectionQuery(bbox, ds);
            DataTable tbl = ds.Tables[0] as SharpMap.Data.FeatureDataTable;
            NetTopologySuite.IO.WKTReader reader = new NetTopologySuite.IO.WKTReader();
            GeoAPI.Geometries.IGeometry point = reader.Read(post.ToString());
            if (tbl.Rows.Count == 0)
                return null;

            double distance = point.Distance(reader.Read((tbl.Rows[0] as SharpMap.Data.FeatureDataRow).Geometry.ToString()));
            SharpMap.Data.FeatureDataRow selectedFeature = tbl.Rows[0] as SharpMap.Data.FeatureDataRow;

            if (tbl.Rows.Count > 1)
                for (int i = 1; i < tbl.Rows.Count; i++)
                {
                    GeoAPI.Geometries.IGeometry line = reader.Read((tbl.Rows[i] as SharpMap.Data.FeatureDataRow).Geometry.ToString());
                    if (point.Distance(line) < distance)
                    {
                        distance = point.Distance(line);
                        selectedFeature = tbl.Rows[i] as SharpMap.Data.FeatureDataRow;
                    }
                }

            //MessageBox.Show(selectedFeature.ItemArray[1].ToString());
            return selectedFeature;
        }
Please help we have using sharpMap 1.1.

Varun
Coordinator
Sep 12, 2014 at 2:34 AM
In FindGeoNearPoint, you forgot to reproject your point to the coordinate system of the datasource. You can either
  • reproject it before calling layer.DataSource.ExecuteIntersectionQuery(bbox, ds); or
  • call ((ICanQueryLayer)layer).ExecuteIntersectionQuery(bbox, ds).
Note: if the queried features have polygonal geometries, the distance will be 0 (if it is a true intersection). So if you have have puntal or lineal features as well, you need to manipulate the 0 distance. Have a look at FindGeoNearPoint in this piece of code
Sep 12, 2014 at 5:48 AM
Edited Sep 12, 2014 at 8:01 AM
Hi FObermaier,
I have try both suggestion but find no luck
  ((ICanQueryLayer)layer).ExecuteIntersectionQuery(bbox, ds);
and second
 private FeatureDataRow FindGeoNearPoint(SharpMap.Layers.VectorLayer layer, GeoAPI.Geometries.IPoint post)
        {
            var mapPosition = post.Coordinate;
            var env = new GeoAPI.Geometries.Envelope(mapPosition);
            env.ExpandBy(5 * mapBox1.Map.PixelWidth);
            var g = NetTopologySuite.Geometries.Prepared.PreparedGeometryFactory.Prepare(mapBox1.Map.Factory.ToGeometry(env));

            var fdrs = new List<Tuple<double, FeatureDataRow>>();
            var fds = new FeatureDataSet();
            var tableCount = 0;
            var l = mapBox1.Map.Layers[0];
            if (l.Enabled && l.MinVisible < mapBox1.Map.Zoom &&
                l.MaxVisible >= mapBox1.Map.Zoom && l is ICanQueryLayer)
            {
                var cql = (ICanQueryLayer)l;
                cql.ExecuteIntersectionQuery(env, fds);
                for (var j = tableCount; j < fds.Tables.Count; j++)
                {
                    var fdt = fds.Tables[j];
                    for (var k = 0; k < fdt.Rows.Count; k++)
                    {
                        var fdr = (FeatureDataRow)fdt.Rows[k];
                        if (g.Intersects(fdr.Geometry))
                        {
                            var distance = g.Geometry.InteriorPoint.Distance(fdr.Geometry);
                            if (fdr.Geometry.Dimension == GeoAPI.Geometries.Dimension.Surface)
                                distance += 5 * mapBox1.Map.PixelWidth;
                            fdrs.Add(Tuple.Create(distance, fdr));
                        }
                    }
                }
                tableCount = fds.Tables.Count;
            }


            if (fdrs.Count > 0)
            {
                fdrs.Sort((t1, t2) => t1.Item1.CompareTo(t2.Item1));
                return fdrs[0].Item2;
            }
            return null;
        }

this function always return null.

Edit: A important observation :
I have write below code for draw a LineString between Envelope’s Max and Min Coordinate
GeoAPI.Geometries.Envelope gmt = new GeoAPI.Geometries.Envelope(mapBox1.Map.ImageToWorld(new System.Drawing.PointF(e.X, e.Y)));

            gmt.ExpandBy(50d, 50d);
            GeoAPI.Geometries.Coordinate[] cor = new GeoAPI.Geometries.Coordinate[2];
            cor[0] = new GeoAPI.Geometries.Coordinate(gmt.MinX, gmt.MinY);
            cor[1] = new GeoAPI.Geometries.Coordinate(gmt.MaxX, gmt.MaxY);

            FeatureDataTable fdtt = CreateLineString(cor);

            SharpMap.Layers.VectorLayer linevlay = new SharpMap.Layers.VectorLayer("Temp");
            linevlay.DataSource = new SharpMap.Data.Providers.GeometryFeatureProvider(fdtt);
            linevlay.Enabled = true;
            linevlay.Style.Line.Color = Color.Black;
            linevlay.Style.Line.Width = 5;
            mapBox1.Map.Layers.Add(linevlay);
At the Zoom lavel 1:166100 I have click on a point and hope to get that feature but all hopes faded

Image


When I zoom in that area I have found this my Envelope didn’t contain any point (Current Zoom Level is 1:34834)

Image


Any suggestion?
Coordinator
Sep 12, 2014 at 2:07 PM
Create a reverse CoordinateTransformation and assign that to Vectorlayer.ReverseCoorginateTransformation.
Sep 12, 2014 at 6:20 PM
Hi FObermaier,

I have already tried it didn't work.
Coordinator
Sep 15, 2014 at 7:57 AM
Now I see what is wrong. You are not clicking exactly enough. You either need to aim better (suitable for very experienced mouse users) or increase the the amount by which you grow the envelope. I did env.ExpandBy(5 * mapBox1.Map.PixelWidth);, making the amount, by which to grow the envelope dependant on the map's zoom. You did gmt.ExpandBy(50d, 50d);, growing it by a fixed size.

I'd go for the zoom dependable aproach, maybe use a greater factor to expand by. I assume you need to click on the center of your symbol to get the correct result.