Initial commit

This commit is contained in:
Daniel Snider 2022-05-15 22:17:48 -07:00
commit 08034bb71d
14 changed files with 426 additions and 0 deletions

11
.gitignore vendored Normal file
View File

@ -0,0 +1,11 @@
# Godot-specific ignores
.import/
export.cfg
export_presets.cfg
# Imported translations (automatically generated from CSV files)
*.translation
# Mono-specific ignores
.mono/
data_*/

116
Circle.gd Normal file
View File

@ -0,0 +1,116 @@
extends Object
const Set = preload("res://Set.gd")
var position: Vector2
var radius: float
func _init(p_position: Vector2 = Vector2(), p_radius: float = 0.0):
position = p_position
radius = p_radius
func contains_point(p: Vector2):
return position.distance_squared_to(p) <= radius * radius + 0.1
func contains_all_points(ps: Array):
for p in ps:
if !contains_point(p):
return false
return true
func circumscribe_two_points(a: Vector2, b: Vector2):
position = a.linear_interpolate(b, 0.5)
radius = a.distance_to(b) / 2.0
func circumscribe_three_points(a: Vector2, b: Vector2, c: Vector2):
var bary_mat := [b - a, c - a]
var det = bary_mat[0].x * bary_mat[1].y - bary_mat[1].x * bary_mat[0].y
var area = 0.5 * det
if area < 0.001:
position = a
radius = 0.0
return
position = Vector2(
a.x + 1.0 / (4.0 * area) * (bary_mat[1].y * a.distance_squared_to(b) - bary_mat[0].y * a.distance_squared_to(c)),
a.y + 1.0 / (4.0 * area) * (bary_mat[0].x * a.distance_squared_to(c) - bary_mat[1].x * a.distance_squared_to(b))
)
radius = position.distance_to(a)
func circumscribe(points: Array):
var n = len(points)
assert(n > 1)
position = Vector2(0, 0)
radius = INF
if n == 2:
circumscribe_two_points(points[0], points[1])
return
elif n == 3:
circumscribe_three_points(points[0], points[1], points[2])
return
# Check every two points
for i in range(n):
for j in range(n):
if i == j: continue
var c = get_script().new()
c.circumscribe_two_points(points[i], points[j])
if c.radius < radius and c.contains_all_points(points):
position = c.position
radius = c.radius
# Check every three points
for i in range(n):
for j in range(n):
for k in range(n):
if i == j or j == k or i == k: continue
var c = get_script().new()
c.circumscribe_three_points(points[i], points[j], points[k])
if c.radius < radius and c.contains_all_points(points):
position = c.position
radius = c.radius
func circumscribe2_internal(input: Set, support: Set):
var c = get_script().new()
if !input.empty():
var input_prime: Set = input.duplicate()
var p: Vector2 = input_prime.pop_random() # remove P from Input
c.circumscribe2_internal(input_prime, support);
if c.contains_point(p):
return c
else:
var support_prime = support.duplicate()
support_prime.add(p)
c.circumscribe2_internal(input_prime, support_prime)
return c
else:
var support_values = support.values()
if len(support_values) == 2:
c.circumscribe_two_points(support_values[0], support_values[1])
elif len(support_values) == 3:
c.circumscribe_three_points(support_values[0], support_values[1], support_values[2])
return c
func circumscribe2(points: Array):
var n = len(points)
assert(n > 1)
if n == 2:
circumscribe_two_points(points[0], points[1])
return
elif n == 3:
circumscribe_three_points(points[0], points[1], points[2])
return
var points_set = Set.new()
points_set.add_all(points)
var c = circumscribe2_internal(points_set, Set.new())
position = c.position
radius = c.radius

18
Global.gd Normal file
View File

@ -0,0 +1,18 @@
extends Node
# Declare member variables here. Examples:
# var a = 2
# var b = "text"
# Called when the node enters the scene tree for the first time.
func _init():
OS.set_window_position(
OS.get_screen_position(OS.get_current_screen()) +
OS.get_screen_size()*0.5 - OS.get_window_size()*0.5)
# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
# pass

28
Main.tscn Normal file
View File

@ -0,0 +1,28 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://MinimumAreaCircle.gd" type="Script" id=1]
[ext_resource path="res://Point.tscn" type="PackedScene" id=2]
[node name="Main" type="Node2D"]
[node name="Camera2D" type="Camera2D" parent="."]
position = Vector2( 2, 2 )
current = true
[node name="MinimumAreaCircle" type="Node2D" parent="."]
script = ExtResource( 1 )
color = Color( 0.305882, 0.34902, 0.827451, 1 )
[node name="Point" parent="MinimumAreaCircle" instance=ExtResource( 2 )]
[node name="Point2" parent="MinimumAreaCircle" instance=ExtResource( 2 )]
position = Vector2( -218, -131 )
[node name="Point3" parent="MinimumAreaCircle" instance=ExtResource( 2 )]
position = Vector2( -186, -51 )
[node name="Point4" parent="MinimumAreaCircle" instance=ExtResource( 2 )]
position = Vector2( -285, 34 )
[node name="Point5" parent="MinimumAreaCircle" instance=ExtResource( 2 )]
position = Vector2( -173, 87 )

24
MinimumAreaCircle.gd Normal file
View File

@ -0,0 +1,24 @@
extends Node2D
const Circle = preload("res://Circle.gd")
onready var circle: Circle = Circle.new()
export var color: Color = Color.red
var selected_idx = 0
func _ready():
update_circle()
for child in get_children():
if child is CanvasItem:
child.connect("moved", self, "update_circle")
func update_circle():
var ps = []
for child in get_children():
ps.append(child.position)
circle.circumscribe(ps)
update()
func _draw():
draw_arc(circle.position, circle.radius, 0, TAU, 200, color, 2.0, true)

17
Point.gd Normal file
View File

@ -0,0 +1,17 @@
extends Node2D
signal moved
var dragging := false
func _unhandled_input(event):
if event is InputEventMouseMotion and dragging and !event.has_meta("handled"):
position = get_viewport().canvas_transform.xform_inv(event.position)
emit_signal("moved")
event.set_meta("handled", true)
elif event.is_action_released("drag"):
dragging = false
func _on_HitBox_input_event(viewport, event: InputEvent, shape_idx):
if event.is_action_pressed("drag"):
dragging = true

19
Point.tscn Normal file
View File

@ -0,0 +1,19 @@
[gd_scene load_steps=4 format=2]
[ext_resource path="res://point.png" type="Texture" id=1]
[ext_resource path="res://Point.gd" type="Script" id=2]
[sub_resource type="CircleShape2D" id=1]
radius = 14.0
[node name="Point" type="Sprite"]
position = Vector2( -292, -74 )
texture = ExtResource( 1 )
script = ExtResource( 2 )
[node name="HitBox" type="Area2D" parent="."]
[node name="CollisionShape2D" type="CollisionShape2D" parent="HitBox"]
shape = SubResource( 1 )
[connection signal="input_event" from="HitBox" to="." method="_on_HitBox_input_event"]

52
Set.gd Normal file
View File

@ -0,0 +1,52 @@
extends Object
var _values: Dictionary
func _init():
_values = Dictionary()
func size() -> int:
return _values.size()
func empty() -> bool:
return _values.size() == 0
func add(value):
_values[value] = true
func add_all(values):
for value in values:
add(value)
func remove(value):
_values.erase(value)
func remove_all(values):
for value in values:
remove(value)
func get_random():
return _values.keys()[randi() % _values.size()]
func pop_random():
assert(size() > 0)
var value = get_random()
remove(value)
return value
func values() -> Array:
return _values.keys()
func has(value) -> bool:
return _values.has(value)
func has_all(values) -> bool:
return _values.has_all(values)
func duplicate():
var new_set = get_script().new()
new_set._values = _values.duplicate()
return new_set
func clear():
_values.clear()

7
default_env.tres Normal file
View File

@ -0,0 +1,7 @@
[gd_resource type="Environment" load_steps=2 format=2]
[sub_resource type="ProceduralSky" id=1]
[resource]
background_mode = 2
background_sky = SubResource( 1 )

BIN
icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

35
icon.png.import Normal file
View File

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://icon.png"
dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

BIN
point.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 B

35
point.png.import Normal file
View File

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/point.png-85d91f0a7902375f86d31abcb57f3516.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://point.png"
dest_files=[ "res://.import/point.png-85d91f0a7902375f86d31abcb57f3516.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

64
project.godot Normal file
View File

@ -0,0 +1,64 @@
; Engine configuration file.
; It's best edited using the editor UI and not directly,
; since the parameters that go here are not all obvious.
;
; Format:
; [section] ; section goes between []
; param=value ; assign values to parameters
config_version=4
[application]
config/name="minareacircle"
run/main_scene="res://Main.tscn"
config/icon="res://icon.png"
[autoload]
Global="*res://Global.gd"
[input]
ui_left={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777231,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":14,"pressure":0.0,"pressed":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":0,"physical_scancode":65,"unicode":0,"echo":false,"script":null)
]
}
ui_right={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777233,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":15,"pressure":0.0,"pressed":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":0,"physical_scancode":68,"unicode":0,"echo":false,"script":null)
]
}
ui_up={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777232,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":12,"pressure":0.0,"pressed":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":0,"physical_scancode":87,"unicode":0,"echo":false,"script":null)
]
}
ui_down={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777234,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":13,"pressure":0.0,"pressed":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":0,"physical_scancode":83,"unicode":0,"echo":false,"script":null)
]
}
drag={
"deadzone": 0.5,
"events": [ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":1,"pressed":false,"doubleclick":false,"script":null)
]
}
[physics]
common/enable_pause_aware_picking=true
[rendering]
quality/depth/hdr=false
environment/default_environment="res://default_env.tres"