Open Cascade DataExchange DXF
eryar@163.com
摘要Abstract:對DXF文本格式進行詳細介紹,并介紹了如何使用開源庫dxflib對DXF文件進行讀寫操作,并將DXF文件中圖形導入到OpenCascade。
關鍵字Key Words:DXF、Open Cascade、Data Exchange, dxflib
一、引言 Introduction
目前市面上的CAD系統都有自己的數據文件,各個系統之間的數據結構和格式各不相同,這樣極大影響了設計和制造部門之間或企業之間的數據傳輸和程序銜接的自動化,同樣給CMM和CAD/CAM的數據通信帶來困難。因此,迫切需要數據交換文件格式的標準化。
產品數據的正確交換可以使雙方不必重建數據,提高效率。產品數據交換的通常做法是使用數據交換接口,即需要交換的每一系統與標準數據格式(中性格式)之間開發雙向轉換接口,兩系統通過中性格式進行交換。
DXF是Drawing eXchange File的縮寫,意思為圖形交換文件,在工程制圖中有廣泛的應用,掌握了DXF文件的讀寫對編寫CAD軟件時的圖形信息的交換有重要意義。它有兩種格式:一種是ASCII DXF格式;一種是二進制DXF格式。ASCII DXF文件格式是ASCII 文字格式的AutoCAD圖形的完整表示,這種文件格式易于被其它程序處理。二進制格式的DXF文件與ASCII格式的DXF文件包含的信息相同,但格式上二進制格式比ASCII格式更精簡,能夠節省百分之二十五的文件空間。AutoCAD能夠更快地對其執行讀寫操作(通常能快五倍)。這可能是對ASCII格式的DXF文件操作時有ASCII與二進制形式的轉換,因而花費時間較多。ASCII格式的DXF文件可讀性強。
OpenCascade也有數據交換接口DataExchange,可對主流圖形交換格式進行讀寫。
Figure 1.1 DataExchange Module of OpenCascade
其中對STEP、IGES、STL、VRML的程序是開源的,對ACIS的SAT、Parasolid的X_T和DXF數據交換的程序是收費的,對DXF讀寫的是DXF-Import-Export,詳情可參考:
http://www.opencascade.org/support/products/dataex/,也可直接和OpenCascade進行聯系。
二、DXF格式簡介 DXF Introduction
一個完整的ASCII格式的DXF文件結構如下:
l HEADER段。它包含圖形的基本信息。它由AutoCAD數據庫版本號和一些系統變量組成。每個參數都包含一個變量名稱及其關聯的值。
l CLASSES段。包含應用程序定義的類的信息,這些類的實例出現在數據庫的BLOCKS、ENTITIES和OBJECTS段中。類定義在類的層次結構中是固定不變的。
l TABLES段。包含以下符號表的定義:
APPID(應用程序標識表)
BLOCK_RECORD(塊參照表)
DIMSTYLE(標注樣式表)
LAYER(圖層表)
LTYPE(線型表)
STYLE(文字樣式表)
UCS(用戶坐標系表)
VIEW(視圖表)
VPORT(視口配置表)
l BLOCKS段。包含構成圖形中每個塊參照的塊定義和圖形圖元。
l ENTITIES段。包含圖形中的圖形對象(圖元),其中包括塊參照(插入圖元)。這里的信息很重要。
l OBJECTS段。包含圖形中的非圖形對象。除圖元、符號表記錄以及符號表以外的所有對象都存儲在此段。OBJECTS段中的條目樣例是包含多線樣式和組的詞典。
l THUMBNAILIMAGE段。包含圖形的預覽圖像數據。此段為可選。
每個段都以一個后跟字符串SECTION的組碼0開始,其后是組碼2和表示該段名稱的字符串(例如,HEADER)。每個段都由定義其元素的組碼和值組成。每個段都以一個后跟字符串ENDSEC的組碼0結束。
關于DXF文件更詳細內容可參考我08年寫的一篇文章《用C讀取DXF文件》,可以從網上下載,網址:http://blog.csdn.net/eryar/article/details/2371755。在11年又寫了一個《Read DXF File》,雖然使用了繼承,但是讀入時的很多判斷的處理感覺還不是很滿意,文章代碼網址:
http://www.shnenglu.com/eryar/archive/2013/03/26/162303.html
參考這些代碼,可以完全理解文本格式的DXF文件,并可自己動手來處理DXF文件了。
三、使用dxflib與OpenCascade交換數據 Wrap dxflib for OpenCascade DataExchange
如果程序中只用到DXF簡單的圖形,如直線、圓弧、圓等,可以自己寫個處理的程序;如果要處理DWG格式的文件,有些庫可以使用,如openDWG Toolkit,雖然帶有Open字樣,但是這個工具并不是免費的,免費的有LibreDWG;如果只處理文本格式的DXF文件,可以使用庫dxflib。當然dxflib也是有不足之處的,如只能處理文本格式的DXF,不能處理二進制格式,不能處理包含的ACIS三維實體等。如果程序只處理簡單的圖形、三維面片等,dxflib還是很好用的。
dxflib的使用方法很簡單,通過調用 DL_Dxf 對象的 in 函數并將指針傳遞給一個繼承 DL_CreationAdapter 抽象類來打開此文件。in 函數運行時,會調用傳遞給它的類中的幾個函數。如今,有數十個這樣的函數(參閱DXFLib程序員手冊),但是在大多數情況下,受關注最多的有如下這幾個函數:addPoint、addLine、 addCircle 和 addVertex。您只需實現您所關注的那些函數;剩下的您可以忽略。
下面給出一個使用dxflib讀取形狀并轉換到OpenCascade中的具體例子。
四、程序示例 Example Code
這里給出具體的程序示例,當然目前只實現部分形狀到OpenCascade的轉換,如果有興趣可以實現其他形狀的實現。程序代碼如下所示:
類聲明文件:DxfReader.h
/*
* Copyright (c) 2013 eryar All Rights Reserved.
*
* File : DxfReader.h
* Author : eryar@163.com
* Date : 2013-12-22 14:40
* Version : 1.0v
*
* Description : Use dxflib to import entities from DXF to OpenCascade.
*
* Key Words : OpenCascade, dxflib, DXF, DataExchange
*
*/
#pragma once
#define WNT
#include <TopoDS_Shape.hxx>
#include <BRep_Builder.hxx>
#include <memory>
#include "dl_dxf.h"
#include "dl_creationadapter.h"
/**
* @breif Facade dxflib for OpenCascade DataExchange with DXF.
*/
class DxfReader : public DL_CreationAdapter
{
public:
/**
* @brief constructor.
* @param fileName [in] dxf file name with path.
*/
DxfReader(const std::string& fileName);
~DxfReader(void);
/**
* @brief Get the shape of the dxf.
* @return OpenCascade topology shape.
*/
const TopoDS_Shape& GetShape(void) const;
public:
virtual void addPoint(const DL_PointData&);
virtual void addLine(const DL_LineData& line);
virtual void addArc(const DL_ArcData& arc);
virtual void addCircle(const DL_CircleData& circle);
virtual void addEllipse(const DL_EllipseData&);
virtual void addPolyline(const DL_PolylineData& polyline);
virtual void addVertex(const DL_VertexData&);
virtual void addSpline(const DL_SplineData&);
virtual void addKnot(const DL_KnotData&);
virtual void addControlPoint(const DL_ControlPointData&);
virtual void add3dFace(const DL_3dFaceData&);
virtual void addSolid(const DL_SolidData& solid);
private:
std::auto_ptr<DL_Dxf> mDxf;
TopoDS_Compound mShape;
BRep_Builder mBuilder;
};
類定義文件:DxfReader.cpp
/*
* Copyright (c) 2013 eryar All Rights Reserved.
*
* File : DxfReader.cpp
* Author : eryar@163.com
* Date : 2013-12-22 14:40
* Version : 1.0v
*
* Description : Use dxflib to import entities from DXF to OpenCascade.
*
* Key Words : OpenCascade, dxflib, DXF, DataExchange
*
*/
#include "DxfReader.h"
#include <Degrees.hxx>
#include <gp_Circ.hxx>
#include <gp_Elips.hxx>
#include <GC_MakeSegment.hxx>
#include <GC_MakeCircle.hxx>
#include <GC_MakeArcOfCircle.hxx>
#include <GC_MakeEllipse.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <BRepBuilderAPI_MakeVertex.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepBuilderAPI_MakePolygon.hxx>
DxfReader::DxfReader(const std::string& fileName)
: mDxf(new DL_Dxf())
{
mBuilder.MakeCompound(mShape);
mDxf->in(fileName, this);
}
DxfReader::~DxfReader(void)
{
}
const TopoDS_Shape& DxfReader::GetShape() const
{
return mShape;
}
void DxfReader::addPoint(const DL_PointData& point)
{
mBuilder.Add(mShape, BRepBuilderAPI_MakeVertex(gp_Pnt(point.x, point.y, point.z)));
}
void DxfReader::addLine(const DL_LineData& line)
{
Handle_Geom_Curve theSegment = GC_MakeSegment(gp_Pnt(line.x1, line.y1, line.z1), gp_Pnt(line.x2, line.y2, line.z2));
mBuilder.Add(mShape, BRepBuilderAPI_MakeEdge(theSegment));
}
void DxfReader::addArc(const DL_ArcData &arc)
{
gp_Circ theCircle;
theCircle.SetRadius(arc.radius);
theCircle.SetLocation(gp_Pnt(arc.cx, arc.cy, arc.cz));
Handle_Geom_Curve theArc = GC_MakeArcOfCircle(theCircle, DEG(arc.angle1), DEG(arc.angle2), false);
mBuilder.Add(mShape, BRepBuilderAPI_MakeEdge(theArc));
}
void DxfReader::addCircle(const DL_CircleData& circle)
{
gp_Circ aCircle;
aCircle.SetRadius(circle.radius);
aCircle.SetLocation(gp_Pnt(circle.cx, circle.cy, circle.cz));
Handle_Geom_Curve theCircle = GC_MakeCircle(aCircle);
mBuilder.Add(mShape, BRepBuilderAPI_MakeEdge(theCircle));
}
void DxfReader::addEllipse(const DL_EllipseData& ellipse)
{
}
void DxfReader::addPolyline(const DL_PolylineData& polyline)
{
}
void DxfReader::addVertex(const DL_VertexData& vertex)
{
}
void DxfReader::addSpline(const DL_SplineData& spline)
{
}
void DxfReader::addKnot(const DL_KnotData& knot)
{
}
void DxfReader::addControlPoint(const DL_ControlPointData& cp)
{
}
void DxfReader::add3dFace(const DL_3dFaceData& face)
{
BRepBuilderAPI_MakePolygon polygon(
gp_Pnt(face.x[0], face.y[0], face.z[0]),
gp_Pnt(face.x[1], face.y[1], face.z[1]),
gp_Pnt(face.x[2], face.y[2], face.z[2]),
gp_Pnt(face.x[3], face.y[3], face.z[3]), true);
BRepBuilderAPI_MakeFace makeFace(polygon.Wire());
if (makeFace.IsDone())
{
mBuilder.Add(mShape, makeFace.Face());
}
//mBuilder.Add(mShape, polygon.Wire());
}
void DxfReader::addSolid(const DL_SolidData &solid)
{
add3dFace(solid);
}
類DxfReader的使用也很簡單,程序如下所示:
/*
* Copyright (c) 2013 eryar All Rights Reserved.
*
* File : Main.cpp
* Author : eryar@163.com
* Date : 2013-12-22 15:00
* Version : 1.0v
*
* Description : Use dxflib to import entities from DXF to OpenCascade.
*
* Key Words : OpenCascade, dxflib, DXF, DataExchange
*
*/
#include "DxfReader.h"
#include <BRepTools.hxx>
#pragma comment(lib, "TKernel.lib")
#pragma comment(lib, "TKMath.lib")
#pragma comment(lib, "TKBRep.lib")
#pragma comment(lib, "TKGeomBase.lib")
#pragma comment(lib, "TKTopAlgo.lib")
int main(int argc, char* argv[])
{
std::string strFile = ((argc > 1) ? argv[1] : "test.dxf");
DxfReader dxfReader(strFile);
ofstream brepFile("dxf.brep");
BRepTools::Write(dxfReader.GetShape(), brepFile);
return 0;
}
程序效果還不錯,給出幾個程序處理的例子如下圖所示:
Figure 4.1 Use DxfReader import DXF to OpenCascade
Figure 4.2 Use DxfReader import DXF to OpenCascade
五、結論 Conclusion
DXF格式是圖形數據交換的一種常見格式,DXF文件的讀寫對CAD/CAM程序很有意義。本文通過把dxflib簡單封裝把DXF中圖形轉換為OpenCascade中的形狀,為免費在OpenCascade中進行DXF數據交換提供了一個思路。希望本文對你有所幫助。
六、參考資料 References
1. 使用開源庫讀取DWG和DXF文件,
http://www.ibm.com/developerworks/cn/opensource/os-autocad/
2. eryar, 用C讀取DXF文件, http://blog.csdn.net/eryar/article/details/2371755
3. eryar, Read DXF File, http://www.shnenglu.com/eryar/archive/2013/03/26/162303.html
4. openDWG, http://www.opendesign.com/
5. OpenCascade, DXF Import-Export, http://www.opencascade.org/support/products/dataex/dxf/