4

The normal vector is calculated with the cross product of two vectors on the plane, so it shoud be perpendicular to the plane. But as you can seein the plot the normal vector produced with quiver isn't perpendicular. Is the calculation of the plane wrong, my normal vector or the way i plot the normal vector?

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

points = [[3.2342, 1.8487, -1.8186],
           [2.9829, 1.6434, -1.8019],
           [3.4247, 1.5550, -1.8093]]

p0, p1, p2 = points
x0, y0, z0 = p0
x1, y1, z1 = p1
x2, y2, z2 = p2

ux, uy, uz = u = [x1-x0, y1-y0, z1-z0] #first vector
vx, vy, vz = v = [x2-x0, y2-y0, z2-z0] #sec vector

u_cross_v = [uy*vz-uz*vy, uz*vx-ux*vz, ux*vy-uy*vx] #cross product

point  = np.array(p1)
normal = np.array(u_cross_v)

d = -point.dot(normal)

print('plane equation:\n{:1.4f}x + {:1.4f}y + {:1.4f}z + {:1.4f} = 0'.format(normal[0], normal[1], normal[2], d))

xx, yy = np.meshgrid(range(10), range(10))

z = (-normal[0] * xx - normal[1] * yy - d) * 1. / normal[2]

# plot the surface
plt3d = plt.figure().gca(projection='3d')
plt3d.quiver(x0, y0, z0, normal[0], normal[1], normal[2], color="m")

plt3d.plot_surface(xx, yy, z)

plt3d.set_xlabel("X", color='red', size=18)
plt3d.set_ylabel("Y", color='green', size=18)
plt3d.set_zlabel("Z", color='b', size=18)
plt.show()

enter image description here

campy
  • 86
  • 1
  • 11
  • is that question solved? – Dorian Jul 24 '20 at 13:57
  • @Dorian nah, it was helpful but it still does not look perpendicular. I only needed the visulalization to verify my code (calculating some point distances in resprect to a plane). Now I am sure the calculations are correct even I am not able to visulaize it correctly. – campy Jul 28 '20 at 11:05
  • not sure if you understood correctly, but that IS the correct solution. your plane is very much aligned with the XY plane. If you chose other parameters you can see that. – Dorian Jul 28 '20 at 12:36

1 Answers1

3

Actually, your plot is 100% correct. The scale of your Z axis does not correspond to the same scale on X & Y axis. If you use a function to set the scale correct, you can see that:

...
plt3d.set_zlabel("Z", color='b', size=18)

# insert these lines
ax = plt.gca()
set_axis_equal(ax)

plt.show()

and the corresponding function from this post:

def set_axes_radius(ax, origin, radius):
    '''
        From StackOverflow question:
        https://stackoverflow.com/questions/13685386/
    '''
    ax.set_xlim3d([origin[0] - radius, origin[0] + radius])
    ax.set_ylim3d([origin[1] - radius, origin[1] + radius])
    ax.set_zlim3d([origin[2] - radius, origin[2] + radius])


def set_axes_equal(ax, zoom=1.):
    '''
        Make axes of 3D plot have equal scale so that spheres appear as spheres,
        cubes as cubes, etc..  This is one possible solution to Matplotlib's
        ax.set_aspect("equal") and ax.axis("equal") not working for 3D.
        input:
          ax:   a matplotlib axis, e.g., as output from plt.gca().

    '''

    limits = np.array([
        ax.get_xlim3d(),
        ax.get_ylim3d(),
        ax.get_zlim3d(),
    ])

    origin = np.mean(limits, axis=1)
    radius = 0.5 * np.max(np.abs(limits[:, 1] - limits[:, 0])) / zoom
    set_axes_radius(ax, origin, radius)
Dorian
  • 1,439
  • 1
  • 11
  • 26