欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android中使用的三角函数与反三角函数

程序员文章站 2022-05-30 20:07:05
...

大家都知道Math类中有三角函数和反三角函数的公式,但笔者小白,在使用的Math类时候发现和我们正常数学不太一样,本篇就为记录Math类的三角函数已经反三角函数的使用:

 

Math:

      举个三角函数的例子:

    /**
     * Returns the trigonometric sine of an angle.  Special cases:
     * <ul><li>If the argument is NaN or an infinity, then the
     * result is NaN.
     * <li>If the argument is zero, then the result is a zero with the
     * same sign as the argument.</ul>
     *
     * <p>The computed result must be within 1 ulp of the exact result.
     * Results must be semi-monotonic.
     *
     * @param   a   an angle, in radians.
     * @return  the sine of the argument.
     */
    @FastNative
    public static native double sin(double a);

    上面使我们经常会使用到的sin()正弦三角函数的Math源码;我们在数学中是填入一个角度值,又上面的注释我们可以看出,这里的参数是一个弧度,在使用时走了很多的误区:


        double angle = 30 * Math.PI / 180;

        double sin = Math.sin(angle);

        double sin2=Math.sin(30);
        Log.e("TAG","sin---"+sin);
        Log.e("TAG","sin2---"+sin2);


下面是我log结果:

07-31 03:50:35.352 6034-6034/com.example.circle E/TAG: sin---0.49999999999999994
                                                       sin2----0.9880316240928618

我们都知道sin(30(度)) 的值为0.5

可是在代码中无法体现角度单位,所以就用到了弧度,

double angle = 30 * Math.PI / 180;

这段代码就是将角度30度转换为弧度的公式,具体角度与弧度的转换公式如下图:

 

Android中使用的三角函数与反三角函数

 

其他三角函数与sin()用法相同,这里就不做过多阐述了,至于反三角函数,看到这里大家就都能明白了,以前我们的数学公式得到的是角度,现在我们在代码中使用三角函数得到的自然就是弧度了,那么之后将弧度转换为角度即可,例如:

                   //根据坐标点求出当前触摸点与x轴的夹角
                    float oldSweepAngle = (float) (Math.atan(y / x) * 180 / Math.PI);

上面的代码只是一个使用arctan() 反三角函数来根据(x,y)得出角度的简单例子,具体三角函数和反三角函数在代码中的实现大家只需要记住角度与弧度转换公式即可,下面插一个笔者做的一个自定义View的小Demo,其中使用到了简单的反三角函数

 

先看效果:

是一个环形的可实现拖动和点击更新进度的一个自定义View,类似于某些音乐播放软件调节音量的控件

Android中使用的三角函数与反三角函数

 

public class MyCircle extends View {
    private int mHeight;
    private int mWidth;
    private int radio;
    private int mWeight;
    private float sweepAngle;

    public MyCircle(Context context) {
        this(context, null);
    }

    public MyCircle(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyCircle(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth = w;
        mHeight = h;
        //外圆半径
        radio = mHeight / 2;
        //选中区域角度
        sweepAngle = 0f;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //设置画布的位置
        canvas.translate(mWidth / 2, mHeight / 2);

        //外圆画笔对象
        Paint paint = new Paint();
        paint.setColor(Color.GRAY);
        paint.setStyle(Paint.Style.FILL);

        //内圆画笔对象
        Paint wPaint = new Paint();
        wPaint.setColor(Color.WHITE);
        wPaint.setStyle(Paint.Style.FILL);

        //画外圆
        canvas.drawCircle(0, 0, radio, paint);

        //画选中的轮盘颜色
        Paint mPaint = new Paint();
        mPaint.setColor(Color.RED);
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL);
        RectF rectF = new RectF(-radio, -radio, radio, radio);
        canvas.drawArc(rectF, -90, sweepAngle, true, mPaint);

        //设定环的宽度
        mWeight = 40;
        //画內圆
        canvas.drawCircle(0, 0, radio - mWeight, wPaint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
                //将下(x,y)移动至圆心,及现在的(0,0)
                float x = event.getX() - radio;
                float y = event.getY() - radio;
                //判断触摸点是否在环上
                if (x * x + y * y <= radio * radio && x * x + y * y >= (radio - mWeight) * (radio - mWeight)) {
                    //根据坐标点求出当前触摸点与x轴的夹角
                    float oldSweepAngle = (float) (Math.atan(y / x) * 180 / Math.PI);
                    if (x > 0)
                        //一四象限需要在原始角度上加90
                        sweepAngle = oldSweepAngle + 90;
                    else {
                        //二三象限需要在原始角度上加270
                        sweepAngle = oldSweepAngle + 270;
                    }
                    invalidate();
                }
                break;
        }
        return true;
    }
}

 

希望此篇文章对你有所帮助,不足之处还请大佬们提供宝贵意见!!!

 

 

 

相关标签: 自定义View