Chuyển đổi giữa các hình xoắn ốc tổ ong và trục tọa độ


7

Dường như có khá nhiều logic trong việc xử lý các lưới lục giác bằng cách sử dụng một hệ tọa độ trục giống như mô tả ở đây .

Tuy nhiên, khi đọc một số lưới hex, tôi đã lướt qua khái niệm về khảm tổ ong xoắn ốc (các liên kết trên gương đó bị hỏng; nội dung được sao chép từ đây , khoảng một nửa trang). Nó dường như được sử dụng chủ yếu trong xử lý hình ảnh, nhưng điều thú vị từ quan điểm là nó gán cho mỗi hex một số cơ sở 7 liên tiếp duy nhất làm định danh.

Tôi không chắc chắn rằng nó thực sự hữu ích cho bất cứ điều gì, nhưng tôi tự hỏi: có thể chuyển đổi qua lại giữa hệ thống đánh số SHM và tọa độ trục không?

Cả hai hệ thống đều có các phương thức để chuyển đổi từ một hình lục giác sang tọa độ Descartes ở trung tâm của nó, vì vậy có lẽ người ta có thể tính toán nó ra khỏi một hệ thống, sau đó sang hệ thống khác. Nhưng điều đó lộn xộn và không hiệu quả, và tôi tin rằng có thể làm tốt hơn.

Do tính chất fractal của SHM, thói quen chuyển đổi trong mã mẫu được cung cấp dựa trên một vòng lặp; Có vẻ như giải pháp chung có thể liên quan đến một loạt?

Lưới hex mẫu có đánh số SHM và tọa độ trục được đánh dấu.


1
Để rõ ràng, tôi đã chọn liên kết đến SHM mà tôi đưa vào ban đầu vì các liên kết trên gương DMGregory đã chọn bị hỏng. Tôi sẽ chỉnh sửa để bao gồm cả hai.
Sixten Otto

Đẹp! Điều này dường như có liên quan đến số Morton và đường cong Z-order . Cả hai đều theo mô hình fractal, và chia sẻ tài sản của việc bảo tồn địa phương.
fede s.

Câu trả lời:


5

Cảm ơn cho một câu đố hấp dẫn! Vâng, có vẻ như chúng ta có thể làm tốt hơn một chuyển đổi thông qua tọa độ cartesian của các trung tâm hình lục giác. Nó có thể được thực hiện hoàn toàn với toán số nguyên, mặc dù tôi đã bao gồm một tỷ lệ hợp lý trong một ma trận bên dưới để giữ cho ký hiệu ngắn gọn.

Bạn đúng rằng cả quá trình mã hóa và giải mã đều yêu cầu các vòng lặp. May mắn thay, vì SHM hoạt động theo các đơn đặt hàng cường độ, các vòng lặp sẽ không bao giờ cần nhiều hơn các lần lặp Log_7 (n + 1), trong đó n là số lượng ô trong lưới, rất hợp lý.

Để giữ cho ký hiệu của tôi đối xứng, tôi đã chọn sử dụng lưới 3 tọa độ như lưới bên dưới ( ví dụ của bạn từ Red Blob Games gọi là "Tọa độ khối" ). Nếu bạn thích, bạn có thể bỏ qua tọa độ z và thay thế tất cả các trường hợp của .z bằng - (x + y) để lấy "Tọa độ trục" thay thế.

"Tọa độ khối" từ Red Blob Games

Để biết tốc độ và độ sạch của mã, tôi khuyên bạn nên sử dụng bảng tra cứu để mã hóa và giải mã. Đầu tiên, để giải mã SHM thành tọa độ khối, bạn có thể xây dựng bảng với các lần lặp lại sau:

Rotate(v) = (-v.z, -v.x, -v.y)

Decode[,] = 2D array of ordered triples, [7 x (max_order_of_magnitude + 1)]

Decode[0, k] = (0, 0, 0) for all k = 0...max_order_of_magnitude
Decode[1, 0] = (0, -1, 1)

Decode[d + 1, k] = Rotate(Decode(d, k)) for d = 2...6, all k
Decode[d, k + 1] = Decode(d, k) + 2 * Rotate(Decode(d, k)) for all d, k

Sau đó giải mã trở nên cực kỳ đơn giản:

SHMToPoint(code)
{
    point = (0, 0, 0)
    order = 0    

    while(code > 0)
    {
        digit = code % 7
        point += Decode(digit, order)
        code = floor(code/7)
        order++
    }
    return point
}

Điều này hoạt động vì hàng đầu tiên của bảng lưu trữ phần bù của các ô được mã hóa bằng các chữ số 0, 1, 2, 3, 4, 5, 6. Hàng tiếp theo lưu trữ các giá trị bù cho 0, 10, 20, 30, 40, 50, 60, v.v. Bằng cách tính tổng các độ lệch được đóng góp theo từng bậc độ lớn, bạn có thể giải mã bất kỳ điểm nào trong phạm vi của bảng.

Để mã hóa, tôi nghĩ phương pháp sau sẽ hiệu quả, nhưng tôi thú nhận rằng tôi chưa thử nghiệm nó. Nó sử dụng bảng tra cứu đơn giản hơn nhiều:

Encode = [0, 5, 1, 6, 3, 4, 2]

và một ma trận xoay và chia tỷ lệ:

Untwist = | 5  -4   2 |
          | 2   5  -4 |
          |-4   2   5 | * 1/21

Để mã hóa tọa độ khối vào SHM, sau đó ...

PointToSHM(point)
{
    code = 0
    magnitude = 1
    while(point != (0, 0, 0))
    {
        digitIndex = (((point.x - 2 * point.y) % 7) + 7) % 7
        code += magnitude *Encode[digitIndex]
        point = Untwist * (point - Decode[digit, 0])
        // treating "point" as a column vector, and rounding if necessary
        magnitude *= 7
    }
    return code
}

Lưu ý rằng mã được tạo ở đây (và được giải mã ở trên) có định dạng số chuẩn (nghĩa là ô được đánh dấu "10" trong sơ đồ SHM sẽ được gán mã 7 trong cơ sở 10 hoặc 111 ở dạng nhị phân). Nếu bạn muốn hiển thị nó trong cơ sở 7, bạn sẽ cần sử dụng cơ số thích hợp khi chuyển đổi nó thành một chuỗi.

Điều này hoạt động bằng cách tìm ra chữ số có nghĩa ít nhất của mã SHM ở mỗi lần lặp, (sử dụng thực tế là các chữ số này lặp lại theo cách xếp mặt phẳng thường xuyên - LUT là chuỗi các chữ số được đọc từ (0, 0, 0) đến (6, 0, -6), lặp lại ở mức bù mỗi hàng). Tiếp theo, nó thực sự thay đổi chữ số đó bằng cách trừ đi phần bù tương ứng từ bảng Giải mã của chúng tôi trước đó và chia tỷ lệ fractal xuống một cấp bằng cách sử dụng ma trận Untwist. Điều này hoạt động giống như một sự thay đổi bên phải trong cơ sở 7, ở dạng hình học - nó đưa chữ số tiếp theo vào vị trí ít quan trọng nhất, đưa ô "10" thành "1", v.v., nơi chúng ta có thể sử dụng lại cùng một mẹo để đọc chữ số trên vòng lặp tiếp theo.

Tôi hi vọng nó làm việc cho bạn!


1
Nhiều đánh giá cao! Tôi sẽ cố gắng tìm một chút thời gian vào cuối tuần này để đưa ra giải pháp này; Tôi sẽ báo cáo lại với kết quả của mình.
Sixten Otto
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.