mirror of
https://github.com/esphome/esphome.git
synced 2024-11-21 22:48:10 +01:00
[display] filled_ring and filled_gauge methods added (#7420)
This commit is contained in:
parent
fb002ac3b0
commit
3ef31e55ca
3 changed files with 153 additions and 0 deletions
|
@ -156,6 +156,148 @@ void Display::filled_circle(int center_x, int center_y, int radius, Color color)
|
|||
}
|
||||
} while (dx <= 0);
|
||||
}
|
||||
void Display::filled_ring(int center_x, int center_y, int radius1, int radius2, Color color) {
|
||||
int rmax = radius1 > radius2 ? radius1 : radius2;
|
||||
int rmin = radius1 < radius2 ? radius1 : radius2;
|
||||
int dxmax = -int32_t(rmax), dxmin = -int32_t(rmin);
|
||||
int dymax = 0, dymin = 0;
|
||||
int errmax = 2 - 2 * rmax, errmin = 2 - 2 * rmin;
|
||||
int e2max, e2min;
|
||||
do {
|
||||
// 8 dots for borders
|
||||
this->draw_pixel_at(center_x - dxmax, center_y + dymax, color);
|
||||
this->draw_pixel_at(center_x + dxmax, center_y + dymax, color);
|
||||
this->draw_pixel_at(center_x - dxmin, center_y + dymin, color);
|
||||
this->draw_pixel_at(center_x + dxmin, center_y + dymin, color);
|
||||
this->draw_pixel_at(center_x + dxmax, center_y - dymax, color);
|
||||
this->draw_pixel_at(center_x - dxmax, center_y - dymax, color);
|
||||
this->draw_pixel_at(center_x + dxmin, center_y - dymin, color);
|
||||
this->draw_pixel_at(center_x - dxmin, center_y - dymin, color);
|
||||
if (dymin < rmin) {
|
||||
// two parts - four lines
|
||||
int hline_width = -(dxmax - dxmin) + 1;
|
||||
this->horizontal_line(center_x + dxmax, center_y + dymax, hline_width, color);
|
||||
this->horizontal_line(center_x - dxmin, center_y + dymax, hline_width, color);
|
||||
this->horizontal_line(center_x + dxmax, center_y - dymax, hline_width, color);
|
||||
this->horizontal_line(center_x - dxmin, center_y - dymax, hline_width, color);
|
||||
} else {
|
||||
// one part - top and bottom
|
||||
int hline_width = 2 * (-dxmax) + 1;
|
||||
this->horizontal_line(center_x + dxmax, center_y + dymax, hline_width, color);
|
||||
this->horizontal_line(center_x + dxmax, center_y - dymax, hline_width, color);
|
||||
}
|
||||
e2max = errmax;
|
||||
// tune external
|
||||
if (e2max < dymax) {
|
||||
errmax += ++dymax * 2 + 1;
|
||||
if (-dxmax == dymax && e2max <= dxmax) {
|
||||
e2max = 0;
|
||||
}
|
||||
}
|
||||
if (e2max > dxmax) {
|
||||
errmax += ++dxmax * 2 + 1;
|
||||
}
|
||||
// tune internal
|
||||
while (dymin < dymax && dymin < rmin) {
|
||||
e2min = errmin;
|
||||
if (e2min < dymin) {
|
||||
errmin += ++dymin * 2 + 1;
|
||||
if (-dxmin == dymin && e2min <= dxmin) {
|
||||
e2min = 0;
|
||||
}
|
||||
}
|
||||
if (e2min > dxmin) {
|
||||
errmin += ++dxmin * 2 + 1;
|
||||
}
|
||||
}
|
||||
} while (dxmax <= 0);
|
||||
}
|
||||
void Display::filled_gauge(int center_x, int center_y, int radius1, int radius2, int progress, Color color) {
|
||||
int rmax = radius1 > radius2 ? radius1 : radius2;
|
||||
int rmin = radius1 < radius2 ? radius1 : radius2;
|
||||
int dxmax = -int32_t(rmax), dxmin = -int32_t(rmin), upd_dxmax, upd_dxmin;
|
||||
int dymax = 0, dymin = 0;
|
||||
int errmax = 2 - 2 * rmax, errmin = 2 - 2 * rmin;
|
||||
int e2max, e2min;
|
||||
progress = std::max(0, std::min(progress, 100)); // 0..100
|
||||
int draw_progress = progress > 50 ? (100 - progress) : progress;
|
||||
float tan_a = (progress == 50) ? 65535 : tan(float(draw_progress) * M_PI / 100); // slope
|
||||
|
||||
do {
|
||||
// outer dots
|
||||
this->draw_pixel_at(center_x + dxmax, center_y - dymax, color);
|
||||
this->draw_pixel_at(center_x - dxmax, center_y - dymax, color);
|
||||
if (dymin < rmin) { // side parts
|
||||
int lhline_width = -(dxmax - dxmin) + 1;
|
||||
if (progress >= 50) {
|
||||
if (float(dymax) < float(-dxmax) * tan_a) {
|
||||
upd_dxmax = ceil(float(dymax) / tan_a);
|
||||
} else {
|
||||
upd_dxmax = -dxmax;
|
||||
}
|
||||
this->horizontal_line(center_x + dxmax, center_y - dymax, lhline_width, color); // left
|
||||
if (!dymax)
|
||||
this->horizontal_line(center_x - dxmin, center_y, lhline_width, color); // right horizontal border
|
||||
if (upd_dxmax > -dxmin) { // right
|
||||
int rhline_width = (upd_dxmax + dxmin) + 1;
|
||||
this->horizontal_line(center_x - dxmin, center_y - dymax,
|
||||
rhline_width > lhline_width ? lhline_width : rhline_width, color);
|
||||
}
|
||||
} else {
|
||||
if (float(dymin) > float(-dxmin) * tan_a) {
|
||||
upd_dxmin = ceil(float(dymin) / tan_a);
|
||||
} else {
|
||||
upd_dxmin = -dxmin;
|
||||
}
|
||||
lhline_width = -(dxmax + upd_dxmin) + 1;
|
||||
if (!dymax)
|
||||
this->horizontal_line(center_x - dxmin, center_y, lhline_width, color); // right horizontal border
|
||||
if (lhline_width > 0)
|
||||
this->horizontal_line(center_x + dxmax, center_y - dymax, lhline_width, color);
|
||||
}
|
||||
} else { // top part
|
||||
int hline_width = 2 * (-dxmax) + 1;
|
||||
if (progress >= 50) {
|
||||
if (dymax < float(-dxmax) * tan_a) {
|
||||
upd_dxmax = ceil(float(dymax) / tan_a);
|
||||
hline_width = -dxmax + upd_dxmax + 1;
|
||||
}
|
||||
} else {
|
||||
if (dymax < float(-dxmax) * tan_a) {
|
||||
upd_dxmax = ceil(float(dymax) / tan_a);
|
||||
hline_width = -dxmax - upd_dxmax + 1;
|
||||
} else
|
||||
hline_width = 0;
|
||||
}
|
||||
if (hline_width > 0)
|
||||
this->horizontal_line(center_x + dxmax, center_y - dymax, hline_width, color);
|
||||
}
|
||||
e2max = errmax;
|
||||
if (e2max < dymax) {
|
||||
errmax += ++dymax * 2 + 1;
|
||||
if (-dxmax == dymax && e2max <= dxmax) {
|
||||
e2max = 0;
|
||||
}
|
||||
}
|
||||
if (e2max > dxmax) {
|
||||
errmax += ++dxmax * 2 + 1;
|
||||
}
|
||||
while (dymin <= dymax && dymin <= rmin && dxmin <= 0) {
|
||||
this->draw_pixel_at(center_x + dxmin, center_y - dymin, color);
|
||||
this->draw_pixel_at(center_x - dxmin, center_y - dymin, color);
|
||||
e2min = errmin;
|
||||
if (e2min < dymin) {
|
||||
errmin += ++dymin * 2 + 1;
|
||||
if (-dxmin == dymin && e2min <= dxmin) {
|
||||
e2min = 0;
|
||||
}
|
||||
}
|
||||
if (e2min > dxmin) {
|
||||
errmin += ++dxmin * 2 + 1;
|
||||
}
|
||||
}
|
||||
} while (dxmax <= 0);
|
||||
}
|
||||
void HOT Display::triangle(int x1, int y1, int x2, int y2, int x3, int y3, Color color) {
|
||||
this->line(x1, y1, x2, y2, color);
|
||||
this->line(x1, y1, x3, y3, color);
|
||||
|
|
|
@ -285,6 +285,13 @@ class Display : public PollingComponent {
|
|||
/// Fill a circle centered around [center_x,center_y] with the radius radius with the given color.
|
||||
void filled_circle(int center_x, int center_y, int radius, Color color = COLOR_ON);
|
||||
|
||||
/// Fill a ring centered around [center_x,center_y] between two circles with the radius1 and radius2 with the given
|
||||
/// color.
|
||||
void filled_ring(int center_x, int center_y, int radius1, int radius2, Color color = COLOR_ON);
|
||||
/// Fill a half-ring "gauge" centered around [center_x,center_y] between two circles with the radius1 and radius2
|
||||
/// with he given color and filled up to 'progress' percent
|
||||
void filled_gauge(int center_x, int center_y, int radius1, int radius2, int progress, Color color = COLOR_ON);
|
||||
|
||||
/// Draw the outline of a triangle contained between the points [x1,y1], [x2,y2] and [x3,y3] with the given color.
|
||||
void triangle(int x1, int y1, int x2, int y2, int x3, int y3, Color color = COLOR_ON);
|
||||
|
||||
|
|
|
@ -34,3 +34,7 @@ display:
|
|||
|
||||
it.line_at_angle(centerX, centerY, minuteAngle, radius - 5, radius);
|
||||
}
|
||||
|
||||
// Nice ring around and some gauge
|
||||
it.filled_ring(centerX, centerY, radius+5, radius+8);
|
||||
it.filled_gauge(centerX, centerY, radius/2, radius/2-5, 66);
|
||||
|
|
Loading…
Reference in a new issue