04-ArcGIS For JavaScript的可视域分析功能

文章目录

  • 综述
  • 代码实现
  • 代码解析
  • 结果

在这里插入图片描述

综述

在数字孪生或者实景三维的项目中,视频融合和可视域分析,一直都是热点问题。Cesium中,支持对阴影的后处理操作,通过重新编写GLSL代码就能实现视域和视频融合的功能。ArcGIS之前支持的可视域分析只要是通过GP服务的方式去实现,并且只针对地形有相应的效果,并不能直接叠加到建模模型上。
ArcGIS for JavaScript最新发布了4.30版本的api,其中新增了对于模型场景的视域分析,并且提供了很好的交互功能,使其在项目应用中又有了更多的可能性。

代码实现

直接上代码,或者直接去官网看。

<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
  <title>Interactive viewshed analysis | Sample | ArcGIS Maps SDK for JavaScript 4.30</title>
  <style>
    html,
    body,
    html,
    body,
    #viewDiv {
      width: 100%;
      height: 100%;
      margin: 0;
      padding: 0;
    }
    #viewshedComponent {
      width: 270px;
    }
    #viewshedComponent calcite-button {
      display: flex;
    }
    #promptText {
      margin-top: 0.4rem;
    }
  </style>
  <link rel="stylesheet" href="https://js.arcgis.com/4.30/esri/themes/light/main.css" />
  <script src="https://js.arcgis.com/4.30/"></script>
  <script type="module" src="https://js.arcgis.com/calcite-components/2.8.5/calcite.esm.js"></script>
  <link rel="stylesheet" type="text/css" href="https://js.arcgis.com/calcite-components/2.8.5/calcite.css" />
  <script>
    require([
      "esri/Map",
      "esri/views/SceneView",
      "esri/geometry/SpatialReference",
      "esri/core/promiseUtils",
      "esri/core/reactiveUtils",
      "esri/views/3d/environment/SunLighting",
      "esri/analysis/ViewshedAnalysis",
      "esri/analysis/Viewshed"
    ], function (
      Map,
      SceneView,
      SpatialReference,
      promiseUtils,
      reactiveUtils,
      SunLighting,
      ViewshedAnalysis,
      Viewshed
    ) {
      const view = new SceneView({
        container: "viewDiv",
        camera: {
          position: {
            spatialReference: SpatialReference.WebMercator,
            x: -9753837.742627423,
            y: 5140806.202422867,
            z: 995.4546383377165
          },
          heading: 1.2311944909542853,
          tilt: 70.07900968078631
        },
        map: new Map({
          basemap: "topo-3d",
          ground: "world-elevation"
        }),
        environment: {
          lighting: new SunLighting({
            date: new Date("January 18, 2024 12:50:00 UTC-6"),
            directShadowsEnabled: true
          })
        }
      });

      view.when(async () => {
        // Hide the 3D basemap's labels layer.
        const labelsLayer = view.map.basemap.referenceLayers.find(
          (layer) => layer.title === "Places and Labels"
        );
        labelsLayer.visible = false;

        // Create the viewshed shape.
        const viewshed = new Viewshed({
          observer: {
            spatialReference: SpatialReference.WebMercator,
            x: -9754426,
            y: 5143111,
            z: 330
          },
          farDistance: 900, // In meters
          tilt: 84, // Tilt of 0 looks down, tilt of 90 looks parallel to the ground, tilt of 180 looks up to the sky
          heading: 63, // Counted clockwise from North
          horizontalFieldOfView: 85,
          verticalFieldOfView: 52
        });
        // Initialize viewshed analysis with the created viewshed shape and add it to the view.
        const viewshedAnalysis = new ViewshedAnalysis({ viewsheds: [viewshed] });
        view.analyses.add(viewshedAnalysis);

        // Access the viewshed's analysis view.
        const analysisView = await view.whenAnalysisView(viewshedAnalysis);
        // Make the existing analysis interactive and select the created viewshed.
        analysisView.interactive = true;
        analysisView.selectedViewshed = viewshed;

        // Add interactivity to the custom UI component's buttons.
        const createButton = document.getElementById("createButton");
        const cancelButton = document.getElementById("cancelButton");
        const promptText = document.getElementById("promptText");

        // Controller which allows to cancel an ongoing viewshed creation operation.
        let abortController = null;

        createButton.addEventListener("click", () => {
          // Cancel any pending creation operation.
          stopCreating();

          // Create a new abort controller for the new operation.
          abortController = new AbortController();

          updateUI();

          // Save current number of viewsheds to track whenever a new one is created.
          const viewshedCounter = viewshedAnalysis.viewsheds.length;
          // Watch whenever the a new viewshed is created and selected and then stop the creation method.
          reactiveUtils.when(
            () => viewshedAnalysis.viewsheds.length > viewshedCounter && analysisView.selectedViewshed,
            () => {
              stopCreating();
              updateUI();
            }
          );

          // Pass the controller as an argument to the interactive creation method
          // and schedule the updateUI function after creating viewsheds is finished.
          analysisView
            .createViewsheds(abortController)
            .catch((e) => {
              // When the operation is cancelled, don't do anything. Any other errors are thrown.
              if (!promiseUtils.isAbortError(e)) {
                throw e;
              }
            })
            .finally(() => {
              // Update the UI to reflect the non-creating mode.
              updateUI();
            });
        });

        cancelButton.addEventListener("click", () => {
          // Pressing the Cancel button stops the viewshed creation process and updates the UI accordingly.
          stopCreating();
          updateUI();
        });
        // Cancel the creation process and updates the UI when ESC is pressed.
        view.on("key-down", (event) => {
          if ((event.key = "Escape")) {
            stopCreating();
            updateUI();
          }
        });

        // Cancel any pending viewshed creation operation.
        function stopCreating() {
          abortController?.abort();
          abortController = null;
        }

        // Update the UI component according to whether there is a pending operation.
        function updateUI() {
          const creating = abortController != null;
          createButton.style.display = !creating ? "flex" : "none";
          cancelButton.style.display = creating ? "flex" : "none";
          promptText.style.display = creating ? "flex" : "none";
        }

        // Add the component to the UI.
        view.ui.add("viewshedComponent", "top-right");
      });

    });
  </script>
</head>

<body>
  <div id="viewDiv"></div>
  <calcite-card id="viewshedComponent">
    <calcite-button id="createButton">Create viewshed</calcite-button>
    <calcite-button id="cancelButton" style="display:none">Cancel </calcite-button>
    <div id="promptText" style="display: none">
      <em>Start the analysis by clicking in the scene to place the observer point and set the target.</em>
    </div>
  </calcite-card>
</body>

</html>

代码解析

ArcGIS for JavaScript提供了新的对象Viewshed和ViewshedAnalysis。
在这里插入图片描述
在这里插入图片描述

Viewshed定义了Viewshed分析的几何形状。视域由位置、距离、方向(由头部和倾斜定义)和视野角度决定。
ViewshedAnalysis允许在3D SceneView中创建和显示viewshed和view dome类型的可见性分析。该分析功能可以包含多个视图。它们可以以交互方式或编程方式创建,并且可以将分析直接添加到SceneView.analyses中。

const viewshed = new Viewshed({
   observer: {
     spatialReference: {
       latestWkid: 3857,
       wkid: 102100
     },
     x: -9754426,
     y: 5143111,
     z: 330
   },
   farDistance: 900,
   heading: 64,
   tilt: 84,
   horizontalFieldOfView: 85,
   verticalFieldOfView: 52
 });
 const viewshedAnalysis = new ViewshedAnalysis({
   viewsheds: [viewshed],
 });

 view.analyses.add(viewshedAnalysis);
···

上面方法是直接去创建可视域的功能,当然也可以通过交互的方式去创建可视域。

```javascript
		const analysisView = await 		 view.whenAnalysisView(viewshedAnalysis);
        // Make the existing analysis interactive and select the created viewshed.
        analysisView.interactive = true;
        analysisView.selectedViewshed = viewshed;
analysisView
            .createViewsheds(abortController)
            .catch((e) => {
              // When the operation is cancelled, don't do anything. Any other errors are thrown.
              if (!promiseUtils.isAbortError(e)) {
                throw e;
              }
            })
            .finally(() => {
              // Update the UI to reflect the non-creating mode.
              updateUI();
            });

结果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/778234.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在 PostgreSQL 中,如何处理数据的版本控制?

文章目录 一、使用时间戳字段进行版本控制二、使用版本号字段进行版本控制三、使用历史表进行版本控制四、使用 RETURNING 子句获取更新前后的版本五、使用数据库触发器进行版本控制 在 PostgreSQL 中&#xff0c;处理数据的版本控制可以通过多种方式实现&#xff0c;每种方式都…

开源六轴协作机械臂myCobot 280接入GPT4大模型!实现更复杂和智能化的任务

本文已经或者同济子豪兄作者授权对文章进行编辑和转载 引言 随着人工智能和机器人技术的快速发展&#xff0c;机械臂在工业、医疗和服务业等领域的应用越来越广泛。通过结合大模型和多模态AI&#xff0c;机械臂能够实现更加复杂和智能化的任务&#xff0c;提升了人机协作的效率…

zerotier-one自建根服务器方法五

一、简介 前面几篇文章已经写完了自己建立服务器的方法&#xff0c;今天写一下我在使用过程中遇到的问题和解决方法。 二、准备工作 准备一个有公网IP的云主机。 要稳定性、安全性、不差钱的可以使用阿里、腾讯等大厂的云服务器。 本人穷屌丝一枚&#xff0c;所以我用的是免…

gcc/g++的四步编译

目录 前言1.预处理&#xff08;进行宏替换&#xff09;2.编译&#xff08;生成汇编&#xff09;3.汇编&#xff08;生成二进制文件&#xff09;4. 链接 &#xff08;生成可执行文件&#xff09;a. 动态库 && 动态链接b. 静态库 && 静态链接c. 验证d. 动静态链接…

指针回顾.

指针的主要作用&#xff1a;提供一种间接访问数据的方法 1.地址:区分不同内存空间的编号 2.指针:指针就是地址,地址就是指针 3.指针变量:存放指针的变量称为指针变量,简称为指针 1.指针的定义 int *p NULL; int *q NULL; char *p NULL; double *p NUL…

前端面试题13(API请求方法)

在前端JavaScript中&#xff0c;进行API请求主要可以通过几种方式来实现&#xff0c;最常见的是使用XMLHttpRequest&#xff08;较旧的方法&#xff09;、fetch&#xff08;现代浏览器推荐方法&#xff09;以及使用第三方库如axios或jQuery.ajax等。 1. XMLHttpRequest 这是最…

springboot集成tika解析word,pdf,xls文件文本内容

介绍 Apache Tika 是一个开源的内容分析工具包&#xff0c;用于从各种文档格式中提取文本和元数据。它支持多种文档类型&#xff0c;包括但不限于文本文件、HTML、PDF、Microsoft Office 文档、图像文件等。Tika 的主要功能包括内容检测、文本提取和元数据提取。 官网 https…

开发个人Go-ChatGPT--5 模型管理 (二)

开发个人Go-ChatGPT–5 模型管理 (二) ChatGPT 这是该项目的最终效果&#xff0c;使用ollama的open-webui进行人与机器的对话功能&#xff0c;对话的后端服务则完全对接自己开发的Go项目。 如何实现呢&#xff1f;则通过这篇文章&#xff0c;一一给大家剖析后端的原理及功能…

html的作业

目录 作业题目 1.用户注册 A图 B代码 2.工商银行电子汇款单 A图 B代码 3.李白诗词 A图 B代码 4.豆瓣电影 A图 B代码 学习产出&#xff1a; 作业题目 1.用户注册 A图 B代码 <!DOCTYPE html> <html lang"zh"> <head><meta charset&qu…

常见算法和Lambda

常见算法和Lambda 文章目录 常见算法和Lambda常见算法查找算法基本查找&#xff08;顺序查找&#xff09;二分查找/折半查找插值查找斐波那契查找分块查找扩展的分块查找&#xff08;无规律的数据&#xff09; 常见排序算法冒泡排序选择排序插入排序快速排序递归快速排序 Array…

52-4 内网代理1 - 内网代理简介

一、正向连接 正向连接是指受控端主机监听一个端口,由控制端主机主动发起连接的过程。这种连接方式适用于受控主机拥有公网IP地址的情况。例如,在攻击者和受害者都具有公网IP的情况下,攻击者可以直接通过受害者的公网IP地址访问受害者主机,因此可以使用正向连接来建立控制通…

mysql5.6的安装步骤

1.下载mysql 下载地址&#xff1a;https://downloads.mysql.com/archives/community/ 在这里我们下载zip的包 2.解压mysql包到指定目录 3. 添加my.ini文件 # For advice on how to change settings please see # http://dev.mysql.com/doc/refman/5.6/en/server-configurat…

调试支付分回调下载平台证书

之前的原生代码放到webman里面&#xff0c;死活跑不通 没办法&#xff0c;只能用esayWeChat6.7 &#xff08;自行下载&#xff09; 它里面配置要用到平台证书 平台证书又要用到 composer require wechatpay/wechatpay 但是请求接口之前&#xff0c;你先要用到一个临时的平台…

ELK日志实时监控

目录 一、ELK/EFK简介 1.1 什么是ELK/EFK? 1.2 常见架构 1、Elasticsearch Logstash Kibana 2、Elasticsearch Logstash Filebeat Kibana 3、Elasticsearch Logstash Filebeat Kibana Redis 4、Elasticsearch Fluentd Filebeat Kibana 1.3 基本流程 二、…

【鸿蒙学习笔记】@Link装饰器:父子双向同步

官方文档&#xff1a;Link装饰器&#xff1a;父子双向同步 目录标题 [Q&A] Link装饰器作用 [Q&A] Link装饰器特点样例&#xff1a;简单类型样例&#xff1a;数组类型样例&#xff1a;Map类型样例&#xff1a;Set类型样例&#xff1a;联合类型 [Q&A] Link装饰器作用…

android新闻app(二)

新闻详细页&#xff1a; 历史浏览记录SQList&#xff1a; 分类&#xff1a; 历史浏览记录主体UI和详细&#xff1a; 侧边栏&#xff1a; 参考&#xff1a;浩宇开发

SSM贫困生申请管理系统-计算机毕业设计源码84308

摘要 随着教育信息化的不断推进&#xff0c;越来越多的高校开始借助信息技术手段提升贫困生申请管理的效率与准确性。为此&#xff0c;我们设计并实现了SSM贫困生申请管理系统&#xff0c;旨在通过信息化手段优化贫困生申请流程&#xff0c;提高管理效率&#xff0c;为贫困生提…

IDEA越用越卡?教你轻松解决IDEA内存占用过高问题

大家好&#xff0c;我是瑶山&#xff0c;最近IDEA越用越卡了&#xff0c;刚刚内存卡爆&#xff0c;带着整个电脑也卡的飞起&#xff0c;只能重启了电脑。 虽然重启后又恢复到了流畅&#xff0c;但是问题还是如鲠在喉&#xff0c;痛定思痛&#xff0c;还是决定处理下&#xff01…

【话题】AI是在帮助开发者还是取代他们

大家好&#xff0c;我是全栈小5&#xff0c;欢迎阅读小5的系列文章&#xff0c;这是《话题》系列文章 目录 引言AI在代码生成中的应用AI在错误检测和自动化测试中的作用对开发者职业前景的影响技能需求的变化与适应策略结论文章推荐 引言 随着人工智能&#xff08;AI&#xff…

《第一行代码》小结

文章目录 一. Android总览1. 系统架构2. 开发环境3. 在红米手机上运行4. 项目资源详解4.1 整体结构4.2 res文件4.3 build.gradle文件 二. Activity0. 常用方法小结1. 创建一个Activity 一. Android总览 1. 系统架构 应用层&#xff1a;所有安装在手机上的应用程序 应用框架层&…