Check if 3D Point is inside square based pyramid If I have a square based pyramid of which I know every point (all 5), what is the algorithm to determine if a given point is inside that pyramid or not? I saw a similar question here Check if a point is inside a rectangular shaped area (3D)? and here How do I find if a point exists in a3D solid?. I tried to change the math a bit but didn't work out for me (maybe because I don't understand some parts correctly).
I have seen approaches with creating a normal to each plane (4 triangles + 1 square) and checking on which side of the plane the point lies... however I do not know the correct math for that.
visualization
If someone could help me with the exact math for that (preferably with explanation), it would really help.
Python "Example":
Input:
# Pyarmid Points
A = np.array([2, 2, 4]) # pyramid top
B = np.array([1, 1, 1]) 
C = np.array([1, 3, 3])
D = np.array([3, 3, 1])
E = np.array([3, 1, 1])

# Example points
point_inside = np.array([2, 2, 2])
point_outside = np.array([3, 3, 3])

Expectation:
def check_point_in_pyramid(A, B, C, D, E, Point):

    # math...
    
    if point_inside_pyramid:

        return true


    return false

So for point_inside the function return would be true and for the point_outside it would be false.
I do not need the python code, I just added it for clarification purposes what I need. The math is enough.
Edit after I read the answers:
I posted this question on stackoverflow too. Below are more deep level explanations and as far as I could tell a different approach to some extent. Definitely interesting. On stackoverflow are more lightweight answer for those looking. https://stackoverflow.com/questions/68641598/check-if-a-3d-point-is-in-a-square-based-pyramid-or-not
 A: Here's one way to do it.  Let the vertices of the pyramid be $v_0,v_1,v_2,v_3$.  The set of points inside the pyramid are precisely those points $x$ that can be expressed as a convex combination of the vertices:$$x=av_0+bv_1+cv_2+dv_3,\tag1$$ where
$$a,b,c,d\geq0,\ a+b+c+d=1$$
This assumes that "inside" includes points on the surface of the pyramid, including the edges and vertices.  If you want to exclude these points, change $a,b,c,d\geq0$ to $a,b,c,d>0$.
To make $(1)$ easier to deal with, subtract $v_0$ from both sides:
$$\begin{align}
x-v_0&=av_0+bv_1+cv_2+dv_3-(a+b+c+d)v_0\\
&=b(v_1-v_0)+c(v_2-v_0)+d(v_3-v_0)
\end{align}$$
which we rewrite as
$$x'=bv_1'+cv_2'+dv_3'$$
If you write this out in terms of coordinates, you'll see that it's a system of $3$ linear equations in the $3$ unknown $b,c,d$.  Solve for $b,c,d$.  $x$ is inside the pyramid if and only if $b,c,d\geq0$ and $b+c+d\leq1$.  If you want to exclude the faces, edges, and vertices from the "inside", change both these inequalities to be strict.
Since you are using python, you could use sympy.linsolve or numpy.linalg.solve to solve the system.  If the point is very near the surface, or on the surface, roundoff error might be a problem, as is usual with floating point calculations.  If the vertices have rational coordinates, then I believe that linsolve will give an exact solution.
I hope you can follow this.  Let me know if something isn't clear.
EDIT
I wrote a script to test that linsolve would give exact solutions for rational input, and as expected, this is true. Here's the script, in case it's of use to you.
import sympy as sp

b,c,d = sp.symbols('b,c,d')
rat = sp.Rational

vertices = sp.Matrix([
[rat(3,5), rat(2,7), rat(0,1)],
[rat(9,11), rat(-7,2), rat(0,1)],
[rat(12,7),rat(4,5), rat(0,1)],
[rat(9,1), rat(3,2), rat(3,1)]])

x = sp.Matrix([[rat(3,2), rat(5,4), rat(2,3)]])

def inside(vert, x):
    v0 = vert.row(0)
    M = sp.zeros(3,3)
    for k in range(3):
        M[k,:] = vert.row(k+1)-v0
    x = x - v0    
    system = (M.transpose(), x.transpose())
    y = list(sp.linsolve(system))[0]
    y = (1-sum(y),)+y
    answer = all(z >=0 for z in y)
    return answer, y
    
answer, y = inside(vertices, x)
print(answer, y)
# For testing
rows = [vertices.row(k) for k in range(4)]
total = sp.zeros(1,3)
for k in range(4):
    total += y[k]*rows[k]
assert total == x

A: Given $q$, a test point and the pyramid vertexes $p_k,\ k=1,\cdots,5$ take one of then, for instance $p_5$ and calculate:
$$
\delta_k = p_k-p_5,\ \ k=1,\cdots,4
$$
and then solve the linear programming problem
$$
\min\sum_{k=1}^4\lambda_k\ \ \text{s. t.}\ \ \cases{q-p_5=\sum_{k=1}^4\lambda_k\delta_k\\ \lambda_k\ge 0,\ \ k = 1,\cdots,4}
$$
now if $0\le \min\sum_{k=1}^4\lambda_k\le 1$ then $q$ is in the pyramid otherwise not.
Attached a python script which implements this procedure.
from scipy.optimize import linprog
import numpy as np
from random import uniform

pts = [[2, 2, 4],[1, 1, 1],[1, 3, 3],[3, 3, 1],[3, 1, 1]]
g = [uniform(1.,3.),uniform(1.,3.),uniform(1.,3.)]
print(g)


def inside(pts, g):
    p5 = pts[4]
    error = 0.000000001
    dp = []
    for i in range(4):
        dp.append(list(np.subtract(np.array(pts[i]),np.array(p5))))
    b = list(np.subtract(np.array(g),np.array(p5)))
    c = [1,1,1,1]
    A = np.transpose(dp)
    x0 = (0,0,0,0)
    x1 = (None,None,None,None)
    res=linprog(c,A_eq=A,b_eq=b,bounds=list(zip(x0,x1)))
    ##print(res)
    if (-error <= res.fun)  & (res.fun <= 1+error):
        return  True
    return  False

print(inside(pts, g))

