Я столкнулся с проблемой при поиске векторов нормалей двух плоскостей и вычислении угла между этими двумя плоскостями. Я использую метод RANSAC для подгонки плоскостей к заданным точкам, но полученные мной векторы нормалей не кажутся перпендикулярными плоскостям. Кроме того, рассчитанный угол между двумя плоскостями не соответствует ожидаемому. Контекст
Я создал две идеальные матрицы. для обозначения двух перпендикулярных плоскостей. Вот матрицы:
import numpy as np
import plotly.graph_objs as go
import webbrowser
from sklearn.linear_model import RANSACRegressor
from sklearn.linear_model import LinearRegression
def fit_plane_and_plot(points, name):
# Extract x, y, z coordinates
X = points[:, :2] # (x, y) coordinates
z = points[:, 2] # z coordinate
# Use RANSAC to fit a plane
ransac = RANSACRegressor(LinearRegression())
ransac.fit(X, z)
# Coefficients of the plane: z = ax + by + c
a, b = ransac.estimator_.coef_
c = ransac.estimator_.intercept_
# Normal vector to the plane
normal_vector = np.array([a, b, -1])
# Choose a point on the plane (e.g., x = 3.5, y = 3.5)
x, y = 3.5, 3.5
z = a * x + b * y + c
point_on_plane = np.array([x, y, z])
# Normal line to the plane: r(t) = p0 + t * normal_vector
def normal_line(t):
return point_on_plane + t * normal_vector
# Test for some t values
t_values = np.linspace(0, 1, 50)
line_points = np.array([normal_line(t) for t in t_values])
# Create grids for plane visualization
x_range = np.linspace(0, 7, 10) # Range for x
y_range = np.linspace(0, 7, 10) # Range for y
x_grid, y_grid = np.meshgrid(x_range, y_range)
# Plane
z_plane = a * x_grid + b * y_grid + c
return x_grid, y_grid, z_plane, line_points, points, name, normal_vector
def plot_planes_and_normals(left_points, right_points):
# Use plotly for an interactive plot
fig = go.Figure()
# Add planes and normal vectors for left and right points
x_grid_left, y_grid_left, z_plane_left, line_points_left, points_left, name_left, normal_vector_left = fit_plane_and_plot(left_points, "Left Plane")
x_grid_right, y_grid_right, z_plane_right, line_points_right, points_right, name_right, normal_vector_right = fit_plane_and_plot(right_points, "Right Plane")
# Plot the planes
fig.add_trace(go.Surface(
x=x_grid_left,
y=y_grid_left,
z=z_plane_left,
colorscale='Blues',
opacity=0.5,
name=name_left
))
fig.add_trace(go.Surface(
x=x_grid_right,
y=y_grid_right,
z=z_plane_right,
colorscale='Reds',
opacity=0.5,
name=name_right
))
# Plot the normal lines
fig.add_trace(go.Scatter3d(
x=line_points_left[:, 0],
y=line_points_left[:, 1],
z=line_points_left[:, 2],
mode='lines',
line=dict(color='blue', width=2),
name='Left Normal Vector'
))
fig.add_trace(go.Scatter3d(
x=line_points_right[:, 0],
y=line_points_right[:, 1],
z=line_points_right[:, 2],
mode='lines',
line=dict(color='red', width=2),
name='Right Normal Vector'
))
# Plot the points
fig.add_trace(go.Scatter3d(
x=points_left[:, 0],
y=points_left[:, 1],
z=points_left[:, 2],
mode='markers',
marker=dict(color='green', size=4),
name='Left Points'
))
fig.add_trace(go.Scatter3d(
x=points_right[:, 0],
y=points_right[:, 1],
z=points_right[:, 2],
mode='markers',
marker=dict(color='purple', size=4),
name='Right Points'
))
# Add labels and legend
fig.update_layout(scene=dict(
xaxis=dict(title='X'),
yaxis=dict(title='Y', range=[0, 7]), # Set Y-axis limits
zaxis=dict(title='Z')
), title='Left and Right Planes and Normal Vectors')
# Save the figure to an HTML file and open it in a browser
file_path = 'plot_superposition.html'
fig.write_html(file_path)
webbrowser.open(file_path)
# Calculate the orientation angles of the planes
def calculate_angles(normal_vector):
norm = np.linalg.norm(normal_vector)
alpha = np.arccos(normal_vector[0] / norm)
beta = np.arccos(normal_vector[1] / norm)
gamma = np.arccos(normal_vector[2] / norm)
return np.degrees(alpha), np.degrees(beta), np.degrees(gamma)
alpha_left, beta_left, gamma_left = calculate_angles(normal_vector_left)
alpha_right, beta_right, gamma_right = calculate_angles(normal_vector_right)
print(f"Angles for the left plane:")
print(f"Angle with x-axis (alpha): {alpha_left:.2f} degrees")
print(f"Angle with y-axis (beta): {beta_left:.2f} degrees")
print(f"Angle with z-axis (gamma): {gamma_left:.2f} degrees")
print(f"Angles for the right plane:")
print(f"Angle with x-axis (alpha): {alpha_right:.2f} degrees")
print(f"Angle with y-axis (beta): {beta_right:.2f} degrees")
print(f"Angle with z-axis (gamma): {gamma_right:.2f} degrees")
# Calculate the angle between the two planes
dot_product = np.dot(normal_vector_left, normal_vector_right)
norm_left = np.linalg.norm(normal_vector_left)
norm_right = np.linalg.norm(normal_vector_right)
cos_angle = dot_product / (norm_left * norm_right)
angle = np.arccos(np.clip(cos_angle, -1.0, 1.0))
angle_deg = np.degrees(angle)
print(f"Angle between the two planes: {angle_deg:.2f} degrees")
# Call the function to plot the planes and normal vectors
plot_planes_and_normals(left_points_measured, right_points_measured)
Проблема
Когда я рисую плоскости и векторы нормалей, я ожидаю, что векторы нормалей будут перпендикулярны самолеты. Однако построенные нормальные векторы не являются таковыми. Кроме того, расчетный угол между двумя плоскостями составляет около 170 градусов, тогда как я ожидаю угол в 90 градусов, поскольку плоскости должны быть перпендикулярны. Вопрос
Можете ли вы помочь мне понять, почему векторы нормалей не перпендикулярны плоскостям и почему рассчитанный угол не соответствует ожидаемому? Есть ли ошибка в моем методе расчета векторов нормалей или в расчете угла между плоскостями?
Пример
Я пробовал инвертировать матрица
Я столкнулся с проблемой при поиске векторов нормалей двух плоскостей и вычислении угла между этими двумя плоскостями. Я использую метод RANSAC для подгонки плоскостей к заданным точкам, но полученные мной векторы нормалей не кажутся перпендикулярными плоскостям. Кроме того, рассчитанный угол между двумя плоскостями не соответствует ожидаемому. [b]Контекст[/b] Я создал две идеальные матрицы. для обозначения двух перпендикулярных плоскостей. Вот матрицы: [code]left_points_measured = np.array([ [0.0, 0.0, 292.89321881], [0.0, 1.0, 352.06658487], [0.0, 2.0, 411.23995092], [1.0, 0.0, 292.89321881], [1.0, 1.0, 352.06658487], [1.0, 2.0, 411.23995092], [2.0, 0.0, 292.89321881], [2.0, 1.0, 352.06658487], [2.0, 2.0, 411.23995092], [3.0, 0.0, 292.89321881], [3.0, 1.0, 352.06658487], [3.0, 2.0, 411.23995092], [4.0, 0.0, 292.89321881], [4.0, 1.0, 352.06658487], [4.0, 2.0, 411.23995092], [5.0, 0.0, 292.89321881], [5.0, 1.0, 352.06658487], [5.0, 2.0, 411.23995092], [6.0, 0.0, 292.89321881], [6.0, 1.0, 352.06658487], [6.0, 2.0, 411.23995092], [7.0, 0.0, 292.89321881], [7.0, 1.0, 352.06658487], [7.0, 2.0, 411.23995092] ])
def fit_plane_and_plot(points, name): # Extract x, y, z coordinates X = points[:, :2] # (x, y) coordinates z = points[:, 2] # z coordinate
# Use RANSAC to fit a plane ransac = RANSACRegressor(LinearRegression()) ransac.fit(X, z)
# Coefficients of the plane: z = ax + by + c a, b = ransac.estimator_.coef_ c = ransac.estimator_.intercept_
# Normal vector to the plane normal_vector = np.array([a, b, -1])
# Choose a point on the plane (e.g., x = 3.5, y = 3.5) x, y = 3.5, 3.5 z = a * x + b * y + c point_on_plane = np.array([x, y, z])
# Normal line to the plane: r(t) = p0 + t * normal_vector def normal_line(t): return point_on_plane + t * normal_vector
# Test for some t values t_values = np.linspace(0, 1, 50) line_points = np.array([normal_line(t) for t in t_values])
# Create grids for plane visualization x_range = np.linspace(0, 7, 10) # Range for x y_range = np.linspace(0, 7, 10) # Range for y x_grid, y_grid = np.meshgrid(x_range, y_range)
# Add labels and legend fig.update_layout(scene=dict( xaxis=dict(title='X'), yaxis=dict(title='Y', range=[0, 7]), # Set Y-axis limits zaxis=dict(title='Z') ), title='Left and Right Planes and Normal Vectors')
# Save the figure to an HTML file and open it in a browser file_path = 'plot_superposition.html' fig.write_html(file_path) webbrowser.open(file_path)
print(f"Angles for the left plane:") print(f"Angle with x-axis (alpha): {alpha_left:.2f} degrees") print(f"Angle with y-axis (beta): {beta_left:.2f} degrees") print(f"Angle with z-axis (gamma): {gamma_left:.2f} degrees")
print(f"Angles for the right plane:") print(f"Angle with x-axis (alpha): {alpha_right:.2f} degrees") print(f"Angle with y-axis (beta): {beta_right:.2f} degrees") print(f"Angle with z-axis (gamma): {gamma_right:.2f} degrees")
# Calculate the angle between the two planes dot_product = np.dot(normal_vector_left, normal_vector_right) norm_left = np.linalg.norm(normal_vector_left) norm_right = np.linalg.norm(normal_vector_right) cos_angle = dot_product / (norm_left * norm_right) angle = np.arccos(np.clip(cos_angle, -1.0, 1.0)) angle_deg = np.degrees(angle)
print(f"Angle between the two planes: {angle_deg:.2f} degrees")
# Call the function to plot the planes and normal vectors plot_planes_and_normals(left_points_measured, right_points_measured) [/code] [b]Проблема[/b] Когда я рисую плоскости и векторы нормалей, я ожидаю, что векторы нормалей будут перпендикулярны самолеты. Однако построенные нормальные векторы не являются таковыми. Кроме того, расчетный угол между двумя плоскостями составляет около 170 градусов, тогда как я ожидаю угол в 90 градусов, поскольку плоскости должны быть перпендикулярны. [b]Вопрос[/b] Можете ли вы помочь мне понять, почему векторы нормалей не перпендикулярны плоскостям и почему рассчитанный угол не соответствует ожидаемому? Есть ли ошибка в моем методе расчета векторов нормалей или в расчете угла между плоскостями? Пример Я пробовал инвертировать матрица