/** @file PTFile.java * * @author marco corvi * @date march 2010 * * @brief PocketTopo file IO * -------------------------------------------------------- * Copyright This sowftare is distributed under GPL-3.0 or later * See the file COPYING. * -------------------------------------------------------- */ package com.topodroid.DistoX; import java.util.ArrayList; import java.util.HashMap; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import android.util.Log; class PTFile { static byte bytes2byte( byte[] b ) { final ByteBuffer bb = ByteBuffer.wrap( b ); bb.order( ByteOrder.LITTLE_ENDIAN ); return bb.get(0); } static int bytes2int( byte[] b ) { final ByteBuffer bb = ByteBuffer.wrap( b ); bb.order( ByteOrder.LITTLE_ENDIAN ); return bb.getInt(); } static byte[] int2bytes( int i ) { final ByteBuffer bb = ByteBuffer.allocate( Integer.SIZE / Byte.SIZE ); bb.order( ByteOrder.LITTLE_ENDIAN ); bb.putInt( i ); return bb.array(); } static int bytes2short( byte[] b ) { final ByteBuffer bb = ByteBuffer.wrap( b ); bb.order( ByteOrder.LITTLE_ENDIAN ); return bb.getShort(); } static byte[] short2bytes( short i ) { final ByteBuffer bb = ByteBuffer.allocate( Short.SIZE / Byte.SIZE ); bb.order( ByteOrder.LITTLE_ENDIAN ); bb.putShort( i ); return bb.array(); } static long bytes2long( byte[] b ) { final ByteBuffer bb = ByteBuffer.wrap( b ); bb.order( ByteOrder.LITTLE_ENDIAN ); return bb.getLong(); } static byte[] long2bytes( long i ) { final ByteBuffer bb = ByteBuffer.allocate( Long.SIZE / Byte.SIZE ); bb.order( ByteOrder.LITTLE_ENDIAN ); bb.putLong( i ); return bb.array(); } private static void write( FileOutputStream fs, byte[] b, int n ) { try { fs.write( b, 0, n ); } catch ( IOException e ) { TDLog.Error( "IO error on write " + n + " bytes: " + e.toString() ); } } private static void read( FileInputStream fs, byte[] b, int n ) { try { fs.read( b, 0, n ); } catch ( IOException e ) { TDLog.Error( "IO error on read " + n + " bytes: " + e.toString() ); } } static byte readByte( FileInputStream fs ) { byte[] b = new byte[1]; read( fs, b, 1 ); return bytes2byte( b ); } static void writeByte( FileOutputStream fs, byte b ) { try { fs.write( b ); } catch ( IOException e ) { } } static int readInt( FileInputStream fs ) { byte[] b = new byte[4]; read( fs, b, 4 ); return bytes2int( b ); } static void writeInt( FileOutputStream fs, int i ) { byte[] b = int2bytes( i ); write( fs, b, 4 ); } static short readShort( FileInputStream fs ) { byte[] b = new byte[2]; read( fs, b, 2 ); return (short)bytes2short( b ); } static void writeShort( FileOutputStream fs, short i ) { byte[] b = short2bytes( i ); write( fs, b, 2 ); } static long readLong( FileInputStream fs ) { byte[] b = new byte[8]; read( fs, b, 8 ); return bytes2long( b ); } static void writeLong( FileOutputStream fs, long i ) { byte[] b = long2bytes( i ); write( fs, b, 8 ); } // --------------------------------------------------------------- // --------------------------------------------------------------- static final float INT16_2_DEG = 0.005493164f; static final float DEG_2_INT16 = 182.0444444f; /* 65536 / 360 */ // #define INT16_MAX 65536 /* 1<<16 */ static final float INT8_2_DEG = 0.711111111f; static final float DEG_2_INT8 = 1.40625f; static short DEG_2_ANGLE( float d ) // u_int16_t { if ( d < 0.0f ) d += 360.0f; return (short)( d * DEG_2_INT16 ); } static float ANGLE_2_DEG( float a ) { return a * INT16_2_DEG; } static short DEG_2_CLINO( float d ) // u_int16_t { if ( d < 0.0f ) d += 360.0f; return (short)( d * DEG_2_INT16 ); } static float CLINO_2_DEG( float c ) { float d = c * INT16_2_DEG; if ( d > 180.0f ) d -= 360.0f; return d; } static byte DEG_2_ROLL( float d ) { if ( d < 0.0f ) d += 360.0f; return (byte)(int)( d * DEG_2_INT8 ); } static float ROLL_2_DEG( float r ) { return r * INT8_2_DEG; } // int _trip_count; // int _shot_count; // int _ref_count; ArrayList< PTTrip > _trips; ArrayList< PTShot > _shots; ArrayList< PTReference > _references; HashMap<String,Integer> stationsId; PTMapping _overview; PTDrawing _outline; PTDrawing _sideview; // String[] _color_line; // color --> th_line // String[] _color_point; // color --> th_point // static String _color_default_line[] = // { "user", // "wall", // 1 black // "contour", // 2 gray // "rock-border", // 3 brown // "border", // 4 blue // "pit", // 5 red // "arrow" // 6 green // }; // static String _color_default_point[] = // { "clay", // "station", // 1 black // "block", // 2 gray // "stalactite", // 3 brown // "water-flow", // 4 blue // "anchor", // 5 red // "debris" // 6 green // }; PTFile() { stationsId = new HashMap<String,Integer>(); // indices of stations (for TopoDroid export) _trips = new ArrayList< PTTrip >(); _shots = new ArrayList< PTShot >(); _references = new ArrayList< PTReference >(); _overview = new PTMapping(); _outline = new PTDrawing(); _sideview = new PTDrawing(); // _color_line = _color_default_line; // _color_point = _color_default_point; } // ----------------------------------------------------- // ----------------------------------------------------- int tripCount() { return _trips.size(); } PTTrip getTrip( int k ) { return _trips.get(k); } int shotCount() { return _shots.size(); } PTShot getShot( int k ) { return _shots.get(k); } int refCount() { return _references.size(); } PTReference getRef( int k ) { return _references.get(k); } PTMapping getOverview() { return _overview; } PTDrawing getOutline() { return _outline; } PTDrawing getSideview() { return _sideview; } // ----------------------------------------------------- // void setColorLine( String[] line ) { _color_line = line; } // void setColorPoint( String[] point ) { _color_point = point; } void clear() { _trips.clear(); _shots.clear(); _references.clear(); _overview.clear(); _outline.clear(); _sideview.clear(); } void read( FileInputStream fs ) { clear(); // read ID and version byte[] bytes = new byte[4]; try { fs.read( bytes, 0, 4 ); // assert bytes == Top3 } catch( IOException e ) { TDLog.Error( "IO error on \"Top3\""); } TDLog.Log( TDLog.LOG_PTOPO, "PT ID " + bytes[0] + bytes[1] + bytes[2] ); int tc = PTFile.readInt( fs ); // Log.v("PTDistoX", "trip count " + tc ); for (int k=0; k<tc; ++k ) { PTTrip trip = new PTTrip(); trip.read( fs ); _trips.add( trip ); } int sc = PTFile.readInt( fs ); // Log.v("PTDistoX", "shot count " + sc ); for ( int k=0; k<sc; ++k ) { PTShot shot = new PTShot(); shot.read( fs ); _shots.add( shot ); } int rc = PTFile.readInt( fs ); TDLog.Log( TDLog.LOG_PTOPO, "PT trips " + tc + " shots " + sc + " refs " + rc ); // Log.v( "PTDistoX", "PT trips " + tc + " shots " + sc + " refs " + rc ); for ( int k=0; k<rc; ++k ) { PTReference ref = new PTReference(); ref.read( fs ); _references.add( ref ); } _overview.read( fs ); _outline.read( fs ); _sideview.read( fs ); } void write( FileOutputStream fs ) { try { byte header[] = { 'T', 'o', 'p', (byte)3 }; fs.write( header, 0, 4 ); } catch( IOException e ) { } PTFile.writeInt( fs, _trips.size() ); for ( PTTrip t : _trips ) t.write( fs ); PTFile.writeInt( fs, _shots.size() ); for ( PTShot s : _shots ) s.write( fs ); PTFile.writeInt( fs, _references.size() ); for ( PTReference r : _references ) r.write( fs ); _overview.write( fs ); _outline.write( fs ); _sideview.write( fs ); } // void print() // { // Log.v( TopoDroidApp.TAG, "FILE trips " + _trips.size() + " shots " + _shots.size() + // " refs " + _references.size() ); // Log.v( TopoDroidApp.TAG, "TRIPS"); // for ( PTTrip t : _trips ) t.print(); // Log.v( TopoDroidApp.TAG, "SHOTS"); // for ( PTShot s : _shots ) s.print(); // Log.v( TopoDroidApp.TAG, "REFERENCES"); // for ( PTReference r : _references ) r.print(); // Log.v( TopoDroidApp.TAG, "OVERVIEW"); // _overview.print(); // Log.v( TopoDroidApp.TAG, "OUTLINE"); // _outline.print(); // Log.v( TopoDroidApp.TAG, "SIDEVIEW"); // _sideview.print(); // } /* // void // PTfile::printTherion( const char * prefix ) // { // if ( prefix == NULL || strlen(prefix) == 0 ) // prefix = "cave"; // std::ostringstream oss; // std::ostringstream oss_plan; // std::ostringstream oss_ext; // oss << prefix << ".th"; // oss_plan << prefix << "-p.th2"; // oss_ext << prefix << "-s.th2"; // const char * outlinefile = oss_plan.str().c_str(); // const char * sideviewfile = oss_ext.str().c_str(); // // TDPath.checkPath( oss.str().c_str() ); // FileOutputStream fp = fopen( oss.str().c_str(), "w" ); // if ( fp == NULL ) return; // FIXME // fprintf(fp, "encoding UTF-8\n"); // fprintf(fp, "survey survey_name\n\n"); // // fprintf(fp, " centerline\n"); // for ( int r=0; r < _ref_count; ++r ) { // _references[r].printTherion( fp ); // } // fprintf(fp, " endcenterline\n\n"); // // bool no_trip_shot = false; // for ( int t=0; t < _trip_count; ++t ) { // int extend = 1; // _trips[t].printTherion( fp ); // for ( int s=0; s < _shot_count; ++s ) { // if ( _shots[s].tripIndex() == -1 ) no_trip_shot = true; // if ( _shots[s].tripIndex() == t ) { // _shots[s].printTherion( fp, extend ); // } // } // fprintf(fp, " endcenterline\n\n"); // } // if ( no_trip_shot ) { // int extend = 1; // fprintf(fp, " centerline\n"); // fprintf(fp, " declination - degrees\n"); // fprintf(fp, " data normal from to length compass clino\n"); // fprintf(fp, " extend right\n"); // for ( int s=0; s < _shot_count; ++s ) { // if ( _shots[s].tripIndex() == -1 ) { // _shots[s].printTherion( fp, extend ); // } // } // fprintf(fp, " endcenterline\n\n"); // } // fprintf(fp, " input %s\n\n", outlinefile ); // fprintf(fp, " input %s\n\n", sideviewfile ); // // _overview.printTherion( fp ); // fprintf(fp, "endsurvey\n"); // fclose( fp ); // // fp = fopen( outlinefile, "w" ); // if ( fp ) { // _outline.printTherion( fp, "outline", "plan", _color_point, _color_line ); // fclose( fp ); // } // // fp = fopen( sideviewfile, "w" ); // if ( fp ) { // _sideview.printTherion( fp, "sideview", "extended", _color_point, _color_line ); // fclose( fp ); // } // // } */ /** add a trip * @param y year * @param * @return trip index */ int addTrip( int y, int m, int d, float declination, String comment ) { PTTrip trip = new PTTrip(); trip.setTime( y, m, d ); trip.setDeclination( declination ); trip.setComment( comment ); _trips.add( trip ); return _trips.size(); } private int getId( String name ) { Integer intId = stationsId.get( name ); if ( intId == null ) { int id = DistoXStationName.toInt( name ); stationsId.put( name, Integer.valueOf( id ) ); return id; } return intId.intValue(); } /** * @return number of shots */ int addShot( short trip, String from, String to, float distance, // [m] float azimuth, // [degrees] float inclination, // [degrees] float roll, // [degrees] int extend, // -1 left, +1 right String comment ) { TDLog.Log( TDLog.LOG_DEBUG, "PT file add shot " + from + " " + to + " " + distance + " " + azimuth + " " + inclination ); PTShot shot = new PTShot( distance, azimuth, inclination, roll, (extend == -1), trip ); int id; if ( from.length() == 0 || from.equals("-") ) { shot.setFromUndefined(); } else { shot.setFrom( getId( from ) ); } if ( to.length() == 0 || to.equals("-") ) { shot.setToUndefined(); } else { shot.setTo( getId( to ) ); } shot.setComment( comment ); _shots.add( shot ); return _shots.size(); } /** add a reference * @return number of references */ int addReference( String station, float e, float n, float a, String comment ) { int e0 = (int)(e * 1000); int n0 = (int)(n * 1000); int a0 = (int)(a * 1000); PTReference ref = new PTReference( station, e0, n0, a0, comment ); _references.add( ref ); return _references.size(); } // void initColors( String color_point[], String color_line[] ) // { // for (int k=0; k<7; ++k ) { // color_point[k] = _color_default_point[k]; // color_line[k] = _color_default_line[k]; // } // } }