-3

In the while loop,the command "plt.plot(x,y,'*')" paints the trail of an object.SO there are many points painted in the axes.But i just want a moving point to discribe the trail.Details are in the "while loop" of following codes.

import matplotlib.pyplot as plt
import numpy as np
#just a dynamic painting
tolerance = 1e-1
radius = np.pi

# missile 1
x_m1, y_m1 = -np.pi, 0
v_m1 = 5

# missile 2
x_m2, y_m2 = 0, np.pi
v_m2 = v_m1
# missile 3
x_m3, y_m3 = np.pi, 0
v_m3 = v_m1
# missile 4
x_m4, y_m4 = 0, -np.pi
v_m4 = v_m1

plt.figure(figsize=(10, 10), dpi=80)
plt.title(" missile flight simulator ", fontsize=40)
plt.xlim(-4, 4)
plt.ylim(-4, 4)
#plt.xticks([])
#plt.yticks([])

# set spines
ax = plt.gca()
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data', 0))
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data', 0))


plt.annotate('missile start point', xy=(x_m1, y_m1),  xycoords='data',
             xytext=(+15, +15), textcoords='offset points', fontsize=12,
             arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.2"))

# alpha labels
for label in ax.get_xticklabels() + ax.get_yticklabels():
    label.set_fontsize(16)
    label.set_bbox(dict(facecolor='white', edgecolor='None', alpha=0.65))


class ob(object):
    """docstring for ob"""
    def __init__(self, x, y):
        self.x = x
        self.y = y


class missile(ob):
    """docstring for missile"""
    def __init__(self, x, y):
        super(missile, self).__init__(x, y)

    def forward(self, v, target):
        """docstring for forward"""
        if self.x < target.x:
            alpha = np.arctan((target.y - self.y) / (target.x - self.x))
        elif self.x > target.x:
            alpha = np.pi + np.arctan((target.y - self.y) / (target.x - self.x))
        elif self.x == target.x and self.y < target.y:
            alpha = np.pi / 2
        else:
            alpha = -np.pi / 2
        self.x = self.x + v * 0.01 * np.cos(alpha)
        self.y = self.y + v * 0.01 * np.sin(alpha)
        return self.x, self.y

    def distance(self, target):
        """docstring for distance"""
        return np.sqrt((self.x - target.x) ** 2 + (self.y - target.y) ** 2)


class target(ob):
    """docstring for target"""
    def __init__(self, x, y):
        super(target, self).__init__(x, y)

    def newposition(self, x, y):
        """docstring for newposition"""
        self.x = x
        self.y = y

m1 = missile(x_m1, y_m1)
m2 = missile(x_m2, y_m2)
m3 = missile(x_m3, y_m3)
m4 = missile(x_m4, y_m4)

while True: #details
#just a dynamic painting
    if m1.distance(m2) < tolerance or m1.distance(m3) < tolerance or m1.distance(m4) < tolerance:    #In the loop,many points are painted to discribe the trail    
        print "collision"
        plt.plot(x_m1, y_m1, 'o')
        plt.annotate('crash point', xy=(x_m1, y_m1),  xycoords='data',
                     xytext=(+15, +15), textcoords='offset points', fontsize=12,
                     arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.2"))
        plt.pause(0.1)
        plt.show()
        break
    elif m3.distance(m2) < tolerance or m3.distance(m4) < tolerance:
        print "collision"
        plt.plot(x_m3, y_m3, 'o')
        plt.annotate('crash point', xy=(x_m3, y_m3),  xycoords='data',
                     xytext=(+15, +15), textcoords='offset points', fontsize=12,
                     arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.2"))
        plt.pause(0.1)
        plt.show
        break
    x_m1, y_m1 = m1.forward(v_m1, m2)
    x_m2, y_m2 = m2.forward(v_m2, m3)
    x_m3, y_m3 = m3.forward(v_m3, m4)
    x_m4, y_m4 = m4.forward(v_m4, m1)
    #print alpha, beta
    plt.plot(x_m1, y_m1, 'bx', alpha=.5)
    plt.plot(x_m2, y_m2, 'k*', alpha=.5)
    plt.plot(x_m3, y_m3, 'r.', alpha=.5)
    plt.plot(x_m4, y_m4, 'gp', alpha=.5)
    plt.legend(("missile1", "missile2", "missile3", "missile4"), loc="upper left", prop={'size': 12})

    plt.pause(0.1)

Are there any resolution given?This programme just for a dynamic painting.Paint a moving point to show the track of an object.The point's coordinate get updated with its regular speed. In my codes,all points of the track are painted,but i only need one moving point.Just like an running car in the road,everytime you see one moving car in different place of the track.You can delete the "while" loop,if you could use other ways to achieve my expectation.

David
  • 35
  • 11
  • 1
    "Details are in the while loop" doesn't provide enough information for anyone to be able to assist you. What do you mean "i just want a moving point to discribe the trail"? Please boil down your problem to a [Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve) (keyword in **minimal** here) – Diziet Asahi Mar 06 '18 at 08:54
  • Paint a moving point to show the track of an object.The point's coordinate get updated with its regular speed. In my codes,all points of the track are painted,but i only need one moving point.Just like an running car in the road,everytime you see one moving car in different place of the track – David Mar 06 '18 at 13:12
  • You can delete the "while" loop,if you could use other ways to achieve my expectation. – David Mar 06 '18 at 13:16
  • There are two ways of producing an animation as shown e.g. [here](https://stackoverflow.com/questions/42722691/python-matplotlib-update-scatter-plot-from-a-function). Choose a method, stick to it and you should directly get the desired plot. It doesn't matter if you update your plot with a single point or multiple points. – ImportanceOfBeingErnest Mar 06 '18 at 20:14

1 Answers1

0

I'm still not sure I understood your question, but:

It looks like you've fallen into the same trap as 90% of people asking about animations and matplotlib, in that you are repeatedly calling plot() at each step of your iterations, thus creating new points (really, new Line2D objects) at each steps, instead of updating the properties of the existing one.

The general procedure for animations is to:

  1. create your figure and all the fixed elements that do not need to be updated
  2. create the artists that need to be updated, and keep a reference to them
  3. in your loop, update (instead of replacing or creating new artists) the properties of the artists created in the previous step.

Since you did not get my hint about creating a minimal working example, let me show that 99% of your code was useless and that your problem can be simplified and solved just like so:

import matplotlib.pyplot as plt
import numpy as np

plt.figure()
# create a placeholder artist object, and keep a reference to it
my_line, = plt.plot([], [], 'bx', alpha=.5)
plt.legend(["my line"], loc="upper left", prop={'size': 12})
plt.xlim([0, 10])
plt.ylim([0, 10])
i = 0

while True:
    # do whatever to get next coordinates
    i = (i + 1) % 10
    new_x, new_y = i, i
    # update artist
    my_line.set_data(new_x, new_y)
    plt.draw()
    plt.pause(0.1)

Finally, I will echo @ImportanceOfBeingErnest's comment and suggest you look into the FuncAnimation module to produce your animations, although the overall strategy remains exactly the same.

Diziet Asahi
  • 38,379
  • 7
  • 60
  • 75
  • Yeah,you completely get my point.This resolution is perfect for me. – David Mar 07 '18 at 01:45
  • When i turned to matplotlib helping document for resolution, the command "set_data" was always seen.But hardly i link it with my problem.Besides,i am very familiar to "plt.plot()".However,i have never thought creating an object like"my_line". Could you give some suggestion about looking for helping document or opening mind in programing. – David Mar 07 '18 at 02:59
  • The document means matplotlib.It's too brief in some aspect to find usage of some function and properties – David Mar 07 '18 at 03:12
  • Are there any methods to stop the moving point "my_line" showing again,after some running time – David Mar 08 '18 at 13:03