65.9K
CodeProject 正在变化。 阅读更多。
Home

DXF 读取器解决方案和简单的 DXF 查看器

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.68/5 (37投票s)

2005年9月8日

CPOL

4分钟阅读

viewsIcon

411998

downloadIcon

33265

该项目读取 DXF 文件,提取和解释数据并在屏幕上绘制。

screenshot.jpg

引言

该项目主要涉及读取 DXF 文件,但为了演示读取器的工作情况,我还包含了一个查看器,该查看器可以解释数据并在屏幕上绘制。事实上,一开始我的唯一目的是从 DXF 文件中提取数据,但后来在屏幕上解释和绘制数据开始花费更多时间,并掩盖了数据提取的优先级。在这一切之后,这是结果。

背景

CodeProject 上有几个 DXF 写入项目(一个是 Omid Shahabi 的,另一个是 Claude Gagnon 的),但我找不到一个读取 DXF 文件的 DXF 读取器。在对网络进行各种扫描后,我偶然发现了 AutoCAD 的 DXF 规范,并决定自己制作一个读取器。但后来我发现,仅仅一个读取器是没有价值的,还需要一个查看器。于是这个项目部分成为了一个 DXF 读取器,主要是作为一个查看器程序,我还制作了一个绘图编辑器。然而,编辑器向用户提供的唯一交互是突出显示形状(按住 Shift 键同时移动鼠标光标即可突出显示)……所有绘图均由软件完成。(稍后我将尝试提供详细信息。)

总体结构

DXF 文件 DXF 读取器 + 解释 查看器 屏幕

嗯,正如你所看到的,结构如上。数据从 DXF 文件中提取并解释,然后调用查看器所需的相应方法,结果显示在屏幕上。

虽然预期的结构如上,但代码本身并没有如此分离。

该应用程序是一个 MDI 应用程序。您可以打开多个 DXF 文件进行查看。

有一个用于绘图的 Canvas 类和一个用于定义对象的 Shape 类。目前可以识别 AutoCADLinePolylineCircleArc 形状。在不久的将来,我计划添加 B-Spline。

DXF 解释方法包含在 canvas 类中。将这些方法与绘图方法分离会更好,但目前这就是我能提供的。

方法

当您单击“文件/打开”时,将调用以下方法

private void menuItem2_Click(object sender, System.EventArgs e) //Opens openfile
						//dialog to select a DXF file
{
    inputFileTxt = "";

    openFileDialog1.InitialDirectory = "c:\\ "; //sets the initial directory of the
					//openfile dialog
    openFileDialog1.Filter = "DXF files (*.dxf)|*.dxf|All files (*.*)|*.*" ; //filters the
								//visible files...
    openFileDialog1.FilterIndex = 1 ;

    if (openFileDialog1.ShowDialog() ==
		System.Windows.Forms.DialogResult.OK) //open file dialog is shown here...
                                                         //if "cancel" button is clicked then
                                                         //nothing will be done...
    {
        inputFileTxt = openFileDialog1.FileName; //filename is taken
					//(file path is also included to this
                                                //name example: c:\windows\system\blabla.dxf

        int ino = inputFileTxt.LastIndexOf("\\ "); 	//index no. of the last "\"
						//(that is before the filename)
                                                  	//is found here

        newCanvas = new Canvas(); //a new canvas is created...
        newCanvas.MdiParent = this; //...its mdiparent is set...
        newCanvas.Text = inputFileTxt.Substring
		(ino+1, inputFileTxt.Length - ino - 1); //...filename is
                                                   //extracted from the text.(blabla.dxf).
        newCanvas.MinimumSize = new Size (500, 400); //...canvas minimum size is set...

        if(inputFileTxt.Length > 0)
        {
            newCanvas.ReadFromFile(inputFileTxt); //the filename is sent to the method
					//for data extraction and interpretation...
        }

        newCanvas.Show(); //the canvas is displayed...
        newCanvas.Activate();
        newCanvas.Focus();
    }

    openFileDialog1.Dispose();
}

如上所述,DXF 解释是在 Canvas 类中完成的。Canvas 类是一个 Windows 窗体。除了标准命名空间外,还包括以下命名空间

using System.IO;
using System.Drawing.Drawing2D;
using System.Data;

Canvas 类的 ReadFromFile(string filename) 方法负责从 DXF 文件中提取数据并将其转发给相应的绘图方法

public void ReadFromFile (string textFile) 	//Reads a text file
                                           	//(in fact a DXF file) for importing an
					//Autocad drawing.
{
    string line1, line2; //these line1 and line2 is used for getting the a/m data groups...

    line1 = "0"; //line1 and line2 are initialized here...
    line2 = "0";
    long position = 0;

    theSourceFile = new FileInfo (textFile); 	//the source file is set.
    StreamReader reader = null; 		//a reader is prepared...

    try
    {
        reader = theSourceFile.OpenText(); 	//the reader is set ...
    }
    catch (FileNotFoundException e)
    {
        MessageBox.Show(e.FileName.ToString() + " cannot be found");
    }
    catch
    {
        MessageBox.Show("An error occurred while opening the DXF file");
        return;
    }

    ////////////////////////////////////////////////////////////////////
    //This part interprets the drawing objects found in the DXF file...
    ////////////////////////////////////////////////////////////////////

    do
    {
        if (line1 == "0" && line2 == "LINE")
            LineModule(reader);
        else if (line1 == "0" && line2 == "LWPOLYLINE")
            PolylineModule(reader);
        else if (line1 == "0" && line2 == "CIRCLE")
            CircleModule(reader);
        else if (line1 == "0" && line2 == "ARC")
            ArcModule(reader);

        GetLineCouple (reader, out line1, out line2); //the related method is called
                                                      //for iterating through the text file
                                                 //and assigning values to line1 and line2...
    } while (line2 != "EOF");

    ////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////

    reader.DiscardBufferedData(); 	//reader is cleared...
    theSourceFile = null;
    reader.Close(); 		//...and closed.
}

让我稍微解释一下 DXF 文件的结构。在 DXF 文件中(可以用记事本打开),数据存储在两行(双行,双重,耦合,无论你怎么称呼它)结构中。第一行包含一种标识符(或标签),第二行包含数据值。因此,为了解释 DXF 文件,我们必须成对地解释行。

根据这种双重结构,我们可以解释 DXF 文件中存在的所有实体。但目前只能识别 LINELWPOLYLINECIRCLEARC 实体。在不久的将来,我计划添加 BSPLINE

我在源代码中提供了大量注释,所以请查看源代码本身以了解模块的说明。

DXF 查看器

查看器部分比读取器包含更多的代码。如上所述,目前我只能绘制有限数量的形状。我希望在不久的将来扩展它。

在开发查看器时,我从 CodeProject 中获得了许多想法和知识。范围从双缓冲技术到制作 GradientBackground

一开始,我说查看器是一个 MDI 应用程序。这样,您就可以打开多个 DXF 文件进行查看。打开文件后,如果单击主菜单中的“窗口”按钮,您可以看到打开的窗口列表。

要实现这一点,请向主菜单添加一个菜单项,然后在其属性中找到 MdiList 并将其值更改为“true”。

我通过重写 OnPaintBackground 事件来创建渐变背景

protected override void OnPaintBackground
(System.Windows.Forms.PaintEventArgs e) //all drawing is made here in OnPaintBackground...
{
    base.OnPaintBackground(e);    //you must pass "e" to the base method

    ...

    Graphics g = e.Graphics;
    Rectangle rect = new Rectangle(this.pictureBox1.Location, this.pictureBox1.Size);
                              //In fact the pictureBox1 is hidden, the sole purpose of it is
                              //to get its dimensions for defining the drawing area.

    System.Drawing.Drawing2D.LinearGradientBrush brush =
			new System.Drawing.Drawing2D.LinearGradientBrush(
    rect,
    Color.SteelBlue,
    Color.Black,
    System.Drawing.Drawing2D.LinearGradientMode.ForwardDiagonal);

    if (this.WindowState != FormWindowState.Minimized)
    {
        e.Graphics.FillRectangle(brush, rect); //gradient background
        Draw(g); //All drawing is made here...
    }

    brush.Dispose();
}

结论

该项目的主要目的是演示如何使用上述技术读取 DXF 文件。事实上,查看器部分在开始时是次要的。后来,我对其给予了一些关注,但我不能声称查看器是由最佳实践组成的。

演示应用程序的压缩文件包含可执行文件和两个示例 DXF 文件。其中一个 DXF 文件是屏幕截图中的那个。绘图看起来是 3D 的,但实际上不是。它是 2D 绘制的...

请随时发送反馈。

历史

  • 2005 年 9 月 8 日:添加了主版本
  • 2005 年 9 月 8 日:更新了源代码和演示应用程序以解决小数点符号冲突
© . All rights reserved.