Buffer not accurate

3129
27
12-20-2016 01:16 PM
by Anonymous User
Not applicable

Hi all,

I am trying to buffer a road segment 200' on each side but it seems like the buffer is not returning me anything accurate. The buffer on each side is like 520' as it is now. Maybe wkid?

var extent2 = new Extent({
                    "xmin": -121.11087086999999, "ymin": 38.517479534000074, "xmax": -119.95226375799996, "ymax": 39.068026806000034,
                    "spatialReference": { "wkid": 4326 }
                });

                //Map
                map = new Map("map", {
                    basemap: "topo",
                    extent: extent2
                });


featureLayer.selectFeatures(selectQuery, FeatureLayer.SELECTION_NEW, function (targetGeometry) {
                            targetGeometry = graphicsUtils.getGeometries(featureLayer.getSelectedFeatures());
                            console.log(targetGeometry);
                            geometryService.union(targetGeometry, function (geometry) {
                                featureLayer.clearSelection();
                                //Buffer params
                                var params = new BufferParameters();
                                params.distances = [200];
                                params.unit = geometryService.UNIT_FOOT;
                                //Simplify features first
                                geometryService.simplify([geometry], function (simplifiedGeometries) {
                                    params.geometries = simplifiedGeometries;
                                    //do the buffer
                                    geometryService.buffer(params, showBuffer);
                                });
                            }, function (err) {
                                console.log(err);
                            });
                        });‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
27 Replies
by Anonymous User
Not applicable

I noticed that a similar issue exists on that ESRI sample. I wonder why.

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
<title>Buffer</title>

<link rel="stylesheet" href="https://js.arcgis.com/3.18/dijit/themes/claro/claro.css">
<link rel="stylesheet" href="https://js.arcgis.com/3.18/esri/css/esri.css">
<style>
   html, body {
    height: 100%;
    width: 100%;
    margin: 0; 
    padding: 0;
    overflow:hidden;
  }
  #leftPane{
    color:#000;
    width:250px;
    padding-bottom:15px;
  }
  #map{
    padding:0;
  }
  .details{
    font-size:14px;
    font-weight:600;
    padding-bottom:20px;
  }

  button{
    margin:2px;
    cursor:pointer;
  }
</style>

<script src="https://js.arcgis.com/3.18/"></script>
<script>
var map, tb;

require(["dojo/dom",

        "dojo/_base/array",
        "dojo/parser",
        "dojo/query",
        "dojo/on",

        "esri/Color",
        "esri/config",
        "esri/map",
        "esri/graphic",
        "esri/dijit/Measurement",
        "esri/geometry/normalizeUtils",
        "esri/tasks/GeometryService",
        "esri/tasks/BufferParameters",
  
        "esri/toolbars/draw",
  
        "esri/symbols/SimpleMarkerSymbol",
        "esri/symbols/SimpleLineSymbol",
        "esri/symbols/SimpleFillSymbol",
        
        "dijit/layout/BorderContainer",
        "dijit/layout/ContentPane",
        "dijit/form/Button", "dojo/domReady!"
        ],
      function(dom, array, parser, query, on, Color, esriConfig, Map, Graphic, Measurement, normalizeUtils, GeometryService, BufferParameters, Draw, SimpleMarkerSymbol, SimpleLineSymbol, SimpleFillSymbol){

        parser.parse();


        esriConfig.defaults.geometryService = new GeometryService("https://utility.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer");

        esriConfig.defaults.io.proxyUrl = "/proxy/";
        esriConfig.defaults.io.alwaysUseProxy = false;


       //Setup button click handlers
        on(dom.byId("clearGraphics"), "click", function(){
          if(map){
            map.graphics.clear();
          }
        });
        //click handler for the draw tool buttons
        query(".tool").on("click", function(evt){
          if(tb){
           tb.activate(evt.target.id);
          }
        });

        map = new Map("map", {
          basemap: "streets",
          center: [-111.5, 39.541],
          zoom: 7
        });
        
        var measurement = new Measurement({
          map: map
        }, dom.byId("measurementDiv"));
        measurement.startup();
        map.on("load", initToolbar);



      function initToolbar(evtObj) {
        tb = new Draw(evtObj.map);
        tb.on("draw-end", doBuffer);
      }

      function doBuffer(evtObj) {
        tb.deactivate();
        var geometry = evtObj.geometry, symbol;
        switch (geometry.type) {
           case "point":
             symbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_SQUARE, 10, new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([255,0,0]), 1), new Color([0,255,0,0.25]));
             break;
           case "polyline":
             symbol = new SimpleLineSymbol(SimpleLineSymbol.STYLE_DASH, new Color([255,0,0]), 1);
             break;
           case "polygon":
             symbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_NONE, new SimpleLineSymbol(SimpleLineSymbol.STYLE_DASHDOT, new Color([255,0,0]), 2), new Color([255,255,0,0.25]));
             break;
        }

          var graphic = new Graphic(geometry, symbol);
          map.graphics.add(graphic);

          //setup the buffer parameters
          var params = new BufferParameters();
          params.distances = [ dom.byId("distance").value ];
          params.outSpatialReference = map.spatialReference;
          params.unit = GeometryService[dom.byId("unit").value];
          //normalize the geometry 

          normalizeUtils.normalizeCentralMeridian([geometry]).then(function(normalizedGeometries){
            var normalizedGeometry = normalizedGeometries[0];
            if (normalizedGeometry.type === "polygon") {
              //if geometry is a polygon then simplify polygon.  This will make the user drawn polygon topologically correct.
              esriConfig.defaults.geometryService.simplify([normalizedGeometry], function(geometries) {
                params.geometries = geometries;
                esriConfig.defaults.geometryService.buffer(params, showBuffer);
              });
            } else {
              params.geometries = [normalizedGeometry];
              esriConfig.defaults.geometryService.buffer(params, showBuffer);
            }

          });
        }

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

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

        }
  });
</script>

</head>

<body class="claro">
<div data-dojo-type="dijit/layout/BorderContainer" 
     data-dojo-props="gutters:'true', design:'sidebar'" 
     style="width:100%;height:100%;">

  <div id="map" 
       data-dojo-type="dijit/layout/ContentPane" 
       data-dojo-props="region:'center'">
  </div>

  <div id="leftPane" 
       data-dojo-type="dijit/layout/ContentPane" 
       data-dojo-props="region:'left'">
    <div class="details">Pick a tool and draw on the map. The drawn graphic will be buffered based on the specified parameters.</div>
    <button type="button" class="tool" id="line">Line</button>
    <button type="button" class="tool" id="polyline">Polyline</button>
    <button type="button" class="tool" id="freehandpolyline">Freehand Polyline</button>
    <br/>
    <button type="button" class="tool" id="polygon">Polygon</button>
    <button type="button" class="tool" id="freehandpolygon">Freehand Polygon</button>
    <br/><hr />
    <div><b>Buffer Parameters</b></div>
    Distance:&nbsp;<input type="text" id="distance" size="5" value="25" />
    <select id="unit" style="width:100px;">
      <option value="UNIT_STATUTE_MILE">Miles</option>
      <option value="UNIT_FOOT">Feet</option>
      <option value="UNIT_KILOMETER">Kilometers</option>
      <option value="UNIT_METER">Meters</option>
      <option value="UNIT_NAUTICAL_MILE">Nautical Miles</option>
      <option value="UNIT_US_NAUTICAL_MILE">US Nautical Miles</option>
      <option value="UNIT_DEGREE">Degrees</option>
    </select><br />
    <button type="button" id="clearGraphics">Clear Graphics</button>
    <div id="measurementDiv"></div>
  </div>
</div>
</body>
</html>
0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Alex,

  Just add:

params.geodesic = true;

by Anonymous User
Not applicable

That works great with the ESRI sample ! Not too sure why it is not in my

app...

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Alex,

   Are you using an esri basemap?

0 Kudos
by Anonymous User
Not applicable

Yes. 

//Map
                map = new Map("map", {
                    basemap: "topo"
                });

And the layer I am buffering is wkid 102100  (3857) (WGS84)

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Alex,

   In your code you seem to be missing:

params.outSpatialReference = map.spatialReference;
0 Kudos
by Anonymous User
Not applicable

Still not accurate. strange.

featureLayer.selectFeatures(selectQuery, FeatureLayer.SELECTION_NEW, function (targetGeometry) {
                            targetGeometry = graphicsUtils.getGeometries(featureLayer.getSelectedFeatures());
                            console.log(targetGeometry);
                            geometryService.union(targetGeometry, function (geometry) {
                                featureLayer.clearSelection();
                                //Buffer params
                                var params = new BufferParameters();
                                params.distances = [200];
                                params.unit = geometryService.UNIT_FOOT;
                                params.outSpatialReference = map.spatialReference;
                                params.geodesic = true;

                                geometryService.simplify([geometry], function (simplifiedGeometries) {
                                    params.geometries = simplifiedGeometries;
                                    //do the buffer
                                    geometryService.buffer(params, showBuffer);
                                });
                            }, function (err) {
                                console.log(err);
                            });
                        });
0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Alex,

   The way I have found in my code to keep buffers accurate is to also use:

params.bufferSpatialReference = new SpatialReference({wkid:102003});

0 Kudos
by Anonymous User
Not applicable

No luck. I am wondering if the union messes up the buffer

On Tue, Dec 20, 2016 at 2:28 PM, Robert Scheitlin, GISP <geonet@esri.com>

0 Kudos