-1

A typical random walk does not care about direction changes. Each iteration generates a new direction. But if you imagine a point animated on a random walk, it will mostly jump around. So, the goal is to have a smoother curve depending on the previously calculated points.

How to adjust a random walk function to have smoother directional changes?

My main idea is to have a method that generates a new point with x and y coordinates, but looks after the previous step and decreases the size of the next step (const radius), if the rotation (directional change) comes closer to 180°.

Therefore, I am using D3js to randomly take a new step in any x and y direction. At the end I'll get an array of all past steps limited by the maximum amount of steps. The radius gives an orientation how long an average step should be taking on the x and y axis'.

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>
Michael W. Czechowski
  • 3,366
  • 2
  • 23
  • 50

1 Answers1

2

Instead of using a coordinates based random walk, I decided to randomly generate each iteration a new radians. So the new and previous radians can be compared to each others to decide with velocity the new point will get. Depending on the minimum range between these radians' the volicity will be set. Afterwards a simple sine and cosine calculation have to be down to generate the coordinates of the new point.

At least I've achieved my final goal: 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>
Michael W. Czechowski
  • 3,366
  • 2
  • 23
  • 50