Demo touching the perimeter of a circle

Dependencies:   RA8875

Revision:
0:f2a6447e607c
Child:
1:e4f92c21e329
diff -r 000000000000 -r f2a6447e607c main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Apr 04 16:50:35 2021 +0000
@@ -0,0 +1,156 @@
+///
+/// RA8875 display library example where a user touch on the perimeter
+/// of a circle should be detected.
+///
+///
+///                           0 deg
+///                          -+-
+///                    -             -
+///        
+///              /                         \
+///        
+///        
+///            |                             |
+/// -90 deg    +              +              + +90 deg
+///            |                             |
+///         
+///         
+///              \                         /
+///         
+///                   
+///                    -             -
+///                          -+-
+///                        +180 deg
+///
+///
+/// NOTE NOTE NOTE NOTE NOTE NOTE
+///
+/// The code in this example would greatly benefit by refactoring to 
+/// use radians, rather than degrees. Further, the coordinate system
+/// desired here is more like a clock-face, with 0 degrees is straight 
+/// up and increasing angle in the clockwise direction.
+///
+/// There are a few transformations (direction of rotation and angle
+/// offset) that didn't "feel right", even with the right result.
+///
+#include "mbed.h"
+#include "RA8875.h"
+
+/// Display with Capacitive Touch panel on I2C
+RA8875 lcd(p5,p6,p7,p12,NC, p9,p10,p13, "tft"); // MOSI,MISO,SCK,/ChipSelect,/reset, SDA,SCL,/IRQ, name
+//RA8875 lcd(p5,p6,p7,p8,NC, p28,p27,p30, "tft");
+
+
+Serial device(USBTX,USBRX);    // Not required for display
+
+// Screen size and color depth
+#define LCD_W 800
+#define LCD_H 480
+#define LCD_C 8         // color - bits per pixel
+
+#define BL_NORM 100      // Backlight Normal setting (0 to 255)
+
+// The Circle definition around which touches are relevant
+const point_t center = {200,250};
+const dim_t radius = 125;
+const dim_t touch_tolerance = 30;
+
+#define PI 3.14159265359f
+
+//              ---------------
+// radius = \  / x ^ 2 + y ^ 2
+//           \/
+int GetRadius(point_t touch, point_t center)
+{
+    return sqrt(pow(touch.x - center.x, 2) + pow(touch.y - center.y, 2));
+}
+
+//           (radians * 180)
+// degrees = ---------------
+//               pi
+float Degrees(float radians)
+{
+    return radians * 180 / PI;
+}
+
+//           (pi * degrees)
+// radians = --------------
+//                180
+float Radians(float degrees)
+{
+    return (degrees * PI)/180;
+}
+
+int GetAngle(point_t touch, point_t center)
+{
+    int angle = 180 - Degrees(atan2(touch.x - center.x, touch.y - center.y));
+    if (angle < 0)
+        angle += 360;
+    return angle;
+}
+
+// From a starting point, and at a given angle (where 0 is straight up),
+// and clockwise is increasing angle,
+// project a given distance at that angle and return those coordinates.
+//
+point_t ProjectPoint(point_t start, int angle, dim_t distance)
+{
+    point_t newPoint;
+    float radians = Radians(angle);     // radians are rooted in 0 to the right, and increasing counterclockwise
+    radians = -radians + Radians(90);   // reverse direction and 0 at the top
+    //device.printf("adj Radians %4.3f\r\n", radians);
+    newPoint.x = start.x + distance * sin(radians);
+    newPoint.y = start.y - distance * cos(radians);
+    return newPoint;
+}
+
+
+int main()
+{
+    device.baud(460800);
+    device.printf("\r\n   RA8875 Touch Dial Example - Build " __DATE__ " " __TIME__ "\r\n");
+
+    lcd.init(LCD_W,LCD_H,LCD_C,BL_NORM);
+    lcd.TouchPanelInit();
+
+    lcd.foreground(White);          // Change to white
+    lcd.printf("RA8875 Touch Dial Example - Build " __DATE__ " " __TIME__ "\r\n");
+    lcd.printf("MBED v%d.%d.%d\r\n", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION);
+
+    // Draw a thick circle
+    for (int r = -3; r <= 3; r++) {
+        lcd.ellipse(center.x, center.y, radius + r, radius + r, BrightBlue);
+    }
+    
+    while (1) {
+        TouchCode_t touched;
+
+        touched = lcd.TouchPanelReadable();
+        if (touched) {
+            point_t Touch = lcd.TouchCoordinates();
+
+            // If the touch is near the drawn circle (+/- 30 pixels),
+            // compute the angle to the touch from the center of the circle
+            if (abs(GetRadius(Touch, center) - radius) <= touch_tolerance) {
+                int angle = GetAngle(Touch, center);
+                device.printf("Touch at (%4d,%4d) is %3d degrees from (%4d,%4d)\r\n", 
+                    Touch.x, Touch.y, angle, center.x, center.y);
+                
+                // Fill the circle using 6° pie slices up to the angle of the touch
+                point_t lastP = ProjectPoint(center, 90, radius);  // seed it at angle 0
+                for (int a=6; a<=360; a+=6) {
+                    point_t p = ProjectPoint(center, 90 - a, radius);
+                    color_t fillColor = (a <= angle) ? Blue : Black;
+                    if ((a <= angle)) {     // show the triangle coordinates (only the fill)
+                        device.printf("    (%3d,%3d), (%3d,%3d), (%3d,%3d)\r\n",
+                            lastP.x,lastP.y, p.x,p.y, center.x,center.y);
+                    }
+                    lcd.filltriangle(center, p, lastP, fillColor);
+                    lastP = p;
+                }
+                // Show the touch point (note we're not erasing the old one)
+                lcd.fillellipse(Touch.x, Touch.y, 5, 5, BrightRed);
+            }
+        }
+    }
+}
\ No newline at end of file