diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..fa65608
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+*.ipynb
diff --git a/index.html b/index.html
index 1fde96e..db6cb70 100644
--- a/index.html
+++ b/index.html
@@ -22,10 +22,10 @@
https://atar-wace-archive.github.io/
Maths page - specialist and methods ramblings
- https://atar-wace-archive.github.io/math
+ https://npc-strider.github.io/math
Programming ramblings - do not expect clean code here!
- https://atar-wace-archive.github.io/code
+ https://npc-strider.github.io/code
diff --git a/math/2.5d rotations.html b/math/2.5d rotations.html
new file mode 100644
index 0000000..78cfa10
--- /dev/null
+++ b/math/2.5d rotations.html
@@ -0,0 +1,420 @@
+
+
+
import math
+import numpy as np
+
+def rotate(theta):
+ return np.array([[cos(theta), -sin(theta)],
+ [sin(theta), cos(theta)]])
+
+T = [[0,0], ... ,[4,0]] #Our starting list of points T
+T_ = []
+
+C = [1,2]
+R = rotate(math.pi/6) #Rotation matrix when theta=pi/6. Store to R to save function calls
+
+for P in T:
+ P = np.array(P) #convert python list (A point P, like [0,0]) to numpy array
+ P_ = np.add( np.matmul(R,P), C ) #multiply with rotation matrix R (matmul), then add C
+ T_.append(P_) #Add our transformed point P_ to our transformed list, T_
+end
+# T_ is now our transformed matrix.
+
+
+ import math
+import numpy as np
+
+def quad(A,B): #A is our origin/fix point, B is our other point.
+ if B[0] > A[0] and B[1] > A[1]:
+ return 1 #First quadrant
+ elif B[0] < A[0] and B[1] > A[1]:
+ return 2 #Second quadrant
+ elif B[0] < A[0] and B[1] < A[1]:
+ return 3 #Third quadrant
+ else:
+ return 4 #Fourth quadrant
+ #By elimination. We could do another if but it's unnecessary
+ # elif B[0] < A[0] and B[1] > A[1]:
+
+def trajectory(distance, n):
+ # Here we create a list of points. n is the amount we create
+ # (higher n results in greater precision)
+ # Not going to include it here - uses bezier interpolation and stuff to create
+ # the illusion of a ballistic trajectory with gravity (not a simple quadratic function)
+ #
+ return points
+
+S = np.array([10,4]) #Silo position vector
+T = np.array([5204,954]) #Target position vector
+
+d = np.linalg.norm(T - S) #Get the distance: d = ((Tx-Sx)^2+(Ty-Sy)^2)^(0.5)
+m = (T[1]-S[1])/(T[0]-S[0]) #Gradient of line between target and silo.
+
+
+X = trajectory(d, 50) #50 is a constant for n. only affects trajectory precision
+ #X now contains a 'flat trajectory', a list of points which have the correct
+ #distance but the wrong angle and offset.
+ #It does not intersect with the target T.
+
+def shear(m, X):
+ q = quad(S,T) #Silo and target is passed to the quadrant finding function.
+ #q is the quadrant
+ if q == 1 or q == 4:
+ return np.array([[1,0],
+ [m,1]]) #shear matrix.
+ else:
+ return np.array([[-1,0],
+ [m,-1]]) #shear matrix, but for quadrants 2 and 3 (negative x).
+ # AN easier way to do this would be to just compare S[0] > T[0]. Forget about the quadrant stuff.
+ # because we only need to know if it's in the negative or positive x.
+
+
+
+SHEAR = shear(m, X) #we get the shear matrix, which the function returns
+
+P_ = np.matmul(SHEAR, X[(0,-1),]) #first, take a slice of the array X to obtain the first (P1)
+ # and last (P2) points. Then multiply this new 2x2 matrix
+ # containing P1 and P2 by the shear matrix
+ # to get P_, which contains P'1 and P'2
+
+d_ = np.linalg.norm(P_[1] - P_[0]) #adjusted distance
+s = d/d_ #scale factor
+
+X_ = s * np.matmul(SHEAR, X) + S # shear, then scale every point by s.
+ # Then add S, the silo position, to each position to yield the
+ # correct positions
+# X_ (X') is now a numpy array containing the shifted position vectors
+# that have been transformed through the 2.5d rotation.
+# The trajectory will still look 'realistic', not curving to the side but still
+# 'visually correct' and will be functionally correct in that it
+# starts at silo S and ends at target T.
+
+