Selecting features from an offline geodatabase

4537
6
Jump to solution
12-01-2014 06:09 PM
ForrestKaye
New Contributor III

I am having trouble selecting features from an offline geodatabase.

I am following the 'Select Features' sample.  I have switched all that parameters to work off of a local gdb.  So I am passing in: QueryParameter() and SelectionMode.  Instead of: Query() and SELECTION_METHOD.  I have also added a .setSelectionColor & .setSelectionColorWidth to the featureLayers in my map.  However, nothing seems to get selected after I create the envelope and release.

Here is some Sample

FeatureLayer fLayer = null;

//added to Mapview in onCreate
localGdb = new Geodatabase(FeatureInformation.getInstance().activeGeodatabasePathString);
for (GeodatabaseFeatureTable gdbFeatureTable : localGdb.getGeodatabaseTables()) {
     if (gdbFeatureTable.hasGeometry()) {
          fLayer = new FeatureLayer(gdbFeatureTable);
          fLayer.setSelectionColor(12828800);
          fLayer.setSelectionColorWidth(30);
          mMapView.addLayer(fLayer);
     }
}
localGdb.dispose();


//This is inside of onDragPointerUp just like Select Features sample
QueryParameters q = new QueryParameters();
//q.setWhere("FEATURE='Fire'");
q.setReturnGeometry(true);
q.setInSpatialReference(mMapView.getSpatialReference());
q.setGeometry(g.getGeometry());
q.setSpatialRelationship(SpatialRelationship.INTERSECTS);
fLayer.selectFeatures(q, SelectionMode.NEW, callback);
0 Kudos
1 Solution

Accepted Solutions
ForrestKaye
New Contributor III

After some time of playing with this.  I finally figured it out with the help of an esri tech.  Essentially where I was going wrong was  referencing my GeodatabaseFeatureTables.  I was creating a new instance of a localGeodatabase inside of my function that was trying to select my features.

Everything was solved once I created a global variable for my localGeodatabase at the same time I was adding those layers into the map. 

Thanks for all your help on Dave!  I wouldn't have gotten as far on it without your help. 

-Cheers

View solution in original post

0 Kudos
6 Replies
DavidMartin
Occasional Contributor II

I'd have thought you need a where clause?? To get back all records found by the spatial filter, try:

q.setWhere("1=1");

You may also need to specify your output fields?? To get back all fields try:

q.setOutFields("*");

And I guess it's probably worth specifying the output spatial reference:

q.setOutSpatialReference(mMapView.getSpatialReference());

Also, where does the graphic, g, come from? Make sure of the obvious - that it does intersect with some of your features(!) - and that its geometry is definitely in a spatial reference equivalent to that of the MapView. You could check this with the condition:

(g.getSpatialReference() == mMapView.getSpatialReference())

0 Kudos
ForrestKaye
New Contributor III

Thank you very much for your reply.  I have noticed that my variable g (my graphic) does not have a spatial reference.  It is null.  I tried several things but can not seem to rectify this by any means.

I am now trying to figure out how to give it a spatial reference.  It is derived from a graphicsLayer which has a spatial reference.  I'm not sure I am understanding the relationship between the graphic, graphicLayer and Envelope.

Here is a better sample of my code.  Should a graphic inherit a spatial relationship from a graphics layer?  I don't see a way to create a graphic with a spatial relationship or a way to set one.  Do I need to project it (this would seem overly complex)?

Thank you very much for your help.

GraphicsLayer gLayerSelect = new GraphicsLayer();  //Global Var
gLayerSelect = new GraphicsLayer(mMapView.getSpatialReference(),null,RenderingMode.DYNAMIC); //Defined in on Create
mMapView.addLayer(gLayerSelect);//added in on Create

private class MyTouchListener extends MapOnTouchListener {
     Graphic g;
     Point p0 = null;
     int uid = -1;
     SimpleFillSymbol sfs;

public MyTouchListener(Context context, MapView view) {
     super(context, view);
     sfs = new SimpleFillSymbol(Color.BLACK);
     sfs.setOutline(new SimpleLineSymbol(Color.RED, 2));
     sfs.setAlpha(100);
}

public boolean onDragPointerMove(MotionEvent from, MotionEvent to) {
     if (uid == -1) { // first time
          //Geometry xGeometry = mMapView.toMapPoint(new Point(from.getX(), to.getY()));
          //g = new Graphic(xGeometry, sfs);
          g = new Graphic(null, sfs);//original
          p0 = mMapView.toMapPoint(from.getX(), from.getY());
          uid = gLayerSelect.addGraphic(g);
     } else {
          Point p2 = mMapView.toMapPoint(new Point(to.getX(), to.getY()));
          Envelope envelope = new Envelope();
          envelope.merge(p0);
          envelope.merge(p2);
          gLayerSelect.updateGraphic(uid, envelope);
     }
     return true;
}

public boolean onDragPointerUp(MotionEvent from, MotionEvent to) {
     if (uid != -1) {
          g = gLayerSelect.getGraphic(uid);
          if (g!= null && g.getGeometry() != null) {
               fLayer.clearSelection();
               QueryParameters q = new QueryParameters();
               q.setWhere("1=1");
               q.setOutSpatialReference(mMapView.getSpatialReference());
               q.setReturnGeometry(true);
               q.setInSpatialReference(mMapView.getSpatialReference());
               q.setGeometry(g.getGeometry());
               q.setSpatialRelationship(SpatialRelationship.INTERSECTS);
               fLayer.selectFeatures(q, SelectionMode.NEW, callback);
               
               if (g.getSpatialReference() == mMapView.getSpatialReference()){
                    String X = "";
               }
          }
          gLayerSelect.removeAll();
     }
     p0 = null;
     uid = -1;
     return true;
}
0 Kudos
DavidMartin
Occasional Contributor II

Looking at your code, I doubt if the spatial reference is a real issue. After all, the geometry is being derived from the map.

Perhaps instead you could try an alternative approach that would also allow you to inspect the query results? Use queryFeatures (with your QueryParameters) on your GeodatabaseFeatureTable and inspect the results in the callback. If you are getting results, you could then select them individually, by iterating them and using Featurelayer.selectFeature on each. (I've not tried it but it looks like a viable approach! )

David

Sent from Samsung Mobile

0 Kudos
ForrestKaye
New Contributor III

I followed your advice and I was able to select the features via queryFeatures with a simple where "1=1" query.  After that I was also able to select features via a spatial query. 

After much digging I have found the source of the problem is but still don't know the cause or a solution.  It seems that there is a disconnect between my global variable that is a feature layer when it is added to the map view and when I try to use it inside of my MyTouchListener class.  Or it has to do with the declaration of the call back as a global variable.  However, both of these are exactly how the Select Features sample has them declared.

1. The only way I can get the FeatureLayer.SelectFeatures(QueryParamaters,...) to work is to add that layer to the mapview at time of selectFeatures.  This leads to duplicate layers. 

2.  On the other hand I can use the global featureLayer when using the method described above using queryfeatures on the geodatabaseFeature table then passing the oids captured in the callback to FeatureLayer.selectFeatures(long[] oids,..)   However using this method in a dynamic way for any/all layers possibly present in a map is proving logically difficult. 

3.  Tried using and this does not work either.  mmapview.getLayers() does not refer back to the actual map layers after I cast them to FeatureLayer.

Layer[] allLayers = mMapView.getLayers();
for (Layer layer : allLayers) {
     try{
          FeatureLayer xFeatureLayer = (FeatureLayer) layer;
          QueryParameters q = new QueryParameters();
          q.setGeometry(g.getGeometry()) //g being a qualifying graphic
          q.setSpatialRelationship(SpatialRelationship.INTERSECTS)
          //other qualifying query paramaters...
          //....
          xFeatureLayer.selectFeatures(q, SelectionMode.NEW, callback);
          }catch (Exception ee) {
               ee.printStackTrace();
          }
     }

So I still don't have a way to select features without adding new Feature layers in at time of query OR capture all Featurelayers added to the map as global variables, then do a combination of queryFeatures and SelectFeatures(long[] oids, ...).  Neither of these seem like the intended way of handling this.

Any thoughts?  Your continued thoughts/help is much appreciated.  Thanks!

0 Kudos
DavidMartin
Occasional Contributor II

I'm only guessing now, but...

1/ How are you instantiating your FeatureLayer? From the GeodatabaseFeatureTable?

2/ Do the FeatureLayer, GeodatabaseFeatureTable (and MapView?) objects all share the same scope?

Sent from Samsung Mobile

0 Kudos
ForrestKaye
New Contributor III

After some time of playing with this.  I finally figured it out with the help of an esri tech.  Essentially where I was going wrong was  referencing my GeodatabaseFeatureTables.  I was creating a new instance of a localGeodatabase inside of my function that was trying to select my features.

Everything was solved once I created a global variable for my localGeodatabase at the same time I was adding those layers into the map. 

Thanks for all your help on Dave!  I wouldn't have gotten as far on it without your help. 

-Cheers

0 Kudos