Случайная прогулка с плавным изменением направления - PullRequest
0 голосов
/ 30 января 2019

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

Как настроить функцию случайного блуждания, чтобы иметь более плавные изменения направления?

Моя главнаяИдея состоит в том, чтобы иметь метод, который генерирует новую точку с координатами x и y, но следит за предыдущим шагом и уменьшает размер следующего шага (const radius), если поворот (изменение направления) приближается к 180 °.

Поэтому я использую D3js , чтобы случайным образом сделать новый шаг в любом направлении x и y.В конце я получу массив всех прошлых шагов, ограниченный максимальным количеством шагов.Радиус указывает, как долго должен выполняться средний шаг по осям x и y '.

const history = [];
const steps = 10;
const radius = 1;

let point = {
  x: 0,
  y: 0,
  radians: null
};

for (let i = 0; i < steps; i++) {
  console.log(point);
  history.push(point);

  const previousPoint = Object.assign({}, point);

  point.x += radius * d3.randomNormal(0, 1)();
  point.y += radius * d3.randomNormal(0, 1)();
  point.radians = Math.atan2(
    point.y - previousPoint.y, 
    point.x - previousPoint.x
  );
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.8.0/d3.js"></script>

1 Ответ

0 голосов
/ 30 января 2019

Вместо использования случайного блуждания на основе координат я решил случайным образом генерировать для каждой итерации новые радианы.Таким образом, новые и предыдущие радианы можно сравнить друг с другом, чтобы определить скорость, с которой будет получена новая точка.В зависимости от минимального диапазона между этими радианами будет установлена ​​волатильность.После этого нужно просто вычислить синус и косинус, чтобы сгенерировать координаты новой точки.

По крайней мере, я достиг своей конечной цели: https://beta.observablehq.com/@nextlevelshit/gentlemans-random-walk-part-3

const steps = 10;
const stepSize = 10;

let point = {
  x: 0,
  y: 0,
  radians: randomRadians(),
  velocity: 0
};

for (let i = 0; i < steps; i++) {
  console.log(point);

  const radians = randomRadians();
  const velocity = 1 - minimumDifference(radians, point.radians) / Math.PI;
  
  point = {
    // Coordinates calculated depending on random radians and velocity
    x: Math.sin(radians * Math.PI) * stepSize * velocity + point.x,
    y: Math.cos(radians * Math.PI) * stepSize * velocity + point.y,
    radians: radians, // Randomly generated radians
    velocity: velocity // Velocity in comparison to previous point
  };
}

function randomRadians() {
  return randomFloat(- Math.PI, Math.PI);
}

function randomFloat(min, max) {
  return Math.random() * (max - min) + min;
}

function minimumDifference(x, y) {
  return Math.min((2 * Math.PI) - Math.abs(x - y), Math.abs(x - y));
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.8.0/d3.js"></script>
...