Does anyone know the simplest way to return the closest point on a polyline to an input point using the javascript api with/without a geometry service? Perhaps I need to publish my own geoprocessing service to best achieve this functionality? Any pointers would be useful...thanks
Please take a look at the document of SnappingManager. The method getSnappingPoint() returns a deferred object, which contains the closest point from a input location.
Hope this helps.
function pipeQueryCallback(pipeFeatureset){ if (pipeFeatureset.features.length > 0) { var pipeGeoms = []; var snappingManager = new esri.SnappingManager({alwaysSnap:true, layerInfos:[{layer:graphicsLayer}],map:map,tolerance:1000}); dojo.forEach(pipeFeatureset.features,function(pipeFeature){pipeGeoms.push(pipeFeature.geometry)}); geomServ.intersect(pipeGeoms,bufferGeom,function(intPipeGeoms){ dojo.forEach(intPipeGeoms,function(intPipeGeom){ graphicsLayer.clear(); graphicsLayer.add(new esri.Graphic(intPipeGeom,symPipeDist)); var deferred = snappingManager.getSnappingPoint(loc); deferred.then(function(value){ if(value !== undefined){ map.graphics.add(value,new esri.symbol.SimpleMarkerSymbol()); } },function(error){alert(error.message)}); }); }); } }
I had the same error with SnappingManager. Could it be that SnappingManager supports only WGS and Web Mercator spatial references? Couldn't find any information about such restriction, but the same code with other spatial references does not work
<script type="text/javascript"> dojo.require("esri.map"); dojo.require("esri.layers.FeatureLayer"); dojo.require("esri.SnappingManager"); dojo.require("esri.toolbars.draw"); var map, snap, featureLayer; function init() { var extent = new esri.geometry.Extent({"xmin":-96.6063,"ymin":38.3106,"xmax":-96.4764, "ymax":38.3689,"spatialReference":{"wkid":4269}}); map = new esri.Map("map", { extent: esri.geometry.geographicToWebMercator(extent)}); var imagery = new esri.layers.ArcGISTiledMapServiceLayer("http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer"); map.addLayer(imagery); featureLayer = new esri.layers.FeatureLayer("http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Hydrography/Watershed173811/FeatureServer/1",{ mode: esri.layers.FeatureLayer.MODE_ONDEMAND }); map.addLayer(featureLayer); dojo.connect(map, "onLoad", initSnapping); } function initSnapping(themap) { var map = themap; snap = new esri.SnappingManager({layerInfos:[{layer:featureLayer, snapToPoint: true, snapToEdge:false}], map: map, tolerence: 500}); toolbar = new esri.toolbars.Draw(map); dojo.connect(toolbar, "onDrawEnd", addToMap); } function addToMap(geometry) { toolbar.deactivate(); map.showZoomSlider(); var sPt = map.toScreen(geometry); var defer = snap.getSnappingPoint(sPt); defer.addCallback(function(result){ if(result){ var snapPoint = result; console.log(snapPoint); } }); var symbol = new esri.symbol.SimpleMarkerSymbol(esri.symbol.SimpleMarkerSymbol.STYLE_SQUARE, 10, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, new dojo.Color([255, 0, 0]), 1), new dojo.Color([0, 255, 0, 0.25])); var graphic = new esri.Graphic(geometry, symbol); map.graphics.add(graphic); } dojo.addOnLoad(init); </script> </head> <body class="tundra"> <button dojoType="dijit.form.Button" onClick="toolbar.activate(esri.toolbars.Draw.POINT);map.hideZoomSlider();"> Point </button> </div> <div id="map" style="width:900px;height:500px;"> </div> </body>
SnappingManager works with any coordinate systems. Please try the code below. Hope this helps.<script type="text/javascript"> dojo.require("esri.map"); dojo.require("esri.layers.FeatureLayer"); dojo.require("esri.SnappingManager"); dojo.require("esri.toolbars.draw"); var map, snap, featureLayer; function init() { var extent = new esri.geometry.Extent({"xmin":-96.6063,"ymin":38.3106,"xmax":-96.4764, "ymax":38.3689,"spatialReference":{"wkid":4269}}); map = new esri.Map("map", { extent: esri.geometry.geographicToWebMercator(extent)}); var imagery = new esri.layers.ArcGISTiledMapServiceLayer("http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer"); map.addLayer(imagery); featureLayer = new esri.layers.FeatureLayer("http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Hydrography/Watershed173811/FeatureServer/1",{ mode: esri.layers.FeatureLayer.MODE_ONDEMAND }); map.addLayer(featureLayer); dojo.connect(map, "onLoad", initSnapping); } function initSnapping(themap) { var map = themap; snap = new esri.SnappingManager({layerInfos:[{layer:featureLayer, snapToPoint: true, snapToEdge:false}], map: map, tolerence: 500}); toolbar = new esri.toolbars.Draw(map); dojo.connect(toolbar, "onDrawEnd", addToMap); } function addToMap(geometry) { toolbar.deactivate(); map.showZoomSlider(); var sPt = map.toScreen(geometry); var defer = snap.getSnappingPoint(sPt); defer.addCallback(function(result){ if(result){ var snapPoint = result; console.log(snapPoint); } }); var symbol = new esri.symbol.SimpleMarkerSymbol(esri.symbol.SimpleMarkerSymbol.STYLE_SQUARE, 10, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, new dojo.Color([255, 0, 0]), 1), new dojo.Color([0, 255, 0, 0.25])); var graphic = new esri.Graphic(geometry, symbol); map.graphics.add(graphic); } dojo.addOnLoad(init); </script> </head> <body class="tundra"> <button dojoType="dijit.form.Button" onClick="toolbar.activate(esri.toolbars.Draw.POINT);map.hideZoomSlider();"> Point </button> </div> <div id="map" style="width:900px;height:500px;"> </div> </body>