0

When using the bezier library, the Curve.plot() function returns an AxesSubplot object

nodes1 = np.array([[0.0, 0.0],[0.625, .75], [1.0, 1.0]])
curve1 = bezier.Curve(nodes1, degree=2)
ax = curve1.plot(num_pts=256)
print ax

returns an

AxesSubplot(0.125,0.11;0.775x0.77)

I know the typical way of creating a subplot is with

fig = pyplot.figure()
ax = fig.add_subplot(111)

but I can't find any documentation on adding an already created subplot to a figure.

I can display the subplot with plt.show() but can't access the figure. If I try to create a figure with plt.figure(), two different figures (in different windows) are displayed.

Community
  • 1
  • 1
user75811
  • 141
  • 1
  • 6
  • the answer to that other thread involves creating a method for plotting lists of data on an subplot; however, I don't have lists of data, I just have the AxesSubplot object because my data comes from the bezier library – user75811 Oct 24 '17 at 03:30
  • I guess [this newly added answer](https://stackoverflow.com/a/46906599/4124317) is what you are looking for. However, it isn't actually too clear why you want to add the axes to a different figure at all, since it already is created within a figure that you can use. If you want to update your question to make that clear, it could potentially be answered. – ImportanceOfBeingErnest Oct 24 '17 at 09:20
  • ... I read through the answers and thought that at least one of them showed how to add an existing axes object a figure - but I didn't actually try it. – wwii Oct 24 '17 at 13:30
  • Do you have to create the *subplot* that way - by using `bezier.Curve.plot`? Do you need that `AxesSubplot` for any purpose other than *displaying* it in a figure? – wwii Oct 24 '17 at 14:04
  • @wwii if you are refering to [this question](https://stackoverflow.com/questions/6309472/matplotlib-can-i-create-axessubplot-objects-then-add-them-to-a-figure-instance), then yes there is an answer which tells you how to add an axes to another figure, but it is years old an not working in any newer matplotlib version. That is why I added an answer which is currently working. I am however completely with you that the approach of moving axes around is most probably not the way to tackle the problem from this question here. – ImportanceOfBeingErnest Oct 24 '17 at 15:58

3 Answers3

1

If the aim is to plot a curve to an existing axes ax, use the ax argument of the plotting function, bezier.Curve.plot(..., ax):

nodes1 = np.array([[0.0, 0.0],[0.625, .75], [1.0, 1.0]])
curve1 = bezier.Curve(nodes1, degree=2)

# create axes with matplotlib
fig, ax = plt.subplots()

# plot curve to existing axes
curve1.plot(num_pts=256, ax=ax)

Alternatively, if you have problems using the bezier package, creating a Bezier curve is not actually that hard. So you may just do it manually:

import numpy as np
from scipy.special import binom
import matplotlib.pyplot as plt

bernstein = lambda n, k, t: binom(n,k)* t**k * (1.-t)**(n-k)

def bezier(points, num=200):
    N = len(points)
    t = np.linspace(0, 1, num=num)
    curve = np.zeros((num, 2))
    for i in range(N):
        curve += np.outer(bernstein(N - 1, i, t), points[i])
    return curve


nodes1 = np.array([[0.0, 0.0],[0.625, .75], [1.0, 1.0]])
curve1 = bezier(nodes1, num=256)

fig, ax = plt.subplots()

ax.plot(curve1[:,0], curve1[:,1])

plt.show()

enter image description here

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
0

On many Python third party libraries (including matplotlib), you can look at the source and see what is going on behind the scenes and often you can use that as a guide for what you want to do - maybe even an opportunity for a subclass to implement your customization or. bezier.Curve.plot source is pretty straightforward and if your intent is to just plot the curve you can use its code, in your own (bezier.Curve.evaluate_multi returns numpy.ndarray: The points on the curve. As a two dimensional NumPy array, with the rows corresponding to each *s* value and the columns to the dimension.

nodes1 = np.array([[0.0, 0.0],[0.625, .75], [1.0, 1.0]])
curve1 = bezier.Curve(nodes1, degree=2)
# if you need to create x values.
s_vals = np.linspace(0.0, 1.0, num_pts)
points = curve1.evaluate_multi(s_vals)

Where the x values are points[:, 0] and the y values are points[:, 1]. Depending on what you actually need... (from pylab_examples example code: subplots_demo.py

f, (ax1, ax2) = plt.subplots(1, 2, sharey=True)
ax1.plot(points[:, 0], points[:, 1])
ax1.set_title('Sharing Y axis')
ax2.scatter(points[:, 0], points[:, 1])

I haven't actually tried this - lacking bezier on this machine.

wwii
  • 23,232
  • 7
  • 37
  • 77
0

First, to avoid another window to open you must "close" the plotting:

pyplot.close()

Then you can execute your

ax = curve1.plot(num_pts=256)

Now, I don't know why do you bring in subplot(111), which uses the whole window anyway (single figure). But if you still want to use a smaller subplot (e.g. 221), you can do the following:

pyplot.close()
fig = pyplot.figure()
#fig = pyplot.gcf(); # This will also do
ax = fig.add_subplot(221); curve.plot(num_pts=256,ax=ax)

(Note: I just tested both cases and they work. Only I used 2D nodes instead of 3D.)

Apostolos
  • 3,115
  • 25
  • 28