diff --git a/Adafruit_GFX.cpp b/Adafruit_GFX.cpp index 5b33ee41..fcf1620a 100644 --- a/Adafruit_GFX.cpp +++ b/Adafruit_GFX.cpp @@ -700,6 +700,111 @@ 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) { + + int16_t halfW = w / 2; + int16_t halfH = h / 2; + + int16_t x0 = cenX - halfW; // top-left + int16_t y0 = cenY - halfH; // top-left + int16_t x1 = cenX + halfW; // top-right + int16_t y1 = cenY - halfH; // top-right + int16_t x2 = cenX - halfW; // bottom-left + int16_t y2 = cenY + halfH; // bottom-left + int16_t x3 = cenX + halfW; // bottom-right + int16_t y3 = cenY + halfH; // bottom-right + + rotatePoint(x0, y0, cenX, cenY, angleDeg); + rotatePoint(x1, y1, cenX, cenY, angleDeg); + rotatePoint(x2, y2, cenX, cenY, angleDeg); + rotatePoint(x3, y3, cenX, cenY, angleDeg); + + drawLine(x0, y0, x1, y1, color); // top left to top right + drawLine(x0, y0, x2, y2, color); // top left to bottom left + drawLine(x1, y1, x3, y3, color); // top right to bottom right + drawLine(x2, y2, x3, y3, color); // bottom left 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) { + + int16_t halfW = w / 2; + int16_t halfH = h / 2; + + int16_t x0 = cenX - halfW; // top-left + int16_t y0 = cenY - halfH; // top-left + int16_t x1 = cenX + halfW; // top-right + int16_t y1 = cenY - halfH; // top-right + int16_t x2 = cenX - halfW; // bottom-left + int16_t y2 = cenY + halfH; // bottom-left + int16_t x3 = cenX + halfW; // bottom-right + int16_t y3 = cenY + halfH; // bottom-right + + rotatePoint(x0, y0, cenX, cenY, angleDeg); + rotatePoint(x1, y1, cenX, cenY, angleDeg); + rotatePoint(x2, y2, cenX, cenY, angleDeg); + rotatePoint(x3, y3, cenX, cenY, angleDeg); + + fillTriangle(x0, y0, x1, y1, x2, y2, color); + fillTriangle(x1, y1, x2, y2, x3, y3, color); +} + +/**************************************************************************/ +/*! + @brief Rotate a point around another point + @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 orgX x coordinate of point to be rotated around + @param orgY y coordinate of point to be rotated around + @param angleDeg angle of rotation of rectangle +*/ +/**************************************************************************/ +void Adafruit_GFX::rotatePoint(int16_t &x0, int16_t &y0, int16_t orgX, + int16_t orgY, int16_t angleDeg) { + float angleRad = radians(angleDeg); + float s = sin(angleRad); + float c = cos(angleRad); + + // Translate to standard position + int16_t xStan = x0 - orgX; + int16_t yStan = y0 - orgY; + + // Rotate point + int16_t xRot = (int16_t)((float)xStan * c - (float)yStan * s); + int16_t yRot = (int16_t)((float)xStan * s + (float)yStan * c); + + // Translate back + x0 = xRot + orgX; + y0 = yRot + orgY; +} + /**************************************************************************/ /*! @brief Draw a triangle with no fill color diff --git a/Adafruit_GFX.h b/Adafruit_GFX.h index 032d8ea4..f6544b51 100644 --- a/Adafruit_GFX.h +++ b/Adafruit_GFX.h @@ -85,6 +85,12 @@ 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 orgX, int16_t orgY, + 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..2abf6522 --- /dev/null +++ b/examples/RotatedRectTest/RotatedRectTest.ino @@ -0,0 +1,67 @@ +/*************************************************** + 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_TOP 44 +#define DRAW_CIRCLE_LEFT 44 +#define FILL_CIRCLE_TOP 84 +#define FILL_CIRCLE_LEFT 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.drawRotatedRect(DRAW_CIRCLE_TOP, DRAW_CIRCLE_TOP, WIDTH, HEIGHT, angle, WHITE); + canvas.fillRotatedRect(DRAW_CIRCLE_TOP, DRAW_CIRCLE_TOP, WIDTH, HEIGHT, angle, GREEN); + //Un-comment to display the rotated rectangles on your display + //tft.drawRGBBitmap(0, 0, canvas.getBuffer(), SCREEN_WIDTH, SCREEN_HEIGHT); + ++angle %= 360; +} + +void initializeTFT(void) +{ + // pinMode(TFT_BACKLIGHT, OUTPUT); + // digitalWrite(TFT_BACKLIGHT, HIGH); + // tft.init(SCREEN_WIDTH, SCREEN_HEIGHT); + // tft.setSPISpeed(SPI_SPEED); + // tft.setRotation(ROTATION); +} + +