I am trying to implement this without success and I have to do this without using external modules numpy, etc. There are 3 modules in the app I am coding this, Python and C#, C++ but no other fancy libraries other than standard ones.
On a separate application, I used numpy's svd and it works very accurately. So I am using it to match my results. My method is PCA and everything is good up to this point. But after I calculate my symmetric covariance matrix, I don't know how to find the largest eigenvector.
The data set is always 3d points, x, y and z.
vector center;
for(point p in points):
center += p;
center /= points.count;
sumxx = 0;
sumxy = 0;
sumxz = 0;
sumyy = 0;
sumyz = 0;
sumzz = 0;
for(point p in points):
vector s = p - center;
sumxx += s.x * s.x;
sumxy += s.x * s.y;
sumxz += s.x * s.z;
sumyy += s.y * s.y;
sumyz += s.y * s.z;
sumzz += s.z * s.z;
matrix3 mat = invert(matrix3(sumxx, sumxy, sumxz, sumxy, sumyy, sumyz, sumxz, sumyz, sumzz));
vector n;
if (determinant(mat) > 0)
normal = find_largest_eigenvalue
Let us recap what you are asking, to clarify :
Find an eigenvector of a matrix mat
This eigenvector should be associated with the largest eigenvalue of the matrix
The matrix is the symmetric covariance matrix of a principal component analysis. In particular, it is symmetric.
Your matrix is square of size 3 by 3, as shown in your code by matrix3 mat = ... and confirmed in a (now deleted) comment.
Under these very specific circumstances, the following answer applies. However tmyklebu warns against numerical instability of this approach for some pathological matrices, typically when r is close to -1.
Alright, lets start with a bit of reading from wikipedia's page on Characteristic polynomials
In linear algebra, the characteristic polynomial of a square matrix is a polynomial, which is invariant under matrix similarity and has the eigenvalues as roots.
blah blah blah, let's skip directly to the 3x3 matrix section in the page on Eigenvalue algorithms.
If A is a 3×3 matrix, then its characteristic equation can be expressed as:
Followed a few lines later by (more or less) this pseudo-code, for symmetric matrices (which you say you have, if I'm not mistaken -- otherwise you might have complex eigenvalues) :
p1 = A(1,2)^2 + A(1,3)^2 + A(2,3)^2
if (p1 == 0)
% A is diagonal.
eig1 = A(1,1)
eig2 = A(2,2)
eig3 = A(3,3)
else
q = (A(1,1) + A(2,2) + A(3,3)) / 3
p2 = (A(1,1) - q)^2 + (A(2,2) - q)^2 + (A(3,3) - q)^2 + 2 * p1
p = sqrt(p2 / 6)
B = (1 / p) * (A - q * I) % I is the identity matrix
r = determinant(B) / 2
% In exact arithmetic for a symmetric matrix -1 <= r <= 1
% but computation error can leave it slightly outside this range.
if (r <= -1)
phi = pi / 3
elseif (r >= 1)
phi = 0
else
phi = acos(r) / 3
end
% the eigenvalues satisfy eig3 <= eig2 <= eig1
eig1 = q + 2 * p * cos(phi)
eig3 = q + 2 * p * cos(phi + (2*pi/3))
eig2 = 3 * q - eig1 - eig3 % since trace(A) = eig1 + eig2 + eig3
end
So you want max(eig1,eig2,eig3) in the first case, eig1 in the second case. Let us call e this largest eigenvalue.
For the eigenvector, you can now just solve (A-e*I)x=0
There are different algorithms for finding eigenvalues. Some work from smallest to largest, like QR; others work from largest to smallest, like power iteration or Jacobi-Davidson.
Maybe a switch of algorithm is what you want. Try power method and see if that helps.
https://scicomp.stackexchange.com/questions/1681/what-is-the-fastest-way-to-calculate-the-largest-eigenvalue-of-a-general-matrix
I am trying to flatten 3D array into 1D array for "chunk" system in my game. It's a 3D-block game and basically I want the chunk system to be almost identical to Minecraft's system (however, this isn't Minecraft clone by any measure). In my previous 2D-games I have accessed the flattened array with following algorithm:
Tiles[x + y * WIDTH]
However, this obviously doesn't work with 3D since it's missing the Z-axis. I have no idea how to implement this sort of algorithm in 3D-space. Width, height and depth are all constants (and width is just as large as height).
Is it just x + y*WIDTH + Z*DEPTH ? I am pretty bad with math and I am just beginning 3D-programming so I am pretty lost :|
PS. The reason for this is that I am looping and getting stuff by index from it quite a lot. I know that 1D arrays are faster than multi-dimensional arrays (for reasons I cant remember :P ). Even though this may not be necessary, I want as good performance as possible :)
Here is a solution in Java that gives you both:
from 3D to 1D
from 1D to 3D
Below is a graphical illustration of the path I chose to traverse the 3D matrix, the cells are numbered in their traversal order:
Conversion functions:
public int to1D( int x, int y, int z ) {
return (z * xMax * yMax) + (y * xMax) + x;
}
public int[] to3D( int idx ) {
final int z = idx / (xMax * yMax);
idx -= (z * xMax * yMax);
final int y = idx / xMax;
final int x = idx % xMax;
return new int[]{ x, y, z };
}
The algorithm is mostly the same. If you have a 3D array Original[HEIGHT, WIDTH, DEPTH] then you could turn it into Flat[HEIGHT * WIDTH * DEPTH] by
Flat[x + WIDTH * (y + DEPTH * z)] = Original[x, y, z]
As an aside, you should prefer arrays of arrays over multi-dimensional arrays in .NET. The performance differences are significant
I think the above needs a little correction. Lets say you have a HEIGHT of 10, and a WIDTH of 90, single dimensional array will be 900. By the above logic, if you are at the last element on the array 9 + 89*89, obviously this is greater than 900. The correct algorithm is:
Flat[x + HEIGHT* (y + WIDTH* z)] = Original[x, y, z], assuming Original[HEIGHT,WIDTH,DEPTH]
Ironically if you the HEIGHT>WIDTH you will not experience an overflow, just complete bonkers results ;)
x + y*WIDTH + Z*WIDTH*DEPTH. Visualize it as a rectangular solid: first you traverse along x, then each y is a "line" width steps long, and each z is a "plane" WIDTH*DEPTH steps in area.
You're almost there. You need to multiply Z by WIDTH and DEPTH:
Tiles[x + y*WIDTH + Z*WIDTH*DEPTH] = elements[x][y][z]; // or elements[x,y,z]
TL;DR
The correct answer can be written various ways, but I like it best when it can be written in a way that is very easy to understand and visualize. Here is the exact answer:
(width * height * z) + (width * y) + x
TS;DR
Visualize it:
someNumberToRepresentZ + someNumberToRepresentY + someNumberToRepresentX
someNumberToRepresentZ indicates which matrix we are on (depth). To know which matrix we are on, we have to know how big each matrix is. A matrix is 2d sized as width * height, simple. The question to ask is "how many matrices are before the matrix I'm on?" The answer is z:
someNumberToRepresentZ = width * height * z
someNumberToRepresentY indicates which row we are on (height). To know which row we are on, we have to know how big each row is: Each row is 1d, sized as width. The question to ask is "how many rows are before the row I'm on?". The answer is y:
someNumberToRepresentY = width * y
someNumberToRepresentX indicates which column we are on (width). To know which column we are on we simply use x:
someNumberToRepresentX = x
Our visualization then of
someNumberToRepresentZ + someNumberToRepresentY + someNumberToRepresentX
Becomes
(width * height * z) + (width * y) + x
The forward and reverse transforms of Samuel Kerrien above are almost correct. A more concise (R-based) transformation maps are included below with an example (the "a %% b" is the modulo operator representing the remainder of the division of a by b):
dx=5; dy=6; dz=7 # dimensions
x1=1; y1=2; z1=3 # 3D point example
I = dx*dy*z1+dx*y1+x1; I # corresponding 2D index
# [1] 101
x= I %% dx; x # inverse transform recovering the x index
# [1] 1
y = ((I - x)/dx) %% dy; y # inverse transform recovering the y index
# [1] 2
z= (I-x -dx*y)/(dx*dy); z # inverse transform recovering the z index
# [1] 3
Mind the division (/) and module (%%) operators.
The correct Algorithm is:
Flat[ x * height * depth + y * depth + z ] = elements[x][y][z]
where [WIDTH][HEIGHT][DEPTH]
To better understand description of 3D array in 1D array would be ( I guess Depth in best answer is meant Y size)
IndexArray = x + y * InSizeX + z * InSizeX * InSizeY;
IndexArray = x + InSizeX * (y + z * InSizeY);
m[x][y][z] = data[xYZ + yZ + z]
x-picture:
0-YZ
.
.
x-YZ
y-picture
0-Z
.
.
.
y-Z
summing up, it should be : targetX*YZ + targetY*Z + targetZ
In case, somebody is interested to flatten an nD (2D, 3D, 4D, ...) array to 1D, I wrote the below code. For example, if the size of the array in different dimensions is stored in the sizes array:
# pseudo code
sizes = {size_x, size_y, size_z,...};
This recursive function gives you the series of {1, size_x, size_x*size_y, size_x*size_y*size_z, ...}
// i: number of the term
public int GetCoeff(int i){
if (i==0)
return 1;
return sizes[i-1]*GetCoeff(i-1);
}
So, we have to multiply nD indexes by their corresponding series term and sum them to get {ix + iy*size_x + iz*size_x*size_y, ...}:
// indexNd: {ix, iy, iz, ...}
public int GetIndex1d(int[] indexNd){
int sum =0;
for (var i=0; i<indexNd.Length;i++)
sum += indexNd[i]*GetCoeff(i);
return sum;
}
In this code I assumed, the nD array is contiguous in memory along firstly x, then y, z, ... . So probably you call your array-like arr[z,y,x]. But, if you call them the other way, arr[x,y,z] then z is the fastest index and we like to calculate iz + iy*size_z + ix* size_z*size_y. In this case, the below function gives us the series {1, size_z, size_z*size_y, ...}:
// Dims is dimension of array, like 3 for 3D
public int GetReverseCoeff(int i){
if (i==0)
return 1;
return sizes[Dims-i]*GetReverseCoeff(i-1);
}
The coefficients are stored in the right order:
public void SetCoeffs(){
for (int i=0;i<Dims;i++)
coeffs[Dims-i-1] = GetReverseCoeff(i);
}
The 1D index is calculated the same as before except coeffs array is used:
// indexNd: {ix, iy, iz, ...}
public int GetIndex1d(int[] indexNd){
int sum =0;
for (var i=0; i<indexNd.Length;i++)
sum += indexNd[i]*coeffs[i];
return sum;
}
Samuel Kerrien's answer to python :
def to1D(crds,dims):
x,y,z=crds
xMax,yMax,zMax=dims
return (z * xMax * yMax) + (y * xMax) + x
def to3D(idx,dims):
xMax,yMax,zMax=dims
z = idx // (xMax * yMax)
idx -= (z * xMax * yMax)
y = idx // xMax
x = idx % xMax
return x, y, z
I have a set of points. I want to separate them into 2 distinct sets. To do this, I choose two points (a and b) and draw an imaginary line between them. Now I want to have all points that are left from this line in one set and those that are right from this line in the other set.
How can I tell for any given point z whether it is in the left or in the right set? I tried to calculate the angle between a-z-b – angles smaller than 180 are on the right hand side, greater than 180 on the left hand side – but because of the definition of ArcCos, the calculated angles are always smaller than 180°. Is there a formula to calculate angles greater than 180° (or any other formula to chose right or left side)?
Try this code which makes use of a cross product:
public bool isLeft(Point a, Point b, Point c){
return ((b.X - a.X)*(c.Y - a.Y) - (b.Y - a.Y)*(c.X - a.X)) > 0;
}
Where a = line point 1; b = line point 2; c = point to check against.
If the formula is equal to 0, the points are colinear.
If the line is horizontal, then this returns true if the point is above the line.
Use the sign of the determinant of vectors (AB,AM), where M(X,Y) is the query point:
position = sign((Bx - Ax) * (Y - Ay) - (By - Ay) * (X - Ax))
It is 0 on the line, and +1 on one side, -1 on the other side.
You look at the sign of the determinant of
| x2-x1 x3-x1 |
| y2-y1 y3-y1 |
It will be positive for points on one side, and negative on the other (and zero for points on the line itself).
The vector (y1 - y2, x2 - x1) is perpendicular to the line, and always pointing right (or always pointing left, if you plane orientation is different from mine).
You can then compute the dot product of that vector and (x3 - x1, y3 - y1) to determine if the point lies on the same side of the line as the perpendicular vector (dot product > 0) or not.
Using the equation of the line ab, get the x-coordinate on the line at the same y-coordinate as the point to be sorted.
If point's x > line's x, the point is to the right of the line.
If point's
x < line's x, the point is to the left of the line.
If point's x == line's x, the point is on the line.
I implemented this in java and ran a unit test (source below). None of the above solutions work. This code passes the unit test. If anyone finds a unit test that does not pass, please let me know.
Code: NOTE: nearlyEqual(double,double) returns true if the two numbers are very close.
/*
* #return integer code for which side of the line ab c is on. 1 means
* left turn, -1 means right turn. Returns
* 0 if all three are on a line
*/
public static int findSide(
double ax, double ay,
double bx, double by,
double cx, double cy) {
if (nearlyEqual(bx-ax,0)) { // vertical line
if (cx < bx) {
return by > ay ? 1 : -1;
}
if (cx > bx) {
return by > ay ? -1 : 1;
}
return 0;
}
if (nearlyEqual(by-ay,0)) { // horizontal line
if (cy < by) {
return bx > ax ? -1 : 1;
}
if (cy > by) {
return bx > ax ? 1 : -1;
}
return 0;
}
double slope = (by - ay) / (bx - ax);
double yIntercept = ay - ax * slope;
double cSolution = (slope*cx) + yIntercept;
if (slope != 0) {
if (cy > cSolution) {
return bx > ax ? 1 : -1;
}
if (cy < cSolution) {
return bx > ax ? -1 : 1;
}
return 0;
}
return 0;
}
Here's the unit test:
#Test public void testFindSide() {
assertTrue("1", 1 == Utility.findSide(1, 0, 0, 0, -1, -1));
assertTrue("1.1", 1 == Utility.findSide(25, 0, 0, 0, -1, -14));
assertTrue("1.2", 1 == Utility.findSide(25, 20, 0, 20, -1, 6));
assertTrue("1.3", 1 == Utility.findSide(24, 20, -1, 20, -2, 6));
assertTrue("-1", -1 == Utility.findSide(1, 0, 0, 0, 1, 1));
assertTrue("-1.1", -1 == Utility.findSide(12, 0, 0, 0, 2, 1));
assertTrue("-1.2", -1 == Utility.findSide(-25, 0, 0, 0, -1, -14));
assertTrue("-1.3", -1 == Utility.findSide(1, 0.5, 0, 0, 1, 1));
assertTrue("2.1", -1 == Utility.findSide(0,5, 1,10, 10,20));
assertTrue("2.2", 1 == Utility.findSide(0,9.1, 1,10, 10,20));
assertTrue("2.3", -1 == Utility.findSide(0,5, 1,10, 20,10));
assertTrue("2.4", -1 == Utility.findSide(0,9.1, 1,10, 20,10));
assertTrue("vertical 1", 1 == Utility.findSide(1,1, 1,10, 0,0));
assertTrue("vertical 2", -1 == Utility.findSide(1,10, 1,1, 0,0));
assertTrue("vertical 3", -1 == Utility.findSide(1,1, 1,10, 5,0));
assertTrue("vertical 3", 1 == Utility.findSide(1,10, 1,1, 5,0));
assertTrue("horizontal 1", 1 == Utility.findSide(1,-1, 10,-1, 0,0));
assertTrue("horizontal 2", -1 == Utility.findSide(10,-1, 1,-1, 0,0));
assertTrue("horizontal 3", -1 == Utility.findSide(1,-1, 10,-1, 0,-9));
assertTrue("horizontal 4", 1 == Utility.findSide(10,-1, 1,-1, 0,-9));
assertTrue("positive slope 1", 1 == Utility.findSide(0,0, 10,10, 1,2));
assertTrue("positive slope 2", -1 == Utility.findSide(10,10, 0,0, 1,2));
assertTrue("positive slope 3", -1 == Utility.findSide(0,0, 10,10, 1,0));
assertTrue("positive slope 4", 1 == Utility.findSide(10,10, 0,0, 1,0));
assertTrue("negative slope 1", -1 == Utility.findSide(0,0, -10,10, 1,2));
assertTrue("negative slope 2", -1 == Utility.findSide(0,0, -10,10, 1,2));
assertTrue("negative slope 3", 1 == Utility.findSide(0,0, -10,10, -1,-2));
assertTrue("negative slope 4", -1 == Utility.findSide(-10,10, 0,0, -1,-2));
assertTrue("0", 0 == Utility.findSide(1, 0, 0, 0, -1, 0));
assertTrue("1", 0 == Utility.findSide(0,0, 0, 0, 0, 0));
assertTrue("2", 0 == Utility.findSide(0,0, 0,1, 0,2));
assertTrue("3", 0 == Utility.findSide(0,0, 2,0, 1,0));
assertTrue("4", 0 == Utility.findSide(1, -2, 0, 0, -1, 2));
}
First check if you have a vertical line:
if (x2-x1) == 0
if x3 < x2
it's on the left
if x3 > x2
it's on the right
else
it's on the line
Then, calculate the slope: m = (y2-y1)/(x2-x1)
Then, create an equation of the line using point slope form: y - y1 = m*(x-x1) + y1. For the sake of my explanation, simplify it to slope-intercept form (not necessary in your algorithm): y = mx+b.
Now plug in (x3, y3) for x and y. Here is some pseudocode detailing what should happen:
if m > 0
if y3 > m*x3 + b
it's on the left
else if y3 < m*x3 + b
it's on the right
else
it's on the line
else if m < 0
if y3 < m*x3 + b
it's on the left
if y3 > m*x3+b
it's on the right
else
it's on the line
else
horizontal line; up to you what you do
I wanted to provide with a solution inspired by physics.
Imagine a force applied along the line and you are measuring the torque of the force about the point. If the torque is positive (counterclockwise) then the point is to the "left" of the line, but if the torque is negative the point is the "right" of the line.
So if the force vector equals the span of the two points defining the line
fx = x_2 - x_1
fy = y_2 - y_1
you test for the side of a point (px,py) based on the sign of the following test
var torque = fx*(py-y_1)-fy*(px-x_1)
if torque>0 then
"point on left side"
else if torque <0 then
"point on right side"
else
"point on line"
end if
Assuming the points are (Ax,Ay) (Bx,By) and (Cx,Cy), you need to compute:
(Bx - Ax) * (Cy - Ay) - (By - Ay) * (Cx - Ax)
This will equal zero if the point C is on the line formed by points A and B, and will have a different sign depending on the side. Which side this is depends on the orientation of your (x,y) coordinates, but you can plug test values for A,B and C into this formula to determine whether negative values are to the left or to the right.
basically, I think that there is a solution which is much easier and straight forward, for any given polygon, lets say consist of four vertices(p1,p2,p3,p4), find the two extreme opposite vertices in the polygon, in another words, find the for example the most top left vertex (lets say p1) and the opposite vertex which is located at most bottom right (lets say ). Hence, given your testing point C(x,y), now you have to make double check between C and p1 and C and p4:
if cx > p1x AND cy > p1y ==> means that C is lower and to right of p1
next
if cx < p2x AND cy < p2y ==> means that C is upper and to left of p4
conclusion, C is inside the rectangle.
Thanks :)
#AVB's answer in ruby
det = Matrix[
[(x2 - x1), (x3 - x1)],
[(y2 - y1), (y3 - y1)]
].determinant
If det is positive its above, if negative its below. If 0, its on the line.
Here's a version, again using the cross product logic, written in Clojure.
(defn is-left? [line point]
(let [[[x1 y1] [x2 y2]] (sort line)
[x-pt y-pt] point]
(> (* (- x2 x1) (- y-pt y1)) (* (- y2 y1) (- x-pt x1)))))
Example usage:
(is-left? [[-3 -1] [3 1]] [0 10])
true
Which is to say that the point (0, 10) is to the left of the line determined by (-3, -1) and (3, 1).
NOTE: This implementation solves a problem that none of the others (so far) does! Order matters when giving the points that determine the line. I.e., it's a "directed line", in a certain sense. So with the above code, this invocation also produces the result of true:
(is-left? [[3 1] [-3 -1]] [0 10])
true
That's because of this snippet of code:
(sort line)
Finally, as with the other cross product based solutions, this solution returns a boolean, and does not give a third result for collinearity. But it will give a result that makes sense, e.g.:
(is-left? [[1 1] [3 1]] [10 1])
false
Issues with the existing solution:
While I found Eric Bainville's answer to be correct, I found it entirely inadequate to comprehend:
How can two vectors have a determinant? I thought that applied to matrices?
What is sign?
How do I convert two vectors into a matrix?
position = sign((Bx - Ax) * (Y - Ay) - (By - Ay) * (X - Ax))
What is Bx?
What is Y? Isn't Y meant to be a Vector, rather than a scalar?
Why is the solution correct - what is the reasoning behind it?
Moreover, my use case involved complex curves rather than a simple line, hence it requires a little re-jigging:
Reconstituted Answer
Point a = new Point3d(ax, ay, az); // point on line
Point b = new Point3d(bx, by, bz); // point on line
If you want to see whether your points are above/below a curve, then you would need to get the first derivative of the particular curve you are interested in - also known as the tangent to the point on the curve. If you can do so, then you can highlight your points of interest. Of course, if your curve is a line, then you just need the point of interest without the tangent. The tangent IS the line.
Vector3d lineVector = curve.GetFirstDerivative(a); // where "a" is a point on the curve. You may derive point b with a simple displacement calculation:
Point3d b = new Point3d(a.X, a.Y, a.Z).TransformBy(
Matrix3d.Displacement(curve.GetFirstDerivative(a))
);
Point m = new Point3d(mx, my, mz) // the point you are interested in.
The Solution:
return (b.X - a.X) * (m.Y - a.Y) - (b.Y - a.Y) * (m.X - a.X) < 0; // the answer
Works for me! See the proof in the photo above. Green bricks satisfy the condition, but the bricks outside were filtered out! In my use case - I only want the bricks that are touching the circle.
Theory behind the answer
I will return to explain this. Someday. Somehow...
An alternative way of getting a feel of solutions provided by netters is to understand a little geometry implications.
Let pqr=[P,Q,R] are points that forms a plane that is divided into 2 sides by line [P,R]. We are to find out if two points on pqr plane, A,B, are on the same side.
Any point T on pqr plane can be represented with 2 vectors: v = P-Q and u = R-Q, as:
T' = T-Q = i * v + j * u
Now the geometry implications:
i+j =1: T on pr line
i+j <1: T on Sq
i+j >1: T on Snq
i+j =0: T = Q
i+j <0: T on Sq and beyond Q.
i+j: <0 0 <1 =1 >1
---------Q------[PR]--------- <== this is PQR plane
^
pr line
In general,
i+j is a measure of how far T is away from Q or line [P,R], and
the sign of i+j-1 implicates T's sideness.
The other geometry significances of i and j (not related to this solution) are:
i,j are the scalars for T in a new coordinate system where v,u are the new axes and Q is the new origin;
i, j can be seen as pulling force for P,R, respectively. The larger i, the farther T is away from R (larger pull from P).
The value of i,j can be obtained by solving the equations:
i*vx + j*ux = T'x
i*vy + j*uy = T'y
i*vz + j*uz = T'z
So we are given 2 points, A,B on the plane:
A = a1 * v + a2 * u
B = b1 * v + b2 * u
If A,B are on the same side, this will be true:
sign(a1+a2-1) = sign(b1+b2-1)
Note that this applies also to the question: Are A,B in the same side of plane [P,Q,R], in which:
T = i * P + j * Q + k * R
and i+j+k=1 implies that T is on the plane [P,Q,R] and the sign of i+j+k-1 implies its sideness. From this we have:
A = a1 * P + a2 * Q + a3 * R
B = b1 * P + b2 * Q + b3 * R
and A,B are on the same side of plane [P,Q,R] if
sign(a1+a2+a3-1) = sign(b1+b2+b3-1)
equation of line is y-y1 = m(x-x1)
here m is y2-y1 / x2-x1
now put m in equation and put condition on y < m(x-x1) + y1 then it is left side point
eg.
for i in rows:
for j in cols:
if j>m(i-a)+b:
image[i][j]=0
A(x1,y1) B(x2,y2) a line segment with length L=sqrt( (y2-y1)^2 + (x2-x1)^2 )
and a point M(x,y)
making a transformation of coordinates in order to be the point A the new start and B a point of the new X axis
we have the new coordinates of the point M
which are
newX = ((x-x1)(x2-x1)+(y-y1)(y2-y1)) / L
from (x-x1)*cos(t)+(y-y1)*sin(t) where cos(t)=(x2-x1)/L, sin(t)=(y2-y1)/L
newY = ((y-y1)(x2-x1)-(x-x1)(y2-y1)) / L
from (y-y1)*cos(t)-(x-x1)*sin(t)
because "left" is the side of axis X where the Y is positive, if the newY (which is the distance of M from AB) is positive, then it is on the left side of AB (the new X axis)
You may omit the division by L (allways positive), if you only want the sign