Java 已知两点经纬度以及方向角,判断两点直线是否相交,若相交求交点经纬度
时间: 2023-08-16 22:06:25 浏览: 167
判断两条直线相交算法
5星 · 资源好评率100%
可以使用以下步骤解决这个问题:
1. 将经纬度转换为直角坐标系的点,这可以通过以下公式实现:x = R * cos(lat) * cos(lon),y = R * cos(lat) * sin(lon),z = R * sin(lat),其中 R 是地球半径,lat 和 lon 分别是纬度和经度。
2. 根据第一个点的经纬度、方向角和距离计算出第一个点的终点坐标。
3. 同样的,根据第二个点的经纬度、方向角和距离计算出第二个点的终点坐标。
4. 计算第一个点到第二个点的向量和交点向量,如果两个向量平行,则两条线段不相交;否则,它们相交。
5. 如果两条线段相交,则计算它们的交点。可以使用以下公式计算:交点 = P1 + (P2 - P1) * t1,其中 P1 和 P2 分别是两个线段的起点和终点,t1 是第一个线段上与第二个线段相交的位置。
6. 将交点的直角坐标系转换回经纬度。
下面是 Java 代码的示例,用于计算两条线段是否相交并找到它们的交点:
```java
public class LineIntersection {
static final double EARTH_RADIUS = 6378137; // 地球半径,单位为米
static class Point {
double x, y, z;
Point(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
}
static Point toCartesian(double lat, double lon) {
double x = EARTH_RADIUS * Math.cos(Math.toRadians(lat)) * Math.cos(Math.toRadians(lon));
double y = EARTH_RADIUS * Math.cos(Math.toRadians(lat)) * Math.sin(Math.toRadians(lon));
double z = EARTH_RADIUS * Math.sin(Math.toRadians(lat));
return new Point(x, y, z);
}
static Point move(Point p, double distance, double azimuth) {
double lat1 = Math.asin(p.z / EARTH_RADIUS); // 起点纬度
double lon1 = Math.atan2(p.y, p.x); // 起点经度
double lat2 = Math.asin(Math.sin(lat1) * Math.cos(distance / EARTH_RADIUS)
+ Math.cos(lat1) * Math.sin(distance / EARTH_RADIUS) * Math.cos(azimuth));
double lon2 = lon1 + Math.atan2(Math.sin(azimuth) * Math.sin(distance / EARTH_RADIUS) * Math.cos(lat1),
Math.cos(distance / EARTH_RADIUS) - Math.sin(lat1) * Math.sin(lat2));
return toCartesian(Math.toDegrees(lat2), Math.toDegrees(lon2));
}
static boolean intersect(Point p1, Point p2, Point q1, Point q2) {
Point v1 = new Point(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z); // p1 -> p2 的向量
Point v2 = new Point(q2.x - q1.x, q2.y - q1.y, q2.z - q1.z); // q1 -> q2 的向量
Point v3 = new Point(q1.x - p1.x, q1.y - p1.y, q1.z - p1.z); // p1 -> q1 的向量
Point n1 = new Point(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x); // v1 和 v2 的叉积
double d = n1.x * v3.x + n1.y * v3.y + n1.z * v3.z; // n1 和 v3 的点积
if (Math.abs(d) < 1e-6) {
return false; // 平行,不相交
}
double t1 = (v2.x * v3.y - v2.y * v3.x) / d;
double t2 = (v1.x * v3.y - v1.y * v3.x) / d;
return t1 >= 0 && t1 <= 1 && t2 >= 0 && t2 <= 1; // 相交当且仅当 t1 和 t2 均在 [0, 1] 内
}
static Point intersection(Point p1, Point p2, Point q1, Point q2) {
Point v1 = new Point(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z); // p1 -> p2 的向量
Point v2 = new Point(q2.x - q1.x, q2.y - q1.y, q2.z - q1.z); // q1 -> q2 的向量
Point v3 = new Point(q1.x - p1.x, q1.y - p1.y, q1.z - p1.z); // p1 -> q1 的向量
Point n1 = new Point(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x); // v1 和 v2 的叉积
double d = n1.x * v3.x + n1.y * v3.y + n1.z * v3.z; // n1 和 v3 的点积
double t1 = (v2.x * v3.y - v2.y * v3.x) / d;
return new Point(p1.x + v1.x * t1, p1.y + v1.y * t1, p1.z + v1.z * t1);
}
public static void main(String[] args) {
// 第一个点的经纬度和方向角
double lat1 = 39.9042;
double lon1 = 116.4074;
double azimuth1 = 45;
double distance1 = 10000; // 以米为单位
// 第二个点的经纬度和方向角
double lat2 = 40.7128;
double lon2 = -74.0060;
double azimuth2 = 225;
double distance2 = 10000; // 以米为单位
// 将经纬度转换为直角坐标系的点
Point p1 = toCartesian(lat1, lon1);
Point p2 = move(p1, distance1, azimuth1);
Point q1 = toCartesian(lat2, lon2);
Point q2 = move(q1, distance2, azimuth2);
// 判断两条线段是否相交
if (intersect(p1, p2, q1, q2)) {
// 计算交点的经纬度
Point intersection = intersection(p1, p2, q1, q2);
double lat = Math.toDegrees(Math.asin(intersection.z / EARTH_RADIUS));
double lon = Math.toDegrees(Math.atan2(intersection.y, intersection.x));
System.out.println("交点经纬度:" + lat + ", " + lon);
} else {
System.out.println("两条线段不相交");
}
}
}
```
阅读全文