简体   繁体   English

Android Canvas检查Point是否在线

[英]Android Canvas Check if Point is on Line

I have a Custom View which draws lines an saves them to an ArrayList. 我有一个自定义视图,它绘制线条并将它们保存到ArrayList。 What I want to be able to do is check if a specified point is on a line inside the Arraylist and return the line. 我想要做的是检查指定点是否在Arraylist内的一行上并返回该行。 I have been able to do this when the line is straight by using if (l.startX == l.stopX && l.startY < l.stopY but this doesn't work if the line is on an angle. I would also like to do this with drawText and drawCircle. Is there some simple way of doing this that I have missed? 通过使用if (l.startX == l.stopX && l.startY < l.stopY但是如果线条处于某个角度,这不起作用,我已经能够做到这一点。我也想用drawText和drawCircle做这个。有没有一些简单的方法可以做到这一点,我错过了?

DrawView.java 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;
    }
  }
}

I don't know if there is a canvas library for this but manually you can: 我不知道是否有一个画布库,但手动你可以:

  1. go through your list of lines 浏览你的行列表
  2. form equations for each line in let's say slope-intercept form y = mx + b 我们说每条线的形式方程式斜率截距形式y = mx + b
  3. plugin in the event.X() and event.Y() into the above equation as x and y for each line 将event.X()和event.Y()插入上面的等式中,每行代表x和y
  4. if the 2 sides are equal then your touch event is on that line 如果两边相等,则您的触摸事件就在该线上

After many hours of trying I managed to come up with a an algorithm to check if a point is on a given line using a mixture of slope-intersect formula and if (x = startX && y > startY && y < stopY) Below is the code, it returns true if point is on line otherwise false, hopefully this can save someone time! 经过几个小时的尝试,我设法得出一个算法来检查一个点是否在给定的线上使用if (x = startX && y > startY && y < stopY)公式的混合和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;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM