手搓栅格工具-山体阴影

一、概述

山体阴影工具通过为栅格中的每个像元确定照明度,来获取表面的假定照明度。 通过设置假定光源的位置并计算每个像元相对于相邻像元的照明度值来实现此目的。 它可以显著增强用于分析或图形显示的表面的可视化效果,尤其是在使用透明度时。

默认情况下,阴影和光是与从 0 到 255(从黑色到白色递增)的整数关联的灰色阴影。

二、参数

1、太阳方位角

方向角指的是太阳的角度方向,是以北为基准方向在 0 到 360 度范围内按顺时针进行测量的。 90 度的方位角指向为东。 默认方位角为 315 度 (NW)。

2、太阳高度角

高度指的是照明源高出地平线的角度或坡度。 高度的单位为度,范围为 0(位于地平线上)到 90(位于头上)之间。 默认值为 45 度。

3、高程缩放因子

一个表面 z 单位中地面 x,y 单位的数量。

z 单位与输入表面的 x,y 单位不同时,可使用 z 因子调整 z 单位的测量单位。 计算最终输出表面时,将用 z 因子乘以输入表面的 z 值。

如果 x,y 单位和 z 单位采用相同的测量单位,则 z 因子为 1。 这是默认设置。

如果 x,y 单位和 z 单位采用不同的测量单位,则必须将 z 因子设置为适当的因子,否则会得到错误的结果。 例如,如果 z 单位是英尺,而 x,y 单位是米,则应使用 z 因子 0.3048 将 z 单位从英尺转换为米(1 英尺 = 0.3048 米)。

三、示例

下面的山体阴影示例的方位角为 315 度,高度角为 45 度,z因子为1.0。
喜马拉雅山脉
原TIF为:
在这里插入图片描述

四、gdal代码实现

def calculateSlopeAndAspect(demData: Array[Float],width: Int,height: Int,demx: Double,   demy: Double, zFactor: Double): (Array[Float], Array[Float]) = {val slopeData = new Array[Float](width * height)val aspectData = new Array[Float](width * height)// 遍历每个像素(跳过边缘1像素,避免越界)for (y <- 0 until height - 1; x <- 0 until width - 1) {// 获取3x3窗口的DEM值val z1 = demData((y - 1) * width + (x - 1))val z2 = demData((y - 1) * width + x)val z3 = demData((y - 1) * width + (x + 1))val z4 = demData(y * width + (x - 1))val z6 = demData(y * width + (x + 1))val z7 = demData((y + 1) * width + (x - 1))val z8 = demData((y + 1) * width + x)val z9 = demData((y + 1) * width + (x + 1))// x方向一阶偏导数val dx = ((z3 + 2 * z6 + z9) - (z1 + 2 * z4 + z7)) / (8.0 * demx)// y方向一阶偏导数val dy = ((z7 + 2 * z8 + z9) - (z1 + 2 * z2 + z3)) / (8.0 * demy)// 计算坡度// 公式:slope = arctan(zFactor * sqrt(dx² + dy²))val slopeRad = atan(zFactor * sqrt(dx * dx + dy * dy))slopeData(y * width + x) = slopeRad.toFloat  // 弧度制坡度// 计算坡向var aspectRad = atan2(dy, -dx)  if (aspectRad < 0) {aspectRad += 2 * Pi  // 转换为0~2π范围}aspectData(y * width + x) = aspectRad.toFloat  // 弧度制坡向}(slopeData, aspectData)
}
def calculateHillShade(slopeData: Array[Float], aspectData: Array[Float], azimuth: Double, altitude: Double): Array[Float] = {//将角度值转为弧度val azimuthRad = toRadians(azimuth)val altitudeRad = toRadians(altitude)val hillShadeData = new Array[Float](slopeData.length)for (i <- slopeData.indices) {val slope = slopeData(i)val aspect = aspectData(i)val hillShade = cos(altitudeRad) * cos(slope) + sin(altitudeRad) * sin(slope) * cos(azimuthRad - aspect)hillShadeData(i) = (255 * hillShade).toFloat}hillShadeData
}

五、geotrellis-raster代码

def calculateHillshade(dem: Tile,cellSize: CellSize,solarAzimuth: Double,solarAltitude: Double,zFactor: Double): Tile = {val (cols, rows) = (dem.cols, dem.rows)val hillshade = ArrayTile.empty(DoubleConstantNoDataCellType, cols, rows)// 太阳参数转换为弧度val azimuthRad = toRadians(solarAzimuth)val altitudeRad = toRadians(solarAltitude)val zenithRad = toRadians(90 - solarAltitude)def getZ(col: Int, row: Int): Double = {if (col < 0 || col >= cols || row < 0 || row >= rows) Double.NaNelse {val v = dem.getDouble(col, row)if (isNoData(v)) Double.NaN else v}}// 遍历每个像素for (row <- 0 until rows; col <- 0 until cols) {val (z1, z2, z3) = (getZ(col-1, row-1), getZ(col, row-1), getZ(col+1, row-1))val (z4, z5, z6) = (getZ(col-1, row),   getZ(col, row),   getZ(col+1, row))val (z7, z8, z9) = (getZ(col-1, row+1), getZ(col, row+1), getZ(col+1, row+1))if (!e.isNaN && isData(e)) {// 计算x、y方向导数val dzdx = ((z3 + 2*z6 + z9) - (z1 + 2*z4 + z7)) / (8 * cellSize.width)val dzdy = ((z7 + 2*z8 + z9) - (z1 + 2*z2 + z3)) / (8 * cellSize.height)// 计算坡度(弧度)val slopeRad = atan(zFactor * math.sqrt(dzdx*dzdx + dzdy*dzdy))// 计算坡向(度)val aspectDeg = {if (dzdx == 0 && dzdy == 0) 0.0else {var aspect = math.toDegrees(atan2(dzdy, -dzdx))if (aspect < 0) aspect + 360 else aspect}}// 计算山体阴影val cosSlope = cos(slopeRad)val sinSlope = sin(slopeRad)val cosZenith = cos(zenithRad)val sinZenith = sin(zenithRad)val deltaAzimuth = azimuthRad - toRadians(aspectDeg)val cosDelta = cos(deltaAzimuth)val shade = math.max(0.0, cosZenith * cosSlope + sinZenith * sinSlope * cosDelta)hillshade.setDouble(col, row, (shade * 255.0))} else {hillshade.setDouble(col, row, Double.NaN)}}hillshade
}

六、3x3网格示例

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Censtos docker安装方法

#设置防火墙 systemctl stop firewalld.service setenforce 0 #安装依赖包 yum install -y yum-utils device-mapper-persistent-data lvm2 #yum-utils&#xff1a;提供了 yum-config-manager 工具。 #device mapper&#xff1a; 是Linux内核中支持逻辑卷管理的通用设备映射机制…

单片机51 day46

单片机 一&#xff1a;基础概念 一&#xff1a;单片机最小系统 单片机&#xff1a;电源时钟&#xff08;晶振&#xff09;复位 //实现的最小组件 电源&#xff1a;5V直流 时钟(晶振)&#xff1a;决定系统运行的速率 一般12M&#xff08;不超过50M&#xff09;&#xff0c…

【无标题】解锁未来无线网络的无限可能——Mesh自组网设备

在科技迅猛发展的今天&#xff0c;无线网络已经成为了现代生活不可或缺的一部分。无论是在家庭中娱乐观看视频、在线游戏&#xff0c;还是在企业中进行办公、远程协作&#xff0c;网络的稳定性和覆盖范围都直接影响着我们的使用体验。传统的Wi-Fi网络在面临多设备同时连接或大面…

Libevent(5)之使用教程(4)工具

Libevent(5)之使用教程(4)工具函数 Author: Once Day Date: 2025年8月3日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 本文档翻译于&#xff1a;Fast portable non-blo…

Linux指令(3):

1. cal指令&#xff1a;我们的cal指令有日历的意思看上面&#xff0c;我们输入一个cal指令&#xff0c;可以查看当前月的日历&#xff0c;我们给cal指令后面加上 - 3&#xff0c;他就会显示这个月为中间的三个月的日历&#xff0c;但是-4 不行&#xff0c;-5 也不行。只能 - 3。…

MLS平滑滤波

1.前言 最近在学习&#xff0c;因此查阅相关资料&#xff0c;该怎么表述感觉有些困难 2.代码 2.1代码1 使用全局坐标系 参考&#xff1a;python点云移动最小二乘法(Moving Least Squares)平滑_移动最小二乘法python-CSDN博客 def Moving_Least_Squares_Smoothing_v1_expla…

华为2288H V5服务器闪红灯 无法开机案例

广东某客户1台华为2288H V5服务器&#xff0c;由于单位外围电力维修导致服务器有过一次异常断电。结果来电之后发现服务器无法开机&#xff0c;开机面板上有个红色心跳指示灯&#xff0c; 工程师到客户现场后通过192.168.2.100登陆到2288H V5服务器的BMC管理口&#xff0c;打算…

SRIO入门之官方例程仿真验证

仿真SRIO事务时序仿真之前先完成下面两步操作&#xff1a;1.Vivado软件版本2020.1&#xff0c;创建好工程及SRIO的IP核2.右键综合化的IP核&#xff0c;然后选择打开IP示例工程直接运行仿真分别将request和response两个模块添加到仿真窗口进行查看运行1000us左右就可以看到信号动…

CMake进阶: 使用FetchContent方法基于gTest的C++单元测试

目录 1.前言 2.FetchContent详解 2.1.FetchContent简介 2.2.FetchContent_Declare 2.2.1.简介 2.2.2.关键特性 2.2.3.常见示例 2.3.FetchContent_MakeAvailable 2.3.1.简介 2.3.2.核心功能与工作流程 2.3.3.示例用法 2.3.4.关键特性 2.3.5.常见问题与解决方案 3.…

亚马逊广告投放:如何减少无效曝光提高ROI

“为什么广告花费高但转化率低&#xff1f;”“如何判断关键词是否值得继续投放&#xff1f;”“曝光量暴涨但订单没增加怎么办&#xff1f;”“ACOS居高不下该如何优化&#xff1f;”“手动广告和自动广告的预算怎么分配&#xff1f;”如果你也在为这些问题头疼&#xff0c;说…

Ethereum:拥抱开源,OpenZeppelin 未来的两大基石 Relayers 与 Monitor

不知道大家是否注意到&#xff0c;OpenZeppelin 正在经历一次重大的战略转型。他们决定在 2026 年 7 月 1 日正式关闭其广受好评的 SaaS 平台——Defender&#xff0c;并将重心全面转向开源工具的建设。 这一举动在社区引发了广泛的讨论&#xff0c;也标志着 OpenZeppelin 希望…

HFSS许可监控与分析

在电磁仿真领域&#xff0c;HFSS&#xff08;High Frequency Structure Simulator&#xff09;因其卓越的性能和广泛的应用而受到用户的青睐。然而&#xff0c;随着企业和研究机构对HFSS使用需求的不断增长&#xff0c;如何有效监控和分析HFSS许可证的使用情况&#xff0c;以确…

【前端:Html】--1.3.基础语法

目录 1.Html--文件路径 2.Html--头部元素 2.1.head元素 2.2.title元素 2.3.style元素 2.4.link元素 2.5.meta元素 2.6.script元素 2.7.base 3.Html--布局技巧 3.1.CSS Float 浮动布局 3.2.CSS Flexbox 布局 3.3.CSS Grid 网格布局 3.Html--响应式web设计 3.1.设…

Java 中 Nd4j 中的 INDArray 经过 reshape 之后数据丢失(rank = 0)

问题&#xff1a; 数据经过&#xff1a; INDArray inputArray Nd4j.create(input); // 将整个输入数组转换为 INDArray INDArray accs inputArray.get(NDArrayIndex.interval(0, imuNum * 3)).reshape(imuNum, 3, 1); // 加速度部分 INDArray oris inputArray.get(NDArrayIn…

正点原子阿波罗STM32F429IGT6移植zephyr rtos(四)---在独立的应用工程里使用MPU6050

硬件平台&#xff1a;正点原子阿波罗STM32F429IGT6 zephyr版本&#xff1a;Zephyr version 4.2.0 开发环境&#xff1a;wsl ubuntu 24.4 前景提要&#xff1a; 正点原子阿波罗STM32F429IGT6移植zephyr rtos&#xff08;三&#xff09;---创建一个独立的应用工程-CSDN博客 一.修…

SAP_MMFI模块-质保金标准解决方案详解

一、业务背景 在许多企业的采购业务中,尤其是设备采购、工程项目或关键物料供应,通常会与供应商约定一笔质保金(或称保留金)。这笔款项在货物交付验收后并不会立即支付,而是会被扣留一段时间(如一年),作为供应商产品质量的保证。 核心业务痛点: 在没有系统化管理的…

Stanford CS336 assignment1 | Byte-Pair Encoding (BPE) Tokenizer

BPE一、 BPETrain1、 unicode standard and unicode encoding2、 子词分词(subword tokenization)3、 BPE的训练a、 Vocabulary initializationb、 Pre-tokenizationc、 Compute BPE merges4、 train_BPE更多实现上的细节二、 BPETokenizerinit函数from_filesencodedecodeencod…

RockAI 的破壁之战:Yan 架构如何啃下“端侧炼丹”硬骨头?

过去两年&#xff0c;AI 模型的发展叙事几乎被两大阵营主导&#xff1a;无所不能的云端模型与充满想象的端侧模型。行业曾描绘一个诱人蓝图&#xff1a;随着轻量化模型能力的提升&#xff0c;AI 终将摆脱云端束缚&#xff0c;在每个人的设备上实现永不离线的贴身智能。然而&…

交叉验证:原理、作用与在机器学习流程中的位置

交叉验证&#xff08;Cross-Validation&#xff09;是机器学习中评估模型性能、选择最优参数和防止过拟合的核心技术。它在整个机器学习流程中扮演着关键角色。一、为什么需要交叉验证&#xff1f;1. 解决训练/测试划分的局限性​​问题​​&#xff1a;随机单次划分训练集/测试…

js怎么判断一个未申明的变量?

在 JavaScript 中&#xff0c;判断一个变量是否未声明&#xff08;未定义&#xff09;需要特别注意&#xff0c;因为直接访问未声明的变量会抛出 ReferenceError 错误。 最安全的方式是使用 typeof 操作符&#xff0c;因为它对未声明的变量操作时不会报错&#xff0c;而是返回 …