Finding all points from a csvLayer within a circle with ArcGIS Javascript

1479
2
Jump to solution
11-20-2019 11:35 AM
NathanRice
New Contributor II

I am new to GIS and I am trying to develop a webpage using the ArcGIS Javascript API. I am currently trying to figure out how to select all of the points from a csv that are within a circle. I have the user input a location and a radius for the circle and it is drawn on the map and all of the points from the csv are also displayed. I would like to find a way to display only the points within the circle and, ultimately, export these points to a new csv file.

I have tried following the tutorials at https://developers.arcgis.com/javascript/latest/sample-code/highlight-features-by-geometry/index.htm... and https://developers.arcgis.com/javascript/latest/sample-code/sandbox/index.html?sample=featurelayer-q... but these seem overly complicated for what I am trying to do. My code so far is shown below. Any help would be greatly appreciated. Thank you!

<!DOCTYPE html><html>  <head>    <meta charset="utf-8" />    <meta       name="viewport"      content="initial-scale=1,maximum-scale=1,user-scalable=no"    />    <title>KY Emissions Inventory</title>     <link       rel="stylesheet"      href="https://js.arcgis.com/4.13/esri/themes/light/main.css"    />      <script src="https://js.arcgis.com/4.13/"></script>     <style>      html,      body,      #viewDiv {        padding: 0;        margin: 0;        height: 100%;        width: 100%;      }    </style>        <script>        require([        "esri/Map",        "esri/views/MapView",        "esri/layers/CSVLayer",        "esri/views/SceneView",        "esri/layers/FeatureLayer",        "esri/layers/GraphicsLayer",        "esri/geometry/geometryEngine",        "esri/Graphic",        "esri/widgets/Slider",        "esri/widgets/Expand",        "esri/widgets/BasemapGallery",        "esri/geometry/Circle",        "esri/symbols/SimpleFillSymbol",        "esri/symbols/SimpleLineSymbol",        "esri/Color"       ], function(        Map,        MapView,        CSVLayer,        SceneView,        FeatureLayer,        GraphicsLayer,        geometryEngine,        Graphic,        Slider,        Expand,        BasemapGallery,        Circle,        SimpleFillSymbol,        SimpleLineSymbol,        Color,        ClassBreaksRenderer      )  {           var map = new Map({          basemap: "streets" //background layer        });          var view = new MapView({          container: "viewDiv",          map: map,        });         view.center = [-85.25, 37.96];        view.zoom = 8;          /********************          * Add feature layer          ********************/           var pTemplate = {          // autocasts as new PopupTemplate()          title: "Facility Information",          content: [            {              type: "fields",              fieldInfos: [                {                  fieldName: "Facility_ID",                  label: "National ID"                },                {                  fieldName: "Facility_Name",                  label: "Facility"                },                {                  fieldName: "Pollutant",                  label: "Pollutant"                },                {                  fieldName: "Emissions",                  label: "Emissions"                },                {                  fieldName: "latitude",                  label: "Latitude"                },                {                  fieldName: "longitude",                  label: "Longitude"                }                ]            }          ]                   };        /*DRAWING POINTS*/         const less10 = {            type: "simple-marker", // autocasts as new SimpleFillSymbol()            color: [0, 0, 255, 0.9],            size: 4,            outline: {                width: .5,                color: [1, 1, 1, 0.5]            }        };         const less100 = {            type: "simple-marker", // autocasts as new SimpleFillSymbol()            color: [212, 255, 0, 0.7],            size: 9,            outline: {                width: .5,                color: [1, 1, 1, 0.5]            }        };         const less500000 = {            type: "simple-marker", // autocasts as new SimpleFillSymbol()            color: [184, 19, 52, 0.5],            size: 18,            outline: {                width: .5,                color: [1, 1, 1, 0.5]            }        };         const renderer = { //the default ones have unreadable values. scientific notation doesn't play well with these            type: "class-breaks", // autocasts as new ClassBreaksRenderer()            field: "Emissions", // total number of adults (25+) with a college degree            defaultSymbol: {                type: "simple-marker", // autocasts as new SimpleFillSymbol()                color: "black",                size: 50,                outline: {                width: 0.1,                color: [50, 50, 50, 0.6]                }            },            defaultLabel: "no data", // legend label for features that don't match a class break            classBreakInfos: [            {            minValue: 0.00000001,            maxValue: 10,            symbol: less10,            label: "35 - 50%" // label for symbol in legend            },            {            minValue: 10,            maxValue: 100,            symbol: less100,            label: "< 35%" // label for symbol in legend            },            {            minValue: 100,            maxValue: Infinity,            symbol: less500000,            label: "35 - 50%" // label for symbol in legend            }        ]        };        /*END DRAWING POINTS*/         /*ADD CSV FILE*/     var fileName = "KY_NULL.csv"; //makes the page display a blank map until a pollutant is selected     var emissionsCSVLayer = new CSVLayer({          url:            fileName,            popupTemplate: pTemplate,            renderer: renderer         });       function getInputFile() {        emissionsCSVLayer = new CSVLayer({          url:            fileName,            popupTemplate: pTemplate,            renderer: renderer         });        map.add(emissionsCSVLayer);      };       getInputFile();       const styleSelect = document.getElementById("pollutant");        styleSelect.addEventListener("change", function(event) {          const value = event.target.value;          switch (value) {            case "SO2":              fileName = "KY_SO2.csv";              break;            case "CO":              fileName = "KY_CO.csv";              break;            case "PT": //particulate matter              fileName = "KY_PM.csv";              break;                case "PM2.5":              fileName = "KY_PM25.csv";              break;            case "PM10":              fileName = "KY_PM10.csv";              break;            case "VOC":              fileName = "KY_VOC.csv";              break;            case "null":              fileName = "KY_NULL.csv";              break;            case "As":              fileName = "KY_As.csv";              break;            case "Benzene":              fileName = "KY_Benzene.csv";              break;            case "CO2":              fileName = "KY_CO2.csv";              break;            case "H2SO4":              fileName = "KY_H2SO4.csv";              break;            case "NO2":              fileName = "KY_NO2.csv";              break;                  case "NOX":              fileName = "KY_NOX.csv";              break;            case "Pb":              fileName = "KY_Pb.csv";              break;            case "VinylChloride":              fileName = "KY_VinylChloride.csv";              break;                                  }          map.removeAll();          getInputFile();        });           /*ADD BASEMAP TOGGLE*/         var basemapGallery = new BasemapGallery({        view: view,        source: {          portal: {            url: "http://www.arcgis.com",            container: document.createElement("div")            //useVectorBasemaps: true, // Load vector tile basemap group          },        }        });       var bgExpand = new Expand({          view: view,          content: basemapGallery         });      view.ui.add(bgExpand, "bottom-left"); // Add to the view       /*END ADD BASEMAP TOGGLE*/       view.ui.add("menu", "top-right");          /*************************          * Create a point graphic          *************************/         // First create a point geometry (this is the location of the Titanic)          var pointExists = false;        var point = {          type: "point", // autocasts as new Point()          longitude: -85.970874,          latitude: 38.407351        };         var pointGraphic;        var circleGraphic;         function makeAPoint(){          point = {          type: "point", // autocasts as new Point()          longitude: parseFloat(long),//-85.970874,          latitude: parseFloat(lat)//38.407351         };         // Create a symbol for drawing the point        var markerSymbol = {          type: "simple-marker", // autocasts as new SimpleMarkerSymbol()          color: [1, 1, 1],          size: 1,          outline: {            // autocasts as new SimpleLineSymbol()            color: [1, 1, 1],            width: 1          }        };         // Create a graphic and add the geometry and symbol to it        pointGraphic = new Graphic({          geometry: point,          symbol: markerSymbol         });         view.graphics.addMany([pointGraphic]);          /*************************          * Create circles          *************************/          var outerCircle = new Circle({             center: [parseFloat(long),parseFloat(lat)],  // longitude & latitude of current location ( obtained in another function)             geodesic: true,             radius: parseFloat(outerCircleRadius),             // radius to search within ( it is global variable initialized early)            radiusUnit: "kilometers"             });            var innerCircle = new Circle({             center: [parseFloat(long),parseFloat(lat)],  // longitude & latitude of current location ( obtained in another function)             geodesic: true,             radius: parseFloat(innerCircleRadius),             // radius to search within ( it is global variable initialized early)            radiusUnit: "kilometers"             });           var outerCircleSymb = new SimpleFillSymbol(SimpleFillSymbol.STYLE_NULL,             new SimpleLineSymbol(             SimpleLineSymbol.STYLE_SHORTDASHDOTDOT,             new Color([1, 1, 1, .4]),2), new Color([255, 255, 0, 0.15]));           var innerCircleSymb = new SimpleFillSymbol(SimpleFillSymbol.STYLE_NULL,             new SimpleLineSymbol(             SimpleLineSymbol.STYLE_SHORTDASHDOTDOT,             new Color([1, 1, 1, .4]),1), new Color([255, 100, 0, 0.15]));         outerCircleGraphic = new Graphic(outerCircle, outerCircleSymb);           innerCircleGraphic = new Graphic(innerCircle, innerCircleSymb);        view.graphics.addMany([outerCircleGraphic, innerCircleGraphic]);              view.center = [parseFloat(long),parseFloat(lat)];        view.zoom = 10       };          var lat = document.getElementById("myButton");      var long = document.getElementById("myButton");      lat.addEventListener("click", RespondClick);      function RespondClick() {        if(pointExists)        {          view.graphics.remove(pointGraphic);          view.graphics.remove(outerCircleGraphic);          view.graphics.remove(innerCircleGraphic);        }        lat = document.getElementById("lat").value;        long = document.getElementById("long").value;        outerCircleRadius = document.getElementById("outerRadius").value;        innerCircleRadius = document.getElementById("innerRadius").value;        makeAPoint();        pointExists = true;      }         /*************************          * End Create a point graphic          *************************/          });     </script>  </head>   <body>    <!--<img src="logo.png" alt="logo"> -->    <div id="viewDiv"></div>     <div id="menu" class="esri-widget">        <input id="lat" placeholder="Latitude">        <input id='long' placeholder="Longitude">        <input id='outerRadius' placeholder="Outer Radius in km">        <input id='innerRadius' placeholder="Inner radius in km">         <button id="myButton">Locate</button>         <p>Choose search parameters:</p>        <div>          <label for="pollutant">Pollutant</label>          <select id="pollutant">            <option value="null">select</option>            <option value="SO2">SO2</option>            <option value="NOX">NOX</option>            <option value="CO">CO</option>            <option value="PT">PT</option>            <option value="PM2.5">PM2.5</option>            <option value="PM10">PM10</option>            <option value="VOC">VOC</option>                <option value="As">As</option>                      <option value="Benzene">Benzene</option>            <option value="CO2">CO2</option>            <option value="H2SO4">H2SO4</option>            <option value="NO2">NO2</option>                <option value="Pb">Pb</option>               <option value="VinylChloride">Vinyl Chloride</option>          </select>        </div>    </div>    </body></html>
0 Kudos
1 Solution

Accepted Solutions
ReneRubalcava
Frequent Contributor

This demo will do most of the workflow you are looking for.

  1. Create buffer based on a clicked location
  2. Query CSV using buffer as geometry to intersect
  3. Highlight results of CSV query
  4. Place results into temporary variable
  5. Button to perform a naive export of features to CSV

https://codepen.io/odoe/pen/wvvOJWb?editors=0010 

The key here is to remember that the LayerView highlight API works off the object ids of features in the Layer View. So you can query for the object ids, pass them to the highlight API to get highlights of your data.

This should give you a good start.

View solution in original post

2 Replies
ReneRubalcava
Frequent Contributor

This demo will do most of the workflow you are looking for.

  1. Create buffer based on a clicked location
  2. Query CSV using buffer as geometry to intersect
  3. Highlight results of CSV query
  4. Place results into temporary variable
  5. Button to perform a naive export of features to CSV

https://codepen.io/odoe/pen/wvvOJWb?editors=0010 

The key here is to remember that the LayerView highlight API works off the object ids of features in the Layer View. So you can query for the object ids, pass them to the highlight API to get highlights of your data.

This should give you a good start.

NathanRice
New Contributor II

Thank you so much! This helped tremendously. 

0 Kudos