当前位置:   article > 正文

dxflib实现dxf文件的读写_dxfib

dxfib

本文转载自:利用dxflib实现dxf文件的读写与可视化-CSDN博客,感谢原作者的分享,此处仅做学习交流使用

dxflib是开源的读写dxf文件的库,在QCAD上可以直接下载(QCAD - Downloads)。dxf作为一种通用的绘图文件格式,包含的信息量非常大,要去理解文件的内容也比较受苦,详细的解释在论坛里可以找到(dxf 格式详解_dxf是什么文件格式_runing9的博客-CSDN博客)。使用dxflib库的优势在于它很好地简化了各部分的读写,代码可读性很强,同时配库只需要将压缩包下的src文件包含在目录中即可。在给导师做一个简易的CAD软件时用到了包括dxf文件的读写,利用MFC做可视化,还做了一个尺寸修改的交互。

一、数据结构

在压缩包内的examples/readwrite文件夹下,有写好的接口类test_creationclass,如下图所示(部分已经修改过),从传入的参数类型来理解各种图元信息的数据结构。目前只使用了包括点、线、圆弧、圆、多段线、文本标注和尺寸标注。

  1. Test_CreationClass();
  2. //图元读取
  3. virtual void addLayer(const DL_LayerData& data);
  4. virtual void addPoint(const DL_PointData& data);
  5. virtual void addLine(const DL_LineData& data);
  6. virtual void addArc(const DL_ArcData& data);
  7. virtual void addCircle(const DL_CircleData& data);
  8. virtual void addPolyline(const DL_PolylineData& data);
  9. virtual void addVertex(const DL_VertexData& data);
  10. virtual void add3dFace(const DL_3dFaceData& data);
  11. virtual void addText(const DL_TextData & data);

1.点

  1. struct DXFLIB_EXPORT DL_PointData {
  2. DL_PointData(double px=0.0, double py=0.0, double pz=0.0) {
  3. x = px;
  4. y = py;
  5. z = pz;
  6. }
  7. double x;//3个坐标值
  8. double y;
  9. double z;
  10. };

2.线

  1. struct DXFLIB_EXPORT DL_LineData {
  2. /**
  3. * Constructor.
  4. * Parameters: see member variables.
  5. */
  6. DL_LineData(double lx1, double ly1, double lz1,
  7. double lx2, double ly2, double lz2) {
  8. x1 = lx1;
  9. y1 = ly1;
  10. z1 = lz1;
  11. x2 = lx2;
  12. y2 = ly2;
  13. z2 = lz2;
  14. }
  15. //2个点坐标
  16. double x1; double y1;double z1;
  17. double x2; double y2; double z2;
  18. };

3.多段线

  1. struct DXFLIB_EXPORT DL_PolylineData {
  2. /**
  3. * Constructor.
  4. * Parameters: see member variables.
  5. */
  6. DL_PolylineData(int pNumber, int pMVerteces, int pNVerteces, int pFlags, double pElevation = 0.0) {
  7. number = pNumber;
  8. m = pMVerteces;
  9. n = pNVerteces;
  10. elevation = pElevation;
  11. flags = pFlags;
  12. }
  13. unsigned int number;//多段线包含的点数,与DL_VertexData配合使用
  14. unsigned int m;//如果多段线是多边形网格,则m方向上的顶点数
  15. unsigned int n;//如果多段线是多边形网格,则n方向上的顶点数
  16. double elevation;//高程
  17. int flags;
  18. };

顶点

  1. struct DXFLIB_EXPORT DL_VertexData {
  2.     /**
  3.      * Constructor.
  4.      * Parameters: see member variables.
  5.      */
  6.     DL_VertexData(double px=0.0, double py=0.0, double pz=0.0,
  7.                   double pBulge=0.0) {
  8.         x = px;
  9.         y = py;
  10.         z = pz;
  11.         bulge = pBulge;
  12.     }
  13.  
  14.     double x;
  15.     double y;
  16.     double z;
  17.     double bulge;//多段线的顶点凸起部分的定义。使用顶点处的弧角的1/4弧度的切线值,直线为0
  18. };

4.圆弧
 

  1. struct DXFLIB_EXPORT DL_ArcData {
  2. DL_ArcData(double acx, double acy, double acz,
  3. double aRadius,
  4. double aAngle1, double aAngle2) {
  5. cx = acx;
  6. cy = acy;
  7. cz = acz;
  8. radius = aRadius;
  9. angle1 = aAngle1;
  10. angle2 = aAngle2;
  11. }
  12. //圆弧圆心点坐标
  13. double cx;
  14. double cy;
  15. double cz;
  16. double radius;//圆弧半径
  17. double angle1;//起始角度(以x正半轴逆时针旋转计算角度)
  18. double angle2;//终止角度
  19. };

5.圆

  1. struct DXFLIB_EXPORT DL_CircleData {
  2.     DL_CircleData(double acx, double acy, double acz,
  3.                   double aRadius) {
  4.  
  5.         cx = acx;
  6.         cy = acy;
  7.         cz = acz;
  8.         radius = aRadius;
  9.     }
  10.     //圆心坐标及半径
  11.     double cx;
  12.     double cy;
  13.     double cz;
  14.     double radius;
  15. };

6.文本标注

  1. struct DXFLIB_EXPORT DL_TextData {
  2. DL_TextData(double ipx, double ipy, double ipz,
  3. double apx, double apy, double apz,
  4. double height, double xScaleFactor,
  5. int textGenerationFlags,
  6. int hJustification,
  7. int vJustification,
  8. const std::string& text,
  9. const std::string& style,
  10. double angle)
  11. : ipx(ipx), ipy(ipy), ipz(ipz),
  12. apx(apx), apy(apy), apz(apz),
  13. height(height), xScaleFactor(xScaleFactor),
  14. textGenerationFlags(textGenerationFlags),
  15. hJustification(hJustification),
  16. vJustification(vJustification),
  17. text(text),
  18. style(style),
  19. angle(angle) {
  20. }
  21. //定义点坐标
  22. double ipx;
  23. double ipy;
  24. double ipz;
  25. //对齐点坐标
  26. double apx;
  27. double apy;
  28. double apz;
  29. double height;//字高
  30. double xScaleFactor;//相对X比例因子
  31. int textGenerationFlags;//默认为0,向后为2,倒置为4
  32. int hJustification;//水平对齐
  33. /* 左侧=0,中心=1,右侧=2,对齐=3,中间=4,适应=5
  34. 对于3、4、5垂直对齐必须为0 */
  35. int vJustification;//垂直对齐,基线=0,底部=1,中间=2,顶部=3
  36. std::string text;//文本内容
  37. std::string style;//字体
  38. double angle;//旋转角度
  39. };

7.尺寸标注


尺寸标注相对复杂一些,它不止简单的一个文本,还包括直线和箭头,称为标注块,也就是说它需要通过块来添加。具体的内容在文件中查阅,这里不在展示。

  1. virtual void addBlock(const DL_BlockData&data);//添加块
  2. virtual void endBlock();//结束块的添加
  3. virtual void addSolid(const DL_SolidData&data);//箭头
  4. virtual void addMText(const DL_MTextData & data);//标注文本

8.dxf文件数据结构的建立

在官方下载下来的文件中,有一个Test_CreationClass头文件和源文件,dxf文件的数据结构直接用这个类就可以。这个就相当于接口类,在里面可以重写各类图元读取的函数,原本里面是打印相关信息,我改成了保存数据到成员中。需要注意的是多段线的读取结束时需要调用donpolyline,完成多段线的添加,而标注块也是类似的道理,需要读取完这个块。内容见下面头文件以及源文件。

  1. #ifndef TEST_CREATIONCLASS_H
  2. #define TEST_CREATIONCLASS_H
  3. #include<vector>
  4. #include "../src/dl_creationadapter.h"
  5. class Test_CreationClass : public DL_CreationAdapter {
  6. public:
  7. Test_CreationClass();
  8. //图元读取
  9. virtual void addLayer(const DL_LayerData& data);
  10. virtual void addPoint(const DL_PointData& data);
  11. virtual void addLine(const DL_LineData& data);
  12. virtual void addArc(const DL_ArcData& data);
  13. virtual void addCircle(const DL_CircleData& data);
  14. virtual void addPolyline(const DL_PolylineData& data);
  15. virtual void addVertex(const DL_VertexData& data);
  16. virtual void add3dFace(const DL_3dFaceData& data);
  17. virtual void addText(const DL_TextData & data);
  18. //标注块整体读取
  19. bool adddim = false;
  20. virtual void addBlock(const DL_BlockData&data);
  21. virtual void endBlock();
  22. virtual void addSolid(const DL_SolidData&data);
  23. virtual void addMText(const DL_MTextData & data);
  24. void printAttributes();
  25. void donepolyline()
  26. {
  27. for (int i = 0; i < m_polylines.size(); ++i)
  28. m_polylines[i].first.number = m_polylines[i].second.size();
  29. }
  30. class dimblock{
  31. public:
  32. dimblock(){
  33. dimlines.clear();
  34. dimtext.clear();
  35. dimarrow.clear();
  36. }
  37. std::vector<DL_LineData>dimlines;
  38. std::vector<DL_MTextData> dimtext;
  39. std::vector<DL_SolidData>dimarrow;
  40. };
  41. public://图元信息
  42. //DL_LayerData m_layerdata; //层
  43. std::vector<DL_PointData>m_points; //点
  44. std::vector<DL_LineData>m_lines; //直线
  45. std::vector<std::pair<DL_PolylineData, std::vector<DL_VertexData>>>m_polylines; //多段线
  46. std::vector<DL_ArcData> m_arcs; //圆弧
  47. std::vector<DL_CircleData >m_circles; //圆
  48. std::vector<DL_SolidData>m_solid; //实体
  49. std::vector<DL_TextData>m_text; //普通文本
  50. std::vector<DL_MTextData>m_mtext; //标注文本
  51. std::vector<dimblock>m_dimblock; //标注块
  52. };
  53. #endif

cpp

  1. #include "test_creationclass.h"
  2. #include <iostream>
  3. #include <stdio.h>
  4. /**
  5. * Default constructor.
  6. */
  7. Test_CreationClass::Test_CreationClass() {
  8. m_points.clear();
  9. m_lines.clear();
  10. m_polylines.clear();
  11. m_circles.clear();
  12. m_arcs.clear();
  13. m_text.clear();
  14. m_mtext.clear();
  15. m_dimblock.clear();
  16. }
  17. /**
  18. * Sample implementation of the method which handles layers.
  19. */
  20. void Test_CreationClass::addLayer(const DL_LayerData& data) {
  21. // printf("LAYER: %s flags: %d\n", data.name.c_str(), data.flags);
  22. // printAttributes();
  23. }
  24. /**
  25. * Sample implementation of the method which handles point entities.
  26. */
  27. void Test_CreationClass::addPoint(const DL_PointData& data) {
  28. m_points.push_back(data);
  29. // printf("POINT (%6.3f, %6.3f, %6.3f)\n",data.x, data.y, data.z);
  30. // printAttributes();
  31. }
  32. /**
  33. * Sample implementation of the method which handles line entities.
  34. */
  35. void Test_CreationClass::addLine(const DL_LineData& data) {
  36. if (adddim)
  37. m_dimblock[m_dimblock.size() - 1].dimlines.push_back(data);
  38. else
  39. m_lines.push_back(data);
  40. // printf("LINE (%6.3f, %6.3f, %6.3f) (%6.3f, %6.3f, %6.3f)\n",data.x1, data.y1, data.z1, data.x2, data.y2, data.z2);
  41. // printAttributes();
  42. }
  43. /**
  44. * Sample implementation of the method which handles arc entities.
  45. */
  46. void Test_CreationClass::addArc(const DL_ArcData& data) {
  47. m_arcs.push_back(data);
  48. // printf("ARC (%6.3f, %6.3f, %6.3f) %6.3f, %6.3f, %6.3f\n",data.cx, data.cy, data.cz, data.radius, data.angle1, data.angle2);
  49. // printAttributes();
  50. }
  51. /**
  52. * Sample implementation of the method which handles circle entities.
  53. */
  54. void Test_CreationClass::addCircle(const DL_CircleData& data) {
  55. m_circles.push_back(data);
  56. // printf("CIRCLE (%6.3f, %6.3f, %6.3f) %6.3f\n",data.cx, data.cy, data.cz, data.radius);
  57. // printAttributes();
  58. }
  59. /**
  60. * Sample implementation of the method which handles polyline entities.
  61. */
  62. void Test_CreationClass::addPolyline(const DL_PolylineData& data) {
  63. std::vector<DL_VertexData> temp; temp.clear();
  64. std::pair<DL_PolylineData, std::vector<DL_VertexData>> newone(data,temp);
  65. m_polylines.push_back(newone);
  66. // printf("POLYLINE \n");
  67. // printf("flags: %d\n", (int)data.flags);
  68. // printAttributes();
  69. }
  70. /**
  71. * Sample implementation of the method which handles vertices.
  72. */
  73. void Test_CreationClass::addVertex(const DL_VertexData& data) {
  74. m_polylines[m_polylines.size() - 1].second.push_back(data);
  75. // printf("VERTEX (%6.3f, %6.3f, %6.3f) %6.3f\n",data.x, data.y, data.z,data.bulge);
  76. // printAttributes();
  77. }
  78. void Test_CreationClass::add3dFace(const DL_3dFaceData& data) {
  79. printf("3DFACE\n");
  80. // for (int i=0; i<4; i++) {
  81. // printf(" corner %d: %6.3f %6.3f %6.3f\n", i, data.x[i], data.y[i], data.z[i]);
  82. // }
  83. // printAttributes();
  84. }
  85. void Test_CreationClass::addBlock(const DL_BlockData&data)
  86. {
  87. adddim = true;
  88. dimblock newone;
  89. m_dimblock.push_back(newone);
  90. }
  91. void Test_CreationClass::endBlock()
  92. {
  93. adddim = false;
  94. if (m_dimblock[m_dimblock.size() - 1].dimlines.size() < 1
  95. && m_dimblock[m_dimblock.size() - 1].dimtext.size() < 1
  96. && m_dimblock[m_dimblock.size() - 1].dimarrow.size()<1)
  97. m_dimblock.pop_back();
  98. }
  99. void Test_CreationClass::addSolid(const DL_SolidData&data)
  100. {
  101. if (adddim)
  102. m_dimblock[m_dimblock.size() - 1].dimarrow.push_back(data);
  103. else
  104. m_solid.push_back(data);
  105. }
  106. void Test_CreationClass::addText(const DL_TextData & data)
  107. {
  108. m_text.push_back(data);
  109. }
  110. void Test_CreationClass::addMText(const DL_MTextData & data)
  111. {
  112. if (adddim)
  113. m_dimblock[m_dimblock.size() - 1].dimtext.push_back(data);
  114. else
  115. m_mtext.push_back(data);
  116. }
  117. void Test_CreationClass::printAttributes() {
  118. // printf(" Attributes: Layer: %s, ", attributes.getLayer().c_str());
  119. // printf(" Color: ");
  120. // if (attributes.getColor()==256) {
  121. // printf("BYLAYER");
  122. // } else if (attributes.getColor()==0) {
  123. // printf("BYBLOCK");
  124. // } else {
  125. // printf("%d", attributes.getColor());
  126. // }
  127. // printf(" Width: ");
  128. // if (attributes.getWidth()==-1) {
  129. // printf("BYLAYER");
  130. // } else if (attributes.getWidth()==-2) {
  131. // printf("BYBLOCK");
  132. // } else if (attributes.getWidth()==-3) {
  133. // printf("DEFAULT");
  134. // } else {
  135. // printf("%d", attributes.getWidth());
  136. // }
  137. // printf(" Type: %s\n", attributes.getLinetype().c_str());
  138. }
  139. // EOF

二、读dxf文件


在外部类中声明上述的类Test_CreationClass为成员变量,定义一个读文件的方法。例如我是外部又建立了一个MyDxf类用来衔接MFC的button事件或其他控件,注意包含相关的头文件。

  1. public:
  2.      Test_CreationClass        * m_data;        //dxf数据输出接口
  1. void MyDxf::OpenDxf_Button(string filePath)
  2. {
  3.     // Load DXF file into memory:
  4.     Initialdxf();
  5.     std::cout << "Reading file " << filePath << "...\n";
  6.     if (!m_dxf->in(filePath, m_data)) { // if file open failed
  7.         std::cerr << filePath << " could not be opened.\n";
  8.         return;
  9.     }
  10.     m_data->donepolyline();
  11.  
  12. }

三、写dxf文件

说是写文件,其实是保存文件,写文件的过程就是对m_data修改的过程,例如后面添加交互功能,画线,画圆之类的,只需往相应的m_data中的容器添加即可。

  1. void MyDxf::SaveDxf_Button(string filePath)
  2. {
  3. if (m_data==NULL)return;
  4. FILE *pfd = fopen(filePath.c_str(), "w+");
  5. DL_Codes::version exportVersion = DL_Codes::AC1015;
  6. DL_WriterA* dw = m_dxf->out(filePath.c_str(), exportVersion);
  7. if (dw == NULL) { printf("Cannot open file 'myfile.m_dxf' \ for writing."); return; }
  8. /*--------------------------------------------------------*/
  9. //1 标题段
  10. m_dxf->writeHeader(*dw);
  11. dw->sectionEnd();
  12. /*--------------------------------------------------------*/
  13. //2 表段
  14. dw->sectionTables();
  15. m_dxf->writeVPort(*dw);
  16. //2.1 线型表(Linetype)
  17. dw->tableLinetypes(3);
  18. m_dxf->writeLinetype(*dw, DL_LinetypeData("BYBLOCK", "BYBLOCK", 0, 0, 0.0));
  19. m_dxf->writeLinetype(*dw, DL_LinetypeData("BYLAYER", "BYLAYER", 0, 0, 0.0));
  20. m_dxf->writeLinetype(*dw, DL_LinetypeData("CONTINUOUS", "Continuous", 0, 0, 0.0));
  21. dw->tableEnd();
  22. //2.2 图层表(Layer)
  23. int numberOfLayers = 3;//层数3
  24. dw->tableLayers(numberOfLayers);
  25. m_dxf->writeLayer(*dw, DL_LayerData("0", 0), DL_Attributes(std::string(""), DL_Codes::black, 100, "CONTINUOUS", 1.0));
  26. m_dxf->writeLayer(*dw, DL_LayerData("mainlayer", 0), DL_Attributes(std::string(""), DL_Codes::black, 100, "CONTINUOUS", 1.0));
  27. m_dxf->writeLayer(*dw, DL_LayerData("anotherlayer", 0), DL_Attributes(std::string(""), DL_Codes::blue, 100, "CONTINUOUS", 1.0));
  28. dw->tableEnd();
  29. //2.3 字样表(Style)
  30. dw->tableStyle(1);
  31. m_dxf->writeStyle(*dw, DL_StyleData("standard", 0, 2.5, 1.0, 0.0, 0, 2.5, "txt", ""));
  32. dw->tableEnd();
  33. //2.4 视图表(View)
  34. m_dxf->writeView(*dw);
  35. m_dxf->writeUcs(*dw);
  36. dw->tableAppid(1);
  37. m_dxf->writeAppid(*dw, "ACAD");
  38. dw->tableEnd();
  39. //2.5 DL_VERSION_R13中需要伪造dimstyle和blockrecord两部分,以使AutoCAD能够读取该文件。
  40. m_dxf->writeDimStyle(*dw, 1, 1, 1, 1, 1);
  41. m_dxf->writeBlockRecord(*dw);
  42. dw->tableEnd();
  43. dw->sectionEnd();
  44. /*--------------------------------------------------------*/
  45. //3 块段
  46. DL_Attributes typetemp1("mainlayer", 256, -1, "BYLAYER", 1.0);//属性
  47. DL_Attributes typetemp2("anotherlayer", 256, -1, "BYLAYER", 1.0);//属性
  48. dw->sectionBlocks();
  49. m_dxf->writeBlock(*dw, DL_BlockData("*Model_Space", 0, 0.0, 0.0, 0.0));
  50. m_dxf->writeEndBlock(*dw, "*Model_Space");
  51. m_dxf->writeBlock(*dw, DL_BlockData("*Paper_Space", 0, 0.0, 0.0, 0.0));
  52. m_dxf->writeEndBlock(*dw, "*Paper_Space");
  53. m_dxf->writeBlock(*dw, DL_BlockData("*Paper_Space0", 0, 0.0, 0.0, 0.0));
  54. m_dxf->writeEndBlock(*dw, "*Paper_Space0");
  55. // m_dxf->writeBlock(*dw, DL_BlockData("myblock1", 0, 0.0, 0.0, 0.0));
  56. // // ...
  57. // // write block entities e.g. with m_dxf->writeLine(), ..
  58. // // ...
  59. // m_dxf->writeEndBlock(*dw, "myblock1");
  60. dw->sectionEnd();
  61. /*--------------------------------------------------------*/
  62. //4 实体段
  63. dw->sectionEntities();
  64. for (int i = 0; i < m_data->m_points.size(); ++i)
  65. {
  66. m_dxf->writePoint(*dw, m_data->m_points[i], typetemp1);
  67. }
  68. for (int i = 0; i < m_data->m_lines.size(); ++i)
  69. {
  70. m_dxf->writeLine(*dw, m_data->m_lines[i], typetemp1);
  71. }
  72. for (int i = 0; i < m_data->m_polylines.size(); ++i)
  73. {
  74. m_dxf->writePolyline(*dw, m_data->m_polylines[i].first, typetemp1);
  75. for (int j = 0; j < m_data->m_polylines[i].second.size(); ++j)
  76. {
  77. m_dxf->writeVertex(*dw, m_data->m_polylines[i].second[j]);
  78. }
  79. m_dxf->writePolylineEnd(*dw);
  80. }
  81. for (int i = 0; i < m_data->m_arcs.size(); ++i)
  82. {
  83. m_dxf->writeArc(*dw, m_data->m_arcs[i], typetemp1);
  84. }
  85. for (int i = 0; i < m_data->m_circles.size(); ++i)
  86. {
  87. m_dxf->writeCircle(*dw, m_data->m_circles[i], typetemp1);
  88. }
  89. for (int i = 0; i < m_data->m_text.size();++i)
  90. {
  91. //m_dxf->writeText(*dw, m_data->m_text[i], typetemp2);//用text写有问题,使用MText代替
  92. DL_MTextData temp(m_data->m_text[i].ipx, m_data->m_text[i].ipy, m_data->m_text[i].ipz,
  93. 0, 0, 0, m_data->m_text[i].height, 0, 5, 1, 1, 1, m_data->m_text[i].text, m_data->m_text[i].style, m_data->m_text[i].angle);
  94. m_dxf->writeMText(*dw, temp, typetemp2);
  95. }
  96. for (int i = 0; i < m_data->m_mtext.size(); ++i)
  97. {
  98. //m_data->m_mtext[i].height = 30;
  99. DL_MTextData temp = m_data->m_mtext[i];
  100. temp.height = 50;
  101. m_dxf->writeMText(*dw, temp, typetemp2);
  102. }
  103. dw->sectionEnd();
  104. /*--------------------------------------------------------*/
  105. //5 文件结束段
  106. m_dxf->writeObjects(*dw);
  107. m_dxf->writeObjectsEnd(*dw);
  108. dw->dxfEOF();
  109. dw->close();
  110. delete dw;
  111. delete m_dxf;
  112. dw = nullptr;
  113. m_dxf = nullptr;
  114. }


版权声明:本文为CSDN博主「卡死脱离态」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Akiyama_sou/article/details/130870304

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/114358?site
推荐阅读
相关标签
  

闽ICP备14008679号