简体   繁体   中英

Python, matplotlib. Plot a function between two points

I want to plot a function between 2 points using matplotlib. The similar problem, but for 3d case is without working answer: How to plot a function oriented on a local x axis matplotlib 3d?

I think it should work something like that:

import matplotlib.pyplot as plt
import math

def foo(x, L):
    # some polynomial on [0, L]
    return x**2  # usually it's more difficult


def magic(plt, foo, point1, point2):
    """
    Plot foo from point1 to point2
    :param plt: matplotlib.pyplot
    :param foo: function
    :param point1: tuple (x1, y1) or list [x1, y1]
    :param point2: tuple (x2, y2) or list [x2, y2]
    :return:
    """
    # do magic
    # create modified function along new local x' axis using points in initial x,y axis?
    # create new axis, rotate and move them?
    pass

x1, y1 = 1, 1  # first point coordinates
x2, y2 = 2, 2  # second point coordinates
dx = x1 - x2
dy = y1 - y2
# length, this ratio is always True in my case (see picture below)
L = math.sqrt(dx * dx + dy * dy)

ax, fig = plt.subplots()
magic(plt, foo, (x1,y1), (x2, y2))
plt.show()

Important: The length along a new axis does not change. If there is a function on [0, L] it means it will have the same domain (or 'length') after rotation/moving or representing it along a new axis.

Here is the image of what I'm trying to do

图片

There's no magic involved. Just a translation from (0,0) to (x1,y1) and a rotation by an angle defined by dx and dy. The sine of that angle is dy/L and the cosine dx/L. Using numpy arrays is both handy to write the function is a concise form as well as speeding up the calculations.

In the code below I changed the example function to make it more clear how the function is transformed. Also, the aspect ratio is set to 'equal'. Otherwise the rotated function would look distorted.

import matplotlib.pyplot as plt
import numpy as np

def foo(x):
    # some function on [0, L]
    return np.sin(x*20)/(x+1)

def function_on_new_axis(foo, point1, point2):
    """
    Plot foo from point1 to point2
    :param foo: function
    :param point1: tuple (x1, y1) or list [x1, y1]
    :param point2: tuple (x2, y2) or list [x2, y2]
    :return:
    """
    # create modified function along new local x' axis using points in initial x,y axis?
    # create new axis, rotate and move them?
    dx = x2 - x1
    dy = y2 - y1
    L = np.sqrt(dx * dx + dy * dy)
    XI = np.linspace(0, L, 500)  # initial coordinate system
    YI = foo(XI)
    s =  dy  / L  # sine of the rotation angle
    c =  dx  / L  # cosine of the rotation angle
    XM = c * XI - s * YI + x1  # modified coordinate system
    YM = s * XI + c * YI + y1
    plt.plot(XI, YI, color='crimson', alpha=0.3)
    plt.plot(XM, YM, color='crimson')
    plt.plot([x1, x2], [y1, y2], 'go')

x1, y1 = 1, 1  # first point coordinates
x2, y2 = 2, 3  # second point coordinates


fig, ax = plt.subplots()
function_on_new_axis(foo, (x1,y1), (x2, y2))
ax.axis('equal')  # equal aspect ratio between x and y axis to prevent that the function would look skewed
# show the axes at (0,0)
ax.spines['left'].set_position('zero')
ax.spines['right'].set_color('none')
ax.spines['bottom'].set_position('zero')
ax.spines['top'].set_color('none')
plt.show()

示例图

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM