项目需要,需要实现一个电子罗盘。现如今,手机传感器越来越灵敏,借助于手机实现电子罗盘,大大方便了野外工作人员。利用手机,可以实现岩层走向和倾向的测量,且精度也能得到一定的保证。利用方向传感器(之前使用的接口),现在换成磁场和加速度传感器联合求解三个方向,然后得到结构。
//获取传感器
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mag_sensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
acc_sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
//给传感器注册监听:
sensorManager.registerListener(this, acc_sensor, SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(this, mag_sensor, SensorManager.SENSOR_DELAY_NORMAL);
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
accValues = event.values;
} else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
magValues = event.values;
}else if (event.sensor.getType() == Sensor.TYPE_PRESSURE) {
preValues = event.values;
}
SensorManager.getRotationMatrix(r, null, accValues, magValues);
SensorManager.getOrientation(r, values); //此处的values与方向传感器结果一致,
//values[0] 手机的方位,正北为0°,顺时针180°为正,逆时针180°为负
//values[1] 手机上下倾斜程度
//values[2] 手机左右倾斜程度
}
一个好的UI展示,往往能受到大家的喜欢。要想完全自定义一个UI,完全超出了我一个小草鸟的能力,而且时间不够,于是百度搜索,发现大佬们早已经写好,自己只需要改动部分代码,然后传入自己的值就行。在这里,对***ChaosAlaska***表示感谢感谢感谢,另外贴出大佬的:https://www.jianshu.com/p/cee9b7c3abe8?utm_source=oschina-app
想要了解的可以自己去看看,写的很详细,再次感谢。
2、界面的代码和上文贴出的大佬的基本一致,就是刻度以及参数的传入自己进行了设置,这里就不贴出重复的了,只贴出不同的部分,希望给到有需要的人。
//传入 方向参数,数组的形式,上面获取到的
public void setValues(float [] values){
if(!isSave){
this.values = values;
val = Math.round(values[0]*180.0/Math.PI);
valStrike = Math.round(calculatedip(values));
invalidate();
}
}
//根据方向参数进行计算产状
private float calculatedip(float[] values) {
float caculated_dia, caculated_dip;
float dip;
double values0;
caculated_dip = (float) Math.acos(1 /Math.sqrt(Math.tan(values[1]) *Math.tan(values[1]) +Math.tan(values[2]) *Math.tan(values[2]) +1));
if(values[0] > 0)
values0 = (double) values[0];
else
values0 = 2 *Math.PI +values[0];
if(values[2] < 0)
caculated_dia = (float) (values0 -Math.acos(Math.tan(values[1]) /Math.tan(caculated_dip)));
else
caculated_dia = (float) (values0 +Math.acos(Math.tan(values[1]) /Math.tan(caculated_dip)));
if(caculated_dia < 0)
while (caculated_dia < 0)
caculated_dia += 2 *Math.PI;
else if(caculated_dia > 2 *Math.PI)
while (caculated_dia > 2 *Math.PI)
caculated_dia -= 2 *Math.PI;
float temp_dip = (float) Math.toDegrees(caculated_dip);
this.dip = String.format("%.2f",temp_dip);
caculated_dia = (float) Math.toDegrees(caculated_dia);
return caculated_dia;
}
//按钮 ”测量“ 功能的实现
public void setIsSave(boolean isSave){
this.isSave = isSave;
}
//产状和倾向画笔的初始化以及产状数字画笔初始化
mdiPaint = new Paint();
mdiPaint.setStyle(Paint.Style.FILL);
mdiPaint.setAntiAlias(true);
mdiPaint.setColor(context.getResources().getColor(R.color.dip));
mstrikePaint = new Paint();
mstrikePaint.setStyle(Paint.Style.FILL);
mstrikePaint.setAntiAlias(true);
mstrikePaint.setColor(context.getResources().getColor(R.color.strike));
mOccurrencePaint = new Paint();
mOccurrencePaint.setStyle(Paint.Style.STROKE);
mOccurrencePaint.setAntiAlias(true);
mOccurrencePaint.setTextSize(50);
mOccurrencePaint.setColor(context.getResources().getColor(R.color.white));
//定义方法
//画产状数字
drawOccuroceText();
//画走向
drawStrikeLine();
//画倾向线
drawDipLine();
//走向线
/*
因为走向线与倾向线始终垂直
所以此时,我们将strke要旋转-valstrike-90度才能绘制出来
*/
private void drawStrikeLine() {
mCanvas.save();
int mTriangleHeight=(mOutSideRadius-mCircumRadius)/2;
mCanvas.rotate(valStrike+90-val,mCenterX,mOutSideRadius+mTextHeight);
mstrikeTriangle.moveTo(width/2,mOutSideRadius+mTextHeight-mCircumRadius+20);
//内接三角形的边长,简单数学运算
float mTriangleSide = (float) ((mTriangleHeight/(Math.sqrt(3)))*2);
mstrikeTriangle.lineTo(width/2-20,mOutSideRadius+mTextHeight);
mstrikeTriangle.lineTo(width/2,mOutSideRadius+mTextHeight+mCircumRadius-20);
mstrikeTriangle.lineTo(width/2+20,mOutSideRadius+mTextHeight);
mstrikeTriangle.close();
mCanvas.drawPath(mstrikeTriangle,mstrikePaint);
mCanvas.restore();
}
//倾向线
private void drawDipLine() {
mCanvas.save();
mCanvas.rotate(valStrike-val,mCenterX,mOutSideRadius+mTextHeight);
mdipTriangle.moveTo(width/2,mOutSideRadius+mTextHeight-mCircumRadius+20);
mdipTriangle.lineTo(width/2-20,mOutSideRadius+mTextHeight);
mdipTriangle.lineTo(width/2+20,mOutSideRadius+mTextHeight);
mdipTriangle.close();
mCanvas.drawPath(mdipTriangle,mdiPaint);
mCanvas.restore();
}
//产状示数
private void drawOccuroceText() {
String occurouce = "产状:"+ valStrike+"°"+ "∠"+ dip+"°";
mOccurrencePaint.getTextBounds(occurouce,0,occurouce.length(),mOccuTextRect);
int owidth = mOccuTextRect.width();
int height = mOccuTextRect.height();
mCanvas.drawText(occurouce,width/2-owidth,mTextHeight+mOutSideRadius*2+height*3,mOccurrencePaint);
}
像控件一样使用,初始化即可。
//在布局里面设置
<com.example.view.MyView
android:id="@+id/miui"
android:layout_gravity="center"
android:background="@color/black"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
//调用方法,传入参数即可
miui.setValues(values);
因篇幅问题不能全部显示,请点此查看更多更全内容