diff --git a/Adafruit_GFX.cpp b/Adafruit_GFX.cpp index 5b33ee41..33eaff06 100644 --- a/Adafruit_GFX.cpp +++ b/Adafruit_GFX.cpp @@ -700,6 +700,135 @@ void Adafruit_GFX::fillRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, endWrite(); } +/**************************************************************************/ +/*! + @brief Draw a rotated rectangle + @param cenX x coordinate of center of rectangle + @param cenY y coordinate of center of rectangle + @param w width of rectangle + @param h height of rectangle + @param angleDeg angle of rotation of rectangle + @param color 16-bit 5-6-5 Color to fill/draw with +*/ +/**************************************************************************/ +void Adafruit_GFX::drawRotatedRect(int16_t cenX, int16_t cenY, int16_t w, + int16_t h, int16_t angleDeg, + uint16_t color) { + + if (w < 1 || h < 1) + return; // We don't draw zero dimensioned objects + + int16_t W = w - 1; + int16_t H = h - 1; + + int16_t halfW = (W / 2); // Midpoint should always be integer + int16_t halfH = (H / 2); // Midpoint should always be integer + + int16_t x0 = W - halfW; // bottom-right + int16_t y0 = H - halfH; // bottom-right + int16_t x1 = -halfW; // bottom-left + int16_t y1 = H - halfH; // bottom-left + int16_t x2 = -halfW; // top-left + int16_t y2 = -halfH; // top-left + int16_t x3 = W - halfW; // top-right + int16_t y3 = -halfH; // top-right + + rotatePoint(x0, y0, angleDeg); + rotatePoint(x1, y1, angleDeg); + rotatePoint(x2, y2, angleDeg); + rotatePoint(x3, y3, angleDeg); + + x0 += cenX; + x1 += cenX; + x2 += cenX; + x3 += cenX; + + y0 += cenY; + y1 += cenY; + y2 += cenY; + y3 += cenY; + + drawLine(x0, y0, x1, y1, color); // bottom right to bottom left + drawLine(x1, y1, x2, y2, color); // bottom left to top left + drawLine(x2, y2, x3, y3, color); // top left to top right + drawLine(x3, y3, x0, y0, color); // top right to bottom right +} + +/**************************************************************************/ +/*! + @brief Draw a filled rotated rectangle + @param cenX x coordinate of center of rectangle + @param cenY y coordinate of center of rectangle + @param w width of rectangle + @param h height of rectangle + @param angleDeg angle of rotation of rectangle + @param color 16-bit 5-6-5 Color to fill/draw with +*/ +/**************************************************************************/ +void Adafruit_GFX::fillRotatedRect(int16_t cenX, int16_t cenY, int16_t w, + int16_t h, int16_t angleDeg, + uint16_t color) { + + if (w < 1 || h < 1) + return; // We don't draw zero dimensioned objects + + int16_t W = w - 1; + int16_t H = h - 1; + + int16_t halfW = (W / 2); // Midpoint should always be integer + int16_t halfH = (H / 2); // Midpoint should always be integer + + int16_t x0 = W - halfW; // bottom-right + int16_t y0 = H - halfH; // bottom-right + int16_t x1 = -halfW; // bottom-left + int16_t y1 = H - halfH; // bottom-left + int16_t x2 = -halfW; // top-left + int16_t y2 = -halfH; // top-left + int16_t x3 = W - halfW; // top-right + int16_t y3 = -halfH; // top-right + + rotatePoint(x0, y0, angleDeg); + rotatePoint(x1, y1, angleDeg); + rotatePoint(x2, y2, angleDeg); + rotatePoint(x3, y3, angleDeg); + + x0 += cenX; + x1 += cenX; + x2 += cenX; + x3 += cenX; + + y0 += cenY; + y1 += cenY; + y2 += cenY; + y3 += cenY; + + fillTriangle(x0, y0, x1, y1, x2, y2, color); + fillTriangle(x2, y2, x3, y3, x0, y0, color); +} + +/**************************************************************************/ +/*! + @brief Rotate a point in standard position + @param x0 x coordinate of point to rotate. This is passed by reference + and updated upon return + @param y0 y coordinate of point to rotate. This is passed by reference + and updated upon return + @param angleDeg angle of rotation of rectangle +*/ +/**************************************************************************/ +void Adafruit_GFX::rotatePoint(int16_t &x0, int16_t &y0, int16_t angleDeg) { + float angleRad = radians(angleDeg); + float s = sin(angleRad); + float c = cos(angleRad); + + float x = x0; + float y = y0; + + // Rotate point + x0 = (int16_t)((x * c) - (y * s)); + y0 = (int16_t)((x * s) + (y * c)); +} + /**************************************************************************/ /*! @brief Draw a triangle with no fill color diff --git a/Adafruit_GFX.h b/Adafruit_GFX.h index 032d8ea4..dd9dc0dc 100644 --- a/Adafruit_GFX.h +++ b/Adafruit_GFX.h @@ -85,6 +85,11 @@ class Adafruit_GFX : public Print { int16_t radius, uint16_t color); void fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color); + void drawRotatedRect(int16_t cenX, int16_t cenY, int16_t w, int16_t h, + int16_t angleDeg, uint16_t color); + void fillRotatedRect(int16_t cenX, int16_t cenY, int16_t w, int16_t h, + int16_t angleDeg, uint16_t color); + void rotatePoint(int16_t &x0, int16_t &y0, int16_t angleDeg); void drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color); void drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, diff --git a/examples/RotatedRectTest/RotatedRectTest.ino b/examples/RotatedRectTest/RotatedRectTest.ino new file mode 100644 index 00000000..20763919 --- /dev/null +++ b/examples/RotatedRectTest/RotatedRectTest.ino @@ -0,0 +1,87 @@ +/*************************************************** + This is an example to exercise the rotated rectangle + methods 'drawRotatedRect' and 'fillRotatedRect'. + The commented lines represent hardware-specific + details that will need to be customized for the + particular display chosen by the end-user. + ****************************************************/ + +// #include +// #include +#include + +// #define TFT_RST D0 +// #define TFT_DC D1 +// #define TFT_CS D2 +// #define TFT_BACKLIGHT D3 +// #define SPI_SPEED 40000000 +// #define ROTATION 1 + +#define SCREEN_WIDTH 128 +#define SCREEN_HEIGHT 128 + +#define SERIAL_SPEED 9600 + +#define DRAW_CIRCLE_X 44 +#define DRAW_CIRCLE_Y 44 +#define FILL_CIRCLE_X 84 +#define FILL_CIRCLE_Y 84 +#define WIDTH 40 +#define HEIGHT 30 +#define BLACK 0x0000 +#define WHITE 0xFFFF +#define GREEN 0x07E0 + + +//Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST); +GFXcanvas16 canvas = GFXcanvas16(SCREEN_WIDTH, SCREEN_HEIGHT); + +int16_t angle = 0; + +void setup(void) +{ + Serial.begin(SERIAL_SPEED); + Serial.println("Start up."); + initializeTFT(); +} + +void loop() +{ + canvas.fillScreen(BLACK); + canvas.fillRect(0, 10, 10, 1, GREEN); + canvas.fillRotatedRect(14, 10, 10, 1, angle, GREEN); + canvas.fillRect(20, 10, 10, 2, GREEN); + canvas.fillRotatedRect(34, 10, 10, 2, angle, GREEN); + canvas.fillRect(40, 10, 10, 3, GREEN); + canvas.fillRotatedRect(54, 11, 10, 3, angle, GREEN); + canvas.fillRect(60, 10, 10, 4, GREEN); + canvas.fillRotatedRect(74, 11, 10, 4, angle, GREEN); + canvas.fillRect(80, 10, 10, 5, GREEN); + canvas.fillRotatedRect(94, 12, 10, 5, angle, GREEN); + //Un-comment to display the rotated rectangles on your display + //tft.drawRGBBitmap(0, 0, canvas.getBuffer(), SCREEN_WIDTH, SCREEN_HEIGHT); + delay(10000); + + for( int scale = 0; scale < HEIGHT; scale++) + { + for(int angle = 0; angle < 360; angle++) + { + canvas.fillScreen(BLACK); + canvas.drawRotatedRect(DRAW_CIRCLE_X, DRAW_CIRCLE_Y, WIDTH - scale, HEIGHT - scale, angle, WHITE); + canvas.fillRotatedRect(FILL_CIRCLE_X, FILL_CIRCLE_Y, WIDTH - scale, HEIGHT - scale, angle, GREEN); + //Un-comment to display the rotated rectangles on your display + //tft.drawRGBBitmap(0, 0, canvas.getBuffer(), SCREEN_WIDTH, SCREEN_HEIGHT); + } + } +} + +void initializeTFT(void) +{ + // pinMode(TFT_BACKLIGHT, OUTPUT); + // digitalWrite(TFT_BACKLIGHT, HIGH); + // tft.init(SCREEN_WIDTH, SCREEN_HEIGHT); + // tft.setSPISpeed(SPI_SPEED); + // tft.setRotation(ROTATION); +} + +