Issues with buffering selected features/query task

5503
22
Jump to solution
10-15-2014 08:02 AM
RyanSellman
Occasional Contributor II

I am trying to give users the ability to select features from a specific feature layer, buffer that selection and query another feature layer using the geometries from the buffer.  I want results from the first selection to be sent to one datagrid and results from the second query to be sent to a different datagrid.  I think I am really close - the way I have it set up now is the user can draw a box to select features (points in this case).  When the drawing ends, it select features within the drawn extent, performs a buffer at a set distance on those features, and uses the buffer extent to select features from a polygon layer.  This all works just fine however, the issue I am having is with the two datagrids.  For some reason, data from the first selection is being pushed to both datagrids.

Here is a bit of JS:

dojo.connect(map, "onLoad", function(map) {

    //initialize the toolbar

    toolBar2 = new esri.toolbars.Draw(map);

    dojo.connect(toolBar2, "onDrawEnd", onDrawEnd);

});

var featureLayerUrl = "http://summitmaps.summitoh.net/arcgis/rest/services/DOES_Mercator/MapServer/2";

featureLayer = new esri.layers.FeatureLayer(featureLayerUrl, {

    mode: esri.layers.FeatureLayer.MODE_SELECTION,

    outFields: ["UNAME", "INSTALLYR", "DNAME", "STREET", "EASEMENT", "INVERT", "OWNERSHIP"]

});

featureLayer.setSelectionSymbol(new esri.symbol.SimpleMarkerSymbol().setSize(8).setColor(new dojo.Color([160, 214, 238])));

map.addLayer(featureLayer);

function onDrawEnd(extent) {

    var newStore = new dojo.data.ItemFileReadStore({

        data: {

            identifier: "",

            items: []

        }

    });

    var grid = dijit.byId("manholeGrid");

    manholeGrid.setStore(newStore);

    toolBar2.deactivate();

    var query = new esri.tasks.Query();

    query.geometry = extent;

    featureLayer.selectFeatures(query, esri.layers.FeatureLayer.SELECTION_NEW, function(features, selectionMethod) {

        var items30 = dojo.map(features, function(feature) {

            return feature.attributes;

        });

        var data30 = {

            identifier: "OBJECTID",

            items: items30

        };

        var store30 = new dojo.data.ItemFileReadStore({

            data: data30

        });

        var manholeGrid = registry.byId("manholeGrid");

        manholeGrid.on("rowclick", onRowClickHandler);

        manholeGrid.setStore(store30);

        map.setExtent(graphicsUtils.graphicsExtent(featureLayer.getSelectedFeatures()), true);

        gsvc = new GeometryService("http://summitmaps.summitoh.net/arcgis/rest/services/Utilities/Geometry/GeometryServer");

        var graphics = featureLayer.graphics;

        var selectedGeoms = graphicsUtils.getGeometries(graphics);

        var params = new BufferParameters();

        params.geometries = selectedGeoms;

        params.distances = [500];

        params.unit = GeometryService.UNIT_FOOT;

        params.outSpatialReference = map.spatialReference;

        gsvc.buffer(params, showBuffer);

        function showBuffer(geometries) {

            var symbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID, SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,

                    new Color([0, 0, 255, 0.65]), 2

                ),

                new Color([0, 0, 255, 0.35])

            );

            arrayUtils.map(geometries, function(geometry) {

                var graphic = new Graphic(geometry, symbol);

                map.graphics.add(graphic);

            });

            queryTaskNew = new esri.tasks.QueryTask("http://summitmaps.summitoh.net/arcgis/rest/services/Cadastral/Parcels/MapServer/0");

            var queryNew = new esri.tasks.Query();

            queryNew.returnGeometry = true;

            queryNew.outFields = ["PARID", "ADDR"];

            queryNew.geometry = geometries[0];

            queryTaskNew.execute(queryNew, showResults300);

            function showResults300(featureSet) {

                var resultFeatures = featureSet.features;

                for (var i = 0, il = resultFeatures.length; i < il; i++) {

                    var items300 = dojo.map(features, function(feature) {

                        return feature.attributes;

                    });

                    var data300 = {

                        identifier: "OBJECTID",

                        items: items300

                    };

                    var store300 = new dojo.data.ItemFileReadStore({

                        data: data300

                    });

                    var grid = registry.byId("parcelGrid");

                    grid.on("rowclick", onRowClickHandler);

                    grid.setStore(store300);

                }

            }

        };

    });

And here is the HTML as it pertains to the above code:

<div data-dojo-type="dijit/layout/ContentPane" title="Manhole">

                    <input type="text" id="doesManholeText" value="BA15" />

                    <button id="doesManholeSearch" data-dojo-type="dijit.form.Button" type="button" data-dojo-attach-point="button">Search</button>

                    <button data-dojo-type="dijit.form.Button" onClick="toolBar2.activate(esri.toolbars.Draw.EXTENT);">Select</button>

                    <button id="clearManholeGrid" data-dojo-type="dijit.form.Button" type="button" data-dojo-attach-point="button">Clear</button>

                    <span id="manhole-result-count"></span>

                    <table data-dojo-type="dojox/grid/DataGrid" data-dojo-id="manholeGrid" id="manholeGrid" style="height: 340px" data-dojo-props="rowsPerPage:'100', rowSelector:'20px'">

                        <thead>

                            <tr>

                                <th field="UNAME">UNAME</th>

                                <th field="INSTALLYR">Install Year</th>

                                <th field="DNAME">DNAME</th>

                                <th field="STREET">Street</th>

                                <th field="EASEMENT">Easement</th>

                                <th field="INVERT">Invert</th>

                                <th field="OWNERSHIP">Ownership</th>

                            </tr>

                        </thead>

                    </table>

                </div>

<div id="bottom" data-dojo-type="dojox/layout/ExpandoPane" title="Click the Arrow to Minimize this Panel" data-dojo-props="title: 'Parcel Search', splitter:true, startExpanded: false, region:'bottom'" style="height: 300px;">

    <div data-dojo-type="dijit/layout/ContentPane" title="Selected Parcels">

        <table data-dojo-type="dojox.grid.DataGrid" data-dojo-id="parcelGrid" id="parcelGrid" style="height: 300px" data-dojo-props="rowsPerPage:'100', rowSelector:'20px'">

            <thead>

                <tr>

                    <th field="PARID">Parcel #</th>

                    <th field="ADDR">Address</th>

                </tr>

            </thead>

        </table>

    </div>

</div>

Can anyone see why I can't get results from the second query, in this case, "queryTaskNew" into the appropriate datagrid?

Any help is much appreciated!!

0 Kudos
22 Replies
DavidChrest
Occasional Contributor II

Robert,

OK, I believe I did this right but all points are still getting buffered instead of only the ones I select. I put the buffering in a function following the selection. See line 10 below. I do not see what I am doing wrong. Any help is immensely appreciated. (I'm a bit of a newbie at some of this)

David

//Set the selection symbol to Day 1 Activities
  activitiesDay1.setSelectionSymbol(symbolSelectedTest);
  //Initialize the query
  var queryDay1ActivitiesTest = new Query();
  tbDrawTest.deactivate(); //turns off selection tool so it does not stay on in map.
  queryDay1ActivitiesTest.geometry = geometryInput;
  //Wire the layer's selection complete event
  activitiesDay1.on("selection-complete", populateGrid1);
  //Day 1 Activities selection
  activitiesDay1.selectFeatures(queryDay1ActivitiesTest, FeatureLayer.SELECTION_NEW, function (features, selectionMethod) {


  //Create buffer of selection
  gsvc = new GeometryService("http://sushi:6080/arcgis/rest/services/Utilities/Geometry/GeometryServer");


  var graphics1 = activitiesDay1.graphics;
  var selectedGeoms = graphicsUtils.getGeometries(graphics1);
  var params = new BufferParameters();
  params.geometries = selectedGeoms;


  params.distances = [500];
  params.unit = GeometryService.UNIT_FOOT;
  params.outSpatialReference = map.spatialReference;
  gsvc.buffer(params, showBuffer);




  function showBuffer(geometries) {
  var symbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID, SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
  new Color([0, 0, 255, 0.65]), 2
  ),
  new Color([0, 0, 255, 0.35])
  );


  array.map(geometries, function (geometry) {
  var graphic = new Graphic(geometry, symbol);
  map.graphics.add(graphic);
  });
  };


  });
  };
0 Kudos
RobertScheitlin__GISP
MVP Emeritus

David,

Nope not quite there yet. You need to work with the features that are returned from the selection method and not the layers original graphics.

//Day 1 Activities selection  
activitiesDay1.selectFeatures(queryDay1ActivitiesTest, FeatureLayer.SELECTION_NEW, function (features, selectionMethod) {

  //Create buffer of selection  
  gsvc = new GeometryService("http://sushi:6080/arcgis/rest/services/Utilities/Geometry/GeometryServer");  
  
  //No need for this //var graphics1 = activitiesDay1.graphics;  
  var selectedGeoms = graphicsUtils.getGeometries(features);  
  var params = new BufferParameters();  
  params.geometries = selectedGeoms; 
DavidChrest
Occasional Contributor II

Ryan,

See my notes and code below to Robert. I am having trouble trying get only my selected points to buffer. Instead, all points in my layer get buffered. Can you see where I am going wrong?

Thanks so much for any help you can provide.

David

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

David,

   Did you see my last reply?

0 Kudos
DavidChrest
Occasional Contributor II

Robert,

Yes! I missed it earlier this morning. Your corrections to my code worked wonderfully! Thanks so very much. My working snipped is below. I interactively select some points from my layer and now just those get buffered. Very nice! Now I can move on tp the rest of Ryan's sample code to have that buffer select features from another layer, which I understand much better and should go more smoothly.

I get individual buffers for every point I select but looks like they can easily be unioned to look neater utilizing "esri/geometry/geometryEngine." Ryan used this method in his web site he mentions above. See API page for geometryEngine here: https://developers.arcgis.com/javascript/jssamples/ge_geodesic_buffers.html.

Thanks so much again! I'll post my complete code once all complete. This seems to be functionality a lot of people would like in their web sites.

David

activitiesDay1.selectFeatures(queryDay1ActivitiesTest, FeatureLayer.SELECTION_NEW, function (features, selectionMethod) {


  //Create buffer of selection
  gsvc = new GeometryService("http://sushi:6080/arcgis/rest/services/Utilities/Geometry/GeometryServer");


  //var graphics1 = activitiesDay1.graphics;
  var selectedGeoms = graphicsUtils.getGeometries(features);
  var params = new BufferParameters();
  params.geometries = selectedGeoms;


  params.distances = [500];
  params.unit = GeometryService.UNIT_FOOT;
  params.outSpatialReference = map.spatialReference;
  gsvc.buffer(params, showBuffer);




  function showBuffer(geometries) {
  var symbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID, SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
  new Color([0, 0, 255, 0.65]), 2
  ),
  new Color([0, 0, 255, 0.35])
  );


  array.map(geometries, function (geometry) {
  var graphic = new Graphic(geometry, symbol);
  map.graphics.add(graphic);
  });
  };


  });
DavidChrest
Occasional Contributor II

Thanks so much to Ryan and Robert for their HUGE help. Below is my working code. I have the buffer distance hard-coded but plan to use an insert value. Use of the geometryEngine is a wonderful way to create buffers and have them union into a single polygon. The JS code below lets the user select points from FeatureLayer1, those selected points then get buffered (500 feet in this case). That buffer is then used to query and select any intersecting points from FeatureLayer2. Some incredibly handy functionality.

//<<<BUFFER OF SELECTED POINTS THEN SELECTS ANOTHER LAYER'S POINTS>>>


//Draw Day 1 tool initialization function
map.on("load", initDrawToolTest);


function initDrawToolTest(evt) {
tbDrawTest = new Draw(evt.map);
tbDrawTest.on("draw-end", displayPolygonTest);
}


//Draw Freehand Polygon for FeatureLayer1
on(dom.byId("TestSelect"), "click", function () {
tbDrawTest.activate(Draw.FREEHAND_POLYGON);
});


//Get geometry from FeatureLayer1 drawn polygon, symbolize polygon, start FeatureLayer1 query 
function displayPolygonTest(evt) {
// Get the geometry from the event object
var geometryInput = evt.geometry;
// Define symbol for finished polygon
var tbDrawSymbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID, new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([53, 119, 221]), 2), new Color([53, 119, 221, 0.3]));
map.graphics.clear();
var graphicPolygon = new Graphic(geometryInput, tbDrawSymbol);
map.graphics.add(graphicPolygon);
selectDay1ActivitiesTest(geometryInput); // Call the next function below...vvv
}


//Symbolize FeatureLayer1, create new Query, select features
function selectDay1ActivitiesTest(geometryInput) {
// Define symbol for selected features (using JSON syntax for improved readability)
var symbolSelectedTest = new SimpleMarkerSymbol({
  "type": "esriSMS",
  "style": "esriSMSCircle",
  "color": [255, 115, 0, 128],
  "size": 6,
  "outline": {
  "color": [255, 0, 0, 214],
  "width": 1
  }
});


//Set the selection symbol to FeatureLayer1
FeatureLayer1.setSelectionSymbol(symbolSelectedTest);
//Initialize the query
var queryDay1ActivitiesTest = new Query();
tbDrawTest.deactivate(); //turns off selection tool so it does not stay on in map.
queryDay1ActivitiesTest.geometry = geometryInput;
//Wire the layer's selection complete event, call function to populate grid with selection results
FeatureLayer1.on("selection-complete", populateGrid1);
//Day 1 Activities selection
FeatureLayer1.selectFeatures(queryDay1ActivitiesTest, FeatureLayer.SELECTION_NEW, function (features, selectionMethod) {


  //Create buffer of selection
  var selectedGeoms = graphicsUtils.getGeometries(features);
  var distance = [500];
  var bufferedGeometries = geometryEngine.geodesicBuffer(selectedGeoms, distance, GeometryService.UNIT_FOOT, true);


  var symbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID, SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
  new Color([0, 0, 255, 0.65]), 2
  ),
  new Color([0, 0, 255, 0.35])
  );


  array.map(bufferedGeometries, function (geometry) {
  var graphic = new Graphic(geometry, symbol);
  map.graphics.add(graphic);
  });


  //Variable represents Query area to select intersecting FeatureLayer2 points
  var geoBuffer = geometryEngine.union(bufferedGeometries);


  //Symbolize FeatureLayer2 selection
  var symbolSelected = new PictureMarkerSymbol({
  "type": "esriPMS",
  "url": "images/coffeeselect.png",
  "contentType": "image/png",
  "width": 20,
  "height": 22
  });
  symbolSelected.setOffset(-1, 0);


  //Set the selection symbol to FeatureLayer2
  FeatureLayer2.setSelectionSymbol(symbolSelected);
  //Select FeatureLayer2 points that intersect buffer
  var querySBTest = new Query();
  querySBTest.geometry = geoBuffer;
  querySBTest.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;
  //Wire the layer's selection complete event, call function to populate grid with selection results
  FeatureLayer2.on("selection-complete", populateGrid2);
  //FeatureLayer2 selection
  FeatureLayer2.selectFeatures(querySBTest, FeatureLayer.SELECTION_NEW);


});
};
0 Kudos
RyanSellman
Occasional Contributor II

Hi David,

So sorry for not getting back to you sooner - I have been out of the office.  Glad you were able to get things working!!

Ryan

0 Kudos
bharathreddy
Occasional Contributor

Hi all,

can u please post the complete working code and i what know which version you are using 3.5 or 3.8

thanks and regards

bharath

0 Kudos
RyanSellman
Occasional Contributor II

Hi Bharath,

I have a working example here:

Edit fiddle - JSFiddle

This is using version 3.14 of the API.

-Ryan

bharathreddy
Occasional Contributor

Hi Ryan,

The example which u sent is helpful but what i'm trying to do is please see the follow link

ArcGIS API for JavaScript Sandbox

im unable to get the buffer on click please suugest me

Bharath

0 Kudos