27391


Android Studioにて、以下のコードからなる図形に対して、  
画面をタッチした時に、その座標が、赤もしくは緑の弧に含まれるかの判定をしたいのですが、  
方法がわからずにいます。

タッチイベントで座標を取得し、座標データを利用する方法がよいのか、  
または、全く違う方法があるのか・・・・  
よい方法があれば、ご教示をお願い致します。

[code]

    public class Circle extends View{
    
        public Circle(Context context) {
            super(context);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            Paint paint1 = new Paint();
            paint1.setColor(Color.argb(255, 255, 0, 0));//red
            Paint paint2 = new Paint();
            paint2.setColor(Color.argb(255,0,255,0));//green
    
            RectF oval1 = new RectF(50.0f, 50.0f, 400.0f, 400.0f);
            RectF oval2 = new RectF(50.0f, 50.0f, 400.0f, 400.0f);
    
            canvas.drawArc(oval1, 0, 80, true, paint1);
            canvas.drawArc(oval2, 150, 60, true, paint2);
    
            paint1.setAntiAlias(true);
            paint2.setAntiAlias(true);
    
        }
    }
    
[/code]

[![画像の説明をここに入力](https://i.stack.imgur.com/Wmsae.png)](https://i.stack.imgur.com/Wmsae.png)


CC BY-SA 3.0
2016-07-06T12:59:24.100
27387
2016-07-06T23:22:12.580
2016-07-06T23:22:12.580
15185
17085
question
android java
タッチした座標が弧に含まれるかの判定


タッチした座標が円弧に含まれるかどうかは、2つの情報があれば分かります。

  * 中心座標からの距離
  * 中心座標からの角度

距離は三平方の定理で分かります。距離が円の半径より大きければ、円弧の外側です。

角度は逆正接で求められます。`atan2()`というベクトルから角度を求める方法がありますので、これで求めた角度を度数法に変換すればよいです。それぞれの円弧の始点と終点の角度の範囲内かどうかを判定します。

プログラミング的なトピックとしては、数学の座標系では中心が始点 `(0,0)` で第一象限は右上ですが、`View` の座標系では左上が始点 `(0,0)`
かつ、y軸が逆転しているという点に注意する必要があります。

また、`Canvas#drawArc()`で指定する角度は、時計の3時の方向が0度になるため、取得した角度を判定するときには、時計回りに90度回転させる必要があります。

例えば、タッチされた場合に色を変える場合は以下のようなコードになります。（簡単のために横幅 500px、縦幅 500px の `View` としています）

[code]

    public class Circle extends View {
    
        private Paint paint = new Paint();
        private RectF rect = new RectF();
    
        private boolean inGreen = false;
        private boolean inRed = false;
    
        public Circle(Context context) {
            super(context);
            initialize();
        }
    
        public Circle(Context context, AttributeSet attribute) {
            super(context, attribute);
            initialize();
        }
    
        private void initialize() {
            paint.setAntiAlias(true);
            rect.set(50.f, 50.f, 400.f, 400.f);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int width = MeasureSpec.makeMeasureSpec(500, MeasureSpec.UNSPECIFIED);
            int height = MeasureSpec.makeMeasureSpec(500, MeasureSpec.UNSPECIFIED);
            setMeasuredDimension(width, height);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            paint.setColor(inRed ? Color.WHITE : Color.RED);
            canvas.drawArc(rect, 0, 80, true, paint);
    
            paint.setColor(inGreen ? Color.WHITE : Color.GREEN);
            canvas.drawArc(rect, 150, 60, true, paint);
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            float x = event.getX() - 250.f;
            float y = 250.f - event.getY();
            float distance = (float) Math.sqrt(x * x + y * y);
            if (distance > 200) {
                inGreen = false;
                inRed = false;
            } else {
                int angle = (int) Math.toDegrees(Math.atan2(x, y));
                angle = angle > 0 ? angle : angle + 360;
                inRed = angle >= 90 && angle <= 170;
                inGreen = angle >= 240 && angle <= 300;
            }
            invalidate();
            return true;
        }
    }
    
[/code]


CC BY-SA 3.0
2016-07-06T15:22:46.633
27391
2016-07-06T15:33:33.567
2016-07-06T15:33:33.567
5337
5337
27387
answer