解析Dxf文件:椭圆的解析

        本人最近刚刚开始接触CAD的dxf文件解析,所以一开始对dxf的解析并不是很熟悉,也是在网上查阅了大量的资料,发现解析椭圆和样条曲线的案例很少,几乎没有完整的相关源码介绍。导致我的解析过程是非常痛苦漫长的,好在历经3天,在经历一次次失败后,终于正确的解析出来了。画不多说,直接上源码吧。

椭圆解析:

头文件部分内容如下:

 std::vector<tContour>       m_contours;      //所有的轮廓


//轮廓结构
typedef struct _tContour{
    QVector<QPointF>                  path;         //轮廓路径
    bool                              bClosure;     //轮廓是否封闭
    int                               iType;        //轮廓类型
    Qt::GlobalColor                   color;        //轮廓颜色
    double                            dArea;        //轮廓面积:平方英尺(sqf)
    Qt::PenStyle                      lt;           //线条类型
    int                               lineWidth;    //轮廓粗细调节
    QPointF                           centroid;     //轮廓重心
}tContour;


vector < pair<DL_EllipseData,DL_Attributes>>    m_VecDxfEllipse;  //存储解析出来的椭圆信息

1.利用dxflib库从dxf文件中读取椭圆数据放到vector容器中


//读取椭圆数据
void Dxf::addEllipse(const DL_EllipseData &data)
{
    if (!(m_bEntities)) {
        return ;
    }
    m_VecDxfEllipse.push_back(pair<DL_EllipseData,DL_Attributes>(data,attributes));
//    qDebug()<<data.cx<<data.cy<<data.cz<<data.mx<<data.my<<data.mz<<data.ratio<<data.angle1<<data.angle2;
    qDebug()<<"cx:"<<data.cx<<"cy:"<<data.cy<<"cz:"<<data.cz
           <<"mx:"<<data.mx<<"my"<<data.my<<"mz"<<data.mz
           <<"ratio:"<<data.ratio<<"angle1:"<<data.angle1<<"angle2:"<<data.angle2;
//    qDebug()<<"addEllipse";
}

2.根据读出来的数据求出椭圆的坐标,放到m_contour容器中

double Dxf::getDotProduct( QPointF v1,  QPointF v2) {
    return v1.x() * v2.x() + v1.y ()* v2.y();
}

double Dxf::getMagnitude2D(QPointF point) const {

    return sqrt(point.x() * point.x() + point.y() * point.y());
}

double Dxf::getAngle(QPointF point) {
    double ret = 0.0;
    double m = getMagnitude2D(point);

    if (m > 1.0e-6) {
        double dp = getDotProduct(QPointF(point.x(),point.y()),QPointF(1.0,0.0));
        if (dp / m >= 1.0) {
            ret = 0.0;
        } else if (dp / m < -1.0) {
            ret = M_PI;
        } else {
            ret = acos(dp / m);
        }
        if (point.y() < 0.0) {
            ret = 2*M_PI - ret;
        }
    }
    return ret;
}

QPointF Dxf::rotate(double angle,QPointF point)
{
    double r = getMagnitude2D(point);
    double a = getAngle(point) + angle;

    double x = cos(a) * r;
    double y = sin(a) * r;

    return QPointF(x,y);
}

QPointF Dxf::rotate(DL_EllipseData data,double angle,QPointF& vc,QPointF &vp)
{
    vp = vc + rotate(angle,(vp - vc));
    return vp;
}

//解析dxf椭圆数据
void Dxf::readEllipse()
{
    for(int i = 0; i < m_VecDxfEllipse.size();i++)
    {
        tContour contour;
        DL_EllipseData data(m_VecDxfEllipse.at(i).first);

        QPointF cp = QPointF(data.cx,data.cy);

        double radius1 = sqrt(pow(data.mx,2) + pow(data.my,2));
        double radius2 = radius1 * data.ratio;
        double angle = getAngle(QPointF(data.mx,data.my));
        double a1 = data.angle1;
        double a2 = data.angle2;
        bool reversed = false;

        double aStep;         // Angle Step (rad)
        double a;             // Current Angle (rad)

        aStep=M_PI/128;
        QPointF vp;
        QPointF vc(cp.x(), cp.y());

        vp.setX(cp.x()+cos(a1) * radius1);
        vp.setY(cp.y() + sin(a1) * radius2);

        rotate(data,angle, vc,vp);

        contour.path.push_back(vp);
        if (!reversed)
        {
            // Arc Counterclockwise:
            if (a1>a2-(1.0e-9))
            {
                a2+=2*M_PI;
            }
            for (a=a1+aStep; a<=a2; a+=aStep)
            {
                vp.setX(cp.x()+cos(a)*radius1);
                vp.setY(cp.y()+sin(a)*radius2);
                rotate(data,angle, vc,vp);
                contour.path.push_back(vp);
            }
        }
        else
        {
            // Arc Clockwise:
            if (a1<a2+(1.0e-9))
            {
                a2-=2*M_PI;
            }
            for (a=a1-aStep; a>=a2; a-=aStep)
            {
                vp.setX(cp.x()+cos(a)*radius1);
                vp.setY(cp.y()+sin(a)*radius2);
                rotate(data,angle, vc,vp);
                contour.path.push_back(vp);
            }
        }
        vp.setX(cp.x()+cos(a)*radius1);
        vp.setY(cp.y()+sin(a)*radius2);


        rotate(data,angle, vc,vp);

        contour.path.push_back(vp);
        m_contours.push_back(contour);
    }
}

3.绘制椭圆


//绘制椭圆
void Dxf::drawEllipse(QPainter& painter)
{
    //解析dxf椭圆数据
    readEllipse();
    QPen pen;
    for(int i = 0;i < m_contours.size();i++)
    {
        QPainterPath paths;
        QPolygonF pg(m_contours.at(i).path);

        paths.addPolygon(pg);
        painter.setPen(QPen(Qt::black, 1));

        painter.drawPath(paths);
//        painter.fillPath(paths,Qt::red);

    }
}

效果如图所示:左边是画图软件LibreCAD解析的效果,右边是自己解析出来的效果,画图软件对图形进行了旋转,而我自己没添加旋转功能,大家也可以自行添加。

 

大致就是这样的一个步骤,整个解析和计算的过程还是比较复杂的,对于新手来说确实有一定的难度,如果大家觉得我这篇文章对你有帮助,记得点赞加收藏,后续我会更新解析dxf样条曲线spline的详细源码,让小伙伴们少走弯路。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值