在Java中,如何确定某个点是否在GeneralPath的边界上?

时间:2012-11-27 03:01:31

标签: java

我发现Java中的GeneralPath类仅提供检查点是否在一般路径内的方法(具体而言,具有直线段的多边形)。有人知道如何 有效地 检查一个点是否在一般路径的边界上?

由于

虚拟解决方案1:我们可以定义一个半径为$ \ epsilon $的圆($ \ epsilon $是一个非常小的正实数值)。然后,我们检查圆上足够数量的点,看看它们中的一个/一些是否属于一般路径。然而,这种虚拟方法可能需要大量的计算工作,这是不太理想的。

虚拟解2:我们可以计算从点(在边界上)到多边形每一边的距离。如果最小距离足够小,则该点位于边界上;否则,它不是。同样,这种方法仍然可以计算密集。

2 个答案:

答案 0 :(得分:4)

我没有遇到过库方法......或是问题的封装解决方案。我认为原因是问题根本无法完全解决。

GeneralPath类继承了getPathIterator中名为Shape2D的方法。如果查看javadoc,您将看到PathIterator对象将路径建模为一系列直线段。 getPathIterator方法采用如下指定的flatness参数:

  

“平坦度 - 允许线段用于近似弯曲段的最大距离偏离原始曲线上的任何点。”

现在,如果您正在查看的形状由直线段组成,则路径迭代器很可能会为您提供这些线段。但如果形状具有弯曲段,则线段仅是近似值。如果你不知道确切的边界是什么,显然不可能测试一个点是否正好在边界上。

即使假设线段精确地模拟真实曲线,您仍然存在问题(除特殊情况外),真实曲线上的大多数点无法使用Java原始数据类型(int,double等)精确表示)。所以再一次“准确性”是有问题的。

我认为你能想到的最好的方法是测试你的点是否在边界的一个小的delta内...并选择一个小于该delta的flatness值,迭代路径线段,并测试每个段的点的切向距离。

注意:如果使flatness非常小,则可能需要测试大量的线段。在坚持使用GeneralPath API时,我认为没有办法解决这个计算问题。


如果将问题限制为真(即直边)多边形,那么您只需要迭代线段,并为每一个测试查看从点到线的距离是否小于某个合适的epsilon 。 This Wikipedia entry为您提供数学知识。请注意,这里的确切性仍然是一个问题......

您没有极其昂贵的计算,但计算精确的平方根不是免费的,并且您必须为N边多边形执行N次。

做得比这更好(即比O(N)更好)将是困难的。但是,如果多边形是固定的,并且您要测试大量的点,那么您可以考虑使用预先计算四叉树数据结构来进行分辨率。预先计算四叉树将是昂贵的,但如果N足够大,测试点将更便宜。 (在最坏的情况下粗略O(log(1/epsilon)),而不是O(N)平均而言。距离边界越远,答案就越便宜。)

但正如我所说,四叉树只会在有限的情况下提供帮助......

答案 1 :(得分:1)

您可以使用描边路径。 BasicStroke有方法

public Shape createStrokedShape(Shape s)

因此,只需定义粗线BasicStroke,获取描边形状并检查描边的Shape是否包含您的点。