从dxf文件中提取spline曲线

1.使用的工具

libDxf-负责解析dxf文件,提取图形元素

open_Nurbs-负责spline曲线的计算

2.效果如下

左图是CAD绘制的spline曲线,右图是程序中显示的曲线,红色点是在CAD中作图时鼠标点击的拟合点。

3.main.cpp代码

#include"zmDXF.h"

#include"myCanvus.h"

#include"opennurbs_public.h"

#include<iostream>


#include<QApplication>

int  main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    //封装了libDxf,解析dxf文件
    zmDXF dxf;
    dxf.read("F:/Temp/QtTest/1.dxf");

    //自定义一个画布,简单显示一下曲线
    myCanvus canvus;
    canvus.show();

    //处理每一条曲线
    for(int i = 0; i < dxf.getSplines().size(); i++)
    {
        zmSpline spline = dxf.getSplines()[i];
        ON_NurbsCurve curve;

        //创建一条NURBS曲线
        //3维   x,y,z
        //有理
        //阶数=多项式次数+1
        //控制点数量
        curve.Create(3, true, spline.m_info.degree + 1, spline.m_ctrlPts.size());

        //对每个控制点赋值
        for(int j = 0; j < spline.m_ctrlPts.size(); j++)
        {
            ON_3dPoint  point;
            point.x = spline.m_ctrlPts[j].x;
            point.y = spline.m_ctrlPts[j].y;
            point.z = spline.m_ctrlPts[j].z;
            curve.SetCV(j, point);
        }

        //节点和dxf读取的不一致,假如读取的节点是0,0,0,1,2,2,2
        //要设置的节点实际是0,0,1,2,2
        //图形学中:节点数量=控制点数量+阶数,与dxf文件一致
        //ON_NurbsCurve中节点数量比上面少2个
        for(int j = 0; j < spline.m_knots.size() - 2; j++)  {
            curve.SetKnot(j, spline.m_knots[j + 1].k);
        }

        //获取节点向量取值范围
        double range[2] = {0, 0};
        curve.GetDomain(range, range + 1);
        double domain = range[1] - range[0];

        //每条线计算100个点进行显示
        QVector<QPointF>pointfs;
        int resolution = 100;
        for(int j = 0; j < resolution; j++)
        {
            ON_3dPoint pt = curve.PointAt(range[0] + domain * j / (resolution - 1));
            pointfs.append(QPointF(pt.x, pt.y));
        }

        //提取拟合点,用红色显示
        QVector<QPointF>fitPoints;
        for(int j = 0; j < spline.m_fitPts.size(); j++)
        {
            QPointF point;
            point.setX(spline.m_fitPts[j].x);
            point.setY(spline.m_fitPts[j].y);
            fitPoints.append(point);
        }
        canvus.addPath(pointfs);
        canvus.addPoints(fitPoints);

    }


    return a.exec();
}

4.对libDXF的简单封装

#ifndef ZMDXF_H
#define ZMDXF_H

#include<QPointF>
#include"zmSpline.h"
#include"zmPoint.h"
#include"zmLine.h"
#include"zmArc.h"
#include"zmPolyLine.h"

class zmDXF : public DL_CreationAdapter
{
public:
    zmDXF();

    void read(const char *file);

    const std::vector<zmSpline> &getSplines()const;

private:
    void addPoint(const DL_PointData &) override; //解析单个点
    void addLine(const DL_LineData &) override; //解析直线

    void addPolyline(const DL_PolylineData &) override; //解析多段线
    void addVertex(const DL_VertexData &) override; //解析顶点

    void addArc(const DL_ArcData &) override; //解析圆弧
    void addCircle(const DL_CircleData &) override; //解析圆

    void addSpline(const DL_SplineData &) override;//样条曲线
    void addControlPoint(const DL_ControlPointData &) override; //样条控制点
    void addFitPoint(const DL_FitPointData &) override; //样条拟合点
    void addKnot(const DL_KnotData &) override; //样条节点

    void addBlock(const DL_BlockData &) override;//块数据
    void addText(const DL_TextData &) override;
    void addMText(const DL_MTextData &) override;

private:
    std::vector<zmArc>m_arcs;
    std::vector<zmLine>m_lines;
    std::vector<zmPoint>m_points;
    std::vector<zmPolyLine>m_polyLines;

    std::vector<zmSpline>m_splines;
};

#endif // ZMDXF_H

 5.下一步看看能不能自己写一个spline的解析,非均匀有理样条公式有点复杂

DXF文件,我们最关心的是如何得到模型上各个点的坐标,并且用这些点连成许多个三用形,构成面,进而绘制出整个模型。在DXF文件的结构,我们已经看到,DXF文件先叙述实体上各个点的坐标,然后叙述实体上有多少个面,每个面由哪些点构成。这样,我们至少需要2个数组来存储一个实体的信息,一个用于存储点的坐标,一个用于存储点序,我们可以把这2个数组放到一个结构,如果模型实体的数目不止一个是,我们就用这个结构来定义一个数组。在本文,我们使用      Visual C++ 6.0 来写一个读取DXF文件的小程序。     在实际应用,模型实体的数目以及实体点和面的数目都是不定的,为了有效地利用内存,我们选择MFC类库的聚合类CobArray类所创建的对象vertex,      sequence来存储和管理实体的点坐标和点序。     CObArray类是一个用来存放数组类的聚合类,它能根据要存进来的数组(或结构)多少自动进行自身大小的高速,而且这个类本身具有的成员函数使得我们对它的对象的操作更加方便、快捷,用它编的程序也易于读懂。     三维实体模型的模型信息的一部分信息可以在标题段读出,通过读取变量名为$UCSORG的三个变量,可以得到三维实体在世界坐标系自身所定义的用户坐标系原点的三维坐标。通过读取$EXTMAX,$EXTMIN可以获知三维实体在世界坐标系的范围,而其它部分的信息只有读完了全部DXF文件后才可以通过计算确定。对于三维实体模型的全部点坐标、点序,可以在实体段按照前面介绍的DXF文件基本结构读出。现
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值