added mandelbrot stuff, changed draw and fourier and added an effective interpolation program for fourier transform
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
from mysurface import Surface
|
||||
from mycontext import Surface
|
||||
from mybody import Body
|
||||
from myabstract import Form,Point,Vector
|
||||
from mymotion import Motion
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import numpy as np
|
||||
import pylab
|
||||
|
||||
# elephant parameters
|
||||
p1, p2, p3, p4 = (50 - 30j, 18 + 8j, 12 - 10j, -14 - 60j )
|
||||
p5 = 40 + 20j # eyepiece
|
||||
|
||||
def fourier(t, C):
|
||||
f = np.zeros(t.shape)
|
||||
A, B = C.real, C.imag
|
||||
for k in range(len(C)):
|
||||
f = f + A[k]*np.cos(k*t) + B[k]*np.sin(k*t)
|
||||
return f
|
||||
|
||||
def elephant(t, p1, p2, p3, p4, p5):
|
||||
npar = 6
|
||||
Cx = np.zeros((npar,), dtype='complex')
|
||||
Cy = np.zeros((npar,), dtype='complex')
|
||||
|
||||
Cx[1] = p1.real*1j
|
||||
Cx[2] = p2.real*1j
|
||||
Cx[3] = p3.real
|
||||
Cx[5] = p4.real
|
||||
|
||||
Cy[1] = p4.imag + p1.imag*1j
|
||||
Cy[2] = p2.imag*1j
|
||||
Cy[3] = p3.imag*1j
|
||||
|
||||
x = np.append(fourier(t,Cx), [-p5.imag])
|
||||
y = np.append(fourier(t,Cy), [p5.imag])
|
||||
|
||||
return x,y
|
||||
|
||||
x, y = elephant(np.linspace(0,2*np.pi,1000), p1, p2, p3, p4, p5)
|
||||
pylab.plot(y,-x,'.')
|
||||
pylab.show()
|
||||
@@ -7,6 +7,7 @@ import pygame
|
||||
import logging
|
||||
import copy
|
||||
import mycolors
|
||||
import random
|
||||
|
||||
# Interface Anatomy
|
||||
# - show(context) //an anatomy must be responsible for drawing itself
|
||||
@@ -36,17 +37,22 @@ class Body(Material):
|
||||
return Body(form,motion,moment)
|
||||
|
||||
def createFromAbsolute(form,motion=Motion(),moment=Motion(d=1)):
|
||||
"""Create a body from an absolute form."""
|
||||
"""Create a body from an absolute form using its motion and its angular moment."""
|
||||
motion.position=Vector(*form.center)
|
||||
form.points=(-motion.position).applyToPoints(form.points)
|
||||
return Body(form,motion,moment)
|
||||
|
||||
def __init__(self,form,motion=Motion(d=2),moment=Motion(d=1)):
|
||||
"""Create body using form and optional name."""
|
||||
"""Create body using its anatomy, its motion and its angular moment.
|
||||
#Attributes:
|
||||
#self.form,self.motion,self.moment
|
||||
#Properties:
|
||||
#self.absolute"""
|
||||
self.form=form
|
||||
self.motion=motion
|
||||
self.moment=moment
|
||||
|
||||
|
||||
def __str__(self):
|
||||
"""Return the string representation of the body."""
|
||||
return "b("+str(self.form)+","+str(self.motion)+")"
|
||||
@@ -105,11 +111,12 @@ class Body(Material):
|
||||
class PhysicalBody(Body):
|
||||
def __init__(self,form,motion=Motion(d=2),moment=Motion(d=1),mass=1):
|
||||
"""Create body using form and optional name."""
|
||||
self.form=form
|
||||
self.motion=motion
|
||||
self.moment=moment
|
||||
super().__init__(form,motion,moment)
|
||||
self.mass=mass
|
||||
|
||||
def __str__(self):
|
||||
"""Return the string representation of a physical body."""
|
||||
return "p"+super().__str__()
|
||||
|
||||
|
||||
|
||||
@@ -117,5 +124,19 @@ class PhysicalBody(Body):
|
||||
|
||||
|
||||
if __name__=="__main__":
|
||||
from mysurface import Surface
|
||||
surface=Surface(fullscreen=True)
|
||||
from mycontext import Context
|
||||
context=Context(fullscreen=False)
|
||||
ru=random.uniform
|
||||
form1=Form.random(n=4)
|
||||
motion1=Motion(Vector(0,0),Vector(ru(-1,1),ru(-1,1)),Vector(0,0))
|
||||
moment1=Motion(Vector([0]),Vector([ru(-1,1)]),Vector([0]))
|
||||
b1=Body(form1,motion1,moment1)
|
||||
#b=Body.random()
|
||||
while context.open:
|
||||
context.check()
|
||||
context.clear()
|
||||
context.show()
|
||||
context.control()
|
||||
b1.show(context)
|
||||
b1.update(0.1)
|
||||
context.flip()
|
||||
|
||||
@@ -7,6 +7,11 @@ import mycolors
|
||||
|
||||
class Context(Rect):
|
||||
|
||||
def createFromSizeAndCorners(size,corners,**kwargs):
|
||||
c=Context(size=size,**kwargs)
|
||||
c.corners=corners
|
||||
return c
|
||||
|
||||
def __init__(self,draw=None,**kwargs):
|
||||
"""Create a context."""
|
||||
if not draw: self.draw=Draw(**kwargs)
|
||||
@@ -64,11 +69,11 @@ class Context(Rect):
|
||||
|
||||
def getSize(self):
|
||||
"""Return the size of the surface shown."""
|
||||
return self.draw.plane.getSize()
|
||||
return self.draw.window.size
|
||||
|
||||
def setSize(self,size):
|
||||
"""Set the size of the surface shown."""
|
||||
self.draw.plane.setSize(size)
|
||||
self.draw.window.size=size
|
||||
|
||||
def getUnits(self):
|
||||
"""Return the units of the surface shown."""
|
||||
@@ -98,6 +103,10 @@ class Context(Rect):
|
||||
self.draw.plane.show(self.draw.window)
|
||||
self.flip()
|
||||
|
||||
def __contains__(self,position):
|
||||
"""Determine if a position is in the context."""
|
||||
return self.draw.plane.contains(position,self.draw.window)
|
||||
|
||||
def show(self):
|
||||
"""Show the plane on screen."""
|
||||
self.draw.plane.show(self.draw.window)
|
||||
@@ -155,7 +164,7 @@ class Context(Rect):
|
||||
|
||||
def transform(self,image,size):
|
||||
"""Change the size of an image."""
|
||||
pass
|
||||
return self.draw.window.transform(image,size)
|
||||
|
||||
def getOpen(self):
|
||||
return self.draw.window.open
|
||||
@@ -179,21 +188,21 @@ class Context(Rect):
|
||||
if self.open:
|
||||
self.__enter__()
|
||||
|
||||
def getXmin(self):
|
||||
"""Return xmin."""
|
||||
return self.corners[0]
|
||||
def getWidth(self):
|
||||
"""Return the width of the window."""
|
||||
return self.size[0]
|
||||
|
||||
def setXmin(self,x):
|
||||
"""Set xmin."""
|
||||
self.corners[0]=x
|
||||
def setWidth(self,width):
|
||||
"""Set the width of the window."""
|
||||
self.size[0]=width
|
||||
|
||||
def getXmax(self,x):
|
||||
"""Get xmax."""
|
||||
return self.corners[2]
|
||||
def getHeight(self):
|
||||
"""Return the height of the window."""
|
||||
return self.size[1]
|
||||
|
||||
def setXmax(self,x):
|
||||
"""Set xmax."""
|
||||
self.corners[2]=x
|
||||
def setHeight(self,height):
|
||||
"""Set the height of the window."""
|
||||
self.size[1]=height
|
||||
|
||||
corners=property(getCorners,setCorners,"Allow the user to manipulate the corners of the surface easily.")
|
||||
rect=property(getRect,setRect,"Allow the user to manipulate the rect of the surface easily.")
|
||||
@@ -203,8 +212,8 @@ class Context(Rect):
|
||||
units=property(getUnits,setUnits,"Allow the user to manipulate the units of the surface easily.")
|
||||
keys=property(getKeys,"Allow the user to manipulate the keys of the surface easily.")
|
||||
open=property(getOpen,setOpen)
|
||||
xmin=property(getXmin,setXmin)
|
||||
xmax=property(getXmax,setXmax)
|
||||
width=property(getWidth,setWidth)
|
||||
height=property(getHeight,setHeight)
|
||||
|
||||
|
||||
|
||||
@@ -213,4 +222,6 @@ Surface=Context
|
||||
|
||||
if __name__=="__main__":
|
||||
context=Context()
|
||||
context.corners=[0,0,1,1]
|
||||
print(context.corners)
|
||||
context()
|
||||
|
||||
@@ -100,9 +100,11 @@ class Draw:
|
||||
size=rect[2:]
|
||||
position=self.plane.getToScreen(position,self.window)
|
||||
size=self.plane.getToScreen(size,self.window)
|
||||
self.window.draw.arcarc(screen,color,rect,start_angle,stop_angle,width)
|
||||
self.window.draw.arc(screen,color,rect,start_angle,stop_angle,width)
|
||||
|
||||
|
||||
def complex(self,screen,color,z,radius,**kwargs):
|
||||
self.circle(screen,color,(z.real,z.imag),radius,**kwargs)
|
||||
|
||||
def show(self):
|
||||
self.plane.showGrid(self.window)
|
||||
|
||||
@@ -24,18 +24,13 @@ class Fourier:
|
||||
self.graph_drawing=[]
|
||||
self.graph_construction=[]
|
||||
self.graph_display=[]
|
||||
self.sample_precision=100
|
||||
self.coefficients_number=100
|
||||
self.display_number=100
|
||||
self.period=100
|
||||
|
||||
self.mode=0
|
||||
self.messages=['drawing', 'construction', 'display']
|
||||
self.coefficients=[]
|
||||
self.context.text.append("mode: "+self.messages[self.mode])
|
||||
self.duration=None
|
||||
self.time=0
|
||||
self.max_step=100
|
||||
self.step=0
|
||||
self.speed=1/100
|
||||
self.vectors=[]
|
||||
|
||||
def __call__(self):
|
||||
@@ -72,12 +67,11 @@ class Fourier:
|
||||
# self.graph_interpolation=self.sample(self.function_interpolation,len(self.graph_drawing))
|
||||
elif self.mode==1: #construction
|
||||
self.step+=1
|
||||
self.time=self.speed*self.step
|
||||
#print(self.time/self.duration)
|
||||
if self.duration is not None:
|
||||
if self.time>self.duration:
|
||||
self.mode=2
|
||||
self.graph_construction=self.discreteComplexComposeGraph(self.coefficients,self.time) #complex now
|
||||
self.time=self.step/self.max_step
|
||||
if self.step>self.max_step:
|
||||
self.mode=2
|
||||
#self.graph_construction=self.discreteComplexComposeGraph(self.coefficients,self.time) #complex now
|
||||
self.graph_construction=self.numpyComposeConstructionGraph(self.coefficients,t=self.time)
|
||||
self.vectors=self.getVectors([(0,0)]+self.graph_construction)
|
||||
self.graph_display.append(self.graph_construction[-1])
|
||||
|
||||
@@ -99,7 +93,7 @@ class Fourier:
|
||||
self.showGraph(self.graph_display,mycolors.BLUE)
|
||||
self.showVectors([(0,0)]+self.graph_construction,self.vectors,mycolors.RED)
|
||||
self.context.text.append("time: "+str(self.time))
|
||||
#self.context.print("coefficients:"+str(self.coefficients),(1000,850),size=20,conversion=False,color=mycolors.GREEN)
|
||||
|
||||
elif self.mode==2:
|
||||
self.showGraph(self.graph_display,mycolors.BLUE)
|
||||
self.context.showConsole(nmax=10)
|
||||
@@ -143,8 +137,13 @@ class Fourier:
|
||||
self.graph_drawing=self.cleanGraph(self.graph_drawing)
|
||||
#self.graph_drawing=self.takeGraphSamples(self.graph_drawing)[:]
|
||||
print(self.graph_drawing)
|
||||
self.coefficients=self.discreteComplexDecomposeGraph(self.graph_drawing)
|
||||
self.graph_construction=self.discreteComplexComposeGraph(self.coefficients,0)
|
||||
#self.coefficients=self.discreteComplexDecomposeGraph(self.graph_drawing)
|
||||
self.graph_drawing=self.graph_drawing[:len(self.graph_drawing)-1+len(self.graph_drawing)%2]
|
||||
self.coefficients=self.numpyFourierTransform(self.graph_drawing)
|
||||
self.graph_drawing=self.numpyInverseFourierTransform(self.coefficients)
|
||||
#print(len(self.coefficients))
|
||||
#self.graph_construction=self.discreteComplexComposeGraph(self.coefficients,0)
|
||||
self.graph_construction=self.graph_drawing
|
||||
self.time=0
|
||||
self.step=0
|
||||
print(self.coefficients)
|
||||
@@ -211,6 +210,20 @@ class Fourier:
|
||||
p=self.context.point()
|
||||
self.graph_drawing.append(p)
|
||||
|
||||
def threeBlueOneBrownFormula(self,graph):
|
||||
c=[]
|
||||
for n in range(len(graph)):
|
||||
cn=sum([graph[n]])
|
||||
|
||||
def numpyFourierTransform(self,graph):
|
||||
"""Return the fourier coefficients by doing a fourier transform for a given graph with the fft."""
|
||||
z=[complex(*graph[i]) for i in range(len(graph))]
|
||||
return np.fft.fft(z)
|
||||
|
||||
def numpyFourierTransform2D(self,graph,**kwargs):
|
||||
"""Return the fourier coefficients by doing a fourier transform for a given graph with the fft2."""
|
||||
return np.fft.fft2(graph,**kwargs)
|
||||
|
||||
def decompose(self,graph):
|
||||
"""Decompose the points into 2 signals the coefficients corresponding to the drawing."""
|
||||
x=[graph[i][0] for i in range(len(graph))]
|
||||
@@ -280,6 +293,14 @@ class Fourier:
|
||||
c.append(d)
|
||||
return c
|
||||
|
||||
def numpyInverseFourierTransform(self,coefficients,**kwargs):
|
||||
"""Return the fourier coefficients by doing a fourier transform for a given graph with the fft."""
|
||||
return [(z.real,z.imag) for z in np.fft.ifft(coefficients,**kwargs)]
|
||||
|
||||
def numpyInverseFourierTransform2D(self,coefficients,**kwargs):
|
||||
"""Create a graph using the coefficients under the form of a list of duos."""
|
||||
return np.fft.ifft2(coefficients,**kwargs)
|
||||
|
||||
def scipyTranform(self,s):
|
||||
"""Find the fourier transform using the scipy module."""
|
||||
l=len(s)
|
||||
@@ -373,14 +394,68 @@ class Fourier:
|
||||
g.append((d.real,d.imag))
|
||||
return g
|
||||
|
||||
def numpyComposeConstructionGraph2D(self,coefficients,t=0):
|
||||
"""Uses the fourier coefficients of the fourier transform. to make the construciton graph."""
|
||||
l=len(coefficients)
|
||||
xs,ys=0,0
|
||||
wo=2*math.pi
|
||||
#wo=1
|
||||
#wo=1/100
|
||||
graph=[]
|
||||
for i,c in enumerate(coefficients):
|
||||
n=i
|
||||
a,b=c
|
||||
print("a:",a.real,a.imag)
|
||||
#x=a.real*math.cos(n*wo*t)+a.imag*math.sin(n*wo*t)
|
||||
#y=b.real*math.cos(n*wo*t)+b.imag*math.sin(n*wo*t)
|
||||
x=a.real*math.cos(n*wo*t)
|
||||
y=a.imag*math.sin(n*wo*t)
|
||||
xs+=x; ys+=y
|
||||
graph.append((xs,ys))
|
||||
print("x,y:",x,y)
|
||||
print("xs,ys:",xs,ys)
|
||||
print(coefficients)
|
||||
print(graph)
|
||||
|
||||
return graph
|
||||
|
||||
def numpyComposeConstructionGraph(self,coefficients,t=0):
|
||||
"""Uses the fourier coefficients of the fourier transform. to make the construciton graph."""
|
||||
l=len(coefficients)
|
||||
xs,ys=0,0
|
||||
wo=2*math.pi
|
||||
#wo=1
|
||||
#wo=1/10
|
||||
graph=[]
|
||||
#print("coefficients:")
|
||||
#print(coefficients)
|
||||
l=len(coefficients)
|
||||
print(l)
|
||||
h=l//2
|
||||
for i in range(l):
|
||||
n=int(((i+1)//2)*(-1)**(i+1))
|
||||
print("n:",n)
|
||||
z=coefficients[n+h]*cmath.exp(n*wo*t*1j)
|
||||
print(z)
|
||||
#print("z:",z.real,z.imag)
|
||||
x=z.real
|
||||
y=z.imag
|
||||
xs+=x; ys+=y
|
||||
graph.append((xs,ys))
|
||||
#print("x,y:",x,y)
|
||||
#print("xs,ys:",xs,ys)
|
||||
print(graph)
|
||||
|
||||
return graph
|
||||
if __name__=="__main__":
|
||||
from mycontext import Context
|
||||
context=Context(name="Application of the Fourier Transform.",fullscreen=False)
|
||||
fourier=Fourier(context)
|
||||
fourier.coefficients=[[0,1,2,0.5],[0,1,5,2],[0,-2,1,6],[0,-4,3,1]]
|
||||
#fourier.coefficients=[(3+5j),(2+1j),(0-0.5j),(1+3.5j),(2-1j)]
|
||||
#fourier.mode=1
|
||||
#fourier.coefficients=[[0,1,2,0.5],[0,1,5,2],[0,-2,1,6],[0,-4,3,1]]
|
||||
fourier.coefficients=np.array([(3+5j),(2+1j),(0-0.5j),(1+3.5j),dtype=complex])
|
||||
#cx=[0+50j,0+18j,12+0j,-14+0j]
|
||||
#cy=[-60-30j,0+8j,0-10j]
|
||||
|
||||
#fourier.coefficients=np.array(list(zip(cx,cy)))
|
||||
fourier.mode=1
|
||||
fourier()
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
class ImmutableBody(Body):
|
||||
"""Define a body than cannot be moved by any other body."""
|
||||
def __init__(self,*args,**kwargs):
|
||||
super().__init(*args,**kwargs)
|
||||
|
||||
|
||||
class Ground(ImmutableBody):
|
||||
"""Define a ground that is an immutable body."""
|
||||
def __init__(self,):
|
||||
"""Create a ground using its line."""
|
||||
self.mass=float('inf')
|
||||
|
||||
#(m1+m2)v=m1v1+m2v2
|
||||
#m*v**2=m1*v1**2+m2*v2**2
|
||||
@@ -0,0 +1,127 @@
|
||||
"""
|
||||
The goal of this program is to make an interpolation of the points of any
|
||||
curve in order to make it a parametric function.
|
||||
|
||||
|
||||
There are 2 main types of interpolations:
|
||||
- Polynomial Interpolation:
|
||||
- Bezier Interpolation:
|
||||
"""
|
||||
|
||||
from marclib.polynomial import Polynomial
|
||||
import numpy as np
|
||||
|
||||
#Deprectated function
|
||||
def directInterpolation(points,t):
|
||||
x=[pt[0] for pt in points]
|
||||
y=[pt[1] for pt in points]
|
||||
plx=Polynomial.createFromInterpolation(range(len(x)),x)
|
||||
ply=Polynomial.createFromInterpolation(range(len(y)),y)
|
||||
l=len(pts)
|
||||
mst=100
|
||||
|
||||
|
||||
|
||||
class PolynomialInterpolation:
|
||||
"""Make an interpolation using the lagrangian polynomial interpolator
|
||||
over list of n-dimensional points."""
|
||||
|
||||
def __init__(self,points,create=True):
|
||||
"""Create the interpolation using a list of n-dimensional points."""
|
||||
self.points=points
|
||||
if create: self.create()
|
||||
|
||||
def create(self):
|
||||
"""Create the components useful for the interpolation which are the
|
||||
split components and the lagrangian polynomials."""
|
||||
self.createComponents()
|
||||
self.createPolynomials()
|
||||
|
||||
def createComponents(self):
|
||||
"""Split its components of each point in separate lists."""
|
||||
self.components=[[pt[i] for pt in self.points] for i in range(len(self.points[0]))]
|
||||
|
||||
def createPolynomials(self):
|
||||
"""Create its polynomials using its components."""
|
||||
lpts=len(self.points)
|
||||
self.polynomials=[Polynomial.createFromInterpolation(range(lpts),c) for c in self.components]
|
||||
|
||||
def __call__(self,t):
|
||||
"""Evaluate the parametric interpolation for the input 't' between 0 and 1."""
|
||||
lcps=len(self.components)
|
||||
return tuple([self.polynomials[i](t) for i in range(lcps)])
|
||||
|
||||
def sample(self,n):
|
||||
"""Make a sample of the interpolation for n points."""
|
||||
lpts=len(self.points)
|
||||
return [self(lpts*t) for t in np.linspace(0,1,n)]
|
||||
|
||||
class BezierInterpolation:
|
||||
"""Make an interpolation using the bezier interpolation over a list of
|
||||
n-dimensional points."""
|
||||
|
||||
def __init__(self,points,create=True):
|
||||
"""Create the interpolation using a list of n-dimensional points."""
|
||||
self.points=points
|
||||
if create: self.create()
|
||||
|
||||
def create(self):
|
||||
pass
|
||||
|
||||
def __call__(self):
|
||||
pass
|
||||
|
||||
def sample(self,n):
|
||||
"""Make a sample of the interpolation for n points."""
|
||||
lpts=len(self.points)
|
||||
return [self(lpts*t) for t in np.linspace(0,1,n)]
|
||||
|
||||
|
||||
if __name__=="__main__":
|
||||
#To show the points
|
||||
from mycontext import Context
|
||||
import mycolors
|
||||
#To create the points
|
||||
import random
|
||||
|
||||
context=Context()
|
||||
|
||||
#Parameters
|
||||
h=1; w=1
|
||||
xmin=-w
|
||||
xmax=w
|
||||
ymin=-h
|
||||
ymax=h
|
||||
n=5
|
||||
|
||||
#Creation of the points
|
||||
pts=[(random.uniform(xmin,xmax),random.uniform(ymin,ymax)) for i in range(n)]
|
||||
|
||||
""" Tests:
|
||||
Calculations for n points in dimension 2:
|
||||
|
||||
x=[pt[0] for pt in pts]
|
||||
y=[pt[1] for pt in pts]
|
||||
plx=Polynomial.createFromInterpolation(range(len(x)),x)
|
||||
ply=Polynomial.createFromInterpolation(range(len(y)),y)
|
||||
print(plx)
|
||||
print(ply)
|
||||
l=len(pts)
|
||||
mst=100
|
||||
npts=[(plx(l*st/mst),ply(l*st/mst)) for st in range(mst)]
|
||||
grapher=Grapher(context,functions=[plx,ply])
|
||||
"""
|
||||
|
||||
#Final version
|
||||
interpolation=Interpolation(pts)
|
||||
npts=interpolation.sample(200) #Sample 200 points by interpolation
|
||||
|
||||
#Main loop of the context
|
||||
while context.open:
|
||||
context.check()
|
||||
context.control()
|
||||
context.clear()
|
||||
context.show()
|
||||
context.draw.lines(context.screen,mycolors.GREEN,pts,connected=False)
|
||||
context.draw.lines(context.screen,mycolors.YELLOW,npts,connected=False)
|
||||
context.flip()
|
||||
@@ -0,0 +1,123 @@
|
||||
from mycontext import Context
|
||||
from PIL import Image, ImageDraw
|
||||
import numpy as np
|
||||
import mycolors
|
||||
from mymanager import SimpleManager
|
||||
|
||||
|
||||
|
||||
def mandelbrot(z,maxiter):
|
||||
c=z
|
||||
for n in range(maxiter):
|
||||
if abs(z) > 2:
|
||||
return n
|
||||
z=z**2+c
|
||||
return maxiter
|
||||
|
||||
def getMatrix(width=800,height=800,corners=[-2,-1,1,1],maxiter=80):
|
||||
xmin,ymin,xmax,ymax=corners
|
||||
xzoom=(xmax-xmin)/width
|
||||
yzoom=(ymax-ymin)/height
|
||||
matrix=np.zeros([width,height])
|
||||
for x in range(0,width):
|
||||
for y in range(0,height):
|
||||
matrix[x][y]=mandelbrot(complex(xmin+x*xzoom,ymin+y*yzoom),maxiter)
|
||||
return matrix
|
||||
|
||||
def showMatrixWithPIL(matrix,width=None,height=None,maxiter=80,save=True):
|
||||
if (width is None) or (height is None):
|
||||
width,height=[len(matrix),len(matrix[0])]
|
||||
im = Image.new('RGB',(width,height),(0, 0, 0))
|
||||
draw = ImageDraw.Draw(im)
|
||||
for x in range(width):
|
||||
for y in range(height):
|
||||
color=int(matrix[x][y] * 255 / maxiter)
|
||||
draw.point([x, y], (color, color, color))
|
||||
if save: im.save('output.png', 'PNG')
|
||||
im.show()
|
||||
|
||||
|
||||
|
||||
class Mandelbrot(SimpleManager):
|
||||
def compute(self,z):
|
||||
c=z
|
||||
for n in range(self.maxiter):
|
||||
if abs(z) > 2:
|
||||
return n
|
||||
z=z**2+c
|
||||
return self.maxiter
|
||||
|
||||
def __init__(self,context,size,maxiter=80):
|
||||
"""Create a set of mandelbrot using the size, the corners and the maxiter (maxiteration)."""
|
||||
self.context=context
|
||||
self.maxiter=maxiter
|
||||
self.size=size
|
||||
|
||||
def buildMatrix(self):
|
||||
"""Return the numpy matrix of the set."""
|
||||
xmin,ymin,xmax,ymax=self.corners
|
||||
xzoom=(xmax-xmin)/self.width
|
||||
yzoom=(ymax-ymin)/self.height
|
||||
self.matrix=np.zeros(self.size)
|
||||
for x in range(self.width):
|
||||
for y in range(self.height):
|
||||
self.matrix[x][y]=self.compute(complex(xmin+x*xzoom,ymin+y*yzoom))
|
||||
|
||||
def showWithPIL(self,save=True):
|
||||
"""Show the set with PIL using the matrix."""
|
||||
im = Image.new('RGB',(self.width,self.height),(0, 0, 0))
|
||||
draw = ImageDraw.Draw(im)
|
||||
for x in range(self.width):
|
||||
for y in range(self.height):
|
||||
color=int(self.matrix[x][y] * 255 / self.maxiter)
|
||||
draw.point([x, y], (color, color, color))
|
||||
if save: im.save('output.png', 'PNG')
|
||||
im.show()
|
||||
|
||||
def showSet(self):
|
||||
"""Show the mandelbrot set on the context."""
|
||||
for x in range(self.width):
|
||||
for y in range(self.height):
|
||||
c=int(self.matrix[x][y] * 255 / self.maxiter)
|
||||
self.context.draw.rect(self.context.screen,(c,c,c),[x,y,1,1])
|
||||
|
||||
|
||||
def update(self):
|
||||
"""Update the mandelbrot set depending on the corners."""
|
||||
self.buildMatrix()
|
||||
|
||||
def show(self):
|
||||
"""Show the mandelbrot set."""
|
||||
self.context.refresh()
|
||||
self.context.control()
|
||||
self.showSet()
|
||||
self.context.flip()
|
||||
|
||||
def getCorners(self):
|
||||
return self.context.corners
|
||||
def getWidth(self):
|
||||
return self.size[0]
|
||||
def getHeight(self):
|
||||
return self.size[1]
|
||||
|
||||
#Properties
|
||||
corners=property(getCorners)
|
||||
height=property(getHeight)
|
||||
width=property(getWidth)
|
||||
|
||||
|
||||
|
||||
if __name__=="__main__":
|
||||
context_size=[800,600]
|
||||
mandelbrot_size=[200,150]
|
||||
corners=[-2,-1,1,1]
|
||||
context=Context.createFromSizeAndCorners(context_size,corners,name="Mandelbrot") #width,height=context.size
|
||||
|
||||
print(context.corners)
|
||||
print(context.position)
|
||||
print([0,0] in context)
|
||||
#width=800;height=600;maxiter=20
|
||||
#matrix=getMatrix(width,height,maxiter=maxiter)
|
||||
#showMatrixWithPIL(matrix,width,height,maxiter=maxiter)
|
||||
m=Mandelbrot(context,mandelbrot_size)
|
||||
m()
|
||||
@@ -0,0 +1,14 @@
|
||||
import numpy as np
|
||||
|
||||
class VisualGraph:
|
||||
"""Wikipedia: In mathematics, and more specifically in graph theory, a graph
|
||||
is a structure amounting to a set of objects in which some pairs of the
|
||||
objects are in some sense "related". The objects correspond to mathematical
|
||||
abstractions called vertices (also called nodes or points) and each of the
|
||||
related pairs of vertices is called an edge (also called link or line).[1]
|
||||
Typically, a graph is depicted in diagrammatic form as a set of dots or
|
||||
circles for the vertices, joined by lines or curves for the edges. Graphs
|
||||
are one of the objects of study in discrete mathematics."""
|
||||
def __init__(self,matrix):
|
||||
"""Create a graph using its
|
||||
self.matrix=matrix
|
||||
@@ -67,14 +67,16 @@ class Grapher(SimpleManager):
|
||||
|
||||
def sampleFunctions(self,functions):
|
||||
"""Sample all the functions one by one."""
|
||||
return [self.sampleFunction(function) for function in functions]
|
||||
ymin=self.context.ymin
|
||||
ymax=self.context.ymax
|
||||
return [self.sampleFunction(function,ymin,ymax) for function in functions]
|
||||
|
||||
def sampleFunction(self,function):
|
||||
def sampleFunction(self,function,ymin,ymax):
|
||||
"""Return n points of the graph."""
|
||||
xmin,xmax=self.getInterval()
|
||||
n=self.sample_number
|
||||
xl=np.linspace(xmin,xmax,n)
|
||||
return [(x,function(x)) for x in xl]
|
||||
return [(x,function(x)) for x in xl if ymin<function(x)<ymax]
|
||||
|
||||
def cleverlySampleFunction(self,function):
|
||||
"""Sample a function in an optimized way to get the nicest visualisation possible with the less points as possible."""
|
||||
@@ -90,7 +92,7 @@ class Grapher(SimpleManager):
|
||||
self.context.clear()
|
||||
self.context.control()
|
||||
self.context.show()
|
||||
self.showGraphs(self.graphs)
|
||||
self.showGraphs(self.functions)
|
||||
#Its just for a demo, it will be removed later
|
||||
if "points" in self.__dict__:
|
||||
self.showPoints()
|
||||
|
||||
@@ -223,19 +223,21 @@ class Plane:
|
||||
def getCorners(self,window):
|
||||
"""Return the corners of the present view."""
|
||||
wsx,wsy=window.size
|
||||
ux,uy=self.units
|
||||
x,y=self.position
|
||||
lx,ly=wsx/ux,wsy/uy
|
||||
return [x-lx/2,y-ly/2,x+lx/2,y+ly/2]
|
||||
|
||||
mx,my=self.getFromScreen([0,wsy],window)
|
||||
Mx,My=self.getFromScreen([wsx,0],window)
|
||||
return (mx,my,Mx,My)
|
||||
|
||||
def setCorners(self,corners,window):
|
||||
"""Change the actual corners of the plane by changing its position and units."""
|
||||
wsx,wsy=window.size
|
||||
xmin,ymin,xmax,ymax=corners
|
||||
xmin,ymin=self.getToScreen([xmin,ymin],window)
|
||||
xmax,ymax=self.getToScreen([xmax,ymax],window)
|
||||
x,y,sx,sy=self.getCoordonnatesFromCorners([xmin,ymin,xmax,ymax])
|
||||
self.position=[x,y]
|
||||
self.units=[wsx//sx,wsy//sy]
|
||||
wsx,wsy=window.size
|
||||
self.position=[xmin+(xmax-xmin)/2,ymin+(ymax-ymin)/2]
|
||||
self.units=[wsx/(xmax-xmin),wsy/(ymax-ymin)]
|
||||
|
||||
#The following functions are static methods
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from mysurface import Surface
|
||||
from mycontext import Surface
|
||||
|
||||
import math
|
||||
import cmath
|
||||
@@ -50,7 +50,7 @@ class Mandelbrot:
|
||||
def show(self,surface,precision=[10,10]):
|
||||
"""Show the mandelbrot set on the surface."""
|
||||
wsx,wsy=surface.draw.window.size
|
||||
corners=surface.draw.plane.getPlaneCorners(surface.draw.window)
|
||||
corners=surface.draw.plane.getCorners(surface.draw.window)
|
||||
mx,my,Mx,My=corners
|
||||
px,py=precision
|
||||
ux,uy=surface.draw.plane.units
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 87 KiB |
@@ -1 +1,25 @@
|
||||
from
|
||||
from mycontext import Context
|
||||
import mycolors
|
||||
import cmath
|
||||
import random
|
||||
|
||||
cx=[0+50j,0+18j,12+0j,-14+0j]
|
||||
cy=[-60-30j,0+8j,0-10j,0]
|
||||
|
||||
a=list(zip(cx,cy))
|
||||
print(a)
|
||||
context=Context()
|
||||
|
||||
n=100
|
||||
|
||||
l=[complex(random.uniform(-1,1),random.uniform(-1,1)) for i in range(n)]
|
||||
|
||||
while context.open:
|
||||
context.check()
|
||||
context.control()
|
||||
context.clear()
|
||||
context.show()
|
||||
for e in l:
|
||||
z=cmath.exp(complex(e))
|
||||
context.draw.complex(context.screen,mycolors.WHITE,z,0.1)
|
||||
context.flip()
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
from __future__ import division
|
||||
import random as rd
|
||||
from math import exp,log
|
||||
import math
|
||||
|
||||
BLUE = ( 0, 0,255)
|
||||
RED = (255, 0, 0)
|
||||
GREEN = ( 0,255, 0)
|
||||
YELLOW = (255,255, 0)
|
||||
BLACK = ( 0, 0, 0)
|
||||
WHITE = (255,255,255)
|
||||
GREY = (100,100,100)
|
||||
PURPLE = (100, 0,100)
|
||||
ORANGE = (255,165, 0)
|
||||
BROWN = (160, 82, 45)
|
||||
HALFGREY = ( 50, 50, 50)
|
||||
DARKGREY = ( 20, 20, 20)
|
||||
DARKRED = ( 10, 10, 10)
|
||||
DARKGREEN = ( 0,100, 0)
|
||||
DARKBLUE = ( 0, 0,100)
|
||||
LIGHTRED = (255,200,200)
|
||||
LIGHTGREEN = (200,255,200)
|
||||
LIGHTBLUE = (200,200,255)
|
||||
LIGHTBROWN = (229,219,222)
|
||||
LIGHTGREY = (200,200,200)
|
||||
BEIGE = (199,175,138)
|
||||
|
||||
sigmoid = s = lambda x:1/(1+math.exp(-x))
|
||||
reverse_sigmoid = lambda x:log(x/(1-x))
|
||||
#r=reverse_sigmoid()
|
||||
|
||||
bijection = lambda x,e,s:(x-e[0])/(e[1]-e[0])*(s[1]-s[0])+s[0]
|
||||
|
||||
|
||||
random = lambda : tuple([rd.randint(0,255) for i in range(3)])
|
||||
reverse = lambda color: tuple([255-c for c in color])
|
||||
darken = lambda color,n=0: tuple([int(c*sigmoid(n/10)) for c in color])
|
||||
lighten = lambda color,n=0: tuple([int(255-(255-c)*sigmoid(n/10)) for c in color])
|
||||
mix = lambda cl1,cl2: tuple([(c1+c2)//2 for (c1,c2) in zip(cl1,cl2)])
|
||||
substract = lambda cl1,cl2: tuple([max(min(2*c1-c2,255),0) for (c1,c2) in zip(cl1,cl2)])
|
||||
increase = lambda color,n=2: tuple([int(255*exp(n*log(c/255))) for c in color])
|
||||
|
||||
|
||||
def setFromWavelength(wavelength):
|
||||
"""Return a color using wavelength."""
|
||||
gamma,max_intensity=0.80,255
|
||||
def adjust(color, factor):
|
||||
if color==0: return 0
|
||||
else: return round(max_intensity*pow(color*factor,gamma))
|
||||
if 380<=wavelength<=440: r,g,b=-(wavelength-440)/(440-380),0,1
|
||||
elif 440<=wavelength<=490: r,g,b=0,(wavelength-440)/(490-440),1
|
||||
elif 490<=wavelength<=510: r,g,b=0,1,-(wavelength-510)/(510-490)
|
||||
elif 510<=wavelength<=580: r,g,b=(wavelength-510)/(580-510),1,0
|
||||
elif 580<=wavelength<=645: r,g,b=1,-(wavelength-645)/(645-580),0
|
||||
elif 645<=wavelength<=780: r,g,b=1,0,0
|
||||
else: r,g,b=0,0,0
|
||||
if 380<=wavelength<=420: factor=0.3+0.7*(wavelength-380)/(420-380)
|
||||
elif 420<=wavelength<=701: factor=1
|
||||
elif 701<=wavelength<=780: factor=0.3+0.7*(780-wavelength)/(780-700)
|
||||
else: factor=0
|
||||
r,g,b=adjust(r,factor),adjust(g,factor),adjust(b,factor)
|
||||
return (r,g,b)
|
||||
|
||||
#if __name__=="__main__":
|
||||
#print(darken(RED,10))
|
||||
#print(mix(YELLOW,RED))
|
||||
#print(reverse(LIGHTBROWN))
|
||||
#print(substract(LIGHTBROWN,ORANGE))
|
||||
#print(increase(LIGHTBROWN))
|
||||
|
||||
#for i in range(380,780,10):
|
||||
# print(setFromWavelength(i))
|
||||
|
||||
#print("mycolors imported")
|
||||
@@ -0,0 +1,52 @@
|
||||
# Programme : mandelbrot.py
|
||||
# Langage : Python 3.6 - Pygame 1.9
|
||||
# Auteur : Mathieu
|
||||
# Description : Calcule et affiche la fractale de Mandelbrot en noir et blanc
|
||||
import pygame
|
||||
# Constantes
|
||||
MAX_ITERATION = 50 # nombre d'itérations maximales avant de considérer que la suite converge
|
||||
XMIN, XMAX, YMIN, YMAX = -2, +0.5, -1.25, +1.25 # bornes du repère
|
||||
LARGEUR, HAUTEUR = 500, 500 # taille de la fenêtre en pixels
|
||||
# Initialisation et création d'une fenêtre aux dimensions spécifiéés munie d'un titre
|
||||
pygame.init()
|
||||
screen = pygame.display.set_mode((LARGEUR,HAUTEUR))
|
||||
pygame.display.set_caption("Fractale de Mandelbrot")
|
||||
# Création de l'ensemble de Mandelbrot
|
||||
# Principe : on balaye l'écran pixel par pixel en convertissant le pixel en un point du plan de notre repère
|
||||
# Si la suite converge, le point appartient à l'ensemble de Mandelbrot et on colore le pixel en noir
|
||||
# Sinon la suite diverge, le point n'appartient pas à l'ensemble et on colore le pixel en blanc
|
||||
for y in range(HAUTEUR):
|
||||
for x in range(LARGEUR):
|
||||
# Les deux lignes suivantes permettent d'associer à chaque pixel de l'écran de coordonnées (x;y)
|
||||
# un point C du plan de coordonnées (cx;cy) dans le repère défini par XMIN:XMAX et YMIN:YMAX
|
||||
cx = (x * (XMAX - XMIN) / LARGEUR + XMIN)
|
||||
cy = (y * (YMIN - YMAX) / HAUTEUR + YMAX)
|
||||
xn = 0
|
||||
yn = 0
|
||||
n = 0
|
||||
while (xn * xn + yn * yn) < 4 and n < MAX_ITERATION: # on teste que le carré de la distance est inférieur à 4 -> permet d'économiser un calcul de racine carrée coûteux en terme de performances
|
||||
# Calcul des coordonnes de Mn
|
||||
tmp_x = xn
|
||||
tmp_y = yn
|
||||
xn = tmp_x * tmp_x - tmp_y * tmp_y + cx
|
||||
yn = 2 * tmp_x * tmp_y + cy
|
||||
n = n + 1
|
||||
if n == MAX_ITERATION:
|
||||
screen.set_at((x, y), (0, 0, 0)) # On colore le pixel en noir -> code RGB : (0,0,0)
|
||||
else:
|
||||
screen.set_at((x, y), (255, 255, 255)) # On colore le pixel en blanc -> code RGB : (255,255,255)
|
||||
pygame.display.flip() # Mise à jour et rafraîchissement de la fenêtre graphique pour affichage
|
||||
# Boucle infinie permettant d'afficher à l'écran la fenêtre graphique
|
||||
# Sans ça, la fenêtre apparaît et disparaît aussitôt
|
||||
loop = True
|
||||
while loop:
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT: # Pour quitter l'application en fermant la fenêtre
|
||||
loop = False
|
||||
elif event.type == pygame.MOUSEBUTTONDOWN:
|
||||
p = pygame.mouse.get_pos()
|
||||
px = (p[0] * (XMAX - XMIN) / LARGEUR + XMIN)
|
||||
py = (p[1] * (YMIN - YMAX) / HAUTEUR + YMAX)
|
||||
print("({};{})".format(px,py))
|
||||
|
||||
pygame.quit()
|
||||
@@ -0,0 +1,87 @@
|
||||
#from mycontext import Context
|
||||
from PIL import Image, ImageDraw
|
||||
import numpy as np
|
||||
import colors
|
||||
|
||||
def getDiscreteColoredArray(array,color1=colors.WHITE,color2=colors.BLACK):
|
||||
f=lambda n:color1 if n==1 else color2
|
||||
return f(array)
|
||||
|
||||
|
||||
def uselessNameSpace():
|
||||
for y in range(HAUTEUR):
|
||||
for x in range(LARGEUR):
|
||||
# Les deux lignes suivantes permettent d'associer à chaque pixel de l'écran de coordonnées (x;y)
|
||||
# un point C du plan de coordonnées (cx;cy) dans le repère défini par XMIN:XMAX et YMIN:YMAX
|
||||
cx = (x * (XMAX - XMIN) / LARGEUR + XMIN)
|
||||
cy = (y * (YMIN - YMAX) / HAUTEUR + YMAX)
|
||||
xn = 0
|
||||
yn = 0
|
||||
n = 0
|
||||
while (xn * xn + yn * yn) < 4 and n < MAX_ITERATION: # on teste que le carré de la distance est inférieur à 4 -> permet d'économiser un calcul de racine carrée coûteux en terme de performances
|
||||
# Calcul des coordonnes de Mn
|
||||
tmp_x = xn
|
||||
tmp_y = yn
|
||||
xn = tmp_x * tmp_x - tmp_y * tmp_y + cx
|
||||
yn = 2 * tmp_x * tmp_y + cy
|
||||
|
||||
|
||||
|
||||
def showMatrixWithScreen(screen,array,width=None,height=None):
|
||||
if not width or not height:
|
||||
width,height=[len(array),len(array[0])]
|
||||
for x in range(width):
|
||||
for y in range(height):
|
||||
screen.set_at((x, y),array[x][y])
|
||||
|
||||
def showMatrixWithContext(context,array,width=None,height=None):
|
||||
if not width or not height:
|
||||
width,height=[len(array),len(array[0])]
|
||||
for x in range(width):
|
||||
for y in range(height):
|
||||
context.draw.square()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def mandelbrot(z,maxiter):
|
||||
c=z
|
||||
for n in range(maxiter):
|
||||
if abs(z) > 2:
|
||||
return n
|
||||
z=z**2+c
|
||||
return maxiter
|
||||
|
||||
def getMatrix(width=800,height=800,corners=[-2,-1,1,1],maxiter=80):
|
||||
xmin,ymin,xmax,ymax=corners
|
||||
xzoom=(xmax-xmin)/width
|
||||
yzoom=(ymax-ymin)/height
|
||||
matrix=np.zeros([width,height])
|
||||
for x in range(0,width):
|
||||
for y in range(0,height):
|
||||
matrix[x][y]=mandelbrot(complex(xmin+x*xzoom,ymin+y*yzoom),maxiter)
|
||||
return matrix
|
||||
|
||||
def showMatrixWithPIL(matrix,width=None,height=None,maxiter=80,save=True):
|
||||
if (width is None) or (height is None):
|
||||
width,height=[len(matrix),len(matrix[0])]
|
||||
im = Image.new('RGB',(width,height),(0, 0, 0))
|
||||
draw = ImageDraw.Draw(im)
|
||||
for x in range(width):
|
||||
for y in range(height):
|
||||
color=int(matrix[x][y] * 255 / maxiter)
|
||||
draw.point([x, y], (color, color, color))
|
||||
if save: im.save('output.png', 'PNG')
|
||||
im.show()
|
||||
|
||||
|
||||
if __name__=="__main__":
|
||||
#context=Context()
|
||||
#width,height=context.size
|
||||
width=800;height=600;maxiter=20
|
||||
matrix=getMatrix(width,height,maxiter=maxiter)
|
||||
showMatrixWithPIL(matrix,width,height,maxiter=maxiter)
|
||||
@@ -0,0 +1,46 @@
|
||||
import numpy as np
|
||||
from matplotlib import pyplot as plt
|
||||
from matplotlib import colors
|
||||
#%matplotlib inline
|
||||
|
||||
settings=[-2.0,0.5,-1.25,1.25,3,3,80]
|
||||
|
||||
def mandelbrot(z,maxiter):
|
||||
c = z
|
||||
for n in range(maxiter):
|
||||
if abs(z) > 2:
|
||||
return n
|
||||
z = z*z + c
|
||||
return maxiter
|
||||
|
||||
def mandelbrot_set(xmin,xmax,ymin,ymax,width,height,maxiter):
|
||||
r1 = np.linspace(xmin, xmax, width)
|
||||
r2 = np.linspace(ymin, ymax, height)
|
||||
return (r1,r2,[mandelbrot(complex(r, i),maxiter) for r in r1 for i in r2])
|
||||
|
||||
|
||||
def mandelbrot_image(xmin,xmax,ymin,ymax,width=3,height=3,maxiter=80,cmap='hot'):
|
||||
print("Initiating the mandelbrot image.")
|
||||
dpi = 72 #Zoom of the image
|
||||
img_width = dpi * width #Find the width of the image using the zoom and the width of the set
|
||||
img_height = dpi * height #Same operation for the height
|
||||
x,y,z = mandelbrot_set(xmin,xmax,ymin,ymax,img_width,img_height,maxiter) #Find the set
|
||||
print("The set is done.")
|
||||
print(type(z[0]))
|
||||
|
||||
fig, ax = plt.subplots(figsize=(width, height),dpi=72) #get plt components
|
||||
ticks = np.arange(0,img_width,3*dpi) #find the steps
|
||||
x_ticks = xmin + (xmax-xmin)*ticks/img_width #split the x axis
|
||||
plt.xticks(ticks, x_ticks)
|
||||
y_ticks = ymin + (ymax-ymin)*ticks/img_width #split the y axis
|
||||
plt.yticks(ticks, y_ticks)
|
||||
print("Image settings are done.")
|
||||
|
||||
norm = colors.PowerNorm(0.3) #Cool colors i guess
|
||||
ax.imshow(z,cmap=cmap,origin='lower',norm=norm) #create a dope heat map
|
||||
print("Image is done.")
|
||||
|
||||
|
||||
mandelbrot_image(-2.0,0.5,-1.25,1.25,maxiter=80,cmap='gnuplot2')
|
||||
#img=Image.fromarray(ms,'RGB')
|
||||
#img.show()
|
||||
@@ -0,0 +1,31 @@
|
||||
from PIL import Image, ImageDraw
|
||||
from mandelbrot import mandelbrot, MAX_ITER
|
||||
|
||||
# Image size (pixels)
|
||||
WIDTH = 600
|
||||
HEIGHT = 400
|
||||
|
||||
# Plot window
|
||||
RE_START = -2
|
||||
RE_END = 1
|
||||
IM_START = -1
|
||||
IM_END = 1
|
||||
|
||||
palette = []
|
||||
|
||||
im = Image.new('RGB', (WIDTH, HEIGHT), (0, 0, 0))
|
||||
draw = ImageDraw.Draw(im)
|
||||
|
||||
for x in range(0, WIDTH):
|
||||
for y in range(0, HEIGHT):
|
||||
# Convert pixel coordinate to complex number
|
||||
c = complex(RE_START + (x / WIDTH) * (RE_END - RE_START),
|
||||
IM_START + (y / HEIGHT) * (IM_END - IM_START))
|
||||
# Compute the number of iterations
|
||||
m = mandelbrot(c)
|
||||
# The color depends on the number of iterations
|
||||
color = 255 - int(m * 255 / MAX_ITER)
|
||||
# Plot the point
|
||||
draw.point([x, y], (color, color, color))
|
||||
|
||||
im.save('output.png', 'PNG')
|
||||
@@ -0,0 +1,58 @@
|
||||
from PIL import Image, ImageDraw
|
||||
import numpy as np
|
||||
#from mandelbrot import mandelbrot, MAX_ITER
|
||||
|
||||
MAX_ITER = 80
|
||||
|
||||
def mandelbrot(c,maxiter):
|
||||
z = 0
|
||||
n = 0
|
||||
while abs(z) <= 2 and n < maxiter:
|
||||
z = z**2 + c
|
||||
n += 1
|
||||
return n
|
||||
|
||||
# Image size (pixels)
|
||||
|
||||
|
||||
def showPicture(corners=[-2,-1,1,1],width=600,height=400,maxiter=80):
|
||||
xmin,ymin,xmax,ymax=corners
|
||||
|
||||
im = Image.new('RGB', (width,height), (0, 0, 0))
|
||||
draw = ImageDraw.Draw(im)
|
||||
xlength=xmax-xmin
|
||||
ylenght=ymax-ymin
|
||||
|
||||
#from pixel to complex
|
||||
xzoom=xlength/width
|
||||
yzoom=ylenght/height
|
||||
|
||||
for x in range(width):
|
||||
for y in range(height):
|
||||
# Convert pixel coordinate to complex number
|
||||
c = complex(xmin+x*xzoom,ymin+y*yzoom)
|
||||
# Compute the number of iterations
|
||||
m = mandelbrot(c,maxiter)
|
||||
# The color depends on the number of iterations
|
||||
color = int(m * 255 / maxiter)
|
||||
# Plot the point
|
||||
draw.point([x, y], (color, color, color))
|
||||
|
||||
im.save('output.png', 'PNG')
|
||||
im.show()
|
||||
|
||||
def getMatrix(corners=[-2,-1,1,1],width=600,height=400,maxiter=80):
|
||||
xmin,ymin,xmax,ymax=corners
|
||||
xzoom=(xmax-xmin)/width
|
||||
yzoom=ymax-ymin/height
|
||||
matrix=np.zeros([width,height])
|
||||
for x in range(0,width):
|
||||
for y in range(0,height):
|
||||
c = complex(xmin+x*xzoom,ymin+y*yzoom)
|
||||
m = mandelbrot(c,maxiter)
|
||||
matrix[x,y]=m
|
||||
return matrix
|
||||
|
||||
#matrix=getMatrix()
|
||||
#print(len(matrix))
|
||||
showPicture()
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
Reference in New Issue
Block a user