Skip to content
This repository was archived by the owner on May 8, 2022. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
source_md5="fea3be65d5f88dc9a57ed5d9b0236798"
dest_md5="52b501c75401e79f4200af6f4b93386c"

Binary file not shown.
74 changes: 74 additions & 0 deletions global/geometry/convex_polygon_2d.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
tool
class_name ConvexPolygon2D
extends Polygon

export(bool) var is_oriented = false setget set_is_oriented
# this is used when checking if the point is inside. If this is oriented then the inside is the part left to the segements
export(bool) var are_border_inside = true setget set_are_border_inside


func _init(new_points = PoolVector2Array(), is_oriented_p = false, are_border_inside_p = true):
._init()
is_oriented = is_oriented_p
are_border_inside = are_border_inside_p
# normaly signals cannot be connected at this point
_set_point_test(new_points)


func set_points(new_points):
if not _set_point_test(new_points):
printerr("array is not convex or has intersection, cannot assign")


func set_is_oriented(oriented):
is_oriented = oriented
emit_signal("changed")


func set_are_border_inside(border_inside):
are_border_inside = border_inside
emit_signal("changed")


func is_inside_convex(point):
# use it only if are_border_inside = false or is_oriented = true is important
# otherwise use is_inside
return _is_array_inside_convex(point, points, are_border_inside, is_oriented)


func get_orientation():
# optimized for convex polygones
return _get_array_first_orientation(points)


func is_valid():
return .is_valid() and is_convex()


func _set_point_test(new_points):
if _is_array_convex(new_points) and not _has_intersection_array(new_points):
points = new_points
emit_signal("changed")
return true
return false


static func _is_array_inside_convex(point, points_array, are_border_inside = true, is_oriented = false):
# only work for convex poly
# if not convex te output is unprevisible
var orientation = _get_array_first_orientation(points_array)
# bool that determine which region we need to check (bounded vs unbounded)
var unbounded_check = is_oriented and orientation == Polygon.Orientation.ANTI_TRIGONOMETRIC
for i in range(points_array.size()):
var edge = points_array[(i + 1) % points_array.size()] - points_array[i % points_array.size()]
var vector_to_point = point - points_array[i % points_array.size()]
var cross = edge.cross(vector_to_point)
var cross_oriented = (cross * orientation) if orientation != Polygon.Orientation.NOT_DEFINED else cross
if cross_oriented < 0.0 or (cross_oriented == 0.0 and not Utils.xor(unbounded_check, are_border_inside)):
# the first check determine if the point is to the side of the unbounded area
# the second condition determine if se are colinear to the edge
# the thrid one with the xor determine the behaviour depending if we consider boder inside
# as the border are considered inside event when we check for the unbounded area
# so in that case we check that teh point is not in the bounded area with inverse value of are_border_inside (achived by the xor)
return unbounded_check
return not unbounded_check
224 changes: 224 additions & 0 deletions global/geometry/polygon.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
tool
class_name Polygon
extends Resource

enum Orientation{
ANTI_TRIGONOMETRIC = -1,
NOT_DEFINED = 0,
TRIGONOMETRIC = 1,
}

export(PoolVector2Array) var points = PoolVector2Array() setget set_points


func _init(new_points = PoolVector2Array()):
._init()
_set_point_test(new_points)


func set_points(new_points):
_set_point_test(new_points)


func reverse_orientation():
points.invert()
emit_signal("changed")


func is_inside(point):
return Geometry.is_point_in_polygon(point, points)


func is_convex():
return _is_array_convex(points) and not _has_intersection_array(points)


func push_back_point(point):
var new_points = points
new_points.push_back(point)
return _set_point_test(new_points)


func insert_point(point, index):
if index >= points.size():
return
var new_points = points
new_points.insert(index, point)
return _set_point_test(new_points)


func pop_back_point():
return pop_point(points.size() - 1)


func pop_point(index):
if index >= points.size():
return null
var new_points = points
var point_back = points[index]
new_points.remove(index)
if _set_point_test(new_points):
return point_back
return null


func get_bounds():
return _get_bounds_array(points)


func _set_point_test(new_points):
points = new_points
emit_signal("changed")
return true


func is_valid():
return points != null and points.size() >= 3


func get_center_of_mass():
return _get_center_of_mass_array(points)


func set_orientation(orientation):
if orientation != Orientation.TRIGONOMETRIC and orientation != Orientation.ANTI_TRIGONOMETRIC:
return
var poly_orientation = get_orientation()
if poly_orientation != Orientation.NOT_DEFINED and poly_orientation != orientation:
reverse_orientation()


func get_shadow_points(shadow_size = 1, shadow_size_offset = Vector2.ZERO):
return _get_shadow_points_array(points, shadow_size, shadow_size_offset)


func get_orientation():
return _get_poly_orientation(points)


func get_border_of_poly(edge_index, border_width):
return _get_border_of_array(points, edge_index, border_width)


static func _get_center_of_mass_array(points_array):
var center = Vector2.ZERO
if points_array.size() == 0:
return center
for i in points_array:
center += points_array
return center / points_array.size()


static func _get_bounds_array(points_array):
if points_array.size() == 0:
return Rect2(Vector2.ZERO, Vector2.ZERO)
var min_x = points_array[0].x
var min_y = points_array[0].y
var max_x = points_array[0].x
var max_y = points_array[0].y
for i in range(1, points_array.size()):
min_x = min(min_x, points_array[i].x)
min_y = min(min_y, points_array[i].y)
max_x = max(max_x, points_array[i].x)
max_y = max(max_y, points_array[i].y)
return Rect2(Vector2(min_x, min_y), Vector2(max_x - min_x, max_y - min_y))


static func _has_intersection_array(points_array):
if points_array.size() < 3:
return false
for i in range(points_array.size() - 2):
for j in range(i + 2, points_array.size()):
var segment_1 = points_array[(i + 1) % points_array.size()] - points_array[i % points_array.size()]
var segment_2 = points_array[(j + 1) % points_array.size()] - points_array[j % points_array.size()]
var intersection = Geometry.line_intersects_line_2d(points_array[i % points_array.size()], segment_1, points_array[j % points_array.size()], segment_2)
var intersetion_segment = intersection - points_array[i % points_array.size()]
if _has_intersection_segent(points_array[i % points_array.size()], points_array[(i + 1) % points_array.size()], points_array[j % points_array.size()], points_array[(j + 1) % points_array.size()]):
return true
return false


static func _has_intersection_segent(point_1_start, point_1_end, point_2_start, point_2_end):
var segment_1 = point_1_end - point_1_start
var segment_2 = point_2_end - point_2_start
var intersection = Geometry.line_intersects_line_2d(point_1_start, segment_1, point_2_start, segment_2)
var intersetion_segment = intersection - point_1_start
# segemnt 1 and intersetion_segment are colinear
# the goal is to determine wehter of not intersection is inside the segment
# juste checking the length is not enought as it can be on the other side (dot is < 0)
return intersection != null and intersetion_segment.length() <= segment_1.length() and intersetion_segment.dot(segment_1) >= 0.0


static func _is_array_convex(points_array):
if points_array.size() < 3:
return false
var orientation_head = _get_array_head_orientation(points_array)
for i in range(1, points_array.size()):
var segment_array = PoolVector2Array([points_array[i % points_array.size()] , points_array[(i + 1) % points_array.size()], points_array[(i + 2) % points_array.size() ]])
var orientation = _get_array_head_orientation(segment_array)
if orientation_head == Orientation.NOT_DEFINED:
orientation_head = orientation
elif orientation != orientation_head and orientation != Orientation.NOT_DEFINED:
return false
return orientation_head != Orientation.NOT_DEFINED


static func _get_array_head_orientation(points_array):
if points_array.size() < 3:
return Orientation.NOT_DEFINED
var edge_1 = points_array[1] - points_array[0]
var edge_2 = points_array[2] - points_array[1]
var angle = fposmod(edge_2.angle_to(edge_1), 2.0 * PI)
if angle == PI or angle == 0.0:
return Orientation.NOT_DEFINED
return Orientation.TRIGONOMETRIC if angle < PI else Orientation.ANTI_TRIGONOMETRIC


static func _get_array_first_orientation(points_array):
# return the first not undefined orientation
# for convec poly this is the orientation of the poly
if points_array.size() < 3 or not _is_array_convex(points_array):
return Orientation.NOT_DEFINED
else:
for i in range(1, points_array.size()):
var segment_array = PoolVector2Array([points_array[i % points_array.size()], points_array[(i + 1) % points_array.size()], points_array[(i + 2) % points_array.size()]])
var orientation = _get_array_head_orientation(segment_array)
if orientation != Orientation.NOT_DEFINED:
return orientation
return Orientation.NOT_DEFINED


static func _get_poly_orientation(points_array):
if points_array.size() < 3:
return Orientation.NOT_DEFINED
var total_angle = 0
for i in range(points_array.size()):
var edge_1 = points_array[(i + 1) % points_array.size()] - points_array[i % points_array.size()]
var edge_2 = points_array[(i + 2) % points_array.size()] - points_array[(i + 1) % points_array.size()]
total_angle += - fposmod(edge_2.angle_to(edge_1), 2.0 * PI) + PI
if total_angle == 2.0 * PI or total_angle == 0.0:
# if total_angle this is jute that all point are colinear and therfore does not have an orientation
return Orientation.NOT_DEFINED
return Orientation.TRIGONOMETRIC if total_angle > 0.0 else Orientation.ANTI_TRIGONOMETRIC


static func _get_shadow_points_array(points_array, shadow_size = 1, shadow_size_offset = Vector2.ZERO):
# todo improve
var center_of_mass = _get_center_of_mass_array(points_array)
var array = PoolVector2Array()
for vector in points_array:
array.push_back((vector - center_of_mass).normalized() * shadow_size + vector + shadow_size_offset)
return array


static func _get_border_of_array(points_array, edge_index, border_width):
if edge_index > points_array.size() or border_width == 0:
return PoolVector2Array()
var orientation = _get_array_first_orientation(points_array)
var edge: Vector2 = points_array[(edge_index + 1) % points_array.size()] - points_array[edge_index % points_array.size()]
var edge_previous: Vector2 = points_array[edge_index % points_array.size()] - points_array[(edge_index - 1) % points_array.size()]
var edge_next: Vector2 = points_array[(edge_index + 2) % points_array.size()] - points_array[(edge_index + 1) % points_array.size()]
var array = [points_array[(edge_index) % points_array.size()], points_array[edge_index % points_array.size()]]
array.push_back((edge + edge_next).tangent().normalized() * orientation * border_width )
array.push_back((edge + edge_previous).tangent().normalized() * orientation * border_width )
return PoolVector2Array(array)
4 changes: 4 additions & 0 deletions global/utils.gd
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,7 @@ static func int_max(a: int, b: int) -> int:
return a
else:
return b


static func xor(bool_1, bool_2):
return (bool_1 and not bool_2) or (not bool_1 and bool_2)
1 change: 1 addition & 0 deletions gui/circular_button.gd
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ func update():
static func get_vector_radial(angle, radius = 1.0):
return Vector2(cos(angle), sin(angle)) * radius


func set_radius_out(new_radius):
if new_radius < radius_in:
return
Expand Down
Loading