step method

void step()

Run one step of the simulation.

Implementation

void step() {
  if (_currentIteration >= iterations || _temperature < 0.1) {
    return;
  }

  // Calculate repulsive forces between all pairs of nodes
  final forces = List<Offset>.filled(nodes.length, Offset.zero);

  for (var i = 0; i < nodes.length; i++) {
    for (var j = i + 1; j < nodes.length; j++) {
      final delta = nodes[i].position - nodes[j].position;
      final distance = delta.distance.clamp(0.1, double.infinity);
      final force = _repulsiveForce(distance);

      final normalized = delta / distance;
      final forceVector = normalized * force;

      forces[i] = forces[i] + forceVector;
      forces[j] = forces[j] - forceVector;
    }
  }

  // Calculate attractive forces along edges
  for (final edge in edges) {
    final sourceIndex = nodes.indexWhere((n) => n.id == edge.sourceId);
    final targetIndex = nodes.indexWhere((n) => n.id == edge.targetId);

    if (sourceIndex == -1 || targetIndex == -1) continue;

    final delta = nodes[sourceIndex].position - nodes[targetIndex].position;
    final distance = delta.distance.clamp(0.1, double.infinity);
    final force = _attractiveForce(distance);

    final normalized = delta / distance;
    final forceVector = normalized * force;

    forces[sourceIndex] = forces[sourceIndex] - forceVector;
    forces[targetIndex] = forces[targetIndex] + forceVector;
  }

  // Apply forces with temperature limiting
  for (var i = 0; i < nodes.length; i++) {
    if (nodes[i].isFixed) continue;

    final force = forces[i];
    final magnitude = force.distance;
    final limited = magnitude > _temperature ? _temperature : magnitude;

    if (magnitude > 0) {
      final normalized = force / magnitude;
      final displacement = normalized * limited;
      var newPosition = nodes[i].position + displacement;

      // Keep within bounds
      newPosition = Offset(newPosition.dx.clamp(50.0, width - 50), newPosition.dy.clamp(50.0, height - 50));

      nodes[i] = nodes[i].copyWith(position: newPosition);
    }
  }

  // Cool down
  _temperature *= coolingFactor;
  _currentIteration++;
}