求三次貝塞爾曲線的控制點------點集用分段三次貝塞爾曲線插值生成光滑曲線

void InterpolateBeizers(std::vector<QPointF>& points,
                        bool bClosedCurve,
                        double smoothValue,
                        std::vector<std::vector<QPointF>>& beizers)
{
    int size=points.size();
    if (size<3)
        return;

    //if is close curve then add the first point at the end
    if (bClosedCurve)
        points.push_back(points.at(0));

    for (int i=0;i<size-1;i++)   //iterate for points but the last one
    {
        // Assume we need to calculate the control
        // points between (x1,y1) and (x2,y2).
        // Then x0,y0 - the previous vertex,
        //      x3,y3 - the next one.
        double x1=points[i].x();
        double y1=points[i].y();

        double x2=points[i+1].x();
        double y2=points[i+1].y();

        double x0=0.0;
        double y0=0.0;

        if (i==0) //if is first point
        {
            if (bClosedCurve)
            {
                QPointF& previousPoint=points[size-2];//last Point, but one (due inserted the first at the end)
                x0=previousPoint.x();
                y0=previousPoint.y();
            }
            else    //Get some previouse point
            {
                QPointF& previousPoint=points[i];  //if is the first point the previous one will be it self
                x0=previousPoint.x();
                y0=previousPoint.y();
            }
        }
        else
        {
            x0=points[i-1].x();   //Previous Point
            y0=points[i-1].y();
        }

        double x3=0.0;
        double y3=0.0;

        if (i==size-2)    //if is the last point
        {
            if (bClosedCurve)
            {
                QPointF& nextPoint=points[1];  //second Point(due inserted the first at the end)
                x3=nextPoint.x();
                y3=nextPoint.y();
            }
            else    //Get some next point
            {
                QPointF& nextPoint=points[i+1];  //if is the last point the next point will be the last one
                x3=nextPoint.x();
                y3=nextPoint.y();
            }
        }
        else
        {
            x3=points[i+2].x();   //Next Point
            y3=points[i+2].y();
        }

        double xc1=(x0+x1)*0.5;
        double yc1=(y0+y1)*0.5;
        double xc2=(x1+x2)*0.5;
        double yc2=(y1+y2)*0.5;
        double xc3=(x2+x3)*0.5;
        double yc3=(y2+y3)*0.5;

        double len1=sqrt((x1-x0)*(x1-x0)+(y1-y0)*(y1-y0));
        double len2=sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
        double len3=sqrt((x3-x2)*(x3-x2)+(y3-y2)*(y3-y2));

        double k1=len1/(len1+len2);
        double k2=len2/(len2+len3);

        double xm1=xc1+(xc2-xc1)*k1;
        double ym1=yc1+(yc2-yc1)*k1;
        double xm2=xc2+(xc3-xc2)*k2;
        double ym2=yc2+(yc3-yc2)*k2;
        // Resulting control points. Here smooth_value is mentioned
        // above coefficient K whose value should be in range [0...1].
        double ctrl1_x=xm1+(xc2-xm1)*smoothValue+x1-xm1;
        double ctrl1_y=ym1+(yc2-ym1)*smoothValue+y1-ym1;
        double ctrl2_x=xm2+(xc2-xm2)*smoothValue+x2-xm2;
        double ctrl2_y=ym2+(yc2-ym2)*smoothValue+y2-ym2;

        std::vector<QPointF> beizer;
        QPointF startPoint(x1,y1);
        QPointF endPoint(x2,y2);
        QPointF firstControlPoint=(i==0&&!bClosedCurve?QPointF(x1,y1):QPointF(ctrl1_x,ctrl1_y));
        QPointF secondControlPoint=(i==points.size()-2&&!bClosedCurve?QPointF(x2,y2):QPointF(ctrl2_x,ctrl2_y));
        beizer.push_back(startPoint);
        beizer.push_back(endPoint);
        beizer.push_back(firstControlPoint);
        beizer.push_back(secondControlPoint);

        beizers.push_back(beizer);
    }
}
相關文章
相關標籤/搜索