Reputation: 23
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
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);
}
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
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:
red is original
Upvotes: 0