В этой статье я покажу вам, как визуально моделировать электрическое поле между двумя зарядами. Нарисуем линии, соответствующие напряженности электричества в данной точке. Код написан на P5.js, хотя вы можете использовать эту концепцию для получения тех же результатов на языке программирования по вашему выбору.

Электромагнитная интенсивность

Напряженность электрического поля определяется следующим уравнением:

где Q - заряд, r - расстояние, а k - константа, которую в этом моделировании мы можем изменить в соответствии с нашими потребностями.

Объект заряда

Первое, что нам нужно сделать, это определить объект заряда. В нашем определении заряд будет иметь 3 свойства: координату x, координату y и значение.

function Charge(x,y,v){
this.x = x
this.y = y
this.v = v 
}

Мы также хотим отображать заряд на экране, поэтому нам нужно определить функцию display (). Заряд будет представлен в виде круга синего или красного цвета в зависимости от его значения.

this.display = function(){
    if(this.v>0){ 
        fill(255,0,0,100);
        }    
    else if (this.v<0){
        fill(0,0,255,100);      
        }    
    stroke(0);    
    strokeWeight(1);    
    ellipse(this.x,this.y,15,15);    
                          }

Теперь нам нужно инициализировать объект в функции setup ().

function setup() {
    createCanvas(800, 700);
    c1 = new Charge(100,200,30)
    c2 = new Charge(600,500,-20)
}

А позже мы должны вызвать функцию display () в функции draw ().

function draw() {
   background(220);
   c1.display()
   c2.display()
}

Результат должен выглядеть так:

Сетки

Теперь нам нужно погрузить наш холст в конец сетки, а затем в каждой ячейке мы должны вычислить интенсивность поля. Это очень важно для целей оптимизации. Если бы мы рассчитывали интенсивность в каждый данный момент, мы наверняка потеряли бы некоторую частоту кадров, но если мы будем использовать сетку, каждый раз, когда мы хотим нарисовать линию, нам просто нужно получить доступ к предварительно рассчитанному значению в сетке.

Во-первых, нам нужно настроить некоторые глобальные переменные: res, grid_X и grid_Y, разрешение будет размером каждой ячейки, а grid_X и grid_Y будут двухмерными массивами, хранящими компоненты x и y вектора интенсивности. Обратите внимание, что нам нужно установить эти переменные в начале скрипта вне какой-либо функции.

var res=10
var grid_X
var grid_Y

Затем нам нужно создать двумерные массивы в функции настройки:

function setup() {
    createCanvas(700, 700);
 
    grid_X = new Array(width/res);
    grid_Y = new Array(width/res);
    
    for (var i = 0; i < width/res; i++) {
        grid_X[i] = new Array(height/res);
        grid_Y[i] = new Array(height/res);
     }
    c1 = new Charge(100,200,30)
    c2 = new Charge(600,500,-20)
 }

Затем мы нарисуем сетку на холсте, чтобы упростить задачу.

function drawGrid(){
    stroke(0,50)
    for(var i=0; i<width;i+=20){
        line(0,i,width,i)
        line(i,0,i,height)
    }
}

Затем нам нужно поместить функцию drawGrid () в функцию draw (). Результат должен выглядеть так:

Теперь для каждой ячейки в сетке нам нужно рассчитать электрическую напряженность и записать значения в массивы. Во-первых, нам нужно преобразовать позиции i и j в сетке в позиции x и y на холсте, мы хотим, чтобы эти точки были в центре ячеек, поэтому мы добавляем к нему res / 2. Следующим шагом является вычисление компонент x и y расстояния, а затем вычисление расстояния с помощью теоремы Питагора. Затем нам нужно вычислить компоненты интенсивности по осям x и y. Мы делаем это для обеих ячеек, а затем складываем компоненты вместе. Последний шаг - нормализовать значения, чтобы каждая строка имела одинаковую длину, и сохранить их в массивах.

function vectorGrid(){
    print("Vector grid")
    var x1 = 0;
    for(var  i=0; i<height/res; i++){
        for(var  j=0; j<height/res; j++){
            x = res/2 + i*res
            y = res/2 + j*res
            
            dx = x-c1.x;
            dy = y-c1.y;
            d1 = sqrt(dx*dx+dy*dy);
            E1 = c1.v/(d1*d1);
            E1x = dx*E1/d1;
            E1y = dy*E1/d1;
            dxn = x-c2.x;
            dyn = y-c2.y;
            d2 = sqrt(dxn*dxn+dyn*dyn);
            E2 = c2.v/(d2*d2);
            E2x = dxn*E2/d2;
            E2y = dyn*E2/d2;
            EEx = E1x+E2x;
            EEy = E1y+E2y;
            EE = sqrt(EEx*EEx + EEy*EEy);
deltax = 15*EEx/EE;
   deltay = 15*EEy/EE;
     grid_X[i][j] = deltax
   grid_Y[i][j] = deltay
  
     
 
  }
 
} 
}

Затем нам нужно поместить функцию vectorGrid () в функцию setup (), которая будет вызываться в начале.

Рисование линий

Последнее, что нам нужно сделать, это написать функцию, которая рисует линии. Мы нарисуем линии в 5000 случайных точках на холсте. После того, как мы выбрали случайные точки, нам нужно преобразовать их в положение в сетке. Затем рисуем линии.

function drawLines(){
    for(var i=0; i<5000; i++){
        x = random(width);
        var xf = floor(x/(res));
        y = random(height);
        var yf = floor(y/(res));
        stroke(0,70)
        line(x, y, x + grid_X[xf][yf], y + grid_Y[xf][yf])
     }
}

Затем мы можем поместить функцию drawLines () в функцию draw () для непрерывного рисования линий.

Окончательный результат должен выглядеть так:

И окончательный код выглядит так:

Последние мысли

Конечно, вы можете поиграть со скриптом, изменив такие параметры, как разрешение, длину строк и их количество. Вы также можете переместить функцию drawLines () в setup (), чтобы линии рисовались только один раз. Если вам интересно, вы можете увидеть более продвинутую версию симуляции здесь: