前几天看到一道FaceBook的面试题,本来只是想用C语言实现下算法,后来闲着无聊便用Qt绘制了一下效果. FaceBook原题如下:

FaceBook算法


我用Qt的实现粗略效果,如下

圆形进度条

算法思路: 用百分比*360度求出旋转偏移角度α,将判断点与圆心连线,用余弦定理求该点偏移β角度,和α比较。如果α>β,说明黑色的范围可以包含此点 . 如果不允许使用反三角函数库,用幂指多項式[ 用泰勒公式展开cos x = 1-x^2/2!+x^4/4!+~+(-1)^kx^2k/(2k)!+¤(x(2k+1) ]来判断角度大小即可。


/*----------------MyWidget.h---------------------------*/

#ifndef MYWIDGET_H
#define MYWIDGET_H

#include <QWidget>
#include <QTimer>
class MyWidget : public QWidget
{
    Q_OBJECT
public:
    int x;int y;
    explicit MyWidget(QWidget *parent = 0);

    void paintEvent(QPaintEvent *);
    static int count;
    bool check;

signals:

private slots:
    void on_time();
private:
    QTimer *timer;

    QVector<QPoint>  pos;

};

#endif // MYWIDGET_H
/*----------------MyWidget.h---------------------------*/
/*----------------MyWidget.cpp---------------------------*/

#include "MyWidget.h"
#include <QPainter>
#include <QPixmap>
#include <math.h> //后便要用到acos函数和pow函数
MyWidget::MyWidget(QWidget *parent) :
    QWidget(parent)
{
    check = true;
    timer = new QTimer();
    timer->setInterval(70);

    connect(timer, SIGNAL(timeout()), this, SLOT(on_time()));
}

int MyWidget::count = -1;

void MyWidget::paintEvent(QPaintEvent *)
{

    QPixmap *pixmap;//定义图片
    QPainter *painter;//定义画图设备
    pixmap = new QPixmap (this->size());
    pixmap->fill(Qt::white);
    painter = new QPainter(pixmap);//加载空图片
    painter->setRenderHint(QPainter::Antialiasing);
    painter->setPen(QPen(Qt::black, 2, Qt::DashLine));
    painter->drawEllipse(QPoint(150, 150), 100, 100);//画圆
    painter->drawPoint(150,150);//描点
    painter->setFont(QFont("宋体", 15, 20, true));

    if(check == true)
    {
        painter->end();
        painter->begin(this);
        painter->drawPixmap(0, 0, *pixmap);
        timer->start();
        check = false;
    }else
    {

        painter->drawText(23, 23, "进度:"+QString::number(count*2)+"%");
        //百分比计数,因为是从两边展开,所以乘了2;
        QVector<QPoint>::iterator it = pos.begin();
        for( ;it != pos.end(); ++it)
        {

            painter->drawPoint(*it);

        }
        painter->end();
        painter->begin(this);
        painter->drawPixmap(0, 0, *pixmap);
        pos.clear();
    }
}

void MyWidget::on_time()
{

    if(count > 49)
        timer->stop();
    else
    {
        count++;
        for(int x = 0; x < 300; ++x )
        {
            for(int y = 0; y < 300; ++y )
            {
                double a = 0.0,b = 0.0,c = 0.0,d = 0.0,tmpd = 0.0;
                double per = count

                per = per*0.01;
                d = pow((x-150.0),2) + pow((y-150.0),2);//求得点(x,y)到圆心距离d^2
                tmpd = pow(d,0.5);//d^2开方求得tmpd
                c = pow((150.0-x),2) + pow((150+tmpd-y),2);//求得斜边c

                b = acos((1.0 - 0.5*(c/d)));//余弦定理求得该点偏移角度b
                a = (2*3.141593)*per;//

                if ( tmpd >= 0 && tmpd<= 100)
                {
                    if(a >= b)
                    {
                        pos.append(QPoint(x,y));
                    }

                }
                this->update();//调用paintEvent重新绘制

            }
        }

    }

}

/*----------------MyWidget.cpp---------------------------*/
/*----------------main.cpp---------------------------*/

#include <QApplication>
#include "MyWidget.h"
int main(int argc, char** argv)
{
    QApplication app(argc, argv);

    MyWidget w;
    QSize Size(300,300);
    w.setFixedSize(Size);
    w.show();

    return app.exec();
}
/*----------------main.cpp---------------------------*/


备份地址: 【FaceBook面试题: QPainter重绘实现圆形进度条