/* * DXFExporter.java * * Created on March 29, 2005, 11:32 PM */ package ika.geoexport; import java.io.*; import java.awt.geom.*; import java.util.*; import ika.geo.*; /** * Exports a GeoSet to a Autocad DXF file. * @author Bernhard Jenny, Institute of Cartography, ETH Zurich. */ public class DXFExporter extends GeoSetExporter { private GeoSet geoSet; private PrintWriter writer; private double south; private double west; public DXFExporter(){ } public String getFileFormatName(){ return "DXF"; } public String getFileExtension() { return "dxf"; } protected void write(GeoSet geoSet, OutputStream outputStream) throws IOException { this.writer = new PrintWriter(new BufferedWriter( new OutputStreamWriter(outputStream))); this.geoSet = geoSet; Rectangle2D bounds = geoSet.getBounds2D(GeoObject.UNDEFINED_SCALE); this.west = bounds.getMinX(); this.south = bounds.getMinY(); this.writeLines(); } private void writeLines() { if (geoSet.getNumberOfChildren() == 0) throw new IllegalArgumentException(); final int numberOfLayers = geoSet.getNumberOfSubSetsInTree(); writeDXFHeader(); writeDXFTables(numberOfLayers); writeDXFBlocks(); writeDXFEntities(); writeDXFEnd(); writer.flush(); } private void writeDXFHeader() { Rectangle2D bounds = geoSet.getBounds2D(GeoObject.UNDEFINED_SCALE); code(0); value("SECTION"); code(2); value("HEADER"); // Version 10 of the dxf specs code(9); value("$ACADVER"); code(1); value("AC1006"); // Insertion base set by BASE command (in WCS) code(9); value("$INSBASE"); code(10); value(0.0); code(20); value(0.0); code(30); value(0.0); // south west minimum: X, Y, and Z drawing extents lower-left corner (in WCS) code(9); value("$EXTMIN"); code(10); value(bounds.getMinX()); code(20); value(bounds.getMinY()); code(30); value(0.0); // maximum north west code(9); value("$EXTMAX"); code(10); value(bounds.getMaxX()); code(20); value(bounds.getMaxY()); code(30); value(0.0); // XY drawing limits lover-left corner (in WCS) code(9); value("$LINMIN"); code(10); value(bounds.getMinX()); code(20); value(bounds.getMinY()); code(30); value(0.0); // XY drawing limits upper-right corner (in WCS) code(9); value("$LINMAX"); code(10); value(bounds.getMaxX()); code(20); value(bounds.getMaxY()); code(30); value(0.0); code(0); value("ENDSEC"); } private void writeDXFTables(int numberOfLayers) { code(0); value("SECTION"); code(2); value("TABLES"); // line type table /* code(0); // start of table value("TABLE"); code(2); // table name value("LTYPE"); code(70); // number of entries in table value(1); code(0); // table entry (same name as table) value("LTYPE"); code(2); // name of table entry value("CONTINUOUS"); code(70); // flags relevant to the table entry value(64); code(3); // descriptive text for linetype value("Solid line"); code(72); // alignment code value(65); code(73); // number of dash length items value(0); code(40); // total pattern length value("0.000000"); code(0); // end of table value("ENDTAB"); */ // layer table code(0); // start of table value("TABLE"); code(2); // table name value("LAYER"); code(70); // number of entries in table value(numberOfLayers); for (int i = 1; i <= numberOfLayers; i++) { code(0); // table entry (same name as table) value("LAYER"); code(2); // name of table entry valueAsString(i); code(70); // flags relevant to the table entry. // The 1 bit is set in the 70 group flags if the layer is frozen value(0); code(62); // color number value(i); code(6); // linetype name value("CONTINUOUS"); } code(0); // end of table value("ENDTAB"); /* // style table code(0); // start of table value("TABLE"); code(2); // table name value("STYLE"); code(70); // number of entries in table value(0); code(0); // end of table value("ENDTAB"); */ code(0); value("ENDSEC"); } private void writeDXFBlocks() { code(0); value("SECTION"); code(2); value("BLOCKS"); code(0); value("ENDSEC"); } private void writeDXFEntities() { code(0); value("SECTION"); code(2); value("ENTITIES"); writeLines(this.geoSet); code(0); value("ENDSEC"); } private void writeDXFEnd() { code(0); value("EOF"); } private void writePolyline(Vector vector, int layerID, int lineWidth) { if (vector.size() == 0) return; code(0); // entity type value("POLYLINE"); code(8); // name of the layer valueAsString(layerID); code(39); // Thickness (if nonzero) value(lineWidth); code(70); // polyline flags value(0); // set to 1 if polygon is closed. code(40); // default starting width value(lineWidth); code(41); // default ending width value(lineWidth); code(66); // start vertices value(1); for (int i = 0; i < vector.size(); i++) { double[] point = (double[])vector.get(i); code(0); value("VERTEX"); code(70); // vertex flags value(0); code(42); // bulge value(0); // 0 = straight line // coordinates code(10); value(this.transformX(point[0])); code(20); value(this.transformY(point[1])); code(30); value(0.0); } // end of vertices code(0); value("SEQEND"); } private static int layerID = 0; private static int layerIDForNewGroup() { return layerID++; } private void writeLines(GeoSet geoSet) { if (geoSet.isVisible() == false) return; final int layerID = layerIDForNewGroup(); final int lineWidth = 5; final int numberOfChildren = geoSet.getNumberOfChildren(); for (int i = 0; i < numberOfChildren; i++) { GeoObject geoObject = geoSet.getGeoObject(i); // only write visible objects if (geoObject.isVisible() == false) continue; if (geoObject instanceof GeoPath) { GeoPath geoPath = (GeoPath)geoObject; PathIterator iterator = geoPath.toPathIterator(null, this.bezierConversionTolerance); double [] coords = new double [6]; java.util.Vector vector = new java.util.Vector(); while (!iterator.isDone()) { final int type = iterator.currentSegment(coords); switch (type) { case PathIterator.SEG_CLOSE: double[] firstPoint = (double[])vector.firstElement(); vector.add(new double[] {firstPoint[0], firstPoint[1]}); writePolyline(vector, layerID, lineWidth); vector.clear(); break; case PathIterator.SEG_MOVETO: writePolyline(vector, layerID, lineWidth); vector.clear(); // fall through case PathIterator.SEG_LINETO: vector.add(new double[] {coords[0], coords[1]}); break; } iterator.next(); } writePolyline(vector, layerID, lineWidth); } else if (geoObject instanceof GeoSet) { GeoSet childGeoSet = (GeoSet)geoObject; writeLines(childGeoSet); } } } private void code(int code) { this.writer.println(code); } private void valueAsString(int value) { this.writer.println(value); } private void value(int value) { this.writer.print(" "); this.writer.println(value); } private void value(double value) { this.writer.print(" "); this.writer.println(value); } private void value(String value) { this.writer.println(value); } private double transformX(double x) { return x; // return (x - this.west) * exportMapScale; !!! ??? } private double transformY(double y) { return y; // return (y - this.south) * exportMapScale; !!! ??? } }