我该怎么写这个功能?任何赞赏的例子
function isPointBetweenPoints(currPoint, point1, point2):Boolean {
var currX = currPoint.x;
var currY = currPoint.y;
var p1X = point1.x;
var p1y = point1.y;
var p2X = point2.x;
var p2y = point2.y;
//here I'm stuck
}
答案 0 :(得分:41)
假设point1
和point2
不同,首先检查点是否在线上。为此,您只需要向量point1 -> currPoint
和point1 -> point2
的“交叉产品”。
dxc = currPoint.x - point1.x;
dyc = currPoint.y - point1.y;
dxl = point2.x - point1.x;
dyl = point2.y - point1.y;
cross = dxc * dyl - dyc * dxl;
当且仅当cross
等于零时,你的观点就在这一行上。
if (cross != 0)
return false;
现在,正如您所知道的那一点确实存在于线上,现在是时候检查是否位于原始点之间。这可以通过比较x
坐标,如果线条“比水平线更垂直”或“y
坐标”
if (abs(dxl) >= abs(dyl))
return dxl > 0 ?
point1.x <= currPoint.x && currPoint.x <= point2.x :
point2.x <= currPoint.x && currPoint.x <= point1.x;
else
return dyl > 0 ?
point1.y <= currPoint.y && currPoint.y <= point2.y :
point2.y <= currPoint.y && currPoint.y <= point1.y;
注意,如果输入数据是整数,则上述算法如果完全是整数,即它不需要整数输入的浮点计算。在计算cross
时要注意潜在的溢出。
P.S。该算法绝对精确,这意味着它将拒绝非常接近线但不精确在线上的点。有时这不是我们需要的。但那是一个不同的故事。
答案 1 :(得分:21)
Distance(point1,currPoint)+Distance(currPoint,point2)==Distance(point1,point2)
但是如果你有浮点值,请注意,它们的不同之处......
答案 2 :(得分:4)
您想检查从point1
到currPoint
的斜率是否与从currPoint
到point2
的斜率相同,所以:
m1 = (currY - p1Y) / (currX - p1X);
m2 = (p2Y - currY) / (p2X - currX);
您还想检查currPoint
是否在其他两个人创建的框内,所以:
return (m1 == m2) && (p1Y <= currY && currY <= p2Y) && (p1X <= currX && currX <= p2X);
编辑:这不是一个很好的方法;看看maxim1000's solution是否有更正确的方法。
答案 3 :(得分:3)
这与Javascript无关。尝试以下算法,点p1 = point1和p2 = point2,第三点是p3 = currPoint:
v1 = p2 - p1
v2 = p3 - p1
v3 = p3 - p2
if (dot(v2,v1)>0 and dot(v3,v1)<0) return between
else return not between
如果你想确定它位于p1和p2之间的线段上:
v1 = normalize(p2 - p1)
v2 = normalize(p3 - p1)
v3 = p3 - p2
if (fabs(dot(v2,v1)-1.0)<EPS and dot(v3,v1)<0) return between
else return not between
答案 4 :(得分:1)
准备好接受似乎比其他一些解决方案简单得多的方法了吗?
您向它传递三个点(三个具有 x 和 y 属性的对象)。点 1 和点 2 定义您的线,点 3 是您要测试的点。
function pointOnLine(pt1, pt2, pt3) {
const dx = (pt3.x - pt1.x) / (pt2.x - pt1.x);
const dy = (pt3.y - pt1.y) / (pt2.y - pt1.y);
const onLine = dx === dy
// Check on or within x and y bounds
const betweenX = 0 <= dx && dx <= 1;
const betweenY = 0 <= dy && dy <= 1;
return onLine && betweenX && betweenY;
}
console.log('pointOnLine({x: 0, y: 0}, {x: 1, y: 1}, {x: 2, y: 2})');
console.log(pointOnLine({ x: 0, y: 0 }, { x: 1, y: 1 }, { x: 2, y: 2 }));
console.log('pointOnLine({x: 0, y: 0}, {x: 1, y: 1}, {x: 0.5, y: 0.5})');
console.log(pointOnLine({ x: 0, y: 0 }, { x: 1, y: 1 }, { x: 0.5, y: 0.5 }));
编辑:根据 RBarryYoung 的观察进一步简化。
答案 5 :(得分:0)
如果要查找其他点是否位于其他两个点之间的直线上,则需要找到这些点的向量并计算这些向量的点积。
假设您有两个点A和B。还有要测试的点P。首先,您要计算向量PA,PB
然后计算那些向量DotProduct(PA,PB)的点积。为简化起见,我们假设计算是在2D模式下进行的。
test_dot_product = DotProduct(PA, PB) = PA.x * PB.x + PA.y * PB.y
因此,当计算点积时,我们需要检查其值是否小于或等于0。如果是,则意味着向量PA和PB朝向不同的方向,而点P位于A和B之间。否则,向量朝向相同的方向和点P在AB范围之外。
if(test_dot_product <= 0.0f){
Point P IS between A and B
}
else{
Point P IS NOT between A and B
}
这是一些示例代码。那是我引擎的2D物理光线投射系统的代码。当我找到射线的命中点和边缘时,我需要检查它是否在边缘的最小和最大点之间...
....
v2 HitPP1 = Edge->Min - HitData->HitPoint;
v2 HitPP2 = Edge->Max - HitData->HitPoint;
//NOTE(dima): If hit point is between edge min and max points
if (Dot(HitPP1, HitPP2) <= 0.0f) {
HitData->HitHappened = 1;
AtLeastOneHitHappened = 1;
}
.....
对不起,我的英语水平
答案 6 :(得分:0)
首先,我将检查区域,如果区域接近0,则该点位于直线上。
但是考虑一下AC的长度如此之大,然后Area远离0增长的情况,但是在视觉上,我们仍然看到B在AC上:当我们需要检查三角形的高度时。< / p>
为此,我们需要记住从一年级学习的公式:Area = Base * Height / 2
代码如下:
bool Is3PointOn1Line(IList<Vector2> arrVert, int idx1, int idx2, int idx3)
{
//check if the area of the ABC triangle is 0:
float fArea = arrVert[idx1].x * (arrVert[idx2].y - arrVert[idx3].y) +
arrVert[idx2].x * (arrVert[idx3].y - arrVert[idx1].y) +
arrVert[idx3].x * (arrVert[idx1].y - arrVert[idx2].y);
fArea = Mathf.Abs(fArea);
if (fArea < SS.EPSILON)
{
//Area is zero then it's the line
return true;
}
else
{
//Check the height, in case the triangle has long base
float fBase = Vector2.Distance(arrVert[idx1], arrVert[idx3]);
float height = 2.0f * fArea / fBase;
return height < SS.EPSILON;
}
}
用法:
Vector2[] arrVert = new Vector2[3];
arrVert[0] = //...
arrVert[1] = //...
arrVert[2] = //...
if(Is3PointOn1Line(arrVert, 0, 1, 2))
{
//Ta-da, they're on same line
}
PS:SS.EPSILON = 0.01f,我使用了Unity的某些功能(例如Vector2.Distance
),但您明白了。