Cesium加载ArcGIS Server4490且orgin -400 400的切片服务

Cesium在使用加载Cesium.ArcGisMapServerImageryProvider加载切片服务时,默认只支持wgs84的4326坐标系,不支持CGCS2000的4490坐标系。

如果是ArcGIS发布的4490坐标系的切片服务,如果原点在orgin X: -180.0Y: 90.0的情况下,我们可以通过WebMapTileServiceImageryProvider按照WMTS的方式加载(需符合OGC标准的WMTS类型)。

但是对于ArcGIS发布4490坐标系的切片服务,如果原点在orgin X: -400.0Y: 400.0的情况下,我们无法实现加载,本文通过示例演示实现Cesium加载ArcGIS Server4490且orgin -400 400的切片服务。

本文使用:

Cesium源码版本:1.94

另外,本文的一些解释需要对切片原理有一定了解(想进一步了解的话可以去看看相关文档说明,不想了解的话按步骤修改就行了)。

为了能够调试源码,打包的时候使用命令:npm run combine

一、通过修改源码实现ArcGIS的切片服务,需要修改的源码文件包括:

  • ArcGisMapServerImageryProvider
  • GeographicTilingScheme
  • Ellipsoid

1、修改ArcGisMapServerImageryProvider类

通过查看ArcGisMapServerImageryProvider(\Source\Scene\ArcGisMapServerImageryProvider.js)源码,我们发现它不支持CGCS2000的4490坐标系(仅支持wgs84的4326坐标系):

找到metadataSuccess方法,进行以下修改:

(1)读取切片元数据时增加支持wkid 4490坐标系的判断,同时将切片信息也传入,目的是为了后面在获取行列号xy时,可以通过读取切片信息,使用自定义方法改写行列号的获取方式。

复制代码

else if (data.tileInfo.spatialReference.wkid === 4490) {that._tilingScheme = new GeographicTilingScheme({ellipsoid: options.ellipsoid,tileInfo: data.tileInfo,rectangle: that._rectangle,numberOfLevelZeroTilesX: options.numberOfLevelZeroTilesX,numberOfLevelZeroTilesY: options.numberOfLevelZeroTilesY});that._tilingScheme._tileInfo = data.tileInfo;//附加自定义属性}

复制代码

 具体位置如图所示:

(2)fullExtent范围增加wkid 4490坐标系判断。

复制代码

else if (data.fullExtent.spatialReference.wkid === 4326 || data.fullExtent.spatialReference.wkid === 4490) {that._rectangle = Rectangle.fromDegrees(data.fullExtent.xmin,data.fullExtent.ymin,data.fullExtent.xmax,data.fullExtent.ymax);}

复制代码

 代码位置:

 2、修改GeographicTilingScheme类

GeographicTilingScheme类的位置是:\Source\Core\GeographicTilingScheme.js

通过增加4490坐标系的椭球、矩阵范围等定义,4490坐标系默认椭球为CGCS2000,矩阵范围为(-180,-90,180,90),开放矩阵范围的目的就是为了支持自定义的origin原点。

复制代码

if (defined(options.tileInfo)&& defined(options.tileInfo.spatialReference)&& defined(options.tileInfo.spatialReference.wkid)&& options.tileInfo.spatialReference.wkid == 4490) {this._tileInfo = options.tileInfo;this._ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.CGCS2000);this._rectangle = defaultValue(options.rectangle, Rectangle.fromDegrees(-180, -90, 180, 90));this._numberOfLevelZeroTilesX = defaultValue(options.numberOfLevelZeroTilesX, 4);this._numberOfLevelZeroTilesY = defaultValue(options.numberOfLevelZeroTilesY, 2);}else {this._ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);this._rectangle = defaultValue(options.rectangle, Rectangle.MAX_VALUE);this._numberOfLevelZeroTilesX = defaultValue(options.numberOfLevelZeroTilesX, 2);this._numberOfLevelZeroTilesY = defaultValue(options.numberOfLevelZeroTilesY, 1);}this._projection = new GeographicProjection(this._ellipsoid);

复制代码

代码位置: 

 (2)修改切片矩阵计算获取行列号数量xy值的原型方法getNumberOfXTilesAtLevel和getNumberOfYTilesAtLeve

复制代码

/*** Gets the total number of tiles in the X direction at a specified level-of-detail.** @param {Number} level The level-of-detail.* @returns {Number} The number of tiles in the X direction at the given level.*/
GeographicTilingScheme.prototype.getNumberOfXTilesAtLevel = function (level) {// return this._numberOfLevelZeroTilesX << level;if (!defined(this._tileInfo)) {return this._numberOfLevelZeroTilesX << level} else { // 使用切片矩阵计算var currentMatrix = this._tileInfo.lods.filter(function (item) {return item.level === level})var currentResolution = currentMatrix[0].resolution// return Math.round(360 / (this._tileInfo.rows * currentResolution))return Math.round(CesiumMath.toDegrees(CesiumMath.TWO_PI * 2) / (this._tileInfo.rows * currentResolution));}
};/*** Gets the total number of tiles in the Y direction at a specified level-of-detail.** @param {Number} level The level-of-detail.* @returns {Number} The number of tiles in the Y direction at the given level.*/
GeographicTilingScheme.prototype.getNumberOfYTilesAtLevel = function (level) {// return this._numberOfLevelZeroTilesY << level;if (!defined(this._tileInfo)) {return this._numberOfLevelZeroTilesY << level} else { // 使用切片矩阵计算var currentMatrix = this._tileInfo.lods.filter(function (item) {return item.level === level})var currentResolution = currentMatrix[0].resolution// return Math.round(180 / (this._tileInfo.cols * currentResolution))return Math.round(CesiumMath.toDegrees(CesiumMath.TWO_PI * 2) / (this._tileInfo.cols * currentResolution));}
};

复制代码

代码位置:

这段代码和参考文章的代码存在一定出入,在文末会做详细说明。

3、修改Ellipsoid类,定义2000椭球参数

Ellipsoid类位置:\Source\Core\Ion.js

 定义2000椭球参数:

复制代码

/*** An Ellipsoid instance initialized to the CGCS2000 standard.** @type {Ellipsoid}* @constant*/
Ellipsoid.CGCS2000 = Object.freeze(new Ellipsoid(6378137.0, 6378137.0, 6356752.31414035585)
);

复制代码

 代码位置:

二、代码调用

源码修改后,为了能够调试源码,使用npm run combine打包下代码,并在调用地方修改下引用,

测试用html页面(做测试的页面,有一些其他代码,可以忽略,留意本文需要的代码部分):

复制代码

<!DOCTYPE html>
<html lang="en">
<head><!-- Use correct character set. --><meta charset="utf-8"/><!-- Tell IE to use the latest, best version. --><meta http-equiv="X-UA-Compatible" content="IE=edge"/><!-- Make the application on mobile take up the full browser screen and disable user scaling. --><metaname="viewport"content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"/><title>cesium加载影像和矢量数据</title><script src="../Build/CesiumUnminified/Cesium.js"></script><style>@import url(../Build/CesiumUnminified/Widgets/widgets.css);html,body,#cesiumContainer {width: 100%;height: 100%;margin: 0;padding: 0;overflow: hidden;}</style>
</head>
<body>
<div id="cesiumContainer"></div>
<script>//天地图tokenlet TDT_tk = "b0df1f950b1fd6914abe9e17079c0345";//Cesium tokenlet cesium_tk = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI1NThjYTk0MC03YjQwLTQ3YWYtOTY5Yy04NDk3OTJmMmI4NDciLCJpZCI6NzAxOTMsImlhdCI6MTYzNDA4ODE1N30.TB1v9XXATQLUGE5GNki_fYFMHddIyQ9arXPIx65e09s";//天地图影像let TDT_IMG_C = "http://{s}.tianditu.gov.cn/img_c/wmts?service=wmts&request=GetTile&version=1.0.0" +"&LAYER=img&tileMatrixSet=c&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}" +"&style=default&format=tiles&tk=" + TDT_tk;//标注let TDT_CIA_C = "http://{s}.tianditu.gov.cn/cia_c/wmts?service=wmts&request=GetTile&version=1.0.0" +"&LAYER=cia&tileMatrixSet=c&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}" +"&style=default&format=tiles&tk=" + TDT_tk;//初始页面加载//Cesium.Ion.defaultAccessToken = cesium_tk;var cgs2000Ellipsolid = Cesium.Ellipsoid.CGCS2000var cgs2000GeographicProj = new Cesium.GeographicProjection(cgs2000Ellipsolid)let viewer = new Cesium.Viewer('cesiumContainer', {// baseLayerPicker: false,timeline: true,homeButton: true,fullscreenButton: true,infoBox: true,animation: true,shouldAnimate: true,mapProjection: cgs2000GeographicProj//imageryProvider: layer, //设置默认底图});let rightTilt = true;if (rightTilt) {viewer.scene.screenSpaceCameraController.tiltEventTypes = [Cesium.CameraEventType.RIGHT_DRAG,Cesium.CameraEventType.PINCH,{eventType: Cesium.CameraEventType.LEFT_DRAG,modifier: Cesium.KeyboardEventModifier.CTRL},{eventType: Cesium.CameraEventType.RIGHT_DRAG,modifier: Cesium.KeyboardEventModifier.CTRL}]viewer.scene.screenSpaceCameraController.zoomEventTypes = [Cesium.CameraEventType.MIDDLE_DRAG,Cesium.CameraEventType.WHEEL,Cesium.CameraEventType.PINCH]}var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);handler.setInputAction(function(evt) {var cartesian=viewer.camera.pickEllipsoid(evt.position,viewer.scene.globe.ellipsoid);var cartographic=Cesium.Cartographic.fromCartesian(cartesian);var lng=Cesium.Math.toDegrees(cartographic.longitude);//经度值var lat=Cesium.Math.toDegrees(cartographic.latitude);//纬度值var mapPosition={x:lng,y:lat,z:cartographic.height};//cartographic.height的值始终为零。alert("longitude:" + lng + ";latitude:" + lat );}, Cesium.ScreenSpaceEventType.LEFT_CLICK);viewer.imageryLayers.remove(viewer.imageryLayers.get(0))//添加tmslet tms = {};tms.url =  "http://10.0.7.16:81/tms";if (tms) {const layerInfo = {url: tms.url,fileExtension: tms.fileExtension || 'jpg',maximumLevel: tms.maxZoom || 7,name: 'tms'}const tmsService = new Cesium.TileMapServiceImageryProvider(layerInfo)tmsService.layerInfo = layerInfo}//添加地形let terrain = {};terrain.url =  "http://data.marsgis.cn/terrain";if (terrain) {const terrainLayer = new Cesium.CesiumTerrainProvider({url: terrain.url})viewer.terrainProvider = terrainLayer}_matrixIds = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18"]//调用影响中文注记服务/*viewer.imageryLayers.addImageryProvider(new Cesium.WebMapTileServiceImageryProvider({url: TDT_CIA_C,layer: "tdtImg_c",style: "default",format: "tiles",tileMatrixSetID: "c",subdomains: ["t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"],tilingScheme: new Cesium.GeographicTilingScheme(),tileMatrixLabels: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19"],maximumLevel: 50,show: false}))*//*var myGeographicTilingScheme = new Cesium.GeographicTilingScheme({ellipsoid: cgs2000Ellipsolid,rectangle: Cesium.Rectangle.fromDegrees(-400, -399.9999999999998, 400, 399.9999999999998),numberOfLevelZeroTilesX: 4,numberOfLevelZeroTilesY: 4})*/var world4490 = new Cesium.ArcGisMapServerImageryProvider({url: 'http://10.1.88.200:6080/arcgis/rest/services/test/global4490ori400/MapServer',//tilingScheme: myGeographicTilingScheme,rectangle: Cesium.Rectangle.fromDegrees(-400, -320, 320, 400),ellipsoid:cgs2000Ellipsolid,numberOfLevelZeroTilesX: 4,numberOfLevelZeroTilesY: 4});viewer.imageryLayers.addImageryProvider(world4490);//viewer.imageryLayers.addImageryProvider(world);//使用ArcGisMapServerImageryProvider加载影像没成功,改用WebMapServiceImageryProvider//var world = new Cesium.ArcGisMapServerImageryProvider({//url:'http://10.1.88.200:6080/arcgis/rest/services/test/globaltdt5/MapServer',//});//viewer.imageryLayers.addImageryProvider(world);var arcgisyx = new Cesium.WebMapServiceImageryProvider({url:'http://10.1.88.200:6080/arcgis/rest/services/test/globaltdt5/MapServer/tile/{z}/{y}/{x}',layers:[0]});// viewer.imageryLayers.addImageryProvider(arcgisyx);var china = new Cesium.ArcGisMapServerImageryProvider({url:'http://10.1.88.200:6080/arcgis/rest/services/test/china4490/MapServer'});viewer.imageryLayers.addImageryProvider(china);
</script>
</body>
</html>

复制代码

1、定义椭球体部分:

 var cgs2000Ellipsolid = Cesium.Ellipsoid.CGCS2000var cgs2000GeographicProj = new Cesium.GeographicProjection(cgs2000Ellipsolid)

2、初始化Cesium.Viewer时,增加2000的mapProjection

复制代码

let viewer = new Cesium.Viewer('cesiumContainer', {// baseLayerPicker: false,timeline: true,homeButton: true,fullscreenButton: true,infoBox: true,animation: true,shouldAnimate: true,mapProjection: cgs2000GeographicProj//imageryProvider: layer, //设置默认底图});

复制代码

3、调用关键代码,加载图层

复制代码

var world4490 = new Cesium.ArcGisMapServerImageryProvider({url: 'http://10.1.88.200:6080/arcgis/rest/services/test/global4490ori400/MapServer',//tilingScheme: myGeographicTilingScheme,rectangle: Cesium.Rectangle.fromDegrees(-400, -320, 320, 400),ellipsoid:cgs2000Ellipsolid,numberOfLevelZeroTilesX: 4,numberOfLevelZeroTilesY: 4});viewer.imageryLayers.addImageryProvider(world4490);

复制代码

说明:

(1)服务说明,发布了一个全球影像4490坐标系-400,400起点的数据(切片方案保证其他参数与-180,90一致,可从本文文末获取切片方案xml文件用来切片测试)

 (2)在新建ArcGisMapServerImageryProvider时,可以不设置tilingScheme。发现ArcGisMapServerImageryProvider里有新建tilingScheme,如果设置了tilingScheme,发现这里的行列数参数没有起作用,故直接在新建ArcGisMapServerImageryProvider传入行列数参数,并在类中新建切片方案的时候读取。

rectangle切片范围:发现用(-400, -400, 400, 400)带入整个地图偏移了:

对切片的原理进一步了解后:

针对-400,400起点切片,为了保证和-180,90按照0级两列一行的大小,如上图,按照格网一样90°大小,划分成4行4列,切片范围应该是(-400, -320, 320, 400),请求的切片应该6块,行列是(行在前列在后):(1,1),(1,2),(1,3),(2,1),(2,2),(2,3)

按照这样设置,此时再次运行后,能够正常加载-400,400起点切片了:

以上是展开的效果,球体的效果:

注:

本文参考文章:Cesium 之加载ArcGIS Server 4490切片服务(含orgin -400 400)_cesium加载arcgis面切片失败_xizhjxust_GIS的博客-CSDN博客

关于getNumberOfXTilesAtLevel和getNumberOfYTilesAtLeve这段代码和上述参考的文档存在一定出入做进一步说明。

但是因为直接拷贝后发现不能正常加载,通过切片原理判断得出,计算的行列式数量不对,改成了2π*2:

 

这里0级的话,-400,400起点切片获取的xy切片数量应该是4行4列,通过反推应该是4π,如果是-180,90起点的话,是2行1列,则x应该用2π,y应该用π,原文章应该是针对-180,90起点的计算方式。

这段代码的写法只支持-400,400起点,因为只是为了测试能够把-400,400起点的切片数据,偷懒直接这么写了。如果要同时支持两种起点,这里的写法应该要改成公式:(右顶点X-左顶点X)/(256*分辨率);(上顶点Y-下顶点Y)/(256*分辨率)

如:

-180,90起点:[180-(-180)]/(256*分辨率)      范围右顶点经度-左顶点经度,256是因为切片大小是256*256,当0级时候,分辨率为0.7031250000026057

-400,400起点:[320-(-400)]/(256*分辨率)      范围右顶点经度-左顶点经度,256是因为切片大小是256*256,当0级时候,分辨率为0.7031250000026057

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

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

相关文章

【最新可用】VMware中ubuntu与主机window之间使用共享文件夹传输大文件

一、VMware设置共享文件夹 &#xff08;1&#xff09;虚拟机关机情况下&#xff0c;创建一个共享文件夹 &#xff08;2&#xff09;ubuntu中挂载共享文件夹 1、如果之前已经挂载 hgfs&#xff0c;先取消挂载 sudo umount /mnt/hgfs2、重新使用以下命令挂载 sudo /usr/bin/vmh…

CompletableFuture总结和实践

CompletableFuture被设计在Java中进行异步编程。异步编程意味着在主线程之外创建一个独立的线程&#xff0c;与主线程分隔开&#xff0c;并在上面运行一个非阻塞的任务&#xff0c;然后通知主线程进展&#xff0c;成功或者失败。 一、概述 1.CompletableFuture和Future的区别&…

Cesium之水流模型

关于Primitive。 Primitive和Entity&#xff0c;一般翻译成图元和实体&#xff0c;图元更接近底层&#xff0c;实体是封装后的高级对象&#xff0c;使用更加简便。一般来说&#xff0c;Primitive的使用相对繁琐&#xff0c;相比Entity需要使用者自己初始化更多对象&#xff0c…

day9 STM32 I2C总线通信

I2C总线简介 I2C总线介绍 I2C&#xff08;Inter-Integrated Circuit&#xff09;总线&#xff08;也称IIC或I2C&#xff09;是由PHILIPS公司开发的两线式串行总线&#xff0c;用于连接微控制器及其外围设备&#xff0c;是微电子通信控制领域广泛采用的一种总线标准。 它是同步通…

【Android】相对布局(RelativeLayout)最全解析

【Android】相对布局&#xff08;RelativeLayout&#xff09;最全解析 一、相对布局&#xff08;RelativeLayout&#xff09;概述二、根据父容器定位三、根据兄弟控件定位 一、相对布局&#xff08;RelativeLayout&#xff09;概述 相对布局&#xff08;RelativeLayout&#x…

【仿写框架之仿写Tomact】四、封装HttpRequest对象(属性映射http请求报文)、HttpResponse对象(属性映射http响应报文)

文章目录 1、创建HttpRequest对象2、创建HttpResponse对象 1、创建HttpRequest对象 HttpRequest对象中的属性与HTTP协议中的内容对应&#xff0c;用于后序servlet从request中获取请求中的参数。 参照http请求报文&#xff1a; import java.io.BufferedReader; import java…

(详解踩坑)GIT版本回滚git stash、git reset、git reset --hard、git revert

目录 背景 一、&#xff08;git log、git reflog&#xff09;查看git提交日志及命令历史 1.1 git log&#xff08;提交日志&#xff09; 1.2 git reflog&#xff08;命令历史&#xff09; 二、git reset&#xff08;回退到指定的版本&#xff0c;并且保留更改&#xff09; …

Vue-9.集成(.editorconfig、.eslintrc.js、.prettierrc)

介绍 同时使用 .editorconfig、.prettierrc 和 .eslintrc.js 是很常见的做法&#xff0c;因为它们可以在不同层面上帮助确保代码的格式一致性和质量。这种组合可以在开发过程中提供全面的代码维护和质量保证。然而&#xff0c;这也可能增加一些复杂性&#xff0c;需要谨慎配置…

Redis消息传递:发布订阅模式详解

目录 1.Redis发布订阅简介 2.发布/订阅使用 2.1 基于频道(Channel)的发布/订阅 2.2 基于模式(pattern)的发布/订阅 3.深入理解Redis的订阅发布机制 3.1 基于频道(Channel)的发布/订阅如何实现的&#xff1f; 3.2 基于模式(Pattern)的发布/订阅如何实现的&#xff1f; 3.3 Sp…

【深入探究人工智能】:常见机器学习算法总结

文章目录 1、前言1.1 机器学习算法的两步骤1.2 机器学习算法分类 2、逻辑回归算法2.1 逻辑函数2.2 逻辑回归可以用于多类分类2.3 逻辑回归中的系数 3、线性回归算法3.1 线性回归的假设3.2 确定线性回归模型的拟合优度3.3线性回归中的异常值处理 4、支持向量机&#xff08;SVM&a…

React+Typescript 状态管理

好 本文 我们来说说状态管理 也就是我们的 state 我们直接顺便写一个组件 参考代码如下 import * as React from "react";interface IProps {title: string,age: number }interface IState {count:number }export default class hello extends React.Component<I…

python 自动化学习(四) pyppeteer 浏览器操作自动化

背景 之前我在工作中涉及到了很多地方都是重复性的页面点点点工作&#xff0c;又因为安全保密原则不开放接口和数据库&#xff0c;只有一个页面来提供点击进行操作&#xff0c;就想着用前面学的自动化来实现&#xff0c;但发现前面学的模拟操作对浏览器来说并没有那么友好&…

安装pyrender和OSMesa

1&#xff09;安装 pyrender Pyrender是一个基于OpenGL的库&#xff0c;可以加载和渲染三维网格、点云、相机等对象3。 pip install pyrender 2&#xff09;理解PyOpenGL和OSMesa的关系是: PyOpenGL是Python的OpenGL绑定库&#xff08;接口壳子&#xff09;,它提供了在Python中…

代码部署到服务器

前言&#xff1a;相信看到这篇文章的小伙伴都或多或少有一些编程基础&#xff0c;懂得一些linux的基本命令了吧&#xff0c;本篇文章将带领大家服务器如何部署一个使用django框架开发的一个网站进行云服务器端的部署。 文章使用到的的工具 Python&#xff1a;一种编程语言&…

uniapp 企业微信侧边栏开发网页授权 注入企业权限 注入应用权限 获取userid(2)

1、网页授权&#xff0c;获取code 代码&#xff1a; oauthUrl() {const that thisuni.removeStorageSync(code)let REDIRECT_URI encodeURIComponent(window.location.href)let CORPID webConfig.appIdlet url https://open.weixin.qq.com/connect/oauth2/authorize?appi…

Flink-----Yarn应用模式作业提交流程

Yarn应用模式作业提交流程 在Yarn当中又分为Session&#xff0c;PerJob&#xff0c;Application&#xff0c;建议和推荐使用独立集群的&#xff0c;其中就包含PerJob 和Application&#xff0c;但是1.17版本的Flink已将PerJob标记为过时&#xff0c;并且Application可以解决Pe…

AI绘画之三_StableDiffusion_界面操作

1 介绍 首先&#xff0c;介绍界面中的重要元素&#xff0c;如图所示&#xff1a; 基础模型&#xff1a;基础模型是最重要的设置项文生图&#xff1a;选项卡列出了各大功能&#xff0c;文生图指通过文字生成图片图生图&#xff1a;图生图指通过图片和文字生成图片修复照片&am…

sql类型-用户定义表类型

一、创建用户定义表类型String_Table_Type CREATE TYPE String_Table_Type AS TABLE ( Id nvarchar(200) NOT NULL ) GO DECLARE test String_Table_Type INSERT INTO test VALUES(a),(b),(c) SELECT * FROM test 二、SqlSugar中使用

【IMX6ULL驱动开发学习】06.DHT11温湿度传感器驱动程序编写与测试

一、DHT11简介 DHT11是一款可测量温度和湿度的传感器。比如市面上一些空气加湿器&#xff0c;会测量空气中湿度&#xff0c;再根据测量结果决定是否继续加湿。 DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器&#xff0c;具有超小体积、极低功耗的特点…

银行客户关系管理系统springboot财务金融进销存java jsp源代码

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 银行客户关系管理系统springboot 系统有1权限&#x…