Reputation: 2346
I have two hexagons which I am trying to make snap together when the edges hit a certain tolerance.
How can I find which edges are the closest?
Here is the code returning the two closest Hexagons:
Canvas.getClosestPiece = function(){
var current = {};
current.x = selection.MidPoint.X;
current.y = selection.MidPoint.Y;
smallestDistance = null;
closestHex = null;
hexagons.forEach(function(hexagon){
if(hexagon !== selection){
testPiece = {};
testPiece.x = hexagon.MidPoint.X;
testPiece.y = hexagon.MidPoint.Y;
if((lineDistance(current, testPiece) < smallestDistance) || smallestDistance === null){
smallestDistance = lineDistance(current, testPiece)
closestHex = hexagon
hexagons.forEach(function(hexagon){
hexagon.lineColor = 'grey'
})
hexagon.lineColor = 'red';
}
}
})
// console.log(smallestDistance)
return [selection, closestHex]
}
Distance between two hexagon midpoints:
function lineDistance( point1, point2 ){
var xs = 0;
var ys = 0;
xs = point2.x - point1.x;
xs = xs * xs;
ys = point2.y - point1.y;
ys = ys * ys;
return Math.sqrt( xs + ys );
}
And here is a standard point array for one of the hexagons that getClosestPiece returns:
Point {X: 658, Y: 284}
Point {X: 704, Y: 304}
Point {X: 704, Y: 354}
Point {X: 658, Y: 375}
Point {X: 613, Y: 354}
Point {X: 613, Y: 304}
Upvotes: 1
Views: 831
Reputation: 7440
to find which edges are the closest you hav to say us that how do you have information of the edge lines of each hexagon. here, i assume they are accessible through an array as a property of each hexagon. so we have 6 edges (edges[0] to edges[5]) for each hexagon. we can find closest edges by looping through them and measuring the distance between center of each two edges. a sample code will look like this:
var dMin=-1, iMin=-1, jMin=-1; //info about the min distance
for(var i=0; i<5; i++) //loop through hexagon1.edges
{
var p1 = midPointOfLine( hexagon1.edges[i] ); //center of this edge line
for(var j=0; j<5; j++) //loop through hexagon2.edges
{
var p2 = midPointOfLine( hexagon2.edges[j] ); //center of this edge line
var d = getDistance(p1, p2); //get distance of two points
if (d<dMin || dMin==-1) {dMin=d; iMin=i; jMin=j;} //store the info about the min distance
}
}
function midPointOfLine(edge) // return new point( X=(X1+X2)/2 , Y=(Y1+Y2)/2 )
{
var mp; //define a new point
mp.X = (edge.startPoint.X + edge.endPoint.X) / 2;
mp.Y = (edge.startPoint.Y + edge.endPoint.Y) / 2;
return mp;
}
function getDistance(p1, p2) //return sqrt( (X2-X1)^2 + (Y2-Y1)^2 )
{
return Math.sqrt( Math.pow(p2.X - p1.X, 2) + Math.pow(p2.Y - p1.Y, 2) );
}
In Summary:
Upvotes: 0
Reputation: 3116
For calculating if to snap, see the other answers.
As to where to snap (which edges), which I think is your real question: calculate the relative angle using
atan2(midy1-midy2, midx1-midx2).
You get a value in radians, which describes the angle of the connection line between the hexes. 0 = horizontal line.
Calculate Math.floor(value*6/(2*pi))
--> you get a number between 0..5 denoting the edge pairing.
If your hexes are rotatable, you need to add/substract the rotatins (in rad) to/from value
. (The signs are best figured out on a piece of paper).
edit: regarding your distance calculation, it is advisable to work with the square of the distance as long as possible (e.g. compare x^2+y^2 against threshold^2), to avoid the expensive Math.sqrt operation. Especially when testing distance against a multitude of other objects.
Upvotes: 0
Reputation: 3965
If your have 2 points with their coordinate like p1(x1, y1) and p2(x2, y2). You can do this:
var disptance = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
Upvotes: 1