Last active
May 12, 2023 18:39
-
-
Save bradmartin333/714f7b87e5bc3254cb02689b71729ea1 to your computer and use it in GitHub Desktop.
Keystone correction using y = mx + b
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from pyray import * | |
import csv | |
# Constants | |
start_wid = 800 | |
start_hgt = 600 | |
debug = True | |
def lerp(v1: Vector2, v2: Vector2, ratio: float): | |
if v2.x == v1.x: | |
return Vector2(v1.x, v1.y + (v2.y - v1.y) * ratio) | |
m = (v2.y - v1.y) / (v2.x - v1.x) | |
b = v1.y - m * v1.x | |
delta = (v2.x - v1.x) * ratio | |
x = delta + v1.x | |
y = m * x + b | |
return Vector2(x, y) | |
def intersection_of_lines(p1: Vector2, p2: Vector2, p3: Vector2, p4: Vector2): | |
if p2.x == p1.x: | |
return Vector2(p1.x, p3.y + (p4.y - p3.y) * (p1.x - p3.x) / (p4.x - p3.x)) | |
m1 = (p2.y - p1.y) / (p2.x - p1.x) | |
b1 = p1.y - m1 * p1.x | |
if p4.x == p3.x: | |
return Vector2(p3.x, p1.y + (p2.y - p1.y) * (p3.x - p1.x) / (p2.x - p1.x)) | |
m2 = (p4.y - p3.y) / (p4.x - p3.x) | |
b2 = p3.y - m2 * p3.x | |
x = (b2 - b1) / (m1 - m2) | |
y = m1 * x + b1 | |
return Vector2(x, y) | |
def shrink_poly(ps: list[Vector2], shrink_factor: float): | |
'''Shrink a polygon by shrink_factor pixels in all directions''' | |
return [ | |
Vector2(ps[0].x + shrink_factor, ps[0].y + shrink_factor), | |
Vector2(ps[1].x - shrink_factor, ps[1].y + shrink_factor), | |
Vector2(ps[2].x - shrink_factor, ps[2].y - shrink_factor), | |
Vector2(ps[3].x + shrink_factor, ps[3].y - shrink_factor) | |
] | |
class Rect: | |
nw_frac = Vector2() | |
se_frac = Vector2() | |
p1 = Vector2() | |
p2 = Vector2() | |
p3 = Vector2() | |
p4 = Vector2() | |
color = BLACK | |
thickness = 3.0 | |
def draw(self): | |
ps = shrink_poly([self.p1, self.p2, self.p3, self.p4], self.thickness) | |
draw_line_ex(ps[0], ps[1], self.thickness, self.color) | |
draw_line_ex(ps[1], ps[2], self.thickness, self.color) | |
draw_line_ex(ps[2], ps[3], self.thickness, self.color) | |
draw_line_ex(ps[3], ps[0], self.thickness, self.color) | |
# Create the window | |
print("Creating Window") | |
set_trace_log_level(8) # DEBUG | |
set_config_flags(ConfigFlags.FLAG_WINDOW_UNDECORATED) | |
set_config_flags(ConfigFlags.FLAG_MSAA_4X_HINT) | |
init_window(800, 600, 'Carmine') | |
# Setup monitor | |
set_window_monitor(0) | |
wid = get_screen_width(0) | |
hgt = get_screen_height(0) | |
set_window_size(wid, hgt) | |
hide_cursor() | |
# https://en.wikipedia.org/wiki/Keystone_effect | |
keystone_points = [Vector2(wid/2 - start_wid/2, hgt/2 - start_hgt/2), | |
Vector2(wid/2 + start_wid/2, hgt/2 - start_hgt/2), | |
Vector2(wid/2 - start_wid/2, hgt/2 + start_hgt/2), | |
Vector2(wid/2 + start_wid/2, hgt/2 + start_hgt/2)] | |
# Read the data from rects.csv | |
rects = [] | |
with open('rects.csv', newline='') as csvfile: | |
reader = csv.reader(csvfile, delimiter=',') | |
next(reader) # Skip the header | |
for row in reader: | |
r = Rect() | |
r.nw_frac = Vector2(float(row[0]), float(row[1])) | |
r.se_frac = Vector2(float(row[2]), float(row[3])) | |
r.color = color_from_normalized( | |
Vector4(float(row[4]), float(row[5]), float(row[6]), float(row[7]))) | |
r.thickness = float(row[8]) | |
rects.append(r) | |
# Main loop | |
while not window_should_close(): | |
begin_drawing() | |
clear_background(WHITE) | |
cursor_pos = get_mouse_position() | |
# Get the quadrant of the screen the cursor is in | |
quadrant = 0 | |
if cursor_pos.x > wid/2: | |
quadrant += 1 | |
if cursor_pos.y > hgt/2: | |
quadrant += 2 | |
# User adjust keystone point | |
if is_mouse_button_pressed(MouseButton.MOUSE_BUTTON_LEFT): | |
keystone_points[quadrant] = cursor_pos | |
if is_key_pressed(KeyboardKey.KEY_LEFT): | |
keystone_points[quadrant].x -= 1 | |
if is_key_pressed(KeyboardKey.KEY_RIGHT): | |
keystone_points[quadrant].x += 1 | |
if is_key_pressed(KeyboardKey.KEY_UP): | |
keystone_points[quadrant].y -= 1 | |
if is_key_pressed(KeyboardKey.KEY_DOWN): | |
keystone_points[quadrant].y += 1 | |
if debug: | |
# Draw the quadrants | |
draw_rectangle_v(Vector2(0, 0), Vector2(wid/2, hgt/2), | |
fade(BLACK, 0.1 if quadrant == 0 else 0)) | |
draw_rectangle_v(Vector2(wid/2, 0), Vector2(wid/2, hgt/2), | |
fade(BLACK, 0.1 if quadrant == 1 else 0)) | |
draw_rectangle_v(Vector2(0, hgt/2), Vector2(wid/2, hgt/2), | |
fade(BLACK, 0.1 if quadrant == 2 else 0)) | |
draw_rectangle_v(Vector2(wid/2, hgt/2), Vector2(wid/2, hgt/2), | |
fade(BLACK, 0.1 if quadrant == 3 else 0)) | |
# Draw lines between the points | |
for i in range(4): | |
for j in range(4): | |
if i != j: | |
draw_line_ex(keystone_points[i], | |
keystone_points[j], 1, BLACK) | |
# Draw the cursor | |
draw_circle_v(cursor_pos, 20, BLACK) | |
draw_line_ex(Vector2(cursor_pos.x, cursor_pos.y - 20), | |
Vector2(cursor_pos.x, cursor_pos.y + 20), 3, WHITE) | |
draw_line_ex(Vector2(cursor_pos.x - 20, cursor_pos.y), | |
Vector2(cursor_pos.x + 20, cursor_pos.y), 3, WHITE) | |
# Draw the rects | |
for r in rects: | |
t1 = lerp(keystone_points[0], keystone_points[1], r.nw_frac.x) | |
t2 = lerp(keystone_points[0], keystone_points[1], r.se_frac.x) | |
b1 = lerp(keystone_points[2], keystone_points[3], r.nw_frac.x) | |
b2 = lerp(keystone_points[2], keystone_points[3], r.se_frac.x) | |
l1 = lerp(keystone_points[0], keystone_points[2], r.nw_frac.y) | |
l2 = lerp(keystone_points[0], keystone_points[2], r.se_frac.y) | |
r1 = lerp(keystone_points[1], keystone_points[3], r.nw_frac.y) | |
r2 = lerp(keystone_points[1], keystone_points[3], r.se_frac.y) | |
r.p1 = intersection_of_lines(t1, b1, l1, r1) | |
r.p2 = intersection_of_lines(t2, b2, l1, r1) | |
r.p3 = intersection_of_lines(t2, b2, l2, r2) | |
r.p4 = intersection_of_lines(t1, b1, l2, r2) | |
r.draw() | |
end_drawing() | |
close_window() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
rx1 | ry1 | rx2 | ry2 | r | g | b | a | t | |
---|---|---|---|---|---|---|---|---|---|
0.0 | 0.0 | 0.2 | 0.2 | 0.0 | 0.0 | 0.0 | 1.0 | 1.0 | |
0.2 | 0.0 | 0.4 | 0.2 | 0.0 | 1.0 | 0.0 | 1.0 | 5.0 | |
0.4 | 0.0 | 0.6 | 0.2 | 0.0 | 0.0 | 1.0 | 1.0 | 5.0 | |
0.6 | 0.0 | 0.8 | 0.2 | 1.0 | 0.0 | 0.0 | 1.0 | 5.0 | |
0.8 | 0.0 | 1.0 | 0.2 | 0.0 | 1.0 | 0.0 | 1.0 | 5.0 | |
0.0 | 0.2 | 0.2 | 0.4 | 0.0 | 0.0 | 1.0 | 1.0 | 5.0 | |
0.2 | 0.2 | 0.4 | 0.4 | 0.0 | 0.0 | 0.0 | 1.0 | 1.0 | |
0.4 | 0.2 | 0.6 | 0.4 | 0.0 | 1.0 | 0.0 | 1.0 | 5.0 | |
0.6 | 0.2 | 0.8 | 0.4 | 0.0 | 0.0 | 1.0 | 1.0 | 5.0 | |
0.8 | 0.2 | 1.0 | 0.4 | 1.0 | 0.0 | 0.0 | 1.0 | 5.0 | |
0.0 | 0.4 | 0.2 | 0.6 | 0.0 | 1.0 | 0.0 | 1.0 | 5.0 | |
0.2 | 0.4 | 0.4 | 0.6 | 0.0 | 0.0 | 1.0 | 1.0 | 5.0 | |
0.4 | 0.4 | 0.6 | 0.6 | 0.0 | 0.0 | 0.0 | 1.0 | 1.0 | |
0.6 | 0.4 | 0.8 | 0.6 | 0.0 | 1.0 | 0.0 | 1.0 | 5.0 | |
0.8 | 0.4 | 1.0 | 0.6 | 0.0 | 0.0 | 1.0 | 1.0 | 5.0 | |
0.0 | 0.6 | 0.2 | 0.8 | 1.0 | 0.0 | 0.0 | 1.0 | 5.0 | |
0.2 | 0.6 | 0.4 | 0.8 | 0.0 | 1.0 | 0.0 | 1.0 | 5.0 | |
0.4 | 0.6 | 0.6 | 0.8 | 0.0 | 0.0 | 1.0 | 1.0 | 5.0 | |
0.6 | 0.6 | 0.8 | 0.8 | 0.0 | 0.0 | 0.0 | 1.0 | 1.0 | |
0.8 | 0.6 | 1.0 | 0.8 | 0.0 | 1.0 | 0.0 | 1.0 | 5.0 | |
0.0 | 0.8 | 0.2 | 1.0 | 0.0 | 0.0 | 1.0 | 1.0 | 5.0 | |
0.2 | 0.8 | 0.4 | 1.0 | 1.0 | 0.0 | 0.0 | 1.0 | 5.0 | |
0.4 | 0.8 | 0.6 | 1.0 | 0.0 | 1.0 | 0.0 | 1.0 | 5.0 | |
0.6 | 0.8 | 0.8 | 1.0 | 0.0 | 0.0 | 1.0 | 1.0 | 5.0 | |
0.8 | 0.8 | 1.0 | 1.0 | 0.0 | 0.0 | 0.0 | 1.0 | 1.0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment