Vector field averaging code not smoothing together?

Am new to python and stackoverflow so I don’t know all the etiquette of the site.

So, I have created a random field of vectors with length 1, and I am trying to write code that will adjust each value to the average of its 4 neighbours. I have written this code:

s= size of field, l = amount of times to loop

def fill_vec(s,r,l):
    dfl_array_vec= df_array_vec
    for i in range (0,l):
        arraynew=pd.DataFrame()
        for j in range (0,s):
            for k in range (0,s):
                found = dfl_array_vec.at[j,k]
                foundS= math.sin(found)
                foundC= math.cos(found)
                SurroundS= 0
                SurroundC=0
                am=0
                if not j == 0:
                    SurroundS = SurroundS +math.sin(dfl_array_vec.at[j-1,k])
                    SurroundC = SurroundC + math.cos(dfl_array_vec.at[j - 1, k])
                    am += 1
                if not j == s-1:
                    SurroundS = SurroundS + math.sin(dfl_array_vec.at[j + 1, k])
                    SurroundC = SurroundC + math.cos(dfl_array_vec.at[j + 1, k])
                    am += 1
                if not k == 0:
                    SurroundS = SurroundS + math.sin(dfl_array_vec.at[j,k-1])
                    SurroundC = SurroundC + math.cos(dfl_array_vec.at[j, k - 1])
                    am += 1
                if not k == s-1:
                    SurroundS = SurroundS + math.sin(dfl_array_vec.at[j, k + 1])
                    SurroundC = SurroundC + math.cos(dfl_array_vec.at[j, k + 1])
                    am += 1
                SurroundS = (SurroundS/am)
                SurroundC = (SurroundC/am)
                distance = math.sqrt(SurroundS**2+ SurroundC**2)
                SurroundS = SurroundS * 1/distance
                SurroundC = SurroundC *1/distance
                foundS += SurroundS
                foundC += SurroundC
                foundS = foundS/2
                foundC = foundC/2
                angle =math.atan2(foundS,foundC)
                arraynew.at[j,k] =(angle*180/math.pi) +180
        dfl_array_vec = arraynew
        print(i)
    return dfl_array_vec

def makeArrayVec(s):

    dfl_array_vec=pd.DataFrame()
    for i in range (0,s):
        for j in range (0,s):
            zval=(random.randrange(0,360))
            dfl_array_vec.at[i,j] = zval
    return dfl_array_vec

df_array_vec= makeArrayVec(s=size)
df_array_vec= fill_vec(s=size,r = 10,l=100)

def vecfieldshow(data):
    xi=np.linspace(0,size,num=size)
    yi = np.linspace(0, size, num=size)
    X,Y=np.meshgrid(xi,yi)
    U=np.sin(data.values)
    V=np.cos(data.values)
    fig=plt.figure()
    ax=fig.add_subplot(111)
    Q=ax.quiver(X,Y,U,V)
    plt.show()

This is what happens when I run the code

But this example is more like what I want img credit https://medium.com/universe-factory/generating-continents-procedurally-with-distortion-fields-d17dd85d5339

Have tried changing the amount the surrounding vectors are weighted for the averaging already, did not change the amount of randomness.

Any help will be appreciated.https://medium.com/universe-factory/generating-continents-procedurally-with-distortion-fields-d17dd85d5339

Answer

Your primary issue is that you’ve used trigonometry functions that accept values in radians but you’ve given them degrees. This turns your code into something resembling a random number generator. I’ve fixed that issue in the code below but haven’t checked the arithmetic.

By the way, this implementation is very slow, probably because you are using a pandas df as an array. Try using numpy arrays instead and I would expect this to be perhaps 100x faster. Also you are continually calling sine and cosine functions on the same cells. You would probably be better off representing the vectors using the normal (x,y) format and then you could just use a simple average on the x and y components and correct the magnitude at the end. output

import pandas as pd
import math
import random
import numpy as np
from matplotlib import pyplot as plt

def fill_vec(s,r,l):
    dfl_array_vec= df_array_vec
    for i in range (0,l):
        arraynew=pd.DataFrame()
        for j in range (0,s):
            for k in range (0,s):
                found = dfl_array_vec.at[j,k]
                foundS= math.sin(found)
                foundC= math.cos(found)
                SurroundS= 0
                SurroundC=0
                am=0
                if not j == 0:
                    SurroundS = SurroundS +math.sin(dfl_array_vec.at[j-1,k])
                    SurroundC = SurroundC + math.cos(dfl_array_vec.at[j - 1, k])
                    am += 1
                if not j == s-1:
                    SurroundS = SurroundS + math.sin(dfl_array_vec.at[j + 1, k])
                    SurroundC = SurroundC + math.cos(dfl_array_vec.at[j + 1, k])
                    am += 1
                if not k == 0:
                    SurroundS = SurroundS + math.sin(dfl_array_vec.at[j,k-1])
                    SurroundC = SurroundC + math.cos(dfl_array_vec.at[j, k - 1])
                    am += 1
                if not k == s-1:
                    SurroundS = SurroundS + math.sin(dfl_array_vec.at[j, k + 1])
                    SurroundC = SurroundC + math.cos(dfl_array_vec.at[j, k + 1])
                    am += 1
                SurroundS = (SurroundS/am)
                SurroundC = (SurroundC/am)
                distance = math.sqrt(SurroundS**2+ SurroundC**2)
                SurroundS = SurroundS * 1/distance
                SurroundC = SurroundC *1/distance
                foundS += SurroundS
                foundC += SurroundC
                foundS = foundS/2
                foundC = foundC/2
                angle =math.atan2(foundS,foundC)
                arraynew.at[j,k] = angle
        dfl_array_vec = arraynew
        print(i)
    return dfl_array_vec

def makeArrayVec(s):

    dfl_array_vec=pd.DataFrame()
    for i in range (0,s):
        for j in range (0,s):
            zval=(random.randrange(0,360))
            dfl_array_vec.at[i,j] = math.pi * zval/180
    return dfl_array_vec

def vecfieldshow(data):
    xi=np.linspace(0,size,num=size)
    yi = np.linspace(0, size, num=size)
    X,Y=np.meshgrid(xi,yi)
    U=np.sin(data.values)
    V=np.cos(data.values)
    fig=plt.figure()
    ax=fig.add_subplot(111)
    Q=ax.quiver(X,Y,U,V)
    plt.show()

size = 10
df_array_vec= makeArrayVec(s=size)
df_array_vec= fill_vec(s=size,r = 10,l=100)

vecfieldshow(df_array_vec)