Qt实现标准渐开线齿轮绘制

重写QGraphicsItem类,实现了标准渐开线圆柱齿轮的绘制,看代码如下,包含一下文件,在自己的程序中可直接使用

#ifndef GEARITEM_H
#define GEARITEM_H

#include <QObject>
#include<QGraphicsItem>

class GearItem : public QObject,public QGraphicsItem
{
    Q_OBJECT
public:
    explicit GearItem(QGraphicsItem *parent = nullptr);
protected:
    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
                    QWidget *widget);
    QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value);
signals:
    void sg_degree(double);
public slots:
    void slt_setDegree(double _degree);
private:
    double m_width=802.0; //宽度
    double m_height=802.0; //高度

    double m_z=23;
    QLineF m_line;
public:
    bool bSend=true;

};

#endif // GEARITEM_H
#include "gearitem.h"
#include<QPainter>
#include<math.h>
#include<QDebug>

GearItem::GearItem(QGraphicsItem *parent) : QGraphicsItem(parent)
{
//    QTransform trans;
//    trans.scale(1,-1);
    setFlag(ItemIsMovable);
    setFlag(QGraphicsItem::ItemSendsGeometryChanges,true);
    m_line.setLine(0,0,10,0);
}

QRectF GearItem::boundingRect() const
{
    QRectF rectF(0,0,m_width,m_height);
    rectF.moveCenter(QPointF(0,0));
    return rectF;
}

void GearItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    QPainterPath painterPath;
    painter->setRenderHint(QPainter::SmoothPixmapTransform );
    double m=20;

    double r=m*m_z*0.5;
    double rb=r*cos(20.0*3.1415926/180.0); //基圆半径
    double rf=r-1.25*m; //齿根圆半径
    double ra=r+1.0*m; //齿顶圆半径

    double tan_alpha1=sqrt(rb*rb-rb*rb)/rb;
//    double alpha1=atan(tan_alpha1);
//    double theta1=tan_alpha1-alpha1;

    double tan_alpha2=sqrt(ra*ra-rb*rb)/rb;
    double alpha2=atan(tan_alpha2);
    double theta2=tan_alpha2-alpha2;



    double angle=(tan_alpha2-tan_alpha1)/30;
    double theta=tan_alpha1;
    QPolygonF polygonF;
    while (theta<=tan_alpha2)
    {
        double x=rb*cos(theta)+rb*theta*sin(theta);
        double y=rb*sin(theta)-rb*theta*cos(theta);
        polygonF.append(QPointF(x,y));
        theta+=angle;
    }

    QPen pen(Qt::black);
    pen.setStyle(Qt::DashDotLine);
    pen.setWidthF(0.5);
    painter->setPen(pen);

    painter->drawEllipse(QPointF(0,0),r,r);

    pen.setStyle(Qt::SolidLine);
    painter->setPen(pen);

    painter->drawEllipse(QPointF(0,0),10,10);
    painter->drawLine(-m_width/2,0,m_width/2,0);

    double _angle_20=20.0*3.1415926/180.0;
    double tan20=tan(_angle_20);
    double rotate_angle=tan20-_angle_20;

    //分度圆上渐开线的展开角的2倍
//    qDebug()<<2*(rotate_angle)*180/3.1415926;

    double rotate_degree=(rotate_angle)*180/3.1415926+360/m_z/4;  //对称角度
    for(int i=0;i<m_z;i++)
    {
        //绘制渐开线
        painter->drawPolyline(polygonF);
        //绘制齿顶圆圆弧
        {
            double degree=rotate_degree-theta2*180/3.1415926;
            QRectF rectF(0,0,2*ra,2*ra);
            rectF.moveCenter(QPointF(0,0));
            painter->drawArc(rectF,(-theta2*180/3.1415926)*16,(-degree)*16*2);
        }

        QLineF lineF(polygonF.first(),QPointF(0,0));
        lineF.setLength(rb-rf);
        painter->drawLine(lineF);
        // 绘制齿根圆圆弧
        {
            double degree=360/m_z-2*rotate_degree;
            QRectF rectF(0,0,2*rf,2*rf);
            rectF.moveCenter(QPointF(0,0));
            painter->drawArc(rectF,(-0)*16,(degree)*16);
        }
        painter->rotate(360/m_z);

    }

    //坐标轴对称变换 旋转
    painter->scale(1,-1);
    painter->rotate(-2*(rotate_degree));
    for(int i=0;i<m_z;i++)
    {
        painter->drawPolyline(polygonF);
        painter->rotate(360/m_z);

        QLineF lineF(polygonF.first(),QPointF(0,0));
        lineF.setLength(rb-rf);
        painter->drawLine(lineF);
    }


}

QVariant GearItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{

    if(change==ItemRotationChange)
    {
        if(bSend)
        {
            emit sg_degree(value.toDouble()-rotation());
        }
    }
    else if(change==ItemPositionChange)
    {
        QLineF line(QPointF(0,0),mapToItem(this,value.toPointF()));


        double degree=(line.angle(m_line));
        qDebug()<<"degree"<<degree;
        if(degree<0)
        {
            degree=-degree;
        }
        setRotation(degree);    //旋转相应角度
        return pos();
    }

    return QGraphicsItem::itemChange(change,value);
}

void GearItem::slt_setDegree(double _degree)
{
    setRotation(rotation()-_degree);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蔡云辉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值