2013-08-26 95 views
1

我有一個自定義視圖,它繪製線條並將它們保存到ArrayList。我想要做的是檢查一個指定的點是否在Arraylist中的一行上並返回該行。當直線使用if (l.startX == l.stopX && l.startY < l.stopY時,我可以做到這一點,但如果線條處於某個角度,則此功能無效。我也想用drawText和drawCircle做到這一點。有沒有一些簡單的方法來做到這一點,我錯過了?Android Canvas檢查點是否在線

DrawView.java

class Line { 
    float startX, startY, stopX, stopY; 
    public Line(float startX, float startY, float stopX, float stopY) { 
    this.startX = startX; 
    this.startY = startY; 
    this.stopX = stopX; 
    this.stopY = stopY; 
    } 
    public Line(float startX, float startY) { // for convenience 
    this(startX, startY, startX, startY); 
    } 
} 

public class DrawView extends View { 
    Paint paint = new Paint(); 
    ArrayList<Line> lines = new ArrayList<Line>(); 

    public DrawView(Context context, AttributeSet attrs) { 
    super(context, attrs); 

    paint.setAntiAlias(true); 
    paint.setStrokeWidth(6f); 
    paint.setColor(Color.BLACK); 
    paint.setStyle(Paint.Style.STROKE); 
    paint.setStrokeJoin(Paint.Join.ROUND); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
    for (Line l : lines) { 
     canvas.drawLine(l.startX, l.startY, l.stopX, l.stopY, paint); 
    } 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 

    if (event.getAction() == MotionEvent.ACTION_DOWN) { 
     lines.add(new Line(event.getX(), event.getY())); 
     return true; 
    } 
    else if ((event.getAction() == MotionEvent.ACTION_MOVE || 
     event.getAction() == MotionEvent.ACTION_UP) && 
     lines.size() > 0) { 
     Line current = lines.get(lines.size() - 1); 
     current.stopX = event.getX(); 
     current.stopY = event.getY(); 
     Invalidate(); 
     return true; 
    } 
    else { 
     return false; 
    } 
    } 
} 

回答

1

多小時的努力,我設法拿出一個算法來檢查點使用的混合物定線路後斜坡相交公式和if (x = startX && y > startY && y < stopY)下面是代碼,如果點在線,則返回true,否則爲false,希望這可以節省一些時間!

public boolean checkPosition(float x, float y, float sx, float sy, float ex, float ey) { 
     float mX = ex - sx; 
     float mY = ey - sy; 
     float smX = sx - ex; 
     float smY = sy - ey; 
     float pmX = mX; 
     float pmY = mY; 
     float psmX = smX; 
     float psmY = smY; 
     float yY = ey - y; 
     float xX = ex - x; 
     float sX = sx - x; 
     float sY = sy - y; 
     float m = mY/mX; 
     float b = sy - (m * sx); 
     if (mX < 0) { 
      pmX = mX * - 1; 
     } 
     if (mY < 0) { 
      pmY = mY * - 1; 
     } 
     if (smX < 0) { 
      psmX = smX * - 1; 
     } 
     if (smY < 0) { 
      psmY = smY * - 1; 
     } 
     if (yY < 0) { 
      yY = yY * - 1; 
     } 
     if (xX < 0) { 
      xX = xX * - 1; 
     } 
     if (sX < 0) { 
      sX = sX * - 1; 
     } 
     if (sY < 0) { 
      sY = sY * - 1; 
     } 
     if (sy == ey && y == sy) { 
      if (sx >= ex) { 
       if (x <= sx && x >= ex) return true; 
       else return false; 
      } 
      else if (ex >= sx) { 
       if (x <= ex && x >= sx) return true; 
       else return false; 
      } 
      else return false; 
     } 
     else if (sx == ex && x == sx) { 
      if (sy >= ey) { 
       if (y <= sy && y >= ey) return true; 
       else return false; 
      } 
      else if (ey >= sy) { 
       if (y <= ey && y >= sy) return true; 
       else return false; 
      } 
      else return false; 
     } 
     else if (xX <= pmX && sX <= psmX && yY <= pmY && sY <= psmY) { 
      if (y == (m * x) + b) return true; 
      else return false; 
     } 
     else return false; 
    } 
+0

如果mX = 0,您的解決方案可能會導致運行時錯誤。我在http://stackoverflow.com/questions/20887806/does-a-line-contain-a-point/23388247#23388247上發佈了一個較短的版本,可以解決這個問題。 –

2

我不知道是否有這個畫布庫,但手動,您可以:

  1. 通過你的線
  2. 形式方程的名單每行代表斜截式y = mx + b
  3. 插件中的event.X()和event.Y()代入上面的等式中作爲每行的x和y
  4. 如果2個邊都相等那麼你的觸摸事件是在該行
+0

我們如何計算截距? –

+0

(stopY-startY)/(stopX-startX) – jaesanx