MapQueried

Topics: Español, SharpMap v2.0, WinForms Controls
Apr 13 at 5:44 PM
Hi!

I'm looking for an example of how to use MapQueried Event.
I've seen this question:
https://sharpmap.codeplex.com/discussions/296846

Im using MapBox and one geometry layer (with a custom symbol). I've already set QueryLayerIndex to 0 (because it's my layer's index) and ActiveTool to MapBox.Tools.QueryBox, but I'm not sure how to handle MapQueried Event.
¿How could I get information about the "point" I've clicked on?
¿Is there any good example out there? I have not found a clarifying example.


Thanks in advance
Apr 13 at 9:56 PM
Here is how I used the MapBox Query event

Create a DataGridView object named dataGridView1 on your form.

Here is the MapBox Queried event that I setup. Just set the dataGridView datasource to the featuredatatable returned in the event.

private void evnt_MapBox1_Queried(SharpMap.Data.FeatureDataTable data)
    {
        dataGridView1.DataSource = data;
    }
You should see the data in the datagridview.
Apr 14 at 2:17 PM
It is not working for me, getting an error " attribute data is not supported by the geometry provider".

Im doing this :
            VectorLayer vlay2 = new VectorLayer("Points");
            Collection<IGeometry> geomColl = new Collection<IGeometry>();
            ////Get the default geometry factory
            GeoAPI.GeometryServiceProvider.Instance = new NetTopologySuite.NtsGeometryServices();
            IGeometryFactory gf =
                GeoAPI.GeometryServiceProvider.Instance.CreateGeometryFactory();
            SharpMap.Data.Providers.GeometryFeatureProvider g = new SharpMap.Data.Providers.GeometryFeatureProvider(geomColl);
            
            Coordinate coordinate = new Coordinate(-3.6690416, 40.4177623);
            geomColl.Add(gf.CreatePoint(new Coordinate(-5.849632, -79.487228)));
            geomColl.Add(gf.CreatePoint(new Coordinate(-79.487228, -5.849632)));
            geomColl.Add(gf.CreatePoint(coordinate));
            SharpMap.Data.Providers.GeometryProvider gs = new SharpMap.Data.Providers.GeometryProvider(geomColl);
            vlay2.DataSource = gs;

            WpfMap.MapLayers.Add(vlay2);
            

            ProjNet.CoordinateSystems.Transformations.CoordinateTransformationFactory ctFact = new ProjNet.CoordinateSystems.Transformations.CoordinateTransformationFactory();
            vlay2.CoordinateTransformation = ctFact.CreateFromCoordinateSystems(ProjNet.CoordinateSystems.GeographicCoordinateSystem.WGS84, ProjNet.CoordinateSystems.ProjectedCoordinateSystem.WebMercator);
            vlay2.ReverseCoordinateTransformation = ctFact.CreateFromCoordinateSystems(ProjNet.CoordinateSystems.ProjectedCoordinateSystem.WebMercator, ProjNet.CoordinateSystems.GeographicCoordinateSystem.WGS84);

            WpfMap.BackgroundLayer = new TileAsyncLayer(BruTile.Predefined.KnownTileSources.Create(), "OSM");
Could you provide me your code example to see what I am doing wrong?
Thanks dude
Apr 14 at 4:40 PM
I think the error is because you are using a Geometry Provider which is just that "Geometry" not features which is data that can be queried. Here is what I do when adding Geometry and Features.

Create a FeatureDataTable...

SharpMap.Data.FeatureDataTable fDT = new SharpMap.Data.FeatureDataTable { TableName = "MyTable" };
fDT.Columns.Add("Index", typeof(uint));
fDT.Columns.Add("X", typeof(string));
fDT.Columns.Add("Y", typeof(string));
fDT.Columns.Add("SomeData1", typeof(string));
fDT.Columns.Add("SomeData2", typeof(string));
fDT.Columns.Add("SomeData3", typeof(string));

Then for each of your points create a FeatureDataRow and add the data into the Row using an ItemArray...

SharpMap.Data.FeatureDataRow fDR = (SharpMap.Data.FeatureDataRow)fDT.NewRow();
fDR.ItemArray = new object[] { "IndexHere", "X", "Y", "SomeData1Here", "SomeData2Here", "SomeData3Here" };

Now you can add your Geometry to the FeatureDataRow as follows...

myFDR.Geometry = new NetTopologySuite.Geometries.Point(myCoord);
myFeatureTable.Rows.Add(myFDR);

Do this for each of your points adding a row to the featuredatatable for each geometry you are adding.
When you are finished set the DataSource on your vectorlayer as follows.

var p = new SharpMap.Data.Providers.GeometryFeatureProvider(fDT);
vlay2.DataSource = p;

I see you are using BruTile OSM - I am not sure how or if you can query that source.
Apr 20 at 6:12 PM
Thank you very much, now it works how I wanted.

I have one more question. If I change the Style.Symbol of the vector layer, it shows the new Image I set but I have to click in the center of the image to launch the MapQueried event. Is there any posibility to change this? I'd like to click in any part of the image and launch MapQueried event.

Thanks in advance, you helped me a lot.
Apr 22 at 3:48 PM
I think this is because you are using a point geometry with a symbol much larger than the actual geometry. I believe the query tool uses the point that you clicked on to perform the ExecuteInterSectionQuery and since it is just a point you have to be dead on when you click to return any data. If you click and drag the mouse while using the query tool it should expand the query to include the point.


I would just use the mapbox mousedown event to create a polygon around where the user clicked and then use this polygon (enlarged by however much you want) to
query that data in each layer. This is what works for me and someone may have an easier way.

private void evnt_MapBox_MouseDown(GeoAPI.Geometries.Coordinate worldPos, MouseEventArgs imagePos)
{
if (imagePos.Button == System.Windows.Forms.MouseButtons.Right)
{
    GeoAPI.Geometries.Envelope myMouseEnv = new GeoAPI.Geometries.Envelope(worldPos.CoordinateValue);

    //Now you can expand the envelope around where the mouse right click occurred so that you can encompass your image
    //Increase the 10.0 experimentally
    double dblBuffer = 10.0 * mapBox1.Map.PixelSize;
            myMouseEnv.ExpandBy(dblBuffer);

    //Now we create a polygon from the envelope
    //There may be a better way to handle the coordinate array that this but it works for me
    GeoAPI.Geometries.Coordinate[] myCoords = new GeoAPI.Geometries.Coordinate[5];
            myCoords[0] = new GeoAPI.Geometries.Coordinate();
            myCoords[1] = new GeoAPI.Geometries.Coordinate();
            myCoords[2] = new GeoAPI.Geometries.Coordinate();
            myCoords[3] = new GeoAPI.Geometries.Coordinate();
            myCoords[4] = new GeoAPI.Geometries.Coordinate();
            myCoords[0].X = myCoord.X + dblBuffer;
            myCoords[0].Y = myCoord.Y + dblBuffer;
            myCoords[1].X = myCoord.X - dblBuffer;
            myCoords[1].Y = myCoord.Y + dblBuffer;
            myCoords[2].X = myCoord.X - dblBuffer;
            myCoords[2].Y = myCoord.Y - dblBuffer;
            myCoords[3].X = myCoord.X + dblBuffer;
            myCoords[3].Y = myCoord.Y - dblBuffer;
            myCoords[4].X = myCoord.X + dblBuffer;
            myCoords[4].Y = myCoord.Y + dblBuffer;

    //Create a geometry factor
    GeoAPI.Geometries.IGeometryFactory gfac = GeoAPI.GeometryServiceProvider.Instance.CreateGeometryFactory();
    //Create a ring from the coordinate array
            GeoAPI.Geometries.ILinearRing myRing = gfac.CreateLinearRing(myCoords);
    //And finally create a polygon from the ring
            NetTopologySuite.Geometries.Polygon myPolygon = new NetTopologySuite.Geometries.Polygon(myRing);
    //Create a FeatureData set that the query will load with the data
    SharpMap.Data.FeatureDataSet fs = new SharpMap.Data.FeatureDataSet();

    foreach (var Layer in mapBox1.Map.Layers)
            {
        var QueryLayer = Layer as SharpMap.Layers.ICanQueryLayer;
        if (QueryLayer != null && QueryLayer.IsQueryEnabled == true)
        {
            switch (((SharpMap.Layers.VectorLayer)Layer).DataSource.ToString())
            {
                case "SharpMap.Data.Providers.ShapeFile":
                    QueryLayer.ExecuteIntersectionQuery(myPolygon, fs);
                                            break;

                case "SharpMap.Data.Providers.GeometryFeatureProvider":
                                            SharpMap.Data.Providers.GeometryFeatureProvider gf = (SharpMap.Data.Providers.GeometryFeatureProvider)(((SharpMap.Layers.VectorLayer)Layer).DataSource);
                                            gf.Open();
                                            gf.ExecuteIntersectionQuery(myPolygon, fs);
                                            gf.Close();
                                            break;
            }
        }
    }

    //Now you should have a table for each queryable layer in your mapbox
    //You can iterate through each table
    foreach (SharpMap.Data.FeatureDataTable ft in fs.Tables)
    {

    }
}
}
Apr 22 at 6:34 PM
I'll try that this weekend.

Would be possible to use Polygon instead of point geometry? I know the size of each symbol, so I might use ImageToWorld to get 4 Coordinates and create a polygon. What do you think about that?

Thanks for keep posting your help here :)
Apr 22 at 7:00 PM
Yes that was going to be one of the options I was going to mention but didn't have much time. You can use the same code in my last post to create the polygon and add it to the geometry collection. Then when you click inside the polygon the intersection query should get the data. I have never displayed custom symbols over polygons before but I believe it should work. When you add the vector layer to the mapbox you may want to set the polygon as transparent if you don't want it to be visible underneath the symbol - again not sure how that will work.
Apr 24 at 10:10 PM
I've tried it but I dont get what I want.
Could you please confirm me if it is possible to display symbols over polygons?

Seems that it's pretty complicated what I'm trying to achieve. I should probably do it "manual" and use Sharpmap just to get the backgroundImage and transformations World-Image, and print and handle events by my self.

Thanks for everything neutroz.
Apr 25 at 1:35 PM
I'm not sure about using themes with Polygons but did find this discussion which seems to indicate that a theme needs a point geometry to function.

http://sharpmap.codeplex.com/discussions/652671