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

queryRenderedFeatures returns nothing for point-in-polygon queries, if polygon type is set to 'Line' #2400

Closed
timiyay opened this issue Apr 6, 2016 · 7 comments

Comments

@timiyay
Copy link

timiyay commented Apr 6, 2016

mapbox-gl-js version: 0.16.0

Steps to Trigger Behavior

  1. create a MapboxGL style containing a polygon source, which is set to type Line in Mapbox Studio
  2. use queryRenderedFeatures with map.on('mousemove') to query for the polygon underneath the cursor

Expected Behavior

The function returns the polygon that intersects the cursor point - this is the behaviour that v0.15.0 featuresAt exhibited.

Actual Behavior

  1. if the cursor is inside the polygon, the functions returns an empty features array
  2. if the cursor is on the polygon edge, the function returns an array of features that share that edge

Background

Our app is being forced to mapbox-gl-js 0.16.0 (see #2300 (comment)), and we're working through the breaking changes since 0.15.0.

We have a large polygon vector tileset, for land parcels. For styling purposes, we set the layer to type: Line in MB Studio. We need this to control line thickness, which type: Fill doesn't allow (it's locked to 1px).

A small feature of our app is to change the mouse cursor to pointer when it hovers over a land parcel, to demonstrate that the feature is clickable. In 0.15.0, we did this with the following code:

map.on('mousemove', function(e) {
  map.featuresAt(e.point, { layer: 'parcels' }, function(err, features) {
    map.getCanvas().style.cursor = features.length ? 'pointer' : '';
  });
});

This worked as expected, as demonstrated in this Codepen: http://codepen.io/timiyay/pen/qZVMMo.

To upgrade to 0.16.0, we started by changing the code to:

map.on('mousemove', function(e) {
  var features = map.queryRenderedFeatures(e.point, { layers: ['parcels'] });
  map.getCanvas().style.cursor = features.length ? 'pointer' : '';
});

This doesn't work, as explained in Actual Behaviour, and demonstrated in this Codepen: http://codepen.io/timiyay/pen/WwXgPQ.

However, if I use Mapbox Studio to change the layer to type: Fill, the code works as expected, as shown in this Codepen: http://codepen.io/timiyay/pen/wGPEEw.

@mourner
Copy link
Member

mourner commented Apr 6, 2016

The actual behavior kind of makes sense, because queryRenderedFeatures implies returning rendered features under the cursor, and in your case it's rendered as line and not polygon. Not even sure how to address this in the core... @ansis thoughts?

@timiyay
Copy link
Author

timiyay commented Apr 6, 2016

@mourner thanks for the reply.

I can definitely see your point, and perhaps queryRenderedFeatures has evolved to be different from featuresAt, rather than a direct replacement.

I will be looking closer at querySourceFeatures, though that appears to be for attribute filtering, not spatial querying. There's no way I see to input the cursor point (https://www.mapbox.com/mapbox-gl-js/api/#Map.querySourceFeatures).

If we get stuck, I'll likely switch the type: Fill, and live without control over the line thickness.

Interested in alternative approaches, for sure.

@jfirebaugh
Copy link
Contributor

The recommended way to render both a stroke with configurable width and a fill is to have two layers: one Line layer and one Fill layer. Both will reference the same data.

mapbox/mapbox-gl-style-spec#223 tracks adding a combined layer type that can support both in a single layer.

@ansis
Copy link
Contributor

ansis commented Apr 6, 2016

You can work around this by creating a second parcels style layer that has type: fill and fill-opacity: 0.

@timiyay
Copy link
Author

timiyay commented Apr 6, 2016

Beautiful, thanks folks.

Will add the workaround, and track the issue.

Cheers.

@mourner
Copy link
Member

mourner commented Apr 6, 2016

@ansis it will still spend time triangulating the layer and filling triangle buffers even if the opacity is 0, right?

@ansis
Copy link
Contributor

ansis commented Apr 6, 2016

@mourner yes, it will, but it shouldn't be a huge cost compared to the total cost of loading all layers

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

No branches or pull requests

4 participants