/** @file DrawingSvg.java * * @author marco corvi * @date mar 2013 * * @brief TopoDroid drawing: dxf export * -------------------------------------------------------- * Copyright This sowftare is distributed under GPL-3.0 or later * See the file COPYING. * -------------------------------------------------------- */ package com.topodroid.DistoX; import java.util.Locale; import java.util.List; // import java.util.ArrayList; import java.util.HashMap; import java.util.Locale; // import java.io.FileWriter; import java.io.StringWriter; import java.io.PrintWriter; import java.io.BufferedWriter; import java.io.IOException; // import android.util.Log; class DrawingSvg { private static final float grad2rad = TDMath.GRAD2RAD; private static void printSvgGrid( BufferedWriter out, List<DrawingPath> grid, String color, float opacity, float xoff, float yoff ) { if ( grid != null && grid.size() > 0 ) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); pw.format(Locale.US, "<g style=\"fill:none;stroke-opacity:%.1f;stroke-width=\"1\";stroke:#666666\" >\n", opacity ); for ( DrawingPath p : grid ) { pw.format(Locale.US, " <path stroke-width=\"1\" stroke=\"#%s\" d=\"", color ); pw.format(Locale.US, "M %.2f %.2f", xoff+p.x1, yoff+p.y1 ); pw.format(Locale.US, " L %.2f %.2f", xoff+p.x2, yoff+p.y2 ); pw.format("\" />\n"); } pw.format("</g>\n"); try { out.write( sw.getBuffer().toString() ); out.flush(); } catch ( IOException e ) { TDLog.Error( "SVG grid io-exception " + e.getMessage() ); } } } static void write( BufferedWriter out, DistoXNum num, DrawingCommandManager plot, long type ) { String wall_group = BrushManager.getLineGroup( BrushManager.mLineLib.mLineWallIndex ); int handle = 0; float xmin=10000f, xmax=-10000f, ymin=10000f, ymax=-10000f; for ( ICanvasCommand cmd : plot.getCommands() ) { if ( cmd.commandType() != 0 ) continue; DrawingPath p = (DrawingPath)cmd; if ( p.mType == DrawingPath.DRAWING_PATH_LINE ) { DrawingLinePath lp = (DrawingLinePath)p; String group = BrushManager.getLineGroup( lp.lineType() ); if ( group != null && group.equals( wall_group ) ) { // ArrayList< LinePoint > pts = lp.mPoints; // for ( LinePoint pt : pts ) for ( LinePoint pt = lp.mFirst; pt != null; pt = pt.mNext ) { if ( pt.mX < xmin ) xmin = pt.mX; if ( pt.mX > xmax ) xmax = pt.mX; if ( pt.mY < ymin ) ymin = pt.mY; if ( pt.mY > ymax ) ymax = pt.mY; } } } else if ( p.mType == DrawingPath.DRAWING_PATH_POINT ) { DrawingPointPath pp = (DrawingPointPath)p; if ( pp.cx < xmin ) xmin = pp.cx; if ( pp.cx > xmax ) xmax = pp.cx; if ( pp.cy < ymin ) ymin = pp.cy; if ( pp.cy > ymax ) ymax = pp.cy; } else if ( p.mType == DrawingPath.DRAWING_PATH_STATION ) { DrawingStationPath st = (DrawingStationPath)p; if ( st.cx < xmin ) xmin = st.cx; if ( st.cx > xmax ) xmax = st.cx; if ( st.cy < ymin ) ymin = st.cy; if ( st.cy > ymax ) ymax = st.cy; } } int width = (int)(xmax - xmin) + 200; int height = (int)(ymax - ymin) + 200; float xoff = 100 + xmin; float yoff = 100 + ymin; try { // SVG_IN_HTML // out.write("<html>\n<body>\n"); // header out.write( "<svg width=\"" + width + "\" height=\"" + height + "\"\n" ); out.write( " xmlns:svg=\"http://www.w3.org/2000/svg\"\n"); out.write( " xmlns=\"http://www.w3.org/2000/svg\" >\n" ); out.write( "<!-- SVG created by TopoDroid v. " + TopoDroidApp.VERSION + " -->\n" ); out.write( " <defs>\n"); out.write( " <marker id=\"Triangle\" viewBox=\"0 0 10 10\" refX=\"0\" refY=\"5\" \n"); out.write( " markerUnits=\"strokeWidth\" markerWidth=\"4\" markerHeight=\"3\" orient=\"auto\" >\n"); out.write( " <path d=\"M 0 0 L 10 5 L 0 10 z\" />\n"); out.write( " </marker>\n"); out.write( " </defs>\n"); // out.write( "<g transform=\"translate(" + (int)( 100 + ((xmin < 0)? -xmin : 0) ) + "," // + (int)( 100 + ((ymin < 0)? -ymin : 0) ) + ")\" >\n" ); out.write( "<g>\n"); // ***** FIXME TODO POINT SYMBOLS // { // // // 8 layer (0), 2 block name, // for ( int n = 0; n < BrushManager.mPointLib.mSymbolNr; ++ n ) { // SymbolPoint pt = (SymbolPoint)BrushManager.mPointLib.getSymbolByIndex(n); // int block = 1+n; // block_name = 1 + therion_code // writeString( out, 8, "POINT" ); // writeComment( out, pt.mName ); // writeInt( out, 2, block ); // writeInt( out, 70, 64 ); // writeString( out, 10, "0.0" ); // writeString( out, 20, "0.0" ); // writeString( out, 30, "0.0" ); // out.write( pt.getDxf() ); // } // } { float SCALE_FIX = DrawingUtil.SCALE_FIX; // centerline data if ( PlotInfo.isSketch2D( type ) ) { if ( TDSetting.mSvgGrid ) { printSvgGrid( out, plot.GetGrid1(), "999999", 0.4f, xoff, yoff ); printSvgGrid( out, plot.GetGrid10(), "666666", 0.6f, xoff, yoff ); printSvgGrid( out, plot.GetGrid100(), "333333", 0.8f, xoff, yoff ); } // FIXME OK PROFILE out.write("<g style=\"fill:none;stroke-opacity:0.6;stroke:red\" >\n"); for ( DrawingPath sh : plot.getLegs() ) { DistoXDBlock blk = sh.mBlock; if ( blk == null ) continue; StringWriter sw4 = new StringWriter(); PrintWriter pw4 = new PrintWriter(sw4); // if ( sh.mType == DrawingPath.DRAWING_PATH_FIXED ) { NumStation f = num.getStation( blk.mFrom ); NumStation t = num.getStation( blk.mTo ); pw4.format(" <path stroke-width=\"1\" stroke=\"black\" d=\""); if ( type == PlotInfo.PLOT_PLAN ) { float x = xoff + DrawingUtil.toSceneX( f.e ); float y = yoff + DrawingUtil.toSceneY( f.s ); float x1 = xoff + DrawingUtil.toSceneX( t.e ); float y1 = yoff + DrawingUtil.toSceneY( t.s ); pw4.format(Locale.US, "M %.2f %.2f L %.2f %.2f\" />\n", x, y, x1, y1 ); } else if ( PlotInfo.isProfile( type ) ) { // FIXME OK PROFILE float x = xoff + DrawingUtil.toSceneX( f.h ); float y = yoff + DrawingUtil.toSceneY( f.v ); float x1 = xoff + DrawingUtil.toSceneX( t.h ); float y1 = yoff + DrawingUtil.toSceneY( t.v ); pw4.format(Locale.US, "M %.2f %.2f L %.2f %.2f\" />\n", x, y, x1, y1 ); } // } out.write( sw4.getBuffer().toString() ); out.flush(); } for ( DrawingPath sh : plot.getSplays() ) { DistoXDBlock blk = sh.mBlock; if ( blk == null ) continue; StringWriter sw41 = new StringWriter(); PrintWriter pw41 = new PrintWriter(sw41); // if ( sh.mType == DrawingPath.DRAWING_PATH_SPLAY ) { NumStation f = num.getStation( blk.mFrom ); pw41.format(" <path stroke-width=\"1\" stroke=\"grey\" d=\""); float dh = blk.mLength * (float)Math.cos( blk.mClino * grad2rad )*SCALE_FIX; if ( type == PlotInfo.PLOT_PLAN ) { float x = xoff + DrawingUtil.toSceneX( f.e ); float y = yoff + DrawingUtil.toSceneY( f.s ); float de = dh * (float)Math.sin( blk.mBearing * grad2rad); float ds = - dh * (float)Math.cos( blk.mBearing * grad2rad); pw41.format(Locale.US, "M %.2f %.2f L %.2f %.2f\" />\n", x, y, x + de, (y+ds) ); } else if ( PlotInfo.isProfile( type ) ) { // FIXME OK PROFILE float x = xoff + DrawingUtil.toSceneX( f.h ); float y = yoff + DrawingUtil.toSceneY( f.v ); float dv = - blk.mLength * (float)Math.sin( blk.mClino * grad2rad )*SCALE_FIX; pw41.format(Locale.US, "M %.2f %.2f L %.2f %.2f\" />\n", x, y, x+dh*blk.mExtend, (y+dv) ); } // } out.write( sw41.getBuffer().toString() ); out.flush(); } out.write("</g>\n"); } // FIXME station scale is 0.3 float POINT_SCALE = 10.0f; for ( ICanvasCommand cmd : plot.getCommands() ) { if ( cmd.commandType() != 0 ) continue; DrawingPath path = (DrawingPath)cmd; int color = path.color(); int red = ( color >> 16 ) & 0xff; int grn = ( color >> 8 ) & 0xff; int blu = ( color ) & 0xff; String color_str = String.format( "#%02x%02x%02x", red, grn, blu ); if ( red > 0xcc && grn > 0xcc && blu > 0xcc ) color_str = "#cccccc"; // cut-off white StringWriter sw5 = new StringWriter(); PrintWriter pw5 = new PrintWriter(sw5); if ( path.mType == DrawingPath.DRAWING_PATH_STATION ) { DrawingStationPath st = (DrawingStationPath)path; pw5.format("<text font-size=\"20\" font=\"sans-serif\" fill=\"black\" stroke=\"none\" text-amchor=\"middle\""); pw5.format(Locale.US, " x=\"%.2f\" y=\"%.2f\">", xoff + st.cx, yoff + st.cy ); pw5.format("%s</text>\n", st.mName ); } else if ( path.mType == DrawingPath.DRAWING_PATH_LINE ) { DrawingLinePath line = (DrawingLinePath) path; String th_name = BrushManager.mLineLib.getSymbolThName( line.mLineType ); pw5.format(" <path stroke=\"%s\" stroke-width=\"2\" fill=\"none\" class=\"%s\"", color_str, th_name ); if ( th_name.equals( "arrow" ) ) pw5.format(" marker-end=\"url(#Triangle)\""); else if ( th_name.equals( "section" ) ) pw5.format(" stroke-dasharray=\"5 3 \""); else if ( th_name.equals( "fault" ) ) pw5.format(" stroke-dasharray=\"8 4 \""); else if ( th_name.equals( "floor-meander" ) ) pw5.format(" stroke-dasharray=\"6 2 \""); else if ( th_name.equals( "ceiling-meander" ) ) pw5.format(" stroke-dasharray=\"6 2 \""); pw5.format(" d=\""); LinePoint p = line.mFirst; pw5.format(Locale.US, "M %.2f %.2f", xoff+p.mX, yoff+p.mY ); for ( p = p.mNext; p != null; p = p.mNext ) { pw5.format(Locale.US, " L %.2f %.2f", xoff+p.mX, yoff+p.mY ); } pw5.format("\" />\n"); } else if ( path.mType == DrawingPath.DRAWING_PATH_AREA ) { DrawingAreaPath area = (DrawingAreaPath) path; pw5.format(" <path stroke=\"black\" stroke-width=\"1\" fill=\"%s\" fill-opacity=\"0.5\" d=\"", color_str ); LinePoint p = area.mFirst; pw5.format(Locale.US, "M %.2f %.2f", xoff+p.mX, yoff+p.mY ); for ( p = p.mNext; p != null; p = p.mNext ) { pw5.format(Locale.US, " L %.2f %.2f", xoff+p.mX, yoff+p.mY ); } pw5.format(" Z\" />\n"); } else if ( path.mType == DrawingPath.DRAWING_PATH_POINT ) { // FIXME point scale factor is 0.3 DrawingPointPath point = (DrawingPointPath) path; int idx = point.mPointType; String name = BrushManager.mPointLib.getSymbolThName( idx ); pw5.format("<!-- point %s -->\n", name ); if ( name.equals("label") ) { DrawingLabelPath label = (DrawingLabelPath)point; pw5.format(Locale.US, "<text x=\"%.2f\" y=\"%.2f\" ", xoff+point.cx, yoff+point.cy ); pw5.format(" style=\"fill:black;stroke:black;stroke-width:0.3\">%s</text>\n", label.mText ); // } else if ( name.equals("continuation") ) { // pw5.format(Locale.US, "<text x=\"%.2f\" y=\"%.2f\" ", xoff+point.cx, yoff+point.cy ); // pw5.format(" style=\"fill:none;stroke:black;stroke-width:0.3\">\?</text>\n" ); // } else if ( name.equals("danger") ) { // pw5.format(Locale.US, "<text x=\"%.2f\" y=\"%.2f\" ", xoff+point.cx, yoff+point.cy ); // pw5.format(" style=\"fill:none;stroke:red;stroke-width:0.3\">!</text>\n" ); } else { SymbolPoint sp = (SymbolPoint)BrushManager.mPointLib.getSymbolByIndex( idx ); if ( sp != null ) { pw5.format(Locale.US, "<g transform=\"translate(%.2f,%.2f),scale(10),rotate(%.2f)\" \n", xoff+point.cx, yoff+point.cy, point.mOrientation ); pw5.format(" style=\"fill:none;stroke:%s;stroke-width:0.1\" >\n", color_str ); pw5.format("%s\n", sp.mSvg ); pw5.format("</g>\n"); } else { pw5.format(Locale.US, "<circle cx=\"%.2f\" cy=\"%.2f\" r=\"10\" ", xoff+point.cx, yoff+point.cy ); pw5.format(" style=\"fill:none;stroke:black;stroke-width:0.1\" />\n"); } } } out.write( sw5.getBuffer().toString() ); out.flush(); } } out.write("</g>\n"); out.write("</svg>\n"); // SVG_IN_HTML // out.write("</body></html>\n"); out.flush(); } catch ( IOException e ) { // FIXME TDLog.Error( "SVG io-exception " + e.getMessage() ); } } }