As part of an ongoing project at Watershed we needed to be able export .dxf natively from an openFrameworks application. While oF has the ability to export numerous file formats such as .obj, .ply, .xml and others with specific addon libraries, the ability to export .dxf is missing. So we decided to build our own addon that granted us this ability.
Quickly for those who might not be familiar with dxf. DXF stands for Drawing eXchange Format which is an industry standard graphical image used with the majority of AutoCAD applications. The file stores three dimensional coordinates that are read and converted into polylines by AutoCAD programs.
A dxf file usually contains the following data structures:
- HEADER
- CLASSES
- TABLES
- BLOCKS
- ENTITIES
- OBJECTS
- THUMBNAILIMAGE
While standard dxf files usually contain three dimensional structures (ie polylines with x,y,z coordinates). Our addon (so far) only generates two dimensional structures, as the files will be used with laser cutting software to produce custom objects.
This post will explain how the addon saves data from an oF application into a dxf file.
In the ofxDxfExport.h we have the following methods.
#include <iostream> #include <fstream> #include "ofMain.h" class ofxDxfExport { public: ofxDxfExport(); ofFile os; void writeFile(string path); void addPoints(vector <ofVec3f> pts,bool endSection); void endFile(); private: void writeHOF(); void writeTable(); void writeBlock(); void writeDictionary(); void writeEOF(); };
The private methods contain no alterable attributes that affect the exported file. So cannot be called outside the ofxDxfExport.cpp file.
The process starts by calling
void writeFile(string path){ } in which the addon opens a file and assigns it a name defined by the user. The addon then generates the above structures. And
#include "ofxDxfExport.h" //-------------------------------------------------------------- void ofxDxfExport::writeFile(string path) { os.open(path+".dxf",ofFile::WriteOnly); writeHOF(); writeTable(); writeBlock(); ofSystemAlertDialog("DXF " + path + " Created"); }
Up until this point the addon has been using predefined data to generate the structures. To add data we call the
void ofxDxfExport::addPoints(vector pts, bool endSection){ } method which copies the users points and pushes them into a loop. The method ensures the list of points that is being added contains something, if points are found then the addon writes the following data to the os file.
void ofxDxfExport::addPoints(vector pts, bool endSection) { if (pts.size() > 0) { os << "LWPOLYLINE" << endl; os << "5" << endl; os << "100" << endl; os << "100" << endl; os << "AcDbEntity" << endl; os << "8" << endl; os << "0" << endl; os << "62" << endl; os << "7" << endl; os << "100" << endl; os << "AcDbPolyline" << endl; os << "90" << endl; os << pts.size() << endl; // Our point size os << "70" << endl; os << "0" << endl;
In dxf the coordinate layout is different to standard formats such as SVG which is simply <polyline x coord y coord | x coord y coord |> . The addon loops through the pts and inserts the values between the other necessary data.
for(int i = 0; i < pts.size(); i++) { os << "10" << endl; os << ofToString(pts[i].x) << endl; os << "20" << endl; os << ofToString(pts[i].y) << endl; os << "30" << endl; os << "0.0" << endl; }
Once the loop has finished the addon closes Polyline entity which is holding our data.
If all data is written the entity is closed by the bool value passed with the method.
// Close the loop os << "10" << endl; os << ofToString(pts[0].x) << endl; os << "20" << endl; os << ofToString(pts[0].y) << endl; os << "30" << endl; os << "0.0" << endl; os << "0" << endl; } if (endSection == true) { os << "ENDSEC" << endl; os << "0" << endl; } else { }
To close the file
void ofxDxfExport::endFile(){ } is called which writes the close routine and section ends.
//---------------------------------------------------------------- void ofxDxfExport::endFile() { writeDictionary(); writeEOF(); }
In practice you call the writeFile -> addPoints -> endFile.
dxf.writeFile(ofToString(ofGetTimestampString())); dxf.addPoints(clickPtsLeft, false); dxf.addPoints(clickPtsRight, true); dxf.endFile();
And thats the addon.
The images below show a successful output from the addon examples.
It is worth noting that Inkscape uses a cartesian coordinate system so (0,0) is in the bottom left of the window. However, to correct this, flip the objects vertically inside Inkscape.
To download and see the source files click the link ->. Any contributions or comments are welcomed.
If you are interested in dxf and laser cutting check out Greg Borenstein’s post for Makezine, which shows you how to create a Zoetrope from Kinect images using Processing.