Update graphic location

1256
10
Jump to solution
04-03-2019 01:56 AM
KennethLindhardt1
Occasional Contributor

Hi, I need to update a graphic point, so that it always stays in front of the camera:

This is what I’m trying, but although the cameraX and cameraY are perfectly updating with the prober coordinates I can’t figure out how to clone the graphic with the new coordinates, so basically it needs to refresh the points XY with the new values, when I move the camera and then redraw the point. I’ve been searching for a long time for an answer, so I hope I can get some help

var cameraX;
watchUtils.whenTrue(view, "stationary", function() {
cameraX = view.camera.position.longitude ;
});
var cameraY;
watchUtils.whenTrue(view, "stationary", function() {
cameraY = view.camera.position.latitude + 0.05;
});
var point = {
type: "point", // autocasts as new Point()
x: cameraX,
y: cameraY,
0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Esteemed Contributor

Kenneth,

   OK, you are close but you need to add the point to the GL inside the stationary function as well.

var cameraX, cameraY, point, markerSymbol;
var graphicsLayer = new GraphicsLayer();
map.add(graphicsLayer);

markerSymbol = {
  type: "simple-marker", // autocasts as new SimpleMarkerSymbol()
  color: [226, 119, 40],
  size : 100,
  outline: { // autocasts as new SimpleLineSymbol()
    color: [255, 255, 255],
    width: 0.2
  }
};

watchUtils.whenTrue(view, "stationary", function() {
  graphicsLayer.removeAll();
  cameraX = view.camera.position.longitude;
  cameraY = view.camera.position.latitude + 0.20;
  point = {
    type: "point", // autocasts as new Point()
    x: cameraX,
    y: cameraY
  };
  graphicsLayer.add(new Graphic({
    geometry: point,
    symbol: markerSymbol,
  }));
});

View solution in original post

10 Replies
RobertScheitlin__GISP
MVP Esteemed Contributor

Kenneth,

   You are using watchUtils stationary to get the camera x and y (not sure why you have those separate...) but you create your point outside of those functions so the point will never get updated with the correct xy.

var cameraX, cameraY, point;
watchUtils.whenTrue(view, "stationary", function() {
  cameraX = view.camera.position.longitude;
  cameraY = view.camera.position.latitude + 0.05;
  point = {
    type: "point", // autocasts as new Point()
    x: cameraX,
    y: cameraY
  };
});
KennethLindhardt1
Occasional Contributor

Hi Robert thank you, sorry for the late reply on this. I can't seem to get this to work at all. 

I would expect, that I also would need to update the graphic layer when I move the camera, so tride different variations of the watchUtils. So I guess the graphic don’t re-read the new camera/cameraY

var cameraX, cameraY, point;
watchUtils.whenTrue(view, "stationary", function() {
cameraX = view.camera.position.longitude;
cameraY = view.camera.position.latitude + 0.20;
point = {
type: "point", // autocasts as new Point()
x: cameraX,
y: cameraY
};
});

markerSymbol = {
type: "simple-marker", // autocasts as new SimpleMarkerSymbol()
color: [226, 119, 40],
size : 100,
outline: { // autocasts as new SimpleLineSymbol()
color: [255, 255, 255],
//width:
}
};

var pointGraphic = new Graphic({
geometry: point,
symbol: markerSymbol,
});

var graphicsLayer = new GraphicsLayer();
map.add(graphicsLayer);


graphicsLayer.add(pointGraphic);
0 Kudos
RobertScheitlin__GISP
MVP Esteemed Contributor

Kenneth,

   OK, you are close but you need to add the point to the GL inside the stationary function as well.

var cameraX, cameraY, point, markerSymbol;
var graphicsLayer = new GraphicsLayer();
map.add(graphicsLayer);

markerSymbol = {
  type: "simple-marker", // autocasts as new SimpleMarkerSymbol()
  color: [226, 119, 40],
  size : 100,
  outline: { // autocasts as new SimpleLineSymbol()
    color: [255, 255, 255],
    width: 0.2
  }
};

watchUtils.whenTrue(view, "stationary", function() {
  graphicsLayer.removeAll();
  cameraX = view.camera.position.longitude;
  cameraY = view.camera.position.latitude + 0.20;
  point = {
    type: "point", // autocasts as new Point()
    x: cameraX,
    y: cameraY
  };
  graphicsLayer.add(new Graphic({
    geometry: point,
    symbol: markerSymbol,
  }));
});
KennethLindhardt1
Occasional Contributor

We wrote on almost the same time, I was even closer :)

Now I got it, awesome thank you Robert.

Really happy now :)

0 Kudos
KennethLindhardt1
Occasional Contributor

Well, I’m not getting that far in my script as I expected. Maybe I should start a new thread, but since we are on our way here, I’ll continue and pass the result to https://community.esri.com/thread/226394-show-camera-position-relative-to-ground

 

The idea was to take everything in small stages, learn something on the way, but I face issues, every time I try to move forward

So I’m trying to combine the Query Elevation (points) https://developers.arcgis.com/javascript/latest/sample-code/elevation-query-points/index.html with the graphic created on camera movement, so I’m trying to use queryElevation() and been trying in many different ways. Now I’m just getting dizzy.

 

So what I would need at the end, is to extract the z value from the graphic, the use  view.camera.position.z – the Graphic Z value, then I should have the camera elevation from ground, which will answer my show camera position relative to ground post.

In what I’m testing I’m using the ElevationLayer from the elevation query points. I can’t figure out if my issues are related to the graphic using   WGS84 (wkid: 4326) and the layer are using wkid: 3857, or if the graphic will reproject to the elevation layer.

 

Thanks.

0 Kudos
RobertScheitlin__GISP
MVP Esteemed Contributor

Kenneth,

  I would have to see the code.

0 Kudos
KennethLindhardt1
Occasional Contributor

Thank you. This is the almost clean version, where I haven’t any queryElevation() stuff in there:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>Add Graphics to a SceneView - 4.10</title>

<link rel="stylesheet" href="https://js.arcgis.com/4.10/esri/css/main.css">
<script src="https://js.arcgis.com/4.11/"></script>

<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}

#outputMessages {
position: absolute;
z-index: 70;
top: 0px;
right: 0;
bottom: 0;
box-sizing: border-box;
padding: 20px;
height: 100%;
width: 350px;
background: rgba(0, 0, 0, 0.7);
color: white;
font-size: 14px;
line-height: 30px;
overflow: auto;
}

#outputMessages span {
color: #f7be81;
font-weight: bold;
}
</style>

<script>
require([
"esri/Map",
"esri/views/SceneView",
"esri/Graphic",
"esri/geometry/Polyline",
"esri/layers/ElevationLayer",
"esri/core/promiseUtils",
"esri/core/watchUtils",
"esri/layers/GraphicsLayer",
], function(
Map,
SceneView,
Graphic,
Polyline,
ElevationLayer,
promiseUtils,watchUtils, GraphicsLayer
) {
// Create elevation layers
var beforeLandslideUrl =
"https://sampleserver6.arcgisonline.com/arcgis/rest/services/OsoLandslide/OsoLandslide_Before_3DTerrain/ImageServer/";

var beforeLandslideLayer = new ElevationLayer({
url: beforeLandslideUrl
});

// Create Map and View
var map = new Map({
basemap: "satellite",
ground: {
layers: [beforeLandslideLayer]
}
});

var view = new SceneView({
container: "viewDiv",
map: map,
camera: {
// initial view:
heading: 332.8,
tilt: 65.5,
position: {
x: -13563643,
y: 6153016,
z: 577,
spatialReference: {
wkid: 3857
}
},
heading: 0.34445102566290225,
tilt: 82.95536300536367
}
});
var outputMessages = document.getElementById("outputMessages");

var cameraX, cameraY, point, markerSymbol;
var graphicsLayer = new GraphicsLayer();
map.add(graphicsLayer);

markerSymbol = {
type: "simple-marker", // autocasts as new SimpleMarkerSymbol()
color: [226, 119, 40],
size : 100,
outline: { // autocasts as new SimpleLineSymbol()
color: [255, 255, 255],
width: 0.2
}
};

watchUtils.whenTrue(view, "stationary", function() {
graphicsLayer.removeAll();
cameraX = view.camera.position.longitude;
cameraY = view.camera.position.latitude + 0.20;
point = {
type: "point", // autocasts as new Point()
x: cameraX,
y: cameraY
};
graphicsLayer.add(new Graphic({
geometry: point,
symbol: markerSymbol,
}));
});

watchUtils.whenTrue(view, "stationary", function() {
// Get the new center of the view only when view is stationary.
var info = "<br> <span> the view center changed. </span> x: " +
cameraX + " y: " +
cameraY + " Z: " +
" Camera Z " + view.camera.position.z
displayMessage(info);

});
function displayMessage(info) {
outputMessages.innerHTML += info;
outputMessages.scrollTop = outputMessages.scrollHeight;
}

});
</script>
</head>

<body>
<div id="viewDiv">
<div id="outputMessages"></div>
<div id="titleDiv"></div>

</div>
</body>

</html>

I’m trying to get this implemented, in some way, but yea, it fails:

var cameraX, cameraY, DefindePoint, markerSymbol;
var graphicsLayer = new GraphicsLayer();
map.add(graphicsLayer);

markerSymbol = {
type: "simple-marker", // autocasts as new SimpleMarkerSymbol()
color: [226, 119, 40],
size : 10,
outline: { // autocasts as new SimpleLineSymbol()
color: [255, 255, 255],
width: 0.2
}
};

watchUtils.whenTrue(view, "stationary", function(event) {

// var position = event;
// var queryBeforeLandslide = beforeLandslideLayer.queryElevation(
// position
// );


graphicsLayer.removeAll();
cameraX = view.camera.position.longitude;
cameraY = view.camera.position.latitude + 0.02;
DefindePoint = {
// type: "point", // autocasts as new Point()
x: cameraX,
y: cameraY,
// mode: "on-the-ground",
};
beforeLandslideLayer.queryElevation(new Point(DefindePoint))

.then(function(result) {
// Print result of each sampled point to the console
result.geometry.DefindePoint.forEach(function(point, index) {
var elevation = Math.round(point[2]);
var resolution = result.sampleInfo[index].demResolution;

var coordinateText = "(" + point[0] + ", " + point[1] + ")";
var resolutionText = Math.round(resolution) + " meter resolution";

console.log("Sampled " + coordinateText + ": " + elevation + " at " + resolutionText);
});
})

// Failed to sample (e.g. service unavailable)
.catch(function(error) {
console.error("Failed to query elevation:", error);
});


graphicsLayer.add(new Graphic({
geometry: DefindePoint,
symbol: markerSymbol,

}));

});

watchUtils.whenTrue(view, "stationary", function() {
// Get the new center of the view only when view is stationary.
var info = "<br> <span> the view center changed. </span> x: " +
cameraX + " y: " + " Ponit = " + + " " +
cameraY + " Z: " +
" Camera Z " + view.camera.position.z
displayMessage(info);

});
function displayMessage(info) {
outputMessages.innerHTML += info;
outputMessages.scrollTop = outputMessages.scrollHeight;
}

});
0 Kudos
RobertScheitlin__GISP
MVP Esteemed Contributor
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
    <title>Add Graphics to a SceneView - 4.11</title>

    <link rel="stylesheet" href="https://js.arcgis.com/4.11/esri/css/main.css">
    <script src="https://js.arcgis.com/4.11/"></script>

    <style>
        html,
        body,
        #viewDiv {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
        }

        #outputMessages {
            position: absolute;
            z-index: 70;
            top: 0px;
            right: 0;
            bottom: 0;
            box-sizing: border-box;
            padding: 20px;
            height: 100%;
            width: 350px;
            background: rgba(0, 0, 0, 0.7);
            color: white;
            font-size: 14px;
            line-height: 30px;
            overflow: auto;
        }

        #outputMessages span {
            color: #f7be81;
            font-weight: bold;
        }
    </style>

    <script>
        require([
            "esri/Map",
            "esri/views/SceneView",
            "esri/Graphic",
            "esri/geometry/Polyline",
            "esri/geometry/Point",
            "esri/layers/ElevationLayer",
            "esri/core/promiseUtils",
            "esri/core/watchUtils",
            "esri/layers/GraphicsLayer",
        ], function (
            Map,
            SceneView,
            Graphic,
            Polyline,
            Point,
            ElevationLayer,
            promiseUtils, watchUtils, GraphicsLayer
        ) {
            // Create elevation layers
            var beforeLandslideUrl =
                "//elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer/";

            var beforeLandslideLayer = new ElevationLayer({
                url: beforeLandslideUrl
            });

            // Create Map and View
            var map = new Map({
                basemap: "satellite",
                ground: {
                    layers: [beforeLandslideLayer]
                }
            });

            var view = new SceneView({
                container: "viewDiv",
                map: map,
                camera: {
                    // initial view:
                    heading: 332.8,
                    tilt: 65.5,
                    position: {
                        x: -13563643,
                        y: 6153016,
                        z: 577,
                        spatialReference: {
                            wkid: 3857
                        }
                    },
                    heading: 0.34445102566290225,
                    tilt: 82.95536300536367
                }
            });
            var outputMessages = document.getElementById("outputMessages");

            var cameraX, cameraY, point, markerSymbol, graZ;
            var graphicsLayer = new GraphicsLayer();
            map.add(graphicsLayer);

            markerSymbol = {
                type: "simple-marker", // autocasts as new SimpleMarkerSymbol()
                color: [226, 119, 40],
                size: 100,
                outline: { // autocasts as new SimpleLineSymbol()
                    color: [255, 255, 255],
                    width: 0.2
                }
            };

            watchUtils.whenTrue(view, "stationary", function () {
                graphicsLayer.removeAll();
                cameraX = view.camera.position.longitude;
                cameraY = view.camera.position.latitude + 0.2;
                point = {
                    type: "point", // autocasts as new Point()
                    x: cameraX,
                    y: cameraY
                };

                beforeLandslideLayer.queryElevation(new Point(point), { returnSampleInfo: true })
                    .then(function (result) {;
                        graZ = result.geometry.z;
                        var info = "<span> the view center changed. </span>" +
                            "<br>  x: " + cameraX + 
                            "<br>  y: " + cameraY + 
                            "<br>  z: " + graZ + 
                            "<br> Camera z: " + (view.camera.position.z - graZ)
                        displayMessage(info);
                    })

                    // Failed to sample (e.g. service unavailable)
                    .catch(function (error) {
                        console.error("Failed to query elevation:", error);
                    });

                graphicsLayer.add(new Graphic({
                    geometry: point,
                    symbol: markerSymbol,
                }));
            });

            function displayMessage(info) {
                outputMessages.innerHTML = info;
                outputMessages.scrollTop = outputMessages.scrollHeight;
            }

        });
    </script>
</head>

<body>
    <div id="viewDiv">
        <div id="outputMessages"></div>
        <div id="titleDiv"></div>
    </div>
</body>

</html>
KennethLindhardt1
Occasional Contributor

That is so amazing, thank you so much. Exactly what I would need.

0 Kudos