I constantly use Plotly to do a quick prototyping and check of my code as I write a lot of algorithms that handle 3D point geometry. I never got to understand how go.Cone behaves as the results can be somehow unexpected with vector scaling arbitrarily.
Here is an example, I have a set of 4 points that I use to best fit a plane. Using the obtained plane normal vector and plane center point I derive the plane equation, which I then use to build the 3D surface simply as
# x, y, z are cartesian coordinates, i, j, k the vector components
plane = plane_from_points(points)
d = - plane[i] * plane[x] - plane[j] * plane[y] - plane[k] * plane[z]
a, b, c = plane[i], plane[j], plane[k]
x_plane = np.linspace(points.x.min(), points.x.max()+100, 50)
y_plane = np.linspace(points.y.min(), points.y.max()+100, 50)
x2d, y2d = np.meshgrid(x_plane, y_plane)
z2d = (-a * x2d - b * y2d - d) / c
which I then plot as
surf = go.Surface(x=x2d, y=y2d, z=z2d)
This works pretty well and the surface looks like the best-fit plane that I’m lookin for. HOWEVER when I try to plot also the plane normal vector as
vector = go.Cone(x=[plane[x]], y=[plane[y]], z=[plane[z]],
u=[plane[i]], v=[plane[j]], w=[plane[k]])
I get a vector that is anything but normal to the plane (see pictures, points used for the plane fitting are blue)
If I put the same point positions, plane equation, vector components in Geogebra I get the correct plot
I’m really puzzled about what I could be doing wrong…Is this related to the perspective which is somewhat distorted? But I guess if the vector is by definition normal it should appear so regardless of the perspective…
Here are the values used to draw the points
# Plane equation
0.963297 x + -0.268436 y + 0.000025 z + -17496.412266 = 0
# Plane center point
{18721.685261, 2004.602757, -1247.349811}
# Plane normal vector
(0.963297, -0.268436, 0.000025)
# Points used to best-fit the plane
{18745.833058, 2091.337311, -942.977098}
{18697.525409, 1917.880742, -956.077473}
{18695.080808, 1909.148370, -1554.346526}
{18748.301769, 2100.044606, -1535.998146}
Here is the complete code (simplified and without the part where I create the surface posted before)
mycolorscale = [[0, 'Blue'], [1, 'Blue']]
surf = go.Surface(x=x2d, y=y2d, z=z2d,
showscale=False, colorscale=mycolorscale, opacity=0.6)
scatter = go.Scatter3d(x = points.x , y = points.y, z = points.z, mode = 'markers')
vector = go.Cone(x=[plane[x]], y=[plane[y]], z=[plane[z]],
u=[plane[i]], v=[plane[j]], w=[plane[k]], showscale=False,
sizeref=20)
fig = go.Figure(data=[scatter2, surf, vector], layout=layout)
fig.show()