remapCoordinateSystemの引数には何を指定する?|Android開発
方位角を取得する、android.hardware.SensorManagerのAPI
remapCoordinateSystem
について引数がイマイチ分からず、ネットの情報も色々異なっていたので自身が確認した内容を残しておきます。
書式
boolean remapCoordinateSystem(float[] inR, int X, int Y, float[] outR)
解説
X
、Y
にはワールド軸の値を設定する。
設定可能な値は以下。
- SensorManager.AXIS_MINUS_X
- SensorManager.AXIS_MINUS_Y
- SensorManager.AXIS_MINUS_Z
- SensorManager.AXIS_X
- SensorManager.AXIS_Y
- SensorManager.AXIS_Z
ワールド軸は自分が立った状態で考えると分かりやすいです。
上が+Z、正面が+Y、右が+X。(足元は-Z、後ろが-Y、左が-X)
この状態で端末を縦長(Portrait)で地面に水平にした状態が基準となります。そして、この状態で自分の正面が北であれば、方位角は0となります。
remapCoordinateSystem
の引数X
、Y
はPortrait状態で見たディスプレイ右方向がX
、ディスプレイ上方向がY
となります。
よって、
- 端末をPortraitで正面に向けた場合、
X
はワールド軸の+Z、Y
はワールド軸の+Zとなります。 - 端末をLandscapeで正面に向けた場合、
X
はワールド軸の-X、Y
はワールド軸の+Zとなります。
ワールド軸の図
Portrait時の引数X,Y
Landscape時の引数X,Y
使い方
public class OrientationSensor implements SensorEventListener
{
private static final int MATRIX_SIZE = 16;
/* 回転行列 */
private float[] mInR;
private float[] mOutR;
private float[] mI;
private float[] mMagneticValues;
private float[] mAccelerometerValues;
private int mCurrentDegreeLandscape;
private int mCurrentDegreePortrait;
public OrientationSensor() {
mInR = new float[MATRIX_SIZE];
mOutR = new float[MATRIX_SIZE];
mI = new float[MATRIX_SIZE];
mMagneticValues = new float[0];
mAccelerometerValues = new float[0];
}
@Override
public void onSensorChanged(SensorEvent event) {
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
mAccelerometerValues = event.values.clone();
break;
case Sensor.TYPE_MAGNETIC_FIELD:
mMagneticValues = event.values.clone();
break;
default:
return;
}
if (mMagneticValues.length <= 0 || mAccelerometerValues.length <= 0) {
return;
}
SensorManager.getRotationMatrix(mInR, mI, mAccelerometerValues, mMagneticValues);
float[] orientationValues = new float[3];
SensorManager.remapCoordinateSystem(mInR, SensorManager.AXIS_Z, SensorManager.AXIS_MINUS_X, mOutR);
SensorManager.getOrientation(mOutR, orientationValues);
int degreeLandscape = radianToDegree(orientationValues[0]);
if (degreeLandscape < 0) {
degreeLandscape += 360;
}
SensorManager.remapCoordinateSystem(mInR, SensorManager.AXIS_X, SensorManager.AXIS_Z, mOutR);
SensorManager.getOrientation(mOutR, orientationValues);
int degreePortrait = radianToDegree(orientationValues[0]);
if (degreePortrait < 0) {
degreePortrait += 360;
}
mCurrentDegreeLandscape = degreeLandscape;
mCurrentDegreePortrait = degreePortrait;
Log.v("OrientationSensor", String.format("DEGREE: land(%d), port(%d)", mCurrentDegreeLandscape, mCurrentDegreePortrait));
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// NOP
}
private static int radianToDegree(float radian) {
return (int) Math.floor(Math.toDegrees(radian));
}
}
mCurrentDegreeLandscape
とmCurrentDegreePortrait
は同じ値になるはずです。