Skip to content

Instantly share code, notes, and snippets.

@raykendo
Created February 1, 2016 16:29
Show Gist options
  • Save raykendo/f174b3c95c5d581f73e6 to your computer and use it in GitHub Desktop.
Save raykendo/f174b3c95c5d581f73e6 to your computer and use it in GitHub Desktop.
Finding a point within a geometry for ArcGIS JavaScript API using client-side processing
define([
"dojo/_base/array",
"esri/geometry/Polygon",
"esri/geometry/Polyline",
"esri/geometry/Point",
"esri/geometry/geometryEngine"
], function (arrayUtils, Polygon, Polyline, Point, geometryEngine) {
/**
* Finds a point on a polyline
* @function pointFromLine
* @param {"esri/geometry/Polyline"} polyline - the polyline to get points from
* @param {"esri/geometry/Polygon"} [testPolygon] - if a polygon is used to determine clickability, return
* @returns {"esri/geometry/Point"} a point that should be contained in the polyline, and polygon (if provided);
*/
function pointFromLine(polyline, testPolygon) {
var resultPoint = null;
arrayUtils.some(polyline.paths, function (path) {
var numSegments = path.length - 1,
segmentPointer, segmentEnd, avgPointCoords;
for (segmentPointer = 0; segmentPointer < numSegments; segmentPointer++) {
segmentEnd = path[segmentPointer + 1];
avgPointCoords = arrayUtils.map(path[segmentPointer], function (coord, index) {
return (coord + segmentEnd[index]) / 2;
});
if (!testPolygon || testPolygon.contains(new Point(avgPointCoords).setSpatialReference(polyline.spatialReference))) {
resultPoint = new Point(avgPointCoords).setSpatialReference(polyline.spatialReference);
break;
}
}
return !!resultPoint;
});
return resultPoint;
}
/**
* finds a point contained within a polygon
* @function pointFromPolygon
* @param {"esri/geometry/Polygon"} polygon
* @returns {"esri/geometry/Point"} - a point that should be contained in the polygon
*/
function pointFromPolygon(polygon) {
var intersects, resultLine;
arrayUtils.some(polygon.rings, function(ring) {
// make a polygon from the first ring and get its extent.
var polygonFromRing = new Polygon(ring).setSpatialReference(polygon.spatialReference),
extent = polygonFromRing.getExtent(),
yAvg, yAvgLine, xAvg, xAvgLine;
// draw a horizontal line that should go through the middle of the current ring
yAvg = (extent.ymin + extent.ymax) / 2;
yAvgLine = new Polyline([
[extent.xmin, yAvg],
[extent.xmax, yAvg]
]).setSpatialReference(polygon.spatialReference);
// test if the horizontal line intersects the whole polygon somehow.
intersects = geometryEngine.intersects(yAvgLine, polygon);
if (intersects) {
// if so, create the intersection line from that line
resultLine = geometryEngine.intersect(yAvgLine, polygon);
return intersects;
}
// draw a vertical line that should go through the middle of the current ring
xAvg = (extent.xmin + extent.xmax) / 2;
xAvgLine = new Polyline([
[xAvg, extent.ymin],
[xAvg, extent.ymax]
]).setSpatialReference(polygon.spatialReference);
// test if the vertical line interesects with the whole polygon
intersects = geometryEngine.intersects(xAvgLine, polygon);
if (intersects) {
// if intersects, create an intersecting line between the two shapes.
resultLine = geometryEngine.intersect(yAvgLine, polygon);
}
return intersects;
});
if (intersects) {
return pointFromLine(resultLine, polygon);
}
return null;
}
/**
* Finds a point that is certain to be contained within another geometry
* @function PointWithin
* @param {object} geometry - an ArcGIS JavaScript API Geometry
* See https://developers.arcgis.com/javascript/jsapi/geometry-amd.html
* @returns {object} and ArcGIS JavsScript API Point Geometry that should be within it.
*/
return function (geometry) {
if (!geometry.type) {
throw "Invalid geometry passed to the function";
return;
}
if (geometry.type === "point") {
return geometry;
}
if (geometry.type === "extent") {
return geometry.getCenter();
}
if (geometry.type === "multipoint") {
return geometry.getPoint(0);
}
if (geometry.type === "polyline") {
return pointFromLine(geometry);
}
if (geometry.type === "polygon") {
return pointFromPolygon(geometry);
}
throw "Unknown geometry type: " + geometry.type;
};
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment