【Godot4.3】点数据简易表示法和Point2D

概述

在构造多点路径时我们会用到PackedVector2Array,并使用Vector2()来构造点。在手动创建多点数据时,这种写法其实很难看,有大量重复的Vector2(),比如下面这样:

var points = [Vector2(100,100),Vector2(200,200),Vector2(300,300)]

如果有办法省去重复的Vector2()就好了。代码会显得简洁不少。

这也就是本篇文章探讨和实现的内容,用更简单的方式去表示点集(PackedVector2Array)。

点数据简易表示法

多点坐标字符串

我们可以用字符串形式,表示多个点的数据。比如:

var points = "100,100 200,200 300,300"

每对坐标用空格间隔。转化函数如下:

# 字符串形式的点数据转化为PackedVector2Array
func PotsStr2Vec2Arr(pots_str:String) -> PackedVector2Array:var arr:PackedVector2Arrayfor cord_str in pots_str.split(" "):var cord = cord_str.split(",")arr.append(Vector2(float(cord[0]),float(cord[1])))return arr

转化结果:

[(100, 100), (200, 200), (300, 300)]

坐标对顺序数组

也可以用坐标元素组成的数组表示多个点。

var points = [[100,100],[200,200],[300,300]]

转化函数:

# Array[Array]形式的点数据转化为PackedVector2Array
func PotsArr2Vec2Arr(pots:Array) -> PackedVector2Array:var arr:PackedVector2Arrayfor cord in pots:arr.append(Vector2(cord[0],cord[1]))return arr

坐标紧凑排列数组

更极端的表示方法是,将顺序的点坐标按顺序紧密的排列。

var points = [100,100,200,200,300,300]

转化函数:

# Array形式的点数据转化为PackedVector2Array
func Pots2Vec2Arr(pots:Array) -> PackedVector2Array:var arr:PackedVector2Array = []if pots.size() % 2 == 0:for i in range(pots.size()):if i % 2 == 0:arr.append(Vector2(pots[i],pots[i+1]))return arr

三合一解析

# 点数据转化为PackedVector2Array
func Vec2Arr(pots) -> PackedVector2Array:var arr:PackedVector2Array = []if pots is String: # 字符串形式for cord_str in pots.split(" "):var cord = cord_str.split(",")arr.append(Vector2(float(cord[0]),float(cord[1])))else: # 数组形式if pots[0] is Array:   # Array[Array] 形式for cord in pots:arr.append(Vector2(cord[0],cord[1]))else:if pots.size() % 2 == 0:for i in range(pots.size()):if i % 2 == 0:arr.append(Vector2(pots[i],pots[i+1]))return arr

则以下三种形式都可以被正确解析:

var points = Vec2Arr("100,100 200,200 300,300")
var points = Vec2Arr([[100,100],[200,200],[300,300]])
var points = Vec2Arr([100,100,200,200,300,300])

Points2D

紧缩二维向量数组PackedVector2Array,通常被用来表示2D折线或多边形的顺序点集,通常用于CanvasItem绘图等。

在求解复杂图形时,对于2D点集,通常我们会进行大量的变换、逆序等操作,而且会对其点、线进行遍历等操作。PackedVector2Array虽然也可以实现这些操作,但是每次都需要重新编写,二且作为数据类型,是无法拓展子类的。所以单独写一个类就很有必要了。

  • 通过将PackedVector2Array封装为Point2D类型,便可以将变换和翻转操作直接写成方法,并直接返回操作后的顶点数据。
  • 简易点数据转化函数可以写成该类的静态方法,既方便类实例使用,也方便其他地方使用。

在这里插入图片描述

class_name Points2Dvar points:PackedVector2Array# ==================== 实例化 ==================== 
func _init(pots) -> void:if pots is PackedVector2Array:self.points = potselse:self.points = Vec2Arr(pots)# ==================== 变换 ==================== 
# 水平翻转
func flip_x() -> PackedVector2Array:return Transform2D.FLIP_X * points
# 垂直翻转
func flip_y() -> PackedVector2Array:return Transform2D.FLIP_Y * points
# 旋转
func rotated(degree:float) -> PackedVector2Array:return Transform2D().rotated(deg_to_rad(degree)) * points
# 平移
func translated(offset:Vector2) -> PackedVector2Array:return Transform2D().translated(offset) * points# ==================== 逆序 ==================== 
func reverse() -> PackedVector2Array:var pots = points.duplicate()pots.reverse()return pots# ==================== 简易点数据转化函数 ==================== 
# 点简易数据转化为 PackedVector2Array
static func Vec2Arr(pots) -> PackedVector2Array:var arr:PackedVector2Array = []if pots is String: # 字符串形式for cord_str in pots.split(" "):var cord = cord_str.split(",")arr.append(Vector2(float(cord[0]),float(cord[1])))else: # 数组形式if pots[0] is Array:   # Array[Array] 形式for cord in pots:arr.append(Vector2(cord[0],cord[1]))else:if pots.size() % 2 == 0:for i in range(pots.size()):if i % 2 == 0:arr.append(Vector2(pots[i],pots[i+1]))return arr

使用测试

extends Node2Dvar points = Points2D.Vec2Arr("100,100 200,200 300,200")func _draw() -> void:draw_polyline(points,Color.AQUAMARINE,1)

可以看到:

  • 通过将Vec2Arr作为Points2D的静态方法,我们可以很方便的使用简易点表示表示法。
extends Node2Dvar points = Points2D.new("100,100 200,200 300,200")func _draw() -> void:draw_polyline(points.points,Color.AQUAMARINE,1)

同样的,我们可在用new()实例化一个Points2D对象时,传入简易点数据表示形式。

使用镜像变换

extends Node2Dvar points = Points2D.new("100,100 200,200 300,200")func _draw() -> void:draw_polyline(points.points,Color.AQUAMARINE,1)draw_polyline(points.flip_x(),Color.ORANGE,1)draw_polyline(points.flip_y(),Color.YELLOW_GREEN,1)

使用旋转变换

extends Node2Dvar points = Points2D.new("100,100 200,200 300,200")func _draw() -> void:draw_polyline(points.points,Color.AQUAMARINE,1)for i in range(1,10):draw_polyline(points.rotated(15 * i),Color.ORANGE,1)

使用逆序+平移变换

extends Node2Dvar points = Points2D.new("100,100 200,200 300,200")func _ready() -> void:var ps2 = Points2D.new(points.reverse())  # 逆序点points.points.append_array(ps2.translated(Vector2(100,-100)))func _draw() -> void:draw_polyline(points.points,Color.AQUAMARINE,1)

可以看到:

  • 通过添加平移了一段距离的折线的逆序点,可以构造一个多边形。上面的点集用draw_polygon()可以直接绘制出多边形。

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

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

相关文章

[Python]二、Python基础数据科学库(1)

F:\BaiduNetdiskDownload\2023人工智能开发学习路线图\2、机器学习核心技术\1、零基础快速入门机器学习 1.机器学习概述 1.1 人工智能概述 1.1.1 人工智能与机器学习、深度学习 1956年-达特茅斯会议-人工智能的起点 人工智能和机器学习、深度学习的关系: 1. 机器学习…

软考(9.22)

1 在浏览器的地址栏中输入xxxyftp.abc.can.cn,在该URL中( )是要访问的主机名。 A.xxxyftp B.abc C.can D.cn 协议://主机名.域名.域名后缀或IP地址(:端口号)/目录/文件名。 本题xxxyftp是主机名,选择A选项。 2 假设磁盘块与缓冲区大小相同,…

Django基础-创建新项目,各文件作用

学习Django的前置知识: python基本语法:需要掌握Python中的变量、循环、条件判断、函数等基本概念。面向对象编程(OOP):Django的核心架构基于面向对象编程,许多功能(如模型和视图)依…

【无人机设计与控制】 基于matlab的蚁群算法优化无人机uav巡检

摘要 本文使用蚁群算法(ACO)优化无人机(UAV)巡检路径。无人机巡检任务要求高效覆盖特定区域,以最小化能源消耗和时间。本研究提出的算法通过仿生蚁群算法优化巡检路径,在全局搜索和局部搜索中平衡探索与开…

文档布局内容检测系统源码分享

文档布局内容检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer…

银河麒麟高级服务器操作系统V10外接硬盘挂载指南

银河麒麟高级服务器操作系统V10外接硬盘挂载指南 1、临时挂载外接硬盘2、永久挂载外接硬盘3、总结 💖The Begin💖点点关注,收藏不迷路💖 在使用银河麒麟高级服务器操作系统V10时,您可能希望将外接硬盘(如sd…

django应用JWT(JSON Web Token)实战

文章目录 一、什么是JWT二、为什么使用JWT三、在django项目中如何应用JWT1、安装djangorestframework-simplejwt库:2、在settings.py中配置JWT认证:3、在urls.py中配置JWT的获取和刷新路由: 四、JWT如何使用1、调用生成JWT的接口获取JWT2、客…

C/C++内存管理 ——

目录 五、C/C内存管理 1、C/C内存分布 2、C语言中动态内存管理方式:malloc/calloc/realloc/free 3、C内存管理方式 1.new/delete操作内置类型 2.new和delete操作自定义类型 4、operator new与operator delete函数 5、new和delete的实现原理 1.内置类…

十六 未来信息综合技术(考点篇)试题

SaaS:软件即服务,PaaS:平台即服务,LaaS:基础设施即服务。 SaaS:偏向于提供各种软件接口来提供相关的服务;PaaS:偏向于吧一些基础的功能整合成一个平台,把整个平台或部分…

【人工智能】Linux系统Mamba安装流程

在编译安装 mamba 之前,你需要确保已安装正常的PyTorch环境。 # 安装必要的系统依赖 sudo apt update sudo apt install build-essential # 安装mamba依赖 pip install packaging wheel # 克隆仓库 git clone https://github.com/Dao-AILab/causal-conv1d.git git …

【python】修改字典的内容

person {"name": "John", "age": 30, "city": "New York"} print("最开始的信息:",person)def process_person_info(person):# 检查对象中是否包含所有必要的键if name in person and age in person …

计算机人工智能前沿进展-大语言模型方向-2024-09-22

计算机人工智能前沿进展-大语言模型方向-2024-09-21 引言: 全球最热销的国产游戏-《黑神话: 悟空》不仅给世界各地玩家们带来愉悦,而且对计算机人工智能研究也带来新的思考。在本期的论文速读中,我们带来一篇关于视觉语言模型(VLMs&#xf…

Java只有国人在搞了?

从Java诞生到现在,在全球一直属于最大的开发平台,拥有着世界上最多的开发者和最活跃的社区。你说Java只有国人在搞就有点过分了,Java中常用的主流框架全是外国人写的,虽说阿里也为Java做了很多贡献,但你还真没有资格说…

英伟达RTX 4090即将在10月份停产,RTX 50震撼来袭,你准备好了吗?

据多家媒体报道,英伟达(NVIDIA)及其合作伙伴计划于2024年10月停止生产其旗舰级显卡GeForce RTX 4090及其衍生型号RTX 4090D。尽管该计划尚未得到官方正式确认,但多家媒体和供应链消息均指出,这一决定旨在为即将到来的新…

vscode 配置rust格式化的正确方法

vscode 配置rust格式化的正确方法: 在settings.json里输入: "[rust]": {"editor.defaultFormatter": "rust-lang.rust-analyzer","editor.formatOnSave": true}

golang学习笔记6-更方便的转换、自定义包及网络部署【推荐收藏】

在上一个笔记中,我讲了基本数据类型的转换。不难发现,string和基本类型的互转比较麻烦,所以我自定义了一个包strtrans,封装了四个函数:ToString(),ToInt(),ToFloat(),ToBool()。其中ToString()适用于整数型&#xff0c…

关于字节 c++

字节的介绍 字节是计算机中最小的存储单位,通常由8个二进制位组成,用来存储一个字符。在C中,字节也是基本数据类型之一,用关键字"byte"来表示。字节主要用于存储一些较小的数据,如整数、字符等。字节的大小…

UE5入门

1.快捷键 工欲善其事,必先利其器,所以学习UE关卡编辑器快捷键必不可少 1.1Actor 选中actor , Q:选择模式 W:平移 E:旋转 R:缩放 CtrlB:打开Actor文件位置 F:聚焦 Ctr…

RP2040 C SDK GPIO和IRQ 唤醒功能使用

RP2040 C SDK GPIO和中断功能使用 📑RP2040 中断功能简介 Each core is equipped with a standard ARM Nested Vectored Interrupt Controller (NVIC) which has 32 interrupt inputs. Each NVIC has the same interrupts routed to it, with the exception of the…

Python办公自动化教程(002):PDF的拆分与合并

1、PyPDF2 介绍 介绍: PyPDF2是一个用于处理PDF文件的Python库,它提供了丰富的功能来读取、编辑、合并、拆分PDF文档,以及提取文本、图像和其他内容。 功能: 读取PDF:PyPDF2可以轻松地打开和读取PDF文件,获…