/* @file DistoXDBlock.java
*
* @author marco corvi
* @date nov 2011
*
* @brief TopoDroid DistoX survey data
* --------------------------------------------------------
* Copyright This sowftare is distributed under GPL-3.0 or later
* See the file COPYING.
* --------------------------------------------------------
*/
package com.topodroid.DistoX;
// import java.lang.Long;
import java.io.StringWriter;
import java.io.PrintWriter;
import java.util.Locale;
import android.view.View;
import android.util.Log;
public class DistoXDBlock
{
public static final char[] mExtendTag = { '<', '|', '>', 'o', '-', '.' };
public static final int EXTEND_LEFT = -1;
public static final int EXTEND_VERT = 0;
public static final int EXTEND_RIGHT = 1;
public static final int EXTEND_IGNORE = 2;
public static final int EXTEND_HIDE = 3;
public static final int EXTEND_START = 4;
public static final int EXTEND_NONE = EXTEND_VERT;
View mView;
int mVisible; // whether is visible in the list
long mId;
long mSurveyId;
// private String mName;
String mFrom; // N.B. mfrom and mTo must be not null
String mTo;
float mLength; // meters
float mBearing; // degrees
float mClino; // degrees
float mRoll; // degrees
float mAcceleration;
float mMagnetic;
float mDip;
String mComment;
long mExtend;
long mFlag;
int mType;
int mShotType; // 0: DistoX, 1: manual
boolean mWithPhoto;
boolean mMultiBad; // whether it disagree with siblings
public static final int BLOCK_BLANK = 0;
public static final int BLOCK_MAIN_LEG = 1; // primary leg shot
public static final int BLOCK_SPLAY = 2;
public static final int BLOCK_SEC_LEG = 3; // additional shot of a centerline leg
public static final int BLOCK_BLANK_LEG = 4; // blank centerline leg-shot
// block colors: blank, centerline, splay, leg, blank-leg, ...
// dark-red white blue grey violet
private static int[] colors = { 0xffffcccc, 0xffffffff, 0xffccccff, 0xffcccccc, 0xffff33ff, 0xffccffcc };
public static final int BLOCK_SURVEY = 0; // flags
public static final int BLOCK_SURFACE = 1;
public static final int BLOCK_DUPLICATE = 2;
// public static final int BLOCK_BACKSHOT = 3;
public boolean isSurvey() { return mFlag == BLOCK_SURVEY; }
public boolean isSurface() { return mFlag == BLOCK_SURFACE; }
public boolean isDuplicate() { return mFlag == BLOCK_DUPLICATE; }
// public boolean isBackshot() { return mFlag == BLOCK_BACKSHOT; }
void setTypeBlankLeg( ) { if ( mType == BLOCK_BLANK ) mType = BLOCK_BLANK_LEG; }
boolean isTypeBlank() { return mType == BLOCK_BLANK || mType == BLOCK_BLANK_LEG; }
static boolean isTypeBlank( int t ) { return t == BLOCK_BLANK || t == BLOCK_BLANK_LEG; }
public int type() { return mType; }
boolean isMagneticBad( )
{
if ( mAcceleration == 0.0f || mMagnetic == 0.0f ) return false;
return TopoDroidApp.isBlockMagneticBad( mAcceleration, mMagnetic, mDip );
}
boolean isRecent( long id ) { return mId >= id; }
boolean isMultiBad() { return mMultiBad; }
// used by PocketTopo parser only
public DistoXDBlock( String f, String t, float d, float b, float c, float r, int e, int type, int shot_type )
{
// assert( f != null && t != null );
mView = null; // view is set by the DistoXDBlockAdapter
mVisible = View.VISIBLE;
mId = 0;
mSurveyId = 0;
// mName = "";
mFrom = f;
mTo = t;
mLength = d;
mBearing = b;
mClino = c;
mRoll = r;
mAcceleration = 0.0f;
mMagnetic = 0.0f;
mDip = 0.0f;
mComment = "";
mExtend = e;
mFlag = BLOCK_SURVEY;
mType = type;
mShotType = shot_type;
mWithPhoto = false;
mMultiBad = false;
}
public DistoXDBlock()
{
mView = null; // view is set by the DistoXDBlockAdapter
mVisible = View.VISIBLE;
mId = 0;
mSurveyId = 0;
// mName = "";
mFrom = "";
mTo = "";
mLength = 0.0f;
mBearing = 0.0f;
mClino = 0.0f;
mRoll = 0.0f;
mAcceleration = 0.0f;
mMagnetic = 0.0f;
mDip = 0.0f;
mComment = "";
mExtend = EXTEND_RIGHT;
mFlag = BLOCK_SURVEY;
mType = BLOCK_BLANK;
mShotType = 0;
mWithPhoto = false;
mMultiBad = false;
}
public void setId( long shot_id, long survey_id )
{
mId = shot_id;
mSurveyId = survey_id;
}
public void setName( String from, String to )
{
if ( from == null || to == null ) {
TDLog.Error( "FIXME ERROR DBlock::setName() either from or to is null");
return;
}
mFrom = from.trim();
mTo = to.trim();
if ( mFrom.length() > 0 ) {
if ( mTo.length() > 0 ) {
mType = BLOCK_MAIN_LEG;
} else {
mType = BLOCK_SPLAY;
}
} else {
if ( mTo.length() > 0 ) {
mType = BLOCK_SPLAY;
} else {
mType = BLOCK_BLANK;
}
}
}
public String Name() { return mFrom + "-" + mTo; }
// x bearing [degrees]
// public void setBearing( float x ) { // FIXME-EXTEND
// mBearing = x;
// if ( mBearing < 180 ) { // east to the right, west to the left
// mExtend = EXTEND_RIGHT;
// } else {
// mExtend = EXTEND_LEFT;
// }
// }
// {
// if ( mFrom == null || mFrom.length() == 0 ) {
// if ( mTo == null || mTo.length() == 0 ) {
// return BLOCK_BLANK;
// }
// return BLOCK_SPLAY;
// }
// if ( mTo == null || mTo.length() == 0 ) {
// return BLOCK_SPLAY;
// }
// return BLOCK_MAIN_LEG;
// }
public int color() { return colors[ mType ]; }
// compute relative angle in radians
public float relativeAngle( DistoXDBlock b )
{
float cc, sc, cb, sb;
cc = TDMath.cosd( mClino );
sc = TDMath.sind( mClino );
cb = TDMath.cosd( mBearing );
sb = TDMath.sind( mBearing );
Vector v1 = new Vector( cc * sb, cc * cb, sc );
cc = TDMath.cosd( b.mClino );
sc = TDMath.sind( b.mClino );
cb = TDMath.cosd( b.mBearing );
sb = TDMath.sind( b.mBearing );
Vector v2 = new Vector( cc * sb, cc * cb, sc );
float dv = (v1.minus(v2)).Length();
return dv; // approximation: 2 * asin( dv/2 );
}
public float relativeDistance( DistoXDBlock b )
{
float cc, sc, cb, sb, len;
len = mLength;
cc = TDMath.cosd( mClino );
sc = TDMath.sind( mClino );
cb = TDMath.cosd( mBearing );
sb = TDMath.sind( mBearing );
Vector v1 = new Vector( len * cc * sb, len * cc * cb, len * sc );
len = b.mLength;
cc = TDMath.cosd( b.mClino );
sc = TDMath.sind( b.mClino );
cb = TDMath.cosd( b.mBearing );
sb = TDMath.sind( b.mBearing );
Vector v2 = new Vector( len * cc * sb, len * cc * cb, len * sc );
return (v1.minus(v2)).Length();
}
public boolean isRelativeDistance( DistoXDBlock b )
{
if ( b == null ) return false;
float dist = relativeDistance( b );
return ( dist/mLength + dist/b.mLength ) < TDSetting.mCloseDistance;
}
private void formatFlag( PrintWriter pw )
{
if ( mFlag == BLOCK_DUPLICATE ) {
pw.format( "*" );
} else if ( mFlag == BLOCK_SURFACE ) {
pw.format( "-" );
// } else if ( mFlag == BLOCK_BACKSHOT ) {
// pw.format( "+" );
}
}
private void formatComment( PrintWriter pw )
{
if ( mComment == null || mComment.length() == 0 ) return;
pw.format(" N");
}
public String toString( boolean show_id )
{
float ul = TDSetting.mUnitLength;
float ua = TDSetting.mUnitAngle;
// TDLog.Log( TDLog.LOG_DATA,
// "DBlock::toString From " + mFrom + " To " + mTo + " data " + mLength + " " + mBearing + " " + mClino );
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
if ( show_id ) pw.format("%d ", mId );
pw.format(Locale.US, "<%s-%s> %.2f %.1f %.1f [%c]",
mFrom, mTo,
mLength*ul, mBearing*ua, mClino*ua, mExtendTag[ (int)(mExtend) + 1 ] );
formatFlag( pw );
formatComment( pw );
if ( mWithPhoto ) { pw.format(" #"); }
// TDLog.Log( TDLog.LOG_DATA, sw.getBuffer().toString() );
return sw.getBuffer().toString();
}
String toNote()
{
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
pw.format("[%c]", mExtendTag[ (int)(mExtend) + 1 ] );
formatFlag( pw );
formatComment( pw );
if ( mWithPhoto ) { pw.format(" #"); }
return sw.getBuffer().toString();
}
public String dataString( String fmt )
{
float ul = TDSetting.mUnitLength;
float ua = TDSetting.mUnitAngle;
return String.format(Locale.US, fmt, mLength*ul, mBearing*ua, mClino*ua );
}
public String distanceString()
{
return String.format(Locale.US, "%.2f", mLength * TDSetting.mUnitLength );
}
public String bearingString()
{
return String.format(Locale.US, "%.1f", mBearing * TDSetting.mUnitAngle );
}
public String clinoString()
{
return String.format(Locale.US, "%.1f", mClino * TDSetting.mUnitAngle );
}
public String extraString()
{
return String.format(Locale.US, "A %.1f M %.1f D %.1f",
TopoDroidApp.deltaAcc( mAcceleration ),
TopoDroidApp.deltaMag( mMagnetic ),
TopoDroidApp.deltaDip( mDip ) * TDSetting.mUnitAngle
);
}
}