I see there is no 2d direct line measurement for 4.7. I use 2d mapview also I want a 2d direct line measurement. In api reference, it says dlm can be made by using geometryengine and draw classes. I used non-intersecting draw line. Now I want to integrate with geometryengine to measure distance but I don't know how.
Also, draw non-intersecting line not work correctly right now even in the sample. I have to double click to draw but it was working correctly before.
Using codes:
view.when(function (evt) {
var draw = new Draw({
view: view
});
// ********************
// draw polyline button
// ********************
var drawLineButton = document.getElementById("meabut");
drawLineButton.onclick = function () {
view.graphics.removeAll();
enableCreateLine(draw, view);
}
});
function enableCreateLine(draw, view) {
// creates and returns an instance of PolyLineDrawAction
// can only draw a line by clicking on the map
var action = draw.create("polyline", {
mode: "click"
});
// focus the view to activate keyboard shortcuts for sketching
view.focus();
// listen to vertex-add event on the polyline draw action
action.on("vertex-add", updateVertices);
// listen to vertex-remove event on the polyline draw action
action.on("vertex-remove", updateVertices);
// listen to cursor-update event on the polyline draw action
action.on("cursor-update", createGraphic);
// listen to draw-complete event on the polyline draw action
action.on("draw-complete", updateVertices);
}
// This function is called from the "vertex-add" and "vertex-remove" events.
// Checks if the last vertex is making the line intersect itself.
function updateVertices(evt) {
// create a polyline from returned vertices
var result = createGraphic(evt);
// if the last vertex is making the line intersects itself,
// prevent "vertex-add" or "vertex-remove" from firing
if (result.selfIntersects) {
evt.preventDefault();
}
}
// create a new graphic presenting the polyline that is being drawn on the view
function createGraphic(evt) {
var vertices = evt.vertices;
view.graphics.removeAll();
// a graphic representing the polyline that is being drawn
var graphicc = new Graphic({
geometry: new 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 the polyline intersects itself.
var intersectingFeature = getIntersectingFeature(graphicc.geometry);
// Add a new graphic for the intersecting segment.
if (intersectingFeature) {
view.graphics.addMany([graphic, intersectingFeature]);
}
// Just add the graphic representing the polyline if no intersection
else {
view.graphics.add(graphicc);
}
// return the graphic and intersectingSegment
return {
graphic: graphicc,
selfIntersects: intersectingFeature
}
}
// function that checks if the line intersects itself
function isSelfIntersecting(polyline) {
if (polyline.paths[0].length < 3) {
return false
}
var line = polyline.clone();
//get the last segment from the polyline that is being drawn
var 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, changes the last
// segment's symbol giving a visual feedback to the user.
function getIntersectingFeature(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) {
var line = polyline.clone();
var lastXYPoint = line.removePoint(0, line.paths[0].length - 1);
var existingLineFinalPoint = line.getPoint(0, line.paths[0].length -
1);
return new Polyline({
spatialReference: view.spatialReference,
hasZ: false,
paths: [
[
[existingLineFinalPoint.x, existingLineFinalPoint.y],
[lastXYPoint.x, lastXYPoint.y]
]
]
});
}
Solved! Go to Solution.
Kutay,
Here are the changes to make your code work:
...
// check the polyline intersects itself.
var intersectingFeature = getIntersectingFeature(graphicc.geometry);
var lengthh = geometryEngine.planarLength(graphicc.geometry, "kilometers");
labelAreas(graphicc, lengthh);
console.log(lengthh, "km");
...
function labelAreas(geom, area) {
var graph = new Graphic({
geometry: geom.geometry.extent.center,
symbol: {
type: "text",
color: "black",
haloColor: "black",
haloSize: "1px",
text: area.toFixed(2) + " km",
xoffset: 3,
yoffset: 3,
font: { // autocast as Font
size: 14,
family: "sans-serif"
}
}
});
view.graphics.add(graph);
// console.log(area);
console.log(geom);
}
...
Kutay,
You just use the geodesicLength or planarLength methods in the geometryEngibe class.
Thanks. I want to text on top of drawing like in these example.
Measure while drawing | ArcGIS API for JavaScript 4.7
I did the source code like this but I couldn't show distance as text on the line vertice.
view.when(function (evt) {
var draw = new Draw({
view: view
});
// ********************
// draw polyline button
// ********************
var drawLineButton = document.getElementById("meabut");
drawLineButton.onclick = function () {
view.graphics.removeAll();
enableCreateLine(draw, view);
}
});
function enableCreateLine(draw, view) {
// creates and returns an instance of PolyLineDrawAction
// can only draw a line by clicking on the map
var action = draw.create("polyline", {
mode: "click"
});
// focus the view to activate keyboard shortcuts for sketching
view.focus();
// listen to vertex-add event on the polyline draw action
action.on("vertex-add", updateVertices);
// listen to vertex-remove event on the polyline draw action
action.on("vertex-remove", updateVertices);
// listen to cursor-update event on the polyline draw action
action.on("cursor-update", createGraphic);
// listen to draw-complete event on the polyline draw action
action.on("draw-complete", updateVertices);
}
// This function is called from the "vertex-add" and "vertex-remove" events.
// Checks if the last vertex is making the line intersect itself.
function updateVertices(evt) {
// create a polyline from returned vertices
var result = createGraphic(evt);
// if the last vertex is making the line intersects itself,
// prevent "vertex-add" or "vertex-remove" from firing
if (result.selfIntersects) {
evt.preventDefault();
}
}
// create a new graphic presenting the polyline that is being drawn on the view
function createGraphic(evt) {
var vertices = evt.vertices;
view.graphics.removeAll();
// a graphic representing the polyline that is being drawn
var graphicc = new Graphic({
geometry: new 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 the polyline intersects itself.
var intersectingFeature = getIntersectingFeature(graphicc.geometry);
var lengthh = geometryEngine.planarLength(graphicc.geometry, "kilometers");
labelAreas(graphicc, length);
console.log(lengthh, "km");
// Add a new graphic for the intersecting segment.
if (intersectingFeature) {
view.graphics.addMany([graphicc, intersectingFeature]);
}
// Just add the graphic representing the polyline if no intersection
else {
view.graphics.add(graphicc);
}
// return the graphic and intersectingSegment
return {
graphic: graphicc,
selfIntersects: intersectingFeature
}
function labelAreas(geom, area) {
var graph = new Graphic({
geometry: geom.geometry,
symbol: {
type: "text",
color: "black",
haloColor: "black",
haloSize: "1px",
text: area.toFixed(2) + " km",
xoffset: 3,
yoffset: 3,
font: { // autocast as Font
size: 14,
family: "sans-serif"
}
}
});
view.graphics.add(graphicc);
// console.log(area);
console.log(geom);
}
}
Kutay,
Please provide a full sample for testing.
Here is my full code
Kutay,
Here are the changes to make your code work:
...
// check the polyline intersects itself.
var intersectingFeature = getIntersectingFeature(graphicc.geometry);
var lengthh = geometryEngine.planarLength(graphicc.geometry, "kilometers");
labelAreas(graphicc, lengthh);
console.log(lengthh, "km");
...
function labelAreas(geom, area) {
var graph = new Graphic({
geometry: geom.geometry.extent.center,
symbol: {
type: "text",
color: "black",
haloColor: "black",
haloSize: "1px",
text: area.toFixed(2) + " km",
xoffset: 3,
yoffset: 3,
font: { // autocast as Font
size: 14,
family: "sans-serif"
}
}
});
view.graphics.add(graph);
// console.log(area);
console.log(geom);
}
...
Don't forget to mark this question as answered by clicking on the "Mark Correct" link on the reply that answered your question.