Select to view content in your preferred language

.setDefinitionExpression using geometry?

2102
15
Jump to solution
05-29-2018 06:43 AM
JamesCrandall
MVP Frequent Contributor

Probably multiple ways to handle this, but I need to set a definition expression on a polygon FeatureLayer using the intersection of another polygon FeatureLayer.  I had been simply using a WHERE clause on an attribute, but the requirement has changed to use the geometry from a different FeatureLayer.

Any help is appreciated.

What I have so far:

createFuncLocLayer: function () {
      this.funcLocLayer = new FeatureLayer(this.config.functionalLocationLayer);
      this.workplanBoundaryLayer.queryFeatures(this.queryWorkplanLayer(), lang.hitch(this, function (result) {
        var wpGeometry = geometryEngine.geodesicBuffer(result.features[0].geometry, -20, "meters")
        
        //How can I apply this.funcLocLayer.setDefinitionExpression to use the wpGeometry variable?

      }));
0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

James,

   A Query class has a where property and a geometry property. You may be use to using the where but you can also just use the geometry property instead or or in addition to the where property.

createFuncLocLayer: function () {
  this.funcLocLayer = new FeatureLayer(this.config.functionalLocationLayer);
  var def = new Deferred();
  if(!this.workplanBoundaryLayer.loaded){
    this.workplanBoundaryLayer.on("load" lang.hitch(this, function(){
      def.resolve(this.workplanBoundaryLayer.graphics[0]);
    }));
  }else{
    def.resolve(this.workplanBoundaryLayer.graphics[0]);
  }
  def.then(lang.hitch(this, function(result){
    var geom = result;
    var wpGeometry = geometryEngine.geodesicBuffer(geom, -20, "meters");
    var query = new Query();
    query.outFields = ["*"];
    query.returnGeometry = true;
    query.outSpatialReference = this.map.spatialReference;
    query.geometry = wpGeometry;
    this.funcLocLayer.queryIds(query, lang.hitch(this,function(objectIds) {
      var qStr = this.funcLocLayer.objectIdField + " IN(" +objectIds.join(',') + ")";
      this.funcLocLayer.setDefinitionExpression(qStr ); 
    });
  }));
...
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

View solution in original post

15 Replies
RobertScheitlin__GISP
MVP Emeritus

James,

   You can not use a Geometry in a layers definition expression. What you have to do is turn that geometry into a sql expression. So you use the geometry to query the OIDs of the layer that intersect (or what ever spatial relationship you want) and then send that array of ObjectIds to the layer definition expression.

createFuncLocLayer: function () {
  this.funcLocLayer = new FeatureLayer(this.config.functionalLocationLayer);
  this.workplanBoundaryLayer.queryFeatures(this.queryWorkplanLayer(), lang.hitch(this, function (result) {
    var wpGeometry = geometryEngine.geodesicBuffer(result.features[0].geometry, -20, "meters");
    var query = new Query();
    query.geometry = wpGeometry;
    ...
    //Add other necessary query prperties such as spatial relationship
    this.funcLocLayer.queryIds(query, lang.hitch(this,function(objectIds) {
      var qStr = this.funcLocLayer.objectIdField + " IN(" +objectIds.join(',') + ")";
      this.funcLocLayer.setDefinitionExpression(qStr ); 
    });
  }));
...
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
JamesCrandall
MVP Frequent Contributor

hmm.  So I will need to first select on funcLocLayer, collect OID's and then use those to setDefinitionExpression on that same FeatureLayer? 

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

James,

   Maybe you better explain your workflow.

0 Kudos
JamesCrandall
MVP Frequent Contributor

I have two polygon Feature Layers:

  • FeatureLayer1 always has a single(1) polygon feature.
  • FeatureLayer2 has thousands of polygon features.

Requirement: Apply definition query/expression to FeatureLayer2 so that the only features available (throughout the entire session) in the map are those that intersect with the single polygon in FeatureLayer1.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

James since FeatureLayer1 will only ever have on Polygon you don't really need a query for that. Just make sure FeatureLayer1 is loaded and grab the first graphic.

i.e.

var geom = FeatureLayer1.graphics[0];

Then run a query on FeatureLayer2 using the geom from the previous as mentioned earlier and then apply the definition query to FeatureLayer2.

JamesCrandall
MVP Frequent Contributor

Good point.

0 Kudos
JamesCrandall
MVP Frequent Contributor

It's very unclear to me how to .execute on the queryTask without having to jump to another showResult function.  Also, I haven't found how to replace the query.where with a query.geometry property.

Do you have any examples of querying with the geometry?

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

James,

   A Query class has a where property and a geometry property. You may be use to using the where but you can also just use the geometry property instead or or in addition to the where property.

createFuncLocLayer: function () {
  this.funcLocLayer = new FeatureLayer(this.config.functionalLocationLayer);
  var def = new Deferred();
  if(!this.workplanBoundaryLayer.loaded){
    this.workplanBoundaryLayer.on("load" lang.hitch(this, function(){
      def.resolve(this.workplanBoundaryLayer.graphics[0]);
    }));
  }else{
    def.resolve(this.workplanBoundaryLayer.graphics[0]);
  }
  def.then(lang.hitch(this, function(result){
    var geom = result;
    var wpGeometry = geometryEngine.geodesicBuffer(geom, -20, "meters");
    var query = new Query();
    query.outFields = ["*"];
    query.returnGeometry = true;
    query.outSpatialReference = this.map.spatialReference;
    query.geometry = wpGeometry;
    this.funcLocLayer.queryIds(query, lang.hitch(this,function(objectIds) {
      var qStr = this.funcLocLayer.objectIdField + " IN(" +objectIds.join(',') + ")";
      this.funcLocLayer.setDefinitionExpression(qStr ); 
    });
  }));
...
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
JamesCrandall
MVP Frequent Contributor

Thank you for that! 

I never would have thought to implement what you did there with the Deferred.  So many unknowns.  Overwhelming really.

Is there an ending ")" missing for this?

this.workplanBoundaryLayer.on("load" lang.hitch(this, function(){

I get an "expected ;" error here on the second ")":

if(!this.workplanBoundaryLayer.loaded){

this.workplanBoundaryLayer.on("load" lang.hitch(this, function(){

def.resolve(this.workplanBoundaryLayer.graphics[0]);

})); //error on this line says "expected ;"

}else{

def.resolve(this.workplanBoundaryLayer.graphics[0]);

}

0 Kudos