可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
If for example, I have the following coordinates with corresponding colors
which represent a hexagonal shaped grid of hexagons:
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"]]
How can one plot this in Python so that the points on the plot retain that hexagonal shape? Additionally how can one represent the 'colors' list on the hexagon.
Somewhat like this:
Simple Hexagonal grid
But the look doesn't matter, just a simple scatter plot type visualization would suffice, just so that one can see where in relation to other hexagons the colors lie.
回答1:
You just need to turn the (y, z)
coordinates from your hexagons into the y
cartesian coordinate on the matplotlib axes.
I think the correct way to do that is using this formula:
y_cartesian = (2 / 3) * sin(60) * (y_hex - z_hex)
You can then add the hexagons using a matplotlib RegularPolygon
patch, or plot the centres using scatter
.
Here's a script to make a plot from your lists:
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()
回答2:
Here's a function that converts a (u, v, w) tuple of hex coordinates into rectangular coordinates. I'll illustrate it using the standard turtle
module (I don't have the matplotlib module). I've changed the colours on the list so we can easily check that each point is plotted in the correct position.
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()
output
回答3:
Below is my attempt to finish PM2Ring's turtle-based solution (+1) as well as fix what I see as a coordinate calculation error in his answer:
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()