【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肯定会大改,只是作为初步试验成功的结果。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

巽星石

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值