Rechercher dans le blog

Mesurer des volumes dans une scène 3D avec le SDK JavaScript d'ArcGIS

En version 4.34, le SDK JavaScript d'ArcGIS a introduit des capacités de mesure de volumes dans les scènes 3D via la classe VolumeMeasurementAnalysis (encore en beta).  Deux types de mesures sont disponibles : les mesures de déblais-remblais (par exemple pour des problématiques d'aplanissement dans les travaux de construction); et les volumes de dépôt (par exemple dans des contextes de mines et carrières pour l'estimation du volume de stockpiles, ou pour des volumes de dragage).
J'ai développé rapidement une petite application, qui vous permet de tester en action ces deux types de mesures dans différents contextes :

Les dessous de l'app

Vous pouvez retrouvez le code complet de cette application sur mon Github, ou en mode bac à sable sur ce CodePen
 

Composant <arcgis-volume-measurement> 

Très simplement, j'ai ajouté le composant <arcgis-volume-measurement> à ma scène, qui permet d'y inclure les capacités de mesure de volumes via une interface utilisateur préconfigurée. L'utilisateur peut choisir le mode de mesure, puis faire une analyse interactive en dessinant sur la scène.

<arcgis-volume-measurement id="volumeMeasurement" slot="bottom-left">

Initialisation de l'analyse en cliquant sur une entité

Pour certains endroits, je possède également des couches d'entités, qui délimitent l'emprise des stockpiles ou des travaux de construction. J'aimerais que l'analyse se lance automatiquement quand l'utilisateur clique dessus. 
Avec un hitTest dans la vue, je récupère la géométrie de l'entité sur laquelle l'utilisateur a cliqué. 
  view.on("click", async (event) => {
    const hit = await view.hitTest(event);
    const feature = hit.results
      .map((r) => r.graphic)
      .filter(
        (g) => g.layer === layerStockpiles || g.layer === layerChantier
      )[0];
    if (!feature) return;

    const polygon = new Polygon({
      rings: feature.geometry.rings,
      spatialReference: feature.geometry.spatialReference
    });
Le code évalue également la couche à laquelle l'entité appartient, afin de lancer le bon type d'analyse en fonction du contexte.
    const measureType =
      feature.layer === layerStockpiles ? "stockpile" : "cut-fill";
Je peux ensuite passer la géométrie et le type de mesure en paramètres du composant d'analyse de volume, ce qui lancera une nouvelle analyse.
    volumeMeasurement.analysis.geometry = polygon;
    volumeMeasurement.analysis.measureType = measureType;
Enfin, j'ai rajouté un test sur l'objectid, qui fait que si l'utilisateur re-clique sur l'entité qu'il vient de sélectionner, celle-ci se désélectionne, pour un comportement plus ergonomique.
  const clickedId = feature.attributes.OBJECTID;
    if (currentFeatureId !== null && currentFeatureId === clickedId) {
      volumeMeasurement.analysis.geometry = null;
      volumeMeasurement.analysis.measureType = "cut-fill";
      currentFeatureId = null;
      return;
    }
    currentFeatureId = clickedId;

Le reste du code

Le reste du code est très simple : j'ai préconfiguré la scène via le Scene Viewer, permettant une intégration  rapide via le composant <arcgis-scene> (au global, passer par le Scene Viewer ou le Map Viewer pour construire sa carte plutôt que tout faire programmatiquement est une pratique fortement recommandée, je vous explique pourquoi dans cet article). 
<arcgis-scene item-id="e64cfad70d6c4b7cb8432a5d211577ab">
Je récupère ensuite les slides crées dans Scene Viewer et les ajoute à mon application, pour que l'utilisateur puisse rapidement passer d'un exemple à l'autre. Je rajoute une liste côté html :
<calcite-list id="slidesList">
Que j'alimente avec les slides préconfigurées côté JS :
 const slides = view.map.presentation?.slides;
  const list = document.getElementById("slidesList");

  if (slides) {
    slides.forEach((slide) => {
      const item = document.createElement("calcite-list-item");
      item.label = slide.title.text;
      if (slide.description.text) {
        item.description = slide.description.text;
      }
      if (slide.thumbnail?.url) {
        const img = document.createElement("img");
        img.src = slide.thumbnail.url;
        img.slot = "content-start";
        img.style.cssText = "width: 64px; height: 40px; object-fit: cover;";
        item.appendChild(img);
      }
      item.addEventListener("click", () => {
        slide.applyTo(view, { animate: true, duration: 1500 });
      });
      list.appendChild(item);
    });
  }
C'est tout pour aujourd'hui ! N'hésitez pas à consulter les autres tutoriels du blog, ou à en apprendre plus sur l'API JavaScript d'ArcGIS

Aucun commentaire:

Enregistrer un commentaire