用可视化案例讲Rust编程5.用泛型和特性实现自适配绘制和颜色设置

上一节我们讲了用泛型实现返回结果,这一节我们来讲讲在函数签名里面使用泛型来对输入参数进行自适配。

先看UML设计图:

图片

好吧,看起来有点复杂,我们一个个来解释。

首先定义的是一个生成绘图元素需要的参数结构,并且定义个特性,就叫做构造绘图元素build_trace。

pub struct traceParam<G>{pub geometrys:Vec<G>,pub colors: Vec<inputColor>,pub size: usize,
}pub trait BuildTrace{fn build_trace(&self) -> Vec<Box<ScatterMapbox<f64,f64>>>;
}

绘图元素的参数,定义了三个参数:

  • 第一个参数是输入一个几何要素集合,因为我们最起码有点线面三种几何要素,所以定义的是一个泛型变量G

  • 第二参数是一个颜色集合,这里也可以用泛型,不过我们不需要那么多种颜色定义,这里给了一个枚举型的输入颜色,枚举定义如下:

#[derive(Debug,Clone)]
pub enum inputColor {NamedColor(NamedColor),Rgba(Rgba),
}

这里支持NameColor和Rgba两种颜色定义即可。

  • 第三个参数是一个size,用来控制点的大小、线的宽度和面要素的边框,当然你也可以设定更多的参数,我这里仅用来说明,就不搞那么麻烦了:

图片

接下去就可以写具体的实现了。

点要素的实现:

impl BuildTrace for traceParam<Point>{fn build_trace(&self) -> Vec<Box<ScatterMapbox<f64,f64>>> {let mut traces:Vec<Box<ScatterMapbox<f64,f64>>> = Vec::new();for (pnt,color) in zip(&self.geometrys,&self.colors) {let mut trace: Box<ScatterMapbox<f64, f64>> = ScatterMapbox::new(vec![pnt.y()], vec![pnt.x()]);trace = match color {inputColor::NamedColor(color) => {MyTrace{color:*color,size:self.size,trace:trace}.set_trace(geo_type::Point)},inputColor::Rgba(color) => {MyTrace{color:*color,size:self.size,trace:trace}.set_trace(geo_type::Point)},_ => panic!(""),};traces.push(trace);}traces}
}

线要素的实现:

impl BuildTrace for traceParam<LineString>{fn build_trace(&self) -> Vec<Box<ScatterMapbox<f64,f64>>> {let mut traces:Vec<Box<ScatterMapbox<f64,f64>>> = Vec::new();for (line,color) in zip(&self.geometrys,&self.colors) {let mut lat:Vec<f64>= Vec::new();let mut lon:Vec<f64>= Vec::new();for coord in line.coords(){lat.push(coord.y);lon.push(coord.x);}let mut trace: Box<ScatterMapbox<f64, f64>> = ScatterMapbox::new(lat, lon);trace = match color {inputColor::NamedColor(color) => {MyTrace{color:*color,size:self.size,trace:trace}.set_trace(geo_type::Line)},inputColor::Rgba(color) => {MyTrace{color:*color,size:self.size,trace:trace}.set_trace(geo_type::Line)},_ => panic!(""),};traces.push(trace);}traces}
}

面数据的实现:

impl BuildTrace for traceParam<Polygon>{fn build_trace(&self) -> Vec<Box<ScatterMapbox<f64,f64>>> {let mut traces:Vec<Box<ScatterMapbox<f64,f64>>> = Vec::new();for (poly,color) in zip(&self.geometrys,&self.colors) {let mut lat:Vec<f64>= Vec::new();let mut lon:Vec<f64>= Vec::new();for coord in poly.exterior(){lat.push(coord.y);lon.push(coord.x);}let mut trace: Box<ScatterMapbox<f64, f64>> = ScatterMapbox::new(lat, lon);trace = match color {inputColor::NamedColor(color) => {MyTrace{color:*color,size:self.size,trace:trace}.set_trace(geo_type::Polygon)},inputColor::Rgba(color) => {MyTrace{color:*color,size:self.size,trace:trace}.set_trace(geo_type::Polygon)},_ => panic!(""),};traces.push(trace);for ipoly in poly.interiors(){let mut ilat:Vec<f64>= Vec::new();let mut ilon:Vec<f64>= Vec::new();for coord in poly.exterior(){ilat.push(coord.y);ilon.push(coord.x);}trace = ScatterMapbox::new(ilat, ilon);      trace = MyTrace{color:NamedColor::White,size:self.size,trace:trace}.set_trace(geo_type::Polygon);traces.push(trace);}}traces}
}

里面三个方法都用了一个处理trace的方法,实现如下:

struct MyTrace<T>{color:T,size:usize,trace:Box<ScatterMapbox<f64,f64>>
}enum geo_type{Point,Line,Polygon,
}
trait SetTrace<T> {fn set_trace(&self,geo_type:geo_type)->Box<ScatterMapbox<f64,f64>>;
}impl SetTrace<NamedColor> for MyTrace<NamedColor>{fn set_trace(&self,geo_type:geo_type)->Box<ScatterMapbox<f64,f64>> {match geo_type{geo_type::Point =>{let t = *self.trace.to_owned().marker(Marker::new().color(self.color)).show_legend(false);Box::new(t)},geo_type::Line =>{let t = *self.trace.to_owned().line(Line::new().width(self.size as f64).color(self.color)).show_legend(false);Box::new(t)},geo_type::Polygon=> {let t = *self.trace.to_owned().fill(plotly::scatter_mapbox::Fill::ToSelf).fill_color(self.color).show_legend(false);Box::new(t)},_ => panic!("")}}
}impl SetTrace<Rgba> for MyTrace<Rgba>{fn set_trace(&self,geo_type:geo_type)->Box<ScatterMapbox<f64,f64>> {match geo_type{geo_type::Point =>{let t = *self.trace.to_owned().marker(Marker::new().color(self.color)).show_legend(false);Box::new(t)},geo_type::Line =>{let t = *self.trace.to_owned().line(Line::new().width(self.size as f64).color(self.color)).show_legend(false);Box::new(t)},geo_type::Polygon=> {let t = *self.trace.to_owned().fill(plotly::scatter_mapbox::Fill::ToSelf).fill_color(self.color).show_legend(false);Box::new(t)},_ => panic!("")}}
}

这两个方法,几乎99%是想同的,只是输入的颜色类型不一样,这样就是静态语言的麻烦之处了,只要函数签名不一致,就相当于两个方法,看到这里,大家可能想问,上一节讲过的泛型,在这里能用么?答案当然可以,不过就算用泛型,最终编译出来的代码也会因为编译器的处理,而实现函数单态化,即编译器会针对具体情况,编译出多个静态函数出来。所以这里如果继续抽象,也不是不行,但是算做过度设计了。

之后,就可以写一个绘制函数,然后进行调用了:

pub fn plot_draw_trace(traces:Vec<Box<ScatterMapbox<f64,f64>>>,outimg: Option<&str>){let mut plot = Plot::new();for t in traces{plot.add_trace(t);}let layout = _get_layout(1024, 800, Center::new(39.9, 116.3),MapboxStyle::Dark);plot.set_layout(layout);match outimg {Some(out) => plot.write_image(out, ImageFormat::PNG, 1200, 900, 1.0),None => plot.show(),}
}//这个是一个内部函数,用来初始化构造制图参数的。
fn  _get_layout(width:usize, height:usize,cnt:Center,ms:MapboxStyle) -> Layout{Layout::new().drag_mode(DragMode::Zoom).margin(Margin::new().top(10).left(10).bottom(10).right(10)).width(width).height(height).mapbox(Mapbox::new().style(ms).access_token("pk.eyJ1IjoiYWxsZW5sdTIwMDgiLCJhIjoiY2xxZjNsaGtmMDd0ZTJqcWM1MzRmemx1NCJ9.TbiPQB6j1w9ilBP4pFHRRw").center(cnt).zoom(10),)
}

最后我们写一个测试调用方法,来绘制一下百度地图:

// 因为在Html里面绘制比较慢,所以我这里就仅画三个图层
#[test]
fn draw_bd_style(){let shp1 = "./data/shp/北京行政区划.shp";let poly1:Vec<Polygon> = readShapefile::shp::read_shp(shp1);let colors:Vec<inputColor> = (0..poly1.len()).map(|x|inputColor::Rgba(Rgba::new(240,243,250,1.0))).collect();let mut t1 = traceParam{geometrys:poly1,colors:colors,size:0}.build_trace();let shp2 = "./data/shp/面状水系.shp";let poly2:Vec<Polygon> = readShapefile::shp::read_shp(&shp2);let colors:Vec<inputColor> = (0..poly2.len()).map(|x|inputColor::Rgba(Rgba::new(108,213,250,1.0))).collect();let mut t2 = traceParam{geometrys:poly2,colors:colors,size:0}.build_trace();let shp3 = "./data/shp/高速.shp";let line1:Vec<LineString> = readShapefile::shp::read_shp(&shp3);let colors:Vec<inputColor> = (0..line1.len()).map(|x|inputColor::Rgba(Rgba::new(255,182,118,1.0))).collect();let mut t3 = traceParam{geometrys:line1,colors:colors,size:1}.build_trace();t1.append(&mut t2);t1.append(&mut t3);plot_draw_trace(t1,None);
}

绘制效果如下:

图片

注意:plotly.rs的JS引用的是Mapbox,所以网络访问上可能会有一些障碍,有可能需要科学上网……

打完收工。

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

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

相关文章

Spring Security——09,解决跨域

解决跨域 一、SpringBoot配置二、配置SpringSecurity三、修改端口四、修改vue项目4.1 拿到token4.2 前端存储token4.3 前端请求头携带token 五、测试5.1 认证测试5.2 授权测试 一键三连有没有捏~~ 浏览器出于安全的考虑&#xff0c;使用 XMLHttpRequest对象发起 HTTP请求时必须…

day 74 js

js脚本 JS的作用&#xff1a; 描述显示的内容&#xff08;HTML&#xff09;修饰 HTML 标签&#xff08;CSS&#xff09;设置 HTML 标签的动作&#xff08;JS&#xff09;JS特点&#xff1a;基于对象的编程语言&#xff0c;通过浏览器解释执行作用&#xff1a;表单验证、改变标签…

使用阿里云服务器可以做什么?太多了

阿里云服务器可以干嘛&#xff1f;能干啥你还不知道么&#xff01;简单来讲可用来搭建网站、个人博客、企业官网、论坛、电子商务、AI、LLM大语言模型、测试环境等&#xff0c;阿里云百科aliyunbaike.com整理阿里云服务器的用途&#xff1a; 阿里云服务器活动 aliyunbaike.com…

AcWing 4. 多重背包问题 I

解题思路 相关思路 import java.util.Scanner; public class Main {public static void main(String[] args){Scanner scanner new Scanner(System.in);int N scanner.nextInt();int V scanner.nextInt();int v[] new int[N1];int w[] new int[N1];int s[] new int[N1];…

揭秘AI幻觉:GPT-4V存在视觉编码漏洞,清华联合NUS提出LLaVA-UHD

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 新建了免费的人工智能中文站https://ai.weoknow.com 新建了收费的人工智能中文站https://ai.hzytsoft.cn/ 更多资源欢迎关注 GPT-4V 的推出引爆了多模态大模型的研究。GPT-4V 在包括多模态问答、推理、交互在内的多个领…

二. CUDA编程入门-双线性插值计算

目录 前言0. 简述1. 执行一下我们的第十个CUDA程序2. Bilinear interpolation3. 代码分析总结参考 前言 自动驾驶之心推出的 《CUDA与TensorRT部署实战课程》&#xff0c;链接。记录下个人学习笔记&#xff0c;仅供自己参考 Note&#xff1a;关于 CUDA 加速双线程插值的内容博主…

爬虫逆向非对称加密和对称加密案例

注意&#xff01;&#xff01;&#xff01;&#xff01;某XX网站逆向实例仅作为学习案例&#xff0c;禁止其他个人以及团体做谋利用途&#xff01;&#xff01;&#xff01; 案例--aHR0cHM6Ly9jcmVkaXQuaGxqLmdvdi5jbi94eWdzL3l6d2ZzeHF5bWQv 第一步&#xff1a;分析页面、请求…

CTF 之Zhuanxv

拿到题目进行目录遍历发现有一个/list文件 打开/list文件&#xff0c;发现是一个登录界面 尝试过爆破&#xff0c;毫无疑问不可能成功。 刷新页面&#xff0c;抓包&#xff0c;然后放一个包&#xff0c;发现又发了一个请求。 GET /loadimage?fileNameweb_login_bg.jpg HTTP/…

1995-2021年各省分品种能源产量和消费量数据

1995-2021年各省分品种能源产量和消费量数据 1、时间&#xff1a;1995-2021年 2、来源&#xff1a;能源统计年鉴、各省年鉴 3、指标&#xff1a;能源消费总量、煤炭消费量、焦炭消费量、原油消费量、汽油消费量、煤油消费量、柴油消费量、燃料油消费量、天然气消费量、电力消…

不开玩笑,你应该像「搬砖」一样写代码!斯坦福大学研究如是说

由于程序员不可避免要进行很多重复性的工作&#xff0c;并且工作强度很高&#xff0c;导致有一种自嘲的说法出现&#xff1a;程序员们自称自己每天都在搬砖&#xff08;实际上很多职场人都这么自嘲&#xff09;。我相信当我们说工作像「搬砖」的时候&#xff0c;只是在表达一种…

非关系型数据库——三万字Redis数据库详解

目录 前言 一、Redis概述 1.主要特点 2.Redis优缺点 3.Redis为什么这么快 4.Redis那么快&#xff0c;为什么不用它做主数据库&#xff0c;只用它做缓存 5.线程模型 5.1单线程架构 5.2多线程IO处理&#xff08;Redis 6及以上&#xff09; 5.3线程模型的优化 6.作用 …

回归预测 | Matlab实现WOA-GPR鲸鱼算法优化高斯过程回归多变量回归预测

回归预测 | Matlab实现WOA-GPR鲸鱼算法优化高斯过程回归多变量回归预测 目录 回归预测 | Matlab实现WOA-GPR鲸鱼算法优化高斯过程回归多变量回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 Matlab实现WOA-GPR鲸鱼算法优化高斯过程回归多变量回归预测 1.Matlab实现…

吹爆!遥感高光谱分类(Python)

目录 一、数据集下载 二、安装包 三、数据处理 四、模型训练 五、模型推理 六、踩坑记录 一、数据集下载 Hyperspectral Remote Sensing Scenes - Grupo de Inteligencia Computacional (GIC) (ehu.eus) Installing SPy — Spectral Python 0.21 documentation 二、安装…

算法打卡day36|动态规划篇04| 01背包理论基础、416. 分割等和子集

目录 01背包理论基础 01背包问题描述 01背包解法 二维数组 一维数组 算法题 Leetcode 416. 分割等和子集 个人思路 解法 动态规划 01背包理论基础 不同的背包种类&#xff0c;虽然有那么多中南背包&#xff0c;但其中01背包和完全背包是重中之重&#xff1b; 01背包问…

Python + Appium 自动化操作微信入门看这一篇就够了

Appium 是一个开源的自动化测试工具&#xff0c;支持 Android、iOS 平台上的原生应用&#xff0c;支持 Java、Python、PHP 等多种语言。 Appium 封装了 Selenium&#xff0c;能够为用户提供所有常见的 JSON 格式的 Selenium 命令以及额外的移动设备相关的控制命令&#xff0c;…

LABVIEW--正弦+高斯噪声信号及滤波

前面板信号 后面板 LABVIEW源程序链接&#xff1a;https://pan.baidu.com/s/11B-75i4fHZwWQyjxn9yCyQ?pwd7tfj 提取码&#xff1a;7tfj

中文地址分词器源码阅读(jiedi)

文章目录 structure.p文件pd.read_excelenumerate思维导图核心源码讲解jiedi.pytrain.py 总结 structure 点击左边的Structure按钮就如Structure界面。从Structure我们可以看出当前代码文件中有多少个全局变量、函数、类以及类中有多少个成员变量和成员函数。 其中V图标表示全…

AI普及时代,【AI书童】助你提升自我竞争力

AI运营官招募令&#xff01;&#xff01;&#xff01; 【AI书童】运营官 未来智慧人工智能 2024-03-26 12:00 浙江 微信公众号&#xff1a;未来智慧人工智能 助力个人和企业在人工智能时代持续成功 随着ChatGPT、GPT-4和Sora等创新技术的推出&#xff0c;人工智能在多模态领…

《梦幻西游》迎来史上最大翻车,老玩家们为何纷纷揭竿而起?

因一次调整&#xff0c;21岁的《梦幻西游》迎来了自己有史以来最大的一波节奏。 玩家在微博上炮轰官方&#xff0c;称&#xff1a;“游戏借着打击工作室牟利的称号&#xff0c;砍副本活动产出&#xff0c;然后自己口袋无限卖”&#xff0c;要求改善游戏现状。 从3月29日起&am…

小黑逆向爬虫探索与成长之路:小黑独立破解毛毛租数据加密与解密

前言 有道和招标网的加密入口定位在前面两期做了详细的介绍&#xff0c;本小结将通过简单的关键词搜索定位到加密与解密入口 数据接口寻找与请求 根据响应数据长度&#xff0c;确定数据接口&#xff0c;发现传入的参数需要加密&#xff0c;响应的结果需要解密&#xff0c;后…