线性变换
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
__pycache__
|
||||||
|
*.pyc
|
1
note/20250709134038-qjup165.sy
Normal file
1
note/20250709134038-qjup165.sy
Normal file
File diff suppressed because one or more lines are too long
1
transform/README.md
Normal file
1
transform/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
线性变换
|
79
transform/RotateSingle.pas
Normal file
79
transform/RotateSingle.pas
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
program RotateSingle;
|
||||||
|
uses
|
||||||
|
Math;
|
||||||
|
|
||||||
|
function LinearTrans(arr: array of array of Real; x: array of Real): array of Real;
|
||||||
|
var
|
||||||
|
result: array[0..1] of Real;
|
||||||
|
i, j: Integer;
|
||||||
|
begin
|
||||||
|
result[0] := x[0]*arr[0][0] + x[1]*arr[0][1];
|
||||||
|
result[1] := x[0]*arr[1][0] + x[1]*arr[1][1];
|
||||||
|
|
||||||
|
LinearTrans := result;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function RotateLine(line: array of Real; p: array of Real; dgr: Real): array of Real;
|
||||||
|
var
|
||||||
|
k, b: Real;
|
||||||
|
arr: array[0..1, 0..1] of Real;
|
||||||
|
kvec, rkvec: array[0..1] of Real;
|
||||||
|
rk: Real;
|
||||||
|
p1: array[0..1] of Real;
|
||||||
|
pvec, rpvec: array[0..1] of Real;
|
||||||
|
rp1: array[0..1] of Real;
|
||||||
|
result: array[0..1] of Real;
|
||||||
|
begin
|
||||||
|
{
|
||||||
|
Rotate y=kx+b with p for dgr.
|
||||||
|
dgr measured in radians.
|
||||||
|
line: [k, b] => y = kx + b
|
||||||
|
}
|
||||||
|
|
||||||
|
k := line[0];
|
||||||
|
b := line[1];
|
||||||
|
|
||||||
|
arr[0][0] := Cos(dgr);
|
||||||
|
arr[0][1] := -Sin(dgr);
|
||||||
|
arr[1][0] := Sin(dgr);
|
||||||
|
arr[1][1] := Cos(dgr);
|
||||||
|
|
||||||
|
kvec[0] := 1;
|
||||||
|
kvec[1] := k;
|
||||||
|
|
||||||
|
rkvec := LinearTrans(arr, kvec);
|
||||||
|
rk := rkvec[1] / rkvec[0]; // (a,b) => (1,b/a)
|
||||||
|
|
||||||
|
p1[0] := 0;
|
||||||
|
p1[1] := b;
|
||||||
|
|
||||||
|
pvec[0] := p1[0] - p[0];
|
||||||
|
pvec[1] := p1[1] - p[1];
|
||||||
|
|
||||||
|
rpvec := LinearTrans(arr, pvec);
|
||||||
|
|
||||||
|
rp1[0] := p[0] + rpvec[0];
|
||||||
|
rp1[1] := p[1] + rpvec[1];
|
||||||
|
|
||||||
|
result[0] := rk;
|
||||||
|
result[1] := rp1[1] - rk * rp1[0];
|
||||||
|
|
||||||
|
RotateLine := result;
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
line, p, result: array[0..1] of Real;
|
||||||
|
dgr: Real;
|
||||||
|
begin
|
||||||
|
line[0] := 3;
|
||||||
|
line[1] := 4;
|
||||||
|
|
||||||
|
p[0] := 2;
|
||||||
|
p[1] := 1;
|
||||||
|
|
||||||
|
dgr := Pi / 4;
|
||||||
|
|
||||||
|
result := RotateLine(line, p, dgr);
|
||||||
|
|
||||||
|
WriteLn('Rotated line: k=', result[0]:0:6, ', b=', result[1]:0:6);
|
||||||
|
end.
|
42
transform/rotate.py
Normal file
42
transform/rotate.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import math
|
||||||
|
from trans import linear_trans
|
||||||
|
|
||||||
|
def rotate_point(p1:list[float],p2:list[float],dgr:float) -> list[float]:
|
||||||
|
'''
|
||||||
|
Rotate p1 with p2 for dgr.
|
||||||
|
dgr measured in radians.
|
||||||
|
'''
|
||||||
|
arr = [
|
||||||
|
[math.cos(dgr),-math.sin(dgr)],
|
||||||
|
[math.sin(dgr), math.cos(dgr)]
|
||||||
|
]
|
||||||
|
vec = [p1[0]-p2[0],p1[1]-p2[1]]
|
||||||
|
rvec = linear_trans(arr,vec)
|
||||||
|
return [p2[0]+rvec[0], p2[1]+rvec[1]]
|
||||||
|
|
||||||
|
def rotate_line(line,p,dgr):
|
||||||
|
'''
|
||||||
|
Rotate y=kx+b with p for dgr.
|
||||||
|
dgr measured in radians.
|
||||||
|
@param line:
|
||||||
|
tuple[k, b] => y = kx + b
|
||||||
|
|
||||||
|
'''
|
||||||
|
k,b = line
|
||||||
|
arr = [
|
||||||
|
[math.cos(dgr),-math.sin(dgr)],
|
||||||
|
[math.sin(dgr), math.cos(dgr)]
|
||||||
|
]
|
||||||
|
vec = [1, k]
|
||||||
|
rvec = linear_trans(arr,vec)
|
||||||
|
rk = rvec[1]/rvec[0] # (a,b) => (1,b/a)
|
||||||
|
|
||||||
|
p1 = [0,b]
|
||||||
|
rp1 = rotate_point(p1,p,dgr)
|
||||||
|
|
||||||
|
return [rk,rp1[1]-rk*rp1[0]]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print(rotate_line((3,4),(2,1),math.pi/4))
|
32
transform/rotate_single.py
Normal file
32
transform/rotate_single.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import math
|
||||||
|
|
||||||
|
def linear_trans(arr,x):
|
||||||
|
return [x[0]*arr[0][0]+x[1]*arr[0][1], x[0]*arr[1][0]+x[1]*arr[1][1]]
|
||||||
|
return [sum(map(lambda x: x[0]*x[1],zip(line,x))) for line in arr]
|
||||||
|
|
||||||
|
|
||||||
|
def rotate_line(line,p,dgr):
|
||||||
|
'''
|
||||||
|
Rotate y=kx+b with p for dgr.
|
||||||
|
dgr measured in radians.
|
||||||
|
@param line:
|
||||||
|
tuple[k, b] => y = kx + b
|
||||||
|
|
||||||
|
'''
|
||||||
|
k,b = line
|
||||||
|
arr = [
|
||||||
|
[math.cos(dgr),-math.sin(dgr)],
|
||||||
|
[math.sin(dgr), math.cos(dgr)]
|
||||||
|
]
|
||||||
|
kvec = [1, k]
|
||||||
|
rkvec = linear_trans(arr,kvec)
|
||||||
|
rk = rkvec[1]/rkvec[0] # (a,b) => (1,b/a)
|
||||||
|
|
||||||
|
p1 = [0,b]
|
||||||
|
pvec = [p1[0]-p[0],p1[1]-p[1]]
|
||||||
|
rpvec = linear_trans(arr,pvec)
|
||||||
|
rp1 = [p[0] + rpvec[0], p[1]+rpvec[1]]
|
||||||
|
|
||||||
|
return [rk,rp1[1]-rk*rp1[0]]
|
||||||
|
|
||||||
|
print(rotate_line((3,4),(2,1),math.pi/4))
|
42
transform/trans.py
Normal file
42
transform/trans.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
def linear_trans2d(arr:list[list[float]],x:list[float]) -> list[float]:
|
||||||
|
'''
|
||||||
|
@param arr:
|
||||||
|
[
|
||||||
|
[a,b],
|
||||||
|
[c,d]
|
||||||
|
]
|
||||||
|
|
||||||
|
@param x:
|
||||||
|
[x1,x2]
|
||||||
|
|
||||||
|
@return
|
||||||
|
arr times x
|
||||||
|
'''
|
||||||
|
return [x[0]*arr[0][0]+x[1]*arr[0][1], x[0]*arr[1][0]+x[1]*arr[1][1]]
|
||||||
|
|
||||||
|
def linear_trans(arr:list[list[float]],x:list[float]) -> list[float]:
|
||||||
|
if len(arr) != len(x):
|
||||||
|
raise ValueError("Shape must be same.")
|
||||||
|
return [sum(map(lambda x: x[0]*x[1],zip(line,x))) for line in arr]
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
def linear_trans_np(arr:np.ndarray,x:np.ndarray) -> np.ndarray:
|
||||||
|
if not arr.shape[0] == arr.shape[1] == x.shape[0]:
|
||||||
|
raise ValueError("Shape must be (k,k) and (k,)")
|
||||||
|
return np.array([np.sum(line * x) for line in arr])
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# check code with np
|
||||||
|
import numpy as np
|
||||||
|
np.random.seed()
|
||||||
|
|
||||||
|
for i in range(100):
|
||||||
|
arr = np.random.random_sample((4,4))
|
||||||
|
x = np.random.random_sample((4,))
|
||||||
|
|
||||||
|
ans = np.dot(arr,x)
|
||||||
|
out = linear_trans_np(arr,x)
|
||||||
|
# print(out)
|
||||||
|
# out = np.array(out)
|
||||||
|
assert np.all(np.abs(ans-out)<0.0001)
|
Reference in New Issue
Block a user