Value range for fitted plane is not right
Closed this issue · 6 comments
Hey,
I'm a bit confused about the following:
plane = Plane.best_fit(points_down[inliers, :3])
min_ = np.min(points_down[inliers, :3], axis=0)
max_ = np.max(points_down[inliers, :3], axis=0)
points = Points(points_down[inliers, :3])
plot_3d( points.plotter(c='k', s=50, depthshade=False),
plane.plotter(alpha=0.2, lims_x=(min_[0], max_[0]), lims_y=(min_[1], max_[1])),
)
The output looks like:
It seems to fit the points correctly, but the calculated values defining the plane are not within the same range as the original ones. Am I missing something? The fitted plane is perpendicular to the z=0 plane. Maybe this causes meshgrid problems to calculate values for z?
Thanks in advance.
Hi @maxim0815,
I don't understand what this means:
the calculated values defining the plane are not within the same range as the original ones.
What do you mean by "the original ones"? There's only one plane.
Hey @ajhynes7,
thanks for the fast response.
With the original ones, I mean the points (black ones in the image). The fitted plane (blue one) looks good, but the area captured by the surface of the plane is not about the same size as the original points. I would have expected the surface of the plane to be about approximately the same size as the fitted points, due to the definition of the range (blue plane covers all the black points).
It's difficult for me to see the problem without access to your dataset. Could you post a minimal working example which includes points in the code? Or you could attach a CSV with your points data.
Sorry for the late reply.
Here are some example points:
points.csv
Minimal working example:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from skspatial.objects import Plane
df = pd.read_csv('points.csv', sep=',', header=None)
a = df.values
plane = Plane.best_fit(a)
fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")
ax.scatter(a[:,0],a[:,1],a[:,2])
lims_x = [np.min(a[:,0]), np.max(a[:,0])]
lims_y = [np.min(a[:,1]), np.max(a[:,1])]
plane.plot_3d(ax, lims_x=lims_x, lims_y=lims_y)
plt.show()
Results in the following plot:
The fitting is correct. The estimated normal does match the given points. It is only a visualization problem and I assume it is because of the way how numpy calculates its meshgrid and the reason that the estimated plane is (almost) orthogonal to the x and y plane.
Hi @maxim0815, I've looked into this now. The problem is due to the values provided for lims_x
and lims_y
.
From the docstring:
x and y limits of the plane. Tuple of form (min, max). The default is (-1, 1). The point on the plane is used as the origin.
The values in lims_x
and lims_y
aren't the actual boundaries of the plotted plane. They're added to the plane point (which in this case is the centroid of your points). So your calculation to get lims_x
and lims_y
doesn't give you the plot you were expecting. If you remove those kwargs from the call to plot_3d
, you'll get the plane in the right place.
I can see how this is confusing. I could rename those kwargs to offsets_x
and offsets_y
to make their meaning clearer. That would require a new major version release since it's a breaking change. Let me know what you think.