Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Unable to get results from querySourceFeatures() #13983

Closed
Yermo opened this issue Feb 25, 2019 · 5 comments
Closed

Unable to get results from querySourceFeatures() #13983

Yermo opened this issue Feb 25, 2019 · 5 comments
Labels
Android Mapbox Maps SDK for Android support

Comments

@Yermo
Copy link

Yermo commented Feb 25, 2019

I am trying to get querySourceFeatures() working on a GeoJSON Source in a NativeScript app with the intention of drawing an animated line by updating the underlying line geometry.

I posted issue #13972 because the documentation is not clear. I attempted to implement the suggestion posted in that issue but there is still something that I am missing. I am still getting an empty array.

To eliminate the possibility that there's some NativeScript bridge/marshalling issue, I decided to try to get querySourceFeatures() to work directly in Java.

I was unable to get the Mapbox-Android-Demo to compile so I have created a fresh Java project following the getting started tutorial.

Working with the Draw a GeoJSON Line example as a base, after quite a bit of trial and error, I have successfully gotten a geojson line to draw on the map.


  String geojsonString = loadGeoJsonFromAsset( "example.geojson");

  Log.d( TAG, "got geojsonString " + geojsonString );

  FeatureCollection testCollection = FeatureCollection.fromJson( geojsonString );

  style.addSource( new GeoJsonSource( "line-source", featureCollection ));

  // this correctly draws a test line on my map. 

  style.addLayer(new LineLayer("linelayer", "line-source")
  .withProperties(PropertyFactory.lineCap(Property.LINE_CAP_SQUARE),
     PropertyFactory.lineJoin(Property.LINE_JOIN_MITER),
     PropertyFactory.lineOpacity(.7f),
     PropertyFactory.lineWidth(7f),
     PropertyFactory.lineColor(Color.parseColor("#3bb2d0"))));

  GeoJsonSource testSource = style.getSourceAs( "line-source");

  // this produces "got source com.mapbox.mapboxsdk.style.sources.GeoJsonSource@671565c"
  
  Log.d( TAG, "got source " + testSource );

  List<Feature> testList = testSource.querySourceFeatures( Expression.literal( true ) );

  // this produces "got testList: []" and I do not understand why.

  Log.d( TAG, "got testList: " + testList );

The reason that I want to query the source of the GeoJSON line is that I want to update it as I get new locations for the user thereby drawing a nice animated line of the user's track on the map.

My understanding is that I have to query the underlying source, get the feature, add the point to the feature geometry, and ... the line should redraw with the additional point?

Just in case it's relevant I'm using the following GeoJSON:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "name": "Test Line over Maryland, USA"
      },
      "geometry": {
        "type": "LineString",
        "coordinates": [
          [-76.926164,39.019062],
          [-76.926100,39.019168],
          [-76.926013,39.019257],
          [-76.925905,39.019328],
          [-76.925777,39.019380],
          [-76.925632,39.019408],
          [-76.925481,39.019405],
          [-76.908129,39.074828],
          [-76.910401,39.075078],
          [-76.913482,39.074758],
          [-76.924829,39.073772],
          [-77.228768,39.158858],
          [-77.233073,39.161274],
          [-77.237891,39.163827],
          [-77.240401,39.165853],
          [-77.242376,39.168174]
        ]
      }
    }
  ]
}

to load the GeoJSON asset I am using this method I ripped off from one of the examples:

    private String loadGeoJsonFromAsset(String filename) {
        try {
            // Load GeoJSON file from local asset folder
            InputStream is = getAssets().open(filename);
            int size = is.available();
            byte[] buffer = new byte[size];
            is.read(buffer);
            is.close();
            return new String(buffer, "UTF-8");
        } catch (Exception exception) {
            Log.e("Exception loading GeoJSON: %s", exception.toString());
            exception.printStackTrace();
            return null;
        }
    }

What am I doing incorrectly?

@Yermo Yermo changed the title Unable to get resuls from querySourceFeatures() Unable to get results from querySourceFeatures() Feb 25, 2019
@Yermo
Copy link
Author

Yermo commented Feb 25, 2019

As an added data point, I copied the code from this example to create another test but am getting the same result:

  final GeoJsonSource source = new GeoJsonSource("test-source",
  FeatureCollection.fromFeatures(new Feature[] {
    Feature.fromGeometry(Point.fromLngLat(17.1, 51), properties),
    Feature.fromGeometry(Point.fromLngLat(17.2, 51), properties),
    Feature.fromGeometry(Point.fromLngLat(17.3, 51), properties),
    Feature.fromGeometry(Point.fromLngLat(17.4, 51), properties),
  }));

  style.addSource(source);

  List<Feature> features = source.querySourceFeatures(eq(get("key1"), literal("value1")));

  Log.d( TAG, "size of features:" + features.size() );

Still gives me an empty array.

@LukasPaczos
Copy link
Contributor

Hey @Yermo, I think your issue might be connected with a fact, that the renderer is asynchronous. What this means is, that whenever you update the map, the work is switched to a GL thread that processes and renders the data.

Having above in mind, when you update the map and try to query it right away, the data might not be ready and rendered yet. To work around this, you can use the OnDidBecomeIdleListener, which you can add with MapView#addOnDidBecomeIdleListener, or post the query to the back of the message queue with an arbitrary delay.

In general, queries are better suited for external interaction or as a reaction to new data rather than initialization flow.

Let us know if this helps!

@LukasPaczos LukasPaczos added Android Mapbox Maps SDK for Android support labels Feb 26, 2019
@Yermo
Copy link
Author

Yermo commented Feb 26, 2019

Oh. I see. I had been under the impression that Sources were just data in the background. That makes sense. I will give that a try.

In my original code, I was trying to use querySourceFeatures() after the line had been drawn in an event callback.

Is my understanding of how to draw an animated line correct? Get the sources. Get the geometry. Update the geometry with a new point. After that is there anything else I need to do? (Currently I am deleting and redrawing the entire line which is quite wasteful when there are many points.)

@LukasPaczos
Copy link
Contributor

Yes, you need to call the GeoJsonSource#setGeoJson with new data each time. Unfortunately, there's no other, more efficient way and tickets like #6177 are tracking the possible improvements here.

@Yermo
Copy link
Author

Yermo commented Feb 26, 2019

Ah. Thank you for all the time you've taken to answer my questions. I greatly appreciate it.

@tobrun tobrun closed this as completed Mar 5, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Android Mapbox Maps SDK for Android support
Projects
None yet
Development

No branches or pull requests

3 participants