Hello,
I'm trying to draw a polygon and get its perimeter and area. Once I'm using spatialReference 2039, the geometryEngine.geodesicLength and geometryEngine.geodesicArea methods fail with this error:
Uncaught Error: Not Implemented
at Object.d.df (VM1280 geometryEngine.js:535)
at Function.b.kc (VM1280 geometryEngine.js:1171)
at b.V (VM1280 geometryEngine.js:773)
at Function.g.PS (VM1280 geometryEngine.js:608)
at Function.d.geodesicLength (VM1280 geometryEngine.js:1275)
at createGraphic (index.html?sample=draw-line:92)
at Object.updateVertices (index.html?sample=draw-line:61)
at Object.r [as onvertex-add] (VM1269 dojo.js:60)
at Function.h.emit (VM1269 dojo.js:55)
at Function.h.emit (VM1269 dojo.js:56)
My code is based on this sample: ArcGIS API for JavaScript Sandbox and can be tested here: Draw polyline - 4.9 . The error appears once drawing begins. Following is my code.
Can you help me out?
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>Draw polyline - 4.9</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.8/esri/css/main.css">
<script src="https://js.arcgis.com/4.8/"></script>
<style>
html,
body,
#viewDiv {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
</style>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/views/2d/draw/Draw",
"esri/Graphic",
"esri/geometry/Polygon",
"esri/geometry/geometryEngine",
"esri/geometry/SpatialReference",
"esri/geometry/Extent",
"esri/layers/TileLayer"
], function(
Map, MapView, Draw, Graphic, Polygon, geometryEngine, SpatialReference, Extent, TileLayer
) {
const map = new Map({
basemap: "satellite"
});
const view = new MapView({
container: "viewDiv",
map: map,
spatialReference: new SpatialReference({wkid: 2039})
});
view.extent = new Extent({
xmin: 169209,
ymin: 659425,
xmax: 192454,
ymax: 672847,
spatialReference: {wkid: 2039}
});
map.layers.add(new TileLayer({ url: "http://gisn.tel-aviv.gov.il/arcgis/rest/services/IView2Ortho2017/MapServer" }));
// add the button for the draw tool
view.ui.add("line-button", "top-left");
const draw = new Draw({
view: view
});
// draw polyline button
document.getElementById("line-button").onclick = function() {
view.graphics.removeAll();
// creates and returns an instance of PolyLineDrawAction
const action = draw.create("polyline");
// focus the view to activate keyboard shortcuts for sketching
view.focus();
// listen polylineDrawAction events to give immediate visual feedback
// to users as the line is being drawn on the view.
action.on(["vertex-add", "vertex-remove", "cursor-update", "redo",
"undo", "draw-complete"
], updateVertices);
}
// Checks if the last vertex is making the line intersect itself.
function updateVertices(event) {
// create a polyline from returned vertices
const result = createGraphic(event);
// if the last vertex is making the line intersects itself,
// prevent the events from firing
if (result.selfIntersects) {
event.preventDefault();
}
}
// create a new graphic presenting the polyline that is being drawn on the view
function createGraphic(event) {
const vertices = event.vertices;
view.graphics.removeAll();
//var polygon = createPolygon(vertices);
// a graphic representing the polyline that is being drawn
const graphic = new Graphic({
geometry: {
type: "polyline",
paths: vertices,
spatialReference: view.spatialReference
},
symbol: {
type: "simple-line", // autocasts as new SimpleFillSymbol
color: [4, 90, 141],
width: 4,
cap: "round",
join: "round"
}
});
// check if the polyline intersects itself.
const intersectingSegment = getIntersectingSegment(graphic.geometry);
// Add a new graphic for the intersecting segment.
if (intersectingSegment) {
view.graphics.addMany([graphic, intersectingSegment]);
}
// Just add the graphic representing the polyline if no intersection
else {
view.graphics.add(graphic);
}
var area = geometryEngine.geodesicLength(graphic.geometry, "meters");
console.log(area);
// return intersectingSegment
return {
selfIntersects: intersectingSegment
}
}
function createPolygon(vertices) {
return new Polygon({
rings: vertices,
spatialReference: view.spatialReference
});
}
// function that checks if the line intersects itself
function isSelfIntersecting(polyline) {
if (polyline.paths[0].length < 3) {
return false
}
const line = polyline.clone();
//get the last segment from the polyline that is being drawn
const lastSegment = getLastSegment(polyline);
line.removePoint(0, line.paths[0].length - 1);
// returns true if the line intersects itself, false otherwise
return geometryEngine.crosses(lastSegment, line);
}
// Checks if the line intersects itself. If yes, change the last
// segment's symbol giving a visual feedback to the user.
function getIntersectingSegment(polyline) {
if (isSelfIntersecting(polyline)) {
return new Graphic({
geometry: getLastSegment(polyline),
symbol: {
type: "simple-line", // autocasts as new SimpleLineSymbol
style: "short-dot",
width: 3.5,
color: "yellow"
}
});
}
return null;
}
// Get the last segment of the polyline that is being drawn
function getLastSegment(polyline) {
const line = polyline.clone();
const lastXYPoint = line.removePoint(0, line.paths[0].length - 1);
const existingLineFinalPoint = line.getPoint(0, line.paths[0].length -
1);
return {
type: "polyline",
spatialReference: view.spatialReference,
hasZ: false,
paths: [
[
[existingLineFinalPoint.x, existingLineFinalPoint.y],
[lastXYPoint.x, lastXYPoint.y]
]
]
};
}
});
</script>
</head>
<body>
<div id="viewDiv">
<div id="line-button" class="esri-widget esri-widget--button esri-interactive"
title="Draw polyline">
<span class="esri-icon-polyline"></span>
</div>
</div>
</body>
</html>
As mentioned in the help, the geometryEngine.geodesicLength() method works with 4326 and Web Mercator spatial references, and it suggests you should use geometryEngine.planarLength() instead.
thank you