2

从谷歌地球我得到了一个带有图片坐标的框,如下所示:

    <LatLonBox>
        <north>53.10685</north>
        <south>53.10637222222223</south>
        <east>8.853144444444444</east>
        <west>8.851858333333333</west>
        <rotation>-26.3448</rotation>
    </LatLonBox>

现在我想测试一个与这个 LatLonBox 相交的点的天气。我的基本想法是检查一个点是否与 LatLonBox 相交,将点旋转给定角度,然后测试该点是否与常规(未旋转)矩形相交。

我试图手动计算旋转:

public static MyGeoPoint rotatePoint(MyGeoPoint point, MyGeoPoint origion, double degree)
{
double x = origion.getLatitude() + (Math.cos(Math.toRadians(degree)) * (point.getLatitude() - origion.getLatitude()) - Math.sin(Math.toRadians(degree)) * (point.getLongitude() - origion.getLongitude()));
double y =  origion.getLongitude()  + (Math.sin(Math.toRadians(degree)) * (point.getLatitude() - origion.getLatitude()) + Math.cos(Math.toRadians(degree))  * (point.getLongitude() - origion.getLongitude()));

return new MyGeoPoint(x, y);

}

public boolean intersect(MyGeoPoint geoPoint)
{   
    geoPoint = MyGeoPoint.rotatePoint(geoPoint, this.getCenter(), - this.getRotation());
    
    return (geoPoint.getLatitude() < getTopLeftLatitude()
            && geoPoint.getLatitude() > getBottomRightLatitude()
                && geoPoint.getLongitude() > getTopLeftLongitude()
                    && geoPoint.getLongitude() < getBottomRightLongitude());
}

结果似乎是错误的。

    LatLonBox box = new LatLonBox(53.10685, 8.851858333333333, 53.10637222222223, 8.853144444444444, -26.3448);
    
    MyGeoPoint point1 = new MyGeoPoint(53.106872, 8.852311);
    MyGeoPoint point2 = new MyGeoPoint(53.10670378322918, 8.852967186822669);   
    MyGeoPoint point3 = new MyGeoPoint(53.10652664993972, 8.851994565566875);
    MyGeoPoint point4 = new MyGeoPoint(53.10631650700605, 8.85270995172055);
    
    System.out.println(box.intersect(point1));
    System.out.println(box.intersect(point2));
    System.out.println(box.intersect(point3));
    System.out.println(box.intersect(point4));

结果是真,假,假,真。但它应该是真实的 4 倍。可能是我,在推理中犯了某种错误。也许是因为纬度值向上变大。但我不知道如何更改公式。

我需要一些帮助 ...


编辑:我认为我的基本想法和公式是正确的。我也找到了类似的解决方案,例如。链接,找不到任何区别。

所以我认为唯一可能的误差源是轴不成比例。所以问题是如何考虑这一点。

我希望有人有一个想法。

4

3 回答 3

4

问题确实是轴不成比例。

以下方法可以解决它。

public static MyGeoPoint rotatePoint(MyGeoPoint point, MyGeoPoint origion, double degree)
{
double x =  origion.longitude   + (Math.cos(Math.toRadians(degree)) * (point.longitude - origion.longitude) - Math.sin(Math.toRadians(degree))  * (point.latitude - origion.latitude) / Math.abs(Math.cos(Math.toRadians(origion.latitude)));
double y = origion.latitude + (Math.sin(Math.toRadians(degree)) * (point.longitude - origion.longitude) * Math.abs(Math.cos(Math.toRadians(origion.latitude))) + Math.cos(Math.toRadians(degree))   * (point.latitude - origion.latitude));
return new MyGeoPoint(x, y);
}
于 2012-10-11T14:04:26.607 回答
0

The problem appears to be that the data structure LatLonBox doesn't make any sense as a description for the boundary of a picture. A box in lat-lon coordinates is not a geometric rectangle. (Think about a box near or including the north pole.) You need to re-think your application to deal in a lat/lon coordinate for the center of the picture and then deal with the rotation as an angle with respect to lines of latitude (parallel to the equator). (Even then, a picture with center on the north or south pole will be a degenerate case that must be handled separately.) So a box should properly be something like:

<geobox>
  <center_lat>41</center_lat>
  <center_lon>-74</center_lon>
  <rotation_degrees_ccw>-23</rotation_degrees_ccw>
  <width>1000</width> <!-- in pixels or meters, but not in degrees! -->
  <height>600</height> <!-- same as above -->
</geobox>

Having said all that, suppose you have a true geometric box centered at (x0,y0), width w, height h, rotated angle T about its center. Then you can test a point P(x,y) for membership in the box with the following. You need the transformation that takes the box to the origin and aligns it with the axes. This is Translate(-x0,-y0) then Rotate(-T). This transformation as a matrix is

[cos(-T) -sin(-T) 0][1 0 -x0]   [ cos(T)  sin(T) -x0*cos(T)-y0*sin(T)]
[sin(-T)  cos(-T) 0][0 1 -y0] = [-sin(T)  cos(T)  x0*sin(T)-y0*cos(T)]
[0        0       1][0 0   1]   [  0        0                  1     ]

You want to apply this transformation to the point to be tested and then see if it lies in the desired box:

// Transform the point to be tested.
ct = cos(T);
st = sin(T);
xp =  ct * x + st * y - x0 * ct - y0 * st;
yp = -st * x + ct * y + x0 * st - y0 * ct;
// Test for membership in the box.
boolean inside = xp >= -w/2 && xp <= w/2 && yp >= -h/2 && yp <= h/2;

It's late and I haven't checked this arithmetic, but it's close. Say if it doesn't work.

于 2012-10-10T02:48:44.057 回答
0

如果我理解正确,您想检查这四个点是否在旋转矩形中。

我建议不要检查角点,因为您的矩形是旋转的,但是:

如果您旋转了矩形 ABCD,则计算线 |AB|、|BC|、|CD| 和|DA|。如果您有两个点,则使用 y=ax+b (您将通过给出两个坐标的 [x,y] 来计算 a,b,从而为您提供两个简单的等式)。

最后函数 intersect 将检查

  if point <= line |CD| 
      AND point >= line |AB|
          AND point <= line |BC|
             AND point >= |DA|

然后它在矩形内。

这可以在您将点 P[x,y] 放入 ax+y+b(a>0 或 -ax-yb)时完成。如果它为零,则它位于该线上,如果它是 < 则它位于该线下方或“在左侧”。希望我帮助..

顺便说一句,你为什么使用 -degree 值,乘以 -1 ,有必要吗?

于 2012-10-05T12:26:57.607 回答