Vue+leaflet笔记之克里金插值

news2024/11/17 5:55:10

Vue+leaflet笔记之克里金插值

文章目录

  • Vue+leaflet笔记之克里金插值
    • 开发环境
    • 代码简介
      • 组件库简介
      • 安装依赖库
      • 实现思路
        • turf生成随机数据
        • 方法一:kriging库插值
        • 方法二:kriging-contour插值(矢量)
        • 方法三:kriging-contour插值(栅格)

本文介绍了Web端使用 Leaflet开发库进行克里金插值的三种方法 (底图来源:天地图),分别结合了kriging、kriging-contour组件库实现克里金插值功能,效果如下图所示。


开发环境

Vue开发库:3.2.37 & Leaflet开发库:1.9.3

Leaflet主要插件:turfkriging.jskriging-contour


代码简介

组件库简介

kriging.js是一个开源的克里金插值算法组件库,核心方法如下:

// 使用gaussian、exponential或spherical模型对数据集进行训练,返回的是一个variogram对象;
kriging.train(t, x, y, model, sigma2, alpha)
// 使用variogram对象使polygons范围描述的地理位置内的格网元素具备不一样的预测值,width是插值格点精度大小
kriging.grid(polygons,variogram,width)
// 将得到的格网grid渲染至canvas上。
kriging.plot(canvas,grid,xlim,ylim,colors): 

仓库地址 https://github.com/sakitam-gis/kriging.js

kriging-contour组件库是一个基于克里金插值算法,根据离散点位置及其权重,生成等值面矢量数据(GeoJSON格式)和栅格数据(Canvas绘制图片),这些数据在任何WebGIS客户端上都可通用展示。

仓库地址 https://github.com/FreeGIS/kriging-contour

安装依赖库

# 安装克里金插值所需的插件
npm i @turf/turf
# 方法一
npm i @sakitam-gis/kriging
# 方法二
npm i kriging-contour

# 引入kriging.js
import kriging from '@sakitam-gis/kriging';
# 引入kriging-contour
import { getVectorContour, drawCanvasContour } from 'kriging-contour/dist/kriging-contour.js'

实现思路

首先划定一个区域,利用turfJS随机一部分数据(也可使用真实点状数据集),然后插件渲染空间插值至canvas或生成面状geojson,然后添加到地图容器中进行展示。

turf生成随机数据

// 随机点的边界(折线的最大包围盒坐标)
const boundaries = turf.lineString([[110, 32], [118, 40], [120, 35]]);
// 随机50个点状要素数据
let positionData = turf.randomPoint(50, { bbox: turf.bbox(boundaries) });
// 再生成些随机数做属性
turf.featureEach(positionData, function (currentFeature, featureIndex) {
    currentFeature.properties = { value: (Math.random() * 100).toFixed(2) };
});

方法一:kriging库插值

使用体验:在大量数据进行插值时,处理速度较慢;色带颜色如果较少,格网间颜色差异较大;插值的范围要按照特定的格式填入,否则无法加载。

  • 核心代码
  • 效果预览

方法二:kriging-contour插值(矢量)

使用体验:插值效果较为平滑;可以对插值效果进行裁剪,仅保留研究区的范围;颜色样式定制更方便一些。

  • 核心代码
  • 效果预览

方法三:kriging-contour插值(栅格)

使用体验:相比kriging库使用起来更简单,需要设置的参数更少,更容易上手;海量数据插值时,处理速度较慢;

  • 核心代码
  • 效果预览
## 详细源码
<template>
  <div class="app-contain">
    <!-- leaflet 地图容器 -->
    <canvas id="canvasMap" style="display: none;"></canvas>
    <div id="myMap"></div>
    <div class="controls">
      <el-button color="#626aef" @click="startKriging('kriging')">普通克里金</el-button>
      <el-button color="#626aef" @click="startKriging('Vector')">克里金矢量</el-button>
      <el-button color="#626aef" @click="startKriging('Image')">克里金图像</el-button>
      <el-button color="#626aef" @click="clearKriging()">清空</el-button>
    </div>
  </div>
</template>

<script setup>
// 引入样式
import L from 'leaflet';
import 'leaflet/dist/leaflet.css'
// 引入turf
import * as turf from '@turf/turf'
// 引入kriging.js
import kriging from '@sakitam-gis/kriging';
// 引入kriging-contour
import { getVectorContour, drawCanvasContour } from 'kriging-contour/dist/kriging-contour.js'
// VUE组件
import { onMounted, reactive, ref } from "vue"
// 天地图TK
let tdtKey = 'YOURS_TK'
let map = null;
let featureLayerGroup = null;
let imageLayerGroup = null;
const initMap = () => {
  // 矢量地图
  const tiandituMap = new L.TileLayer(`http://t0.tianditu.gov.cn/cva_c/wmts?layer=cva&style=default&tilematrixset=c&Service=WMTS&Request=GetTile&Version=1.0.0&Format=tiles&TileMatrix={z}&TileCol={x}&TileRow={y}&tk=${tdtKey}`,
    {
      tileSize: 512,
      noWrap: true,
      bounds: [[-90, -180], [90, 180]]
    })
  // 文字注记
  const tiandituText = new L.TileLayer(`http://t0.tianditu.com/vec_c/wmts?layer=vec&style=default&tilematrixset=c&Service=WMTS&Request=GetTile&Version=1.0.0&Format=tiles&TileMatrix={z}&TileCol={x}&TileRow={y}&tk=${tdtKey}`,
    {
      tileSize: 512,
      noWrap: true,
      bounds: [[-90, -180], [90, 180]]
    })
  const layers = L.layerGroup([tiandituText, tiandituMap])
  map = L.map('myMap', {  //需绑定地图容器div的id
    center: [39.56, 116.20], //初始地图中心
    crs: L.CRS.EPSG4326,
    zoom: 5, //初始缩放等级
    maxZoom: 18, //最大缩放等级
    minZoom: 0, //最小缩放等级
    zoomControl: true, //缩放组件
    attributionControl: false, //去掉右下角logol
    scrollWheelZoom: true, //默认开启鼠标滚轮缩放
    // 限制显示地理范围
    maxBounds: L.latLngBounds(L.latLng(-90, -180), L.latLng(90, 180)),
    layers: [layers] // 图层
  })
  // 矢量图层组
  featureLayerGroup = new L.FeatureGroup().addTo(map).bringToFront()
  // 图像图层组
  imageLayerGroup = new L.FeatureGroup().addTo(map).bringToFront()
}

const startKriging = (krigingType) => {
  // 随机点的边界(折线的最大包围盒坐标)
  const boundaries = turf.lineString([[110, 32], [118, 40], [120, 35]]);
  // 随机50个点状要素数据
  let positionData = turf.randomPoint(50, { bbox: turf.bbox(boundaries) });
  // 再生成些随机数做属性
  turf.featureEach(positionData, function (currentFeature, featureIndex) {
    currentFeature.properties = { value: (Math.random() * 100).toFixed(2) };
  });
  if ('Vector' == krigingType) {
    showKrigingVector(boundaries, positionData);
  } else if ('Image' == krigingType) {
    showKrigingImage(boundaries, positionData)
  } else if ('kriging' == krigingType) {
    showKriging(boundaries, positionData)
  }
}

const showKriging = (boundaries, positionData) => {
  // 清空图层
  clearKriging();
  // 完全透明
  let scope = L.geoJSON(boundaries, {
    style: function () {
      return {
        fillColor: '6666ff',
        color: 'red',
        weight: 2,
        opacity: 0,
        fillOpacity: 0,
      };
    }
  }).addTo(imageLayerGroup);

  map.fitBounds(scope.getBounds());
  //根据scope边界线,生成范围信息
  let xlim = [scope.getBounds()._southWest.lng, scope.getBounds()._northEast.lng];
  let ylim = [scope.getBounds()._southWest.lat, scope.getBounds()._northEast.lat];

  function loadkriging(points) {
    let canvas = document.getElementById("canvasMap");
    canvas.width = 2000;
    canvas.height = 1000;
    // 数量
    let pointLength = points.features.length;
    let t = [];// 数值
    let x = [];// 经度
    let y = [];// 纬度
    // 加载点数过多的话,会出现卡顿
    for (let i = 0; i < pointLength; i++) {
      x.push(points.features[i].geometry.coordinates[0]);
      y.push(points.features[i].geometry.coordinates[1]);
      t.push(points.features[i].properties.value);
      // 将插值点展示到地图中,并添加提示文字(可删除,非核心代码)
      L.circle([y[i], x[i]], { radius: 1 })
        .addTo(imageLayerGroup)
        .bindTooltip(points.features[i].properties.value, {
          permanent: true, //是永久打开还是悬停打开
          direction: 'top' //方向
        }).openTooltip();
    }

    // 克里金插值参数
    const params = {
      krigingModel: 'exponential',//model还可选'gaussian','spherical'
      krigingSigma2: 0,
      krigingAlpha: 100,
      canvasAlpha: 0.8,//canvas图层透明度-0.75
      colors: ["#00A600", "#01A600", "#03A700", "#04A700", "#05A800", "#07A800", "#08A900", "#09A900", "#0BAA00", "#0CAA00", "#0DAB00", "#0FAB00", "#10AC00", "#12AC00", "#13AD00", "#14AD00", "#16AE00", "#17AE00", "#19AF00", "#1AAF00", "#1CB000", "#1DB000", "#1FB100", "#20B100", "#22B200", "#23B200", "#25B300", "#26B300", "#28B400", "#29B400", "#2BB500", "#2CB500", "#2EB600", "#2FB600", "#31B700", "#33B700", "#34B800", "#36B800", "#37B900", "#39B900", "#3BBA00", "#3CBA00", "#3EBB00", "#3FBB00", "#41BC00", "#43BC00", "#44BD00", "#46BD00", "#48BE00", "#49BE00", "#4BBF00", "#4DBF00", "#4FC000", "#50C000", "#52C100", "#54C100", "#55C200", "#57C200", "#59C300", "#5BC300", "#5DC400", "#5EC400", "#60C500", "#62C500", "#64C600", "#66C600", "#67C700", "#69C700", "#6BC800", "#6DC800", "#6FC900", "#71C900", "#72CA00", "#74CA00", "#76CB00", "#78CB00", "#7ACC00", "#7CCC00", "#7ECD00", "#80CD00", "#82CE00", "#84CE00", "#86CF00", "#88CF00", "#8AD000", "#8BD000", "#8DD100", "#8FD100", "#91D200", "#93D200", "#95D300", "#97D300", "#9AD400", "#9CD400", "#9ED500", "#A0D500", "#A2D600", "#A4D600", "#A6D700", "#A8D700", "#AAD800", "#ACD800", "#AED900", "#B0D900", "#B2DA00", "#B5DA00", "#B7DB00", "#B9DB00", "#BBDC00", "#BDDC00", "#BFDD00", "#C2DD00", "#C4DE00", "#C6DE00", "#C8DF00", "#CADF00", "#CDE000", "#CFE000", "#D1E100", "#D3E100", "#D6E200", "#D8E200", "#DAE300", "#DCE300", "#DFE400", "#E1E400", "#E3E500", "#E6E600", "#E6E402", "#E6E204", "#E6E105", "#E6DF07", "#E6DD09", "#E6DC0B", "#E6DA0D", "#E6D90E", "#E6D710", "#E6D612", "#E7D414", "#E7D316", "#E7D217", "#E7D019", "#E7CF1B", "#E7CE1D", "#E7CD1F", "#E7CB21", "#E7CA22", "#E7C924", "#E8C826", "#E8C728", "#E8C62A", "#E8C52B", "#E8C42D", "#E8C32F", "#E8C231", "#E8C133", "#E8C035", "#E8BF36", "#E9BE38", "#E9BD3A", "#E9BC3C", "#E9BB3E", "#E9BB40", "#E9BA42", "#E9B943", "#E9B945", "#E9B847", "#E9B749", "#EAB74B", "#EAB64D", "#EAB64F", "#EAB550", "#EAB552", "#EAB454", "#EAB456", "#EAB358", "#EAB35A", "#EAB35C", "#EBB25D", "#EBB25F", "#EBB261", "#EBB263", "#EBB165", "#EBB167", "#EBB169", "#EBB16B", "#EBB16C", "#EBB16E", "#ECB170", "#ECB172", "#ECB174", "#ECB176", "#ECB178", "#ECB17A", "#ECB17C", "#ECB17E", "#ECB27F", "#ECB281", "#EDB283", "#EDB285", "#EDB387", "#EDB389", "#EDB38B", "#EDB48D", "#EDB48F", "#EDB591", "#EDB593", "#EDB694", "#EEB696", "#EEB798", "#EEB89A", "#EEB89C", "#EEB99E", "#EEBAA0", "#EEBAA2", "#EEBBA4", "#EEBCA6", "#EEBDA8", "#EFBEAA", "#EFBEAC", "#EFBFAD", "#EFC0AF", "#EFC1B1", "#EFC2B3", "#EFC3B5", "#EFC4B7", "#EFC5B9", "#EFC7BB", "#F0C8BD", "#F0C9BF", "#F0CAC1", "#F0CBC3", "#F0CDC5", "#F0CEC7", "#F0CFC9", "#F0D1CB", "#F0D2CD", "#F0D3CF", "#F1D5D1", "#F1D6D3", "#F1D8D5", "#F1D9D7", "#F1DBD8", "#F1DDDA", "#F1DEDC", "#F1E0DE", "#F1E2E0", "#F1E3E2", "#F2E5E4", "#F2E7E6", "#F2E9E8", "#F2EBEA", "#F2ECEC", "#F2EEEE", "#F2F0F0", "#F2F2F2"
      ]
    }
    // 对数据集进行训练
    let variogram = kriging.train(t, x, y, params.krigingModel, params.krigingSigma2, params.krigingAlpha);
    // 将插值范围封装成特定格式
    let bbox = turf.bbox(boundaries); // 外包矩形范围
    // 根据外包矩形范围生成外包矩形面Polygon
    let bboxPolygon = turf.bboxPolygon(bbox);
    let positions = [];
    bboxPolygon.geometry.coordinates[0].forEach((v) => {
      positions.push([v[0], v[1]])
    })
    // 将边界封装成特定的格式
    let range = [positions]
    // 使用variogram对象使polygons描述的地理位置内的格网元素具备不一样的预测值,最后一个参数,是插值格点精度大小
    let grid = kriging.grid(range, variogram, 0.05);
    // 将得到的格网grid渲染至canvas上
    kriging.plot(canvas, grid, [xlim[0], xlim[1]], [ylim[0], ylim[1]], params.colors);
  }

  //将canvas对象转换成image的URL
  function returnImgae() {
    let mycanvas = document.getElementById("canvasMap");
    return mycanvas.toDataURL("image/png");
  }

  // 执行克里金插值函数
  loadkriging(positionData);

  let imageBounds = [[ylim[0], xlim[0]], [ylim[1], xlim[1]]];
  L.imageOverlay(returnImgae(), imageBounds, { opacity: 0.8 }).addTo(imageLayerGroup);
}

// 生成矢量等值面并渲染
const showKrigingVector = (boundaries, positionData) => {
  // 清空图层
  clearKriging();
  // 展点(可删除)
  L.geoJSON(positionData, {
    pointToLayer: function (feature, latlng) {
      return L.circleMarker(latlng, {
        radius: 5,
        fillColor: '#6666ff',
        fillOpacity: 1,
        color: "#fff",
        weight: 2,
      });
    }, onEachFeature(feature, layer) {
      // 显示文字
      let content = feature.properties.value
      // marker的icon文字
      let myIcon = L.divIcon({
        html: `<div style="white-space: nowrap;color:#6666ff;">${content}</div>`,
        iconAnchor: [0, 0],
        className: 'my-div-icon',
        iconSize: 120
      });
      let featureCenter = L.latLng(feature.geometry.coordinates[1], feature.geometry.coordinates[0]);
      featureLayerGroup.addLayer(L.marker(featureCenter, { icon: myIcon }));
    }
  }).addTo(featureLayerGroup)
  // 颜色色带
  let colors = [{ fill: "#ffdc84" }, { fill: "#ffd782" }, 
    { fill: "#ffd281" }, { fill: "#ffcd7f" }, { fill: "#ffc87e" },  { fill: "#ffc37c" },     { fill: "#ffbe7a" }, {fill: "#ffb979"}, {fill: "#feb477"},{fill: "#feaf76"}, 
    {fill: "#feaa74"}, {fill: "#fea573"}, {fill: "#fea071"}, {fill: "#fe9b6f"}, 
    {fill: "#fe966e"}, {fill: "#fe906c"}, {fill: "#fe8b6b"}, {fill: "#fe8669"}, 
    {fill: "#fe8167"}, {fill: "#fe7c66"}, {fill: "#fe7764"}, {fill: "#fe7263"}, 
    {fill: "#fd6d61"}, {fill: "#fd6860"}, {fill: "#fd635e"}, {fill: "#fd5e5c"}, 
    {fill: "#fd595b"}, {fill: "#fd5459"}, {fill: "#fd4f58"}, {fill: "#fd4a56"}]
  // 等级分级
  let levelV = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220, 250, 260, 270, 280, 290, 300, 400];
  let kriging_contours = getVectorContour(positionData, 'value', {
    model: 'exponential',
    sigma2: 0,
    alpha: 100
  }, levelV, boundaries);
  // 展示生成的矢量等值面
  L.geoJSON(kriging_contours, {
    style: function (feature) {
      return {
        fillColor: hotColor(feature.properties.value),
        weight: 0,
        fillOpacity: 0.3,
      };
    }
  }).addTo(featureLayerGroup);
  // 根据值来配色
  function hotColor(d) {
    let index = levelV.findIndex((item) => item >= d);
    if (index > -1) {
      return colors[index].fill
    } else {
      return colors[colors.length - 1].fill
    }
  }
}

// 生成图像等值面并渲染
const showKrigingImage = (boundaries, positionData) => {
  // 清空图层
  clearKriging();
  // 完全透明
  let scope = L.geoJSON(boundaries, {
    style: function () {
      return {
        fillColor: '6666ff',
        color: 'red',
        weight: 2,
        opacity: 0,
        fillOpacity: 0,
      };
    }
  }).addTo(imageLayerGroup);
  map.fitBounds(scope.getBounds());
  //根据scope边界线,生成范围信息
  let xlim = [scope.getBounds()._southWest.lng, scope.getBounds()._northEast.lng];
  let ylim = [scope.getBounds()._southWest.lat, scope.getBounds()._northEast.lat];
  // 色带
  let colors = ["#006837", "#1a9850", "#66bd63", "#a6d96a", "#d9ef8b", "#ffffbf", "#fee08b", "#fdae61", "#f46d43", "#d73027", "#a50026"]
  // 画布
  let canvas = document.getElementById("canvasMap");
  canvas.width = 1000;
  canvas.height = 1000;
  let kriging_contours = drawCanvasContour(positionData, 'value', {
    model: 'exponential',
    sigma2: 0,
    alpha: 100
  }, canvas, [xlim[0], xlim[1]], [ylim[0], ylim[1]], colors);
  //将canvas对象转换成image的URL
  function returnImgae() {
    let mycanvas = document.getElementById("canvasMap");
    return mycanvas.toDataURL("image/png");
  }
  let imageBounds = [[ylim[0], xlim[0]], [ylim[1], xlim[1]]];
  L.imageOverlay(returnImgae(), imageBounds, { opacity: 0.9 }).addTo(imageLayerGroup);
}

// 清空图层
const clearKriging = () => {
  imageLayerGroup.clearLayers();
  featureLayerGroup.clearLayers();
}

onMounted(() => {
  initMap();
})
</script>

<style scoped>
#myMap {
  width: 96vw;
  height: 96vh;
}

.controls {
  position: absolute;
  top: 0px;
  left: 200px;
  padding: 15px;
  z-index: 1000;
}
</style>

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

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

相关文章

逆向工具(IDA、pyinstxtractor+uncompyle6、jadx等持续更新)

IDA Pro IDA Pro&#xff08;Interactive Disassembler Professional&#xff09;交互式反汇编器专业版&#xff0c;CTF、RE、PWN必备。 打开一个可执行文件前&#xff0c;应先用file命令或者DIE等工具&#xff0c;确定是32位还是64位&#xff0c;然后用相应的IDA工具打开可执…

ModaHub魔搭社区:商业向量数据库产品Pincone的特点与应用

目录 Pincone简介 Pincone有以下几个特点 高性能搜索 全功能管理 轻松扩容 Pincone能干什么&#xff1f; 如何接入Pincone Pincone简介 Pincone 可以算是当前最火的商业向量数据库产品了&#xff0c;它最近获得了1亿美元的B轮融资&#xff0c;估值达到7.5 亿美元&#x…

YOLOv8实战火焰和烟雾检测 (视频教程)

课程链接&#xff1a;https://edu.csdn.net/course/detail/38718 YOLOv8 基于先前 YOLO 版本在目标检测任务上的成功&#xff0c;进一步提升性能和灵活性。 本课程将手把手地教大家使用YOLOv8结合可变形卷积&#xff08;deformable convolution&#xff09;训练火焰和烟雾数…

TypeScript 【类型推断】与【类型别名】的使用解读

什么是类型推断&#xff1f; 在 TypeScript 中&#xff0c; 如果声明变量时&#xff0c;没有明确的指定类型&#xff0c;那么 TypeScript 会依照类型推论&#xff08;Type Inference&#xff09;的规则推断出一个类型。 以下代码虽然没有明确指定类型&#xff0c;但是会在编译的…

APK反编译的那些事

谷歌对dex文件的介绍&#xff1a;常量数组/字符串 DEX_FILE_MAGIC 是字节列表&#xff0c;这类字节必须出现在 .dex 文件的开头&#xff0c;以便系统将其原样识别。该值会特意包含一个换行符&#xff08;"\n" 或 0x0a&#xff09;和空字节&#xff08;"\0"…

单片机原理及接口技术期末复习知识点

第1章 单片机概述 什么是单片机&#xff1a;单片机是由CPU、存储器、I/O接口及总线集成在一个芯片上。简单了解AT89S51单片机简介。 相当于MCS-51系列中的87C51&#xff0c;AT89S51芯片内4KB的Flash存储取代了87C51片内的4K的EPROM。 第2章 AT89S51单片机的内部结构 MCS-51单…

毫米波雷达系统性能参数分析

毫米波雷达系统性能参数分析 1、距离2、速度3、角度 本文主要分析描述雷达系统的系统性能的一些参数&#xff0c;包括最大作用距离&#xff0c;距离分辨率&#xff0c;最大探测速度……等参数。通过理解这些参数的组成&#xff0c;能够帮助我们设计雷达系统参数。 1、距离 &a…

做UI设计要会什么知识?

做UI设计要会什么知识&#xff1f;在互联网这个行业里&#xff0c;要想做好一件事情&#xff0c;做得好是必须要懂产品&#xff0c;懂用户体验。在很多人眼中&#xff0c;做设计就是打杂&#xff0c;干不了&#xff0c;其实不是这样的。要想成为一名优秀的UI设计师&#xff0c;…

Django高级扩展之系统后台使用celery

如果我们在系统后台想某日某时执行某个任务&#xff0c;或者每隔一段时间执行某个任务&#xff0c;可以使用celery来完成。 目录 安装 安装celery 安装django_celery_beat celery配置 注册应用 celery配置 修改__init__.py 表迁移 执行迁移 控制台运行截图 新增数据…

gunicorn不停服重启更新服务

简介 Gunicorn是基于unix系统&#xff0c;被广泛应用的高性能的Python WSGI HTTP Server。用来解析HTTP请求的网关服务。 它通常是在进行反向代理&#xff08;如nginx&#xff09;&#xff0c;或者进行负载均衡&#xff08;如 AWS ELB&#xff09;和一个web 应用&#xff08;比…

AI + 算力 = “最强龙头”?

随着人工智能技术的飞速发展&#xff0c;“AI算力”的结合应用已成为科技行业的热点话题&#xff0c;甚至诞生出“AI算力最强龙头“的网络热门等式。该组合不仅可以提高计算效率&#xff0c;还可以为各行各业带来更强大的数据处理和分析能力&#xff0c;从而推动创新和增长。 …

Java项目-SpringBoot+Vue 的学生就业管理信息系统

&#x1f495;&#x1f495;作者&#xff1a;程序员徐师兄 个人简介&#xff1a;7 年大厂程序员经历&#xff0c;擅长Java、微信小程序、Python、Android等&#xff0c;大家有这一块的问题可以一起交流&#xff01; 各类成品java毕设 。javaweb&#xff0c;ssh&#xff0c;ssm&…

小航助学2023年6月GESP_C++三级试卷(含题库答题软件账号)

需要在线模拟训练的题库账号请点击 小航助学编程在线模拟试卷系统&#xff08;含题库答题软件账号&#xff09;_程序猿下山的博客-CSDN博客 单选题2.0分 删除编辑附件图文 答案:D 第1题高级语言编写的程序需要经过以下&#xff08; &#xff09;操作&#xff0c;可以生成在…

geo-tool 解析百度经纬出错 {‘status‘: 240, ‘message‘: ‘APP 服务被禁用‘}

geo-tool 解析百度经纬出错 {status: 240, message: APP 服务被禁用} 引子一、查错二、排错三、测试通过参考 作者&#xff1a;高玉涵 时间&#xff1a;2023.6.25 环境&#xff1a;Windows 10 专业版 22H2&#xff0c;Python 3.10.4 第三方包&#xff1a;geo-tool 1.1.2 引…

【模拟CMOS集成电路】HSPICE入门仿真分析实例

【模拟CMOS集成电路】HSPICE入门仿真分析实例 一、采用HSPICE的MOS器件仿真二、INV倒相器HSPICE仿真附录程序源码&#xff08;一&#xff09;程序源码&#xff08;二&#xff09; 一、采用HSPICE的MOS器件仿真 一、采用HSPICE的MOS器件仿真, 并回答以下问题。   1&#xff0…

Visual Studio 2019使用详解

VS2019&#xff08;Visual Studio 2019&#xff09;是由微软开发的集成开发环境&#xff08;IDE&#xff09;&#xff0c;用于开发各种应用程序&#xff0c;包括桌面应用程序、Web应用程序、移动应用程序等。 对工具的熟悉程度有助于提升开发效率&#xff0c;磨刀不误砍柴功&am…

solr快速上手:整合spring-data-solr实现客户端操作(十)

0. 引言 前一章介绍了官方的solr客户端SolrJ&#xff0c;但是solrJ的使用相对来说并不方便&#xff0c;仍然需要做一些负责的客户端操作以及语句的书写&#xff0c;有没有更加方便的ORM框架呢&#xff0c;这就提到了spring-data-solr了 1. 简介 首先如果你还不知道spring-da…

面试题:深拷贝和浅拷贝(+内存图)

深拷贝和浅拷贝主要是针对对象的属性是对象&#xff08;引用类型&#xff09; 一、基本类型和引用类型的区别 1&#xff09;、基本类型&#xff1a;就是值类型&#xff0c;即在变量所对应的内存区域存储的是值。 2&#xff09;、引用类型&#xff1a;就是地址类型。 何为地…

Kubeadm 部署k8s实现并且演示滚动不停服务更新

1. 环境准备 在开始之前&#xff0c;部署Kubernetes集群机器需要满足以下几个条件&#xff1a; 一台或多台机器&#xff0c;操作系统 CentOS7.x-86_x64&#xff1b;硬件配置&#xff1a;2GB或更多RAM&#xff0c;2个CPU或更多CPU&#xff0c;硬盘30GB或更多&#xff1b;集群中…

【Activiti】原理

一、核心类 RepositoryService&#xff1a;部署管理流程资源&#xff0c;如bpmn文件、附件等等&#xff1b;RuntimeService&#xff1a;操作运行时的流程&#xff1b;TaskService&#xff1a;流程中任务的信息&#xff1b;HistoryService&#xff1a;流程的历史信息&#xff1…