Ashbury
Ashbury

Reputation: 2346

Finding the distance between two hexagons

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?

Hexagon 1, Side 1 is closest to Hexagon 3, Side 4

Hexagon 1, Side 2 is closest to Hexagon 3, Side 5

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

Answers (4)

S.Serpooshan
S.Serpooshan

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:

  • Check distance between center of each edge of hexagon1 and center of each edge of hexagon2.
  • The center of each edge is mid point of its start and end points: ( (x1+x2)/2, (y1+y2)/2 ).
  • The distance of two points can be calculated from sqrt(dx*dx + dy*dy) formula.

Upvotes: 0

Torben Klein
Torben Klein

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

xrcwrn
xrcwrn

Reputation: 5327

Use Euclian Distance formula

dist=sqrt((x2-xq)^2 + (y2-y1)^2)

Upvotes: 0

Ringo
Ringo

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

Related Questions