关于Touch的顺时针(CW),逆时针(CCW)旋转

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

/**
 * @author 麦子 2013.7.10
 */
public class TouchRoundView extends View
{

    private Paint paint = null; // 画笔
    private float px, py; // Touch 记录点
    private float angle = 0; // 记录全局旋转的角度
    private float[] touch = null; // 测试点

    public TouchRoundView(Context context)
    {
        super(context);
        this.init();
    }

    public TouchRoundView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        this.init();
    }

    private void init()
    {
        this.paint = new Paint();
        this.paint.setAntiAlias(true); // 抗锯齿
        this.paint.setStyle(Paint.Style.STROKE); // 设置为画线
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        canvas.drawColor(Color.WHITE); // 设置为白底
        float cx = this.getWidth() / 2;
        float cy = this.getHeight() / 2;
        canvas.drawCircle(cx, cy, 10, paint); // 中心点
        canvas.drawCircle(cx, cy, 200, paint); // 画圆
        if (this.touch != null)
        {
            canvas.drawLine(cx, cy, this.touch[0], this.touch[1], this.paint);
        } else
        {
            canvas.drawLine(cx, cy, cx, cy - 200, this.paint);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        int action = event.getAction();
        float x = event.getX(), y = event.getY();
        if (action == MotionEvent.ACTION_MOVE)
        {
            float cx = this.getWidth() / 2;
            float cy = this.getHeight() / 2;
            float angle1 = TouchRoundView.angle(cx, cy, this.px, this.py, cx, cy - 100);
            float angle2 = TouchRoundView.angle(cx, cy, x, y, cx, cy - 100);
            float tAngle1 = CWAngle(cx, cy, this.px, this.py, angle1);
            float tAngle2 = CWAngle(cx, cy, x, y, angle2);
            this.angle = this.angle + (tAngle2 - tAngle1);
            this.touch = getLocationFromPointRoundPointAngle(cx, cy - 200, cx, cy, this.angle);
        }
        this.px = x;
        this.py = y;
        this.postInvalidate();
        return true;
    }

    /**
     * 计算三点间的夹角 cx, cy (角顶点)
     * 
     * @param cx
     *            角顶点x坐标
     * @param cy
     *            角顶点y坐标
     */
    public static float angle(float cx, float cy, float fx, float fy, float sx, float sy)
    {
        float ma_x = fx - cx;
        float ma_y = fy - cy;
        float mb_x = sx - cx;
        float mb_y = sy - cy;
        float v1 = (ma_x * mb_x) + (ma_y * mb_y);
        float ma_val = (float) Math.sqrt(ma_x * ma_x + ma_y * ma_y);
        float mb_val = (float) Math.sqrt(mb_x * mb_x + mb_y * mb_y);
        float cosM = v1 / (ma_val * mb_val);
        float angle = (float) (Math.acos(cosM) * 180 / Math.PI);
        return angle;
    }

    /***
     * 第四象限 | 第一象限 <br>
     * ———————————————— <br>
     * 第三象限 | 第二象限 <br>
     * 
     * @param cx
     *            中心x坐标
     * @param cy
     *            中心y坐标
     * @param ax
     *            活动点x坐标
     * @param ay
     *            活动点y坐标
     * 
     * @param calDegree
     *            活动点与垂直方向上的夹角
     * 
     * @return 计算顺时针方向的角度(0~360)
     */
    public static float CWAngle(float cx, float cy, float ax, float ay, float calDegree)
    {
        calDegree %= 360; // 求模运算
        if (ax > cx && ay < cy)
        { // 第一象限
            return calDegree;
        } else if (ax > cx && ay >= cy)
        { // 第二象限
            return calDegree;
        } else if (ax < cx && ay >= cy)
        { // 第三象限
            return 360 - calDegree;
        } else if (ax < cx && ay < cy)
        { // 第四象限
            return 360 - calDegree;
        } else if (ax == cx && ay < cy)
        { // 垂直于中心点之上
            return 0;
        } else if (ax == cx && ay > cy)
        { // 垂直于中心点之下
            return 180;
        }
        return 0;
    }

    /**
     * 计算一个点绕另一个点旋转一个角度后的新位置
     * 
     * @param cx
     *            旋转点x坐标
     * @param cy
     *            旋转点y坐标
     */
    public static float[] getLocationFromPointRoundPointAngle(float x, float y, float cx, float cy, float angle)
    {
        float radians = (float) Math.toRadians(angle);
        float rx = (float) (Math.cos(radians) * (x - cx) - Math.sin(radians) * (y - cy) + cx);
        float ry = (float) (Math.sin(radians) * (x - cx) + Math.cos(radians) * (y - cy) + cy);
        return new float[] { rx, ry };
    }

}

PS:最近项目中可能会出现随着手指来旋转某个对象,在网上查了一些资料自己整理出来了,上面的三个静态方法是在网上搜索加上自己理解整理的,可以单独出来直接用。

posted on 2013-07-10 21:11  麥籽  阅读(1618)  评论(0编辑  收藏  举报