GetFeatureInfo call for MapBox layer question

Topics: Data Access, WinForms Controls
Jan 29, 2014 at 8:37 PM
I am using SharpMap 1.0 and went through some of the tutorials on the process to create a map box and how to call and display WMS layers. What I need to do now is be able to click on a feature from the WMS layer and get feature information via a GetFeatureInfo call. In the "How To" page, there was an entry for "How do I return a set of feature attribute data from a click on a map?" but that was using a MapImage rather than a MapBox and so the example code is not correct for what I am using (from the tutorial). I can't find any other reference for how to do this. Any thoughts?

Thanks - Peter
Developer
Jan 30, 2014 at 8:15 AM
plen wrote:
What I need to do now is be able to click on a feature from the WMS layer and get feature information via a GetFeatureInfo call.
If you check out the code you can see a SharpMap.Wms.Demo project. There are some demo pages, and the first (Default) have also a GetFeatureInfo sample call.
Coordinator
Jan 30, 2014 at 9:20 AM
MapBox has inbuilt query functionality, so set your ActiveTool to some Query item of the enumeration. Subscribe to the MapQueried event.

If you want to follow the way explained in the HowTo, you need to grow your your bounding box a little. If you don't do that, you need to exactly click on the feature, which is very unlikely.
Developer
Jan 30, 2014 at 9:44 AM
FObermaier wrote:
MapBox has inbuilt query functionality, so set your ActiveTool to some Query item of the enumeration. Subscribe to the MapQueried event.
Oh ok, now I'm in. You use sharpmap control to display wms layers client-side, and not as a server.
So my answer is useless to you, sorry.
Feb 3, 2014 at 4:20 PM
Thanks for the feedback items. I don't necessarily want/need to follow what was in the HowTo, I am just looking for a way to capture a map click on my MapBox and submit a getFeatureInfo request. Is there an example somewhere for MapQueried events? I am seeing this as two parts: one for capturing the map click and getting the coordinates of the click and second, making a getFeatureInfo call.
Coordinator
Feb 3, 2014 at 8:05 PM
The WinFormSamples project has information on how to use MapQueried events
Feb 4, 2014 at 3:11 PM
I must be missing something. I downloaded the SharpMap source and found three areas that used MapQueried. It doesn't seem like this is used with WMS layers. In my case, I registered my MapBox with a MapQueried event, a MapQueryStarted event, and a MapQueryDone event. When I changed the ActiveTool to either a SharpMap.Forms.MapBox.Tools.QueryPoint or a SharpMap.Forms.MapBox.Tools.QueryBox,only the MapQueryStarted and MapQueryDone events were triggered. Nothing for MapQueried. Now, if I create a VectorLayer from a Shape file, I do get the MapQueried event, but I do not get that event with a WmsLayer.

Now, I was able to get the coordinates from a mouse click on the map using a MouseDown event:

private void mapBox1_MouseDown(GeoAPI.Geometries.Coordinate worldPos, MouseEventArgs imagePos) {
}

So, my first part of getting the coordinates of a map click is solved. The second part of making a GetFeatureInfo call back to the WMS layer location with that coordinate information is still an unknown. For example, in OpenLayers, I can load a WMS layer and when I click on the map, I can have OpenLayers make a GetFeatureInfo call (an HTTP call) back to the WMS to see if there are any features at that location. The WMS would then return its results as HTML (or some other designated format). Given what I have seen so far, maybe SharpMap does not have that capability. This is what I am trying to find out.

Thoughts? Thanks - Peter
Coordinator
Feb 4, 2014 at 3:25 PM
Sorry for the misleading information. SharpMap's current WmsLayer implementation does not implement ICanQueryLayer interface.

Now to get your desired result you would have to implement ICanQueryLayer on WmsLayer. That should be straight forward, if you are familiar with WMS and a neat addition, too.
Mar 18, 2015 at 2:37 PM
Edited Mar 18, 2015 at 3:24 PM
FObermaier wrote:
Sorry for the misleading information. SharpMap's current WmsLayer implementation does not implement ICanQueryLayer interface.

Now to get your desired result you would have to implement ICanQueryLayer on WmsLayer. That should be straight forward, if you are familiar with WMS and a neat addition, too.
Hello all,
I'm quite new to SharpMap and not a full-time C# Developer.

I think, my question is related to the question above:
I have tried to Query a Geometry Layer with the
BeginInvoke((MethodInvoker)delegate { changeMode(MapBox.Tools.QueryPoint); });
but following exception is thrown in SharpMap.UI
System.NotSupportedException wurde nicht behandelt.
  HResult=-2146233067
  Message=Attribute data is not supported by the GeometryProvider.
  Source=SharpMap
  StackTrace:
       bei SharpMap.Data.Providers.GeometryProvider.OnExecuteIntersectionQuery(IGeometry geom, FeatureDataSet ds)
       bei SharpMap.Data.Providers.BaseProvider.ExecuteIntersectionQuery(IGeometry geom, FeatureDataSet ds)
       bei SharpMap.Layers.VectorLayer.ExecuteIntersectionQuery(IGeometry geometry, FeatureDataSet ds)
       bei SharpMap.Forms.MapBox.OnMouseUp(MouseEventArgs e) in d:\Development\Codeplex\_SharpMap\Branches\1.0\SharpMap.UI\Forms\MapBox.cs:Zeile 1884.
       bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
       bei System.Windows.Forms.Control.WndProc(Message& m)
       bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       bei System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       bei System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       bei System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
       bei System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       bei System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       bei System.Windows.Forms.Application.Run(Form mainForm)
       bei SharpMapUmsatz.Program.Main() in D:\Daten\VisualStudio\SharpMapTest\SharpMapTutorial\Program.cs:Zeile 18.
       bei System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       bei System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       bei Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       bei System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       bei System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       bei System.Threading.ThreadHelper.ThreadStart()
  InnerException: 
What I tried to do:
Insert geometric points on the Map. And then query with on-mouse-click additional information regarding these points.

Here is the code I have used to add the layer (label layer did mess up everything - no layers where shown)
            var gf = new NetTopologySuite.Geometries.GeometryFactory();
            var fdt = new SharpMap.Data.FeatureDataTable();
            // FeatureDataTable has x und y coordinates, added name
            fdt.Columns.Add(new DataColumn("NAME", typeof(String)));

            // create a point by specifying the coordinates directly
            var coordinates = new[] { new Coordinate(13.03631710000002, 47.8214988, 200370), 
                new Coordinate(13.381943800000045, 47.3740838, 200464), new Coordinate(13.601719399999979, 47.19041199999999, 280538) };

            foreach (Coordinate xyz in coordinates)
            {
                fdt.BeginLoadData();
                var fdr = (FeatureDataRow)fdt.LoadDataRow(new[] { (object)Convert.ToString(xyz.Z) }, true);
                //              var fdr = (FeatureDataRow)fdt.LoadDataRow(new[] { (object)"Mayence" }, true);
                fdr.Geometry = gf.CreatePoint(new GeoPoint(xyz.X, xyz.Y));
                fdt.EndLoadData();
            }
            
            VectorLayer layAddresses = new VectorLayer("Points");
            LabelLayer layAddressLabels = new LabelLayer("PointNames");

            layAddresses.DataSource = new SharpMap.Data.Providers.GeometryProvider(fdt);
            layAddressLabels.DataSource = layAddresses.DataSource;
            SharpMap.Styles.VectorStyle defaultStyle = new SharpMap.Styles.VectorStyle();

            layAddresses.Style.PointColor = Brushes.Blue;

            #region LabelLayerStyle
            /*
            layAddressLabels.Enabled = true;
            layAddressLabels.LabelColumn = "Name";
            layAddressLabels.Style = new LabelStyle();
            layAddressLabels.Style.ForeColor = Color.Blue;
            layAddressLabels.Style.BackColor = Brushes.White;
            layAddressLabels.Style.Font = new Font(FontFamily.GenericSansSerif, 12, FontStyle.Bold);
            layAddressLabels.Style.Offset = new PointF(4, 4);
            layAddressLabels.Style.HorizontalAlignment = LabelStyle.HorizontalAlignmentEnum.Left;
            layAddressLabels.Style.VerticalAlignment = LabelStyle.VerticalAlignmentEnum.Bottom;
            layAddressLabels.Style.CollisionDetection = true;
            layAddressLabels.LabelFilter = SharpMap.Rendering.LabelCollisionDetection.ThoroughCollisionDetection;
            */
 
            layAddressLabels.SRID = 4326;
            #endregion
            layAddresses.SRID = 4326;

            mapBox1.Map.Layers.Add(layAddresses);
//            mapBox1.Map.Layers.Add(layAddressLabels);
            mapBox1.Refresh();
Thanks in advance, Andreas
Coordinator
Mar 18, 2015 at 8:37 PM
GeometryProvider is not suitable for calls to ExecuteIntersectionQuery
Use GeometryFeatureProvider instead. This will solve your issue with labels, too.