# Force directed graph: bounding box

In this example we’ll keep the force directed graph constrained inside a box. The nodes won’t be able to go outside.

The basic gist of it is that you impose a constraint that takes effect on every tick of the simulation.  You can either put this code inside the tick function, or you can define a custom force to do the work for you.

Let’s go through both methods.

The first method is to put the constraints inside the tick function. Click above to see this method in action!

Here’s the relevant code.

function tickActions() {
//constrains the nodes to be within a box
node
.attr("cx", function(d) { return d.x = Math.max(radius, Math.min(width - radius, d.x)); })
.attr("cy", function(d) { return d.y = Math.max(radius, Math.min(height - radius, d.y)); });

.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
}


The other option is to define a custom force that applies on every tick.  Like before, click on the above picture to see this method in action.

Look at the below code:

//custom force to put stuff in a box
function box_force() {
for (var i = 0, n = nodes_data.length; i < n; ++i) {
curr_node = nodes_data[i];
}
}

simulation
.force("charge_force", charge_force)
.force("center_force", center_force)
.force("box_force", box_force)
;


We define the custom force box_force()  that implements the constraint for us. In this custom force we loop through every node and update its x and y position to be constrained inside the box.

You then add the force to the simulation like you’d apply any other force.

We also need to ensure that we can’t drag the nodes out of the graph ourselves with the mouse. To fix this we can modify the drag function to impose the same constraint as the custom force:

//make sure you can't drag the circle outside the box
function drag_drag(d) {
}


Click here if you need a reminder of how drag and drop works in d3.

This is why you’ve got the iterations parameter for the collideForce and the linkForce: to have the option to negate the soft force. We haven’t implemented the iterations parameter here in this custom function.