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

【Godot4.3】三角形类

概述

在GDSCript中你想要表示一个平面三角形,只需要设定3个点的位置,也就是3个Vector2就行了,或者一个size()==3PackedVector2Array

但是想要进一步处理三角形,获得它的一些几何特征,比如:某个内角的角度值,角平分线、垂直平分线、中线、高线,还有对应的内接圆、外接圆圆心与半径等,就会变得比较困难。

本篇就讲述如何在Godot4.3中,用类来表示三角形,并获取它的几何特征。

类设计

  • Triangle类用于表示一个二维平面的三角形,可以获取内接圆、外接圆圆心与半径
  • Angle类用来表示一个角,可以获取角平分线、中线和高线
  • Segment类用来表示线段,比如三角形的边,可以获取垂直平分线

目前的设计只是一个初步实现,进一步可能会修改或添加一些方法。

三角形

# 三角形
class Triangle:
	var point_a:Vector2
	var point_b:Vector2
	var point_c:Vector2
	
	func _init(point_a:Vector2,point_b:Vector2,point_c:Vector2) -> void:
		self.point_a = point_a
		self.point_b = point_b
		self.point_c = point_c
	
	# 获取三角形的点集
	func get_points() -> PackedVector2Array:
		var points:PackedVector2Array
		points.append_array([point_a,point_b,point_c,point_a])
		return points
	
	# 获取角A
	func get_angle_a() -> Angle:
		return Angle.new(point_a,point_b,point_c)
	
	# 获取角B
	func get_angle_b() -> Angle:
		return Angle.new(point_b,point_a,point_c)
	
	# 获取角C
	func get_angle_c() -> Angle:
		return Angle.new(point_c,point_a,point_b)
	
	# 重心 - 任意两条中线的交点
	func gravity_center():
		var s1 = get_angle_a().get_mid_line()
		var s2 = get_angle_b().get_mid_line()
		return Geometry2D.line_intersects_line(s1.start,s1.vec().normalized(),s2.start,s2.vec().normalized())
	
	# 垂心 - 任意两条垂线的交点
	func high_center():
		var s1 = get_angle_a().get_high_line()
		var s2 = get_angle_b().get_high_line()
		return Geometry2D.line_intersects_line(s1.start,s1.vec().normalized(),s2.start,s2.vec().normalized())
	
	
	# 外心 - 任意两条垂直平分线的交点
	func out_center():
		var s1 = get_angle_a().seg_ab().mid_vertical_line()
		var s2 = get_angle_a().seg_bc().mid_vertical_line()
		return Geometry2D.line_intersects_line(s1.start,s1.vec().normalized(),s2.start,s2.vec().normalized())
	
	# 外接圆半径 - 外心与三个顶点距离中最长的一个
	func out_radius():
		var c:Vector2 = out_center()
		
		# 外心与各顶点的距离
		var m:float = minf(c.distance_to(point_a),c.distance_to(point_b))
		m = minf(m,c.distance_to(point_c))

		return m
	
	
	# 内心(内接圆圆心) - 任意两条角平分线的交点
	func inner_center() :
		var s1 = get_angle_a().get_half_angle_line()
		var s2 = get_angle_b().get_half_angle_line()
		return Geometry2D.line_intersects_line(s1.start,s1.vec().normalized(),s2.start,s2.vec().normalized())
		
	# 内接圆半径 - 内心在三条角平分线上短的那段的长度中最短的一个
	func inner_radius():
		var c:Vector2 = inner_center()
		
		# 内心与各边的垂直相交点
		var p1:Vector2 = Geometry2D.get_closest_point_to_segment(c,point_a,point_b)
		var p2:Vector2 = Geometry2D.get_closest_point_to_segment(c,point_a,point_c)
		var p3:Vector2 = Geometry2D.get_closest_point_to_segment(c,point_b,point_c)

		
		var m:float = minf(c.distance_to(p1),c.distance_to(p2))
		m = minf(m,c.distance_to(p3))

		return m

# 内角
class Angle:
	# 点
	var point_a:Vector2
	var point_b:Vector2
	var point_c:Vector2
	
	# 永远以point_a作为角的顶点
	func _init(point_a:Vector2,point_b:Vector2,point_c:Vector2) -> void:
		self.point_a = point_a
		self.point_b = point_b
		self.point_c = point_c
	
	# 线段ab
	func seg_ab() -> Segment:
		return Segment.new(point_a,point_b)
	# 线段ab
	func seg_ac() -> Segment:
		return Segment.new(point_a,point_c)
	# 线段ab
	func seg_bc() -> Segment:
		return Segment.new(point_b,point_c)
	
	# 获取夹角(弧度)
	func angle() -> float:
		return abs(seg_ab().vec().angle_to(seg_ac().vec()))
	
	# 获取角平分线
	func get_half_angle_line() -> Segment:
		var ang = seg_ab().vec().angle_to(seg_ac().vec())
		var len = maxf(seg_ab().vec().length(),seg_ac().vec().length()) # 取较长边长度
		
		var p = point_a + seg_ab().vec().normalized().rotated(ang/2.0) * len
		var p1 = Geometry2D.line_intersects_line(point_b,seg_bc().vec(),point_a,point_a.direction_to(p))
		return Segment.new(point_a,p1)
	
	# 获取中线
	func get_mid_line() -> Segment:
		return Segment.new(point_a,seg_bc().mid_point())
		
	# 获取高线
	func get_high_line() -> Segment:
		
		var p = Geometry2D.get_closest_point_to_segment_uncapped(point_a,point_b,point_c)
		return Segment.new(point_a,p)

线段

# 线段
class Segment:
	var start:Vector2
	var end:Vector2

	func _init(p1:Vector2,p2:Vector2) -> void:
		start = p1
		end = p2
	
	# 返回向量
	func vec() -> Vector2:
		return end - start
	
	# 获取点集
	func points() -> PackedVector2Array:
		var arr:PackedVector2Array
		arr.append_array([start,end])
		return arr
	
	# 获取中点
	func mid_point() -> Vector2:
		return start.lerp(end,0.5)
		
	# 垂直平分线
	func mid_vertical_line() -> Segment:
		var half_normal = vec().rotated(deg_to_rad(90))/2.0
		var p1 = mid_point() + half_normal
		var p2 = mid_point() - half_normal
		return Segment.new(p1,p2)

测试

创建和绘制三角形

extends Node2D

var t1:Triangle = Triangle.new(Vector2(100,100),Vector2(200,100),Vector2(150,200))


func _process(delta: float) -> void:
	t1.point_c = get_global_mouse_position()
	queue_redraw()

func _draw() -> void:
	draw_polyline(t1.get_points(),Color.WHITE,1)

中线和重心

func _draw() -> void:
	draw_polyline(t1.get_points(),Color.WHITE,1)
	# 三条中线
	var l1 = t1.get_angle_a().get_mid_line().points()
	var l2 = t1.get_angle_b().get_mid_line().points()
	var l3 = t1.get_angle_c().get_mid_line().points()
	draw_polyline(l1,Color.AQUAMARINE,1)
	draw_polyline(l2,Color.AQUAMARINE,1)
	draw_polyline(l3,Color.AQUAMARINE,1)
    # 重心
    draw_circle(t1.gravity_center(),3,Color.BROWN)

在这里插入图片描述

角平分线和内心

func _draw() -> void:
	draw_polyline(t1.get_points(),Color.WHITE,1)
	# 三条角平分线
	var l4 = t1.get_angle_a().get_half_angle_line().points()
	var l5 = t1.get_angle_b().get_half_angle_line().points()
	var l6 = t1.get_angle_c().get_half_angle_line().points()
	draw_polyline(l4,Color.AQUAMARINE,1)
	draw_polyline(l5,Color.AQUAMARINE,1)
	draw_polyline(l6,Color.AQUAMARINE,1)
	# 重心
	draw_circle(t1.inner_center(),3,Color.BROWN)
	draw_circle(t1.inner_center(),t1.inner_radius(),Color.YELLOW,false,1)

在这里插入图片描述

垂直平分线和外心

func _draw() -> void:
	draw_polyline(t1.get_points(),Color.WHITE,1)
	# 三条边的垂直平分线
	var l4 = t1.get_angle_a().seg_ab().mid_vertical_line().points()
	var l5 = t1.get_angle_a().seg_bc().mid_vertical_line().points()
	var l6 = t1.get_angle_a().seg_ac().mid_vertical_line().points()
	draw_polyline(l4,Color.AQUAMARINE,1)
	draw_polyline(l5,Color.AQUAMARINE,1)
	draw_polyline(l6,Color.AQUAMARINE,1)
	# 外心
	draw_circle(t1.out_center(),3,Color.BROWN)
	draw_circle(t1.out_center(),t1.out_radius(),Color.YELLOW,false,1)

在这里插入图片描述

高线和垂心

func _draw() -> void:
	draw_polyline(t1.get_points(),Color.WHITE,1)
	# 三条边的垂直平分线
	var l4 = t1.get_angle_a().get_high_line().points()
	var l5 = t1.get_angle_b().get_high_line().points()
	var l6 = t1.get_angle_c().get_high_line().points()
	draw_polyline(l4,Color.AQUAMARINE,1)
	draw_polyline(l5,Color.AQUAMARINE,1)
	draw_polyline(l6,Color.AQUAMARINE,1)
	# 垂心
	if t1.high_center():
		draw_circle(t1.high_center(),3,Color.BROWN)

在这里插入图片描述

总结

本文所述,是三角形几何特性获得的初步,API肯定会大改,只是作为初步试验成功的结果。

三角形是一种特殊的多边形,一些几何特性值得深入研究。


http://www.kler.cn/a/317694.html

相关文章:

  • 机器学习day3-KNN算法、模型调优与选择
  • rockylinux 8安装 gcc11.2
  • Qt 实现文件监控程序
  • 以往运维岗本人面试真题分享
  • mysql5.7安装SSL报错解决(2),总结
  • 【前端】深入浅出的React.js详解
  • lunar无第三方依赖的公历、农历、法定节假日...日历工具库
  • 什么是单例模式?
  • 用最新的C++技术,如何实现一个序列化工具库?
  • CSS的盒子模型(Box Model)
  • 2024年最强网络安全学习路线,详细到直接上清华的教材!
  • sftp上传文件报错提示“Permission denied“
  • geodatatool(地图资源下载工具)3.8更新
  • JavaScript 网页设计案例详解( 最新技术趋势)
  • jmeter本身常用性能优化方法
  • JavaWeb校园二手交易平台
  • 统信服务器操作系统【qcow2 镜像空间扩容】方案
  • Stable Diffusion Fooocus批量绘图脚本
  • 【深度学习|地学应用】glacier——让我们一起看看深度学习在冰川研究中的应用是怎么样的呢?
  • 【ANTLR】核心语法标记
  • Vue + element-ui实现动态表单项以及动态校验规则
  • 数据库1-1、1-n 、n-n关系实际场景
  • 如何用Stable Diffusion XL模型,绘制精致的二次元插图,学完就能用!
  • Ansible部署与应用基础
  • Nginx的相关细节
  • 【Elasticsearch】-spring boot 依赖包冲突问题