当前位置: 首页 > news >正文

JAVA代码 实现定位数据动态聚集并绘制多边形区域

文章目录

  • 思路
    • 1、限制聚合距离
    • 2、绘制多边形区域
    • 3、多边形区域之间合并
    • 4、多边形定边点
    • 4、逻辑流程
  • 一些性能上的优化
    • 1、多边形设置圆心
    • 2、采用分支合并思路
    • 3、清理聚集较分散区域
  • 合理性处理
    • 1、解决多边形内凹角问题
    • 2、解决定边点插入位置问题
    • 3、多边形区域扩展
    • 成果展示

最近有根据一堆离散的报警数据(内部包含经纬度 报警类型)需要聚合出每个报警发生的区域需求,比如 超速报警 聚集点有哪些,疲劳驾驶报警有哪些等等,个人没有采用已成型的算法 比如DBSCAN,而是自己实现
image-20230329170556207

思路

为了让聚合的区域更精确,以及聚合的区域过大,我们采取了如下措施

1、限制聚合距离

何为限制聚合距离呢,就是定位点与定位点间 或定位点与多边形区域之间设置距离限制,如果点与点 或点与多边形距离小于设置阈值,则点加入该区域,否则成都一个独立区域?

2、绘制多边形区域

为了避免区域内非聚集空白区过多,我们取消了圆形区域,决定基于聚集的点形成多边形区域

3、多边形区域之间合并

为什么多边形区域之间需要合并呢,随着区域的增多,可能一个点同时与多个多边形区域距离符合阈值需要加入,那此时,对应的多边形就需要合并在一起组成新的区域

4、多边形定边点

组成多边形我们就使用定位数据点,并按顺序存入,最后前端根据定位点顺序绘制出多边形(A>B>C) 那么前端就会基于 A>B B>C C>A 绘制出一个三角形区域

报警模型

/*** @author lei* @create 2023-02-27 15:51* @desc**/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Alarm {private Integer vehicleId;@ApiModelProperty("经度")private Integer longitude;@ApiModelProperty("纬度")private Integer latitude;private String pointName;private Integer alarmType;public Alarm(Integer vehicleId, Integer longitude, Integer latitude, String pointName) {this.vehicleId = vehicleId;this.longitude = longitude;this.latitude = latitude;this.pointName = pointName;}
}

4、逻辑流程

基于当前定位点循环当前所有的多边形区域,与区域元素进行判断,满足则加入(contine区域列表并记录已有区域)并与剩下区域列表中区域依次比对,不满足则新建区域,已有满足区域但还有匹配区域则两个区域进行合并

    private static boolean collectCalc(List<PolygonMapArea> polygonMapAreas, Alarm curAlarm, Double collectDistance) {// 是否需要初始化新多边形boolean needInitNewPolygon = true;PolygonMapArea belongedArea = null;MapPoint curPoint = new MapPoint(curAlarm.getLongitude(), curAlarm.getLatitude(), curAlarm.getPointName());for (PolygonMapArea polygonMapArea : polygonMapAreas) {if (!polygonMapArea.isLive()) {continue;}// 先算圆心到当前点距离是否超过指定阈值,超过则进行下一个多边形判断double distance = AreaUtil.distance(polygonMapArea.getCycleCenter(), curPoint);if (distance > polygonMapArea.getRadius() + collectDistance) {continue;}if (polygonMapArea.getPoints().getSize() == 1) {needInitNewPolygon = false;if (belongedArea == null) {// 归属当前聚集点,计算最大经纬度与圆心polygonMapArea.getAlarms().add(curAlarm);polygonDrawCircle(curPoint, polygonMapArea, distance);polygonMapArea.setBelong(true);belongedArea = polygonMapArea;} else {mergePolygonArea(belongedArea, polygonMapArea, collectDistance);}continue;}// 属于当前多边形扫描圆距离,则进行多边形内外部判断boolean inPolygonArea = AreaUtil.locateInPolygonArea(curPoint, polygonMapArea);if (inPolygonArea) {// 当前点在现多边形内needInitNewPolygon = false;if (belongedArea == null) {polygonMapArea.getAlarms().add(curAlarm);polygonMapArea.setBelong(true);belongedArea = polygonMapArea;} else {mergePolygonArea(belongedArea, polygonMapArea, collectDistance);}continue;}// 当前点在多边形之外,则与各边进行判断,找到与其相邻最近边,如距离小于指定阈值则加入多边形Pair<Pair<Node<MapPoint>, Node<MapPoint>>, Double> nearestEdge = getNearestEdge(curPoint, polygonMapArea.getPoints());if (nearestEdge == null) {log.warn("当前点:{}未找到最近边", curAlarm);continue;}Pair<Node<MapPoint>, Node<MapPoint>> nearestNode = nearestEdge.getKey();double nearestEdgeDistance = nearestEdge.getValue();if (nearestEdgeDistance <= collectDistance) {needInitNewPolygon = false;if (belongedArea == null) {polygonMapArea.getAlarms().add(curAlarm);if (nearestEdgeDistance > AreaUtil.ON_LINE_DISTANCE) {// 加入多边形并削内凹角tryRecalculationArea(polygonMapArea, nearestNode.getKey(), nearestNode.getValue(), curPoint);}polygonMapArea.setBelong(true);belongedArea = polygonMapArea;} else {mergePolygonArea(belongedArea, polygonMapArea, collectDistance);}}}return needInitNewPolygon;}

一些性能上的优化

1、多边形设置圆心

多边形圆心是由 多边形定边点数据中洗出来的 (最大经度,最大纬度) (最小经度最小纬度) 获取出的中心点

当判断点是否加入多边形时 先与圆心距离判断 (点与圆心点距离小于等于 圆半径+聚合距离是着可能需要加入,如大于着必不可能加入该多边形)

2、采用分支合并思路

区域列表循环采用分支合并思路,基于当前机器核心线程数拆分现有区域列表,异步计算最后合并汇总数据

 /*** 获取对应报警类型计算线程池** @param alarm* @return ThreadPoolExecutor* @author lei* @date 2023-03-27 11:06:57*/private static ThreadPoolExecutor getCalcExecutor(Alarm alarm) {return ALARM_TYPE_EXECUTOR_MAP.computeIfAbsent(alarm.getAlarmType(), alarmType -> {alarmType = Optional.ofNullable(alarmType).orElse(0);ThreadPoolExecutor executor = new ThreadPoolExecutor(CORE, CORE, 10, TimeUnit.MINUTES,new ArrayBlockingQueue<>(1024), new ThreadFactoryBuilder().setNameFormat(alarmType + "-calc-%d").setUncaughtExceptionHandler((t, e) -> log.error("线程:{}处理异常", t.getName(), e)).build(), new ThreadPoolExecutor.CallerRunsPolicy());log.debug("初始化报警类型:{}计算线程池!", alarmType);return executor;});}/*** 加入多边形计算** @param polygonMapAreas 现有聚集区* @param curAlarm        当前报警* @param collectDistance 聚集距离* @param calcIncr        累计计算量* @param incrId* @return void* @author lei* @date 2023-03-08 11:24:30*/private static void forkJoinPolygonArea(List<PolygonMapArea> polygonMapAreas, Alarm curAlarm, Double collectDistance,AtomicLong calcIncr, AtomicLong incrId) {long calcNum = calcIncr.incrementAndGet();if (CollUtil.isEmpty(polygonMapAreas)) {initPolygonArea(curAlarm, polygonMapAreas, incrId);return;}boolean needInitNewPolygon;List<List<PolygonMapArea>> splitAreaList = splitPolygonArea(polygonMapAreas);int splitAreaSize = splitAreaList.size();if (splitAreaSize > 1) {// 与各个子分支区域列表计算ThreadPoolExecutor calcExecutor = getCalcExecutor(curAlarm);List<CompletableFuture<Boolean>> collect = splitAreaList.stream().map(areas ->CompletableFuture.supplyAsync(() -> collectCalc(areas, curAlarm, collectDistance), calcExecutor)).collect(toList());List<Boolean> forkResultList = collect.stream().map(CompletableFuture::join).collect(toList());// 分支结果全真为真,非全真则再次合并needInitNewPolygon = splitAreaSize == forkResultList.stream().filter(x -> x).count();if (!needInitNewPolygon) {forkMergePolygonArea(polygonMapAreas, collectDistance);}} else {needInitNewPolygon = collectCalc(polygonMapAreas, curAlarm, collectDistance);}if (needInitNewPolygon) {initPolygonArea(curAlarm, polygonMapAreas, incrId);}// 清理较为离散的区域cleanDispersedArea(polygonMapAreas, calcNum);}/*** 合并线程子分支区域计算结果** @return List<PolygonMapArea> 返回分支合并后的区域列表,此时的区域列表为当前定位点计算后的最新结果* @author lei* @date 2023-03-27 15:46:26*/private static void forkMergePolygonArea(List<PolygonMapArea> polygonMapAreas, Double collectDistance) {PolygonMapArea belongArea = null;for (PolygonMapArea polygonMapArea : polygonMapAreas) {if (polygonMapArea.isBelong() && polygonMapArea.isLive()) {if (belongArea == null) {belongArea = polygonMapArea;} else {mergePolygonArea(belongArea, polygonMapArea, collectDistance);}}}}

3、清理聚集较分散区域

我们采取了定量清理区域逻辑思路,比如计算了20000个定位点清理一部分区域(区域一个点),区域数量达到10000个时清理区域内小于三个点的数据

合理性处理

1、解决多边形内凹角问题

由于每个定位点都有可能成为组成多边形区域的点,故此有可能组成的多边形是弯弯曲曲的畸形,比如像手,像魔爪等等,不是一个外凸的多边形

我们期望减少内凹角,使其成为一个更加饱满的多边形区域,比如下图

image-20230329193211239

使用jts依赖库

 compile 'org.locationtech.jts:jts-core:1.19.0'

核心思路是拿需消除内凹角的多边形所有定边点,使用jts依赖库绘制图形然后获取凸包,然后过滤出多边形定边点 不在凸包列表的数据

// 转换多边形定边点数据
Coordinate[] coordinates = points.getList().stream().map(x -> {Coordinate coordinate = new Coordinate(x.getLongitude(), x.getLatitude());return coordinate;}).toArray(Coordinate[]::new);
// 计算凸包
ConvexHull convexHull = new ConvexHull(coordinates, new GeometryFactory());
Geometry geometry = convexHull.getConvexHull();
Set<Coordinate> after = Arrays.stream(geometry.getCoordinates()).collect(Collectors.toSet());
// 踢出多边形定边点中不在Set集合中的数据

2、解决定边点插入位置问题

当新的定位点时要成为组成多边形定边点的时候会面临一个问题,这个点要插入哪里呢(插入顺序)?因为一旦位置选错了后,绘制成的多边形地图就会交叉

比如下图的多边形

image-20230329194503157

先分析上图问题产生原因

1、最开始 是 2 3 4组成三角区域,5点到来时,需要先判断该点与多边形哪一边更近(答案很显然,与 3 4 更近)于是加入了 3 后 成为新多边形 2 3 5 4

6点到来,则需要与多边形 2 3 5 4判断最近边,但此时其与 3 5 54 边距离是相等的,由于我逻辑的不完整性,选错了边,选了3 5 边,绘制最终多边形 2 3 6 5 4,导致多边形交叉

如何解决选错边的问题?如何选择插入的边?

思考了很久,我们可以将要插入的点与最近两个边夹角大小来判断,即上图的 3 5 6 与 4 5 6两个夹角的大小来判断,插入夹角较小的那一边。

35 54 一个最近边的结束 也是另一个最近边的开始

但还特别需要注意的是 多边形的组成顺序并不一定都是我上图的 2 3 5…这样顺时针(多边形从右边开始绘制)组成的,也可能多边形是逆时针绘制组成出来的(多边形从左边开始生成绘制)

抛除6点,我们假设上图多边形是从左边绘制的,并且 6点不是与 35 54最近,而是与 24 32 最近,那么此时会发现,相邻的两个边,一个最近边的结束不是另一个最近边的开始 这个时候我们夹角度数就要修改为 4 2 6 与 3 2 6,这样计算夹角才对

那么我们如何确定顺时针与逆时针呢?我们只需要判断第二个最近边的开始是不是第一边的结束即可

    /*** 根据当前点 获取与当前多边形最近边** @param curPoint 当前点* @param points   当前多边形组合点* @return Pair<Pair < Node < MapPoint>,Node<MapPoint>>,Double> 最近边组成点 当前点与最近边距离* @author lei* @date 2023-03-02 15:45:18*/private static Pair<Pair<Node<MapPoint>, Node<MapPoint>>, Double> getNearestEdge(MapPoint curPoint, LinkList<MapPoint> points) {Node<MapPoint> foreachNode = points.getFirst();Double nearestEdgeDistance = null;List<Pair<Pair<Node<MapPoint>, Node<MapPoint>>, Double>> pairList = new ArrayList<>();for (int i = 0; i < points.getSize(); i++) {Node<MapPoint> endPoint = foreachNode.getNext();double curDistance = AreaUtil.pointToLine(foreachNode.getData(), endPoint.getData(), curPoint);if (nearestEdgeDistance == null || nearestEdgeDistance >= curDistance) {nearestEdgeDistance = curDistance;Pair<Pair<Node<MapPoint>, Node<MapPoint>>, Double> nearestEdge = new Pair<>(Pair.of(foreachNode, foreachNode.getNext()), curDistance);pairList.add(nearestEdge);}foreachNode = endPoint;}Map<Double, List<Pair<Pair<Node<MapPoint>, Node<MapPoint>>, Double>>> map = pairList.stream().collect(Collectors.groupingBy(Pair::getValue));List<Pair<Pair<Node<MapPoint>, Node<MapPoint>>, Double>> nearestEdgeList = map.get(nearestEdgeDistance);// 特殊情况会出现当前点d与多边形两个边 (顺时针查找ab bc、或逆时针查找 ab ca)距离相同情况,因此做特殊处理,返回其夹角度数最小所在的那一边if (points.getSize() >= 3 && nearestEdgeList.size() == 2) {// 边1Pair<Pair<Node<MapPoint>, Node<MapPoint>>, Double> nearestEdgeOne = nearestEdgeList.get(0);Pair<Node<MapPoint>, Node<MapPoint>> edgeOne = nearestEdgeOne.getKey();Node<MapPoint> edgeOneStart = edgeOne.getKey();Node<MapPoint> edgeOneEnd = edgeOne.getValue();// 边2Pair<Pair<Node<MapPoint>, Node<MapPoint>>, Double> nearestEdgeTwo = nearestEdgeList.get(1);Pair<Node<MapPoint>, Node<MapPoint>> edgeTwo = nearestEdgeTwo.getKey();Node<MapPoint> edgeTwoStart = edgeTwo.getKey();Node<MapPoint> edgeTwoEnd = edgeTwo.getValue();double cosValue1;double cosValue2;// 顺时针相邻if (edgeTwoStart.equals(edgeOneEnd)) {// 求 边1 开始 结束 当前点组成夹角余弦 (a b d)cosValue1 = AreaUtil.cosValue(edgeOneStart.getData(), edgeOneEnd.getData(), curPoint);// 求 边2 结束 开始 当前点组成夹角余弦  (c b d)cosValue2 = AreaUtil.cosValue(edgeTwoEnd.getData(), edgeTwoStart.getData(), curPoint);} else {// a b c a// 求 边1 结束 开始 当前点组成夹角余弦 (b a d)cosValue1 = AreaUtil.cosValue(edgeOneEnd.getData(), edgeOneStart.getData(), curPoint);// 求 边2 开始 结束 当前点组成夹角余弦  (c a d)cosValue2 = AreaUtil.cosValue(edgeTwoStart.getData(), edgeTwoEnd.getData(), curPoint);}// 返回小夹角所在边,如夹角一致则交由下一步消内凹逻辑return cosValue1 >= cosValue2 ? nearestEdgeOne : nearestEdgeTwo;}return nearestEdgeList.get(0);}

3、多边形区域扩展

我们生成了某一类型报警的 N个聚集区域后,当其他车辆快要经过这里时我们怎么提前预警呢?

1、基于现在车辆定位点计算其与报警聚集区距离,小于等于阈值则报警

此方案可行,但是如果车辆速度过快(且我们的车辆定位是30s传一条)且聚集区比较小的话可能还没起到提示作用就已经过了该聚集区了

2、在原有多边形区域基础之上,向外扩展指定阈值,当车辆在记录扩展后的区域达到阈值或在进入到扩展后的区域时触发提醒

我们最终选择了方案二

那么多边形区域如何扩展呢?

使用jts依赖库

 compile 'org.locationtech.jts:jts-core:1.19.0'

我们将原多边形区域定边点使用jts依赖库组成几何图形,并设置外扩,我们拿到外扩后的几何图形凸包即可

/*** 多边形区域扩展** @param points         定位点* @param extendDistance 外扩距离 m* @return List<MapPoint>* @author lei* @date 2023-03-21 16:19:30*/
public static List<MapPoint> extendPoints(List<MapPoint> points, double extendDistance) {List<MapPoint> extendsPoints = points;if (extendDistance > 1 && points.size() >= NEED_EXTEND_SIZE) {Coordinate[] coordinates = points.stream().map(point -> new Coordinate(point.getLongitude(), point.getLatitude())).toArray(Coordinate[]::new);ConvexHull convexHull = new ConvexHull(coordinates, new GeometryFactory());Geometry polygon = convexHull.getConvexHull();// 每个圆弧的线段数,值越夹角越平滑,int quadrantSegments = 1;// 端点类型int endCapStyle = BufferParameters.CAP_SQUARE;// 连接类型int joinStyle = BufferParameters.JOIN_MITRE;// 指定斜接连接的斜率限制 当两个线段夹角很小时,斜接点锐角非常尖锐; 避免锐化可限制斜接点的斜率,当斜率超过指定阈值将强使用JOIN_BEVELdouble mitreLimit = 5.0;BufferParameters bufferParams = new BufferParameters(quadrantSegments, endCapStyle, joinStyle, mitreLimit);bufferParams.setSingleSided(true);// 向外扩展区域Geometry expandedPolygon = BufferOp.bufferOp(polygon, extendDistance * 10, bufferParams);Coordinate[] extendArray = expandedPolygon.convexHull().getCoordinates();extendsPoints = Arrays.stream(extendArray).map(x -> new MapPoint((int) x.x, (int) x.y)).distinct().collect(Collectors.toList());}return extendsPoints;
}

image-20230329201521732

成果展示

image-20230329202203117

image-20230329170556207

image-20230329170526505

image-20230329170454613

image-20230329170739492

相关文章:

JAVA代码 实现定位数据动态聚集并绘制多边形区域

文章目录思路1、限制聚合距离2、绘制多边形区域3、多边形区域之间合并4、多边形定边点4、逻辑流程一些性能上的优化1、多边形设置圆心2、采用分支合并思路3、清理聚集较分散区域合理性处理1、解决多边形内凹角问题2、解决定边点插入位置问题3、多边形区域扩展成果展示最近有根据…...

基于储能进行调峰和频率调节研究【超线性增益的联合优化】(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

体验 Linux 的几个监控命令(htop、nmon、netdata)

体验 Linux 的几个监控命令htopnmonnetdatahtop 安装&#xff0c; sudo dnf install -y htop使用&#xff0c; htopnmon 安装&#xff0c; sudo dnf install -y nmon使用&#xff0c; nmon输入c&#xff0c; 输入C&#xff0c; 输入m&#xff0c; 输入n&#xff0c; 输入…...

NOC大赛2022NOC软件创意编程初赛图形化小低组(小学高年级组)

一、选择题 1.如果要控制所有角色一起朝舞台区右侧移动,下面哪个积太块是不需要的 2.要想让三个角色一起移动起来,下面哪个积木块没有作用 ? 3.小猴按照下面的程序前进,小猴最后一次前进了()步。 4.小可同学写了一个画笔程序画出花朵,但是运行后什么都看不到,不可…...

python进行股票收益率计算和风险控制的实现

股票收益率计算和风险控制的实现 在进行股票投资时&#xff0c;计算收益率和进行风险控制是非常重要的。本文将介绍一个与此相关的函数&#xff1a;radio_day_cal()。 radio_day_cal()函数 def radio_day_cal(last_day, sheet_name, df_dict, code_list, new_list):i 0days…...

自从有了这套近4000页的开发文档后,Java面试路上就像开了挂一样

Java是世界最流行的编程语言&#xff0c;也是国内大多数IT公司的主流语言。招聘网站上Java岗位众多&#xff0c;Java工程师似乎不愁找工作。但仔细一看就会发现&#xff0c;Java岗位的招聘薪酬天差地别&#xff0c;人才要求也是五花八门。而在Java工程师求职过程中&#xff0c;…...

Python文件操作

目录 一、文件操作介绍 二、文件的打开和关闭 三、文件的读写 四、文件文件夹相关操作 五、test 一、文件操作介绍 文件 : python中文件是对象 Liunx 文件 : 一切设备都可以看成是文件 磁盘文件 管道 网络Socket 文件属性: 读 写 执行权限 就是把一些存储存放起来&…...

036:cesium加载GPX文件,显示图形

第036个 点击查看专栏目录 本示例的目的是介绍如何在vue+cesium中加载GPX文件, 显示图形。 直接复制下面的 vue+cesium源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共83行)相关API参考:专栏目标示例效果 配置方式 1)查看基础设置:https:/…...

【AI探索】我问了ChatGPT几个终极问题

终于尝试了一把ChatGPT的强大之处&#xff0c;问了一下关心的几个问题&#xff1a; chatGPT现在在思考吗&#xff1f;有没有什么你感兴趣的问题&#xff1f; 你认为AI会对人类产生哪些方面的影响&#xff1f; 你对人类所涉及到的学科有了解吗&#xff1f;你认为在哪些方面与人类…...

Leetcode 优先队列详解

优先队列 优先队列&#xff08;Priority Queue&#xff09;&#xff1a;一种特殊的队列。在优先队列中&#xff0c;元素被赋予优先级&#xff0c;当访问队列元素时&#xff0c;具有最高优先级的元素最先删除 普通队列详解Leetcode 队列详解 优先队列与普通队列最大的不同点在于…...

通过两道一年级数学题反思自己

背景 做完这两道题我开始反思自己&#xff0c;到底是什么限制了我&#xff1f;是我自己&#xff1f;是曾经教导我的老师&#xff1f;还是我的父母&#xff1f; 是考试吗&#xff1f;还是什么&#xff1f; 提目 1、正方体个数问题 2、相碰可能性 过程 静态思维&#xff1a; …...

Pytorch :从零搭建一个神经网络

文章目录安装依赖从源码编译pytorchCXX_ABI问题数据集归一化Transforms搭建神经网络Components of a neural networknn.Flattennn.Linearnn.Sequentialnn.SoftmaxModel Parameters优化模型参数设置超参数添加优化循环添加 loss function优化过程完整实现模型的保存和加载安装 …...

【华为OD机试 2023最新 】 区块链文件转储系统(C++ 100%)

题目描述 区块链底层存储是一个链式文件系统,由顺序的N个文件组成,每个文件的大小不一,依次为F1,F2,…,Fn。随着时间的推移,所占存储会越来越大。 云平台考虑将区块链按文件转储到廉价的SATA盘,只有连续的区块链文件才能转储到SATA盘上,且转储的文件之和不能超过SATA盘…...

基于springcloud实现分布式架构网上商城演示【项目源码】分享

基于springcloud实现分布式架构网上商城演示摘要 首先,论文一开始便是清楚的论述了系统的研究内容。其次,剖析系统需求分析,弄明白“做什么”,分析包括业务分析和业务流程的分析以及用例分析,更进一步明确系统的需求。然后在明白了系统的需求基础上需要进一步地设计系统,主要包…...

【Qt】(自制类)适用于QTextCharFormat的字体选择对话框

先附上github链接&#xff1a;https://github.com/Ls-Jan/Qt_CharFormatDialog 主要是作为QFontDialog的平替/增强&#xff0c;毕竟Qt自带的字体选择器一言难尽(用过的都叹气)。 【运行界面】 【功能】 一目了然&#xff0c;可以选择字体&#xff0c;设置字号&#xff0c;设置…...

Unity即时战略/塔防项目实战(一)——构造网格建造系统

Unity即时战略/塔防项目实战&#xff08;一&#xff09;—— 构造网格建造系统 效果展示 Unity RTS游戏网格建造系统实现原理 地形和格子划分&#xff0c;建造系统BuildManager构建 地形最终需要划分成一个一个的小方格&#xff0c;首先定义一下小方格&#xff1a; private…...

【ZOJ 1095】Humble Numbers 题解(动态规划)

一个素数只有2&#xff0c;3&#xff0c;5或7的数被称为谦逊数。序列1、2、3、4、5、6、7、8、9、10、12、14、15、16、18、20、21、24、25、27。。。显示了前20个不起眼的数字。 编写一个程序来查找并打印此序列中的第n个元素。 输入规范 输入由一个或多个测试用例组成。每个…...

百科媒体背书,什么媒体的收录可以修改百科?

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好 大家都知道百科在百度搜索引擎中有很高的权重&#xff0c;排名非常靠前&#xff0c;任何机构&#xff0c;个人&#xff0c;或者企业做网络宣传百科是必不可少的&#xff0c;虽然任何人都可以注册并编辑其内容。但是&#x…...

USB鼠标实现——HID 报告的返回(八)

文章目录HID 报告的返回仓库地址USB 鼠标阅读顺序报告返回HID 报告的返回 仓库地址 仓库地址 USB 鼠标阅读顺序 枚举过程USB鼠标实现——设备描述符&#xff08;一&#xff09;USB鼠标实现——设置地址&#xff08;二&#xff09;USB鼠标实现——配置描述符集合&#xff08…...

DOPE PEG Maleimide,DOPE-PEG-Mal,二油酰磷脂酰乙醇胺PEG马来酰亚胺

文章关键词&#xff1a;高分子PEG&#xff0c;DOPE&#xff0c;聚乙二醇化修饰试剂基团反应特点&#xff1a; DOPE PEG Maleimide是一种由 DOPE 和马来酰亚胺基团组成的 PEG 化合物。基础产品数据&#xff1a; CAS号&#xff1a;N/A 中文名&#xff1a;1,2-二油酰-SN-甘油-3-磷…...

python-课后作业-2

1.Python 3.x的range()函数返回一个&#xff1a;可迭代的序列对象 注意&#xff1a; Python 3.x的range()函数返回一个可迭代的序列对象&#xff0c;其中包含指定范围内的整数。range()函数的语法如下&#xff1a; range([start], stop[, step]) 其中&#xff0c;start表示序…...

redis 六. list应用场景及底层分析

List 类型一. 简单命令示例二. java 操作示例三. 使用场景四. 底层分析一. 简单命令示例 1.首先简单说明: List是一个双端链表的结构,内容是2的32次方减1个元素,大概40多亿,主要功能有push/pop等,一般用在栈,队列,消息队列等场景 2.简单命令 //1.向列表左边添加元素 LPUSH ke…...

成语填字接龙隐私政策

1. 适用范围 (a) 在您注册本应用帐号时&#xff0c;您根据本应用要求提供的个人注册信息&#xff1b; (b) 在您使用本应用网络服务&#xff0c;或访问本应用平台网页时&#xff0c;本应用自动接收并记录的您的浏览器和计算机上的信息&#xff0c;包括但不限于您的IP地址、浏览…...

导出LKD3588开发板的根文件系统

序:将RK3588上的整个根文件系统的文件通过ssh拷贝到PC系统(虚拟机) 工具:RK3588上的ubuntu系统需要安装:ssh, rsync。 PC电脑(虚拟机)上安装:ssh, rsync。 安装ssh 和rsync不做介绍,百度里面全是,也很简单需要设置开发板root权限的密码,因为后面同步文件的时候会用到…...

【统计模型】某地区土壤所含可给态磷回归分析

目录 某地区土壤所含可给态磷回归分析 一、研究目的 二、数据来源和相关说明 三、描述性分析 3.1 样本描述 3.2 数据可视化 四、数据建模 4.1 回归模型A 4.2 回归模型B 4.3 回归模型B模型诊断 4.4 回归模型C 五、结论及建议 5.1 结论 5.2 建议 六、代码 某地区土…...

redis 十. 线程基础

目录一. redis 基础复习与了解redis6二. redis 线程问题总结一. redis 基础复习与了解redis6 redis官网, redis中文网站, redis命令参考网站此处以redis6.0.8或以上版本为例(查看自己redis版本命令"redis- server -v")按照redis6以上版本测试使用时,redis.conf下需要…...

NQA简介

NQA简介定义目的NQA原理描述使用DHCP进行测试DNS测试NQA的联动机制NQA的应用场景定义 网络质量分析NQA&#xff08;Network Quality Analysis&#xff09;是一种实时的网络性能侦探和统计技术&#xff0c;可以对响应时间、网络抖动、丢包率等网络信息进行统计。NQA能够实时监视…...

[python]上下文管理contextlib模块与with语句

文章目录with语句自定义对象支持withcontextlib模块closing自动关闭suppress回避错误ExitStack清理Python 中的 with 语句用于清理工作&#xff0c;封装了 try…except…finally编码范式&#xff0c;提高了易用性。with语句 with语句有助于简化资源管理&#xff1a; # 离开作…...

STM32之TIM编码器接口

编码器简介&#xff1a; 例子讲解&#xff1a;正交编码器有两个输出&#xff0c;一个A相&#xff0c;一个B相&#xff0c;AB接口输出正交信号。然后接入STM32的定时器的编码器接口&#xff0c;编码器接口自动控制定时器时基单元中的CNT计数器进行自增或自减&#xff0c;比如初始…...

b站第一,Python自动化测试实战详细教学,3天教你学会自动化测试

目录 简介 Python自动化测试概述 Python自动化测试目标 Python自动化测试流程 1. 测试计划和设计 2. 测试脚本开发 3. 测试执行和管理 4. 测试维护和优化 Python自动化测试最佳实践 Python自动化测试工具和框架 结论 简介 自动化测试是软件开发过程中一个必不可少的…...

wordpress文章显示数量/青岛百度网站排名

在电脑Windows10系统上安装Centos7&#xff0c;安装后找不到Windows7引导菜单。 原因&#xff1a;因为CentOS 7已采用新式的grub2系统&#xff0c;所以需要进入/boot/grub2目录后使用vi编辑grub.cfg文件。 解决方法一&#xff1a;修改Centos 7的Grub2引导&#xff0c;添加Windo…...

zenme用ps做网站图/怎么样免费做网站

1.阿里分布式事务Seata介绍 作者&#xff1a;屹远&#xff08;陈龙&#xff09;&#xff0c;蚂蚁金服分布式事务核心研发 。 本文根据 8月11日 SOFA Meetup#3 广州站 《分布式事务 Seata 及其三种模式详解》主题分享整理&#xff0c;着重分享分布式事务产生的背景、理论基础&a…...

长沙培训网站制作/如何营销

想开发网页爬虫&#xff0c;发现被反爬了&#xff1f;想对 App 抓包&#xff0c;发现数据被加密了&#xff1f;不要担心&#xff0c;使用 Airtest 开发 App 爬虫&#xff0c;只要人眼能看到&#xff0c;你就能抓到&#xff0c;最快只需要2分钟&#xff0c;兼容 Unity3D、Cocos2…...

山东网站营销推广费用/以图搜图百度识图

度度熊保护村庄 Accepts: 47 Submissions: 900 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem Description 哗啦啦村袭击了喵哈哈村! 度度熊为了拯救喵哈哈村,带着自己的伙伴去救援喵哈哈村去了!度度熊与伙伴们很快的就过来占…...

wordpress 游客不可见/seo优化师培训

1、宏基Aspire 4738ZG入手本来是不准备购买笔记本电脑的&#xff0c;但是微知的这台华硕F5R也有3年半的历史了&#xff0c;运行状况还算正常&#xff0c;就是主板修了一次花了微知800大洋&#xff0c;实在是让微知心痛不已在心痛的同时&#xff0c;这款电脑也很难完成微知简单的…...

iis7建设网站/wix网站制作

1 基于区域的图像分割 图像分割中常用的直方图门限法、区域生长法、基于图像的随机场模型法、松弛标记区域分割法等均属于基于区域的方法。 &#xff08;1&#xff09;直方图门限分割就是在一定的准则下&#xff0c;用一个或几个门限值将图像的灰度直方图&#xff08;一…...