Aplikace maticového počtu v geometrii#

Pomocí matic dokážeme efektivně popsat transformaci roviny nebo projekci prostoru do roviny. Ukážeme si toto využití matic na jednoduchých příkladech. Ukážeme si i triky, jak obejít omezení plynoucí z vlastností násobení, a to že počátek se zobrazuje na počátek a rovnoběžky se zobrazují na rovnoběžky. Ukážeme si, že zavedením homogenních souřadnic je možné do repertoáru transformací vyjádřitelných maticemi je možno započítat i posunutí a perspektivu.

import numpy as np
np.set_printoptions(precision=3, suppress=True)
from numpy import sqrt, sin, cos, pi
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
vzory=np.array([[0,0],[2,0],[2,1],[1,1.6],[0,1],[0,0]]).T
plt.plot(*vzory)
plt.gca().set_aspect('equal')
../_images/5a1979a581a00dce8871d936713ed8c2b8a6257e4d9c5501271760f452e0284e.png

Transformace roviny#

Kartézské souřadnice#

Modrý domeček postupně zobrazujeme různými maticemi.

A=np.array([[2,0],[0,2]])
B=np.array([[1,0.5],[0,0.6]])
theta=pi/3
P=np.array([[cos(theta)**2,sin(theta)*cos(theta)],[sin(theta)*cos(theta),sin(theta)**2]]) # projekce
R=np.array([[cos(theta),-sin(theta)],[sin(theta),cos(theta)]]) # rotace

def transformuj(M, vzory=vzory):
    obrazy = M @ vzory
    fig,ax = plt.subplots()
    poly = Polygon(vzory.T, facecolor='C0', alpha=0.5)
    ax.add_patch(poly)
    poly = Polygon(obrazy.T, facecolor='C1', alpha=0.5)
    ax.add_patch(poly)
    ax.plot(*vzory, *obrazy)
    ax.set(title=M)
    ax.set_aspect('equal')
    ax.grid()

for M in [A,B,P,R,R@P,P@R]:
    transformuj(M)
    
../_images/660a23d21be0b6d932f7ba98e7326644c61e083f2e14c5814a06c548233851f6.png ../_images/e0b349e2b212c1a80d8624266c0cbebcb9b20e15da657cacf8d9918904f2fa90.png ../_images/24aeae8b7b863019a932f5ac9887d4dba94a3488f7d63777dc4d4b33c67fd418.png ../_images/d8b7500cd2a4e581a3b8c317219188b29640c3cdd77eb3586dff1c471cda4919.png ../_images/fa74e3df69124dadd24172c95f06d4fed02579c5cef56b7ea47ab6470833827f.png ../_images/543bf39b147a074e879a3528efdb471eb1a9cc43748a3bf34e97d29219e71e54.png

Homogenní souřadnice#

Homogenní souřadnice umožňují i posunutí. Neplatí zde, že počátek se nutně zobrazuje na počátek.

vzory_h = np.zeros((vzory.shape[0] + 1, vzory.shape[1]))
vzory_h[:2,:] = vzory
vzory_h[2,:] = 1
print("Obrázek v homogenních souřadnicích: \n",vzory_h)
M = np.array([1,0,3,0,1,1]).reshape((2,3))
obrazy = M @ vzory_h
fig,ax = plt.subplots()
poly = Polygon(vzory.T, facecolor='C0', alpha=0.5)
ax.add_patch(poly)
poly = Polygon(obrazy.T, facecolor='C1', alpha=0.5)
ax.add_patch(poly)
ax.plot(*vzory, *obrazy)
ax.set(title=M)
ax.set_aspect('equal')
ax.grid()
Obrázek v homogenních souřadnicích: 
 [[0.  2.  2.  1.  0.  0. ]
 [0.  0.  1.  1.6 1.  0. ]
 [1.  1.  1.  1.  1.  1. ]]
../_images/8de484de90d524cb4ecb426de1a88070e2752971b4ad55aca8964af8fdc3d72d.png

Transformace prostoru do roviny#

Afinní transformace#

vzory3d = np.zeros((3,12))
vzory3d[:2,:] = np.tile(vzory,2)
vzory3d[2,6:] = 1.7
vzory3d
array([[0. , 2. , 2. , 1. , 0. , 0. , 0. , 2. , 2. , 1. , 0. , 0. ],
       [0. , 0. , 1. , 1.6, 1. , 0. , 0. , 0. , 1. , 1.6, 1. , 0. ],
       [0. , 0. , 0. , 0. , 0. , 0. , 1.7, 1.7, 1.7, 1.7, 1.7, 1.7]])
Matice=[
    np.array([[1,0,0],[0,1,0]]), 
    np.array([[1,0,0.5],[0,1,.5]]), 
    np.array([[0,0,1],[0,1,0]]), 
    np.array([[0.5,0,.6],[-.2,1,.8]]), 
]

for A in Matice:
    projekce = A @ vzory3d
    fig, ax = plt.subplots()
    plt.plot(*projekce,"C0")
    for i in range(5):
        plt.plot(projekce[0,i::6], projekce[1,i::6], 'C0')
        ax.set(title=A)
        ax.grid()
../_images/b42dbd94d97d405521922bdcf4900bfeb543f497bf0817ddeba326b62ab79c93.png ../_images/22850289325700f441a41313b612a85a86efc9a65896a689e5523ac23fe4f945.png ../_images/6dda917f511d69e14a4281bfb5f734d3346aa84a47065776e23f76711ba026fd.png ../_images/49cdff1a9fd02e9c809d587d880d748edbe8a3b35b6d102e89dbffb00e8380df.png

Perspektiva#

Viz Wikipedie

f=5
v = vzory3d + np.array([[-3,-2,5]]).T # posun obrazku mimo pocatek soustavy souřadnic

M = np.diag([1,1,1/f]) # projekcni matice
o = M @ v # aplikace matice
o = o / o[2,:] # prevod z homogennich souradnic na kartezske

fig, ax = plt.subplots()
ax.plot(*o[:2,:],"C0")
for i in range(5):
    ax.plot(o[0,i::6], o[1,i::6], 'C0')
ax.set(title=M)
ax.grid();
../_images/5b5dbe6795749405fd575ab09dfe89c5a1cbb6b526f8f139a119ef9b0a3078e9.png