/* @file CalibCBlock.java * * @author marco corvi * @date nov 2011 * * @brief TopoDroid DistoX calibration data * -------------------------------------------------------- * Copyright This sowftare is distributed under GPL-3.0 or later * See the file COPYING. * -------------------------------------------------------- */ package com.topodroid.DistoX; import java.io.StringWriter; import java.io.PrintWriter; import java.util.Locale; public class CalibCBlock { private static final float grad2rad = TDMath.GRAD2RAD; private static int[] colors = { 0xffcccccc, 0xffffcccc, 0xffccccff }; public long mId; public long mCalibId; public long gx; public long gy; public long gz; public long mx; public long my; public long mz; public long mGroup; public float mBearing; // computed compass public float mClino; // computed clino public float mRoll; // computed roll public float mError; // error in the calibration algo associated to this data public long mStatus; boolean isSaturated() { return ( mx >= 32768 || my >= 32768 || mz >= 32768 ); } boolean isGZero() { return ( gx == 0 && gy == 0 && gz == 0 ); } public CalibCBlock() { mId = 0; mCalibId = 0; gx = 0; gy = 0; gz = 0; mx = 0; my = 0; mz = 0; mGroup = 0; mError = 0.0f; } public boolean isFarFrom( float b0, float c0, float thr ) { computeBearingAndClino(); float c = c0 * grad2rad; float b = b0 * grad2rad; Vector v1 = new Vector( (float)Math.cos(c) * (float)Math.cos(b), (float)Math.cos(c) * (float)Math.sin(b), (float)Math.sin(c) ); c = mClino * grad2rad; b = mBearing * grad2rad; Vector v2 = new Vector( (float)Math.cos(c) * (float)Math.cos(b), (float)Math.cos(c) * (float)Math.sin(b), (float)Math.sin(c) ); float x = v1.dot(v2); return x < thr; // 0.70: approx 45 degrees } public void setId( long id, long cid ) { mId = id; mCalibId = cid; } // FIXME ZERO-DATA public void setGroupIfNonZero( long g ) { mGroup = isGZero() ? 0 : g; } public void setGroup( long g ) { mGroup = g; } public void setError( float err ) { mError = err; } public int color() { if ( mGroup <= 0 ) return colors[0]; return colors[ 1 + (int)(mGroup % 2) ]; } void setStatus( long s ) { mStatus = s; } public void setData( long gx0, long gy0, long gz0, long mx0, long my0, long mz0 ) { gx = ( gx0 > TopoDroidUtil.ZERO ) ? gx0 - TopoDroidUtil.NEG : gx0; gy = ( gy0 > TopoDroidUtil.ZERO ) ? gy0 - TopoDroidUtil.NEG : gy0; gz = ( gz0 > TopoDroidUtil.ZERO ) ? gz0 - TopoDroidUtil.NEG : gz0; mx = ( mx0 > TopoDroidUtil.ZERO ) ? mx0 - TopoDroidUtil.NEG : mx0; my = ( my0 > TopoDroidUtil.ZERO ) ? my0 - TopoDroidUtil.NEG : my0; mz = ( mz0 > TopoDroidUtil.ZERO ) ? mz0 - TopoDroidUtil.NEG : mz0; } public void computeBearingAndClino() { float f = TopoDroidUtil.FV; // StringWriter sw = new StringWriter(); // PrintWriter pw = new PrintWriter( sw ); // pw.format("Locale.US, G %d %d %d M %d %d %d E %.2f", gx, gy, gz, mx, my, mz, mError ); // TDLog.Log( TDLog.LOG_DATA, sw.getBuffer().toString() ); Vector g = new Vector( gx/f, gy/f, gz/f ); Vector m = new Vector( mx/f, my/f, mz/f ); doComputeBearingAndClino( g, m ); } public void computeBearingAndClino( CalibAlgo calib ) { float f = TopoDroidUtil.FV; Vector g = new Vector( gx/f, gy/f, gz/f ); Vector m = new Vector( mx/f, my/f, mz/f ); Vector g0 = calib.GetAG().timesV( g ); Vector m0 = calib.GetAM().timesV( m ); Vector g1 = calib.GetBG().plus( g0 ); Vector m1 = calib.GetBM().plus( m0 ); doComputeBearingAndClino( g1, m1 ); } private void doComputeBearingAndClino( Vector g, Vector m ) { g.normalize(); m.normalize(); Vector e = new Vector( 1.0f, 0.0f, 0.0f ); Vector y = m.cross( g ); Vector x = g.cross( y ); y.normalize(); x.normalize(); float ex = e.dot( x ); float ey = e.dot( y ); float ez = e.dot( g ); mBearing = TDMath.atan2( -ey, ex ); mClino = - TDMath.atan2( ez, (float)Math.sqrt(ex*ex+ey*ey) ); mRoll = TDMath.atan2( g.y, g.z ); if ( mBearing < 0.0f ) mBearing += TDMath.M_2PI; if ( mRoll < 0.0f ) mRoll += TDMath.M_2PI; mClino *= TDMath.RAD2GRAD; mBearing *= TDMath.RAD2GRAD; mRoll *= TDMath.RAD2GRAD; } public String toString() { float ua = TDSetting.mUnitAngle; StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); computeBearingAndClino(); pw.format(Locale.US, "%d <%d> %5.1f %5.1f %5.1f %6.4f", mId, mGroup, mBearing*ua, mClino*ua, mRoll*ua, mError*TDMath.RAD2GRAD ); if ( TDSetting.mRawCData == 1 ) { pw.format( " %d %d %d %d %d %d", gx, gy, gz, mx, my, mz ); } else if ( TDSetting.mRawCData == 2 ) { pw.format( " %04x %04x %04x %04x %04x %04x", gx & 0xffff, gy & 0xffff, gz & 0xffff, mx & 0xffff, my & 0xffff, mz & 0xffff ); } return sw.getBuffer().toString(); } }