flauwekeul / honeycomb

Create hex grids easily, in node or the browser.
https://abbekeultjes.nl/honeycomb
MIT License
630 stars 57 forks source link

Offset is not applying to pointy hex when using distance method #109

Open enpepolicy opened 11 months ago

enpepolicy commented 11 months ago

Describe the bug Offset is not applying to pointy hex when using grid distance method

To Reproduce const WideHex = defineHex({ dimensions: { xRadius: 50, yRadius: 30 }, // wide hexes offset: -1, // or 1 }) const distanceCalculator = new Grid(WideHex, rectangle({ width: 10, height: 10 }))

console.log( Starting coordinates:${boardTile.x},${boardTile.y}, Destination coordinates:${qBoardCoordinate},${rBoardCoordinate}, Distance:${distanceCalculator.distance( [boardTile.x, boardTile.y], [qBoardCoordinate, rBoardCoordinate] )}, distanceCalculator.toJSON(), )

// Case 1

Starting coordinates:3,1 Destination coordinates:4,2 Distance:2 { hexSettings: { dimensions: { xRadius: 50, yRadius: 30 }, orientation: 'POINTY', origin: { x: 0, y: 0 }, offset: -1 }, coordinates: [ W { q: 0, r: 0 }, W { q: 1, r: 0 }, W { q: 2, r: 0 }, W { q: 3, r: 0 }, W { q: 4, r: 0 }, W { q: 5, r: 0 }, W { q: 6, r: 0 }, W { q: 7, r: 0 }, W { q: 8, r: 0 }, W { q: 9, r: 0 }, W { q: 0, r: 1 }, W { q: 1, r: 1 }, W { q: 2, r: 1 }, W { q: 3, r: 1 }, W { q: 4, r: 1 }, W { q: 5, r: 1 }, W { q: 6, r: 1 }, W { q: 7, r: 1 }, W { q: 8, r: 1 }, W { q: 9, r: 1 }, W { q: -1, r: 2 }, W { q: 0, r: 2 }, W { q: 1, r: 2 }, W { q: 2, r: 2 }, W { q: 3, r: 2 }, W { q: 4, r: 2 }, W { q: 5, r: 2 }, W { q: 6, r: 2 }, W { q: 7, r: 2 }, W { q: 8, r: 2 }, W { q: -1, r: 3 }, W { q: 0, r: 3 }, W { q: 1, r: 3 }, W { q: 2, r: 3 }, W { q: 3, r: 3 }, W { q: 4, r: 3 }, W { q: 5, r: 3 }, W { q: 6, r: 3 }, W { q: 7, r: 3 }, W { q: 8, r: 3 }, W { q: -2, r: 4 }, W { q: -1, r: 4 }, W { q: 0, r: 4 }, W { q: 1, r: 4 }, W { q: 2, r: 4 }, W { q: 3, r: 4 }, W { q: 4, r: 4 }, W { q: 5, r: 4 }, W { q: 6, r: 4 }, W { q: 7, r: 4 }, W { q: -2, r: 5 }, W { q: -1, r: 5 }, W { q: 0, r: 5 }, W { q: 1, r: 5 }, W { q: 2, r: 5 }, W { q: 3, r: 5 }, W { q: 4, r: 5 }, W { q: 5, r: 5 }, W { q: 6, r: 5 }, W { q: 7, r: 5 }, W { q: -3, r: 6 }, W { q: -2, r: 6 }, W { q: -1, r: 6 }, W { q: 0, r: 6 }, W { q: 1, r: 6 }, W { q: 2, r: 6 }, W { q: 3, r: 6 }, W { q: 4, r: 6 }, W { q: 5, r: 6 }, W { q: 6, r: 6 }, W { q: -3, r: 7 }, W { q: -2, r: 7 }, W { q: -1, r: 7 }, W { q: 0, r: 7 }, W { q: 1, r: 7 }, W { q: 2, r: 7 }, W { q: 3, r: 7 }, W { q: 4, r: 7 }, W { q: 5, r: 7 }, W { q: 6, r: 7 }, W { q: -4, r: 8 }, W { q: -3, r: 8 }, W { q: -2, r: 8 }, W { q: -1, r: 8 }, W { q: 0, r: 8 }, W { q: 1, r: 8 }, W { q: 2, r: 8 }, W { q: 3, r: 8 }, W { q: 4, r: 8 }, W { q: 5, r: 8 }, W { q: -4, r: 9 }, W { q: -3, r: 9 }, W { q: -2, r: 9 }, W { q: -1, r: 9 }, W { q: 0, r: 9 }, W { q: 1, r: 9 }, W { q: 2, r: 9 }, W { q: 3, r: 9 }, W { q: 4, r: 9 }, W { q: 5, r: 9 } ] }

// Case 2

Starting coordinates:3,1 Destination coordinates:4,2 Distance:2 { hexSettings: { dimensions: { xRadius: 50, yRadius: 30 }, orientation: 'POINTY', origin: { x: 0, y: 0 }, offset: 1 }, coordinates: [ W { q: 0, r: 0 }, W { q: 1, r: 0 }, W { q: 2, r: 0 }, W { q: 3, r: 0 }, W { q: 4, r: 0 }, W { q: 5, r: 0 }, W { q: 6, r: 0 }, W { q: 7, r: 0 }, W { q: 8, r: 0 }, W { q: 9, r: 0 }, W { q: -1, r: 1 }, W { q: 0, r: 1 }, W { q: 1, r: 1 }, W { q: 2, r: 1 }, W { q: 3, r: 1 }, W { q: 4, r: 1 }, W { q: 5, r: 1 }, W { q: 6, r: 1 }, W { q: 7, r: 1 }, W { q: 8, r: 1 }, W { q: -1, r: 2 }, W { q: 0, r: 2 }, W { q: 1, r: 2 }, W { q: 2, r: 2 }, W { q: 3, r: 2 }, W { q: 4, r: 2 }, W { q: 5, r: 2 }, W { q: 6, r: 2 }, W { q: 7, r: 2 }, W { q: 8, r: 2 }, W { q: -2, r: 3 }, W { q: -1, r: 3 }, W { q: 0, r: 3 }, W { q: 1, r: 3 }, W { q: 2, r: 3 }, W { q: 3, r: 3 }, W { q: 4, r: 3 }, W { q: 5, r: 3 }, W { q: 6, r: 3 }, W { q: 7, r: 3 }, W { q: -2, r: 4 }, W { q: -1, r: 4 }, W { q: 0, r: 4 }, W { q: 1, r: 4 }, W { q: 2, r: 4 }, W { q: 3, r: 4 }, W { q: 4, r: 4 }, W { q: 5, r: 4 }, W { q: 6, r: 4 }, W { q: 7, r: 4 }, W { q: -3, r: 5 }, W { q: -2, r: 5 }, W { q: -1, r: 5 }, W { q: 0, r: 5 }, W { q: 1, r: 5 }, W { q: 2, r: 5 }, W { q: 3, r: 5 }, W { q: 4, r: 5 }, W { q: 5, r: 5 }, W { q: 6, r: 5 }, W { q: -3, r: 6 }, W { q: -2, r: 6 }, W { q: -1, r: 6 }, W { q: 0, r: 6 }, W { q: 1, r: 6 }, W { q: 2, r: 6 }, W { q: 3, r: 6 }, W { q: 4, r: 6 }, W { q: 5, r: 6 }, W { q: 6, r: 6 }, W { q: -4, r: 7 }, W { q: -3, r: 7 }, W { q: -2, r: 7 }, W { q: -1, r: 7 }, W { q: 0, r: 7 }, W { q: 1, r: 7 }, W { q: 2, r: 7 }, W { q: 3, r: 7 }, W { q: 4, r: 7 }, W { q: 5, r: 7 }, W { q: -4, r: 8 }, W { q: -3, r: 8 }, W { q: -2, r: 8 }, W { q: -1, r: 8 }, W { q: 0, r: 8 }, W { q: 1, r: 8 }, W { q: 2, r: 8 }, W { q: 3, r: 8 }, W { q: 4, r: 8 }, W { q: 5, r: 8 }, W { q: -5, r: 9 }, W { q: -4, r: 9 }, W { q: -3, r: 9 }, W { q: -2, r: 9 }, W { q: -1, r: 9 }, W { q: 0, r: 9 }, W { q: 1, r: 9 }, W { q: 2, r: 9 }, W { q: 3, r: 9 }, W { q: 4, r: 9 } ] }

Expected behavior When changing offset one of them should calculate 1 and the other 2, as distance as seen in redblob blog.

Environment (please complete the following information):

Screenshots Not apply

Additional context Not for the moment

flauwekeul commented 11 months ago

Thanks for opening the issue. I'll look into it next week at the earliest.

flauwekeul commented 11 months ago

I don't see how the distance between hexes in a grid is affected by the hex offset setting. And I couldn't find anything related to that on the redblobgames.com website. Do you have a link that explains the expected behavior?

enpepolicy commented 11 months ago

Yes of course, look this link (https://www.redblobgames.com/grids/hexagons/)

Distance are different in the Coordinate Systems -> offset coordinates-> (pointed odd r and pointed even r) have different distances from 3,1 to 4,2.

enpepolicy commented 11 months ago

IMG_20231010_092915.jpg

enpepolicy commented 9 months ago

HI flauwekeul , could you check it?

flauwekeul commented 9 months ago

I will, sorry for the silence. I was able to reproduce the problem. My free time is very limited, but I'll try to look into it this year. Thanks for your patience.

enpepolicy commented 9 months ago

got it working with this: ` it('calculates the correct distance between hex coordinates in an odd-r layout', () => { // Tests for horizontal distances expect(oddRHorizontalLayoutDistance([0, 0], [6, 0])).toBe(6) expect(oddRHorizontalLayoutDistance([1, 1], [5, 1])).toBe(4)

    // Tests for vertical distances
    expect(oddRHorizontalLayoutDistance([0, 0], [0, 6])).toBe(6)
    expect(oddRHorizontalLayoutDistance([3, 3], [3, 6])).toBe(3)

    // Tests for diagonal distances
    expect(oddRHorizontalLayoutDistance([1, 1], [5, 5])).toBe(6)
    expect(oddRHorizontalLayoutDistance([2, 2], [5, 6])).toBe(5)

    // Test for the same location (distance should be 0)
    expect(oddRHorizontalLayoutDistance([4, 4], [4, 4])).toBe(0)

    // Tests for complex distances where rowOffset calculation is necessary
    expect(oddRHorizontalLayoutDistance([0, 6], [5, 6])).toBe(5)
    expect(oddRHorizontalLayoutDistance([1, 6], [5, 5])).toBe(5)

    // Others
    expect(oddRHorizontalLayoutDistance([0, 0], [2, 1])).toBe(3)
  })

  type HexPoint = [number, number]
  type CubePoint = [number, number, number]

 function oddrToCube(hex: [number, number]): CubePoint {
   const x = hex[0] - Math.floor((hex[1] - (hex[1] & 1)) / 2)
  const z = hex[1]
  const y = -x - z
  return [x, y, z]
 }

 function cubeDistance(a: CubePoint, b: CubePoint): number {
  return Math.max(
   Math.abs(a[0] - b[0]),
   Math.abs(a[1] - b[1]),
   Math.abs(a[2] - b[2])
  )
 }

 function oddRHorizontalLayoutDistance(
   hex1: HexPoint,
   hex2: HexPoint
 ): number {
  const cube1 = oddrToCube(hex1)
  const cube2 = oddrToCube(hex2)
  return cubeDistance(cube1, cube2)
 }`
ghost commented 6 months ago

i dunno if this is useful, but I used offset [1,1] and the distances were calculated correctly.

const size = 40; const gridSize = 11; const center = 5;

const Hex = defineHex({ dimensions: { xRadius: size/2, yRadius: size/2 }, offset:[1,1] }) const hexgrid = new Grid(Hex, rectangle({ width: gridSize, height: gridSize }))