视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
读取、识别、显示DXF格式文件源码
2025-09-25 17:42:28 责编:小OO
文档
问题的提出和解决方案

Software development in industry, building and many other fields requires working with CAD drawings. The most popular CAD formats are AutoCAD DWG and AutoCAD DXF, the latter being "simplified" dwg - a special format to be used by developers. The problem is that DXF and DWG formats are really complicated. They have dozens of objects with hundreds of interaction tricks and thousands of properties. Official DXF Reference from Autodesk has 256 pages though it fails to describe many important facts. Hence, the development for CAD drawings is often required but is not easy to implement. This article is to tell you how to write the DXF reader in C#, what problems can arise and of course you can find example in C# source code, which is free for use under MPL license. 

DXF 结构

DXF is an open ASCII format from Autodesk and you can easily find documentation on it in the web. Here are some words about it. Below is a very simple example, to show the main parts: 

Hide   Copy Code

  0 

SECTION

  2

ENTITIES

  0

LINE

 10

39.199********317

 20

36.4554281665769

 30

0.0

 11

39.199********322

 21

736.4554281665768

 31

0.0

  0

ENDSEC

  0

EOF

0 - introduction of extended symbol names, following the "0" 

SECTION, ENDSEC - begin / end of section. Sections can include Header, Entities, Objects. In the above code, you see only Entities section where the entities are. 

LINE - begins LINE entity description. Lines: 

Hide   Copy Code

10 

39.19953392043317 

mean X1 double value. The value after 20 is Y1, after 30 - Z1 (0 in 2D drawings). 11, 21 and 31 codes are consequently for X2, Y2, Z2. So here we see the line with coordinates (39.19.., 36, 45.. - 39,19.., 736,45..) - this is vertical line. 

So our aim is to read this ASCII format. We need to load the file to stream and to take lines - even lines (0, 2, 4..) are CODE, odd lines (1, 3, 5...) are VALUE and repeat this procedure step by step till the end of file "EOF". 

Hide   Shrink   Copy Code

// take a pair of lines in DXF file, repeat this till "EOF":

public void Next()

{

  FCode = Convert.ToInt32(FStream.ReadLine()); //code

  FValue = FStream.ReadLine(); // value

}

// for code=0 we create entities. Entities here are not only those which visible in AutoCAD.

// Entities can be also names of Sections and many other internal DXF objects.

// This method is called for all FCode == 0

public DXFEntity CreateEntity()

{

  DXFEntity E;

  switch (FValue)

  {

    case "ENDSEC":

      return null;   // here we do not create entity

    case "ENDBLK":

      return null;

    case "ENDTAB":

      return null;

    case "LINE":    // for "LINE" value we create DXFLine object

      E = new DXFLine();

      break;

    case "SECTION": // "SECTION" will be object to store other objects like Line

      E = new DXFSection();

      break;

    case "BLOCK": // create block object

      E = new DXFBlock();

      break;

    case "INSERT": // insert is reference to block.

      E = new DXFInsert();

      break;

    case "TABLE":

      E = new DXFTable();

      break;

    case "CIRCLE":

      E = new DXFCircle();

      break;

    case "LAYER":

      E = new DXFLayer();

      break;

    case "TEXT":

      E = new DXFText();

      break;

    case "MTEXT":

      E = new DXFMText();

      break;

    case "ARC":

      E = new DXFArc();

      break;

    case "ELLIPSE":

      E = new DXFEllipse();

      break;

    default: // there are many other objects are possible. For them we create empty Entity

      E = new DXFEntity();

      break;

  }

  // each Entity will need reference to the Base object Converter, which stores all Entities.

  E.Converter = this;

  return E; // return Entity and after it is added to the array of Entities

}  

The method to read properties of entities is essentially similar to the one described above but it has one important point: different entities have both identical and different properties. For instance, many Entities have "base point" - in DXF, which is described by codes: 10 (x), 20 (y), 30(z): 

Hide   Copy Code

LINE

 10

39.199********317

 20

36.4554281665769

 30

0.0 

These codes are the same for LINE, CIRCLE, ELLIPSE, TEXT and for many others. So we can make Object-Oriented structure to read and to store the properties in order to avoid double-coding. We will store Layer and Base Point in entity "DXFVisibleEntity" which will be ancestor for all visible entities. Look at the code to read these properties: 

Hide   Shrink   Copy Code

//base class for all visible entities

public class DXFVisibleEntity : DXFEntity

{

//Base point (x, y, z) for all entities

  public DXFImport.SFPoint Point1 = new SFPoint();

  // virtual function ReadProperty() is overridden in all descendants of Entity to read

  //specific properties

  public override void ReadProperty()

  {

  // for the different codes we read values

    switch (Converter.FCode)

    {

        //read Layer

      case 8:

        layer = Converter.LayerByName(Converter.FValue);

        break;

        //read Coordinates

      case 10: //X

        Point1.X = Convert.ToSingle(Converter.FValue, Converter.N);

        break;

      case 20: //Y

        Point1.Y = Convert.ToSingle(Converter.FValue, Converter.N);

        break;

        //read Color

      case 62:

        FColor = CADImage.IntToColor(Convert.ToInt32(Converter.FValue, Converter.N));

        break;

    }

  }

We use the same approach to read the second coordinate in LINE, radius in Circle and so on. 

DXF File and DXF Import .NET Structure 

This scheme shows main parts of DXF file and the way they are connected with the C# source code in the project. The dash lines stand for associations between DXF file objects and objects, programmed in C#. 

CADImage is a class for loading from DXF file and drawing to Graphics. It stores the DXF Entities in field:

Hide   Copy Code

public DXFSection FEntities;  

In the scheme, it is DXFSection. 

DXFEntity is base class for all Entities classes. Classes DXFBlocks and DXFSection are not visible. Class DXFVisibleEntity is the ancestor for all visible Entities. 

By the way, the scheme above is made in DXF format in ABViewer software. 

CAD Tricks 

If you are not familiar with AutoCAD, please pay attention to the structure of DXF entities. There is a special entity "Block" which may have many "inserts" in the CAD drawing. Block is just set of entities (including nested blocks) which can be inserted many times.

Note 

Hide   Copy Code

Block changes many properties of element when showing it. 

So if you want to know the color of entity, it is not enough to read  

"Entity.Color"  - it is necessary to see all the Inserts and Blocks, 

in which this entity can be included. To get the correct color in DXF Import 

.NET project we made the following function: EntColor(DXFEntity E, DXFInsert Ins).

Please use EntColor() function get the correct Color type even if you do not have Blocks in the file. Pay attention that the most common color is "ByLayer" and in order to read the correct color, we need to read the color from Layer entity. This functionality is also provided in this function. 

Below is the EntColor function. It has many tricks, for instance checking the layer.name == "0" - in DXF layer "0" is special and elements with color "ByLayer" get the color from Block if they are on "0" layer. 

Hide   Shrink   Copy Code

//Use this func to know the color of Entity, DXFInsert is Insert entity or null. 

public static Color EntColor(DXFEntity E, DXFInsert Ins)

{

  DXFInsert vIns = Ins;

  DXFEntity Ent = E;

  Color Result = DXFConst.clNone;

  if(Ent is DXFVisibleEntity) Result = E.FColor;

  /*if(Ent is Polyline)

    Result = ((Polyline)Ent).Pen.Pen.Color;*/

  if(E.layer == null) return  Result; 

/* algorithm is rather difficult here. This is the way, how AutoCAD works with the colors,

if you try to create entities in AutoCAD, you will see how they use Colors */ 

  if((Result ==  clByLayer)||(Result == clByBlock))

  {

    if((vIns == null)||((Result == clByLayer)&&(Ent.layer.name != "0")))

    {

      if(Result == clByLayer)

      {

        if(Ent.layer.color != clNone)

          Result = Ent.layer.color;

        else Result = Color.Black;

      }

    }

    else

    {

      while(vIns != null)

      {

        Result = vIns.color;

        if((Result !=  clByBlock) && !((Result ==  clByLayer) &&

          (vIns.layer.name == "0")))

        {

          if(Result ==  clByLayer)

            Result = vIns.layer.color;

          break;

        }

        if((vIns.owner == null)&&(Result == clByLayer))

          Result = vIns.layer.color;

        vIns = vIns.owner;

      }

    }

  }

  if((Result == clByLayer)||(Result == clByBlock))

    Result = clNone;

  return Result;

}

How to Use the Software 

The main code is in DXFImport.cs. You can just use this file in your project or see to it as an example of reading and visualization of DXF files. 

Sample code to use DXFImport.cs is Form1.cs. 

How to View Entities 

In Form1.cs, we use the Form1_Paint event: 

Hide   Copy Code

private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)

{

 //FCADImage - base class to reference to DXF

  if (FCADImage == null)

    return;

  FCADImage.Draw(e.Graphics); // CADImage.Draw() accepts Graphics to draw to

}

We can use FCADImage.Draw() for drawing to any Graphics - for instance, to printer. FCADImage.Draw() function should use a special algorithm, when each entity is drawn with the use of block/insert/layer parameters. 

Hide   Copy Code

public void Draw(Graphics e)

{

  if (FMain == null)

    return;

  FGraphics = e;

  // Iterate begins to  over the entities to draw all of them

  FEntities.Iterate(new CADEntityProc(DrawEntity), FParams);

}

Pay attention to FEntities.Iterate() func, it allows accessing all entities including their being inside the blocks. This is how it works: There is a class DXFGroup which is an ancestor of Entity and which can store array of Entities. For instance, Block is ancestor of DXFGroup and can store many entities like LINE. For better unification, we can use ONE BASE GROUP ENTITY object for all the drawing, this Entity will have array of all entities, each of them can also be the Group - the classic "Tree". 

Iterate method finally should call Draw() for each Entity in order to draw it to the Graphics:

Hide   Copy Code

    protected static void DrawEntity(DXFEntity Ent)

        {

            Ent.Draw(FGraphics);

        } 

Draw() method is overridden in descendants of Entity to draw particular entities. Let us see in detail how it is implemented in DXFLine: 

Hide   Copy Code

// draw line

public override void Draw(System.Drawing.Graphics G)

  {

    // points P1  (x1, y1) and P2 (x2, y2) of Line

    SFPoint P1, P2;

    // read color via EntColor to get real color

    Color RealColor = DXFConst.EntColor(this, Converter.FParams.Insert);

    // Read point 1 -convert global coordinates to the screen coordinates:

    P1 = Converter.GetPoint(Point1);

    //read point 2

    P2 = Converter.GetPoint(Point2);

    if (FVisible)

      G.DrawLine(new Pen(RealColor, 1),  P1.X, P1.Y, P2.X, P2.Y);

  } 

1.We get the Real Color via DXFConst.EntColor(this, Converter.FParams.Insert); as I described before.

2.Points are converted from Global Coordinates to screen coordinates in function GetPoint(). GetPoint not only converts global-to-screen but also uses Block offsets and block scale inside. Thus it facilitates the development work, eliminating the need to "see" what block is being drawn at the moment - Block changes "FParams.matrix" to draw itself. And all entities coordinates use this "FParams.matrix".

3.Entity is drawn to the given Graphics G: 

So you can draw to printer, to raster image or to other Graphics.

DXF Import .NET Reference

Hide   Copy Code

public class DXFConst 

Stores constants and base functions.

Hide   Copy Code

public class DXFMatrix 

Class to work with coordinates.

Hide   Copy Code

public struct FRect 

Description of 3D space where the CAD drawing is situated in global coordinates.

Hide   Copy Code

public struct CADIterate

Stores all needed parameters for entities when processing "Iterate" function.

Hide   Copy Code

public class CADImage 

Class to draw CAD drawing.

Hide   Copy Code

public class DXFEntity 

Base class for all DXF Entities.

Hide   Copy Code

public class DXFGroup : DXFEntity

Base class for all group entities.

Hide   Copy Code

public class DXFTable : DXFGroup 

Class to read from DXF "Table" section - here it reads only Layers.

Hide   Copy Code

public class DXFVisibleEntity : DXFEntity

Base class for all visible entities (invisible - are "DXFTable", "DXFLayer", etc.)

Hide   Copy Code

public class DXFCustomVertex: DXFVisibleEntity 

Special class for 3D point in DXF.

Hide   Copy Code

public class DXFText: DXFCustomVertex

Stores and Draws "Text" DXF entity.

The following classes are for particular DXF entities:

Hide   Copy Code

public class DXFLine : DXFVisibleEntity

public class DXFArc: DXFCircle

public class DXFEllipse: DXFArc

public class DXFLayer: DXFEntity

Hide   Copy Code

public class DXFBlock : DXFGroup

Class to work with DXF Block. 

Hide   Copy Code

public class DXFInsert : DXFVisibleEntity  

Class to work with "Insert" in DXF, for AutoCAD users this is "Block reference". Blocks are not visible, Inserts are visible. 

Conclusion 

The purpose of the article is to give some advice how to write DXF readers. DXF file structure is not so difficult as its logical presentation. The article looks through the base DXF format problems and shows how to find solution for them. The example source is written in C# and may be helpful for all who need to have access to DXF files. 下载本文

显示全文
专题