GeometryEngine.within() - must have equivalent geometries

839
4
Jump to solution
07-30-2018 12:00 PM
CharlesLoftis
New Contributor III

Using ArcGIS andorid 100x API I'm trying to determine if points returned onLocationChanged are within a queried feature. When I use the GeometryEngine.within() method I'm getting runtime errors stating that "geometry1 and geometry2 must have equivalent spatial references." Adding a breakpoint to my code I see that my Point (i.e., geometry 1) has spatial reference SR: 4326, but the spatial reference (feature.getGeometry()) associated with the feature returned from my queryFeatureAsync (i.e., geometry 2) is null. Assuming this is the source of the problem, how can I get my feature to have the correct spatial reference? 

Code snippet:

       // get the MapView's LocationDisplay
      this.mLocationDisplay = this.mMapView.getLocationDisplay();
      this.mLocationDisplay.addLocationChangedListener(new LocationDisplay.LocationChangedListener() {
         @Override
         public void onLocationChanged(LocationDisplay.LocationChangedEvent locationChangedEvent) {
            final LocationDataSource.Location l = locationChangedEvent.getLocation();
            // segments == layer containing geometries of interest
            if (MainActivity.this.segments != null) {
               final FeatureTable featureTable = MainActivity.this.segments.getFeatureTable();
               featureTable.addDoneLoadingListener(new Runnable() {
                  @Override
                  public void run() {
                     featureTable.removeDoneLoadingListener(null);
                     QueryParameters queryParameters = new QueryParameters();
                     queryParameters.setWhereClause(String.format("feature_identifier='%1$s'", "myFeature"));
                     final ListenableFuture<FeatureQueryResult> listenableFuture = featureTable.queryFeaturesAsync(queryParameters);
                     listenableFuture.addDoneListener(new Runnable() {
                        @Override
                        public void run() {
                           try {
                              FeatureQueryResult featureQueryResult = listenableFuture.get();
                              if (featureQueryResult.iterator().hasNext()) {
                                 try {
                                    Iterator<Feature> iterator = featureQueryResult.iterator(); // create an Iterator
                                    Feature feature;
                                    while (iterator.hasNext()) { // cycle through results
                                       feature = iterator.next();
                                       if (l.getPosition() != null) {
                                          //****next line: geometry1 and geometry2 must have equivalent spatial references *****
                                          if (GeometryEngine.within(l.getPosition(), feature.getGeometry())) {
                                             Log.d(TAG, "inside feature");
                                          } else {
                                             Log.d(TAG, "outside feature");
                                          }
                                       }
                                    }
                                 } catch (Exception e) {
                                    Log.e(TAG, e.getMessage());
                                 }
                              }
                           } catch (Exception e) {
                              Log.e(TAG, e.getMessage());
                           }
                        }
                     });
                  }
               });
            }
         }
      });
0 Kudos
1 Solution

Accepted Solutions
ShellyGill1
Esri Contributor

Hi Charles,

If you know the correct spatial reference of your feature layer, you can create the SpatialReference directly from a WKID for example, and then 'assign' it to a geometry that has a null spatial reference by using the GeometryEngine.project method - GeometryEngine| arcgis-android .  Does your FeatureLayer also have a null spatial reference, or is it just the Feature's Geometry that is like that? 

Shelly

View solution in original post

4 Replies
ShellyGill1
Esri Contributor

Hi Charles,

If you know the correct spatial reference of your feature layer, you can create the SpatialReference directly from a WKID for example, and then 'assign' it to a geometry that has a null spatial reference by using the GeometryEngine.project method - GeometryEngine| arcgis-android .  Does your FeatureLayer also have a null spatial reference, or is it just the Feature's Geometry that is like that? 

Shelly

CharlesLoftis
New Contributor III

Thanks for the quick reply.

After further inspection the spatial reference of my point is wkid:4326 (WGS_1984) and the spatial reference of the feature is wkid:4269 (GRS_1980) (not sure why I saw it as null before).

Newbie question

  • Why are my features using one spatial reference whereas the location listener is receiving coordinates in different spatial reference? 

I see that I can create a new Point assigning it the same spatial reference as my feature and location as received from my location listener but is there a way to acquire/request the feature and/or point to use the same spatial reference?

Is it cheaper for me to re-create the point and assign the spatial ref or use the GeometryEngine.project method?

0 Kudos
CharlesLoftis
New Contributor III

BTW, both of the options below work - not sure which one is "best". I suspect that re-creating the point may be a bit cheaper, but the projecting makes the code more readable.

if (GeometryEngine.within(new Point(l.getPosition().getX(), l.getPosition().getY(), feature.getGeometry().getSpatialReference()), feature.getGeometry())) {
if (GeometryEngine.within(GeometryEngine.project(l.getPosition(), feature.getGeometry().getSpatialReference()), feature.getGeometry())) {
0 Kudos
ShellyGill1
Esri Contributor

> Why are my features using one spatial reference whereas the location listener is receiving coordinates in different spatial reference?

Location comes from the location provider in the Android framework - the data provided by that uses WGS84. You can combine data from many different data sources within a map view, and different data sources might have different spatial references. We preserve the spatial reference of the data that's there - we just reproject them automatically if possible (i.e. when the spatial reference is known) when we display them, so the data aligns with eachother. Unless otherwise specified, the map view will use the spatial reference of the first layer it loads (might typically be the basemap).

I see that I can create a new Point assigning it the same spatial reference as my feature and location as received from my location listener but is there a way to acquire/request the feature and/or point to use the same spatial reference?

 

You can use the GeometryEngine.project method to project a geometry from one spatial reference to another, which results in a copy of the geometry (geometries are immutable). The feature belongs to it's containing dataset - you cant change the spatial reference of one feature's geometry. 

Is it cheaper for me to re-create the point and assign the spatial ref or use the GeometryEngine.project method?

Good question Charles, and I honestly don't know the answer. My guess would be if you've already got a handle to the spatial reference you want to use, then that might probably be quicker, but I'm really not sure.