-1

I'm using matplotlib.

I managed to plot a 2D array of hexagons using plt.scatter, where I set the marker to 'h' for hexagon and set the size to something big like s=500 or so. Through simple math I made arrays for the position of each hexagon (normalized the pitch to 1). Here's my picture of the hexagons which plotted as expected.

However, I want to plot triangles (6 equal ones) within those hexagons and it's not as easy. Here's part of the code I used to plot the triangles:

fig4, ax4 = plt.subplots()
ax4.set_aspect('equal')
for i in range(len(powtri)):
    for j in range(len(powtri[i])):
        plt.scatter(x=X_tric[i][j], y=Y_tric[i][j], s=size, marker=markers[i][j], c=powtri[i][j], cmap='jet')
cbar3 = plt.colorbar(fraction=0.03, pad=0.04)  
cbar3.set_label('Normalized assembly power')
plt.axis('off')
plt.title('Triangle Powers')

My options are using the markers 4&5 or <&> (which I used in the markers array to alternate left/right triangles) and then I calculated the centers of each triangle (or position of pointy end for each triangle), but the actual problem is that my picture keeps getting cut off with ugly formatting and the sizes and position of of the triangle markers keep changing so I end up with this.

Am I approaching this the wrong way?

Thanks.

Scorp
  • 1
  • 1

1 Answers1

1

I think you need an equilateral triangle for what you want to do and I don't think the options supplied by 4,5,< or > are quite right.

Luckily matplotlib allows you to create new markers however you want. There are two ways that might be particularly useful to your project.

  1. Create a regular polygon marker with marker=(N, 0, angle), where N is the number of sides and angle is how to rotate the marker e.g.
plt.scatter([0], [0], marker=(3, 0, 0))
  1. Create a marker using a using a list of vertices. E.g. you can make a equilateral triangle using
length = np.sqrt(1**2 - 0.5**2)
plt.scatter([0], [0], marker=[(0, 0), (1, 0), (0.5, length)])

In your case it seems the second option might be the way to go. The reason I say that is because when combined with this answer to rotate markers, the rotation seems to happen around 0, whereas for the (3, 0, 0) method it happens around the centre of the triangle (I've not investigated why). Putting it all together

import matplotlib.pyplot as plt
from matplotlib.markers import MarkerStyle
import numpy as np

fig, ax = plt.subplots()

length = np.sqrt(1**2 - 0.5**2)
m = MarkerStyle([(0, 0), (1, 0), (0.5, length)])

for deg in range(6):
    m._transform.rotate_deg(60)
    ax.scatter([0], [0], marker=m, s=10000)

fig.show()

you can get this. I hope this is useful for achieving your goal.

enter image description here

tomjn
  • 5,100
  • 1
  • 9
  • 24
  • Sounds like a good idea, but I already managed to make it work. This only works for left and right triangles (where the hex is pointed vertically). I had to split my main array into left and right triangle versions accordingly. Then I correlated the market size to screen size to work for any client. And tada! https://imgur.com/DngLHVV – Scorp Mar 08 '21 at 22:21