确定:是线段上的点
determinate: is point on line segment
我正在尝试编写一个 java 方法,其中 returns 如果点 (x,y) 在线段上则为布尔值 true,否则为 false。
我试过这个:
public static boolean OnDistance(MyLocation a, MyLocation b, MyLocation queryPoint) {
double value = java.lang.Math.signum((a.mLongitude - b.mLongitude) * (queryPoint.mLatitude - a.mLatitude)
- (b.mLatitude - a.mLatitude) * (queryPoint.mLongitude - a.mLongitude));
double compare = 1;
if (value == compare) {
return true;
}
return false;
}
但是没用。
我不是 JAVA 编码员,所以我坚持数学背后......对于初学者,假设你在平面上(不是球面)
我会使用矢量数学,所以让:
a,b
- 是线的端点
q
- 查询点
c=q-a
- 查询的线方向向量
d=b-a
- 直线方向矢量
参数提取使用点积
t=dot(c,d)/(|c|*|d|)
t
是行参数 <0,1>
如果超出范围 q
不在行内
|c|=sqrt(c.x*c.x+c.y*c.y)
矢量大小
dot(c,d)=c.x*d.x+c.y*d.y
标量向量相乘
现在计算线上的对应点
e=a+(t*d)
e
是直线 ab
上最接近 q
的点
计算q
和ab
的垂直距离
l=|q-e|;
if (l>treshold)
then q
不在行 ab
否则它在行 ab
。阈值是距离您仍接受为内线的最大距离。无需 l
sqrt-ed 阈值常量可以由 2 代替以提高速度。
如果将所有这些添加到单个方程式
然后有些事情会自己简化(希望没有犯一些愚蠢的数学错误)
l=|(q-a)-(b-a)*(dot(q-a,b-a)/|b-a|^2)|;
return (l<=treshold);
或
l=|c-(d*dot(c,d)/|d|^2)|;
return (l<=treshold);
如您所见,我们甚至不需要 sqrt
:)
[注释]
如果您需要球面或椭圆面,那么您需要将其指定得更近一些,即半轴是什么。该线变为 arc/curve 并需要根据表面形状进行一些修正,请参见
但也可以通过近似来完成,也可以通过点 e
的二进制搜索来完成,请参阅:
- mine approx class in C++
所用到的矢量数学可以在文末找到:
这里是3D C++实现(名称不同):
double distance_point_axis(double *p,double *p0,double *dp)
{
int i;
double l,d,q[3];
for (i=0;i<3;i++) q[i]=p[i]-p0[i]; // q = p-p0
for (l=0.0,i=0;i<3;i++) l+=dp[i]*dp[i]; // l = |dp|^2
for (d=0.0,i=0;i<3;i++) d+=q[i]*dp[i]; // d = dot(q,dp)
if (l<1e-10) d=0.0; else d/=l; // d = dot(q,dp)/|dp|^2
for (i=0;i<3;i++) q[i]-=dp[i]*d; // q=q-dp*dot(q,dp)/|dp|^2
for (l=0.0,i=0;i<3;i++) l+=q[i]*q[i]; l=sqrt(l); // l = |q|
return l;
}
其中p0[3]
为轴上任意点,dp[3]
为轴方向向量。 p[3]
是您想要轴距离的查询点。
我正在尝试编写一个 java 方法,其中 returns 如果点 (x,y) 在线段上则为布尔值 true,否则为 false。
我试过这个:
public static boolean OnDistance(MyLocation a, MyLocation b, MyLocation queryPoint) {
double value = java.lang.Math.signum((a.mLongitude - b.mLongitude) * (queryPoint.mLatitude - a.mLatitude)
- (b.mLatitude - a.mLatitude) * (queryPoint.mLongitude - a.mLongitude));
double compare = 1;
if (value == compare) {
return true;
}
return false;
}
但是没用。
我不是 JAVA 编码员,所以我坚持数学背后......对于初学者,假设你在平面上(不是球面)
我会使用矢量数学,所以让:
a,b
- 是线的端点q
- 查询点c=q-a
- 查询的线方向向量d=b-a
- 直线方向矢量参数提取使用点积
t=dot(c,d)/(|c|*|d|)
t
是行参数<0,1>
如果超出范围q
不在行内|c|=sqrt(c.x*c.x+c.y*c.y)
矢量大小dot(c,d)=c.x*d.x+c.y*d.y
标量向量相乘现在计算线上的对应点
e=a+(t*d)
e
是直线ab
上最接近 计算
的垂直距离q
和ab
l=|q-e|;
if
(l>treshold)
thenq
不在行ab
否则它在行ab
。阈值是距离您仍接受为内线的最大距离。无需l
sqrt-ed 阈值常量可以由 2 代替以提高速度。如果将所有这些添加到单个方程式
然后有些事情会自己简化(希望没有犯一些愚蠢的数学错误)
l=|(q-a)-(b-a)*(dot(q-a,b-a)/|b-a|^2)|; return (l<=treshold);
或
l=|c-(d*dot(c,d)/|d|^2)|; return (l<=treshold);
如您所见,我们甚至不需要
sqrt
:)
q
的点
[注释]
如果您需要球面或椭圆面,那么您需要将其指定得更近一些,即半轴是什么。该线变为 arc/curve 并需要根据表面形状进行一些修正,请参见
但也可以通过近似来完成,也可以通过点 e
的二进制搜索来完成,请参阅:
- mine approx class in C++
所用到的矢量数学可以在文末找到:
这里是3D C++实现(名称不同):
double distance_point_axis(double *p,double *p0,double *dp)
{
int i;
double l,d,q[3];
for (i=0;i<3;i++) q[i]=p[i]-p0[i]; // q = p-p0
for (l=0.0,i=0;i<3;i++) l+=dp[i]*dp[i]; // l = |dp|^2
for (d=0.0,i=0;i<3;i++) d+=q[i]*dp[i]; // d = dot(q,dp)
if (l<1e-10) d=0.0; else d/=l; // d = dot(q,dp)/|dp|^2
for (i=0;i<3;i++) q[i]-=dp[i]*d; // q=q-dp*dot(q,dp)/|dp|^2
for (l=0.0,i=0;i<3;i++) l+=q[i]*q[i]; l=sqrt(l); // l = |q|
return l;
}
其中p0[3]
为轴上任意点,dp[3]
为轴方向向量。 p[3]
是您想要轴距离的查询点。