Android:如何检查路径是否包含接触点?
我会尝试开发一个应用程序,在其中我可以画一个平面图。因此,每个房间都有自己的ID或名称,如果我触摸一个房间,我想用该ID或名称显示祝酒词。问题是如何检查是否接触以及接触的路径 我看到很多关于这个问题的专题讨论。有人说要使用Android:如何检查路径是否包含接触点?,android,path,drawable,contains,android-canvas,Android,Path,Drawable,Contains,Android Canvas,我会尝试开发一个应用程序,在其中我可以画一个平面图。因此,每个房间都有自己的ID或名称,如果我触摸一个房间,我想用该ID或名称显示祝酒词。问题是如何检查是否接触以及接触的路径 我看到很多关于这个问题的专题讨论。有人说要使用getBounds方法,然后包含检查接触点是否在Rect中的方法。但是,我猜getBounds返回包含路径的最小Rect,对吗 所以,房间有不同的自定义几何形式,出于这个原因,若我得到两个封闭房间的边界,该方法可以返回一组共享的点。糟糕!每个房间只有它们的面积点。我怎样才能解决
getBounds
方法,然后包含检查接触点是否在Rect中的方法。但是,我猜getBounds
返回包含路径的最小Rect
,对吗
所以,房间有不同的自定义几何形式,出于这个原因,若我得到两个封闭房间的边界,该方法可以返回一组共享的点。糟糕!每个房间只有它们的面积点。我怎样才能解决这个问题
在iOS中,我可以使用
PathContainsPoint
方法,但不幸的是,Android Path没有类似的功能。好的,我解决了我的问题。我发布了示例代码:
Path p;
Region r;
@Override
public void onDraw(Canvas canvas) {
p = new Path();
p.moveTo(50, 50);
p.lineTo(100, 50);
p.lineTo(100, 100);
p.lineTo(80, 100);
p.close();
canvas.drawPath(p, paint);
RectF rectF = new RectF();
p.computeBounds(rectF, true);
r = new Region();
r.setPath(p, new Region((int) rectF.left, (int) rectF.top, (int) rectF.right, (int) rectF.bottom));
}
public boolean onTouch(View view, MotionEvent event) {
Point point = new Point();
point.x = event.getX();
point.y = event.getY();
points.add(point);
invalidate();
Log.d(TAG, "point: " + point);
if(r.contains((int)point.x,(int) point.y))
Log.d(TAG, "Touch IN");
else
Log.d(TAG, "Touch OUT");
return true;
}
这里有一个想法:创建一条新的路径,它是一个围绕被接触点的小正方形,然后将该路径与要使用的路径相交,看看结果是否为空。正如Edward Falk所说,最好的方法是使用,因为区域是正方形的。一个点可以在2或3个区域中。例如: 所有区域都将包含蓝点,但实际上只有path4包含此点
int x, y;
Path tempPath = new Path(); // Create temp Path
tempPath.moveTo(x,y); // Move cursor to point
RectF rectangle = new RectF(x-1, y-1, x+1, y+1); // create rectangle with size 2xp
tempPath.addRect(rectangle, Path.Direction.CW); // add rect to temp path
tempPath.op(pathToDetect, Path.Op.DIFFERENCE); // get difference with our PathToCheck
if (tempPath.isEmpty()) // if out path cover temp path we get empty path in result
{
Log.d(TAG, "Path contains this point");
return true;
}
else
{
Log.d(TAG, "Path don't contains this point");
return false;
}
Region和path.op()方法工作正常,但缺乏精确性。在一些测试之后,它们似乎在路径的段级别定义了一个区域,如下所示:。另一种方法是与客户合作。虽然效果更好,但它仍然记录了一些意想不到的触动,并忽略了明显的触动。但还有另一种解决方案,它包括沿着路径检索一组点,并在它们周围的区域内注册触摸。为此,我们可以使用PathMeasure
类获得所需的点数,并将它们存储在列表中
:
PathMeasure-PathMeasure=新的PathMeasure(路径,false);
List listFloat=new ArrayList();
对于(浮动i=0;i<1.1;i+=0.1){
浮点[]点坐标=新浮点[2];
getPosTan(pathMeasure.getLength()*i,点坐标,null);
添加(点坐标[0]);
添加(点坐标[1]);
}
然后,我们需要循环查看列表
,并检查触摸事件是否位于围绕这些点的定义区域内。这里,一个区域覆盖了路径长度的十分之一,因为我们收集了十个点:
float areaLength = pathMeasure.getLength() / 20; // since we collect ten points, we define a zone covering a tenth of path length
for (int i = 0; i < listFloat.size() - 1; i += 2) {
if (touchX > listFloat.get(i) - areaLength
&& touchX < listFloat.get(i) + areaLength
&& touchY > listFloat.get(i+1) - areaLength
&& touchY < listFloat.get(i+1) + areaLength) {
Log.d(TAG, "path touched");
}
}
float areaLength=pathMeasure.getLength()/20;//因为我们收集了10个点,所以我们定义了一个覆盖路径长度十分之一的区域
对于(int i=0;ilistFloat.get(i)-areaLength
&&touchXlistFloat.get(i+1)-区域长度
&&touchY
这些连续区域以更高的精度捕捉触摸事件,更接近路径:。
可以通过使用
Rect
类来改进此方法,以确保这些区域不相互重叠,并以更高的精度绑定起点和终点。这可以识别路径周围而不是多段线上给定边界多边形中的触摸事件。确切地说,我所寻找的并不重要。我保存了每个接触点是为了我自己的目的。很显然,在onDraw中创建新的RectF和区域对性能不好,如果可能的话可以更好地重用。我有另一个路径而不是事件(x,y),所以我如何检查我的一个路径是否在当前路径内?是的,但您仅限于API 19和更高版本。还有其他解决方案吗?谢谢,我已经通过对路径进行子类化并跟踪所有点来解决它,然后我使用了这个公式并将其改写为Java。我想如果您愿意,我可以发布一个完整解决方案的答案。我不确定这是否对任何人都有帮助。这个答案不起作用。也许这是故意的行为,也许是一个bug。我使用Path.op(uuu,Path.op.INTERSECT)
查看路径是否与以(x,y)为中心的小矩形相交,并且当(x,y)相对靠近路径,但不在路径内部时,它有时会返回非空的交点。注意,我的路径是由直线组成的,有时直线会自行延伸。还要注意,这不仅仅是因为我为op()
创建的“小矩形”不够小@巴坦多我对你的解决方案感兴趣你能把答案贴出来吗?
float areaLength = pathMeasure.getLength() / 20; // since we collect ten points, we define a zone covering a tenth of path length
for (int i = 0; i < listFloat.size() - 1; i += 2) {
if (touchX > listFloat.get(i) - areaLength
&& touchX < listFloat.get(i) + areaLength
&& touchY > listFloat.get(i+1) - areaLength
&& touchY < listFloat.get(i+1) + areaLength) {
Log.d(TAG, "path touched");
}
}