Skip to content

Selective Wind #2085

@bptarpley

Description

@bptarpley

This feature request is to make the "wind" feature more robust. The idea is to make it configurable such that a wind from a particular direction will blow nodes that belong to particular groups.

Let's assume, for instance, that we set the "group" attribute on 100 nodes--specifically, for the first 25 set that attribute to "a", for the next 25 set "b", next 25 set "c", and the last 25 set "d".

Let's also assume that we can pass in a "wind" specification to the groups module:

groups: {
  a: {
    color: "red",
    wind: { x: 0, y: -1 }
  },
  b: {
    color: "blue",
    wind: { x: 0, y: 1 }
  },
  c: {
    color: "green",
    wind: { x: 1, y: 0 }
  },
  d: {
    color: "yellow",
    wind: { x: -1, y: 0 }
  },
}

Then, upon running the physics simulation, a "wind" effectively blows all nodes with "group" set to "a" northward, all set to "b" southward, all set to "c" eastward, and all set to "d" westward.

The use case for such a feature would be to help tease out and organize particularly messy graphs with heterogeneous types of nodes.

I was able to make this work with the following hack, so it should be relatively easy to implement. I'd make a pull request but I'm fuzzy on how to validate the available options, update the documentation, etc:

this.network.physics._performStep = function(nodeId) {
    const node = this.body.nodes[nodeId];
    const force = this.physicsBody.forces[nodeId];

    // THIS IS THE HACK. IT'S HACKY BECAUSE IT PRESUMES THAT A "wind" OBJECT EXISTS
    // IN THE GROUPS CONFIGURATION
    if (node.options.hasOwnProperty('group')) {
        force.x += this.options.groups[node.options.group].wind.x;
        force.y += this.options.groups[node.options.group].wind.y;
    } 

    const velocity = this.physicsBody.velocities[nodeId];

    // store the state so we can revert
    this.previousStates[nodeId] = {
        x: node.x,
        y: node.y,
        vx: velocity.x,
        vy: velocity.y,
    };

    if (node.options.fixed.x === false) {
        velocity.x = this.calculateComponentVelocity(
            velocity.x,
            force.x,
            node.options.mass
        );
        node.x += velocity.x * this.timestep;
    } else {
        force.x = 0;
        velocity.x = 0;
    }

    if (node.options.fixed.y === false) {
        velocity.y = this.calculateComponentVelocity(
            velocity.y,
            force.y,
            node.options.mass
        );
        node.y += velocity.y * this.timestep;
    } else {
        force.y = 0;
        velocity.y = 0;
    }

    const totalVelocity = Math.sqrt(
        Math.pow(velocity.x, 2) + Math.pow(velocity.y, 2)
    );
    return totalVelocity;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions