I've plotted a polygon on a set of ternary axes using python-ternary and joined up the vertices to form a region on the plot. However, I'd like to be able to fill this region so that it is a shape rather than just the outline.
I used the following code to generate the axes and a set of vertices for the polygon:
import ternary
import numpy as np
# Define the scale (the sum of the three components for each point)
scale = 100
# Define the vertices of the polygon (each point should sum to the scale value)
polygon_vertices = [
(20, 30, 50),
(40, 30, 30),
(30, 60, 10),
(10, 50, 40)
]
# Create a figure with a ternary axis
figure, tax = ternary. Figure(scale=scale)
tax.set_title("Ternary Plot with Polygon Contour", fontsize=20)
# Plot the vertices of the polygon on the ternary plot
tax.scatter(polygon_vertices, marker='o', color='red', label='Vertices')
# Connect the vertices to form the contour of the polygon
for i in range(len(polygon_vertices)):
next_i = (i + 1) % len(polygon_vertices)
tax. Plot([polygon_vertices[i], polygon_vertices[next_i]], color='blue', linewidth=2, linestyle='--')
# Fill the polygon area using the ax. Fill method
tax.ax.fill(*zip(*polygon_vertices), color='lightblue', alpha=0.8, label='Polygon Area')
# Set axis labels
tax.left_axis_label("Component 1", fontsize=15)
tax.right_axis_label("Component 2", fontsize=15)
tax.bottom_axis_label("Component 3", fontsize=15)
tax.get_axes().axis('off')
# Set the gridlines
tax.gridlines(color="blue", multiple=10)
# Set ticks and gridlines
tax.ticks(axis='lbr', linewidth=1, multiple=10)
tax.gridlines(multiple=10, color="black")
# Display the legend
tax.legend()
tax.get_axes().set_aspect(1) #sets as equilateral triangle, needs to be the last step of plotting
tax._redraw_labels() #see above
# Display the plot
tax.show()
I get the resulting plot shown here:
As seen in the plot, it does plot the filled polygon but not in the correct place, and it plots two of them. I'm not sure why. How do I get the correct region filled?
Note: This is not the same question as Python fill polygon as this is Cartesian coordinates. When I try and plot with add_patches, I get a Type Error as Polygon can only take two positional arguments but I provide it with three, despite the earlier conversion of ternary to cartesian coordinates.
Calling tax.ax.fill()
will go to matplotlib's standard ax.fill()
. That function doesn't work with ternary coordinates, it needs regular x and y coordinates.
As tax.fill()
isn't implemented in the ternary library, you can use project_sequence()
from ternary.helpers
to convert the ternary coordinates to regular xs and ys. And then call matplotlib's tax.ax.fill()
with those.
import ternary
from ternary.helpers import project_sequence
import numpy as np
# Define the scale (the sum of the three components for each point)
scale = 100
# Define the vertices of the polygon (each point should sum to the scale value)
polygon_vertices = [
(20, 30, 50),
(40, 30, 30),
(30, 60, 10),
(10, 50, 40)
]
# Create a figure with a ternary axis
figure, tax = ternary.figure(scale=scale)
tax.set_title("Ternary Plot with Polygon Contour", fontsize=20)
# Plot the vertices of the polygon on the ternary plot
tax.scatter(polygon_vertices, marker='o', color='red', label='Vertices')
# Connect the vertices to form the contour of the polygon
for i in range(len(polygon_vertices)):
next_i = (i + 1) % len(polygon_vertices)
tax.plot([polygon_vertices[i], polygon_vertices[next_i]], color='blue', linewidth=2, linestyle='--')
# Fill the polygon area using the ax.fill method
xs, ys = project_sequence(polygon_vertices)
tax.ax.fill(xs, ys, color='lightblue', alpha=0.8, label='Polygon Area')
# Set axis labels
tax.left_axis_label("Component 1", fontsize=15)
tax.right_axis_label("Component 2", fontsize=15)
tax.bottom_axis_label("Component 3", fontsize=15)
tax.ax.axis('off')
# Set the gridlines
tax.gridlines(color="blue", multiple=10)
# Set ticks and gridlines
tax.ticks(axis='lbr', linewidth=1, multiple=10)
tax.gridlines(multiple=10, color="black")
# Display the legend
tax.legend()
tax.ax.set_aspect(1) #sets as equilateral triangle, needs to be the last step of plotting
tax._redraw_labels() #see above
# Display the plot
tax.show()