【Godot4.3】三角形类
概述
在GDSCript中你想要表示一个平面三角形,只需要设定3个点的位置,也就是3个Vector2
就行了,或者一个size()==3
的PackedVector2Array
。
但是想要进一步处理三角形,获得它的一些几何特征,比如:某个内角的角度值,角平分线、垂直平分线、中线、高线,还有对应的内接圆、外接圆圆心与半径等,就会变得比较困难。
本篇就讲述如何在Godot4.3中,用类来表示三角形,并获取它的几何特征。
类设计
Triangle
类用于表示一个二维平面的三角形,可以获取内接圆、外接圆圆心与半径Angle
类用来表示一个角,可以获取角平分线、中线和高线Segment
类用来表示线段,比如三角形的边,可以获取垂直平分线
目前的设计只是一个初步实现,进一步可能会修改或添加一些方法。
三角形
# 三角形
class Triangle:var point_a:Vector2var point_b:Vector2var point_c:Vector2func _init(point_a:Vector2,point_b:Vector2,point_c:Vector2) -> void:self.point_a = point_aself.point_b = point_bself.point_c = point_c# 获取三角形的点集func get_points() -> PackedVector2Array:var points:PackedVector2Arraypoints.append_array([point_a,point_b,point_c,point_a])return points# 获取角Afunc get_angle_a() -> Angle:return Angle.new(point_a,point_b,point_c)# 获取角Bfunc get_angle_b() -> Angle:return Angle.new(point_b,point_a,point_c)# 获取角Cfunc 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:Vector2var point_b:Vector2var point_c:Vector2# 永远以point_a作为角的顶点func _init(point_a:Vector2,point_b:Vector2,point_c:Vector2) -> void:self.point_a = point_aself.point_b = point_bself.point_c = point_c# 线段abfunc seg_ab() -> Segment:return Segment.new(point_a,point_b)# 线段abfunc seg_ac() -> Segment:return Segment.new(point_a,point_c)# 线段abfunc 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) * lenvar 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:Vector2var end:Vector2func _init(p1:Vector2,p2:Vector2) -> void:start = p1end = p2# 返回向量func vec() -> Vector2:return end - start# 获取点集func points() -> PackedVector2Array:var arr:PackedVector2Arrayarr.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.0var p1 = mid_point() + half_normalvar p2 = mid_point() - half_normalreturn Segment.new(p1,p2)
测试
创建和绘制三角形
extends Node2Dvar 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肯定会大改,只是作为初步试验成功的结果。
三角形是一种特殊的多边形,一些几何特性值得深入研究。