Маршрут чертеже полей
есть ли способ рисовать поля направления в python?
моя попытка изменить http://www.compdigitec.com/labs/files/slopefields.py давать
#!/usr/bin/python
import math
from subprocess import CalledProcessError, call, check_call
def dy_dx(x, y):
try:
# declare your dy/dx here:
return x**2-x-2
except ZeroDivisionError:
return 1000.0
# Adjust window parameters
XMIN = -5.0
XMAX = 5.0
YMIN = -10.0
YMAX = 10.0
XSCL = 0.5
YSCL = 0.5
DISTANCE = 0.1
def main():
fileobj = open("data.txt", "w")
for x1 in xrange(int(XMIN / XSCL), int(XMAX / XSCL)):
for y1 in xrange(int(YMIN / YSCL), int(YMAX / YSCL)):
x= float(x1 * XSCL)
y= float(y1 * YSCL)
slope = dy_dx(x,y)
dx = math.sqrt( DISTANCE/( 1+math.pow(slope,2) ) )
dy = slope*dx
fileobj.write(str(x) + " " + str(y) + " " + str(dx) + " " + str(dy) + "n")
fileobj.close()
try:
check_call(["gnuplot","-e","set terminal png size 800,600 enhanced font "Arial,12"; set xrange [" + str(XMIN) + ":" + str(XMAX) + "]; set yrange [" + str(YMIN) + ":" + str(YMAX) + "]; set output 'output.png'; plot 'data.txt' using 1:2:3:4 with vectors"])
except (CalledProcessError, OSError):
print "Error: gnuplot not found on system!"
exit(1)
print "Saved image to output.png"
call(["xdg-open","output.png"])
return 0
if __name__ == '__main__':
main()
однако лучшее изображение, которое я получаю от этого. Как я могу получить вывод, который больше похож на первое изображение? Кроме того, как я могу добавить три сплошные линии?
3 ответов
вы можете использовать этот код matplotlib в качестве базы. Измените его для своих нужд. Я обновил код, чтобы показать стрелки одинаковой длины.
также можно изменить форму оси "коробки"на " стрелки". Дайте мне знать, если вам нужно это изменение, и я могу добавить его.
import matplotlib.pyplot as plt
from scipy import *
from scipy import integrate
from scipy.integrate import ode
import numpy as np
fig = plt.figure(num=1)
ax=fig.add_subplot(111)
## Vector field function
def vf(t,x):
dx=np.zeros(2)
dx[0]=1
dx[1]=x[0]**2-x[0]-2
return dx
#Solution curves
t0=0; tEnd=10; dt=0.01;
r = ode(vf).set_integrator('vode', method='bdf',max_step=dt)
ic=[[-3.5,-10], [-3,-10], [-2.5,-10]]
color=['r','b','g']
for k in range(len(ic)):
Y=[];T=[];S=[];
r.set_initial_value(ic[k], t0).set_f_params()
while r.successful() and r.t +dt < tEnd:
r.integrate(r.t+dt)
Y.append(r.y)
S=np.array(np.real(Y))
ax.plot(S[:,0],S[:,1], color = color[k], lw = 1.25)
#Vector field
X,Y = np.meshgrid( np.linspace(-5,5,20),np.linspace(-10,10,20) )
U = 1
V = X**2-X-2
#Normalize arrows
N = np.sqrt(U**2+V**2)
U2, V2 = U/N, V/N
ax.quiver( X,Y,U2, V2)
plt.xlim([-5,5])
plt.ylim([-10,10])
plt.xlabel(r"$x$")
plt.ylabel(r"$y$")
plt.show()
мне было очень весело сделать один из них в качестве хобби-проекта с использованием pygame. Я нарисовал наклон на каждом пикселе, используя оттенки синего для положительного и оттенки красного для отрицательного. Черный - для неопределенного. Это dy/dx = log(sin(x/y)+cos(y/x))
:
dy / dx=log (sin (x/y)+cos (y/x) http://oi43.tinypic.com/90umn4.jpg
вы можете увеличить и уменьшить-вот увеличено в средней верхней части здесь:
и нажать на точку на графике линии через эту точку:
это всего лишь 440 строк кода, так что здесь .zip всех файлов. Думаю, я приведу здесь соответствующие отрывки.
само уравнение вводится как допустимое выражение Python в строке, например "log(sin(x/y)+cos(y/x))"
. Это тогда compile
d. Эта функция здесь отображает цветовое поле, где self.func.eval()
дает dy/dx
в данный момент. Код здесь немного сложный, потому что я сделал его рендеринг поэтапно-первые блоки 32x32, затем 16x16 и т. д. - чтобы сделать его более быстрым для пользователя.
def graphcolorfield(self, sqsizes=[32,16,8,4,2,1]):
su = ScreenUpdater(50)
lastskip = self.xscreensize
quitit = False
for squaresize in sqsizes:
xsquaresize = squaresize
ysquaresize = squaresize
if squaresize == 1:
self.screen.lock()
y = 0
while y <= self.yscreensize:
x = 0
skiprow = y%lastskip == 0
while x <= self.xscreensize:
if skiprow and x%lastskip==0:
x += squaresize
continue
color = (255,255,255)
try:
m = self.func.eval(*self.ct.untranscoord(x, y))
if m >= 0:
if m < 1:
c = 255 * m
color = (0, 0, c)
else:
#c = 255 - 255 * (1.0/m)
#color = (c, c, 255)
c = 255 - 255 * (1.0/m)
color = (c/2.0, c/2.0, 255)
else:
pm = -m
if pm < 1:
c = 255 * pm
color = (c, 0, 0)
else:
c = 255 - 255 * (1.0/pm)
color = (255, c/2.0, c/2.0)
except:
color = (0, 0, 0)
if squaresize > 1:
self.screen.fill(color, (x, y, squaresize, squaresize))
else:
self.screen.set_at((x, y), color)
if su.update():
quitit = True
break
x += xsquaresize
if quitit:
break
y += ysquaresize
if squaresize == 1:
self.screen.unlock()
lastskip = squaresize
if quitit:
break
это код, который отображает линию через точку:
def _grapheqhelp(self, sx, sy, stepsize, numsteps, color):
x = sx
y = sy
i = 0
pygame.draw.line(self.screen, color, (x, y), (x, y), 2)
while i < numsteps:
lastx = x
lasty = y
try:
m = self.func.eval(x, y)
except:
return
x += stepsize
y = y + m * stepsize
screenx1, screeny1 = self.ct.transcoord(lastx, lasty)
screenx2, screeny2 = self.ct.transcoord(x, y)
#print "(%f, %f)-(%f, %f)" % (screenx1, screeny1, screenx2, screeny2)
try:
pygame.draw.line(self.screen, color,
(screenx1, screeny1),
(screenx2, screeny2), 2)
except:
return
i += 1
stx, sty = self.ct.transcoord(sx, sy)
pygame.draw.circle(self.screen, color, (int(stx), int(sty)), 3, 0)
и он работает назад и вперед, начиная с этой точки:
def graphequation(self, sx, sy, stepsize=.01, color=(255, 255, 127)):
"""Graph the differential equation, given the starting point sx and sy, for length
length using stepsize stepsize."""
numstepsf = (self.xrange[1] - sx) / stepsize
numstepsb = (sx - self.xrange[0]) / stepsize
self._grapheqhelp(sx, sy, stepsize, numstepsf, color)
self._grapheqhelp(sx, sy, -stepsize, numstepsb, color)
Я никогда не удосужился рисовать фактические линии, потому что пиксельный подход выглядел слишком круто.
попробуйте изменить значения параметров следующим образом:
XSCL = .2
YSCL = .2
эти параметры определяют, сколько точек отбирается на осях.
в соответствии с вашим комментарием вам также нужно построить функции, для которых применяется вывод dy_dx(x, y).
В настоящее время вы только вычисляете и строите линии наклона,рассчитанные вашей функцией dy_dx(x, y). Вам нужно будет найти (в этом случае 3) функции для построения в дополнение к склон.
начните с определения функции:
def f1_x(x):
return x**3-x**2-2x;
и затем, в вашем цикле, вам также придется записать нужные значения для функций в файл fileobj.