From 615f3b939c5b5c2acf345a850ec733a572ba4e38 Mon Sep 17 00:00:00 2001 From: nitko12 Date: Mon, 14 Sep 2020 12:07:34 +0200 Subject: [PATCH] Better polygon drawing. --- Image Flowchart.drawio | 248 ------------------ .../2-Inkplate_basic_grayscale.ino | 17 +- .../3-Inkplate-basic_partial_update.ino | 48 ++-- .../4-Inkplate-basic_custom_font.ino | 50 ++-- .../02-Inkplate_Low_Power.ino | 42 +-- ...kplate_Battery_Voltage_And_Temperature.ino | 43 +-- .../06-Inkplate_SD_TXT_file.ino | 56 ++-- .../07-Inkplate_easyC/07-Inkplate_easyC.ino | 52 ++-- .../08-Inkplate_MCP23017_expander.ino | 24 +- .../09-Inkplate_Web_Server.ino | 72 ++--- .../10-Inkplate_Web_BMP_pictures.ino | 43 +-- .../11-Inkplate_SD_JPEG_pictures.ino | 6 +- .../01-Daily_weather_station_example.ino | 13 +- src/include/Shapes.cpp | 27 +- src/include/Shapes.h | 65 +++-- src/include/ShapesPolygon.cpp | 231 ++++++++++++++++ src/include/Triangulate.cpp | 143 ---------- src/include/Triangulate.h | 30 --- test/drawing1bit/drawing1bit.ino | 1 + test/drawing3bit/drawing3bit.ino | 1 + test/test.ino | 34 ++- 21 files changed, 566 insertions(+), 680 deletions(-) delete mode 100644 Image Flowchart.drawio create mode 100644 src/include/ShapesPolygon.cpp delete mode 100644 src/include/Triangulate.cpp delete mode 100644 src/include/Triangulate.h create mode 100644 test/drawing1bit/drawing1bit.ino create mode 100644 test/drawing3bit/drawing3bit.ino diff --git a/Image Flowchart.drawio b/Image Flowchart.drawio deleted file mode 100644 index 77a3e1b..0000000 --- a/Image Flowchart.drawio +++ /dev/null @@ -1,248 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/1. Basic Inkplate Functionality/2-Inkplate_basic_grayscale/2-Inkplate_basic_grayscale.ino b/examples/1. Basic Inkplate Functionality/2-Inkplate_basic_grayscale/2-Inkplate_basic_grayscale.ino index 8d4caf3..795f84b 100644 --- a/examples/1. Basic Inkplate Functionality/2-Inkplate_basic_grayscale/2-Inkplate_basic_grayscale.ino +++ b/examples/1. Basic Inkplate Functionality/2-Inkplate_basic_grayscale/2-Inkplate_basic_grayscale.ino @@ -17,14 +17,13 @@ 15 July 2020 by e-radionica.com */ -#include "Inkplate.h" //Include Inkplate library to the sketch -#include "image.h" //Include image file that holds grayscale image data. You can see it in next tab inside Arduino IDE. +#include "Inkplate.h" //Include Inkplate library to the sketch +#include "image.h" //Include image file that holds grayscale image data. You can see it in next tab inside Arduino IDE. Inkplate display(INKPLATE_3BIT); // Create object on Inkplate library and set library to work in grayscale mode (3-bit) // Other option is monochrome mode, which is demonstrated in next example // "2-Inkplate_basic_monochrome" - -#define DELAY_MS \ +#define DELAY_MS \ 5000 //Delay in milliseconds between screen refresh. Refreshing e-paper screens more often than 5s is not recommended \ //Want to refresh faster? Use partial update! Find example in "3-Inkplate-basic_partial_update" @@ -54,9 +53,9 @@ void loop() displayCurrentAction( "Drawing a pixel"); // Function which writes small text at bottom left indicating what's currently done // NOTE: you do not need displayCurrentAction function to use Inkplate! - display.display(); // Send image to display. You need to call this one each time you want to transfer frame buffer - // to the screen. - delay(DELAY_MS); // Wait a little bit + display.display(); // Send image to display. You need to call this one each time you want to transfer frame buffer + // to the screen. + delay(DELAY_MS); // Wait a little bit // Now, let's draw some random pixels! display.clearDisplay(); // Clear everything that is inside frame buffer in ESP32 @@ -73,7 +72,7 @@ void loop() display.clearDisplay(); display.drawLine( 0, 0, 799, 599, - 0); // All of those drawing fuctions originate from Adafruit GFX library, so maybe you are already familiar + 0); // All of those drawing fuctions originate from Adafruit GFX library, so maybe you are already familiar display.drawLine(799, 0, 0, 599, 0); // with those. Arguments are: start X, start Y, ending X, ending Y, color. displayCurrentAction("Drawing two diagonal lines"); display.display(); @@ -270,7 +269,7 @@ void loop() { display.setTextColor(i); display.setTextSize(i + - 1); // textSize parameter starts at 0 and goes up to 10 (larger won't fit Inkplate 6 screen) + 1); // textSize parameter starts at 0 and goes up to 10 (larger won't fit Inkplate 6 screen) display.setCursor(200, (i * i * 8)); // setCursor works as same as on LCD displays - sets "the cursor" at the // place you want to write someting next display.print("INKPLATE6!"); // The actual text you want to show on e-paper as String diff --git a/examples/1. Basic Inkplate Functionality/3-Inkplate-basic_partial_update/3-Inkplate-basic_partial_update.ino b/examples/1. Basic Inkplate Functionality/3-Inkplate-basic_partial_update/3-Inkplate-basic_partial_update.ino index 0a32948..da80419 100644 --- a/examples/1. Basic Inkplate Functionality/3-Inkplate-basic_partial_update/3-Inkplate-basic_partial_update.ino +++ b/examples/1. Basic Inkplate Functionality/3-Inkplate-basic_partial_update/3-Inkplate-basic_partial_update.ino @@ -15,8 +15,8 @@ 15 July 2020 by e-radionica.com */ -#include "Inkplate.h" //Include Inkplate library to the sketch -Inkplate display(INKPLATE_1BIT); //Create an object on Inkplate library and also set library into 1-bit mode (Monochrome) +#include "Inkplate.h" //Include Inkplate library to the sketch +Inkplate display(INKPLATE_1BIT); //Create an object on Inkplate library and also set library into 1-bit mode (Monochrome) //Char array where you can store your text that will be scrolled. const char text[] = "This is partial update on Inkplate 6 e-paper display! :)"; @@ -26,27 +26,33 @@ int offset = 800; //Variable that keeps count on how much screen has been partially updated int n = 0; -void setup() { - display.begin(); //Init Inkplate library (you should call this function ONLY ONCE) - display.clearDisplay(); //Clear frame buffer of display - display.display(); //Put clear image on display - display.setTextColor(BLACK, WHITE); //Set text color to be black and background color to be white - display.setTextSize(4); //Set text to be 4 times bigger than classic 5x7 px text - display.setTextWrap(false); //Disable text wraping +void setup() +{ + display.begin(); //Init Inkplate library (you should call this function ONLY ONCE) + display.clearDisplay(); //Clear frame buffer of display + display.display(); //Put clear image on display + display.setTextColor(BLACK, WHITE); //Set text color to be black and background color to be white + display.setTextSize(4); //Set text to be 4 times bigger than classic 5x7 px text + display.setTextWrap(false); //Disable text wraping } -void loop() { - display.clearDisplay(); //Clear content in frame buffer - display.setCursor(offset, 300); //Set new position for text - display.print(text); //Write text at new position - if(n>9) { //Check if you need to do full refresh or you can do partial update - display.display(); //Do a full refresh +void loop() +{ + display.clearDisplay(); //Clear content in frame buffer + display.setCursor(offset, 300); //Set new position for text + display.print(text); //Write text at new position + if (n > 9) + { //Check if you need to do full refresh or you can do partial update + display.display(); //Do a full refresh n = 0; - }else{ - display.partialUpdate(); //Do partial update - n++; //Keep track on how many times screen has been partially updated } - offset-=20; //Move text into new position - if(offset<0) offset = 800; //Text is scrolled till the end of the screen? Get it back on the start! - delay(500); //Delay between refreshes. + else + { + display.partialUpdate(); //Do partial update + n++; //Keep track on how many times screen has been partially updated + } + offset -= 20; //Move text into new position + if (offset < 0) + offset = 800; //Text is scrolled till the end of the screen? Get it back on the start! + delay(500); //Delay between refreshes. } diff --git a/examples/1. Basic Inkplate Functionality/4-Inkplate-basic_custom_font/4-Inkplate-basic_custom_font.ino b/examples/1. Basic Inkplate Functionality/4-Inkplate-basic_custom_font/4-Inkplate-basic_custom_font.ino index 4af788f..cff5fb6 100644 --- a/examples/1. Basic Inkplate Functionality/4-Inkplate-basic_custom_font/4-Inkplate-basic_custom_font.ino +++ b/examples/1. Basic Inkplate Functionality/4-Inkplate-basic_custom_font/4-Inkplate-basic_custom_font.ino @@ -19,36 +19,38 @@ 15 July 2020 by e-radionica.com */ -#include "Inkplate.h" //Include Inkplate library to the sketch -#include "Not_Just_Groovy20pt7b.h" //Include first .h font file to the sketch -#include "DSEG14Classic_Regular20pt7b.h" //Include second font -Inkplate display(INKPLATE_1BIT); //Create an object on Inkplate library and also set library into 1-bit mode (Monochrome) +#include "Inkplate.h" //Include Inkplate library to the sketch +#include "Not_Just_Groovy20pt7b.h" //Include first .h font file to the sketch +#include "DSEG14Classic_Regular20pt7b.h" //Include second font +Inkplate display(INKPLATE_1BIT); //Create an object on Inkplate library and also set library into 1-bit mode (Monochrome) -void setup() { - display.begin(); //Init Inkplate library (you should call this function ONLY ONCE) - display.clearDisplay(); //Clear frame buffer of display - display.display(); //Put clear image on display - - display.setFont(&Not_Just_Groovy20pt7b); //Select new font - display.setTextSize(2); //Set font scaling to two (font will be 2 times bigger) - display.setCursor(0,60); //Set print cursor on X = 0, Y = 60 - display.println("Inkplate 6"); //Print some text - display.setTextSize(1); //Set font scaling to one (font is now original size) - display.print("by e-radionica.com"); //Print text +void setup() +{ + display.begin(); //Init Inkplate library (you should call this function ONLY ONCE) + display.clearDisplay(); //Clear frame buffer of display + display.display(); //Put clear image on display - display.setFont(&DSEG14Classic_Regular20pt7b); //Select second font - display.setCursor(0, 250); //Set print position on X = 0, Y = 250 - display.println("Some old-school 14 segment"); //Print text + display.setFont(&Not_Just_Groovy20pt7b); //Select new font + display.setTextSize(2); //Set font scaling to two (font will be 2 times bigger) + display.setCursor(0, 60); //Set print cursor on X = 0, Y = 60 + display.println("Inkplate 6"); //Print some text + display.setTextSize(1); //Set font scaling to one (font is now original size) + display.print("by e-radionica.com"); //Print text + + display.setFont(&DSEG14Classic_Regular20pt7b); //Select second font + display.setCursor(0, 250); //Set print position on X = 0, Y = 250 + display.println("Some old-school 14 segment"); //Print text display.println("display font on e-paper"); display.print("display"); - display.setFont(); //Use original 5x7 pixel fonts - display.setCursor(0, 550); //Set new print position at X = 0, Y = 550 - display.setTextSize(3); //Set font scaling to three (font will be 3 times bigger) - display.print("Classic 5x7 px fonts"); //Print text - display.display(); //Display everything on display + display.setFont(); //Use original 5x7 pixel fonts + display.setCursor(0, 550); //Set new print position at X = 0, Y = 550 + display.setTextSize(3); //Set font scaling to three (font will be 3 times bigger) + display.print("Classic 5x7 px fonts"); //Print text + display.display(); //Display everything on display } -void loop() { +void loop() +{ //Nothing... } diff --git a/examples/2. Advanced Inkplate Features/02-Inkplate_Low_Power/02-Inkplate_Low_Power.ino b/examples/2. Advanced Inkplate Features/02-Inkplate_Low_Power/02-Inkplate_Low_Power.ino index 8f276cc..b6eef15 100644 --- a/examples/2. Advanced Inkplate Features/02-Inkplate_Low_Power/02-Inkplate_Low_Power.ino +++ b/examples/2. Advanced Inkplate Features/02-Inkplate_Low_Power/02-Inkplate_Low_Power.ino @@ -17,34 +17,36 @@ 15 July 2020 by e-radionica.com */ -#include "Inkplate.h" //Include Inkplate library to the sketch -#include "picture1.h" //Include .h files of 3 pictures. All three pictures were converted using LCD Image Converter software +#include "Inkplate.h" //Include Inkplate library to the sketch +#include "picture1.h" //Include .h files of 3 pictures. All three pictures were converted using LCD Image Converter software #include "picture2.h" #include "picture3.h" -#include "driver/rtc_io.h" //ESP32 library used for deep sleep and RTC wake up pins -const uint8_t* pictures[] = {pic1, pic2, pic3}; //This array of pinters holds address of every picture in the memory, - //so we can easly select it by selecting index in array +#include "driver/rtc_io.h" //ESP32 library used for deep sleep and RTC wake up pins +const uint8_t *pictures[] = {pic1, pic2, pic3}; //This array of pinters holds address of every picture in the memory, + //so we can easly select it by selecting index in array -#define uS_TO_S_FACTOR 1000000 //Conversion factor for micro seconds to seconds -#define TIME_TO_SLEEP 20 //How long ESP32 will be in deep sleep (in seconds) +#define uS_TO_S_FACTOR 1000000 //Conversion factor for micro seconds to seconds +#define TIME_TO_SLEEP 20 //How long ESP32 will be in deep sleep (in seconds) RTC_DATA_ATTR int slide = 0; -Inkplate display(INKPLATE_3BIT); //Create an object on Inkplate library and also set library into 3 Bit mode (Grayscale) +Inkplate display(INKPLATE_3BIT); //Create an object on Inkplate library and also set library into 3 Bit mode (Grayscale) -void setup() { - display.begin(); //Init Inkplate library (you should call this function ONLY ONCE) - display.clearDisplay(); //Clear frame buffer of display - display.drawBitmap3Bit(0, 0, pictures[slide], 800, 600); //Display selected picture at location X=0, Y=0. All three pictures have resolution of 800x600 pixels - display.display(); //Refresh the screen with new picture - slide++; //Update counter for pictures. With this variable, we choose what picture is going to be displayed on screen - if (slide > 2) slide = 0; //We do not have more than 3 images, so roll back to zero +void setup() +{ + display.begin(); //Init Inkplate library (you should call this function ONLY ONCE) + display.clearDisplay(); //Clear frame buffer of display + display.drawBitmap3Bit(0, 0, pictures[slide], 800, 600); //Display selected picture at location X=0, Y=0. All three pictures have resolution of 800x600 pixels + display.display(); //Refresh the screen with new picture + slide++; //Update counter for pictures. With this variable, we choose what picture is going to be displayed on screen + if (slide > 2) + slide = 0; //We do not have more than 3 images, so roll back to zero - rtc_gpio_isolate(GPIO_NUM_12); //Isolate/disable GPIO12 on ESP32 (only to reduce power consumption in sleep) - esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR); //Activate wake-up timer -- wake up after 20s here - esp_deep_sleep_start(); //Put ESP32 into deep sleep. Program stops here. + rtc_gpio_isolate(GPIO_NUM_12); //Isolate/disable GPIO12 on ESP32 (only to reduce power consumption in sleep) + esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR); //Activate wake-up timer -- wake up after 20s here + esp_deep_sleep_start(); //Put ESP32 into deep sleep. Program stops here. } -void loop() { +void loop() +{ //Nothing! If you use deep sleep, whole program should be in setup() because each time the board restarts, not in a loop()! loop() must be empty! - } diff --git a/examples/2. Advanced Inkplate Features/03-Inkplate_Battery_Voltage_And_Temperature/03-Inkplate_Battery_Voltage_And_Temperature.ino b/examples/2. Advanced Inkplate Features/03-Inkplate_Battery_Voltage_And_Temperature/03-Inkplate_Battery_Voltage_And_Temperature.ino index e83a31e..542bbfa 100644 --- a/examples/2. Advanced Inkplate Features/03-Inkplate_Battery_Voltage_And_Temperature/03-Inkplate_Battery_Voltage_And_Temperature.ino +++ b/examples/2. Advanced Inkplate Features/03-Inkplate_Battery_Voltage_And_Temperature/03-Inkplate_Battery_Voltage_And_Temperature.ino @@ -15,36 +15,37 @@ 15 July 2020 by e-radionica.com */ -#include "Inkplate.h" //Include Inkplate library to the sketch -#include "symbols.h" //Include .h file that contains byte array for battery symbol and temperature symbol. - //It is in same folder as this sketch. You can even open it (read it) by clicking on symbols.h tab in Arduino IDE -Inkplate display(INKPLATE_1BIT); //Create an object on Inkplate library and also set library into 1-bit mode (Monochrome) +#include "Inkplate.h" //Include Inkplate library to the sketch +#include "symbols.h" //Include .h file that contains byte array for battery symbol and temperature symbol. + //It is in same folder as this sketch. You can even open it (read it) by clicking on symbols.h tab in Arduino IDE +Inkplate display(INKPLATE_1BIT); //Create an object on Inkplate library and also set library into 1-bit mode (Monochrome) -void setup() { - display.begin(); //Init Inkplate library (you should call this function ONLY ONCE) - display.clearDisplay(); //Clear frame buffer of display - display.display(); //Put clear image on display - display.setTextSize(2); //Scale text to be two times bigger then original (5x7 px) - display.setTextColor(BLACK, WHITE); //Set text color to black and background color to white +void setup() +{ + display.begin(); //Init Inkplate library (you should call this function ONLY ONCE) + display.clearDisplay(); //Clear frame buffer of display + display.display(); //Put clear image on display + display.setTextSize(2); //Scale text to be two times bigger then original (5x7 px) + display.setTextColor(BLACK, WHITE); //Set text color to black and background color to white } -void loop() { +void loop() +{ int temperature; float voltage; - temperature = display.readTemperature(); //Read temperature from on-board temperature sensor - voltage = display.readBattery(); //Read battery voltage (NOTE: Doe to ESP32 ADC accuracy, you should calibrate the ADC!) - display.clearDisplay(); //Clear everything in frame buffer of e-paper display - display.drawBitmap(100, 100, battSymbol, 106, 45, BLACK); //Draw battery symbol at position X=100 Y=100 + temperature = display.readTemperature(); //Read temperature from on-board temperature sensor + voltage = display.readBattery(); //Read battery voltage (NOTE: Doe to ESP32 ADC accuracy, you should calibrate the ADC!) + display.clearDisplay(); //Clear everything in frame buffer of e-paper display + display.drawBitmap(100, 100, battSymbol, 106, 45, BLACK); //Draw battery symbol at position X=100 Y=100 display.setCursor(210, 120); - display.print(voltage, 2); //Print battery voltage + display.print(voltage, 2); //Print battery voltage display.print('V'); - display.drawBitmap(100, 200, tempSymbol, 38, 79, BLACK); //Draw temperature symbol at position X=100, Y=200 + display.drawBitmap(100, 200, tempSymbol, 38, 79, BLACK); //Draw temperature symbol at position X=100, Y=200 display.setCursor(150, 225); - display.print(temperature, DEC); //Print temperature + display.print(temperature, DEC); //Print temperature display.print('C'); - display.display(); //Send everything to display (refresh the screen) - delay(10000); //Wait 10 seconds before new measurement - + display.display(); //Send everything to display (refresh the screen) + delay(10000); //Wait 10 seconds before new measurement } diff --git a/examples/2. Advanced Inkplate Features/06-Inkplate_SD_TXT_file/06-Inkplate_SD_TXT_file.ino b/examples/2. Advanced Inkplate Features/06-Inkplate_SD_TXT_file/06-Inkplate_SD_TXT_file.ino index ba31fc1..c475041 100644 --- a/examples/2. Advanced Inkplate Features/06-Inkplate_SD_TXT_file/06-Inkplate_SD_TXT_file.ino +++ b/examples/2. Advanced Inkplate Features/06-Inkplate_SD_TXT_file/06-Inkplate_SD_TXT_file.ino @@ -19,43 +19,53 @@ 15 July 2020 by e-radionica.com */ -#include "Inkplate.h" //Include Inkplate library to the sketch -#include "SdFat.h" //Include library for SD card -Inkplate display(INKPLATE_1BIT); //Create an object on Inkplate library and also set library into 1 Bit mode (Monochrome) -SdFile file; //Create SdFile object used for accessing files on SD card +#include "Inkplate.h" //Include Inkplate library to the sketch +#include "SdFat.h" //Include library for SD card +Inkplate display(INKPLATE_1BIT); //Create an object on Inkplate library and also set library into 1 Bit mode (Monochrome) +SdFile file; //Create SdFile object used for accessing files on SD card -void setup() { - display.begin(); //Init Inkplate library (you should call this function ONLY ONCE) - display.clearDisplay(); //Clear frame buffer of display - display.display(); //Put clear image on display +void setup() +{ + display.begin(); //Init Inkplate library (you should call this function ONLY ONCE) + display.clearDisplay(); //Clear frame buffer of display + display.display(); //Put clear image on display //Init SD card. Display if SD card is init propery or not. - if (display.sdCardInit()) { + if (display.sdCardInit()) + { display.println("SD Card ok! Reading data..."); display.partialUpdate(); //Try to load text with max lenght of 200 chars. - if (!file.open("/text.txt", O_RDONLY)) { //If it fails to open, send error message to display, otherwise read the file. + if (!file.open("/text.txt", O_RDONLY)) + { //If it fails to open, send error message to display, otherwise read the file. display.println("File open error"); display.display(); - } else { - display.clearDisplay(); //Clear everything that is stored in frame buffer of epaper - display.setCursor(0,0); //Set print position at the begining of the screen - char text[201]; //Array where data from SD card is stored (max 200 chars here) - int len = file.fileSize(); //Read how big is file that we are opening - if(len>200) len = 200; //If it's more than 200 bytes (200 chars), limit to max 200 bytes - file.read(text, len); //Read data from file and save it in text array - text[len] = 0; //Put null terminating char at the and of data - display.print(text); //Print data/text - display.display(); //Do a full refresh of display } - } else { //If card init was not successful, display error on screen and stop the program (using infinite loop) + else + { + display.clearDisplay(); //Clear everything that is stored in frame buffer of epaper + display.setCursor(0, 0); //Set print position at the begining of the screen + char text[201]; //Array where data from SD card is stored (max 200 chars here) + int len = file.fileSize(); //Read how big is file that we are opening + if (len > 200) + len = 200; //If it's more than 200 bytes (200 chars), limit to max 200 bytes + file.read(text, len); //Read data from file and save it in text array + text[len] = 0; //Put null terminating char at the and of data + display.print(text); //Print data/text + display.display(); //Do a full refresh of display + } + } + else + { //If card init was not successful, display error on screen and stop the program (using infinite loop) display.println("SD Card error!"); display.partialUpdate(); - while (true); + while (true) + ; } } -void loop() { +void loop() +{ //Nothing... } diff --git a/examples/2. Advanced Inkplate Features/07-Inkplate_easyC/07-Inkplate_easyC.ino b/examples/2. Advanced Inkplate Features/07-Inkplate_easyC/07-Inkplate_easyC.ino index 9f5bd57..14991cd 100644 --- a/examples/2. Advanced Inkplate Features/07-Inkplate_easyC/07-Inkplate_easyC.ino +++ b/examples/2. Advanced Inkplate Features/07-Inkplate_easyC/07-Inkplate_easyC.ino @@ -18,26 +18,29 @@ 15 July 2020 by e-radionica.com */ -#include "Inkplate.h" //Include Inkplate library to the sketch -#include //Adafruit library for sensors -#include "Adafruit_BME680.h" //Adafruit library for BME680 Sensor +#include "Inkplate.h" //Include Inkplate library to the sketch +#include //Adafruit library for sensors +#include "Adafruit_BME680.h" //Adafruit library for BME680 Sensor -Inkplate display(INKPLATE_1BIT); //Create an object on Inkplate library and also set library into 1 Bit mode (Monochrome) -Adafruit_BME680 bme; //Create an object on Adafruit BME680 library - //(with no arguments sent to constructor, that means we are using I2C communication for BME680 sensor) +Inkplate display(INKPLATE_1BIT); //Create an object on Inkplate library and also set library into 1 Bit mode (Monochrome) +Adafruit_BME680 bme; //Create an object on Adafruit BME680 library + //(with no arguments sent to constructor, that means we are using I2C communication for BME680 sensor) -int n = 0; //Variable that keep track on how many times screen has been partially updated -void setup() { - display.begin(); //Init Inkplate library (you should call this function ONLY ONCE) - display.clearDisplay(); //Clear frame buffer of display - display.display(); //Put clear image on display - display.setTextSize(2); //Set text scaling to two (text will be two times bigger than normal) +int n = 0; //Variable that keep track on how many times screen has been partially updated +void setup() +{ + display.begin(); //Init Inkplate library (you should call this function ONLY ONCE) + display.clearDisplay(); //Clear frame buffer of display + display.display(); //Put clear image on display + display.setTextSize(2); //Set text scaling to two (text will be two times bigger than normal) - if (!bme.begin(0x76)) { //Init. BME680 library. e-radionica.com BME680 sensor board uses 0x76 I2C address for sensor + if (!bme.begin(0x76)) + { //Init. BME680 library. e-radionica.com BME680 sensor board uses 0x76 I2C address for sensor display.println("Sensor init failed!"); display.println("Check sensor wiring/connection!"); display.partialUpdate(); - while (1); + while (1) + ; } //Set up oversampling and filter initialization for the sensor @@ -48,14 +51,18 @@ void setup() { bme.setGasHeater(320, 150); // 320*C for 150 ms } -void loop() { - if (!bme.performReading()) { //If sending command to start reading data fails, send error message to display +void loop() +{ + if (!bme.performReading()) + { //If sending command to start reading data fails, send error message to display display.clearDisplay(); display.setCursor(0, 0); display.print("Failed to read data from sensor"); display.partialUpdate(); - } else { //Otherwise, clear frame buffer of epaper display - display.clearDisplay(); //Print out new data + } + else + { //Otherwise, clear frame buffer of epaper display + display.clearDisplay(); //Print out new data display.setCursor(0, 0); display.print("Air temperature: "); display.print(bme.temperature); @@ -73,13 +80,16 @@ void loop() { display.print(bme.gas_resistance / 1000.0); display.println(" kOhms"); - if(n>20) { //If display has been partially updated more than 20 times, do a full refresh, otherwise, perform a partial update. + if (n > 20) + { //If display has been partially updated more than 20 times, do a full refresh, otherwise, perform a partial update. display.display(); n = 0; - }else{ + } + else + { display.partialUpdate(); n++; } } - delay(2000); //Wait a little bit between readings + delay(2000); //Wait a little bit between readings } diff --git a/examples/2. Advanced Inkplate Features/08-Inkplate_MCP23017_expander/08-Inkplate_MCP23017_expander.ino b/examples/2. Advanced Inkplate Features/08-Inkplate_MCP23017_expander/08-Inkplate_MCP23017_expander.ino index f3bab37..37bb63d 100644 --- a/examples/2. Advanced Inkplate Features/08-Inkplate_MCP23017_expander/08-Inkplate_MCP23017_expander.ino +++ b/examples/2. Advanced Inkplate Features/08-Inkplate_MCP23017_expander/08-Inkplate_MCP23017_expander.ino @@ -23,20 +23,22 @@ 15 July 2020 by e-radionica.com */ -#include "Inkplate.h" //Include Inkplate library to the sketch +#include "Inkplate.h" //Include Inkplate library to the sketch -#define LED_PIN 15 //We are going to use pin GPB7 (remember! GPA0 = 0, GPA1 = 1, ..., GPA7 = 7, GPB0 = 8, GBP1 = 9, ..., GPB7 = 15) +#define LED_PIN 15 //We are going to use pin GPB7 (remember! GPA0 = 0, GPA1 = 1, ..., GPA7 = 7, GPB0 = 8, GBP1 = 9, ..., GPB7 = 15) -Inkplate display(INKPLATE_1BIT); //Create an object on Inkplate library and also set library into 1-bit mode (Monochrome) +Inkplate display(INKPLATE_1BIT); //Create an object on Inkplate library and also set library into 1-bit mode (Monochrome) -void setup() { - display.begin(); //Init Inkplate library (you should call this function ONLY ONCE) - pinModeMCP(LED_PIN, OUTPUT); //Set pin 15 (or GPB7) to output. On that pin, we sholud connect LED with current limiting resistor +void setup() +{ + display.begin(); //Init Inkplate library (you should call this function ONLY ONCE) + display.pinModeMCP(LED_PIN, OUTPUT); //Set pin 15 (or GPB7) to output. On that pin, we sholud connect LED with current limiting resistor } -void loop() { - digitalWriteMCP(LED_PIN, LOW); //Set output to low (LED does not light up) - delay(1000); //Wait for one second - digitalWriteMCP(LED_PIN, HIGH); //Set output to high (LED lights up) - delay(1000); //Wait for one second +void loop() +{ + display.digitalWriteMCP(LED_PIN, LOW); //Set output to low (LED does not light up) + delay(1000); //Wait for one second + display.digitalWriteMCP(LED_PIN, HIGH); //Set output to high (LED lights up) + delay(1000); //Wait for one second } diff --git a/examples/2. Advanced Inkplate Features/09-Inkplate_Web_Server/09-Inkplate_Web_Server.ino b/examples/2. Advanced Inkplate Features/09-Inkplate_Web_Server/09-Inkplate_Web_Server.ino index c2240de..b82f651 100644 --- a/examples/2. Advanced Inkplate Features/09-Inkplate_Web_Server/09-Inkplate_Web_Server.ino +++ b/examples/2. Advanced Inkplate Features/09-Inkplate_Web_Server/09-Inkplate_Web_Server.ino @@ -18,62 +18,68 @@ 15 July 2020 by e-radionica.com */ -#include //Include ESP32 WiFi library -#include //Include ESP32 WiFi library for AP -#include //Include ESP32 library for Web server -#include "Inkplate.h" //Include Inkplate library to the sketch -#include "htmlCode.h" //Include .h file where we stored out html code of our web page +#include //Include ESP32 WiFi library +#include //Include ESP32 WiFi library for AP +#include //Include ESP32 library for Web server +#include "Inkplate.h" //Include Inkplate library to the sketch +#include "htmlCode.h" //Include .h file where we stored out html code of our web page -#define ssid "Inkplate6" -#define pass "e-radionica" +#define ssid "Inkplate6" +#define pass "e-radionica" -Inkplate display(INKPLATE_1BIT); //Create an object on Inkplate library and also set library into 1 Bit mode (Monochrome) -WebServer server(80); //Create Web server on port 80 (HTTP port number) +Inkplate display(INKPLATE_1BIT); //Create an object on Inkplate library and also set library into 1 Bit mode (Monochrome) +WebServer server(80); //Create Web server on port 80 (HTTP port number) IPAddress serverIP; String txt; -void setup() { - display.begin(); //Init Inkplate library (you should call this function ONLY ONCE) - display.clearDisplay(); //Clear frame buffer of display - display.display(); //Put clear image on display - display.setTextSize(3); //Scale text to be two times bigger then original (5x7 px) - display.setTextColor(BLACK, WHITE); //Set text color to black and background color to white - display.setTextWrap(true); //If text does not fit on screen, send it to new line +void setup() +{ + display.begin(); //Init Inkplate library (you should call this function ONLY ONCE) + display.clearDisplay(); //Clear frame buffer of display + display.display(); //Put clear image on display + display.setTextSize(3); //Scale text to be two times bigger then original (5x7 px) + display.setTextColor(BLACK, WHITE); //Set text color to black and background color to white + display.setTextWrap(true); //If text does not fit on screen, send it to new line - WiFi.begin(); //Init. WiFi library - WiFi.mode(WIFI_AP); //Set WiFi to Access point mode - WiFi.softAP(ssid, pass); //Set SSID (WiFi name) and password for Access point + WiFi.begin(); //Init. WiFi library + WiFi.mode(WIFI_AP); //Set WiFi to Access point mode + WiFi.softAP(ssid, pass); //Set SSID (WiFi name) and password for Access point - serverIP = WiFi.softAPIP(); //Get the server IP address + serverIP = WiFi.softAPIP(); //Get the server IP address - server.on("/", handleRoot); //If you open homepage, go to handle root function - server.on("/string/{}", handleString); //If you send some text to Inkplate, go to handleString function. Note that {} brackets at the end of address. That means that web address has some arguments (our text!). - server.begin(); //Start the web server + server.on("/", handleRoot); //If you open homepage, go to handle root function + server.on("/string/{}", handleString); //If you send some text to Inkplate, go to handleString function. Note that {} brackets at the end of address. That means that web address has some arguments (our text!). + server.begin(); //Start the web server updatePaper(); } -void loop() { - server.handleClient(); //You have to constantly read if there is any new client connected to web server +void loop() +{ + server.handleClient(); //You have to constantly read if there is any new client connected to web server } -void updateHTML() { //This function will send response to client and send HTML code of our web page +void updateHTML() +{ //This function will send response to client and send HTML code of our web page server.send(200, "text/html", s); } -void handleRoot() { //This function will send response to client if client open a root (homepage) of our web page +void handleRoot() +{ //This function will send response to client if client open a root (homepage) of our web page updateHTML(); } -void handleString() { //This function will send response to client, send HTML code of web page, get the text from argument sent in web page address and refresh screen with new text +void handleString() +{ //This function will send response to client, send HTML code of web page, get the text from argument sent in web page address and refresh screen with new text txt = server.arg(0); updateHTML(); updatePaper(); } -void updatePaper() { //This function updates screen with new data (text) - display.clearDisplay(); //Clear everything from epaper frame buffer - display.setCursor(20, 40); //Print out instruction on how to connect to Inkplate WiFi and how to open a web page +void updatePaper() +{ //This function updates screen with new data (text) + display.clearDisplay(); //Clear everything from epaper frame buffer + display.setCursor(20, 40); //Print out instruction on how to connect to Inkplate WiFi and how to open a web page display.print("Connect to "); display.print(ssid); display.println(" WiFi with pass: "); @@ -87,7 +93,7 @@ void updatePaper() { //This function updates display.println('/'); display.println(); display.fillRect(10, 240, 780, 4, BLACK); - display.println("User text:"); //Print out what user typed in web page + display.println("User text:"); //Print out what user typed in web page display.print(txt); - display.display(); //Send everything to screen (refresh the screen) + display.display(); //Send everything to screen (refresh the screen) } diff --git a/examples/2. Advanced Inkplate Features/10-Inkplate_Web_BMP_pictures/10-Inkplate_Web_BMP_pictures.ino b/examples/2. Advanced Inkplate Features/10-Inkplate_Web_BMP_pictures/10-Inkplate_Web_BMP_pictures.ino index a2ef00f..4eb1e53 100644 --- a/examples/2. Advanced Inkplate Features/10-Inkplate_Web_BMP_pictures/10-Inkplate_Web_BMP_pictures.ino +++ b/examples/2. Advanced Inkplate Features/10-Inkplate_Web_BMP_pictures/10-Inkplate_Web_BMP_pictures.ino @@ -16,15 +16,16 @@ 23 July 2020 by e-radionica.com */ -#include "Inkplate.h" //Include Inkplate library to the sketch -#include "HTTPClient.h" //Include library for HTTPClient -#include "WiFi.h" //Include library for WiFi -Inkplate display(INKPLATE_1BIT); //Create an object on Inkplate library and also set library into 1 Bit mode (Monochrome) +#include "Inkplate.h" //Include Inkplate library to the sketch +#include "HTTPClient.h" //Include library for HTTPClient +#include "WiFi.h" //Include library for WiFi +Inkplate display(INKPLATE_1BIT); //Create an object on Inkplate library and also set library into 1 Bit mode (Monochrome) -const char* ssid = ""; //Your WiFi SSID -const char* password = ""; //Your WiFi password +const char *ssid = ""; //Your WiFi SSID +const char *password = ""; //Your WiFi password -void setup() { +void setup() +{ display.begin(); //Init Inkplate library (you should call this function ONLY ONCE) display.clearDisplay(); //Clear frame buffer of display display.display(); //Put clear image on display @@ -35,7 +36,8 @@ void setup() { //Connect to the WiFi network. WiFi.mode(WIFI_MODE_STA); WiFi.begin(ssid, password); - while (WiFi.status() != WL_CONNECTED) { + while (WiFi.status() != WL_CONNECTED) + { delay(500); display.print("."); display.partialUpdate(); @@ -50,9 +52,10 @@ void setup() { //certain softwares. //Forth parameter will dither the image. //Photo taken by: Roberto Fernandez - if (!display.drawBitmapFromWeb("https://varipass.org/neowise_mono.bmp", 0, 0, false, true)) { + if (!display.drawBitmapFromWeb("https://varipass.org/neowise_mono.bmp", 0, 0, false, true)) + { //If is something failed (wrong filename or wrong bitmap format), write error message on the screen. - //REMEMBER! You can only use Windows Bitmap file with color depth of 1, 4, 8 or 24 bits with no compression! + //REMEMBER! You can only use Windows Bitmap file with color depth of 1, 4, 8 or 24 bits with no compression! display.println("Image open error"); display.display(); } @@ -70,24 +73,29 @@ void setup() { //Check response code. int httpCode = http.GET(); - if (httpCode == 200) { + if (httpCode == 200) + { //Get the response length and make sure it is not 0. int32_t len = http.getSize(); - if (len > 0) { - if (!display.drawBitmapFromWeb(http.getStreamPtr(), 0, 0, len)) { + if (len > 0) + { + if (!display.drawBitmapFromWeb(http.getStreamPtr(), 0, 0, len)) + { //If is something failed (wrong filename or wrong bitmap format), write error message on the screen. - //REMEMBER! You can only use Windows Bitmap file with color depth of 1, 4, 8 or 24 bits with no compression! + //REMEMBER! You can only use Windows Bitmap file with color depth of 1, 4, 8 or 24 bits with no compression! display.println("Image open error"); display.display(); } display.display(); } - else { + else + { display.println("Invalid response length"); display.display(); } } - else { + else + { display.println("HTTP error"); display.display(); } @@ -97,6 +105,7 @@ void setup() { WiFi.mode(WIFI_OFF); } -void loop() { +void loop() +{ //Nothing... } diff --git a/examples/2. Advanced Inkplate Features/11-Inkplate_SD_JPEG_pictures/11-Inkplate_SD_JPEG_pictures.ino b/examples/2. Advanced Inkplate Features/11-Inkplate_SD_JPEG_pictures/11-Inkplate_SD_JPEG_pictures.ino index b1c03d7..a7fad27 100644 --- a/examples/2. Advanced Inkplate Features/11-Inkplate_SD_JPEG_pictures/11-Inkplate_SD_JPEG_pictures.ino +++ b/examples/2. Advanced Inkplate Features/11-Inkplate_SD_JPEG_pictures/11-Inkplate_SD_JPEG_pictures.ino @@ -22,9 +22,9 @@ #include "Inkplate.h" //Include Inkplate library to the sketch #include "SdFat.h" //Include library for SD card -Inkplate display( - INKPLATE_1BIT); // Create an object on Inkplate library and also set library into 1 Bit mode (Monochrome) -SdFile file; // Create SdFile object used for accessing files on SD card + +Inkplate display(INKPLATE_1BIT); // Create an object on Inkplate library and also set library into 1 Bit mode (Monochrome) +SdFile file; // Create SdFile object used for accessing files on SD card void setup() { diff --git a/examples/3. Projects/01-Daily_weather_station_example/01-Daily_weather_station_example.ino b/examples/3. Projects/01-Daily_weather_station_example/01-Daily_weather_station_example.ino index 74aa2ea..38b6e72 100644 --- a/examples/3. Projects/01-Daily_weather_station_example/01-Daily_weather_station_example.ino +++ b/examples/3. Projects/01-Daily_weather_station_example/01-Daily_weather_station_example.ino @@ -55,10 +55,9 @@ Inkplate display(INKPLATE_1BIT); Network network; // Contants used for drawing icons -char abbrs[32][16] ={ "sn", "sl", "h", "t", "hr", "lr", "s", "hc", "lc", "c" }; -const uint8_t *logos[16] ={ icon_sn, icon_sl, icon_h, icon_t, icon_hr, icon_lr, icon_s, icon_hc, icon_lc, icon_c }; -const uint8_t *s_logos[16] ={ icon_s_sn, icon_s_sl, icon_s_h, icon_s_t, icon_s_hr, icon_s_lr, icon_s_s, icon_s_hc, icon_s_lc, icon_s_c }; - +char abbrs[32][16] = {"sn", "sl", "h", "t", "hr", "lr", "s", "hc", "lc", "c"}; +const uint8_t *logos[16] = {icon_sn, icon_sl, icon_h, icon_t, icon_hr, icon_lr, icon_s, icon_hc, icon_lc, icon_c}; +const uint8_t *s_logos[16] = {icon_s_sn, icon_s_sl, icon_s_h, icon_s_t, icon_s_hr, icon_s_lr, icon_s_s, icon_s_hc, icon_s_lc, icon_s_c}; char abbr1[16]; char abbr2[16]; @@ -66,7 +65,7 @@ char abbr3[16]; char abbr4[16]; // Variables for storing temperature -char temps[8][4] ={ +char temps[8][4] = { "0F", "0F", "0F", @@ -74,7 +73,7 @@ char temps[8][4] ={ }; // Variables for storing days of the week -char days[8][4] ={ +char days[8][4] = { "", "", "", @@ -160,8 +159,6 @@ void loop() else display.partialUpdate(); - - // Go to sleep before checking again esp_sleep_enable_timer_wakeup(1000L * DELAY_MS); (void)esp_light_sleep_start(); diff --git a/src/include/Shapes.cpp b/src/include/Shapes.cpp index 6dd18a9..fb2940c 100644 --- a/src/include/Shapes.cpp +++ b/src/include/Shapes.cpp @@ -5,11 +5,11 @@ #endif #ifndef _swap_int16_t -#define _swap_int16_t(a, b) \ - { \ - int16_t t = a; \ - a = b; \ - b = t; \ +#define _swap_int16_t(a, b) \ + { \ + int16_t t = a; \ + a = b; \ + b = t; \ } #endif @@ -99,23 +99,6 @@ void Shapes::fillElipse(int rx, int ry, int xc, int yc, int c) } } -void Shapes::fillPolygon(int *x, int *y, int n, int color) -{ - int tx[100], ty[100]; - triangulate.triangulate(x, y, n, tx, ty); - - for (int i = 0; i < n - 2; ++i) - { - fillTriangle(tx[i * 3 + 0], ty[i * 3 + 0], tx[i * 3 + 1], ty[i * 3 + 1], tx[i * 3 + 2], ty[i * 3 + 2], color); - } -} - -void Shapes::drawPolygon(int *x, int *y, int n, int color) -{ - for (int i = 0; i < n; ++i) - drawLine(x[i], y[i], x[(i + 1) % n], y[(i + 1) % n], color); -} - void Shapes::drawThickLine(int x1, int y1, int x2, int y2, int color, float thickness) { float deg = atan2f((float)(y2 - y1), (float)(x2 - x1)); diff --git a/src/include/Shapes.h b/src/include/Shapes.h index 22f9110..c921ac0 100644 --- a/src/include/Shapes.h +++ b/src/include/Shapes.h @@ -3,35 +3,58 @@ #include "../libs/Adafruit-GFX-Library/Adafruit_GFX.h" #include "Arduino.h" -#include "Triangulate.h" + +#define maxVer 100 +#define maxHt 600 class Shapes : virtual public Adafruit_GFX { - public: - Shapes(int16_t w, int16_t h) : Adafruit_GFX(w, h){}; +public: + Shapes(int16_t w, int16_t h) : Adafruit_GFX(w, h){}; - virtual void drawPixel(int16_t x, int16_t y, uint16_t color) = 0; + virtual void drawPixel(int16_t x, int16_t y, uint16_t color) = 0; - virtual void selectDisplayMode(uint8_t _mode) = 0; - virtual uint8_t getDisplayMode() = 0; + virtual void selectDisplayMode(uint8_t _mode) = 0; + virtual uint8_t getDisplayMode() = 0; - void drawElipse(int rx, int ry, int xc, int yc, int c); - void fillElipse(int rx, int ry, int xc, int yc, int c); - void drawPolygon(int *x, int *y, int n, int color); - void fillPolygon(int *x, int *y, int n, int color); - void drawThickLine(int x1, int y1, int x2, int y2, int color, float thickness); - void drawGradientLine(int x1, int y1, int x2, int y2, int color1, int color2, float thickness = -1); + void drawElipse(int rx, int ry, int xc, int yc, int c); + void fillElipse(int rx, int ry, int xc, int yc, int c); + void drawPolygon(int *x, int *y, int n, int color); + void fillPolygon(int *x, int *y, int n, int color); + void drawThickLine(int x1, int y1, int x2, int y2, int color, float thickness); + void drawGradientLine(int x1, int y1, int x2, int y2, int color1, int color2, float thickness = -1); - private: - Triangulate triangulate; +private: + struct EdgeBucket + { + int ymax; + float xofymin; + float slopeinverse; + }; - virtual void startWrite(void) = 0; - virtual void writePixel(int16_t x, int16_t y, uint16_t color) = 0; - virtual void writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) = 0; - virtual void writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) = 0; - virtual void writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) = 0; - virtual void writeLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color) = 0; - virtual void endWrite(void) = 0; + struct edgeTableTuple + { + int countEdgeBucket; + EdgeBucket buckets[maxVer]; + }; + + void initedgeTable(); + void insertionSort(edgeTableTuple *ett); + void storeEdgeInTuple(edgeTableTuple *receiver, int ym, int xm, float slopInv); + void storeEdgeInTable(int x1, int y1, int x2, int y2); + void removeEdgeByYmax(edgeTableTuple *tup, int yy); + void updatexbyslopeinv(edgeTableTuple *tup); + void scanlineFill(uint8_t c); + + virtual void startWrite(void) = 0; + virtual void writePixel(int16_t x, int16_t y, uint16_t color) = 0; + virtual void writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) = 0; + virtual void writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) = 0; + virtual void writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) = 0; + virtual void writeLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color) = 0; + virtual void endWrite(void) = 0; + + edgeTableTuple *edgeTable, activeEdgeTuple; }; #endif \ No newline at end of file diff --git a/src/include/ShapesPolygon.cpp b/src/include/ShapesPolygon.cpp new file mode 100644 index 0000000..9226ccc --- /dev/null +++ b/src/include/ShapesPolygon.cpp @@ -0,0 +1,231 @@ +#include "Shapes.h" + +void Shapes::initedgeTable() +{ + int i; + for (i = 0; i < maxHt; i++) + edgeTable[i].countEdgeBucket = 0; + activeEdgeTuple.countEdgeBucket = 0; +} + +void Shapes::insertionSort(edgeTableTuple *ett) +{ + int i, j; + EdgeBucket temp; + + for (i = 1; i < ett->countEdgeBucket; i++) + { + temp.ymax = ett->buckets[i].ymax; + temp.xofymin = ett->buckets[i].xofymin; + temp.slopeinverse = ett->buckets[i].slopeinverse; + j = i - 1; + + while ((temp.xofymin < ett->buckets[j].xofymin) && (j >= 0)) + { + ett->buckets[j + 1].ymax = ett->buckets[j].ymax; + ett->buckets[j + 1].xofymin = ett->buckets[j].xofymin; + ett->buckets[j + 1].slopeinverse = ett->buckets[j].slopeinverse; + j = j - 1; + } + ett->buckets[j + 1].ymax = temp.ymax; + ett->buckets[j + 1].xofymin = temp.xofymin; + ett->buckets[j + 1].slopeinverse = temp.slopeinverse; + } +} + +void Shapes::storeEdgeInTuple(edgeTableTuple *receiver, int ym, int xm, float slopInv) +{ + (receiver->buckets[(receiver)->countEdgeBucket]).ymax = ym; + (receiver->buckets[(receiver)->countEdgeBucket]).xofymin = (float)xm; + (receiver->buckets[(receiver)->countEdgeBucket]).slopeinverse = slopInv; + + insertionSort(receiver); + + (receiver->countEdgeBucket)++; +} + +void Shapes::storeEdgeInTable(int x1, int y1, int x2, int y2) +{ + float m, minv; + int ymaxTS, xwithyminTS, scanline; //ts stands for to store + + if (x2 == x1) + { + minv = 0.000000; + } + else + { + m = ((float)(y2 - y1)) / ((float)(x2 - x1)); + + if (y2 == y1) + return; + + minv = (float)1.0 / m; + } + + if (y1 > y2) + { + scanline = y2; + ymaxTS = y1; + xwithyminTS = x2; + } + else + { + scanline = y1; + ymaxTS = y2; + xwithyminTS = x1; + } + storeEdgeInTuple(&edgeTable[scanline], ymaxTS, xwithyminTS, minv); +} + +void Shapes::removeEdgeByYmax(edgeTableTuple *tup, int yy) +{ + int i, j; + for (i = 0; i < tup->countEdgeBucket; i++) + { + if (tup->buckets[i].ymax == yy) + { + for (j = i; j < tup->countEdgeBucket - 1; j++) + { + tup->buckets[j].ymax = tup->buckets[j + 1].ymax; + tup->buckets[j].xofymin = tup->buckets[j + 1].xofymin; + tup->buckets[j].slopeinverse = tup->buckets[j + 1].slopeinverse; + } + tup->countEdgeBucket--; + i--; + } + } +} + +void Shapes::updatexbyslopeinv(edgeTableTuple *tup) +{ + int i; + + for (i = 0; i < tup->countEdgeBucket; i++) + { + (tup->buckets[i]).xofymin = (tup->buckets[i]).xofymin + (tup->buckets[i]).slopeinverse; + } +} + +void Shapes::scanlineFill(uint8_t c) +{ + int i, j, x1, ymax1, x2, ymax2, FillFlag = 0, coordCount; + + for (i = 0; i < maxHt; i++) + { + for (j = 0; j < edgeTable[i].countEdgeBucket; j++) + storeEdgeInTuple(&activeEdgeTuple, edgeTable[i].buckets[j].ymax, edgeTable[i].buckets[j].xofymin, + edgeTable[i].buckets[j].slopeinverse); + + removeEdgeByYmax(&activeEdgeTuple, i); + insertionSort(&activeEdgeTuple); + + j = 0; + FillFlag = 0; + coordCount = 0; + x1 = 0; + x2 = 0; + ymax1 = 0; + ymax2 = 0; + while (j < activeEdgeTuple.countEdgeBucket) + { + if (coordCount % 2 == 0) + { + x1 = (int)(activeEdgeTuple.buckets[j].xofymin); + ymax1 = activeEdgeTuple.buckets[j].ymax; + if (x1 == x2) + { + if (((x1 == ymax1) && (x2 != ymax2)) || ((x1 != ymax1) && (x2 == ymax2))) + { + x2 = x1; + ymax2 = ymax1; + } + + else + { + coordCount++; + } + } + else + { + coordCount++; + } + } + else + { + x2 = (int)activeEdgeTuple.buckets[j].xofymin; + ymax2 = activeEdgeTuple.buckets[j].ymax; + + FillFlag = 0; + if (x1 == x2) + { + if (((x1 == ymax1) && (x2 != ymax2)) || ((x1 != ymax1) && (x2 == ymax2))) + { + x1 = x2; + ymax1 = ymax2; + } + else + { + coordCount++; + FillFlag = 1; + } + } + else + { + coordCount++; + FillFlag = 1; + } + + if (FillFlag) + { + Serial.println(x1); + Serial.println(x2); + Serial.println(); + drawLine(x1, i, x2, i, c); + } + } + + j++; + } + updatexbyslopeinv(&activeEdgeTuple); + } +} + +void Shapes::drawPolygon(int *x, int *y, int n, int color) +{ + for (int i = 0; i < n; ++i) + drawLine(x[i], y[i], x[(i + 1) % n], y[(i + 1) % n], color); +} + +void Shapes::fillPolygon(int *x, int *y, int n, int color) +{ + edgeTable = (edgeTableTuple *)ps_malloc(maxHt * sizeof(edgeTableTuple)); + initedgeTable(); + + int count = 0, x1, y1, x2, y2; + + for (int i = 0; i < n + 1; ++i) + { + count++; + if (count > 2) + { + x1 = x2; + y1 = y2; + count = 2; + } + if (count == 1) + { + x1 = x[i % n]; + y1 = y[i % n]; + } + else + { + x2 = x[i % n]; + y2 = y[i % n]; + drawLine(x1, y1, x2, y2, color); + storeEdgeInTable(x1, y1, x2, y2); + } + } + scanlineFill(color); + free(edgeTable); +} \ No newline at end of file diff --git a/src/include/Triangulate.cpp b/src/include/Triangulate.cpp deleted file mode 100644 index 46b3099..0000000 --- a/src/include/Triangulate.cpp +++ /dev/null @@ -1,143 +0,0 @@ -#include "Triangulate.h" -#include "Arduino.h" -#include "math.h" - -float Triangulate::area(int x1, int y1, int x2, int y2, int x3, int y3) -{ - return fabs((float)((x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2))) / 2.0); -} - -bool Triangulate::isInside(int x1, int y1, int x2, int y2, int x3, int y3, int x, int y) -{ - float A = area(x1, y1, x2, y2, x3, y3); - float A1 = area(x, y, x2, y2, x3, y3); - float A2 = area(x1, y1, x, y, x3, y3); - float A3 = area(x1, y1, x2, y2, x, y); - return fabs(-A + A1 + A2 + A3) < 1e-3; -} - -void Triangulate::preProcess(int *x, int *y, int n) -{ - for (int i = 0; i < n; ++i) - { - int prev = (i - 1 + n) % n; - int next = (i + 1 + n) % n; - float deg = atan2(y[prev] - y[i], x[prev] - x[i]) - atan2(y[next] - y[i], x[next] - x[i]); - if (deg < 0.0) - deg += 2 * M_PI; - innerAngle[i] = deg; - } -} - -void Triangulate::updateVertex(int p, int *x, int *y, int n) -{ - int prev = (p - 1 + n) % n; - int next = (p + 1 + n) % n; - float deg = atan2(y[prev] - y[p], x[prev] - x[p]) - atan2(y[next] - y[p], x[next] - x[p]); - if (deg < 0.0) - deg += 2 * M_PI; - innerAngle[p] = deg; - bool f = 0; - for (int j = 0; j < n; ++j) - { - if (prev != j && p != j && next != j && innerAngle[p] > M_PI && - isInside(x[prev], y[prev], x[p], y[p], x[next], y[next], x[j], y[j])) - f = 1; - } - earTip[p] = !f; -} - -bool Triangulate::isConvex(int *x, int *y, int n) -{ - for (int i = 0; i < n; ++i) - if (innerAngle[i] > M_PI) - return 0; - return 1; -} - -void Triangulate::trivialTriangles(int *x, int *y, int n) -{ - for (int i = 0; i < n - 2; ++i) - { - tx[tc] = x[0]; - ty[tc] = y[0]; - ++tc; - tx[tc] = x[i + 1]; - ty[tc] = y[i + 1]; - ++tc; - tx[tc] = x[i + 2]; - ty[tc] = y[i + 2]; - ++tc; - } -} - -void Triangulate::findEars(int *x, int *y, int n) -{ - for (int i = 0; i < n; ++i) - { - if (innerAngle[i] > M_PI) - continue; - int prev = (i - 1 + n) % n; - int next = (i + 1 + n) % n; - bool f = 0; - for (int j = 0; j < n; ++j) - { - if (prev != j && i != j && next != j && innerAngle[i] > M_PI && - isInside(x[prev], y[prev], x[i], y[i], x[next], y[next], x[j], y[j])) - f = 1; - } - earTip[i] = !f; - } -} - -int Triangulate::smallestEar(int *x, int *y, int n) -{ - int mn = 0; - for (int i = 1; i < n; ++i) - if (earTip[i] && innerAngle[i] < innerAngle[mn]) - mn = i; - return mn; -} - -void Triangulate::nonTrivialTriangles(int *x, int *y, int n) -{ - findEars(x, y, n); - int initialN = n; - while (tc / 3 < initialN - 2) - { - int pos = smallestEar(x, y, n); - int prev = (pos - 1 + n) % n; - int next = (pos + 1 + n) % n; - tx[tc] = x[prev]; - ty[tc] = y[prev]; - ++tc; - tx[tc] = x[pos]; - ty[tc] = y[pos]; - ++tc; - tx[tc] = x[next]; - ty[tc] = y[next]; - ++tc; - for (int i = pos; i < n - 1; i++) - { - x[i] = x[i + 1]; - y[i] = y[i + 1]; - innerAngle[i] = innerAngle[i + 1]; - earTip[i] = earTip[i + 1]; - } - --n; - updateVertex(prev, x, y, n); - updateVertex(prev + 1, x, y, n); - } -} - -void Triangulate::triangulate(int *x, int *y, int n, int *_tx, int *_ty) -{ - tc = 0; - preProcess(x, y, n); - if (isConvex(x, y, n)) - trivialTriangles(x, y, n); - else - nonTrivialTriangles(x, y, n); - memcpy(_tx, tx, 100); - memcpy(_ty, ty, 100); -} \ No newline at end of file diff --git a/src/include/Triangulate.h b/src/include/Triangulate.h deleted file mode 100644 index 9c927bd..0000000 --- a/src/include/Triangulate.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef TRIANGULATE_H -#define TRIANGULATE_H - -#include "Arduino.h" - -class Triangulate -{ - private: - int tx[100]; - int ty[100]; - int tc = 0; - - float innerAngle[100]; - bool earTip[100]; - - float area(int x1, int y1, int x2, int y2, int x3, int y3); - bool isInside(int x1, int y1, int x2, int y2, int x3, int y3, int x, int y); - void preProcess(int *x, int *y, int n); - void updateVertex(int p, int *x, int *y, int n); - bool isConvex(int *x, int *y, int n); - void trivialTriangles(int *x, int *y, int n); - void findEars(int *x, int *y, int n); - int smallestEar(int *x, int *y, int n); - void nonTrivialTriangles(int *x, int *y, int n); - - public: - void triangulate(int *x, int *y, int n, int *_tx, int *_ty); -}; - -#endif \ No newline at end of file diff --git a/test/drawing1bit/drawing1bit.ino b/test/drawing1bit/drawing1bit.ino new file mode 100644 index 0000000..ca997e5 --- /dev/null +++ b/test/drawing1bit/drawing1bit.ino @@ -0,0 +1 @@ +#include "Inkplate.h" diff --git a/test/drawing3bit/drawing3bit.ino b/test/drawing3bit/drawing3bit.ino new file mode 100644 index 0000000..35a3d58 --- /dev/null +++ b/test/drawing3bit/drawing3bit.ino @@ -0,0 +1 @@ +#include "Inkplate.h" \ No newline at end of file diff --git a/test/test.ino b/test/test.ino index 861cf96..b767407 100644 --- a/test/test.ino +++ b/test/test.ino @@ -1,6 +1,8 @@ #include "Inkplate.h" #include "SdFat.h" +const int n = 10; + Inkplate display(INKPLATE_1BIT); void setup() @@ -11,20 +13,42 @@ void setup() display.joinAP("e-radionica.com", "croduino"); - Serial.println(); + Serial.println("aaaa"); delay(500); } void loop() { display.clearDisplay(); - display.display(); - if (display.sdCardInit()) + // Code block for generating random points and sorting them in a counter + // clockwise direction. + int xt[n]; + int yt[n]; + + for (int i = 0; i < n; ++i) { - Serial.println(display.drawJpegFromSd("Lenna.jpg", 0, 0, 1, 0)); + xt[i] = random(100, 700); + yt[i] = random(100, 500); } - display.display(); + int k; + for (int i = 0; i < n - 1; ++i) + + for (int j = i + 1; j < n; ++j) + if (atan2(yt[j] - 300, xt[j] - 400) < atan2(yt[i] - 300, xt[i] - 400)) + { + k = xt[i], xt[i] = xt[j], xt[j] = k; + k = yt[i], yt[i] = yt[j], yt[j] = k; + } + + display.clearDisplay(); + display.drawPolygon(xt, yt, n, 1); + display.display(); + delay(5000); + + display.clearDisplay(); + display.fillPolygon(xt, yt, n, 1); + display.display(); delay(5000); } \ No newline at end of file