UNPKG

remove-overlaps

Version:

Given set of N circles at predefined positions attempts to remove overlap between circles

55 lines (43 loc) 1.92 kB
/** * Performs removal of overal between two circular nodes */ var clamp = require('./clamp.js'); module.exports = { intersectQuad: function(currentNode, quad) { // Continue subdivision only if current circle intersects our quad // Find the closest point to the circle within the rectangle var closestX = clamp(currentNode.x, quad.left(), quad.x + quad.half); var closestY = clamp(currentNode.y, quad.top(), quad.y + quad.half); // Calculate the distance between the circle's center and this closest point var dx = currentNode.x - closestX; var dy = currentNode.y - closestY; // If the distance is less than the circle's radius, an intersection occurs var distanceSquared = dx * dx + dy * dy; return distanceSquared < (currentNode.r * currentNode.r); }, removeOverlap: function(currentNode, otherNode) { var dx = currentNode.x - otherNode.x; var dy = currentNode.y - otherNode.y; var distance = Math.sqrt(dx * dx + dy * dy); var totalRadius = otherNode.r + currentNode.r; if (totalRadius <= distance) return 0; // they are not overlapping! // Otherwise we should move each node in opposite direction, so that distance // is equal to totalRadius var offset = (distance - totalRadius)/distance * 0.5; var mx = dx * offset; var my = dy * offset; currentNode.x -= mx; currentNode.y -= my; otherNode.x += mx; otherNode.y += my; return Math.abs(mx) + Math.abs(my); }, validate: function(positions) { positions.forEach(validatePosition) } }; function validatePosition(p) { if (p.x === undefined) throw new Error('[circular overlap removal] x coordinate must be defined ' + p) if (p.y === undefined) throw new Error('[circular overlap removal] y coordinate must be defined ' + p) if (p.r === undefined) throw new Error('[circular overlap removal] r circle radius must be defined ' + p) }