Query statistics by geometry

Note: Support for 3D on mobile devices may vary, view the system requirements for more information.

This sample demonstrates how to query for statistics in a FeatureLayerView by geometry and display the results of the query in a chart.

This application displays 2010 population density by census tracts. The population is queried by age and gender among census tracts intersecting a buffer, and is displayed in a population pyramid chart.

How it works

The population pyramid chart is updated as the user drags the center point of the buffer or resizes the buffer by moving its edge handler point. As the user moves one of the two points, a geodesic buffer is recalculated and used to query the statistics of all features in the layer view that intersect the buffer. The center and edge handler points of the buffer graphic are updated by listening to the move events on SketchViewModel.

// Listen to sketch view model's move events when user clicks
// on the center or edge graphic. When users move these graphics
// run a client side stats query to return total number of population
// by gender for the census tracts that intersect the buffer
sketchViewModel.on("move-start", bufferMoveHandler);
sketchViewModel.on("move", bufferMoveHandler);
sketchViewModel.on("move-complete", bufferMoveHandler);

/*********************************************************************
* Edge or center graphics are being moved. Recalculate the buffer with
* updated geometry information and run the query stats again.
*********************************************************************/
function bufferMoveHandler(event) {
  // user is moving the CENTER graphic. Move the buffer polygon graphic,
  // line graphic, center and edge point graphics to the pointer location
  if (event.graphic.attributes && event.graphic.attributes.center) {
    // center graphic is initially created when view loads at the view.center
    // in drawBufferPolygon() function
    centerGraphic.geometry = event.geometry;

    const edgeScreenPoint = view.toScreen(edgeGraphic.geometry);
    const adjustedGeometry = view.toMap(edgeScreenPoint.x + event.dx, edgeScreenPoint.y + event.dy);
    edgeGraphic.geometry = adjustedGeometry;

    // updated vertices for the polyline
    vertices = [
      [centerGraphic.geometry.x, centerGraphic.geometry.y],
      [adjustedGeometry.x, adjustedGeometry.y]
    ];
  }
  // user is moving on the EDGE graphic. Resize the polyline graphic
  // and recalculate the buffer polygon
  else if (event.graphic.attributes && event.graphic.attributes.edge) {
    // EdgeGraphic is initially created in drawBufferPolygon() function when view is loaded
    edgeGraphic.geometry = event.geometry;
    vertices = [
      [centerGraphic.geometry.x, centerGraphic.geometry.y],
      [edgeGraphic.geometry.x, edgeGraphic.geometry.y]
    ];
  }
  // client-side stats query of features that intersect the buffer
  calculateBuffer(vertices);
}

The updated buffer polygon is then used to query statistics to get total population belonging to different age categories by gender among census tracts. Once the statistics query results are returned, the information is displayed in the population pyramid chart.

/*********************************************************************
 * Spatial query the census tracts feature layer view for statistics
 * using the updated buffer polygon.
*********************************************************************/
function queryLayerViewAgeStats(buffer) {
  // female and male age group stats array for the chart
  let femaleAgeData = [],
    maleAgeData = [];

  // client-side spatial query: get a sum of age groups for
  // census tracts that intersect the polygon buffer
  const query = featureLayerView.layer.createQuery();
  query.outStatistics = statDefinitions;
  query.geometry = buffer;

  // query the features on the client using FeatureLayerView.queryFeatures
  return featureLayerView.queryFeatures(query).then(function (results) {
    // statistics query returns a feature with stats attributes
    const attributes = results.features[0].attributes;
    // loop through stats attributes and add the values
    // to gender arrays to be used for the population pyramid.
    for (var key in attributes) {
      if (key.includes("FEM")) {
        femaleAgeData.push(attributes[key]);
      } else {
        // make all male age group population total negative so that
        // data will be displayed to the left of female age group
        maleAgeData.push(-Math.abs(attributes[key]));
      }
    }
    // return sum of age groups by gender
    return [femaleAgeData, maleAgeData];
  })
    .catch(function (error) {
      console.log(error)
    });
}
Loading...

Sample search results

TitleSample