Julia Set Viewer

Я пытался настроить средство просмотра набора julia на своем сайте http://thejamespaterson.com/scripts/julia/, но в настоящее время у меня возникают проблемы с настройкой программы для отображения правильного набора параметров julia. Например, при тестировании со значением C 0+0i я получаю следующее изображение: не правильный набор джулии Результатом должен быть круг. Я не уверен, почему это происходит. Я написал свою собственную библиотеку комплексных чисел и функции построения графиков, и они размещены ниже. Любая помощь будет оценена;

function complexNum(real, imaginary) {
  this.real = real;
  this.imaginary = imaginary;
  return this;
}

function addComplex(c1, c2) {
  this.real = c1.real + c2.real;
  this.imaginary = c1.imaginary + c2.imaginary;
  return this;
}

function multComplex(c1, c2) {
  this.real = (c1.real * c2.real) - (c1.imaginary * c2.imaginary);
  this.imaginary = (c1.real * c2.imaginary) + (c2.real * c1.imaginary);
  return this;
}

function dispComplex(c) {
  var sign = '';
  if (c.imaginary >= 0) {
    sign = '+';
  }
  return c.real + sign + c.imaginary + "i";
}

function getComplexModulus(c) {
  return Math.sqrt((c.real * c.real) + (c.imaginary * c.imaginary));
}

//globals
var MAXITERATION = 100;
var BOUNDARY = 4;
var CANVASID = "juliaDraw";
var CONTEXT = document.getElementById("juliaDraw").getContext('2d');
var HEIGHT = 750;
var WIDTH = 750;
var juliaImageData = CONTEXT.createImageData(WIDTH, HEIGHT);

function readInput(inputID) {
  return document.getElementById(inputID).value;
}

function drawPointOnCanvas(x, y, color) {
  //console.log('drawing pixel at '+x+','+y);
  CONTEXT.fillStyle = color;
  CONTEXT.fillRect(x, y, 1, 1);
}

function createArray(length) {
  var arr = new Array(length || 0),
    i = length;
  if (arguments.length > 1) {
    var args = Array.prototype.slice.call(arguments, 1);
    while (i--) arr[length - 1 - i] = createArray.apply(this, args);
  }
  return arr;
}

function doesPointEscape(c, complexNum) {
  var iterations = 0;
  var escaped = false;
  while ((!escaped) && (iterations < MAXITERATION)) {
    if (getComplexModulus(complexNum) > BOUNDARY) {
      escaped = true;
    }
    complexNum = addComplex(multComplex(complexNum, complexNum), c);
    iterations++;
  }
  if (escaped) {
    return true;
  } else {
    return false;
  }
}

function plotJuliaSet(canvasID, width, height, c, start, stepsize) {
  var complexNumberArray = createArray(width + 1, height + 1);
  var doesPointEscapeArray = createArray(width + 1, height + 1);
  var real = start.real;
  var imaginary = start.imaginary;
  console.log('====Drawing Set====');
  console.log('c = ' + dispComplex(c));
  for (var x = 0; x <= width; x++) {
    imaginary = start.imaginary;
    for (var y = 0; y <= height; y++) {
      complexNumberArray[x][y] = new complexNum(real, imaginary);
      doesPointEscapeArray[x][y] = doesPointEscape(c, complexNumberArray[x][y]);
      if (doesPointEscapeArray[x][y]) {
        //drawPointOnCanvas(x, y,'blue');
      } else {
        drawPointOnCanvas(x, y, 'black');
        //console.log('point '+dispComplex(complexNumberArray[x][y])+' does not escape');
      }
      imaginary = imaginary - stepsize;
    }
    real = real + stepsize;
  }
  //CONTEXT.putImageData(juliaImageData, 0, 0);
  console.log('done');
}

function defaultDraw() {
  CONTEXT.clearRect(0, 0, WIDTH, HEIGHT);
  var start = new complexNum(-2, 2);
  var c = new complexNum(0, 0);
  plotJuliaSet(CANVASID, WIDTH, HEIGHT, c, start, 2 / 350);
}

function drawJulia() {
  CONTEXT.clearRect(0, 0, WIDTH, HEIGHT);
  var start = new complexNum(-2, 2);
  var c = new complexNum(readInput('realValue') * 1, readInput('imagValue') * 1);
  plotJuliaSet(CANVASID, WIDTH, HEIGHT, c, start, 2 / 350);
}
<!doctype html>
<html>

<head>
  <title>Julia Set Viewer</title>
  <style>
    .desc {
      float: right;
      width: 300px;
    }
    #juliaDraw {
      border: 1px dotted;
      float: left;
    }
  </style>
</head>

<body>
  <div class="desc">
    <h1>Julia Set Viewer</h1>
    <p>You can view Julia sets with this simple online tool. Don't know what a Julia set is? Learn about it <a href="https://www.youtube.com/watch?v=2AZYZ-L8m9Q">here.</a>
      This script uses a complex number library that I built to handle the arithmetic required to process these images. The source code is hosted on my <a href="https://github.com/jamjar919">github.</a>
    </p>
  </div>
  <canvas id="juliaDraw" width=750 height=750 onClick="defaultDraw()"></canvas>
  <div class="controls">
    <form>
      <label>Real:
        <input type="text" id="realValue" value="0">
      </label>
      <label>Imag:
        <input type="text" id="imagValue" value="0">
      </label>
      <input type="button" onClick="drawJulia()">
    </form>
  </div>
  <script src="complex.js"></script>
  <script src="juliaset.js"></script>
</body>

</html>

1 ответ

Решение

Проблема возникает из-за путаницы по поводу использования this указатель в Javascript.

Измените вычисление Джулии в doPointEscape() на

complexNum = new addComplex(new multComplex(complexNum, complexNum), c);

и это работает.

Это вернет новый комплексный номер из multComplex, затем добавит его в c и вернет новый комплексный номер из addComplex, который назначен complexNum.

Ваши функции multComplex и addComplex используют this указатель, но для this указатель, который ссылается на один из ваших комплексных чисел, вы должны были бы вызвать функцию на существующий или вызов new создать новый.

Кроме того, вы можете переписать ваши функции multComplex() и addComplex() как

function multComplex(c1, c2) {
    var real = (c1.real * c2.real) - (c1.imaginary * c2.imaginary);
    var imaginary = (c1.real * c2.imaginary) + (c2.real * c1.imaginary);
    return new ComplexNum(real, imaginary);
}

function addComplex(c1, c2) {
    var real = c1.real + c2.real;
    var imaginary = c1.imaginary + c2.imaginary;
    return new ComplexNum(real, imaginary);
}

тогда ваша функция doPointEscape() должна работать как есть.

Другие вопросы по тегам