FAQ
Cover
This is the archive Discourse for the Processing (ALPHA) software.
Please visit the new Processing forum for current information.

   Processing 1.0 _ALPHA_
   Topics & Contributions
   Tools
(Moderator: REAS)
   DXF File exporter
« Previous topic | Next topic »

Pages: 1 2 
   Author  Topic: DXF File exporter  (Read 3355 times)
simong

Email
DXF File exporter
« on: Oct 15th, 2003, 2:17pm »

Hi. I've written a little hack to export Processing graphics as 3D DXF files, which can be read into AutoCad, 3D Studio, Rhino, etc.
 
It's geometry-only, and it will all come out as a mesh of triangles, but it works. It will export all triangle-based graphics: polygons, rects, boxes, spheres, but not lines or raster graphics like images, text, movies, etc. It's ugly in that it uses undocumented internal structures of BGraphics, which are subject to change, but it works on 65 Alpha.
 
There are three calls of note:
1) DXFinit(); // Must be the first line of setup.
2) DXFloop(); // Should be the first line of loop.
3) DXFwrite(String fileName); // Call at the end of your drawing stuff, but DON'T CALL IT IN LOOP WITHOUT PROTECTING IT FROM EXECUTING EVERY TIME. Probably good to put it on a key trigger or something.
 
Here's an example app:
 
http://www.architecture.yale.edu/872a/processingExamples/DXFWriter/
 
Code:

// Demonstrates the use of DXF exporter for Processing graphics.
// Works with Processing 65 Alpha. Untested with other versions.
// 10.14.03 Simon Greenwold (simong@media.mit.edu)
 
void setup() {
  DXFinit();  // Must be first line of setup().
  size(200,200);
}
 
void loop() {
  DXFloop();   // Must be first line of loop().
 
 
  // Any kind of graphics calls you want go here.
  // Note that pixels, lines, images, movies, and text
  // will not be exported to DXF.
  // Only rectangles, triangles, polygons, boxes, spheres, etc.
  triangle(1, 2, 40, 50, 20, 2);
  rect(10, 10, 45, 60);
  translate(width/2, height/2);
  rotateX(PI/8);
  rotateZ(PI/6);
  box(40);
  scale(2, 1, 3);
  translate(20, 30, 40);
  sphere(10);
 
 
  // If the 'w' key is pressed, write the file.  
  if (keyPressed && key == 'w') {
    DXFwrite("Tester.dxf");  // Should appear at the end of loop().
  }
}
 
//--------- DXFwrite --------------------
// Writes all current triangle-based graphics
// (polygons, boxes, spheres, etc.) to a DXF file.
// Call this at the end of your loop (after everything has drawn).
// But be sure to put a condition like a keypress on it!
// You don't want it running over and over in a loop.
// File will appear in the same folder as the
// Processing executable.
 
void DXFwrite(String fileName) {
  java.util.ArrayList text = new java.util.ArrayList(100);
  DXFheader(text);
  DXFgraphics(text);
  DXFfooter(text);
  saveStrings(fileName, (String[])text.toArray(new String[0]));
  println("DXF file \"" + fileName + "\" written with " + g.triangles_count + " triangles.");
}
 
//--------- DXFinit --------------------
// Should be called as the first line of setup()
// Makes sure that graphics are drawn in a way that
// the writer can use.
void DXFinit() {
  hint(NEW_GRAPHICS);
  lights();
}
 
//--------- DXFloop --------------------
// Should be called as the first line of loop()
// It makes sure that all triangles are done in 3D
void DXFloop() {
  rotateX(PI/8);
  rotateX(-PI/8);
}
 
// DXFwrite utility functions below. Do not use.
void DXFheader(java.util.ArrayList text) {
  text.add("0");
  text.add("SECTION");
  text.add("2");
  text.add("ENTITIES");
}
 
void DXFfooter(java.util.ArrayList text) {
  text.add("0");
  text.add("ENDSEC");
  text.add("0");
  text.add("EOF");
}
 
void DXFgraphics(java.util.ArrayList text) {
  float a[];
  float b[];
  float c[];
  for (int i = 0; i < g.triangles_count; i++) {
    a = g.vertices[g.triangles[i][0]];
    b = g.vertices[g.triangles[i][1]];
    c = g.vertices[g.triangles[i][2]];
 
    if (a[VW] != 0.0 && b[VW] != 0.0 && c[VW] != 0.0) {
 text.add("0");
 text.add("3DFACE");
 text.add("8");
 text.add("0");
 
 text.add("10");
 text.add(Float.toString(a[VX]/a[VW]));
 text.add("20");
 text.add(Float.toString(a[VY]/a[VW]));
 text.add("30");
 text.add(Float.toString(a[VZ]/a[VW]));
 text.add("11");
 text.add(Float.toString(b[VX]/b[VW]));
 text.add("21");
 text.add(Float.toString(b[VY]/b[VW]));
 text.add("31");
 text.add(Float.toString(b[VZ]/b[VW]));
 text.add("12");
 text.add(Float.toString(c[VX]/c[VW]));
 text.add("22");
 text.add(Float.toString(c[VY]/c[VW]));
 text.add("32");
 text.add(Float.toString(c[VZ]/c[VW]));
 text.add("13");
 text.add(Float.toString(c[VX]/c[VW]));
 text.add("23");
 text.add(Float.toString(c[VY]/c[VW]));
 text.add("33");
 text.add(Float.toString(c[VZ]/c[VW]));
    }
  }
}

 
Let me know how it works for you,
-Simon
 
simong

Email
An improvement...
« Reply #1 on: Oct 20th, 2003, 4:54am »

I've improved this slightly so that you can export things to different layers, which lets you manipulate them independently in your 3D program. Here's a link to a short tutorial on using it:
 
http://www.architecture.yale.edu/872a/assignment5/dxfWriter.html
 
And here is the code:
 
Code:

//--------- DXFwrite --------------------
// Writes all current triangle-based graphics
// (polygons, boxes, spheres, etc.) to a DXF file.
// Call this at the end of your loop (after everything has drawn).
// But be sure to put a condition like a keypress on it!
// You don't want it running over and over in a loop.
// File will appear in the same folder as the
// Processing executable.
 
void DXFwrite(String fileName) {
  java.util.ArrayList text = new java.util.ArrayList(100);
  DXFheader(text);
  DXFgraphics(text);
  DXFfooter(text);
  saveStrings(fileName, (String[])text.toArray(new String[0]));
  println("DXF file \"" + fileName + "\" written with " + g.triangles_count + " triangles.");
}
 
final int MAX_TRI_LAYERS = 100000;
final int DXF_NO_LAYER = -1;
int currentDXFLayer = 0;
int[] DXFLayerList = new int[MAX_TRI_LAYERS];
 
//--------- DXFinit --------------------
// Should be called as the first line of setup()
// Makes sure that graphics are drawn in a way that
// the writer can use.
void DXFinit() {
  hint(NEW_GRAPHICS);
  lights();
}
 
//--------- DXFloop --------------------
// Should be called as the first line of loop()
// It makes sure that all triangles are done in 3D
void DXFloop() {
  rotateX(PI/8);
  rotateX(-PI/8);
  for (int i = 0; i < MAX_TRI_LAYERS; i++) {
    DXFLayerList[i] = DXF_NO_LAYER;
  }
  DXFlayer(0);
}
 
// DXFwrite utility functions below. Do not use.
void DXFheader(java.util.ArrayList text) {
  text.add("0");
  text.add("SECTION");
  text.add("2");
  text.add("ENTITIES");
}
 
void DXFfooter(java.util.ArrayList text) {
  text.add("0");
  text.add("ENDSEC");
  text.add("0");
  text.add("EOF");
}
 
 
 
void DXFlayer(int layer) {
  currentDXFLayer = layer;
 
  if (g.triangles_count >= MAX_TRI_LAYERS) {
    return;
  }
  DXFLayerList[g.triangles_count] = currentDXFLayer;
 
}
 
void DXFgraphics(java.util.ArrayList text) {
  float a[];
  float b[];
  float c[];
 
  currentDXFLayer = 0;
   
  for (int i = 0; i < g.triangles_count; i++) {
    a = g.vertices[g.triangles[i][0]];
    b = g.vertices[g.triangles[i][1]];
    c = g.vertices[g.triangles[i][2]];
 
    if (a[VW] != 0.0 && b[VW] != 0.0 && c[VW] != 0.0) {
 text.add("0");
 text.add("3DFACE");
 text.add("8");
 
 if (i < MAX_TRI_LAYERS) {
   if (DXFLayerList[i] >= 0) {
     currentDXFLayer = DXFLayerList[i];
   }
 }
 text.add(Integer.toString(currentDXFLayer));
 
 text.add("10");
 text.add(Float.toString(a[VX]/a[VW]));
 text.add("20");
 text.add(Float.toString(a[VY]/a[VW]));
 text.add("30");
 text.add(Float.toString(a[VZ]/a[VW]));
 text.add("11");
 text.add(Float.toString(b[VX]/b[VW]));
 text.add("21");
 text.add(Float.toString(b[VY]/b[VW]));
 text.add("31");
 text.add(Float.toString(b[VZ]/b[VW]));
 text.add("12");
 text.add(Float.toString(c[VX]/c[VW]));
 text.add("22");
 text.add(Float.toString(c[VY]/c[VW]));
 text.add("32");
 text.add(Float.toString(c[VZ]/c[VW]));
 text.add("13");
 text.add(Float.toString(c[VX]/c[VW]));
 text.add("23");
 text.add(Float.toString(c[VY]/c[VW]));
 text.add("33");
 text.add(Float.toString(c[VZ]/c[VW]));
    }
  }
}

 
Enjoy!
-Simon
 
REAS


WWW
Re: DXF File exporter
« Reply #2 on: Oct 23rd, 2003, 11:31pm »

This is exciting. I'm going to post it on the "tutorials" section of the site:
http://www.proce55ing.net/learning/tutorials/index.html
 
I'd love to see the results of people using this.
 
SeanC
Guest
Email
Re: DXF File exporter
« Reply #3 on: Oct 26th, 2003, 1:46am »

Is there any way to add in vector curves?  It would be amazing if that could be exported in .dxf format.
 
simong

Email
Re: DXF File exporter
« Reply #4 on: Oct 27th, 2003, 3:03am »

Here's an example from someone in my class:
 
http://www.architecture.yale.edu/872a/students/Malaika/mk_sks/HW5/031022 _planarb/applet/index.html
 
REAS


WWW
Re: DXF File exporter
« Reply #5 on: Oct 27th, 2003, 3:51am »

I'm a rendering dummy. What environment was this project imported into and rendered. How do you distinguish different areas of the model to give them different materials and colors?
 
REAS


WWW
Re: DXF File exporter
« Reply #6 on: Oct 27th, 2003, 4:14am »

Simon,  
 
FYI. There is some aspect of your DXF code which in not compatible with the Java 1.1 syntax. It's not possible to view the applets with the default JVM included with many browsers.
 
+ Casey
 
 
mflux

fluxhavoc WWW
Re: DXF File exporter
« Reply #7 on: Oct 29th, 2003, 10:14am »

It's probably  
 
  text.add("0");  
  text.add("SECTION");  
  text.add("2");  
  text.add("ENTITIES");
 
That's breaking. Current processing versions are having trouble with the java vector class when you use add.  
 
Try using text.addElement("blah"); That should fix it.
 
simong

Email
Re: DXF File exporter
« Reply #8 on: Oct 29th, 2003, 10:45pm »

Thanks for the addElement fix. That'll probably do it.
 
As for the environment, I'm not sure what she brought it into. My favorite is Rhino, but that's not free. Blender is free but it's hard to learn. Basically there's nothing out there that can't read a DXF.
 
You separate objects from each other by calling DXFLayer(layerNum); after each call to this, any new drawing will occur on layerNum until you call it again with a different layer. So you separate your meshes by layer.
 
Let me know if it works for you,
-Simon
 
REAS


WWW
Re: DXF File exporter
« Reply #9 on: Oct 30th, 2003, 8:23pm »

ah, thank you for the info.
 
simong

Email
A vast improvement...
« Reply #10 on: Nov 2nd, 2003, 2:28pm »

This is a much improved version. It is faster and will not run out of memory. It also now works with JVM 1.1 browsers.
 
Here is an example app:
http://www.architecture.yale.edu/872a/processingExamples/DXFWriter/
 
Code:
 //--------- DXFwrite --------------------
  // Writes all current triangle-based graphics
  // (polygons, boxes, spheres, etc.) to a DXF file.
  // Call this at the end of your loop (after everything has drawn).
  // But be sure to put a condition like a keypress on it!
  // You don't want it running over and over in a loop.
  // File will appear in the same folder as the
  // Processing executable.
 
  void DXFwrite(String fileName) {
    try {
 BufferedWriter fileWriter = new BufferedWriter(new FileWriter(fileName));
 DXFheader(fileWriter);
 DXFgraphics(fileWriter);
 DXFfooter(fileWriter);
 fileWriter.close();
    }
    catch (IOException e) {
 e.printStackTrace();  //To change body of catch statement use Options | File Templates.
 return;
    }
    //saveStrings(fileName, (String[])text.toArray(new String[0]));
    println("DXF file \"" + fileName + "\" written with " + g.triangles_count + " triangles.");
  }
 
  final int MAX_TRI_LAYERS = 500000;
  final int DXF_NO_LAYER = -1;
  int currentDXFLayer = 0;
  int[] DXFLayerList = new int[MAX_TRI_LAYERS];
 
  //--------- DXFinit --------------------
  // Should be called as the first line of setup()
  // Makes sure that graphics are drawn in a way that
  // the writer can use.
  void DXFinit() {
    hint(NEW_GRAPHICS);
    lights();
  }
 
  //--------- DXFloop --------------------
  // Should be called as the first line of loop()
  // It makes sure that all triangles are done in 3D
  void DXFloop() {
    rotateX(PI/8);
    rotateX(-PI/8);
    for (int i = 0; i < MAX_TRI_LAYERS; i++) {
 DXFLayerList[i] = DXF_NO_LAYER;
    }
    DXFlayer(0);
  }
 
  // DXFwrite utility functions below. Do not use.
  private void DXFheader(BufferedWriter writer) throws IOException {
    writer.write("0");
    writer.newLine();
    writer.write("SECTION");
    writer.newLine();
    writer.write("2");
    writer.newLine();
    writer.write("ENTITIES");
    writer.newLine();
  }
 
  private void DXFfooter(BufferedWriter writer) throws IOException {
    writer.write("0");
    writer.newLine();
    writer.write("ENDSEC");
    writer.newLine();
    writer.write("0");
    writer.newLine();
    writer.write("EOF");
    writer.newLine();
  }
 
 
 
  void DXFlayer(int layer) {
    currentDXFLayer = layer;
 
    if (g.triangles_count >= MAX_TRI_LAYERS) {
 return;
    }
    DXFLayerList[g.triangles_count] = currentDXFLayer;
 
  }
 
  private void DXFgraphics(BufferedWriter writer) throws IOException {
    float a[];
    float b[];
    float c[];
 
    currentDXFLayer = 0;
 
    for (int i = 0; i < g.triangles_count; i++) {
 a = g.vertices[g.triangles[i][0]];
 b = g.vertices[g.triangles[i][1]];
 c = g.vertices[g.triangles[i][2]];
 
 if (a[VW] != 0.0 && b[VW] != 0.0 && c[VW] != 0.0) {
   writer.write("0");
   writer.newLine();
   writer.write("3DFACE");
   writer.newLine();
   writer.write("8");
   writer.newLine();
 
   if (i < MAX_TRI_LAYERS) {
     if (DXFLayerList[i] >= 0) {
  currentDXFLayer = DXFLayerList[i];
     }
   }
   writer.write(Integer.toString(currentDXFLayer));
   writer.newLine();
 
   writer.write("10");
   writer.newLine();
   writer.write(Float.toString(a[VX]/a[VW]));
   writer.newLine();
   writer.write("20");
   writer.newLine();
   writer.write(Float.toString(a[VY]/a[VW]));
   writer.newLine();
   writer.write("30");
   writer.newLine();
   writer.write(Float.toString(a[VZ]/a[VW]));
   writer.newLine();
   writer.write("11");
   writer.newLine();
   writer.write(Float.toString(b[VX]/b[VW]));
   writer.newLine();
   writer.write("21");
   writer.newLine();
   writer.write(Float.toString(b[VY]/b[VW]));
   writer.newLine();
   writer.write("31");
   writer.newLine();
   writer.write(Float.toString(b[VZ]/b[VW]));
   writer.newLine();
   writer.write("12");
   writer.newLine();
   writer.write(Float.toString(c[VX]/c[VW]));
   writer.newLine();
   writer.write("22");
   writer.newLine();
   writer.write(Float.toString(c[VY]/c[VW]));
   writer.newLine();
   writer.write("32");
   writer.newLine();
   writer.write(Float.toString(c[VZ]/c[VW]));
   writer.newLine();
   writer.write("13");
   writer.newLine();
   writer.write(Float.toString(c[VX]/c[VW]));
   writer.newLine();
   writer.write("23");
   writer.newLine();
   writer.write(Float.toString(c[VY]/c[VW]));
   writer.newLine();
   writer.write("33");
   writer.newLine();
   writer.write(Float.toString(c[VZ]/c[VW]));
   writer.newLine();
 }
    }
  }
 
fry

WWW
Re: DXF File exporter
« Reply #11 on: Nov 3rd, 2003, 6:17pm »

you oughta be able to put a PrintWriter around that BufferedWriter (or instead of it?) and just use println() and print() instead of having to call newLine() each time.
 
simong

Email
Re: DXF File exporter
« Reply #12 on: Nov 8th, 2003, 5:22pm »

Sho nuff. This is better:
 
Code:
  //--------- DXFwrite --------------------
   // Writes all current triangle-based graphics
   // (polygons, boxes, spheres, etc.) to a DXF file.
   // Call this at the end of your loop (after everything has drawn).
   // But be sure to put a condition like a keypress on it!
   // You don't want it running over and over in a loop.
   // File will appear in the same folder as the
   // Processing executable.
 
   void DXFwrite(String fileName) {
 try {
    PrintWriter fileWriter = new PrintWriter(new BufferedWriter(new FileWriter(fileName)));
    DXFheader(fileWriter);
    DXFgraphics(fileWriter);
    DXFfooter(fileWriter);
    fileWriter.close();
 }
 catch (IOException e) {
    e.printStackTrace();  //To change body of catch statement use Options | File Templates.
    return;
 }
 //saveStrings(fileName, (String[])text.toArray(new String[0]));
 println("DXF file \"" + fileName + "\" written with " + g.triangles_count + " triangles.");
   }
 
   final int MAX_TRI_LAYERS = 500000;
   final int DXF_NO_LAYER = -1;
   int currentDXFLayer = 0;
   int[] DXFLayerList = new int[MAX_TRI_LAYERS];
 
   //--------- DXFinit --------------------
   // Should be called as the first line of setup()
   // Makes sure that graphics are drawn in a way that
   // the writer can use.
   void DXFinit() {
 hint(NEW_GRAPHICS);
 lights();
   }
 
   //--------- DXFloop --------------------
   // Should be called as the first line of loop()
   // It makes sure that all triangles are done in 3D
   void DXFloop() {
 rotateX(PI/8);
 rotateX(-PI/8);
 for (int i = 0; i < MAX_TRI_LAYERS; i++) {
    DXFLayerList[i] = DXF_NO_LAYER;
 }
 DXFlayer(0);
   }
 
   // DXFwrite utility functions below. Do not use.
   private void DXFheader(PrintWriter writer) throws IOException {
 writer.println("0");
 writer.println("SECTION");
 writer.println("2");
 writer.println("ENTITIES");
   }
 
   private void DXFfooter(PrintWriter writer) throws IOException {
 writer.println("0");
 writer.println("ENDSEC");
 writer.println("0");
 writer.println("EOF");
   }
 
 
 
   void DXFlayer(int layer) {
 currentDXFLayer = layer;
 
 if (g.triangles_count >= MAX_TRI_LAYERS) {
    return;
 }
 DXFLayerList[g.triangles_count] = currentDXFLayer;
 
   }
 
   private void DXFgraphics(PrintWriter writer) throws IOException {
 float a[];
 float b[];
 float c[];
 
 currentDXFLayer = 0;
 
 for (int i = 0; i < g.triangles_count; i++) {
    a = g.vertices[g.triangles[i][0]];
    b = g.vertices[g.triangles[i][1]];
    c = g.vertices[g.triangles[i][2]];
 
    if (a[VW] != 0.0 && b[VW] != 0.0 && c[VW] != 0.0) {
  writer.println("0");
  writer.println("3DFACE");
  writer.println("8");
 
  if (i < MAX_TRI_LAYERS) {
     if (DXFLayerList[i] >= 0) {
   currentDXFLayer = DXFLayerList[i];
     }
  }
  writer.println(Integer.toString(currentDXFLayer));
 
  writer.println("10");
  writer.println(Float.toString(a[VX]/a[VW]));
  writer.println("20");
  writer.println(Float.toString(a[VY]/a[VW]));
  writer.println("30");
  writer.println(Float.toString(a[VZ]/a[VW]));
  writer.println("11");
  writer.println(Float.toString(b[VX]/b[VW]));
  writer.println("21");
  writer.println(Float.toString(b[VY]/b[VW]));
  writer.println("31");
  writer.println(Float.toString(b[VZ]/b[VW]));
  writer.println("12");
  writer.println(Float.toString(c[VX]/c[VW]));
  writer.println("22");
  writer.println(Float.toString(c[VY]/c[VW]));
  writer.println("32");
  writer.println(Float.toString(c[VZ]/c[VW]));
  writer.println("13");
  writer.println(Float.toString(c[VX]/c[VW]));
  writer.println("23");
  writer.println(Float.toString(c[VY]/c[VW]));
  writer.println("33");
  writer.println(Float.toString(c[VZ]/c[VW]));
    }
 }
 
fry

WWW
Re: DXF File exporter
« Reply #13 on: Nov 8th, 2003, 6:15pm »

and another tiny that might be useful.. nf() is a number-formatting replacement for Float.toString() or similar methods. i use it when generating illustrator files to make sure it doesn't produce too many decimals and hork the file (ai can't take more than 4 digits.. though you may want more digits accuracy for dxf..)
 
so writer.println(Float.toString(c[VZ]/c[VW]));  
 
becomes writer.println(nf(c[VZ]/c[VW], 0, 4));
 
the zero means not to set a specific # of digits on the lefthand side of the decimal, and the 4 means 4 digits to the right of the decimal place.
 
cheewee2000

WWW Email
Re: DXF File exporter
« Reply #14 on: Oct 25th, 2004, 12:36am »

How do I get the DXF file exporter to export to a specific location on the server when the file is played as an applet on the web?
 
Pages: 1 2 

« Previous topic | Next topic »