Skip to content
105 changes: 105 additions & 0 deletions Adafruit_GFX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions Adafruit_GFX.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
67 changes: 67 additions & 0 deletions examples/RotatedRectTest/RotatedRectTest.ino
Original file line number Diff line number Diff line change
@@ -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 <SPI.h>
// #include <Adafruit_ST7789.h>
#include <Adafruit_GFX.h>

// #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.drawRotatedRect(DRAW_CIRCLE_X, DRAW_CIRCLE_Y, WIDTH, HEIGHT, angle, WHITE);
canvas.fillRotatedRect(FILL_CIRCLE_X, FILL_CIRCLE_Y, 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);
}