Javascript 确定一个点是否位于由3个给定纬度/经度的点组成的三角形内

Javascript 确定一个点是否位于由3个给定纬度/经度的点组成的三角形内,javascript,geometry,geolocation,Javascript,Geometry,Geolocation,我有3个点(lat,lon)组成一个三角形。我如何才能找到一个点是否在这个三角形内?大多数语言都包含一个函数。在Java中,它是Polygon.contains() 只需从点创建多边形,然后在测试点上调用contains()。尝试光线投射算法 实现起来非常简单 function SameSide(p1,p2, a,b) cp1 = CrossProduct(b-a, p1-a) cp2 = CrossProduct(b-a, p2-a) if DotProduct(c

我有3个点(lat,lon)组成一个三角形。我如何才能找到一个点是否在这个三角形内?

大多数语言都包含一个函数。在Java中,它是Polygon.contains()


只需从点创建多边形,然后在测试点上调用contains()。

尝试光线投射算法

实现起来非常简单

function SameSide(p1,p2, a,b)
    cp1 = CrossProduct(b-a, p1-a)
    cp2 = CrossProduct(b-a, p2-a)
    if DotProduct(cp1, cp2) >= 0 then return true
    else return false

function PointInTriangle(p, a,b,c)
    if SameSide(p,a, b,c) and SameSide(p,b, a,c)
        and SameSide(p,c, a,b) then return true
    else return false
在下面的链接中解释


您可以使用点多边形测试

很简单。从你的点向东画一条线,距离足够远。数一数这条线与你的plygon相交的次数。如果它是偶数,你的点在外面,如果是奇数,你的点在里面


这适用于任何类型的多边形。

主要问题是是否可以使用二维近似值(换句话说,三角形是否足够小)


如果是这样,像重心坐标这样简单的东西会很好用。

我今天做了类似的事情!还有(lat,lon),实际上是(theta,phi),虽然我对我使用的网格了解得更多一些。我正在使用(θ,phi)和0Java代码处理三角形,即3个点

    public static boolean pntInTriangle(double px, double py, double x1, double y1, double x2, double y2, double x3, double y3) {

    double o1 = getOrientationResult(x1, y1, x2, y2, px, py);
    double o2 = getOrientationResult(x2, y2, x3, y3, px, py);
    double o3 = getOrientationResult(x3, y3, x1, y1, px, py);

    return (o1 == o2) && (o2 == o3);
}

private static int getOrientationResult(double x1, double y1, double x2, double y2, double px, double py) {
    double orientation = ((x2 - x1) * (py - y1)) - ((px - x1) * (y2 - y1));
    if (orientation > 0) {
        return 1;
    }
    else if (orientation < 0) {
        return -1;
    }
    else {
        return 0;
    }
}
公共静态布尔pntInTriangle(双px、双py、双x1、双y1、双x2、双y2、双x3、双y3){
double o1=getOrientationResult(x1,y1,x2,y2,px,py);
double o2=getOrientationResult(x2,y2,x3,y3,px,py);
double o3=getOrientationResult(x3,y3,x1,y1,px,py);
回报率(o1==o2)和&(o2==o3);
}
私有静态int getOrientationResult(双x1、双y1、双x2、双y2、双px、双py){
双取向=((x2-x1)*(py-y1))-((px-x1)*(y2-y1));
如果(方向>0){
返回1;
}
否则如果(方向<0){
返回-1;
}
否则{
返回0;
}
}

这里是重心坐标解决方案的Javascript实现:

//如果顶点位于A、B和C的三角形内的点P为true
//将二维向量和点表示为[x,y]。基于
// http://www.blackpawn.com/texts/pointinpoly/default.html
函数点intriange(P,A,B,C){
//计算向量
函数vec(from,to){return[to[0]-from[0],to[1]-from[1]];}
var v0=向量(A,C);
var v1=向量向量(A,B);
var v2=向量向量(A,P);
//计算点积
函数点(u,v){返回u[0]*v[0]+u[1]*v[1];}
var dot00=点(v0,v0);
var dot01=点(v0,v1);
var dot02=点(v0,v2);
var dot11=点(v1,v1);
var dot12=点(v1,v2);
//计算重心坐标
var invDenom=1.0/(dot00*dot11-dot01*dot01);
变量u=(dot11*dot02-dot01*dot12)*INVDNOM;
变量v=(dot00*dot12-dot01*dot02)*INVDNOM;
//检查点是否在三角形中
返回值(u>=0)和(v>=0)和(u+v<1);
}

据说它比基于交叉积的解决方案更快。

这不是一个Project Euler问题吗?您的三角形可能有多大?它是否足够小,以至于可以认为表面是平的,或者你需要球面几何体?马克说得更进一步,你如何定义“内部”和“外部”?如果你的点是火奴鲁鲁、曼谷和拉各斯,那么三角形边缘大致沿着赤道,北极在里面还是南极在里面?首先我有一个起点a。我计算一个距离500米的点B,方位为60度。点C也是500米,但方位为120度。我想知道一个点是否在该区域内,角度范围为60度(从60度到120度).B和C有相同的lon。我不知道我是否帮了你。这不是真正的语言,而是本例中语言提供的框架。知道软件的功能总是很好的。对于像查找点是否位于三角形内这样简单的问题,我不认为使用多边形是最佳/最有效的解决方案。我同意@Christo。您并不总是可以使用
awt
。这并不理想,因为Polygon.contains()支持任何类型的多边形,因此,与其他答案中提供的其他手动(但简单)解决方案相比,该算法更加复杂和繁重。此外,awt并不是Java开发人员通常疯狂使用的一组类。我不完全理解它是如何工作的。getOrientationResult中的神奇表达式从何而来?方向公式是错误的。我找到了多个来源,证实了点P1、P2和P3的三角形的公式是:(P1.x-P3.x)*(P2.y-P3.y)-(P1.y-P3.y)*(P2.x-P3.x);另外,三个三角形的方向必须和原始三角形的方向相同,这里没有提到。来源(抱歉,它们是西班牙语的,但是公式是通用的;-)在这个例子中有太多的“魔力”
CrossProduct
永远不会被导出。如果使用这种方法,请确保处理边的情况-两条平行线可以有无限多个交点。棘手的是,当它是嵌入在3d球体上的2d空间时,三角形的边不是线,它们是伟大的圆弧。从技术上讲,你仍然可以使用重心坐标,但距离函数是不同的,你必须处理周期性,这只是一个巨大的麻烦。对于较大或放置不方便的三角形,所需答案与二维三角形答案不完全匹配。
// Returns true if point P inside the triangle with vertices at A, B and C
// representing 2D vectors and points as [x,y]. Based on                        
// http://www.blackpawn.com/texts/pointinpoly/default.html
function pointInTriange(P, A, B, C) {
  // Compute vectors        
  function vec(from, to) {  return [to[0] - from[0], to[1] - from[1]];  }
  var v0 = vec(A, C);
  var v1 = vec(A, B);
  var v2 = vec(A, P);
  // Compute dot products
  function dot(u, v) {  return u[0] * v[0] + u[1] * v[1];  }
  var dot00 = dot(v0, v0);
  var dot01 = dot(v0, v1);
  var dot02 = dot(v0, v2);
  var dot11 = dot(v1, v1);
  var dot12 = dot(v1, v2);
  // Compute barycentric coordinates
  var invDenom = 1.0 / (dot00 * dot11 - dot01 * dot01);
  var u = (dot11 * dot02 - dot01 * dot12) * invDenom;
  var v = (dot00 * dot12 - dot01 * dot02) * invDenom;
  // Check if point is in triangle
  return (u >= 0) && (v >= 0) && (u + v < 1);
}