/* @file DrawingIO.java
*
* @author marco corvi
* @date nov 2015
*
* @brief TopoDroid drawing: drawing I/O
* --------------------------------------------------------
* Copyright This sowftare is distributed under GPL-3.0 or later
* See the file COPYING.
* --------------------------------------------------------
*/
package com.topodroid.DistoX;
import java.io.File;
import java.io.FileWriter;
import java.io.FileReader;
import java.io.BufferedWriter;
import java.io.BufferedReader;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.StringWriter;
import java.io.PrintWriter;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.EOFException;
import java.util.List;
import java.util.HashMap;
import java.util.Locale;
import android.graphics.RectF;
import android.util.Log;
class DrawingIO
{
private static float toTherion = TDConst.TO_THERION;
private static float oneMeter = DrawingUtil.SCALE_FIX * toTherion;
private static String readLine( BufferedReader br )
{
String line = null;
try {
line = br.readLine();
} catch ( IOException e ) {
e.printStackTrace();
}
if ( line != null ) {
line = line.trim();
line.replaceAll(" *", " ");
// line.replaceAll("\\s+", " ");
}
return line;
}
public static boolean doLoadTherion( DrawingSurface surface,
String filename,
float dx, float dy,
SymbolsPalette missingSymbols,
SymbolsPalette localPalette )
{
float x, y, x1, y1, x2, y2;
boolean is_not_section = true;
// TDLog.Log( TDLog.LOG_PLOT, "Load Therion file " + filename + " delta " + dx + " " + dy );
// BrushManager.makePaths( );
BrushManager.resetPointOrientations();
// TDLog.Log( TDLog.LOG_PLOT, "after reset 0: " + BrushManager.mOrientation[0]
// + " 7: " + BrushManager.mOrientation[7] );
synchronized( TDPath.mTherionLock ) {
try {
FileReader fr = new FileReader( filename );
BufferedReader br = new BufferedReader( fr );
String line = null;
while ( (line = readLine(br)) != null ) {
int comment = line.indexOf('#');
if ( comment == 0 ) {
if ( line.startsWith( "#P " ) ) { // POINT PALETTE
if ( localPalette != null ) {
localPalette.mPalettePoint.clear();
localPalette.addPointFilename( "user" );
String[] syms = line.split( " " );
for ( int k=1; k<syms.length; ++k ) {
if ( syms[k].length() > 0 && ! syms[k].equals("user") ) localPalette.addPointFilename( syms[k] );
}
BrushManager.mPointLib.makeEnabledListFromPalette( localPalette );
}
} else if ( line.startsWith( "#L " ) ) { // LINE PALETTE
if ( localPalette != null ) {
localPalette.mPaletteLine.clear();
localPalette.addLineFilename("user");
String[] syms = line.split( " " );
for ( int k=1; k<syms.length; ++k ) {
if ( syms[k].length() > 0 && ! syms[k].equals("user") ) localPalette.addLineFilename( syms[k] );
}
BrushManager.mLineLib.makeEnabledListFromPalette( localPalette );
}
} else if ( line.startsWith( "#A " ) ) { // AREA PALETTE
if ( localPalette != null ) {
localPalette.mPaletteArea.clear();
localPalette.addAreaFilename("user");
String[] syms = line.split( " " );
for ( int k=1; k<syms.length; ++k ) {
if ( syms[k].length() > 0 && ! syms[k].equals("user") ) localPalette.addAreaFilename( syms[k] );
}
BrushManager.mAreaLib.makeEnabledListFromPalette( localPalette );
}
}
continue;
} else if (comment > 0 ) {
line = line.substring( 0, comment );
}
if ( line.length() == 0 /* || line.charAt(0) == '#' */ ) {
continue;
}
// TDLog.Log( TDLog.LOG_PLOT, " line: >>" + line + "<<");
line = line.replaceAll("\\s+", " ");
String[] vals = line.split( " " );
// FIXME assert( vals.length > 0 );
if ( vals[0].equals( "scrap" ) ) {
if ( vals.length < 4 ) {
TDLog.Error( "bad scrap cmd: " + line );
} else {
// String name = vals[1];
// skip "-projection" vals[2]
is_not_section = ! vals[3].equals("none");
}
} else if ( vals[0].equals( "point" ) ) {
// ****** THERION POINT ********************************** point X Y type [options]
if ( vals.length < 4 ) {
TDLog.Error( "bad point cmd: " + line );
} else {
int ptType = BrushManager.mPointLib.mSymbolNr;
boolean has_orientation = false;
float orientation = 0.0f;
int scale = DrawingPointPath.SCALE_M;
String options = null;
try {
x = dx + Float.parseFloat( vals[1] ) / TDConst.TO_THERION;
y = dy - Float.parseFloat( vals[2] ) / TDConst.TO_THERION;
} catch ( NumberFormatException e ) {
TDLog.Error( "Therion Point error (number fmt) <" + line + ">" );
continue;
}
String type = vals[3];
String label_text = null;
int k = 4;
if ( type.equals( "station" ) ) {
if ( ! TDSetting.mAutoStations ) {
if ( vals.length > k+1 && vals[k].equals( "-name" ) ) {
String name = vals[k+1];
DrawingStationPath station_path = new DrawingStationPath( name, x, y, scale );
surface.addDrawingPath( station_path );
}
}
continue;
}
while ( vals.length > k ) {
if ( vals[k].equals( "-orientation" ) ) {
try {
orientation = Float.parseFloat( vals[k+1] );
has_orientation = true;
} catch ( NumberFormatException e ) {
TDLog.Error( "Therion Point orientation error : " + line );
}
k += 2;
} else if ( vals[k].equals( "-scale" ) ) {
// FIXME assert (vals.length > k+1 );
if ( vals[k+1].equals("xs") ) {
scale = DrawingPointPath.SCALE_XS;
} else if ( vals[k+1].equals("s") ) {
scale = DrawingPointPath.SCALE_S;
} else if ( vals[k+1].equals("l") ) {
scale = DrawingPointPath.SCALE_L;
} else if ( vals[k+1].equals("xl") ) {
scale = DrawingPointPath.SCALE_XL;
}
k += 2;
} else if ( vals[k].equals( "-text" ) ) {
// FIXME assert (vals.length > k+1 );
label_text = vals[k+1];
k += 2;
if ( label_text.startsWith( "\"" ) ) {
while ( k < vals.length ) {
label_text = label_text + " " + vals[k];
if ( vals[k].endsWith( "\"" ) ) break;
++ k;
}
label_text = label_text.replaceAll( "\"", "" );
++ k;
}
} else {
options = vals[k];
++ k;
while ( vals.length > k ) {
options += " " + vals[k];
++ k;
}
}
}
BrushManager.mPointLib.tryLoadMissingPoint( type );
// map pre 3.1.1 thnames to 3.1.1 names
String thname = type;
if ( thname.equals( "user" ) ) { thname = "u:user"; }
else if ( thname.equals( "danger" ) ) { thname = "u:danger"; }
else if ( thname.equals( "archeo" ) ) { thname = "archeo-material"; }
ptType = BrushManager.mPointLib.getSymbolIndexByThName( thname );
// Log.v("DistoX", "type " + type + " thname " + thname + " " + ptType );
if ( ptType < 0 ) {
if ( missingSymbols != null ) missingSymbols.addPointFilename( type ); // add "type" to the missing point-types
ptType = 0; // SymbolPointLibrary.mPointUserIndex; // FIXME
// continue;
}
if ( ptType == BrushManager.mPointLib.mPointLabelIndex ) {
if ( label_text != null ) {
// "danger" is no longer mapped on a label
// if ( label_text.equals( "!" ) ) { // "danger" point
// DrawingPointPath path = new DrawingPointPath( BrushManager.mPointLib.mPointDangerIndex, x, y, scale, options );
// surface.addDrawingPath( path );
// } else { // regular label
DrawingLabelPath path = new DrawingLabelPath( label_text, x, y, scale, options );
if ( has_orientation ) {
path.setOrientation( orientation );
}
surface.addDrawingPath( path );
// }
}
} else if ( has_orientation && BrushManager.mPointLib.isSymbolOrientable(ptType) ) {
// TDLog.Log( TDLog.LOG_PLOT, "[2] point " + ptType + " has orientation " + orientation );
BrushManager.rotateGradPoint( ptType, orientation );
DrawingPointPath path = new DrawingPointPath( ptType, x, y, scale, options );
surface.addDrawingPath( path );
BrushManager.rotateGradPoint( ptType, -orientation );
} else {
DrawingPointPath path = new DrawingPointPath( ptType, x, y, scale, options );
surface.addDrawingPath( path );
}
}
} else if ( vals[0].equals( "line" ) ) {
// ********* THERION LINES ************************************************************
if ( vals.length < 2 ) {
TDLog.Error( "bad line cmd: " + line );
} else {
if ( vals.length >= 6 && vals[1].equals( "border" ) && vals[2].equals( "-id" ) ) { // THERION AREAS
boolean visible = true;
// TDLog.Log( TDLog.LOG_PLOT, "area id " + vals[3] );
if ( vals.length >= 8 && vals[6].equals("-visibility") && vals[7].equals("off") ) {
visible = false;
}
int arType = BrushManager.mAreaLib.mSymbolNr;
DrawingAreaPath path = new DrawingAreaPath( arType, vals[3], visible );
// TODO insert new area-path
line = readLine( br );
if ( ! line.equals( "endline" ) ) {
String[] pt = line.split( "\\s+" );
try {
x = dx + Float.parseFloat( pt[0] ) / TDConst.TO_THERION;
y = dy - Float.parseFloat( pt[1] ) / TDConst.TO_THERION;
} catch ( NumberFormatException e ) {
TDLog.Error( "Therion Line error (number fmt) <" + line + ">" );
continue;
}
path.addStartPoint( x, y );
while ( (line = readLine( br )) != null ) {
if ( line.equals( "endline" ) ) {
line = readLine( br ); // area statement
String[] vals2 = line.split( " " );
if ( vals2.length >= 2 ) {
BrushManager.mAreaLib.tryLoadMissingArea( vals2[1] );
String thname = vals2[1];
if ( thname.equals( "user" ) ) { thname = "u:user"; }
arType = BrushManager.mAreaLib.getSymbolIndexByThName( thname );
if ( arType < 0 ) {
if ( missingSymbols != null ) missingSymbols.addAreaFilename( vals2[1] );
arType = 0; // SymbolAreaLibrary.mAreaUserIndex; // FIXME
// continue;
}
// TDLog.Log(TDLog.LOG_PLOT, "set area type " + arType + " " + vals2[1]);
double orientation = 0;
if ( vals2.length >= 4 && vals2[2].equals("#orientation") ) {
try {
orientation = Double.parseDouble( vals2[3] );
} catch ( NumberFormatException e ) {
TDLog.Error( "Therion Area orientation error <" + line + ">" );
}
}
path.setAreaType( arType );
path.setOrientation( orientation );
surface.addDrawingPath( path );
}
line = readLine( br ); // skip two lines
line = readLine( br );
break;
}
// TDLog.Log( TDLog.LOG_DEBUG, " line point: >>" + line + "<<");
String[] pt2 = line.split( " " );
if ( pt2.length == 2 ) {
try {
x = dx + Float.parseFloat( pt2[0] ) / TDConst.TO_THERION;
y = dy - Float.parseFloat( pt2[1] ) / TDConst.TO_THERION;
path.addPoint( x, y );
// TDLog.Log( TDLog.LOG_DEBUG, "area pt " + x + " " + y);
} catch ( NumberFormatException e ) {
TDLog.Error( "Therion Line X-Y error (10) <" + line + ">" );
continue;
} catch ( ArrayIndexOutOfBoundsException e ) {
TDLog.Error( "Therion Line X-Y error (11) " + line );
continue;
}
} else if ( pt2.length == 6 ) {
try {
x1 = dx + Float.parseFloat( pt2[0] ) / TDConst.TO_THERION;
y1 = dy - Float.parseFloat( pt2[1] ) / TDConst.TO_THERION;
x2 = dx + Float.parseFloat( pt2[2] ) / TDConst.TO_THERION;
y2 = dy - Float.parseFloat( pt2[3] ) / TDConst.TO_THERION;
x = dx + Float.parseFloat( pt2[4] ) / TDConst.TO_THERION;
y = dy - Float.parseFloat( pt2[5] ) / TDConst.TO_THERION;
path.addPoint3( x1, y1, x2, y2, x, y );
// TDLog.Log( TDLog.LOG_DEBUG, "area pt " + x1 + " " + y1 + " " + x2 + " " + y2 + " " + x + " " + y);
} catch ( NumberFormatException e ) {
TDLog.Error( "Therion Line X-Y error (12) <" + line + ">" );
continue;
} catch ( ArrayIndexOutOfBoundsException e ) {
TDLog.Error( "Therion Line X-Y error (13) " + line );
continue;
}
}
}
}
} else { // ********* regular lines
// FIXME assert (vals.length > 1 );
// TDLog.Log( TDLog.LOG_PLOT, "line type " + vals[1] );
boolean closed = false;
boolean reversed = false;
int outline = DrawingLinePath.OUTLINE_UNDEF;
String options = null;
String type = vals[1];
for (int index = 2; index < vals.length; ++index ) {
if ( vals[index] == null || vals[index].length() == 0 ) {
continue;
}
if ( vals[index].equals( "-close" ) ) {
++ index;
if ( vals.length > index && vals[index].equals( "on" ) ) {
closed = true;
}
} else if ( vals[index].equals( "-reverse" ) ) {
++ index;
if ( vals.length > index && vals[index].equals( "on" ) ) {
reversed = true;
}
} else if ( vals[index].equals( "-outline" ) ) {
++ index;
if ( vals.length > index ) {
if ( vals[index].equals( "out" ) ) { outline = DrawingLinePath.OUTLINE_OUT; }
else if ( vals[index].equals( "in" ) ) { outline = DrawingLinePath.OUTLINE_IN; }
else if ( vals[index].equals( "none" ) ) { outline = DrawingLinePath.OUTLINE_NONE; }
}
} else {
if ( options == null ) {
options = vals[index];
} else {
options += " " + vals[index];
}
}
}
int lnTypeMax = BrushManager.mLineLib.mSymbolNr;
int lnType = lnTypeMax;
DrawingLinePath path = null;
BrushManager.mLineLib.tryLoadMissingLine( type );
String thname = type;
if ( thname.equals( "user" ) ) { thname = "u:user"; }
lnType = BrushManager.mLineLib.getSymbolIndexByThName( thname );
if ( lnType < 0 ) {
if ( missingSymbols != null ) missingSymbols.addLineFilename( type );
lnType = 0; // SymbolLineLibrary.mLineUserIndex; // FIXME
// continue;
}
// TODO insert new line-path
line = readLine( br );
if ( ! line.equals( "endline" ) ) {
path = new DrawingLinePath( lnType );
path.setClosed( closed );
path.setReversed( reversed );
if ( outline != DrawingLinePath.OUTLINE_UNDEF ) path.mOutline = outline;
if ( options != null ) path.setOptions( options );
// TDLog.Log( TDLog.LOG_PLOT, " line start point: <" + line + ">");
String[] pt0 = line.split( "\\s+" );
try {
x = dx + Float.parseFloat( pt0[0] ) / TDConst.TO_THERION;
y = dy - Float.parseFloat( pt0[1] ) / TDConst.TO_THERION;
path.addStartPoint( x, y );
} catch ( NumberFormatException e ) {
TDLog.Error( "Therion Line X-Y error (1) <" + line + ">" );
continue;
} catch ( ArrayIndexOutOfBoundsException e ) {
TDLog.Error( "Therion Line X-Y error (2) " + line );
continue;
}
// Log.v( "DistoX", " line start point: <" + line + "> " + x + " " + y );
while ( (line = readLine( br )) != null ) {
if ( line.indexOf( "l-size" ) >= 0 ) continue;
if ( line.equals( "endline" ) ) {
if ( path != null ) {
if ( type.equals("section") ) { // section line only in non-section scraps
if ( is_not_section ) {
path.makeStraight( false ); // FIXME true = with arrow
}
} else {
path.computeUnitNormal(); // for section-line already done by makeStraight
}
surface.addDrawingPath( path );
}
break;
}
if ( path != null ) {
// TDLog.Log( TDLog.LOG_PLOT, " line point: >>" + line + "<<");
String[] pt = line.split( " " );
if ( pt.length == 2 ) {
try {
x = dx + Float.parseFloat( pt[0] ) / TDConst.TO_THERION;
y = dy - Float.parseFloat( pt[1] ) / TDConst.TO_THERION;
path.addPoint( x, y );
} catch ( NumberFormatException e ) {
TDLog.Error( "Therion Line X-Y error (3) <" + line + ">" );
continue;
} catch ( ArrayIndexOutOfBoundsException e ) {
TDLog.Error( "Therion Line X-Y error (4) " + line );
continue;
}
} else if ( pt.length == 6 ) {
try {
x1 = dx + Float.parseFloat( pt[0] ) / TDConst.TO_THERION;
y1 = dy - Float.parseFloat( pt[1] ) / TDConst.TO_THERION;
x2 = dx + Float.parseFloat( pt[2] ) / TDConst.TO_THERION;
y2 = dy - Float.parseFloat( pt[3] ) / TDConst.TO_THERION;
x = dx + Float.parseFloat( pt[4] ) / TDConst.TO_THERION;
y = dy - Float.parseFloat( pt[5] ) / TDConst.TO_THERION;
path.addPoint3( x1, y1, x2, y2, x, y );
} catch ( NumberFormatException e ) {
TDLog.Error( "Therion Line X-Y error (5) <" + line + ">" );
continue;
} catch ( ArrayIndexOutOfBoundsException e ) {
TDLog.Error( "Therion Line X-Y error (6) " + line );
continue;
}
}
}
} // end while ( line-points )
}
}
}
}
}
} catch ( FileNotFoundException e ) {
// this is OK
} catch ( IOException e ) {
e.printStackTrace();
}
}
// remove repeated names
return (missingSymbols != null )? missingSymbols.isOK() : true;
}
// =========================================================================
// EXPORT
// exportTherion calls DrawingSurface' exportTherion,
// which calls DrawingCommandManager's exportTherion,
// which calls the full method exportTherion with the list of sketch items
//
// FIXME DataHelper and SID are necessary to export splays by the station
static public void exportTherion( // DataHelper dh, long sid,
DrawingSurface surface, int type, File file, String fullname, String projname, int proj_dir )
{
// Log.v("DistoX", "Export Therion file " + file.getPath() );
try {
FileWriter fw = new FileWriter( file );
BufferedWriter bw = new BufferedWriter( fw );
surface.exportTherion( /* dh, sid, */ type, bw, fullname, projname, proj_dir );
bw.flush();
bw.close();
} catch ( IOException e ) {
TDLog.Error( "Export Therion i/o: " + e.getMessage() );
}
}
static public void exportDataStream( DrawingSurface surface, int type, File file, String fullname, int proj_dir )
{
try {
FileOutputStream fos = new FileOutputStream( file );
// ByteArrayOutputStream bos = new ByteArrayOutputStream( 4096 );
BufferedOutputStream bfos = new BufferedOutputStream( fos );
DataOutputStream dos = new DataOutputStream( bfos );
surface.exportDataStream( type, dos, fullname, proj_dir );
dos.close();
// CACHE add filename/bos.toByteArray to cache
// mTdrCache.put( fullname + ".tdr", bos );
// byte[] bytes = bos.toByteArray();
// fos.write( bytes, 0, bos.size() );
fos.close();
} catch ( FileNotFoundException e ) {
TDLog.Error( "Export Data file: " + e.getMessage() );
} catch ( IOException e ) {
TDLog.Error( "Export Data i/o: " + e.getMessage() );
}
}
// tdr files CACHE
// no need to use a cache: buffering streams is as fast as reading from file
// and requires less management overhead
// static HashMap< String, ByteArrayOutputStream > mTdrCache = new HashMap< String, ByteArrayOutputStream >();
// static void clearTdrCache() { mTdrCache.clear(); }
// =========================================================================
// EXPORT details
// V ... S ... I ...
// paths: P. T, L. A. U. X.
// F
// stations: U
// E
static public boolean doLoadDataStream( DrawingSurface surface,
String filename,
float dx, float dy,
SymbolsPalette missingSymbols,
SymbolsPalette localPalette,
RectF bbox, boolean complete )
{
int version = 0;
boolean in_scrap = false;
// BrushManager.makePaths( );
BrushManager.resetPointOrientations();
DrawingPath path = null;
int project_dir = 0;
float north_x1, north_y1, north_x2, north_y2;
File file = new File( filename );
FileInputStream fis = null;
DataInputStream dis = null;
synchronized( TDPath.mTherionLock ) {
try {
// CACHE check if filename is in the cache: if so use the cache byte array
// ByteArrayOutputStream bos = mTdrCache.get( file.getName() );
// if ( bos == null ) {
fis = new FileInputStream( filename );
BufferedInputStream bfis = new BufferedInputStream( fis );
dis = new DataInputStream( bfis );
// } else {
// Log.v("DistoX", "cache hit " + filename );
// ByteArrayInputStream bis = new ByteArrayInputStream( bos.toByteArray() );
// dis = new DataInputStream( bis );
// }
boolean todo = true;
while ( todo ) {
int what = dis.read();
// Log.v("DistoX", "Read " + what );
path = null;
switch ( what ) {
case 'V':
version = dis.readInt();
// TDLog.Log( TDLog.LOG_PLOT, "TDR version " + version );
break;
case 'I': // plot info: bounding box
{
float xmin = dis.readFloat();
float ymin = dis.readFloat();
float xmax = dis.readFloat();
float ymax = dis.readFloat();
if ( bbox != null ) {
bbox.left = xmin;
bbox.top = ymin;
bbox.right = xmax;
bbox.bottom = ymax;
}
if ( dis.readInt() == 1 ) {
north_x1 = dis.readFloat();
north_y1 = dis.readFloat();
north_x2 = dis.readFloat();
north_y2 = dis.readFloat();
}
// TDLog.Log(TDLog.LOG_PLOT, "TDR bbox " + xmin + "-" + xmax + " " + ymin + "-" + ymax );
}
break;
case 'S':
{
String name = dis.readUTF();
int type = dis.readInt();
if ( type == PlotInfo.PLOT_PROFILE ) project_dir = dis.readInt();
// read palettes
String points = dis.readUTF();
String[] vals = points.split(",");
for ( String val : vals ) if ( val.length() > 0 ) localPalette.addPointFilename( val );
String lines = dis.readUTF();
vals = points.split(",");
for ( String val : vals ) if ( val.length() > 0 ) localPalette.addLineFilename( val );
String areas = dis.readUTF();
vals = points.split(",");
for ( String val : vals ) if ( val.length() > 0 ) localPalette.addAreaFilename( val );
in_scrap = true;
// Log.v("DistoX", "TDR type " + type );
}
break;
case 'P':
path = DrawingPointPath.loadDataStream( version, dis, dx, dy, missingSymbols );
break;
case 'T':
path = DrawingLabelPath.loadDataStream( version, dis, dx, dy );
break;
case 'L':
path = DrawingLinePath.loadDataStream( version, dis, dx, dy, missingSymbols );
break;
case 'A':
path = DrawingAreaPath.loadDataStream( version, dis, dx, dy, missingSymbols );
break;
case 'U':
path = DrawingStationPath.loadDataStream( version, dis ); // consume DrawingStationName data
break;
case 'X':
path = DrawingStationName.loadDataStream( version, dis ); // consume DrawingStationName data
break;
case 'F':
// TDLog.Log( TDLog.LOG_PLOT, "<F>" );
if ( complete ) break; // continue parsing stations
case 'E':
todo = false;
break;
default:
todo = false;
TDLog.Error( "ERROR bad input (1) " + (int)what );
break;
}
if ( path != null && in_scrap ) {
if ( what == 'U' ) {
surface.addDrawingStationPath( (DrawingStationPath)path );
} else {
surface.addDrawingPath( path );
}
}
}
dis.close();
if ( fis != null ) fis.close();
} catch ( FileNotFoundException e ) {
// this is OK
} catch ( IOException e ) {
e.printStackTrace();
}
// Log.v("DistoX", "read: " + sb.toString() );
}
return (missingSymbols != null )? missingSymbols.isOK() : true;
}
static public void exportDataStream( int type, DataOutputStream dos, String scrap_name, int proj_dir, RectF bbox,
DrawingPath north,
List<ICanvasCommand> cstack,
List<DrawingStationPath> userstations,
List<DrawingStationName> stations )
{
try {
dos.write( 'V' ); // version
dos.writeInt( TopoDroidApp.VERSION_CODE );
dos.write( 'S' );
dos.writeUTF( scrap_name );
dos.writeInt( type );
if ( type == PlotInfo.PLOT_PROFILE ) dos.writeInt( proj_dir );
BrushManager.mPointLib.toDataStream( dos );
BrushManager.mLineLib.toDataStream( dos );
BrushManager.mAreaLib.toDataStream( dos );
dos.write('I');
dos.writeFloat( bbox.left );
dos.writeFloat( bbox.top );
dos.writeFloat( bbox.right );
dos.writeFloat( bbox.bottom );
if ( north != null ) {
dos.writeInt( 1 );
dos.writeFloat( north.x1 );
dos.writeFloat( north.y1 );
dos.writeFloat( north.x2 );
dos.writeFloat( north.y2 );
} else {
dos.writeInt( 0 );
}
synchronized( cstack ) {
for ( ICanvasCommand cmd : cstack ) {
if ( cmd.commandType() != 0 ) continue;
DrawingPath p = (DrawingPath) cmd;
if ( p.mType == DrawingPath.DRAWING_PATH_STATION ) continue; // safety check: should not happen
p.toDataStream( dos );
}
}
synchronized( userstations ) { // user stations are always exported to data stream
for ( DrawingStationPath sp : userstations ) {
sp.toDataStream( dos );
}
}
dos.write('F'); // final: bbox and autostations (reading can skip all that follows)
if ( TDSetting.mAutoStations ) {
synchronized( stations ) {
for ( DrawingStationName st : stations ) {
if ( st.mStation != null && st.mStation.barriered() ) continue;
if ( bbox.left > st.cx || bbox.right < st.cx ) continue;
if ( bbox.top > st.cy || bbox.bottom < st.cy ) continue;
st.toDataStream( dos );
}
}
}
dos.write('E'); // end
} catch ( IOException e ) {
e.printStackTrace();
}
}
static private void exportTherionHeader1( BufferedWriter out, int type, RectF bbox ) throws IOException
{
out.write("encoding utf-8");
out.newLine();
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
pw.format("##XTHERION## xth_me_area_adjust %.1f %.1f %.1f %.1f\n",
bbox.left*6, 400-bbox.bottom*6, bbox.right*6, 400-bbox.top*6 );
pw.format("##XTHERION## xth_me_area_zoom_to 25\n\n");
pw.format("# %s created by TopoDroid v. %s\n\n", TopoDroidUtil.currentDate(), TopoDroidApp.VERSION );
out.write( sw.getBuffer().toString() );
}
static private void exportTherionHeader2( BufferedWriter out ) throws IOException
{
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
pw.format("#P ");
BrushManager.mPointLib.writePalette( pw );
pw.format("\n#L ");
BrushManager.mLineLib.writePalette( pw );
pw.format("\n#A ");
BrushManager.mAreaLib.writePalette( pw );
pw.format("\n");
out.write( sw.getBuffer().toString() );
}
static private void exportTherionHeader2( BufferedWriter out, String points, String lines, String areas ) throws IOException
{
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
pw.format("#P");
String[] vals = points.split(",");
for ( int k=0; k<vals.length; ++k ) if ( vals[k].length() > 0 ) pw.format(" %s", vals[k] );
pw.format("\n#L");
vals = lines.split(",");
for ( int k=0; k<vals.length; ++k ) if ( vals[k].length() > 0 ) pw.format(" %s", vals[k] );
pw.format("\n#A");
vals = lines.split(",");
for ( int k=0; k<vals.length; ++k ) if ( vals[k].length() > 0 ) pw.format(" %s", vals[k] );
pw.format("\n");
out.write( sw.getBuffer().toString() );
}
static private void exportTherionHeader3( BufferedWriter out,
int type, String scrap_name, String proj_name, int project_dir,
boolean do_north, float x1, float y1, float x2, float y2 ) throws IOException
{
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
if ( type == PlotInfo.PLOT_SECTION
|| type == PlotInfo.PLOT_H_SECTION
|| type == PlotInfo.PLOT_X_SECTION ) {
if ( do_north ) { // H_SECTION (horizontal section) : north line is 5 m long
pw.format("scrap %s -projection %s -scale [%.0f %.0f %.0f %.0f 0 5 0 0 m]", scrap_name, proj_name,
x1*toTherion, -y1*toTherion, x2*toTherion, -y2*toTherion );
} else {
pw.format("scrap %s -projection %s -scale [0 0 %.0f 0 0 0 1 0 m]", scrap_name, proj_name, oneMeter );
}
} else if ( type == PlotInfo.PLOT_PROFILE ) {
pw.format("scrap %s -projection [%s %d] -scale [0 0 %.0f 0 0 0 1 0 m]", scrap_name, proj_name, project_dir, oneMeter );
} else {
pw.format("scrap %s -projection %s -scale [0 0 %.0f 0 0 0 1 0 m]", scrap_name, proj_name, oneMeter );
}
out.write( sw.getBuffer().toString() );
out.newLine();
out.newLine();
}
static private void exportTherionClose( BufferedWriter out ) throws IOException
{
out.newLine();
out.newLine();
out.write("endscrap");
out.newLine();
}
// FIXME DataHelper and SID are necessary to export splays by the station
static public void exportTherion( // DataHelper dh, long sid,
int type, BufferedWriter out, String scrap_name, String proj_name, int project_dir,
RectF bbox,
DrawingPath north,
List<ICanvasCommand> cstack,
List<DrawingStationPath> userstations,
List<DrawingStationName> stations,
List<DrawingPath> splays )
{
try {
exportTherionHeader1( out, type, bbox );
exportTherionHeader2( out );
if ( north != null ) {
exportTherionHeader3( out, type, scrap_name, proj_name, 0, true, north.x1, north.y1, north.x2, north.y2 );
} else {
exportTherionHeader3( out, type, scrap_name, proj_name, project_dir, false, 0, 0, 0, 0 );
}
synchronized( cstack ) {
for ( ICanvasCommand cmd : cstack ) {
if ( cmd.commandType() != 0 ) continue;
DrawingPath p = (DrawingPath) cmd;
if ( p.mType == DrawingPath.DRAWING_PATH_POINT ) {
DrawingPointPath pp = (DrawingPointPath)p;
out.write( pp.toTherion() );
out.newLine();
} else if ( p.mType == DrawingPath.DRAWING_PATH_STATION ) { // should never happen
// if ( ! TDSetting.mAutoStations ) {
// DrawingStationPath st = (DrawingStationPath)p;
// out.write( st.toTherion() );
// out.newLine();
// }
} else if ( p.mType == DrawingPath.DRAWING_PATH_LINE ) {
DrawingLinePath lp = (DrawingLinePath)p;
if ( lp.size() > 1 ) {
out.write( lp.toTherion() );
out.newLine();
}
} else if ( p.mType == DrawingPath.DRAWING_PATH_AREA ) {
DrawingAreaPath ap = (DrawingAreaPath)p;
out.write( ap.toTherion() );
out.newLine();
}
}
}
out.newLine();
if ( TDSetting.mTherionSplays ) {
float th = TDConst.TO_THERION;
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
for ( DrawingPath splay : splays ) {
pw.format("line u:splay -visibility off\n");
pw.format( Locale.US, " %.2f %.2f\n %.2f %.2f\n", splay.x1*th, -splay.y1*th, splay.x2*th, -splay.y2*th );
pw.format("endline\n");
}
out.write( sw.toString() );
out.newLine();
}
if ( TDSetting.mAutoStations ) {
for ( DrawingStationName st : stations ) {
if ( st.mStation != null && st.mStation.barriered() ) continue;
// FIXME if station is in the convex hull (bbox) of the lines
if ( bbox.left > st.cx || bbox.right < st.cx ) continue;
if ( bbox.top > st.cy || bbox.bottom < st.cy ) continue;
out.write( st.toTherion() );
out.newLine();
/*
* this was to export splays by the station instead of all of them
*
if ( TDSetting.mTherionSplays ) {
float th = TDConst.TO_THERION;
float x = st.cx * th;
float y = - st.cy * th;
th *= DrawingUtil.SCALE_FIX;
List< DistoXDBlock > blks = dh.selectSplaysAt( sid, st.mName, false );
if ( type == PlotInfo.PLOT_PLAN ) {
for ( DistoXDBlock blk : blks ) {
float h = blk.mLength * TDMath.cosd( blk.mClino ) * th;
float e = h * TDMath.sind( blk.mBearing );
float n = h * TDMath.cosd( blk.mBearing );
out.write( "line splay\n" );
out.write( String.format(Locale.US, " %.2f %.2f\n %.2f %.2f\n", x, y, x+e, y+n ) );
out.write( "endline\n" );
}
} else if ( PlotInfo.isProfile( type ) ) {
for ( DistoXDBlock blk : blks ) {
float v = blk.mLength * TDMath.sind( blk.mClino ) * th;
float h = blk.mLength * TDMath.cosd( blk.mClino ) * th * blk.mExtend;
out.write( "line splay\n" );
out.write( String.format(Locale.US, " %.2f %.2f\n %.2f %.2f\n", x, y, x+h, y+v ) );
out.write( "endline\n" );
}
} else if ( PlotInfo.isSection( type ) ) {
for ( DistoXDBlock blk : blks ) {
float d = blk.mLength;
float b = blk.mBearing;
float c = blk.mClino;
long e = blk.mExtend;
}
}
}
*/
}
} else {
synchronized( userstations ) {
for ( DrawingStationPath sp : userstations ) {
out.write( sp.toTherion() );
out.newLine();
}
}
}
exportTherionClose( out );
} catch ( IOException e ) {
e.printStackTrace();
}
}
static public void dataStream2Therion( File file, BufferedWriter out, RectF bbox, boolean endscrap )
{
int version = 0;
boolean in_scrap = false;
boolean do_north = false;
float north_x1=0, north_y1=0, north_x2=0, north_y2=0;
String name = "";
int type = 0;
boolean project = false;
int project_dir = 0;
String points = "";
String lines = "";
String areas = "";
// synchronized( TDPath.mTherionLock )
{
try {
FileInputStream fis = new FileInputStream( file );
DataInputStream dis = new DataInputStream( fis );
boolean todo = true;
while ( todo ) {
int what = dis.read();
switch ( what ) {
case 'V':
version = dis.readInt();
break;
case 'I': // plot info: bounding box
{
bbox.left = dis.readFloat();
bbox.top = dis.readFloat();
bbox.right = dis.readFloat();
bbox.bottom = dis.readFloat();
if ( dis.readInt() == 1 ) {
do_north = true;
north_x1 = dis.readFloat();
north_y1 = dis.readFloat();
north_x2 = dis.readFloat();
north_y2 = dis.readFloat();
}
exportTherionHeader1( out, type, bbox );
exportTherionHeader2( out, points, lines, areas );
String proj = PlotInfo.projName[ type ];
if ( do_north ) {
exportTherionHeader3( out, type, name, proj, 0, true, north_x1, north_y1, north_x2, north_y2 );
} else {
exportTherionHeader3( out, type, name, proj, project_dir, false, 0, 0, 0, 0 );
}
in_scrap = true;
}
break;
case 'S':
{
name = dis.readUTF();
type = dis.readInt();
if ( type == PlotInfo.PLOT_PROFILE ) project_dir = dis.readInt();
// read palettes
points = dis.readUTF();
lines = dis.readUTF();
areas = dis.readUTF();
}
break;
case 'P':
out.write( DrawingPointPath.loadDataStream( version, dis, 0, 0, null ).toTherion() );
break;
case 'T':
out.write( DrawingLabelPath.loadDataStream( version, dis, 0, 0 ).toTherion() );
break;
case 'L':
out.write( DrawingLinePath.loadDataStream( version, dis, 0, 0, null ).toTherion() );
break;
case 'A':
out.write( DrawingAreaPath.loadDataStream( version, dis, 0, 0, null ).toTherion() );
break;
case 'U':
out.write( DrawingStationPath.loadDataStream( version, dis ).toTherion() );
break;
case 'X':
// NOTE need to check XSection ??? STATION_XSECTION
out.write( DrawingStationName.loadDataStream( version, dis ).toTherion() );
break;
case 'F':
break; // continue parsing stations
case 'E':
todo = false;
break;
default:
todo = false;
TDLog.Error( "ERROR bad input (2) " + (int)what );
break;
}
}
if (endscrap ) exportTherionClose( out );
dis.close();
fis.close();
} catch ( FileNotFoundException e ) {
// this is OK
} catch ( IOException e ) {
e.printStackTrace();
}
}
}
}