Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Openlayers3] How to do a GetFeatureInfo request #514

Open
abiuan opened this issue Jun 7, 2016 · 6 comments
Open

[Openlayers3] How to do a GetFeatureInfo request #514

abiuan opened this issue Jun 7, 2016 · 6 comments

Comments

@abiuan
Copy link

abiuan commented Jun 7, 2016

Hello,
at first glance I have a simple task: do a GetFeatureInfo request inside a handleClick method of a ClickHandler behaviour.
This behaviour is added to a map containing a TileWms layer.

Building the url I have some mandatory parameters like bbox, width, height, i, j for which I'm unable to find a value.

  • i and j are coordinate in pixel whereas I have longitude and latitude
  • map.getView().getExtent() returns null

Any suggest?

I looked Openlayers3 examples and they use the method getGetFeatureInfoUrl() that is not available in wicketstuff-openlayers3. Could be added?

Regards

Alberto

@martin-g
Copy link
Member

martin-g commented Jun 7, 2016

@cmiles74 Ping!

@cmiles74
Copy link
Contributor

cmiles74 commented Jun 7, 2016

My current approach to implementing features has been to wait until I need one, then go ahead and implement it. So far, I haven't needed to use a WMS layer; that's why the method your interested in hasn't been implemented yet.

Looking at the OpenLayers 3 documentation, it looks like you use this method to construct a URL, then you can read the feature information from the URL. If the WMS layer doesn't support this function, you'll get a null return value and if there's not a feature at the coordinate, I guess you get a not found or something from the URL's endpoint.

Right now we do have a ClickFeatureHandler that you can add to your layer, you can take a look at our example code to see how that works. You add it to your layer and when it gets called, it has the feature ID, the coordinates and any properties that are attached to the feature. This does not do what you want, but I am wondering how much of this information you'll be getting from the WMS layer. Some of the data you want may be there already, but at the minimum we'll have the coordinate.

In my opinion, implementing this feature will be pretty straightforward. Is this something you might be interested in contributing? I do my best to keep the current code up-to-date as the OpenLayers 3 library changes, but it's something that I do as time allows. Having another contributor would be a huge help. :-)

@abiuan
Copy link
Author

abiuan commented Jun 8, 2016

Unfortunately ClickFeatureHandler works only on WFS layers and, obviously, is quite different from ClickHandler, because features are already on the client.
In case of WMS layer there is only an image hence you have to call GetFeatureInfo to obtain features data.
I have to use a WMS layer because I have a big amount of features (~ 400k) and a WFS layer is unusable in that case.
Finally, I think ClickHandler is the right behaviour to use. The only thing is missing is how to build the url to call the WMS service.
I would be happy to contribute but i'm not a big expert of Openlayers and I'm not a good friend of javascript. Anyway I will give it a try. Do you have some suggest?

@abiuan
Copy link
Author

abiuan commented Jun 8, 2016

I tool a look to the sources and I didn't found a good sample to follow. All methods are simple getters or setters. In this case the problem is different because it has to call the javascript method that returns something and the wrapper has to to the same. Is there something similar that I can follow?

I'm also reasoning about the main problem: wrapping a javascript library. Are there a common pattern? Is it conceivable a "wrapper generator" to produce java code from javascript sources?

@cmiles74
Copy link
Contributor

cmiles74 commented Jun 8, 2016

Yep, you are right; most of the work is done in Javascript. Really what this library does is provide a kind of bridge between the Java and Javascript code. The developer describes what they want in Java and then we emit the proper Javascript to the browser. It's both kind of cool and kind of yucky all at the same time. ;-)

Take a look at ClickHandler.java and it's matching Javascript class, ClickHandler.js...

These two files provide a Wicket "behavior", they let you decorate a component with some Javascript that does something. In this case, we always use the ClickHandler to decorate the map on the Wicket side.

Anyway, the ClickHandler Java class is pretty simple. We provide a default projection and let the developer override this if they want. The developer needs to implement the "handleClick" method and when they do, they'll get the latitude and longitude that was clicked on.

The "respond" method gets called by our Javascript code that lives in the ClickHandler.js file. When "respond" is called, we get the AjaxRequestTarget and, although you can't see it here, some parameters are passed in by the Javascript code. In the "respond" method you can see us pulling this data out through the RequestCycle and then parsing them into coordinates. Lastly, the respond method calls the developer's "handleClick" method with those parsed out coordinates.

The "renderHead" method sets everything up for the code in the Javascript file, ClickHandler.js. It creates a map of parameters and passes the following data:

  • The callback URL, the Javascript calls this to invoke our "respond" method
  • The element ID of the component that this behavior is attached to, this will be the map
  • The clickHandlerId, this is an id unique to each click handler in case there are more than one attached to the map
  • The projection to use, if we have one

Then the ClickHandler.js file is loaded and, as you can see, it's a template. The parameters in the map will be written into the template when it's written to the browser. If you take a look at the
ClickHandler.js file, you can see that we use the "${variable}" notation to fill that data in.

At the top of ClickHandler.js, you can see the click handling function that will get called when something is clicked. All it does is post some data back to the server and that data is then available to the "respond" method in the Java class. In this function we return a little JSON data with the coordinate that was clicked.

Next we actually (finally) setup our Javascript click handler on the OpenLayers map. We register to handle single clicks and provide a function that gets the click event. The function gets the coordinate
from the event and if we've set the projection, it transforms the coordinate. Lastly it calls the click handler with the coordinate and that click handler will post back to the Wicket server and then Wicket
will call the "respond" method in our Java class.

Whew! The process is a little complicated but the code, I think, is pretty simple. Or at least there isn't too much of it.

I'm a little torn on the smartest way to implement this. My thinking is that we should create a new type of click handler, maybe call it ClickWMSFeatureHandler. It will differ from the regular click feature handler in that it won't be asking the map for the feature data (via forEachFeatureAtPixel), instead the Javascript code will use the getFeatureInfoUrl OpenLayers function and return that data instead. If the WMS layer provides feature data, we can call the developer's handleClick method otherwise we can call handleClickMiss.

Once implemented, we can take another look at it and see if there's a better way. All of these click handlers are pretty specialized, this might just be the most practical way to go.

Let me know if this doesn't make any sense. It sounds reasonable to me, but I've been doing this stuff for a while. ;-)

Thank you!

@martin-g
Copy link
Member

martin-g commented Jun 8, 2016

Let me know if this doesn't make any sense. It sounds reasonable to me, but I've been doing this stuff for a while. ;-)

Sounds reasonable to me too! :-)
Very good explanation how Wicket Ajax behaviors work!
Thanks, @cmiles74 !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants