Kim BeomSik
Kim BeomSik

Reputation: 23

B-spline Curve in c++

Could anyone help me about B-spline Curve error?

I want to draw B-spline Curve in c++, but even though all coordinates are positive, the segment's coordinate is negative.

This is B-spline Curve code.

void BSplineCurve(Dot &ControlPoint1, Dot &ControlPoint2, 
                  Dot &ControlPoint3,Dot &ControlPoint4, 
                  Dot &DrawCurve, double &t){

    double t2 = t * t;
    double t3 = t2 * t;
    double mt3 = (1 - t) * (1 - t) * (1 - t);

    double bi3 = mt3 / 6;
    double bi2 = ((3 * t3) - (6 * t2) + 4) / 6;
    double bi1 = ((-3 * t3) + (3 * t2) + (3 * t) + 1) / 6;
    double bi  = mt3 / 6;

    DrawCurve.x = ControlPoint1.x * bi3;
    DrawCurve.x += ControlPoint2.x * bi2;
    DrawCurve.x += ControlPoint3.x * bi1;
    DrawCurve.x += ControlPoint4.x * bi;

    DrawCurve.y = ControlPoint1.y * bi3;
    DrawCurve.y += ControlPoint2.y * bi2;
    DrawCurve.y += ControlPoint3.y * bi1;
    DrawCurve.y += ControlPoint4.y * bi;
}

This is Drawing Code.

double t = 3.f;
do{

    if ((3 < t) && (t <= 4)) {
    BSplineCurve(ControlPoint1, ControlPoint2, ControlPoint3, ControlPoint4, DrawCurve, t);
    Draw1Dot(DrawCurve.x, DrawCurve.y, DrawCurve.R, DrawCurve.G, DrawCurve.B);
    }
    else if ((4 < t) && (t <= 5)) {
    BSplineCurve(ControlPoint2, ControlPoint3, ControlPoint4, ControlPoint5, DrawCurve, t);
    Draw1Dot(DrawCurve.x, DrawCurve.y, DrawCurve.R, DrawCurve.G, DrawCurve.B);
    }
    else if ((5 < t) && (t <= 6)) {
    BSplineCurve(ControlPoint3, ControlPoint4, ControlPoint5, ControlPoint6, DrawCurve, t);
    Draw1Dot(DrawCurve.x, DrawCurve.y, DrawCurve.R, DrawCurve.G, DrawCurve.B);
    }
    t += 0.001;
} while(t < 6.001);

This is Control Point's coordinate.

Poiont1 : 50, 50

Poiont2 : 50, 100

Poiont3 : 200, 100

Poiont4 : 200, 50

Poiont5 : 350, 50

Poiont6 : 350, 100

But this is 1st segment's coordinate.

Q3 : -1543, -349

Upvotes: 1

Views: 6591

Answers (2)

AMA
AMA

Reputation: 4214

Your drawing code looks wrong.

In function BSplineCurve the t parameter should take values in [0, 1] range. By changing t from 0 to 1 one will build a cubic B-spline between points ControlPoint2 and ControlPoint3.

You could try something like:

Dot points[6] = {ControlPoint1, ControlPoint2, ControlPoint3, ControlPoint4, ControlPoint5, ControlPoint6};
for(double t = 3.0; t < 6.0; t += 0.001)
{
    const int start = static_cast<int>(t);
    BSplineCurve(points[start - 3], 
                 points[start - 2], 
                 points[start - 1], 
                 points[start], 
                 DrawCurve, 
                 t - start);
    Draw1Dot(DrawCurve.x, DrawCurve.y, DrawCurve.R, DrawCurve.G, DrawCurve.B);
}

Update

Your B-spline calculation code looks wrong too :-)

bi should be t3/6.0 and not mt3/6.0. See here (slide 25).


The fixed function can look something like this (I did not test it):

void BSplineCurve(const Dot &point1, 
                  const Dot &point2, 
                  const Dot &point3,
                  const Dot &point4, 
                  const double t,
                  Dot &result)
{
    const double t2 = t * t;
    const double t3 = t2 * t;
    const double mt = 1.0 - t;
    const double mt3 = mt * mt * mt;

    const double bi3 = mt3;
    const double bi2 = 3 * t3 - 6 * t2 + 4;
    const double bi1 =-3 * t3 + 3 * t2 + 3 * t + 1;
    const double bi  = t3;

    result.x = point1.x * bi3 + 
               point2.x * bi2 +
               point3.x * bi1 +
               point4.x * bi;
    result.x /= 6.0;

    result.y = point1.y * bi3 + 
               point2.y * bi2 +
               point3.y * bi1 +
               point4.y * bi;
    result.y /= 6.0;
}

Upvotes: 2

Alexandr
Alexandr

Reputation: 164

Maybe the point you use is too very close. In spline it is not good iidea to use very close point. becaue so we have very "galloping" curve. Like this:

enter image description here

red is original

Upvotes: 0

Related Questions