Creating a minimum bounding polygon around different geometry types

1258
3
Jump to solution
07-11-2013 07:45 AM
JeffHobson
New Contributor
Hi all,

I have a layer with several geometries of varying types (currently just points and polygons, but lines/polylines may come in the future). I need to create a minimum bounding polygon around these geometries, preferrably with some way to expand or buffer it so there is some padding around the geometries. I've tried using GeometryService.convexHull, passing in an example list of geometries containing one point and one circle polygon, but this always returns an error.

Any ideas?

Thanks,
Jeff
0 Kudos
1 Solution

Accepted Solutions
DianaBenedict
Occasional Contributor III
Jeff

Below are a couple of functions that I use to get the geometry envelope. In my example if the geom is a point or multipoint with only one point in the array I utilize the buffer geometry task.  Note that you can simply use the zoomExtent as the geometry that you want to do whatever it is that you need. In my case I take the geometry.envelope and then expand it so that I can zoom to that feature. Also note that my example accepts an array of graphics. This array can have 1 or more graphics and I process them all the same. Finally, I have had minor issues with my buffer function since we changed spatial reference. Meaning that my map now uses webMercator but my data is in geographic.  At some point I will have to figure that out ,, but that is essentially why you see me setting so many different spatial ref and distance properties in the buffer function.

  zoomToGraphics: function (map, graphicsArray, expandFactor) {     var zoomExtent = esri.graphicsExtent(graphicsArray);     //If the extent height and width are 0, null is returned     if (!zoomExtent) {       var geomArray = esri.getGeometries(graphicsArray);       var deferred = this.bufferGeometry(geomArray, [50], graphicsArray[0].geometry.spatialReference, map.spatialReference);       deferred.then(function (results) {         zoomExtent = results[0].getExtent();         if (expandFactor) {           map.setExtent(zoomExtent.expand(expandFactor), false);         } else {           map.setExtent(zoomExtent, false);         }       }, function (error) {         alert("Error during buffer Geom: " + error.message);       });     } else {       if (expandFactor) {         map.setExtent(zoomExtent.expand(expandFactor), false);       } else {         map.setExtent(zoomExtent, false);       }     }   },    //require(["esri/tasks/GeometryService", ... ], function(GeometryService, ... ){ ... });   // dojo require dojo.deferred   //TODO: need to set up the spatial reference correctly ...   bufferGeometry: function (inGeometryArray, distanceArray, inSpatialRef, outSpatialRef) {     var geomService = esri.config.defaults.geometryService; //new esri.tasks.GeometryService(geomServiceURL);     var bufferParams = new esri.tasks.BufferParameters();     bufferParams.geometries = inGeometryArray;     bufferParams.bufferSpatialReference = inSpatialRef;     bufferParams.outSpatialReference = outSpatialRef;     bufferParams.distances = distanceArray; //units in feet     bufferParams.unit = esri.tasks.GeometryService.UNIT_METER;      var deferred = geomService.buffer(bufferParams);     return deferred;   }

View solution in original post

0 Kudos
3 Replies
JeffHobson
New Contributor
Apparently it won't work with points and polygons. My solution right now is to just use the polygons, but if anyone else comes across this, I would recommend performing two convexHull operations, one with the points and one with the polygons, and then a third to combine the two results.
0 Kudos
DianaBenedict
Occasional Contributor III
Jeff

Below are a couple of functions that I use to get the geometry envelope. In my example if the geom is a point or multipoint with only one point in the array I utilize the buffer geometry task.  Note that you can simply use the zoomExtent as the geometry that you want to do whatever it is that you need. In my case I take the geometry.envelope and then expand it so that I can zoom to that feature. Also note that my example accepts an array of graphics. This array can have 1 or more graphics and I process them all the same. Finally, I have had minor issues with my buffer function since we changed spatial reference. Meaning that my map now uses webMercator but my data is in geographic.  At some point I will have to figure that out ,, but that is essentially why you see me setting so many different spatial ref and distance properties in the buffer function.

  zoomToGraphics: function (map, graphicsArray, expandFactor) {     var zoomExtent = esri.graphicsExtent(graphicsArray);     //If the extent height and width are 0, null is returned     if (!zoomExtent) {       var geomArray = esri.getGeometries(graphicsArray);       var deferred = this.bufferGeometry(geomArray, [50], graphicsArray[0].geometry.spatialReference, map.spatialReference);       deferred.then(function (results) {         zoomExtent = results[0].getExtent();         if (expandFactor) {           map.setExtent(zoomExtent.expand(expandFactor), false);         } else {           map.setExtent(zoomExtent, false);         }       }, function (error) {         alert("Error during buffer Geom: " + error.message);       });     } else {       if (expandFactor) {         map.setExtent(zoomExtent.expand(expandFactor), false);       } else {         map.setExtent(zoomExtent, false);       }     }   },    //require(["esri/tasks/GeometryService", ... ], function(GeometryService, ... ){ ... });   // dojo require dojo.deferred   //TODO: need to set up the spatial reference correctly ...   bufferGeometry: function (inGeometryArray, distanceArray, inSpatialRef, outSpatialRef) {     var geomService = esri.config.defaults.geometryService; //new esri.tasks.GeometryService(geomServiceURL);     var bufferParams = new esri.tasks.BufferParameters();     bufferParams.geometries = inGeometryArray;     bufferParams.bufferSpatialReference = inSpatialRef;     bufferParams.outSpatialReference = outSpatialRef;     bufferParams.distances = distanceArray; //units in feet     bufferParams.unit = esri.tasks.GeometryService.UNIT_METER;      var deferred = geomService.buffer(bufferParams);     return deferred;   }
0 Kudos
JeffHobson
New Contributor
Thank you very much for the information! Right now I'm happy just having a convex hull to test with, but further down the road I will be needing a buffer, so I'll definitely be referencing your code.

Thanks again!
Jeff
0 Kudos