# snapping code: from separate checks to 1 formula

I'm working on a 3D-project with three.js and webGl. I've written a function to check for 2 objects to be near each other and thus "snap" to each other.

The objects don't move on the Y-axis, so I only have to check the 4 sides of each object against the side of all other objects in the scene. At the moment I'm doing that with this code:

for (var i = 0; i < elements.length; i++) {

var newBox = updateBoundingBox(elements[i]);

var snapped = null;

if (newBox.min.x - box.max.x < 5 && newBox.min.x - box.max.x > -box.size().x / 2//5
&& box.max.z > newBox.min.z && box.min.z < newBox.max.z) {

activeElement.position.x = newBox.min.x - ((box.max.x - box.min.x) / 2) - 0.5;
box = updateBoundingBox(activeElement);
snapped = [elements[i], "X"];
}

if (newBox.min.z - box.max.z < 5 && newBox.min.z - box.max.z > -box.size().z / 2//5
&& box.max.x > newBox.min.x && box.min.x < newBox.max.x) {

activeElement.position.z = newBox.min.z - ((box.max.z - box.min.z) / 2) - 0.5;
box = updateBoundingBox(activeElement);
snapped = [elements[i], "Z"];

}

if (box.min.x - newBox.max.x < 5 && box.min.x - newBox.max.x > -box.size().x / 2
&& box.max.z > newBox.min.z && box.min.z < newBox.max.z) {

activeElement.position.x = newBox.max.x + ((box.max.x - box.min.x) / 2) + 0.6;
box = updateBoundingBox(activeElement);
snapped = [elements[i], "X"];

}

if (box.min.z - newBox.max.z < 5 && box.min.z - newBox.max.z > -box.size().z / 2
&& box.max.x > newBox.min.x && box.min.x < newBox.max.x) {

activeElement.position.z = newBox.max.z + ((box.max.z - box.min.z) / 2) + 0.5;
box = updateBoundingBox(activeElement);
snapped = [elements[i], "Z"];

}

if (snapped != null) {

activeElement.snapped.push(snapped);
debug.snapped = true;
}

}


But, it is very obvious that the 4 if-statements are almost identical, so I was wondering if it was possible to write them in a better/shorter way so I can just loop over them?

1) Do not hard-code the distance that will define 'near', but rather make it a variable/parameter.
2) Split the solution : 1) do we 'approximatively' overlap ? and 2) are we on the left or right, and are we up or down ?
3) Use as much 'standard' code as you can : here 'update' will define a BBox based on a list of points, 'expand' and 'overlaps' will do what-you-guess.

var nearDistance = 5;
var newBox new BoundingBox();
var boxSize = null;

for (var i = 0; i < elements.length; i++) {
var thisElement = elements[i];

// newBox is now the BBox of thisElement
newBox.update(thisElement);

// do we approximatively overlap ?
newBox.expand(nearDistance);
var overlaps = newBox.overlaps(box);
if (!overlaps) continue;

// are we on the left/right, up/down ??

newBox.expand(-nearDistance);
boxSize = box.size() ;

var newXPosition = -1, newZPosition = -1;

if ( newBox.min.x - box.max.x > -boxSize.x / 2) {
// left
newXPosition = newBox.min.x - ((box.max.x - box.min.x) / 2) - 0.5;
} else {
// right
newXPosition = newBox.max.x + ((box.max.x - box.min.x) / 2) + 0.6;
}

if (newBox.min.z - box.max.z > -boxSize.z / 2 ) {
// up
newZPosition = newBox.min.z - ((box.max.z - box.min.z) / 2) - 0.5;
} else {
// down
newZPosition= newBox.max.x + ((box.max.x - box.min.x) / 2) + 0.6;
}