Java项目实战记录:雷达数据渲染
Java项目实战记录:雷达数据渲染
业务背景
我之前已经成功使用Java语言解析了C++处理的雷达数据文件,并提取了其中的经纬度点数据。这些文件中的点数据量相当庞大,每个雷达产品文件通常包含超过20万个数据点,有时甚至更多。
目前面临着如何在前端展示这20万个点数据的挑战。有两种可行的解决方案:一种是直接将所有点数据传输到前端进行渲染;另一种则是在后端将点数据渲染成PNG图片,然后再将图片传输到前端展示。经过考虑,决定采用第二种方案,即在后端进行数据的渲染处理。这样不仅可以有效减轻前端的负担,提高数据处理和展示的效率,而且还可以通过优化渲染过程来提高整体的展示质量。
代码逻辑
这里,选用了GeoTools这个强大的开源Java库来执行雷达数据的渲染任务。GeoTools是专为地理空间数据处理设计的工具集,它提供了丰富的API来支持地理数据的读取、查询、分析和展示。利用GeoTools,能够高效地将雷达扫描得到的点数据转换为图像,并以PNG格式保存。
数据结构
雷达数据结构如下所示:
import lombok.Data;/*** 雷达点数据信息*/
@Data
public class LonLatData {private float lon; // 经度private float lat; // 纬度private double val; // 回拨强度 (等于value/100)
}
颜色渲染
根据回拨强度需要渲染不同颜色,定义一个Style样式,具体分类如下所示:
/* * 根据数值创建基于值的点样式。** @return 样式对象,根据不同的值范围应用不同的颜色。*/public static Style createValueBasedPointStyle() {// 创建一个黑色描边,宽度为1。Stroke stroke = styleFactory.createStroke(filterFactory.literal(Color.BLACK), filterFactory.literal(1));FeatureTypeStyle fts = styleFactory.createFeatureTypeStyle();// 定义值的范围及其对应的颜色(十六进制表示)。Object[][] valueRanges = {{-5, Double.NEGATIVE_INFINITY, "#00acb8"},{0, -5, "#c1c0ac"},{10, 0, "#7a71fe"},{15, 10, "#1e26e3"},{20, 15, "#a6fcbb"},{25, 20, "#00ea15"},{30, 25, "#10932d"},{35, 30, "#fcf477"},{40, 35, "#c9c815"},{45, 40, "#8c8c12"},{50, 45, "#feadc0"},{55, 50, "#ff6370"},{60, 55, "#ee0244"},{65, 60, "#d48eff"},{Double.POSITIVE_INFINITY, 65, "#ab23ff"}};// 遍历每个值范围,为每个范围创建一个规则并添加到FeatureTypeStyle。for (Object[] range : valueRanges) {fts.rules().add(createRuleForRange(Double.parseDouble(range[1].toString()), Double.parseDouble(range[0].toString()), range[2].toString()));}// 创建样式并添加FeatureTypeStyle。Style style = styleFactory.createStyle();style.featureTypeStyles().add(fts);return style;}
MapContent加载数据并输出截图
首先创建了一个MapContent
对象,用它作为整个地图的内容载体。接着,创建了一个包含所有雷达数据点的图层,并为这些点指定了样式,这样做旨在通过视觉上的区分,提高数据的可读性。然后,将这个图层添加到MapContent
中,最后使用GeoTools的功能,将这些内容渲染成一张清晰展示雷达数据的PNG图片。
/*** 根据坐标和值创建地图图像。** @param coordinates 坐标对象列表,每个对象包含坐标点和与之相关联的值。* @param outputPath 图像输出路径,指定生成的地图图像保存的位置。* @throws Exception 抛出异常,处理文件操作或渲染过程中可能出现的错误。*/public static void createMapImageVal(ArrayList<CoordinatePojo> coordinates, String outputPath) throws Exception {// 步骤1: 定义SimpleFeatureTypeSimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder();typeBuilder.setName("Point");typeBuilder.setCRS(DefaultGeographicCRS.WGS84); // 坐标参考系统typeBuilder.add("location", Point.class); // 添加位置字段typeBuilder.add("value", Double.class); // 添加值字段SimpleFeatureType TYPE = typeBuilder.buildFeatureType(); // 构建特征类型// 步骤2: 创建SimpleFeatureCollectionDefaultFeatureCollection featureCollection = new DefaultFeatureCollection("internal", TYPE);GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);// 为每个坐标点创建特征并添加到集合中for (CoordinatePojo data : coordinates) {Point point = geometryFactory.createPoint(data.getCoordinate()); // 根据坐标创建点// 根据点的值创建SimpleFeatureSimpleFeature feature = SimpleFeatureBuilder.build(TYPE, new Object[]{point, data.getValue()}, null);featureCollection.add(feature); // 将特征添加到集合}// 创建基于值的点样式Style style = createValueBasedPointStyle(); // 假设这是一个自定义方法创建基于值的样式// 步骤3: 定义样式// 这里我们使用了自定义的创建样式方法,而不是SLD.createPointStyle// 步骤4: 渲染图像MapContent mapContent = new MapContent();mapContent.setTitle("Sample Map"); // 设置地图标题Layer layer = new FeatureLayer(featureCollection, style); // 创建图层mapContent.addLayer(layer); // 将图层添加到地图内容GTRenderer renderer = new StreamingRenderer();renderer.setMapContent(mapContent); // 设置地图内容Rectangle imageBounds = null;ReferencedEnvelope mapBounds = null;try {mapBounds = mapContent.getMaxBounds(); // 获取最大边界double heightToWidth = mapBounds.getSpan(1) / mapBounds.getSpan(0); // 计算高宽比imageBounds = new Rectangle(0, 0, 800, (int) Math.round(800 * heightToWidth)); // 设置图像边界} catch (Exception e) {// 处理可能的异常}BufferedImage image = new BufferedImage(imageBounds.width, imageBounds.height, BufferedImage.TYPE_INT_ARGB);Graphics2D gr = image.createGraphics();gr.setPaint(Color.WHITE);gr.fill(imageBounds); // 填充背景色renderer.paint(gr, imageBounds, mapBounds); // 渲染图像File file = new File(outputPath); // 创建文件ImageIO.write(image, "png", file); // 写入图像文件gr.dispose(); // 释放资源mapContent.dispose(); // 释放地图内容}
完整代码
GenerateMapImage地图渲染工具
import com.zykj.radar_server.datahandle.RadarDataParser;
import com.zykj.radar_server.datahandle.pojo.LonLatData;
import com.zykj.radar_server.entity.pojo.CoordinatePojo;
import com.zykj.radar_server.entity.pojo.RadarDataPojo;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.feature.DefaultFeatureCollection;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.map.FeatureLayer;
import org.geotools.map.Layer;
import org.geotools.map.MapContent;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.renderer.GTRenderer;
import org.geotools.renderer.lite.StreamingRenderer;
import org.geotools.styling.SLD;
import org.geotools.styling.Stroke;
import org.geotools.styling.Style;import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.List;import org.geotools.styling.*;
import org.opengis.filter.FilterFactory2;public class GenerateMapImage {/*** 根据坐标和值创建地图图像。** @param coordinates 坐标对象列表,每个对象包含坐标点和与之相关联的值。* @param outputPath 图像输出路径,指定生成的地图图像保存的位置。* @throws Exception 抛出异常,处理文件操作或渲染过程中可能出现的错误。*/public static void createMapImageVal(ArrayList<CoordinatePojo> coordinates, String outputPath) throws Exception {// 步骤1: 定义SimpleFeatureTypeSimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder();typeBuilder.setName("Point");typeBuilder.setCRS(DefaultGeographicCRS.WGS84); // 坐标参考系统typeBuilder.add("location", Point.class); // 添加位置字段typeBuilder.add("value", Double.class); // 添加值字段SimpleFeatureType TYPE = typeBuilder.buildFeatureType(); // 构建特征类型// 步骤2: 创建SimpleFeatureCollectionDefaultFeatureCollection featureCollection = new DefaultFeatureCollection("internal", TYPE);GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);// 为每个坐标点创建特征并添加到集合中for (CoordinatePojo data : coordinates) {Point point = geometryFactory.createPoint(data.getCoordinate()); // 根据坐标创建点// 根据点的值创建SimpleFeatureSimpleFeature feature = SimpleFeatureBuilder.build(TYPE, new Object[]{point, data.getValue()}, null);featureCollection.add(feature); // 将特征添加到集合}// 创建基于值的点样式Style style = createValueBasedPointStyle(); // 假设这是一个自定义方法创建基于值的样式// 步骤3: 定义样式// 这里我们使用了自定义的创建样式方法,而不是SLD.createPointStyle// 步骤4: 渲染图像MapContent mapContent = new MapContent();mapContent.setTitle("Sample Map"); // 设置地图标题Layer layer = new FeatureLayer(featureCollection, style); // 创建图层mapContent.addLayer(layer); // 将图层添加到地图内容GTRenderer renderer = new StreamingRenderer();renderer.setMapContent(mapContent); // 设置地图内容Rectangle imageBounds = null;ReferencedEnvelope mapBounds = null;try {mapBounds = mapContent.getMaxBounds(); // 获取最大边界double heightToWidth = mapBounds.getSpan(1) / mapBounds.getSpan(0); // 计算高宽比imageBounds = new Rectangle(0, 0, 800, (int) Math.round(800 * heightToWidth)); // 设置图像边界} catch (Exception e) {// 处理可能的异常}BufferedImage image = new BufferedImage(imageBounds.width, imageBounds.height, BufferedImage.TYPE_INT_ARGB);Graphics2D gr = image.createGraphics();gr.setPaint(Color.WHITE);gr.fill(imageBounds); // 填充背景色renderer.paint(gr, imageBounds, mapBounds); // 渲染图像File file = new File(outputPath); // 创建文件ImageIO.write(image, "png", file); // 写入图像文件gr.dispose(); // 释放资源mapContent.dispose(); // 释放地图内容}// StyleFactory 用于创建地图样式元素,例如图层的边框、填充等。private static final StyleFactory styleFactory = CommonFactoryFinder.getStyleFactory();// FilterFactory2 用于创建过滤条件,例如,在样式规则中选择符合特定条件的要素。private static final FilterFactory2 filterFactory = CommonFactoryFinder.getFilterFactory2();/*** 根据数值创建基于值的点样式。** @return 样式对象,根据不同的值范围应用不同的颜色。*/public static Style createValueBasedPointStyle() {// 创建一个黑色描边,宽度为1。Stroke stroke = styleFactory.createStroke(filterFactory.literal(Color.BLACK), filterFactory.literal(1));FeatureTypeStyle fts = styleFactory.createFeatureTypeStyle();// 定义值的范围及其对应的颜色(十六进制表示)。Object[][] valueRanges = {{-5, Double.NEGATIVE_INFINITY, "#00acb8"},{0, -5, "#c1c0ac"},{10, 0, "#7a71fe"},{15, 10, "#1e26e3"},{20, 15, "#a6fcbb"},{25, 20, "#00ea15"},{30, 25, "#10932d"},{35, 30, "#fcf477"},{40, 35, "#c9c815"},{45, 40, "#8c8c12"},{50, 45, "#feadc0"},{55, 50, "#ff6370"},{60, 55, "#ee0244"},{65, 60, "#d48eff"},{Double.POSITIVE_INFINITY, 65, "#ab23ff"}};// 遍历每个值范围,为每个范围创建一个规则并添加到FeatureTypeStyle。for (Object[] range : valueRanges) {fts.rules().add(createRuleForRange(Double.parseDouble(range[1].toString()), Double.parseDouble(range[0].toString()), range[2].toString()));}// 创建样式并添加FeatureTypeStyle。Style style = styleFactory.createStyle();style.featureTypeStyles().add(fts);return style;}/*** 根据给定的值范围和颜色创建一个规则。** @param min 范围的最小值。* @param max 范围的最大值。* @param hexColor 颜色的十六进制表示。* @return 样式规则,包含一个基于值范围的符号化表示。*/public static Rule createRuleForRange(double min, Object max, String hexColor) {// 根据十六进制颜色创建填充,并设置不透明度为1.0。Fill fill = styleFactory.createFill(filterFactory.literal(hexToColor(hexColor)), filterFactory.literal(1.0));// 获取默认的圆形标记,并设置填充和描边。Mark mark = styleFactory.getCircleMark();mark.setFill(fill);mark.setStroke(null); // 不使用描边。// 创建图形对象,清除默认的图形符号,添加自定义的标记。Graphic graphic = styleFactory.createDefaultGraphic();graphic.graphicalSymbols().clear();graphic.graphicalSymbols().add(mark);graphic.setSize(filterFactory.literal(4)); // 设置图形大小。// 创建点符号器,应用上面的图形。PointSymbolizer symbolizer = styleFactory.createPointSymbolizer(graphic, null);// 创建规则,设置过滤条件为值在指定范围内。Rule rule = styleFactory.createRule();rule.symbolizers().add(symbolizer);rule.setFilter(filterFactory.between(filterFactory.property("value"),filterFactory.literal(min),filterFactory.literal(max)));return rule;}/*** 将十六进制颜色字符串转换为Color对象。** @param hex 十六进制颜色字符串(例如,"#ff0000"表示红色)。* @return 转换后的Color对象。*/public static Color hexToColor(String hex) {// 将十六进制字符串转换为整数,并创建颜色对象。// 这里没有添加前缀"FF",因为Color类的构造函数默认处理不透明颜色。return new Color(Integer.parseInt(hex.substring(1), 16));}}
测试代码
测试数据自行准备,如何解析雷达数据请看我上一篇博客。
package com.zykj.radar_server.data;import com.zykj.radar_server.datahandle.GenerateMapImage;
import com.zykj.radar_server.datahandle.RadarDataParser;
import com.zykj.radar_server.datahandle.pojo.LonLatData;
import com.zykj.radar_server.entity.pojo.CoordinatePojo;
import com.zykj.radar_server.entity.pojo.RadarDataPojo;import org.junit.jupiter.api.Test;
import org.locationtech.jts.geom.Coordinate;
import org.springframework.boot.test.context.SpringBootTest;import java.util.ArrayList;
import java.util.List;@SpringBootTest
public class GenerateMapImageTest {@Testpublic void test() throws Exception {String filePath = "D:\\雷达测试数据\\数据\\20190305_110801_ZHBJ_Z_VOL_2.50.dat";RadarDataPojo radarDataPojo = RadarDataParser.handlePolarProductForPojo(filePath);ArrayList<LonLatData> lonLatDataList = radarDataPojo.getLonLatDataList();System.out.println(lonLatDataList.size());ArrayList<CoordinatePojo> coordinates = new ArrayList<>();for (int i = 0; i < lonLatDataList.size(); i++) {CoordinatePojo coordinatePojo = new CoordinatePojo();coordinatePojo.setCoordinate(new Coordinate(lonLatDataList.get(i).getLon(), lonLatDataList.get(i).getLat()));double val = lonLatDataList.get(i).getVal();coordinatePojo.setValue(val);coordinates.add(coordinatePojo);}// 指定输出图片路径String outputPath = "D:\\temp\\layers\\jiangsu_map_val4.png";GenerateMapImage.createMapImageVal(coordinates, outputPath);System.out.println("地图图片已生成: " + outputPath);}}
渲染效果
雷达数据渲染效果如下所示,颜色越深回波强度越大:
渲染点的大小可自行调节。
相关文章:
Java项目实战记录:雷达数据渲染
目录 Java项目实战记录:雷达数据渲染业务背景代码逻辑数据结构颜色渲染MapContent加载数据并输出截图 完整代码GenerateMapImage地图渲染工具测试代码 渲染效果 Java项目实战记录:雷达数据渲染 业务背景 我之前已经成功使用Java语言解析了C处理的雷达数…...
进程的概念 | PCB | Linux下的task_struct | 父子进程和子进程
在讲进程之前首先就是需要去回顾一下我们之前学的操作系统是干嘛的,首先操作系统是一个软件,它是对上提供一个良好高效,稳定的环境的,这是相对于用户来说的,对下是为了进行更好的软硬件管理的,所以操作系统…...
【GPT-SOVITS-03】SOVITS 模块-生成模型解析
说明:该系列文章从本人知乎账号迁入,主要原因是知乎图片附件过于模糊。 知乎专栏地址: 语音生成专栏 系列文章地址: 【GPT-SOVITS-01】源码梳理 【GPT-SOVITS-02】GPT模块解析 【GPT-SOVITS-03】SOVITS 模块-生成模型解析 【G…...
2024HVV行动-进军蓝中研判(log4j2、fastjson、Struts2、Shiro)
1、log4j2 特征: 恶意请求中包含 JNDI 协议地址,如"ldap://"、"rmi://"等,被 log4j2 解析为 JNDI 查找。 原理: 在日志输出中,未对字符进行严格的过滤,执行了 JNDI 协议加载的远程恶…...
亮点抢先看!4月16-17日,百度Create大会开设“AI公开课”,大咖带你打造赚钱工具
3月16日,2024百度Create AI开发者大会正式开放售票,嘉宾套票定价399元。据悉,本次大会以“创造未来(Create the Future)”为主题,设有20深度论坛、超30节AI公开课、3000平AI互动体验区和AI音乐节等精彩环节…...
【笔记本清灰/实用经验】荣耀Magicbook14-2020款-R5-4500U-清灰实战
清灰有风险,动手需谨慎,本文只分享本人的清灰过程,对使用它所产生的任何后果不任何负责任 文章目录 背景信息准备阶段工具准备信息收集 正式清灰初始化清灰流程放掉身体的静电(重要)拆笔记本后盖断开电源(重…...
如何写好Stable Diffusion的prompt
Stable Diffusion是一种强大的文本到图像生成模型,其效果在很大程度上取决于输入的提示词(Prompt)。以下是一些关于如何编写有效的Stable Diffusion Prompt的秘诀: 明确描述:尽量清晰地描述你想要的图像内容。使用具体…...
计算机毕业设计 | SpringBoot+vue 移动端社区物业管理系统(附源码+论文)
1, 概述 课题背景 近几年来,随着物业相关的各种信息越来越多,比如报修维修、缴费、车位、访客等信息,对物业管理方面的需求越来越高,我们在工作中越来越多方面需要利用网页端管理系统来进行管理,我们所需…...
玩转C语言——数组初探
一、前言 通过前面的学习,我们已了解C语言的结构变量、分支结构和循环结构。今天,我们一起来认识C语言的另一知识点——数组。先赞后看,养成习惯。 二、数组概念 学习数组,我们要明白数组是什么。在我看来:数组是⼀组…...
Nginx指令配置大全
基本命令 nginx -t 检查配置文件是否有语法错误 nginx -s reload 热加载,重新加载配置文件 nginx -s stop 快速关闭 nginx -s quit 等待工作进程处理完成后关闭配置块介绍 全局块 全局块是默认配置文件从开始到events块之间的…...
富格林:安全出金关注可信操作
富格林悉知,现货黄金投资凭借着诸多优势,成为了热门的投资产品之一,也获得了投资者的追捧。在投资中想要安全盈利出金,投资者一定要沉下心来学习专业知识和技术,这样才能在以后的投资操作中避免亏损,顺畅盈…...
DELETE、TRUNCATE 和 DROP 在MySQL中的区别及使用示例
在MySQL数据库中,DELETE、TRUNCATE TABLE 和 DROP 这三个命令分别适用于不同的数据删除需求,它们在工作原理、应用场景以及特性上有所区别。接下来,我们通过实例演示来明确这三者的不同之处。 DELETE 命令 功能与示例:DELETE 语…...
程序员应该如何选择职业赛道?
程序员选择职业赛道是一个涉及个人兴趣、技能匹配、市场需求和长远发展规划的综合决策过程。以下是一些关键步骤和考虑因素: 自我评估: 技能与专长:分析自己在编程语言、算法、数据结构等方面的现有技能,并思考这些技能更适合前端…...
深入浅出Hive性能优化策略
我们将从基础的HiveQL优化讲起,涵盖数据存储格式选择、数据模型设计、查询执行计划优化等多个方面。会的直接滑到最后看代码和语法。 目录 引言 Hive架构概览 示例1:创建表并加载数据 示例2:优化查询 Hive查询优化 1. 选择适当的文件格…...
利用卷积神经网络进行人脸识别
利用卷积神经网络(Convolutional Neural Networks, CNNs)进行人脸识别是计算机视觉领域的一个热门话题。下面是一个简化的指南,涵盖了从理论基础到实际应用的各个方面,可以作为你博文的基础内容。 理论基础 卷积神经网络简介&am…...
固态硬盘有坏道怎么恢复数据 固态硬盘坏道怎么修复
固态硬盘是一种高速、低噪音、低功耗的存储设备,但是它也有一个致命的问题——坏道。坏道是指存储芯片中的某些存储单元出现了故障,导致数据无法正常读取或写入。如果你的固态硬盘出现了坏道,那么你的数据就有可能会丢失,带来了很大的困扰。那么,固态硬盘有坏道怎么恢复数…...
adobe animate 时间轴找不到编辑多个帧按钮
如题,找了半天,在时间轴上找不到编辑多个帧按钮,导致无法批量处理帧 然后搜索发现原来是有些版本被隐藏了,需要再设置一下 勾选上就好了...
5 亿欧元巨额奖励!法国国防部启动量子初创公司项目
内容来源:量子前哨(ID:Qforepost) 编辑丨王珩 编译/排版丨沛贤 深度好文:800字丨6分钟阅读 据C4ISNET报道,法国国防部采购机构宣布向五家法国量子计算研究初创公司授予合同,用于开发量子计算技…...
Linux:系统初始化,内核优化,性能优化(2)
优化ssh协议 Linux:ssh配置_ssh配置文件-CSDN博客https://blog.csdn.net/w14768855/article/details/131520745?ops_request_misc%257B%2522request%255Fid%2522%253A%2522171068202516800197044705%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fb…...
JS08-DOM节点
DOM节点 查找节点 父节点 通过.parentNode属性可以获得某个元素的父节点,并对其进行操作。例如,隐藏.son元素的父节点。 <div class"father"><div class"son">儿子</div></div><script>let son d…...
2024/3/14打卡棋子(14届蓝桥杯)——差分
标准差分模板 差分——前缀和的逆运算(一维二维)-CSDN博客 题目 小蓝拥有 nn 大小的棋盘,一开始棋盘上全都是白子。 小蓝进行了 m 次操作,每次操作会将棋盘上某个范围内的所有棋子的颜色取反(也就是白色棋子变为黑色࿰…...
A Survey on Multimodal Large Language Models
目录 1. Introduction2. 概述方法多模态指令调优 3.1.1 简介3.1.2 预备知识3.1.3 模态对齐3.1.4 数据3.1.5 模态桥接3.1.6 评估 3.2.多模态情境学习3.3.多模态思维链3.3.1 模态桥接3.3.2 学习范式3.3.3 链配置3.3.4 生成模式3.4.LLMs辅助视觉推理3.4.1 简介3.4.2 训练范式3.4.3…...
Java面向对象编程(高级)一
在Java中,面向对象编程更是核心设计理念之一,为开发者提供了丰富的工具和特性来创建灵活、可扩展的应用程序。 本博客将深入探讨Java面向对象编程的高级特性,包括但不限于多态、继承、封装、抽象类、接口等方面的内容。我们将从实际案例出发…...
1056:点和正方形的关系
【题目描述】 有一个正方形,四个角的坐标(x,y)分别是(1,-1),(1,1),(-1,-1),(-1,1),x是横轴,y是纵轴。写一个程序,判断一个给定的点是…...
【iOS】ARC学习
文章目录 前言一、autorelease实现二、苹果的实现三、内存管理的思考方式__strong修饰符取得非自己生成并持有的对象__strong 修饰符的变量之间可以相互赋值类的成员变量也可以使用strong修饰 __weak修饰符循环引用 __unsafe_unretained修饰符什么时候使用__unsafe_unretained …...
数据分析 | Matplotlib
Matplotlib 是 Python 中常用的 2D 绘图库,它能轻松地将数据进行可视化,作出精美的图表。 绘制折线图: import matplotlib.pyplot as plt #时间 x[周一,周二,周三,周四,周五,周六,周日] #能量值 y[61,72,66,79,80,88,85] # 用来设置字体样式…...
mac npm install 很慢或报错
npm ERR! code CERT_HAS_EXPIRED npm ERR! errno CERT_HAS_EXPIRED npm ERR! request to https://registry.npm.taobao.org/pnpm failed, reason: certificate has expired 1、取消ssl验证: npm config set strict-ssl false 修改后一般就可以了,…...
100天精通Python(实用脚本篇)——第118天:基于selenium和ddddocr库实现反反爬策略之验证码识别
文章目录 专栏导读一、前言二、ddddocr库使用说明1. 介绍2. 算法步骤3. 安装4. 参数说明5. 纯数字验证码识别6. 纯英文验证码识别7. 英文数字验证码识别8. 带干扰的验证码识别 三、验证码识别登录代码实战1. 输入账号密码2. 下载验证码3. 识别验证码并登录 书籍推荐 专栏导读 …...
51单片机与ARM单片机的区别
51的MCU与ARM的MCU的区别 51单片机与ARM单片机区别主要体现在以下几个方面: 指令集架构(ISA): 51单片机:基于Intel 8051架构,采用的是CISC(复杂指令集计算机)设计,其指令…...
Android 10.0 mtk平台系统添加公共so库的配置方法
1.前言 在10.0的系统定制化开发中,由于 Android对应用应用的系统库限制越来越严格,上层应用包括(apk、jar包)不能直接引用系统的一些so库了。如果需要使用,只能使用,系统申明的公共库。 如果使用非系统申明的公共库,apk运行后调用该so库时,app会直接挂掉,或者系统开发…...
市直单位政府网站建设问题/广告资源对接平台
1. Model任务 Model负责通过数据库、AD(Active Directory)、Web Service及其他方式获取数据,以及将用户输入的数据保存到数据库、AD、Web Service等中。 Model只专注于有效地提供数据访问机制、数据格式验证、业务逻辑验证等。 2. 定义Model …...
wordpress仿逛/互联网营销师在哪里报名
作为最早的数字沟通方式之一,Email是人类交流史上一次质的飞跃。但时至今日,被垃圾邮件,拖低办公效率等问题拖累的Email早已是怨声载道。第三方邮箱客户端为了解决这些问题应运而出,各有特色。不过什么样的第三方邮箱客户端才是最…...
熊掌号接合网站做seo/谷歌浏览器搜索入口
一、内联元素与行元素的区别 1、内联元素即行内元素。2、内联元素,在文档流中挤在一行;不能设置宽高(即,即使设置了也不管用,例如a标签)、margin和padding的top和bottom 块元素,独占一行&#x…...
新洲城乡建设局网站/济南seo优化公司
> 一只公鹿,它走着走着,越走越快,最后它变成了高速公路(鹿)!!!!> > > > 火柴棍突然觉得头很痒,就伸手挠,挠着挠着就把自己烧死了...> > > > 有一天一跟火柴跌倒了,把头摔破了就去医院包扎,结果出来后就…...
招聘网站续费怎么做分录/百度指数是什么
最近在学习C#多线程编程的时候,对线程的挂起这一部分总感觉理解的不够清楚,看过几本书上的资料,但也都大多语焉不详,草草带过。幸好在园子里看到这样一篇很有意思的文章,有些《大话XXXX》丛书的风格,写的相…...
推广平台软件/兰州网络推广优化服务
import export 这两个家伙对应的就是es6自己的module功能。 我们之前写的Javascript一直都没有模块化的体系,无法将一个庞大的js工程拆分成一个个功能相对独立但相互依赖的小工程,再用一种简单的方法把这些小工程连接在一起。 这有可能导致两个问题&…...