1

I have plotted curve created by a list with several values. How to find out the x-coordinate that correspond with y-coordinate 0.04400918? This value is not exactly included in the list that describes the curve. Thank you very much.

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D                 # 3d graph
from mpl_toolkits.mplot3d import proj3d                 # 3d graph
import matplotlib.pylab as pl
fig=pl.figure()
ax = Axes3D(fig)
x=[0.02554897, 0.02587839, 0.02623991, 0.02663096, 0.02704882, 0.02749103, 0.02795535, 0.02844018, 0.02894404, 0.02946527, 0.03000235] 
y=[0.04739086, 0.0460989,  0.04481555, 0.04354088, 0.04227474, 0.04101689, 0.03976702, 0.03852497, 0.03729052, 0.0360633,  0.03484293] 
z=[1.05764017e-18, 1.57788964e-18, 2.00281370e-18, 2.40500994e-18, 2.80239565e-18, 3.19420769e-18, 3.58001701e-18, 3.96024361e-18, 4.33484911e-18, 4.70364652e-18, 5.06672528e-18] 
y_point=0.04400918 
ax.plot3D(x,y,z)
plt.show()
Alex
  • 347
  • 1
  • 10

1 Answers1

1

Here is a specific resolution for your problem.

Some works have already been done for solving line-plane equation. This topic explains how to solve it. Even better, this snippet implements a solution.

For now, we only need to adapt it to our problem.

  • The first step is to find all the time the line is crossing the plan. To do that, we will iterate over the y dataset and collect all consecutive values when y_point is between them:
lines = []
for i in range(len(y) - 1):
    if y[i] >= y_point and y_point >= y[i+1]:
        lines.append([[x[i], y[i], z[i]], [x[i+1], y[i+1], z[i+1]]])
  • Then, for all of these lines, we will solve the intersection equation with the plane. We will use the function provided in sources above.

  • Finally, we will plot the results


Full code:

# Modules
import numpy as np
import matplotlib.pyplot as plt

# Data
x = [0.02554897, 0.02587839, 0.02623991, 0.02663096, 0.02704882, 0.02749103, 0.02795535, 0.02844018, 0.02894404, 0.02946527, 0.03000235] 
y = [0.04739086, 0.0460989,  0.04481555, 0.04354088, 0.04227474, 0.04101689, 0.03976702, 0.03852497, 0.03729052, 0.0360633,  0.03484293] 
z = [1.05764017e-18, 1.57788964e-18, 2.00281370e-18, 2.40500994e-18, 2.80239565e-18, 3.19420769e-18, 3.58001701e-18, 3.96024361e-18, 4.33484911e-18, 4.70364652e-18, 5.06672528e-18] 


y_point = 0.04400918


# Source: https://rosettacode.org/wiki/Find_the_intersection_of_a_line_with_a_plane#Python
# Resolve intersection
def LinePlaneCollision(planeNormal, planePoint, rayDirection, rayPoint, epsilon=1e-6):
    ndotu = planeNormal.dot(rayDirection)
    if abs(ndotu) < epsilon:
        raise RuntimeError("no intersection or line is within plane")

    w = rayPoint - planePoint
    si = -planeNormal.dot(w) / ndotu
    Psi = w + si * rayDirection + planePoint
    return Psi

# For all line, apply the solving process
def solveAllPoints(lines, y_point):
    collision_points = []
    for line in lines:
        # Define plane
        planeNormal = np.array([0, 1, 0])       # Plane normal (e.g. y vector)
        planePoint = np.array([0, y_point, 0])  # Any point on the plane
        # Define ray
        rayDirection = line[1] - line[0]        # Line direction
        rayPoint = line[0]                      # Any point of the line
        # Append point
        collision_points.append(LinePlaneCollision(planeNormal, planePoint, rayDirection, rayPoint))
    return collision_points

# Find all consecutive Y points crossing the plane.
# This function is only working for the given problem (intersection of the line 
# with 1 plan defined by a normal vector = [0,1,0])
def getCrossingLines(y_point, x, y, z):
    lines = []
    for i in range(len(y) - 1):
        if y[i] >= y_point and y_point >= y[i+1]:
            lines.append([[x[i], y[i], z[i]], [x[i+1], y[i+1], z[i+1]]])
    return np.array(lines)

# Get coordinates for drawing our plane
# Related topic: https://stackoverflow.com/questions/53115276/matplotlib-how-to-draw-a-vertical-plane-in-3d-figure
def getXYZPlane(x, y, z):
    xs = np.linspace(min(x), max(x), 100)
    zs = np.linspace(min(z), max(z), 100)

    X, Z = np.meshgrid(xs, zs)
    Y = np.array([y_point for _ in X])
    return X, Y, Z

# Create plot
plt3d = plt.figure().gca(projection='3d')
ax = plt.gca()

# Draw data line
ax.plot3D(x,y,z)

# Plot plan
X, Y, Z = getXYZPlane(x, y, z)
ax.plot_surface(X, Y, Z)

# Draw crossing points (lines-planes)
lines = getCrossingLines(y_point, x, y , z)
for pt in solveAllPoints(lines, y_point):
    ax.scatter(pt[0], pt[1], pt[2], color='green')

plt.show()

Output enter image description here

Alexandre B.
  • 5,387
  • 2
  • 17
  • 40
  • 1
    Thank you very much for you great answer with the explanation. It helped me a lot. Could I ask you for this question? https://stackoverflow.com/questions/61027711/finding-point-as-a-origin-of-the-vector-that-is-prependicular-to-tangent – Alex Apr 04 '20 at 11:58
  • How to place the plane through a given point in such a way that it would be perpendicular with a tangent in a point on the curve, please? – Alex Apr 04 '20 at 15:23
  • 1
    As this is a new question, feel free to open a new topic – Alexandre B. Apr 04 '20 at 16:14
  • Here is it. Thank you https://stackoverflow.com/questions/61027711/finding-point-as-a-origin-of-the-vector-that-is-prependicular-to-tangent – Alex Apr 04 '20 at 16:38