Add regular polygon shapes to display component (#6108)

This commit is contained in:
mathieu-mp 2024-03-01 04:49:26 +01:00 committed by GitHub
parent 082e76131b
commit 4aeb8e8081
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 133 additions and 0 deletions

View File

@ -257,6 +257,67 @@ void Display::filled_triangle(int x1, int y1, int x2, int y2, int x3, int y3, Co
this->filled_flat_side_triangle_(x3, y3, x2, y2, x_temp, y_temp, color);
}
}
void HOT Display::get_regular_polygon_vertex(int vertex_id, int *vertex_x, int *vertex_y, int center_x, int center_y,
int radius, int edges, RegularPolygonVariation variation,
float rotation_degrees) {
if (edges >= 2) {
// Given the orientation of the display component, an angle is measured clockwise from the x axis.
// For a regular polygon, the human reference would be the top of the polygon,
// hence we rotate the shape by 270° to orient the polygon up.
rotation_degrees += ROTATION_270_DEGREES;
// Convert the rotation to radians, easier to use in trigonometrical calculations
float rotation_radians = rotation_degrees * PI / 180;
// A pointy top variation means the first vertex of the polygon is at the top center of the shape, this requires no
// additional rotation of the shape.
// A flat top variation means the first point of the polygon has to be rotated so that the first edge is horizontal,
// this requires to rotate the shape by π/edges radians counter-clockwise so that the first point is located on the
// left side of the first horizontal edge.
rotation_radians -= (variation == VARIATION_FLAT_TOP) ? PI / edges : 0.0;
float vertex_angle = ((float) vertex_id) / edges * 2 * PI + rotation_radians;
*vertex_x = (int) round(cos(vertex_angle) * radius) + center_x;
*vertex_y = (int) round(sin(vertex_angle) * radius) + center_y;
}
}
void HOT Display::regular_polygon(int x, int y, int radius, int edges, RegularPolygonVariation variation,
float rotation_degrees, Color color, RegularPolygonDrawing drawing) {
if (edges >= 2) {
int previous_vertex_x, previous_vertex_y;
for (int current_vertex_id = 0; current_vertex_id <= edges; current_vertex_id++) {
int current_vertex_x, current_vertex_y;
get_regular_polygon_vertex(current_vertex_id, &current_vertex_x, &current_vertex_y, x, y, radius, edges,
variation, rotation_degrees);
if (current_vertex_id > 0) { // Start drawing after the 2nd vertex coordinates has been calculated
if (drawing == DRAWING_FILLED) {
this->filled_triangle(x, y, previous_vertex_x, previous_vertex_y, current_vertex_x, current_vertex_y, color);
} else if (drawing == DRAWING_OUTLINE) {
this->line(previous_vertex_x, previous_vertex_y, current_vertex_x, current_vertex_y, color);
}
}
previous_vertex_x = current_vertex_x;
previous_vertex_y = current_vertex_y;
}
}
}
void HOT Display::regular_polygon(int x, int y, int radius, int edges, RegularPolygonVariation variation, Color color,
RegularPolygonDrawing drawing) {
regular_polygon(x, y, radius, edges, variation, ROTATION_0_DEGREES, color, drawing);
}
void HOT Display::regular_polygon(int x, int y, int radius, int edges, Color color, RegularPolygonDrawing drawing) {
regular_polygon(x, y, radius, edges, VARIATION_POINTY_TOP, ROTATION_0_DEGREES, color, drawing);
}
void Display::filled_regular_polygon(int x, int y, int radius, int edges, RegularPolygonVariation variation,
float rotation_degrees, Color color) {
regular_polygon(x, y, radius, edges, variation, rotation_degrees, color, DRAWING_FILLED);
}
void Display::filled_regular_polygon(int x, int y, int radius, int edges, RegularPolygonVariation variation,
Color color) {
regular_polygon(x, y, radius, edges, variation, ROTATION_0_DEGREES, color, DRAWING_FILLED);
}
void Display::filled_regular_polygon(int x, int y, int radius, int edges, Color color) {
regular_polygon(x, y, radius, edges, VARIATION_POINTY_TOP, ROTATION_0_DEGREES, color, DRAWING_FILLED);
}
void Display::print(int x, int y, BaseFont *font, Color color, TextAlign align, const char *text) {
int x_start, y_start;

View File

@ -137,6 +137,42 @@ enum DisplayRotation {
DISPLAY_ROTATION_270_DEGREES = 270,
};
#define PI 3.1415926535897932384626433832795
const int EDGES_TRIGON = 3;
const int EDGES_TRIANGLE = 3;
const int EDGES_TETRAGON = 4;
const int EDGES_QUADRILATERAL = 4;
const int EDGES_PENTAGON = 5;
const int EDGES_HEXAGON = 6;
const int EDGES_HEPTAGON = 7;
const int EDGES_OCTAGON = 8;
const int EDGES_NONAGON = 9;
const int EDGES_ENNEAGON = 9;
const int EDGES_DECAGON = 10;
const int EDGES_HENDECAGON = 11;
const int EDGES_DODECAGON = 12;
const int EDGES_TRIDECAGON = 13;
const int EDGES_TETRADECAGON = 14;
const int EDGES_PENTADECAGON = 15;
const int EDGES_HEXADECAGON = 16;
const float ROTATION_0_DEGREES = 0.0;
const float ROTATION_45_DEGREES = 45.0;
const float ROTATION_90_DEGREES = 90.0;
const float ROTATION_180_DEGREES = 180.0;
const float ROTATION_270_DEGREES = 270.0;
enum RegularPolygonVariation {
VARIATION_POINTY_TOP = 0,
VARIATION_FLAT_TOP = 1,
};
enum RegularPolygonDrawing {
DRAWING_OUTLINE = 0,
DRAWING_FILLED = 1,
};
class Display;
class DisplayPage;
class DisplayOnPageChangeTrigger;
@ -247,6 +283,42 @@ class Display : public PollingComponent {
/// Fill a triangle contained between the points [x1,y1], [x2,y2] and [x3,y3] with the given color.
void filled_triangle(int x1, int y1, int x2, int y2, int x3, int y3, Color color = COLOR_ON);
/// Get the specified vertex (x,y) coordinates for the regular polygon inscribed in the circle centered on
/// [center_x,center_y] with the given radius. Vertex id are 0-indexed and rotate clockwise. In a pointy-topped
/// variation of a polygon with a 0° rotation, the vertex #0 is located at the top of the polygon. In a flat-topped
/// variation of a polygon with a 0° rotation, the vertex #0 is located on the left-side of the horizontal top
/// edge, and the vertex #1 is located on the right-side of the horizontal top edge.
/// Use the edges constants (e.g.: EDGES_HEXAGON) or any integer to specify the number of edges of the polygon.
/// Use the variation to switch between the flat-topped or the pointy-topped variation of the polygon.
/// Use the rotation in degrees to rotate the shape clockwise.
void get_regular_polygon_vertex(int vertex_id, int *vertex_x, int *vertex_y, int center_x, int center_y, int radius,
int edges, RegularPolygonVariation variation = VARIATION_POINTY_TOP,
float rotation_degrees = ROTATION_0_DEGREES);
/// Draw the outline of a regular polygon inscribed in the circle centered on [x,y] with the given
/// radius and color.
/// Use the edges constants (e.g.: EDGES_HEXAGON) or any integer to specify the number of edges of the polygon.
/// Use the variation to switch between the flat-topped or the pointy-topped variation of the polygon.
/// Use the rotation in degrees to rotate the shape clockwise.
/// Use the drawing to switch between outlining or filling the polygon.
void regular_polygon(int x, int y, int radius, int edges, RegularPolygonVariation variation = VARIATION_POINTY_TOP,
float rotation_degrees = ROTATION_0_DEGREES, Color color = COLOR_ON,
RegularPolygonDrawing drawing = DRAWING_OUTLINE);
void regular_polygon(int x, int y, int radius, int edges, RegularPolygonVariation variation, Color color,
RegularPolygonDrawing drawing = DRAWING_OUTLINE);
void regular_polygon(int x, int y, int radius, int edges, Color color,
RegularPolygonDrawing drawing = DRAWING_OUTLINE);
/// Fill a regular polygon inscribed in the circle centered on [x,y] with the given radius and color.
/// Use the edges constants (e.g.: EDGES_HEXAGON) or any integer to specify the number of edges of the polygon.
/// Use the variation to switch between the flat-topped or the pointy-topped variation of the polygon.
/// Use the rotation in degrees to rotate the shape clockwise.
void filled_regular_polygon(int x, int y, int radius, int edges,
RegularPolygonVariation variation = VARIATION_POINTY_TOP,
float rotation_degrees = ROTATION_0_DEGREES, Color color = COLOR_ON);
void filled_regular_polygon(int x, int y, int radius, int edges, RegularPolygonVariation variation, Color color);
void filled_regular_polygon(int x, int y, int radius, int edges, Color color);
/** Print `text` with the anchor point at [x,y] with `font`.
*
* @param x The x coordinate of the text alignment anchor point.