geometryService.distance not returning what's expected

2178
4
Jump to solution
02-19-2016 01:10 PM
RaymondGoins
Occasional Contributor

This is killing me. Been working on this for hours and can't seem to work this out.

Here is my function.

function selectInBuffer(results){
        //console.log(results);
        sResults = {displayFieldName: null, features:[]};
        var feat;
        var features = results.features;

        for (var i = 0; i < features.length; i++) {
          var feat = features;
          tfeat = feat;
          var distParams = new DistanceParameters();
          distParams.distanceUnit = geometryService.UNIT_FOOT;
          distParams.geometry1 = pt;
          distParams.geometry2 = feat.geometry;
          distParams.geodesic = true;
          distp = geometryService.distance(distParams);
          console.dir(distp);
          tfeat.dist = distp;
          feat.setSymbol(symbol2);
          feat.setInfoTemplate(infoTemplate);
          map.graphics.add(feat);
          if (!sResults.displayFieldName){ sResults.displayFieldName = results.displayFieldName }
                sResults.features.push(feat);

        }
        console.log(tfeat);
        registry.byId("grid").set("content", formatResults(results));
        //console.log(sResults);
      }

According to all the samples I have seen, var distp should be just a number. I am getting back an object that I can't seem to do anything with it.

Here is what is return with firebug

gsd1.jpg

gsd2.jpg

What I am trying to do is create a buffer, which works fine. Then query a layer to return the features in that buffer, again works fine. What I am doing here is loop through those results to push a field into the object array with the distance. Then I want to sort the array based on the distance. Then show the results in a grid.

Thanks in advance for help.

Ray

0 Kudos
1 Solution

Accepted Solutions
RaymondGoins
Occasional Contributor

I decided to use geometryEngine instead. I then sent the results to a php script through ajax, queried the data, added the distance then sorted the array with PHP. Works rather well.

Thanks for your help.

Ray

View solution in original post

0 Kudos
4 Replies
RobertScheitlin__GISP
MVP Emeritus

Raymond,

  The GeometryService.distance method returns a deferred

Name                                                      Return Type  Summary

distance(params, callback?, errback?)    Deferred        Measures the planar or geodesic distance between geometries.

So you function should look more like this:

      function selectInBuffer(results){
        //console.log(results);
        sResults = {displayFieldName: null, features:[]};
        var feat;
        var features = results.features;
  
        for (var i = 0; i < features.length; i++) {
          var feat = features;
//I am not sure where tfeat comes from!!!
          tfeat = feat;
          var distParams = new DistanceParameters();
          distParams.distanceUnit = geometryService.UNIT_FOOT;
          distParams.geometry1 = pt;
          distParams.geometry2 = feat.geometry;
          distParams.geodesic = true;
          //distp = geometryService.distance(distParams);
          //console.dir(distp);
          geometryService.distance(distParams, function(distance) {
//Again not sure where tfeat comes from or why you are setting the distance to it
            tfeat.dist = distance;
            feat.setSymbol(symbol2);
            feat.setInfoTemplate(infoTemplate);
            map.graphics.add(feat);
            if (!sResults.displayFieldName){
              sResults.displayFieldName = results.displayFieldName
            }
            sResults.features.push(feat);
          });
        }
        console.log(tfeat);
        registry.byId("grid").set("content", formatResults(results));
        //console.log(sResults);
      }
RaymondGoins
Occasional Contributor

Thanks for the response. Had a couple days off and just getting back to looking at my app.

To clarify some of my crazy code I will just try to explain what I am doing.

I have a feature. When the page loads I have a drop down of a distance the user would like to buffer. When the drop down changes the script runs and returns the results and selects them on the map and also shows a grid of those results. The results are not sorted in any way so I would like to sort them by the distance they are away from the original feature hence the distance function.

I took your suggestion and redid my function. Have 2 issues

1. When I push the distance value into the feat object it seems to be putting in the same value all the time. (see image)

2. Just got word they would like to add a where clause when running the buffer query. Can I do that???

The initial point is already on the map and is in the variable "pt" which is the center of the circle for the buffer.

here are the functions I have so far. I use jQuery also so the onchange event is jquery not esri.

onChane event

$("#buffer").change(function(){
map.graphics.clear();
var fbuffer = dom.byId("buffer").value;
//console.log(pt);
// When the buffer distance is changed create the new buffer and query.
circle = new Circle({
center: pt,
geodesic: false,
radius: fbuffer,
radiusUnit: "esriFeet",
spatialReference: pt.spatialReference
});
var graphic = new Graphic(circle, circleSymb);
map.graphics.add(graphic);
var query2 = new Query();
query2.outFields = ["*"];
query2.geometry = circle;
query2.returnGeometry = true;
query2.outSpatialReference = map.spatialReference;
query2.spatialRelationship = Query.SPATIAL_REL_CONTAINS;
console.dir(query2);
queryTask2.execute(query2, selectInBuffer);
});

Select function

function selectInBuffer(results){
//console.log(results);
sResults = {displayFieldName: null, features:[]};
var features = results.features;
for (i = 0; i < features.length; i++) {
var feat = features;
var distParams = new DistanceParameters();
distParams.distanceUnit = geometryService.UNIT_FOOT;
distParams.geometry1 = pt;
distParams.geometry2 = feat.geometry;
distParams.geodesic = true;
feat.setSymbol(symbol2);
feat.setInfoTemplate(infoTemplate);
map.graphics.add(feat);
geometryService.distance(distParams, function(distance) {
var d = distance;
console.log(feat);
// Add distance to feature object
feat['dist'] =  d;
console.log(feat);
if (!sResults.displayFieldName){ sResults.displayFieldName = results.displayFieldName }
// push feature into results object to use for the "show Feature" function
sResults.features.push(feat);
});
}
//console.log(feat);
registry.byId("grid").set("content", formatResults(sResults));
//console.log(sResults);
}

Function to format results for the grid this is where I would sort the results by distance

function formatResults(results)
{
console.log(results);
var template = "";
var wfeatures = results.features;
var ServLocArray = { 'STOP_NBR':'Stop#', 'SVC_LOC_NBR':'Svc Loc#', 'ACCT_NBR':'Acct#' ,'RespParty':'Resp Party', 'DAY_PHONE':'Day Phone', 'SLOC_DWELLING_CD':'Dwl Cd', 'Address':'Service Address', 'DIST': 'Dist', 'PipeType':'Pipe Type', 'INSTDATE':'Install Year', 'TIER1_FLAG':'Tier1?' };

/*wfeatures.sort(function(a,b){
  return a.dist-b.dist;
})   */
console.log(wfeatures);
template = "<i>Total features returned: " + wfeatures.length + "</i>";
template += '<table border="1" style="text-align:center;">';
template += "<tr>"
$.each(ServLocArray, function(tkey, tvalue){
  template += "<th>"+tvalue+"</th>"
});
template += "<th>act</th>";
template += "</tr>";
for (var i = 0, il = wfeatures.length; i < il; i++)
{
srvloc = wfeatures.attributes['SVC_LOC'];
var instyear = formatDate(wfeatures.attributes['INSTDATE'], 'yyyy');
template += "<tr>";
template += "<td>"+ wfeatures.attributes['STOP_NBR'] +"</td>";
template += "<td>"+ srvloc +' <a href="#" onclick="showFeature(sResults.features['+ i +']); return false;">(show)</a></td>';
template += "<td>"+ wfeatures.attributes['ACCT_NBR'] +"</td>";
template += '<td><div class="csspointer" style="color:blue;text-decoration:underline;" onClick="window.open(\'/gis/CstarQuery/'+srvloc+'\', \'\',  \'width=400,height=400,menubar=no,scrollbars=yes\')">'+ wfeatures.attributes['FNAME'] +" "+ wfeatures.attributes['LNAME'] +'</div></td>';
template += "<td>"+ format_phone(wfeatures.attributes['DAY_PHONE']) +"</td>";
template += "<td>"+ format_phone(wfeatures.attributes['SLOC_DWELLING_CD']) +"</td>";
template += "<td width='150'>"+ wfeatures.attributes['BLDGNBR'] +" "+ wfeatures.attributes['STNAME'] +" "+ wfeatures.attributes['SUFFIX'] +"</td>";
//template += "<td width='75'>"+ wfeatures.dist +"</td>";
template += "<td>"+ format_phone(wfeatures.attributes['DAY_PHONE']) +"</td>";
          template += "<td>"+ instyear +"</td>";
template += "<td>"+ wfeatures.attributes['TIER1_FLAG']  +"</td>";
template += '<td><div class="csspointer" style="color:blue;text-decoration:underline;" onClick="window.open(\'/gis/CstarQuery/'+srvloc+'\', \'\',  \'width=400,height=400,menubar=no,scrollbars=yes\')">CStar</div></td>';
template += "</tr>";
}

template += "</table>";

return template;
}

I hope that clarifies thing a bit. the tfeat was a temporary holder I was trying to create in order to sort the features. but dropped that idea and trying to just push the distance into the feat array.

gsd3.jpg

Thanks again for your help.

Ray

0 Kudos
RaymondGoins
Occasional Contributor

OK I got it adding the distance to the feature set. Now another problem. WTF!!!

When I loop through the results the buffer distance come through undefined. When i view the object in firebug the damn thing is there. Am I missing something???

I also have out figure out sorting the array.

function selectInBuffer(results){
        //console.log(results);
        sResults = {displayFieldName: null, features:[]};
        var features = results.features;
        if(features.length > 0)
        {
          $.each(results.features, function(k, v)
          {
            //console.log(k);
            var distParams = new DistanceParameters();
            distParams.distanceUnit = geometryService.UNIT_FOOT;
            distParams.geometry1 = pt;
            distParams.geometry2 = v.geometry;
            distParams.geodesic = true;
            v.setSymbol(symbol2);
            v.setInfoTemplate(infoTemplate);
            map.graphics.add(v);
            geometryService.distance(distParams, function(distance) {
              var d = distance;
              //console.log(features);
              // Add distance to feature object
              results.features.buffer = d;
              //console.log(results);
              if (!sResults.displayFieldName){ sResults.displayFieldName = results.displayFieldName }
              // push feature into results object to use for the "show Feature" function
              sResults.features.push(results.features);
            });
          });
        }
        registry.byId("grid").set("content", formatResults(results));
      }

function formatResults(results)
      {
        var template = "";
        var wfeatures = results.features;
        //console.log(results);
        /*wfeatures.sort(function(a,b){
          return a.dist-b.dist;
        }) */
        //console.log(wfeatures);
        var ServLocArray = { 'STOP_NBR':'Stop#', 'SVC_LOC_NBR':'Svc Loc#', 'ACCT_NBR':'Acct#' ,'RespParty':'Resp Party', 'DAY_PHONE':'Day Phone', 'SLOC_DWELLING_CD':'Dwl Cd', 'Address':'Service Address', 'DIST': 'Dist', 'PipeType':'Pipe Type', 'INSTDATE':'Install Year', 'TIER1_FLAG':'Tier1?' };

        template = "<i>Total features returned: " + wfeatures.length + "</i>";
        template += '<table border="1" style="text-align:center;">';
        template += "<tr>"
        $.each(ServLocArray, function(tkey, tvalue){
          template += "<th>"+tvalue+"</th>"
        });
        template += "<th>act</th>";
        template += "</tr>";
        if(wfeatures.length > 0)
        {
          $.each(wfeatures, function(k, v) {
            console.log(v);
            srvloc = v['attributes']['SVC_LOC'];
            ptype = v['attributes']['DIAM'] + '" ' + v['attributes']['PIPETYPE'];
            var bdist = v['buffer'];
            var instyear = formatDate( v['attributes']['INSTDATE'], 'yyyy');
            template += "<tr>";
            template += "<td>"+  v['attributes']['STOP_NBR'] +"</td>";
            template += "<td>"+ srvloc +' <a href="#" onclick="showFeature(sResults.features['+ k +']); return false;">(show)</a></td>';
            template += "<td>"+  v['attributes']['ACCT_NBR'] +"</td>";
            template += '<td><div class="csspointer" style="color:blue;text-decoration:underline;" onClick="window.open(\'/gis/CstarQuery/'+srvloc+'\', \'\',  \'width=400,height=400,menubar=no,scrollbars=yes\')">'+  v['attributes']['FNAME'] +" "+  v['attributes']['LNAME'] +'</div></td>';
            template += "<td>"+ format_phone( v['attributes']['DAY_PHONE']) +"</td>";
            template += "<td>"+ v['attributes']['SLOC_DWELLING_CD'] +"</td>";
            template += "<td width='150'>"+  v['attributes']['BLDGNBR'] +" "+  v['attributes']['STNAME'] +" "+  v['attributes']['SUFFIX'] +"</td>";
            template += "<td width='75'>"+  bdist +"</td>";
            template += "<td>"+ ptype +"</td>";
            template += "<td>"+ instyear +"</td>";
            template += "<td>"+  v['attributes']['TIER1_FLAG']  +"</td>";
            template += '<td><div class="csspointer" style="color:blue;text-decoration:underline;" onClick="window.open(\'/gis/CstarQuery/'+srvloc+'\', \'\',  \'width=400,height=400,menubar=no,scrollbars=yes\')">CStar</div></td>';
            template += "</tr>";
          });
        } else {
          template += '<tr><td colspan="12">No Results found</td></tr>';
        }
        template += "</table>";
        return template;
      }

gsd4.jpg

gsd5.jpg

Thanks again

Ray

0 Kudos
RaymondGoins
Occasional Contributor

I decided to use geometryEngine instead. I then sent the results to a php script through ajax, queried the data, added the distance then sorted the array with PHP. Works rather well.

Thanks for your help.

Ray

0 Kudos