Introduction
This project mainly deals with reading a DXF file, but in order to demonstrate the reader is working I also included a viewer, which interprets the data and draw it on the screen. In fact, at the beginning my sole purpose was to extract data from a DXF file but later on interpretation and drawing of the data on the screen started to take much more time and shaded the priority of the data extraction. After all of these, here is the result.
Background
There are a couple of DXF writer projects here in CodeProject (one is from Omid Shahabi, the other is from Claude Gagnon), but I couldn't find a DXF reader which reads DXF files. After various scans through the net, I came across the DXF specification of the AutoCAD and I decided to make my own reader. But then I found out that a reader by itself will have no value, there should also be a viewer. And the project become partially a DXF reader and mainly a viewer program, and I also made a drawing editor. However, the only interaction that the editor presents to the user is to highlight the shapes (to highlight keep shift button pressed while moving the cursor)... all drawings are made by the software. (I'll try to provide details later on.)
General Structure
DXF File |
→ |
DXF Reader |
+ |
Interpretation |
→ |
Viewer |
→ |
Screen |
Well, as you can see, the structure is as above. The data is extracted from the DXF file and interpreted and then necessary methods of the viewer are called and the result is shown on the screen.
Although the intended structure is as above, the code itself is not separated this much.
The application is an MDI application. You can open multiple DXF files for viewing.
There is a Canvas
class for drawing and a Shape
class for defining objects. Currently Line
, Polyline
, Circle
and Arc
shapes of the AutoCAD
can be recognized. In the near future, I'm planning to add B-Spline too.
DXF Interpretation methods are included in the canvas
class. Separating these methods from the drawing methods would be much better but for now this is all I can present.
Methods
When you click File/Open, the following method will be called:
private void menuItem2_Click(object sender, System.EventArgs e) {
inputFileTxt = "";
openFileDialog1.InitialDirectory = "c:\\ "; openFileDialog1.Filter = "DXF files (*.dxf)|*.dxf|All files (*.*)|*.*" ; openFileDialog1.FilterIndex = 1 ;
if (openFileDialog1.ShowDialog() ==
System.Windows.Forms.DialogResult.OK) {
inputFileTxt = openFileDialog1.FileName;
int ino = inputFileTxt.LastIndexOf("\\ ");
newCanvas = new Canvas(); newCanvas.MdiParent = this; newCanvas.Text = inputFileTxt.Substring
(ino+1, inputFileTxt.Length - ino - 1); newCanvas.MinimumSize = new Size (500, 400);
if(inputFileTxt.Length > 0)
{
newCanvas.ReadFromFile(inputFileTxt); }
newCanvas.Show(); newCanvas.Activate();
newCanvas.Focus();
}
openFileDialog1.Dispose();
}
As mentioned above, DXF interpretation is made in the Canvas
class. Canvas
class is a Windows Form. In addition to the standard namespaces, the following namespaces are included:
using System.IO;
using System.Drawing.Drawing2D;
using System.Data;
The ReadFromFile(string filename)
method of the Canvas
deals with extracting data from the DXF file and forwarding data to the necessary drawing methods:
public void ReadFromFile (string textFile) {
string line1, line2;
line1 = "0"; line2 = "0";
long position = 0;
theSourceFile = new FileInfo (textFile); StreamReader reader = null;
try
{
reader = theSourceFile.OpenText(); }
catch (FileNotFoundException e)
{
MessageBox.Show(e.FileName.ToString() + " cannot be found");
}
catch
{
MessageBox.Show("An error occurred while opening the DXF file");
return;
}
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); } while (line2 != "EOF");
reader.DiscardBufferedData(); theSourceFile = null;
reader.Close(); }
Let me explain a little bit about the structure of a DXF file. In DXF files (they can be opened in Notepad), the data is stored in two-line (bi-line, dual, coupling, whatever you call it) structures. The first line contains a kind of an identifier (or a Tag) and the second line contains the data value. So in order to interpret a DXF file, we must interpret lines two-by-two.
Depending on this dual structure, we can interpret all entities that reside in a DXF file. But currently only LINE
, LWPOLYLINE
, CIRCLE
and ARC
entities can be recognizable. For the near future, I'm planning to add BSPLINE
.
I provided plenty of comments in the source code, so please look in the source code itself for explanation of the modules.
DXF Viewer
Viewer part contains much more coding than the reader. As I mentioned above, currently I can draw a limited number of shapes. I hope to expand it in the near future.
While developing the Viewer, I got lots of ideas and knowledge from CodeProject. It varies from double buffering techniques to making a GradientBackground
.
In the beginning, I said that the viewer is an MDI application. In this way, you can open multiple DXF files to view. After opening a file, if you click on the "Window" button in the main menu, you can see a list of the opened windows.
To make this, add a menu item to the main menu, and then in its properties find MdiList
and change its value to "true
".
I made the gradient background with overriding OnPaintBackground
event:
protected override void OnPaintBackground
(System.Windows.Forms.PaintEventArgs e) {
base.OnPaintBackground(e);
...
Graphics g = e.Graphics;
Rectangle rect = new Rectangle(this.pictureBox1.Location, this.pictureBox1.Size);
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); Draw(g); }
brush.Dispose();
}
Conclusion
The main purpose of this project is to demonstrate that the DXF files can be read with the above mentioned techniques. In fact, the viewer part has a secondary priority at the beginning. Later on, I paid some attention to it, but I cannot claim that the viewer is composed of the best practices.
The compressed file for the demo application has the executable file and two sample DXF files. One of the DXF files is the one that can be seen in the screenshot. The drawing seems to be 3-D, but it is not. It is drawn in 2D...
Please feel free to send feedback.
History
- 8th September, 2005: Added main version
- 8th September, 2005: Updated source code and demo application to solve the decimal symbol conflict