Place pins arbitrarily (not just image corners)

This commit is contained in:
Ruben van de Ven 2024-11-08 18:14:14 +01:00
parent 12349dfd55
commit 348a96b12c
2 changed files with 31 additions and 21 deletions

View file

@ -29,7 +29,7 @@ def on_key_press(symbol, modifiers):
exit()
pins = PygletCornerPin(window)
pins = PygletCornerPin(window, source_points=[[100,100], [700,100], [100,500], [300,300]])
# event handlers for dragging:
window.push_handlers(pins)

View file

@ -11,6 +11,7 @@ incidently so won't really hurt performance.
import pyglet
from typing import Optional
import logging
import copy
def adj(m): # Compute the adjugate of m
return [
@ -63,8 +64,17 @@ def general2DProjection(
d = basisToPoints(x1d, y1d, x2d, y2d, x3d, y3d, x4d, y4d)
return multmm(d, adj(s))
def transform2d(w, h, x1, y1, x2, y2, x3, y3, x4, y4):
t = general2DProjection(0, 0, x1, y1, w, 0, x2, y2, 0, h, x3, y3, w, h, x4, y4)
def transform2d_wh(w, h, x1d, y1d, x2d, y2d, x3d, y3d, x4d, y4d):
"""
Transform the image corners based on width and height of the image
"""
return transform2d(0, 0, x1d, y1d, w, 0, x2d, y2d, 0, h, x3d, y3d, w, h, x4d, y4d)
def transform2d(x1s, y1s, x2s, y2s, x3s, y3s, x4s, y4s, x1d, y1d, x2d, y2d, x3d, y3d, x4d, y4d):
"""
Transform the image based on 4 arbitrarily placed pins
"""
t = general2DProjection(x1s, y1s, x1d, y1d, x2s, y2s, x2d, y2d, x3s, y3s, x3d, y3d, x4s, y4s, x4d, y4d)
for i in range(9):
t[i] = t[i] / t[8]
@ -77,7 +87,7 @@ def transform2d(w, h, x1, y1, x2, y2, x3, y3, x4, y4):
# Below are all pyglet specific functions
class PygletCornerPin(pyglet.event.EventDispatcher):
def __init__(self, window: pyglet.window.Window, corners: Optional[list[list[float]]] = None) -> None:
def __init__(self, window: pyglet.window.Window, corners: Optional[list[list[float]]] = None, source_points: Optional[list[list[float]]] = None) -> None:
"""
Creates CornerPin utility for a given Pyglet window. If not given, corners default to the
bottom left, bottom right, top left, top right corners of the window (i.e. no transform)
@ -85,21 +95,23 @@ class PygletCornerPin(pyglet.event.EventDispatcher):
Do not forget to register event handlers by running `window.register_handlers(pins)`.
"""
self.window = window
self.corners = corners if corners else [
self.source_points = source_points if source_points else [
[0, 0],
[self.window.width, 0],
[0, self.window.height],
[self.window.width, self.window.height],
]
self.pin_positions = corners if corners else copy.deepcopy(self.source_points)
self.batch = pyglet.graphics.Batch()
self.dragging: Optional[int] = None
self.handles = [
pyglet.shapes.Arc(c[0],c[1],20, thickness=2, color=(0,0,255,255), batch=self.batch) for c in self.corners
pyglet.shapes.Arc(c[0],c[1],20, thickness=2, color=(0,0,255,255), batch=self.batch) for c in self.pin_positions
]
self.current_corner = None
def update_handles(self):
for i, c in enumerate(self.corners):
for i, c in enumerate(self.pin_positions):
self.handles[i].x = c[0]
self.handles[i].y = c[1]
@ -109,14 +121,12 @@ class PygletCornerPin(pyglet.event.EventDispatcher):
"""
self.batch.draw()
def transform2d_matrix(self, x1, y1, x2, y2, x3, y3, x4, y4):
def transform2d_matrix(self,x1s, y1s, x2s, y2s, x3s, y3s, x4s, y4s, x1d, y1d, x2d, y2d, x3d, y3d, x4d, y4d):
"""
Calculate the transform matrix
"""
t = transform2d(
self.window.width,
self.window.height,
x1, y1, x2, y2, x3, y3, x4, y4 )
x1s, y1s, x2s, y2s, x3s, y3s, x4s, y4s, x1d, y1d, x2d, y2d, x3d, y3d, x4d, y4d)
return pyglet.math.Mat4(t)
# event handlers
@ -126,8 +136,8 @@ class PygletCornerPin(pyglet.event.EventDispatcher):
currentcorner = None
dist = r * r
for i in range(4):
dx = x - self.corners[i][0]
dy = y - self.corners[i][1]
dx = x - self.pin_positions[i][0]
dy = y - self.pin_positions[i][1]
if dist > dx**2 + dy ** 2:
dist = dx**2 + dy ** 2
currentcorner = i
@ -139,15 +149,15 @@ class PygletCornerPin(pyglet.event.EventDispatcher):
if self.dragging is None:
return pyglet.event.EVENT_UNHANDLED
self.dragging = None
logging.debug(f"Corner pins set to {self.corners}")
logging.debug(f"Corner pins set to {self.pin_positions}")
return pyglet.event.EVENT_HANDLED
def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
if self.dragging is None:
return pyglet.event.EVENT_UNHANDLED
self.corners[self.dragging][0] = x
self.corners[self.dragging][1] = y
self.pin_positions[self.dragging][0] = x
self.pin_positions[self.dragging][1] = y
self.update_view()
def on_key_release(self, symbol: int, modifiers: int):
@ -186,15 +196,15 @@ class PygletCornerPin(pyglet.event.EventDispatcher):
base *= 2
if symbol == pyglet.window.key.RIGHT:
self.corners[self.current_corner][0] += base
self.pin_positions[self.current_corner][0] += base
if symbol == pyglet.window.key.LEFT:
self.corners[self.current_corner][0] -= base
self.pin_positions[self.current_corner][0] -= base
if symbol == pyglet.window.key.UP:
self.corners[self.current_corner][1] += base
self.pin_positions[self.current_corner][1] += base
if symbol == pyglet.window.key.DOWN:
self.corners[self.current_corner][1] -= base
self.pin_positions[self.current_corner][1] -= base
self.update_view()
def update_view(self):
self.window.view = self.transform2d_matrix(*[x for c in self.corners for x in c])
self.window.view = self.transform2d_matrix(*[x for c in self.source_points for x in c], *[x for c in self.pin_positions for x in c])