Kiryu144
Kiryu144

Reputation: 89

Calculating a exact spline with 3 given Points in 2D. C++

I have a std::vector with 3 points (2D) with values x >= 0 and x <= 512. With these 3 points I have to calculate a draw that passes all of these 3 points. Here you see the 3 Points and the corresponding circle. I need a function to interpolate the points based on a variable which defines the accuracy (eg the number of points inbetween). If its not clear: I work in C++.

Upvotes: 1

Views: 737

Answers (1)

Yevgeniy Logachev
Yevgeniy Logachev

Reputation: 761

To solve your issue you need to calculate center of triangle's circumscribed circle and it radius. Then find min X and max X from triangle coordinates then calculate delta between maxX - minX and divide delta to numbers of input points. Then in loop you iterates from minX to maxX and calculate coordinates by using circle formula R^2 = (x - centerX)^2 + (y - centerY)^2. Below a small example

#include <iostream>
#include <vector>
#include <math.h>

template <typename T>
class CPoint2D
{
public:
    CPoint2D(T _x, T _y)
    : x(_x)
    , y(_y)
    {}

    ~CPoint2D()
    {}

    const T& X() const { return x; }
    const T& Y() const { return y; }

private:
    T x;
    T y;
};

typedef CPoint2D<float> CPoint2Df;

bool GetCenterCircumscribedCircle(float x0, float y0,
                                  float x1, float y1,
                                  float x2, float y2,
                                  float& centerX, float& centerY, float& radius)
{
    if ((x0 == x1 && x1 == x2) ||
        (y0 == y1 && y1 == y2))
    {
        return false;
    }

    float D = 2.0f * (y0 * x2 + y1 * x0 - y1 * x2 - y0 * x1 - y2 * x0 + y2 * x1);
    centerX = (  y1 * x0 * x0
               - y2 * x0 * x0
               - y1 * y1 * y0
               + y2 * y2 * y0
               + x1 * x1 * y2
               + y0 * y0 * y1
               + x2 * x2 * y0
               - y2 * y2 * y1
               - x2 * x2 * y1
               - x1 * x1 * y0
               + y1 * y1 * y2
               - y0 * y0 * y2) / D;
    centerY = (  x0 * x0 * x2
               + y0 * y0 * x2
               + x1 * x1 * x0
               - x1 * x1 * x2
               + y1 * y1 * x0
               - y1 * y1 * x2
               - x0 * x0 * x1
               - y0 * y0 * x1
               - x2 * x2 * x0
               + x2 * x2 * x1
               - y2 * y2 * x0
               + y2 * y2 * x1) / D;

    radius = sqrt((x0 - centerX) * (x0 - centerX) + (y0 - centerY) * (y0 - centerY));

    return true;
}

void CalculatePointsOnCirle(const std::vector<CPoint2Df>& triVertexes, std::vector<CPoint2Df>& outPoints, float stride)
{
    if (triVertexes.size() != 3)
    {
        return;
    }

    const CPoint2Df& v1 = triVertexes[0];
    const CPoint2Df& v2 = triVertexes[1];
    const CPoint2Df& v3 = triVertexes[2];

    float minX = std::min(v1.X(), v2.X());
    minX = std::min(minX, v3.X());

    float maxX = std::max(v1.X(), v2.X());
    maxX = std::max(maxX, v3.X());

    float deltaX = (maxX - minX) / stride;

    float centerX;
    float centerY;
    float radius;
    if (GetCenterCircumscribedCircle(v1.X(), v1.Y(),
                                     v2.X(), v2.Y(),
                                     v3.X(), v3.Y(),
                                     centerX, centerY, radius))
    {
        for (float x = minX; x < maxX; x += deltaX)
        {
            float y = sqrt(radius * radius - (x - centerX) * (x - centerX));

            outPoints.push_back(CPoint2Df(x, y));
        }
    }
}

int main(int argc, const char * argv[])
{
    std::vector<CPoint2Df> triVertex = {CPoint2Df(0.0f, 0.0f),
                                        CPoint2Df(256.0f, 256.0f),
                                        CPoint2Df(512.0f, 0.0f)};

    std::vector<CPoint2Df> outPoints;

    CalculatePointsOnCirle(triVertex, outPoints, 4);

    for (unsigned int i = 0; i < outPoints.size(); ++i)
    {
        printf("p[%d]: (%f, %f)\n", i, outPoints[i].X(), outPoints[i].Y());
    }

    return 0;
}

Upvotes: 1

Related Questions