Yassine
Yassine

Reputation: 33

contour deformation in python

I have a contour map and I want to make a deformation of all the contour lines, where the contour of level 0.5 will be deformed around the blue point situated in his line and then pass on the blue point on the contour of level 1, and so on.

Original map :
original map

Deformed map :
deformed map

I think there are two steps, the first one is the delete some parts of the map and the second is to redraw the contour map.

I think i have to iterate through the contour map like this:

CS = plt.contour(X, Y, Z)
for level in CS.collections:
    for kp, path in list(enumerate(level.get_paths())):

But I have no idea how to use kp and path

Any tips for doing this would be appreciated!

Upvotes: 2

Views: 1530

Answers (1)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339430

Here is an example on how you could change the contour plot to achieve the intended deformation.
It generates some data x,y,z which should later be modified. Then it specifies a deformation function, which when multiplied to z deforms the data in the desired way. This deformation function takes the x and y data as input as well as the angle of the line along which to perform the deformation and a width (spread) of the deformation. Finally a parameter i is used for stearing the degree of deformation (i.e. i=0 means no deformation). Of course you can use any other function to deform your contour.

enter image description here

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation

#### generate some x,y,z data ####
r = np.linspace(0,6,  num=100)
phi = np.linspace(0, 2*np.pi, num=200)
R, Phi = np.meshgrid(r,phi)
x = R*np.cos(Phi)
y = R*np.sin(Phi)
z = R
##################################

fig, ax=plt.subplots()
ax.set_aspect("equal")

def update(i):
    ax.clear()
    f = lambda x,y, offs, width, i: 1-i*np.exp(-(np.arctan2(x,y)-offs)**2/width)  
    z_deformed = z*f(x,y, np.pi/4, 1./8., i=i)
    ax.contour(x,y,z_deformed, 10, linewidths=4)
    ax.contourf(x,y,z_deformed, 10, alpha=0.3)
    ax.set_xlim([-4,4])
    ax.set_ylim([-4,4])

update(0) #plot the original data
anipath = 0.5*np.sin(np.linspace(0, np.pi, num=20))**2
ani = matplotlib.animation.FuncAnimation(fig, update, frames=anipath, interval = 100)

plt.show()

Of course you can use other shapes of deformation. E.g. to get a triangular shape use

f = lambda x, A, a, b: A*(1.-np.abs((x-b)/a))*(np.abs((x-b)) < a )
z_deformed = z - f(np.arctan2(x,y), i, 1./8., np.pi/4 )

Upvotes: 2

Related Questions