天天看點

OpenCASCADE DataExchange DWG

<a href="mailto:[email protected]">[email protected]</a>

Abstract. DWG is a file format created in the 70’s for the emerging CAD applications. Currently it is the native file format of AutoCAD, a proprietary CAD program developed by Autodesk. Libredwg is a free C library to read and write DWG files. This program is part of GNU project, released under the aegis of GNU. The paper focus on the usage of Libredwg, and use the Libredwg to read a DWG file and output the entities of the DWG to Tcl script for OpenCASCADE Draw Test Harness visualization.

Key Words. OpenCASCADE, DWG, Libredwg, DataExchange, Windows

1. Introduction

DWG是CAD軟體AutoCAD及基于AutoCAD的軟體儲存設計資料所用的一種專有檔案格式,始于1970年代的一套Interact CAD軟體。之後Autodesk公司于1982年取得版權開始使用這種檔案格式。Autodesk公司擁有、開發并且更新DWG檔案格式,通常每隔幾年DWG就會随着在AutoCAD中添加新的特性而對DWG格式進行更新。

DWG格式及它的ASCII格式變體DXF格式,已經成為CAD制圖資料交換中的事實檔案标準,據估計全世界有超過十億個DWG檔案。有幾家公司正在對DWG檔案格式進行逆向工程以試圖為其它的設計軟體提供讀寫DWG檔案的能力。Autodesk公司也提供了一套需要授權的DWG讀寫技術開發包“RealDWG”。

新版的AutoCAD可以打開舊版的DWG檔案,AutoCAD2007可以打開2.0版本的DWG檔案并且可以儲存為R14版本。另外Autodesk公司提供一個免費的DWG檢視工個“DWG TrueView”用于檢視所有版本的DWG檔案。另外Autodesk公司是vendor lock-in政策的強力支援者,盡力保護DWG檔案格式并且禁止開發支援DWG格式的開放源代碼庫。

2006年11月12日,Autodesk公司對Open Design Alliance-一款支援DWG格式的自由庫OpenDWG提出了訴訟。

ASCII格式的DXF檔案的文檔Autodesk提供了,但是二進制的DWG格式并沒有提供相關文檔,由上可見對DWG檔案的讀寫處理是非常困難的。本文主要介紹如何使用Libredwg庫來對讀取DWG中的幾何資料,并将幾何資料生成為可以在OpenCASCADE中顯示的Tcl腳本,以驗證讀取資料的正确性。

2.Modify Libredwg for Visual Studio

Libredwg是一個Free的讀寫DWG檔案的C庫,這個程式是GNU項目的一部分,授權方式是GNU GPL3。

Libredwg是Libdwg的一個分支,其目的是建立OpenDWG庫的一個替代庫。也是高優先級的Free軟體項目:

從網上下載下傳的Libredwg源程式是在Linux下編譯的,并沒有配置在Windows下編譯方法。為了使用Libredwg可以在Windows上的Visual Studio中編譯通過,對Libredwg做了一些修改,最終編譯成功。在Visual Studio 2008上成功編譯的工程可以文後的連結中下載下傳。

下面給出使用Libredwg讀取DWG檔案中直線、圓及文字的例子程式:

/*

 * load_dwg.c: load a DWG, get lines, text and circles

 * written by Felipe Castro

 * modified by Felipe Corrêa da Silva Sances

 * modified by Thien-Thi Nguyen

 */

#include &lt;dwg.h&gt;

#include "suffix.c"

void add_line(double x1, double y1, double x2, double y2)

{

  // Make something with that

}

void add_circle(double x, double y, double R)

void add_text(double x, double y, char *txt)

int load_dwg(char *filename)

  unsigned int i;

  int success;

  Dwg_Data dwg;

  dwg.num_objects = 0;

  success = dwg_read_file(filename, &amp;dwg);

  for (i = 0; i &lt; dwg.num_objects; i++)

    {

      Dwg_Entity_LINE *line;

      Dwg_Entity_CIRCLE *circle;

      Dwg_Entity_TEXT *text;

      switch (dwg.object[i].type)

        {

      case DWG_TYPE_LINE:

        line = dwg.object[i].tio.entity-&gt;tio.LINE;

        add_line(line-&gt;start.x, line-&gt;end.x, line-&gt;start.y, line-&gt;end.y);

        break;

      case DWG_TYPE_CIRCLE:

        circle = dwg.object[i].tio.entity-&gt;tio.CIRCLE;

        add_circle(circle-&gt;center.x, circle-&gt;center.y, circle-&gt;radius);

      case DWG_TYPE_TEXT:

        text = dwg.object[i].tio.entity-&gt;tio.TEXT;

        add_text(text-&gt;insertion_pt.x, text-&gt;insertion_pt.y, text-&gt;text_value);

        }

    }

  dwg_free(&amp;dwg);

  return success;

int main (int argc, char *argv[])

  REQUIRE_INPUT_FILE_ARG (argc);

  load_dwg (argv[1]);

  return 0;

因為Libredwg用的C程式設計風格,沒有定義導出定義宏,是以決定将Libredwg編譯成靜态庫libredwg.lib,然後使用其頭檔案及這個靜态庫的方式來在程式中使用Libredwg庫。

經過測試,若DWG中隻有簡單的線和圓等簡單實體,Libredwg還是可以正确讀取出。但是若用rewrite的例子來測試寫DWG的功能,簡單的執行個體如一個圓的資料都會寫出到DWG失敗,看樣子寫的功能還沒有完全實作好。

3.DWG to OCC

基于上面的例子程式,結合Libredwg的讀取功能,将DWG中的幾何資料導出成Tcl腳本,這樣就可以友善在OpenCASCADE的Draw Test Harness中來測試結果了。下面給出具體的程式執行個體及如何在Draw Test Harness中來使用生成的Tcl腳本。

*    Copyright (c) 2014 eryar All Rights Reserved.

*

*        File    : Main.cpp

*        Author  : [email protected]

*        Date    : 2014-10-15 20:46

*        Version : 1.0v

*    Description : Use libredwg to read data from DWG and

*                  output them to Tcl script for Draw.

*      Key words : OpenCASCADE, libredwg, Draw Test Harness

*/

#include "dwg.h"

#include &lt;fstream&gt;

#include &lt;iostream&gt;

#pragma comment(lib, "../Debug/libredwg.lib")

// Output the entities to Tcl for OpenCASCADE Draw.

static std::ofstream theTclExporter("d:/dwg2occ.tcl");

void OutputLine(int id, const Dwg_Entity_LINE* theLine)

    // Draw Tcl command: vline name xa ya za xb yb zb

    theTclExporter &lt;&lt; "vline line" &lt;&lt; id &lt;&lt; " " 

        &lt;&lt; theLine-&gt;start.x &lt;&lt; " " &lt;&lt; theLine-&gt;start.y &lt;&lt; " " &lt;&lt; theLine-&gt;start.z &lt;&lt; " " 

        &lt;&lt; theLine-&gt;end.x &lt;&lt; " " &lt;&lt; theLine-&gt;end.y &lt;&lt; " " &lt;&lt; theLine-&gt;end.z &lt;&lt; std::endl;

void OutputCircle(int id, const Dwg_Entity_CIRCLE* theCircle)

    // Draw Tcl command: circle name x y [z [dx dy dz]] [ux uy [uz]] radius

    // 1. make a curve

    theTclExporter &lt;&lt; "circle circle" &lt;&lt; id &lt;&lt; " "

        &lt;&lt; theCircle-&gt;center.x &lt;&lt; " " &lt;&lt; theCircle-&gt;center.y &lt;&lt; " " &lt;&lt; theCircle-&gt;center.z &lt;&lt; " " 

        &lt;&lt; "0 0 1 " &lt;&lt; theCircle-&gt;radius &lt;&lt; std::endl;

    // 2. make edge from the circle

    theTclExporter &lt;&lt; "mkedge e" &lt;&lt; id &lt;&lt; " "

        &lt;&lt; "circle" &lt;&lt; id &lt;&lt; std::endl;

    // 3. display the circle edge

    theTclExporter &lt;&lt; "vdisplay e" &lt;&lt; id &lt;&lt; std::endl;

void OutputText(int id, const Dwg_Entity_TEXT* theText)

    // vdrawtext : vdrawtext  : vdrawtext name X Y Z R G B hor_align ver_align angle zoomable height Aspect [Font [isMultiByte]]

    theTclExporter &lt;&lt; "vdrawtext " &lt;&lt; theText-&gt;text_value &lt;&lt; " "

        &lt;&lt; theText-&gt;insertion_pt.x &lt;&lt; " " &lt;&lt; theText-&gt;insertion_pt.y &lt;&lt; " 0" 

        &lt;&lt; " 255 255 000 " 

        &lt;&lt; theText-&gt;horiz_alignment &lt;&lt; " " &lt;&lt; theText-&gt;vert_alignment &lt;&lt; " " 

        &lt;&lt; theText-&gt;height &lt;&lt; " 1 Times-Roman"&lt;&lt; std::endl;

int LoadDwg(char* theDwgFile)

    int aResult = 0;

    Dwg_Data aDwgData;

    aResult = dwg_read_file(theDwgFile, &amp;aDwgData);

    for (unsigned int i = 0; i &lt; aDwgData.num_objects; ++i)

        switch (aDwgData.object[i].type)

        case DWG_TYPE_LINE:

            OutputLine(i, aDwgData.object[i].tio.entity-&gt;tio.LINE);

            break;

        case DWG_TYPE_CIRCLE:

            OutputCircle(i, aDwgData.object[i].tio.entity-&gt;tio.CIRCLE);

        case DWG_TYPE_TEXT:

            OutputText(i, aDwgData.object[i].tio.entity-&gt;tio.TEXT);

    return aResult;

int main(int argc, char* argv[])

    theTclExporter.flags(std::ios::fixed);

    theTclExporter &lt;&lt; "pload ALL" &lt;&lt; std::endl;

    theTclExporter &lt;&lt; "vinit" &lt;&lt; std::endl;

    theTclExporter &lt;&lt; "vtrihedron tr" &lt;&lt; std::endl;

    if (argc &lt; 1)

        std::cout &lt;&lt; "please input the dwg file name!" &lt;&lt; std::endl;

    else

        LoadDwg(argv[1]);

    theTclExporter &lt;&lt; "vdisplayall" &lt;&lt; std::endl;

    theTclExporter &lt;&lt; "vfit" &lt;&lt; std::endl;

    theTclExporter &lt;&lt; "vhelp" &lt;&lt; std::endl;

    return 0;

将生成的dwg2occ.tcl在OpenCASCADE的Draw Test Harness中顯示如下所示:

OpenCASCADE DataExchange DWG

Figure 3.1 Import the Tcl script in the Draw Test Hanress of OpenCASCADE

OpenCASCADE DataExchange DWG

Figure 3.2 Enitites in the DWG file

OpenCASCADE DataExchange DWG

Figure 3.3 Entities in the Draw Test Harness of OpenCASCADE

通過對比發現,直線和圓已經正确讀出,但是文字沒有讀出來。看來Libredwg的可靠性還有待提高啊。

4.Conclusion

通過使用Libredwg來讀取DWG格式中幾何資料,并将其轉換成OpenCASCADE的Draw Test Harness中能執行的Tcl腳本,以友善測試libredwg讀取資料的正确性。

通過簡單測試發現,libredwg能讀取直線和圓,但是文字内容沒有正确讀出,看來libredwg的可靠性還有待提高,但是發現這個開源庫的更新很緩慢。

5. References

3. OpenCASCADE Test Harness User’s Guide 6.7.1

繼續閱讀