Interpolating function for two points on TFT-Screen

Hello,

Currently I am trying to write an interpolating function, which connects individual dots I draw on my TFT ILI9341 Touch Screen. For some reason though, it behaves in a really buggy way.. It connects points at different parts, not where I draw and it behaves in a random way. It also stops working when I approach the maximum X value. Could anyone help me correcting my linearInterpolation function? I would be happy about any help! thank you. :slight_smile:

My Display.cpp:

#include "Display.h"

// XPT2046_Touchscreen ts(CS_PIN); // Instanziierung eines ts Objekts der Klasse XPT2046_Touchscreen
// ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC);
#define TIRQ_PIN 2
#define CS_PIN 8
#define TFT_DC 9
#define TFT_CS 10

Display::Display() : ts(CS_PIN), tft(TFT_CS, TFT_DC)
{
}

// Original raw minimum and maximum values:
// X --> 340 bis 3900
// Y --> 200 bis 3850

boolean Display::isTouched()
{
    return touched = ts.touched();
}

int Display::getX()
{
    if (touched)
    {
        TS_Point p = ts.getPoint(); // point getter function
        {
            if (map(p.x, 340, 3900, 320, 0) <= 320)
            {
                return map(p.x, 340, 3900, 320, 0);
            }
            else if (map(p.x, 340, 3900, 320, 0) > 320)
            {
                return maximumX;
            }
            else if (map(p.x, 340, 3900, 320, 0) < 0)
            {
                return minimumX;
            }
            else
            {
                {
                    //   return _beyondDisplay;
                }
            }
        }
    }
}

int Display::getY()
{
    if (touched)
    {
        TS_Point p = ts.getPoint(); // point getter function
        {
            if (map(p.y, 200, 3850, 240, 0) <= 240)
            {
                return map(p.y, 200, 3850, 240, 0);
            }
            else if (map(p.y, 200, 3850, 240, 0) > 240)
            {
                return maximumY;
            }
            else if (map(p.y, 200, 3850, 240, 0) < 0)
            {
                return minimumY;
            }
            else
            {
                //      return _beyondDisplay;
            }
        }
    }
}

void Display::drawButtons()
{
    for (int i{0}; i < 4; ++i)
    {
        tft.fillRoundRect(_gap + (_gap + _widthSquare) * i, 220, _widthSquare, _heightSquare, _radiusOfRoundCorner, CL(250, 0, 0));
        tft.setCursor(26 + ((_gap + _widthSquare) * i), 227);
        tft.print(buttonNames[i]);
    }
    tft.drawLine(0, 120, 320, 120, CL(255, 255, 255));
    tft.drawLine(0, 121, 320, 121, CL(255, 255, 255));
    tft.drawLine(0, 119, 320, 119, CL(255, 255, 255));
}

void Display::clear()
{
    tft.fillScreen(ILI9341_BLACK);
    drawButtons();
}

void Display::start()
{
    Serial.begin(38600);
    tft.begin();
    tft.setRotation(1);
    tft.fillScreen(ILI9341_BLACK);
    ts.begin();
    ts.setRotation(1);
    while (!Serial && (millis() <= 1000))
        ; // weiß nicht was das ist
}

boolean Display::pointInRect(int x, float y, float rectX, float rectY, float rectW, float rectH)
{
    boolean ret = false;
    if ((x >= rectX) && (x <= (rectX + rectW)) && (y >= rectY) && (y <= (rectY + rectH)))
    {
        ret = true;
    }
    return ret;
}

void Display::touchButton()
{
    if (pointInRect(_x, _y, _gap, (240 - _heightSquare), (_widthSquare), (_heightSquare)))
    {
        tft.fillRoundRect(_gap, (240 - _heightSquare), _widthSquare, _heightSquare, _radiusOfRoundCorner, CL(250, 100, 0));
        clear();
        // clearArray();
    }
}

void Display::draw(int x, int y)
{
    wave1Values[map(x, 0, 320, 0, 256)] = map(y, 0, 240, -32767, 32767);

    for (int i{0}; i < 257; ++i)
    {
        tft.fillCircle(map(i, 0, 256, 0, 320), map(wave1Values[i], -32767, 32767, 0, 240), pointRadius, CL(255, 0, 0));
    }
}


void Display::linearInterpolation()
{
    Serial.println(getX());
     for (int i = X_old; i < getX();)
    {
        if (X_old <= getX())
        {
            i++;
        }
        else
        {
            i--;
        }
        wave1Values[i] = map(i, X_old, getX(), wave1Values[map(X_old, 0, 320, 0, 256)], wave1Values[map(getX(), 0, 320, 0, 256)]);
    }  
    X_old = getX();
}

Relevant loop part of my main code:

void loop ()
{
  if (display.isTouched())
  {
    Serial.println(display.getX());
    if (previousIsTouched)
    {
      display.linearInterpolation();
    }
    display.touchButton();
    display.clear();
    display.draw(display.getX(), display.getY());
  }
  previousIsTouched = display.isTouched();

  sequencer.stepButtons();
  sequencer.stepLED();
}

connects individual dots I draw on my TFT

Do you mean draw a line between them? If so, why not just call the line draw function?

There are literally thousands of examples of line drawing algorithms available online, and nearly all will do interpolation, most using the Bresenham algorithm. Why re-invent the wheel?

Thank you guys, you are both right, I will look up the Bresenham algorithm and also try it with the drawLine function!

For a start this loop assumes you only ever increase X:

     for (int i = X_old; i < getX();)

yet in the loop body you explicitly check for direction:

        if (X_old <= getX())
        {
            i++;
        }
        else
        {
            i--;
        }

so clearly the existing attempt isn't consistent...

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.