要查找点P(x,y)是否位于具有中心(x1,y1)的圆内,有两种可能的方法:
在Point2D类中使用distance()函数。这个相当于距离公式法。
if (new Point(x1, y1).distance(x, y) < Diam/2)
在Ellipse2D.Double中使用contains()函数。这个检查点是否位于圆圈内。
if (new Ellipse2D.Double(x1, y1, Diam, Diam).contains(new Point(x, y)));
这两个函数都内置在java2D中。但出于好奇,我想知道哪一个在性能方面更快/更好。有什么想法吗?
答案 0 :(得分:3)
来自java来源:
的Point2D:
public static double distance(double x1, double y1,
double x2, double y2)
{
x1 -= x2;
y1 -= y2;
return Math.sqrt(x1 * x1 + y1 * y1);
}
Ellipse2D的:
public boolean contains(double x, double y) {
// Normalize the coordinates compared to the ellipse
// having a center at 0,0 and a radius of 0.5.
double ellw = getWidth();
if (ellw <= 0.0) {
return false;
}
double normx = (x - getX()) / ellw - 0.5;
double ellh = getHeight();
if (ellh <= 0.0) {
return false;
}
double normy = (y - getY()) / ellh - 0.5;
return (normx * normx + normy * normy) < 0.25;
}
所以椭圆几乎没有什么可做,但没有sqrt()。
但你为什么不绕圈子让我们知道呢? ;)
编辑:
因此,让我为您完成这些复杂的信息技术: (我很年轻,需要积分)
Point2D A = new Point2D.Double( 1.0, 2.0 );
Point2D B = new Point2D.Double( 2.0, 1.0 );
Ellipse2D E = new Ellipse2D.Double( 1.0, 2.0, 2.0, 1.0 );
double x = 1.0;
double c=0; // Keep compiler from optimizing
boolean y = false;
long start = System.currentTimeMillis();
for( long i=0; i<1000000000L; i++ ){
y |= E.contains( B );
}
long durA = System.currentTimeMillis() - start;
start = System.currentTimeMillis();
for( long i=0; i<1000000000L; i++ ){
c += A.distance( B ) - x/2.0;
}
long durB = System.currentTimeMillis() - start;
System.out.println( y ); // Keep compiler from optimizing
System.out.println( c );
System.out.printf( "%d / %d", durA, durB );
将在我的系统中产生:
324 / 946
正如其他人所指出的那样:速度的主要区别在于使用sqrt()来返回距离。 Ellipse2D中的比较不需要返回距离,可以使用更快的方法。
所以第二种方法更快。请注意,这是1,000,000,000次运行。所以实际上这种差异几乎不可察觉。因此,这不是“真正的”基准。有许多效果会导致明显不同的结果。
答案 1 :(得分:2)
最好的方法绝对是你不必采取平方根以应用毕达哥拉斯的方法。这意味着你不测试:
distance <= radius
但相反,你这样做:
distance^2 <= radius^2
这是一种方法:
/**
* @param x The x coordinate of the point to test.
* @param y The y coordinate of the point to test.
* @param cX The x coordinate of the center of the circle.
* @param cY The y coordinate of the center of the circle.
* @param r The radius of the circle.
*/
public static boolean liesInCircle(double x, double y, double cX, double cY, double r)
{
double dx = x - cX;
double dy = y - cY;
return dx * dx + dy * dy <= r * r;
}
答案 2 :(得分:0)
更快的方法实际上是
double dx = x1-x;
double dy = y1-y;
if(dx*dx+dy*dy< Diam*Diam/4)
因为它将避免在第一种方法中执行sqrt()
,并且比第二种方法更适合圆形。此外,您可以避免创建不会再次使用的对象。
答案 3 :(得分:0)
查看源代码,看起来Point
方法使用标准距离函数:
sqrt((x1 - x2)^2 + (y1 - y2)^2)
Ellipse
方法使用毕达哥拉斯定理的一些近似值:
((x - Cx) / (Dx - 0.5))^2 + ((y - Cy) / (Dy - 0.5))^2 < 0.25
正如已经指出的那样,Ellipse
方法应该更快,因为它不必使用平方根。