aboutsummaryrefslogtreecommitdiff
path: root/tools/CurveEditor/source/Internal/Curve/BezierSpline.cpp
blob: 03ab848a94dcf1b43ed97a56d73cb4d40dcac9e7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include "BezierSpline.h"

namespace nvidia {
namespace CurveEditor {

std::vector<QPointF> BezierSpline::sample(const std::vector<BezierSplinePoint>& splinePoints, long segmentCount)
{
    std::vector<QPointF> samplePoints;

    if (segmentCount < 1)
        return samplePoints;

    long  lPointCount = (long)splinePoints.size();
    float fLengthStep = 1.0 / segmentCount;
    float ft;
    QPointF p0;
    QPointF p1;
    QPointF p2;
    QPointF p3;
    QPointF p01;
    QPointF p11;
    QPointF p21;
    QPointF p02;
    QPointF p12;
    QPointF p03;

    for (int i = 1; i < lPointCount; i++)
    {
        const BezierSplinePoint& pt1 = splinePoints[i - 1];
        const BezierSplinePoint& pt2 = splinePoints[i];

        // start point of each Bezier curve segment
        samplePoints.push_back(pt1.valuePoint);

        // sample each point on each Bezier curve segment by percent value and De Casteljau algorithm
        // the sample points are not including start point and end poit of the Bezier curve segement
        for (int j = 1; j < segmentCount; j++)
        {
            ft = fLengthStep * j;

            p0 = pt1.valuePoint;
            p1 = pt1.ctrlPoint1;
            p2 = pt2.ctrlPoint0;
            p3 = pt2.valuePoint;

            p01 = p0 + (p1 - p0) * ft;
            p11 = p1 + (p2 - p1) * ft;
            p21 = p2 + (p3 - p2) * ft;

            p02 = p01 + (p11 - p01) * ft;\
            p12 = p11 + (p21 - p11) * ft;
            p03 = p02 + (p12 - p02) * ft;

            samplePoints.push_back(p03);
        }

        if (i == lPointCount - 1)
        {// end point of last Bezier curve segment
            samplePoints.push_back(pt2.valuePoint);
        }
    }
    return samplePoints;
}

BezierSpline::BezierSpline(long segmentCount)
    : Spline(segmentCount)
    , _controlPoints()
{
}

bool BezierSpline::getControlPoint(int index, BezierSplinePoint &pt)
{
    long lPointCount = (long)_controlPoints.size();

    if (lPointCount == 0)
    {
        return false;
    }

    index = index < 0 ? 0 : (index >= lPointCount ? lPointCount - 1: index);

    pt = _controlPoints[index];

    return true;
}

void BezierSpline::appendControlPoint(BezierSplinePoint pt)
{
    _controlPoints.push_back(pt);

    _needSample = true;
}

void BezierSpline::insertControlPoint(int index, BezierSplinePoint pt)
{
    long lPointCount = (long)_controlPoints.size();

    index = index < 0 ? 0 : (index >= lPointCount ? lPointCount: index);

    _controlPoints.insert(_controlPoints.begin() + index, pt);

    _needSample = true;
}

bool BezierSpline::setControlPoint(int index, BezierSplinePoint pt)
{
    long lPointCount = (long)_controlPoints.size();

    if (0 <= index && index < lPointCount)
    {
        _controlPoints[index] = pt;
        _needSample = true;
        return true;
    }
    else
    {
        return false;
    }
}

bool BezierSpline::removeControlPoint(int index)
{
    long lPointCount = (long)_controlPoints.size();

    if (0 <= index && index < lPointCount)
    {
        _controlPoints.erase(_controlPoints.begin() + index);
        _needSample = true;
        return true;
    }
    else
    {
        return false;
    }
}

void BezierSpline::_doSample()
{
    _samplePoints = sample(_controlPoints, _segmentCount);
}

} // namespace CurveEditor
} // namespace nvidia