Una simple solución de mínimos cuadrados debería ser suficiente.
La ecuación de un plano es: $ax + by + c = z$ . Así que establece matrices como esta con todos tus datos:
$$ \begin{bmatrix} x_0 & y_0 & 1 \\ x_1 & y_1 & 1 \\ &... \\ x_n & y_n & 1 \\ \end{bmatrix} \begin{bmatrix} a \\ b \\ c \end{bmatrix} = \begin{bmatrix} z_0 \\ z_1 \\ ... \\ z_n \end{bmatrix} $$ En otras palabras:
$$Ax = B$$
Ahora resuelve para $x$ que son sus coeficientes. Pero como (supongo) tienes más de 3 puntos, el sistema está sobredeterminado, así que necesitas usar la pseudoinversa de la izquierda: $A^+ = (A^T A)^{-1} A^T$ . Así que la respuesta es: $$ \begin{bmatrix} a \\ b \\ c \end{bmatrix} = (A^T A)^{-1} A^T B $$
Y aquí hay un sencillo código Python con un ejemplo:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
# These constants are to create random data for the sake of this example
N_POINTS = 10
TARGET_X_SLOPE = 2
TARGET_y_SLOPE = 3
TARGET_OFFSET = 5
EXTENTS = 5
NOISE = 5
# Create random data.
# In your solution, you would provide your own xs, ys, and zs data.
xs = [np.random.uniform(2*EXTENTS)-EXTENTS for i in range(N_POINTS)]
ys = [np.random.uniform(2*EXTENTS)-EXTENTS for i in range(N_POINTS)]
zs = []
for i in range(N_POINTS):
zs.append(xs[i]*TARGET_X_SLOPE + \
ys[i]*TARGET_y_SLOPE + \
TARGET_OFFSET + np.random.normal(scale=NOISE))
# plot raw data
plt.figure()
ax = plt.subplot(111, projection='3d')
ax.scatter(xs, ys, zs, color='b')
# do fit
tmp_A = []
tmp_b = []
for i in range(len(xs)):
tmp_A.append([xs[i], ys[i], 1])
tmp_b.append(zs[i])
b = np.matrix(tmp_b).T
A = np.matrix(tmp_A)
# Manual solution
fit = (A.T * A).I * A.T * b
errors = b - A * fit
residual = np.linalg.norm(errors)
# Or use Scipy
# from scipy.linalg import lstsq
# fit, residual, rnk, s = lstsq(A, b)
print("solution: %f x + %f y + %f = z" % (fit[0], fit[1], fit[2]))
print("errors: \n", errors)
print("residual:", residual)
# plot plane
xlim = ax.get_xlim()
ylim = ax.get_ylim()
X,Y = np.meshgrid(np.arange(xlim[0], xlim[1]),
np.arange(ylim[0], ylim[1]))
Z = np.zeros(X.shape)
for r in range(X.shape[0]):
for c in range(X.shape[1]):
Z[r,c] = fit[0] * X[r,c] + fit[1] * Y[r,c] + fit[2]
ax.plot_wireframe(X,Y,Z, color='k')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
plt.show()
5 votos
Hay mucho más que explicar. Hay muchas medidas diferentes para determinar lo bien que se ajusta un plano a unos datos determinados, y diferentes medidas dan lugar a diferentes planos de "mejor" ajuste. Así que será mejor que nos digas qué tienes en mente como medida de lo bien que se ajusta un plano a unos datos determinados.
0 votos
Lo siento, pero me gustaría poder decirte más. Pero sólo sé un poco. Digamos que el conjunto de Puntos que tengo (más de un centenar) ya se parecen a un plano, es decir, se visualizan como un plano pero no perfectamente. "Obtener el plano de simetría A ajustándolo al conjunto de puntos B.." Eso es todo lo que tengo que hacer. No dicen nada más.
1 votos
No había mencionado antes la parte de la simetría, ¿sabe a qué se refiere?
0 votos
El "plano de simetría" puede confundirte. Tengo este conjunto de puntos que representa el plano de simetría (pero podría ser cualquier plano), pero en realidad no conozco la ecuación de este plano (y la necesito). Así que supuse que la única manera de encontrar esta ecuación es encontrando el plano que mejor se ajusta dado este conjunto de puntos. Lo siento si no me estoy explicando bien.
5 votos
Veamos un problema más sencillo. Digamos que tienes un grupo de puntos en 2 dimensiones que casi se encuentran a lo largo de una línea, pero no del todo, y quieres encontrar la línea que mejor se ajusta a esos puntos. Podrías dibujar una línea, luego dibujar segmentos de línea verticales desde cada punto hasta la línea, y sumar las longitudes de todos esos segmentos de línea, y pedir la línea que haga esa suma lo más pequeña posible. Pero también puedes dibujar segmentos de línea horizontales, y podrías obtener una respuesta diferente al minimizar la suma de esas longitudes. O podrías dibujar segmentos de línea perpendiculares a la línea. Continúa...
2 votos
...En lugar de sumar las longitudes de los segmentos de la línea, podrías sumar los cuadrados de las longitudes - puede parecer una idea extraña, pero a menudo es una buena idea en este tipo de problemas. Así que tienes todas esas opciones, sólo para dibujar una línea en 2 dimensiones; hay incluso más opciones para un plano en 3. Por eso tienes que saber realmente a qué se refiere alguien cuando te pide que ajustes un plano a unos puntos.