Как построить координаты (x, y, z) в форме гексагональной сетки?

Если, например, у меня есть следующие координаты с соответствующими цветами, которые представляют собой гексагональную сетку из шестиугольников:

coord = [[0,0,0],[0,1,-1],[-1,1,0],[-1,0,1],[0,-1,1],[1,-1,0],[1,0,-1]]
colors = [["Green"],["Blue"],["Green"],["Green"],["Red"],["Green"],["Green"]]

Как можно построить это на Python, чтобы точки на графике сохранили шестиугольную форму? Кроме того, как можно представить список «цветов» на шестиугольнике.

Примерно так:

Простая шестиугольная сетка

Но внешний вид не имеет значения, достаточно простой визуализации типа графика рассеяния, чтобы можно было увидеть, где по отношению к другим шестиугольникам лежат цвета.


person ishido    schedule 02.10.2017    source источник
comment
Вы используете ASCII или хотите использовать графический модуль черепахи?   -  person EgMusic    schedule 02.10.2017
comment
Что обозначают координаты? Я не могу установить связь между изображением и coord. Вы, вероятно, захотите указать используемое здесь соглашение, например если я возьму список [[a,b,c],[d,e,f]], что такое a, b, c, d, e, f?   -  person ImportanceOfBeingErnest    schedule 02.10.2017
comment
@ChaseBarnes, я хочу использовать самое простое решение. ASCII было бы достаточно.   -  person ishido    schedule 02.10.2017
comment
@ImportanceOfBeingErnest координаты - это разные шестиугольники на шестиугольной плитке. Каждый набор координат (x, y, z) имеет свойство, представленное здесь как цвет, которое я хотел бы отобразить в виде визуализации.   -  person ishido    schedule 02.10.2017
comment
Я задал вопрос: что в списке [[a, b, c], [d, e, f]] означает a, b, c, d, e, f?   -  person ImportanceOfBeingErnest    schedule 02.10.2017
comment
@ImportanceOfBeingErnest Каждая позиция в шестиугольной мозаике может быть представлена ​​набором координат. Список coord - это список, представляющий позиции 7 шестиугольников. См .: redblobgames.com/grids/hexagons/#coordinates   -  person ishido    schedule 02.10.2017
comment
@ishido решением SIMPLIST будет графический модуль черепахи. ASCII будет сложно реализовать.   -  person EgMusic    schedule 02.10.2017


Ответы (3)


Вам просто нужно превратить (y, z) координаты из ваших шестиугольников в y декартовы координаты на осях matplotlib.

Я думаю, что правильный способ сделать это - использовать эту формулу:

y_cartesian = (2 / 3) * sin(60) * (y_hex - z_hex)

Затем вы можете добавить шестиугольники с помощью патча RegularPolygon matplotlib или графика центры, использующие scatter .

Вот сценарий для построения сюжета из ваших списков:

import matplotlib.pyplot as plt
from matplotlib.patches import RegularPolygon
import numpy as np

coord = [[0,0,0],[0,1,-1],[-1,1,0],[-1,0,1],[0,-1,1],[1,-1,0],[1,0,-1]]
colors = [["Green"],["Blue"],["Green"],["Green"],["Red"],["Green"],["Green"]]
labels = [['yes'],['no'],['yes'],['no'],['yes'],['no'],['no']]

# Horizontal cartesian coords
hcoord = [c[0] for c in coord]

# Vertical cartersian coords
vcoord = [2. * np.sin(np.radians(60)) * (c[1] - c[2]) /3. for c in coord]

fig, ax = plt.subplots(1)
ax.set_aspect('equal')

# Add some coloured hexagons
for x, y, c, l in zip(hcoord, vcoord, colors, labels):
    color = c[0].lower()  # matplotlib understands lower case words for colours
    hex = RegularPolygon((x, y), numVertices=6, radius=2. / 3., 
                         orientation=np.radians(30), 
                         facecolor=color, alpha=0.2, edgecolor='k')
    ax.add_patch(hex)
    # Also add a text label
    ax.text(x, y+0.2, l[0], ha='center', va='center', size=20)

# Also add scatter points in hexagon centres
ax.scatter(hcoord, vcoord, c=[c[0].lower() for c in colors], alpha=0.5)

plt.show()

введите описание изображения здесь

person tmdavison    schedule 02.10.2017
comment
Большое вам спасибо за это. Можно ли дополнительно поставить метку в каждый шестиугольник? Скажите, есть ли у меня список labels = [['yes'],['no'],['yes'],['no'],['yes'],['no'],['no']]. Я видел, что у RegularPolygon есть опция ярлыков - person ishido; 02.10.2017
comment
label для RegularPolygon Думаю, стоит поставить метку в легенде. Вместо этого вы можете использовать ax.text(x, y, label). Смотрите мое редактирование - person tmdavison; 02.10.2017

Вот функция, которая преобразует кортеж (u, v, w) шестнадцатеричных координат в прямоугольные координаты. Я проиллюстрирую это с помощью стандартного модуля turtle (у меня нет модуля matplotlib). Я изменил цвета в списке, чтобы мы могли легко проверить правильность расположения каждой точки.

import turtle
from math import sqrt

root3 = sqrt(3)

# the scale used for drawing
side = 50

# Convert hex coordinates to rectangular
def hex_to_rect(coord):
    u, v, w = coord
    x = u - v/2 - w/2
    y = (v - w) * root3 / 2
    return x * side, y * side

# Initialize the turtle
t = turtle.Turtle()
t.speed(0)
t.hideturtle()
t.up()

coords = [[0,0,0], [0,1,-1], [-1,1,0], [-1,0,1], [0,-1,1], [1,-1,0], [1,0,-1]]
colors = ['black', 'red', 'orange', 'green', 'cyan', 'blue', 'magenta']

#Plot the points
for hexcoord, color in zip(coords, colors):
    xy = hex_to_rect(hexcoord)
    t.goto(xy)
    t.dot(15, color)

# Wait for the user to close the window
turtle.done()

вывод

точки на гексагональной сетке

person PM 2Ring    schedule 02.10.2017
comment
@Chase Barnes Спасибо, что исправили опечатку. Но информация об установке matplotlib не имеет отношения к моему ответу. - person PM 2Ring; 02.10.2017
comment
Я понимаю, но на всякий случай, если люди захотят узнать, как устанавливать модули, вот оно. - person EgMusic; 02.10.2017
comment
Основываясь на моем понимании проблемы, у вас есть зеленый кружок, где у вас должен быть голубой кружок в [0, -1, 1], то есть в нижнем положении. - person cdlane; 02.10.2017
comment
Я предполагаю, что центральный шестиугольник на диаграмме OP показывает, как декодируются X, Y и Z, что ставит [0, -1, 1] (голубой) в качестве нижнего шестиугольника. - person cdlane; 02.10.2017
comment
@cdlane Исправлено. Я только что заметил, что вы тоже отправили ответ. - person PM 2Ring; 02.10.2017

Ниже представлена ​​моя попытка завершить решение PM2Ring на основе черепах (+1), а также исправить то, что я вижу как ошибку вычисления координат в его ответе:

from math import sqrt
from turtle import Turtle, Screen

ROOT3_OVER_2 = sqrt(3) / 2

FONT_SIZE = 18
FONT = ('Arial', FONT_SIZE, 'normal')

SIDE = 50  # the scale used for drawing

# Convert hex coordinates to rectangular
def hex_to_rect(coord):
    v, u, w = coord
    x = -u / 2 + v - w / 2
    y = (u - w) * ROOT3_OVER_2
    return x * SIDE, y * SIDE

def hexagon(turtle, radius, color, label):
    clone = turtle.clone()  # so we don't affect turtle's state
    xpos, ypos = clone.position()
    clone.setposition(xpos - radius / 2, ypos - ROOT3_OVER_2 * radius)
    clone.setheading(-30)
    clone.color('black', color)
    clone.pendown()
    clone.begin_fill()
    clone.circle(radius, steps=6)
    clone.end_fill()
    clone.penup()
    clone.setposition(xpos, ypos - FONT_SIZE / 2)
    clone.write(label, align="center", font=FONT)

# Initialize the turtle
tortoise = Turtle(visible=False)
tortoise.speed('fastest')
tortoise.penup()

coords = [[0, 0, 0], [0, 1, -1], [-1, 1, 0], [-1, 0, 1], [0, -1, 1], [1, -1, 0], [1, 0, -1]]
colors = ["Green", "Blue", "Green", "Green", "Red", "Green", "Green"]
labels = ['yes', 'no', 'yes', 'no', 'yes', 'no', 'no']

# Plot the points
for hexcoord, color, label in zip(coords, colors, labels):
    tortoise.goto(hex_to_rect(hexcoord))
    hexagon(tortoise, SIDE, color, label)

# Wait for the user to close the window
screen = Screen()
screen.exitonclick()

введите описание изображения здесь

person cdlane    schedule 02.10.2017