java 获取两条经纬度线段的交点坐标工具类
程序员文章站
2022-03-19 16:19:21
java 获取两条经纬度线段的交点坐标工具类网上有线段是否相交的判断方法,但是很少有获取线段交点的坐标的方法我在这里整合了网上的一些相交的方法,通过相交的xy轴点返推出了经纬度。使用方法可以按GisCheckUtils类中main方法中的实例使用,如需要修改(如需要获取延长线上的交点修改getIntersectPoint()方法中加/////的地方即可),查看代码中发注释修改代码即可。如过发现问题可以在下面留言讨论。一、获取两条经纬度线段的交点坐标工具类package cn.wys.utils...
java 获取两条经纬度线段的交点坐标工具类
网上有线段是否相交的判断方法,但是很少有获取线段交点的坐标的方法
我在这里整合了网上的一些相交的方法,通过相交的xy轴点返推出了经纬度。
使用方法可以按GisCheckUtils类中main方法中的实例使用,如需要修改(如需要获取延长线上的交点
修改getIntersectPoint()方法中加----的地方即可),查看代码中发注释修改代码即可。
如过发现问题可以在下面留言讨论。
一、获取两条经纬度线段的交点坐标工具类
package cn.wys.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @program: Wys
* @description 获取两条经纬度线段的交点坐标工具类
* @author: wys
* @create: 2020-11-27 09:21
**/
public class GisCheckUtils {
private static Logger log = LoggerFactory.getLogger(GisCheckUtils.class);
/**
* 地球周长
*/
private static double L = 6381372 * Math.PI * 2;
/**
* 平面展开后,x轴等于周长
*/
private static double W = L;
/**
* y轴约等于周长一半
*/
private static double H = L / 2;
/**
* 米勒投影中的一个常数,范围大约在正负2.3之间
*/
private static double mill = 2.3;
public static void main(String[] args) {
/* 拾取坐标系统 可直接复制坐标测试
http://api.map.baidu.com/lbsapi/getpoint/index.html
*/
//线段一
SegmentLatLon segmentLatLonOne = new SegmentLatLon();
segmentLatLonOne.setStartLatLon(new LatLon(116.393561, 39.940041));
segmentLatLonOne.setEndLatLon(new LatLon(116.400172, 39.953704));
//线段二
SegmentLatLon segmentLatLonTwo = new SegmentLatLon();
segmentLatLonTwo.setStartLatLon(new LatLon(116.37387, 39.946569));
segmentLatLonTwo.setEndLatLon(new LatLon(116.402288,39.943856));
//判断是否相交(延长线相交不算)
boolean b = segIntersect(segmentLatLonOne, segmentLatLonTwo);
log.info("判断是否相交: " + b);
//交点坐标(延长线相交不算)
LatLon intersectPoint = getIntersectPoint(segmentLatLonOne, segmentLatLonTwo);
log.info("交点坐标:" + intersectPoint);
}
/**
* 将经纬度转换成X和Y轴
* 米勒投影算法
*
* @param lat 纬度
* @param lon 经度
* @return
*/
private static Point millierConvertion(double lat, double lon) {
// 将经度从度数转换为弧度
double x = lon * Math.PI / 180;
// 将纬度从度数转换为弧度
double y = lat * Math.PI / 180;
// 米勒投影的转换
y = 1.25 * Math.log(Math.tan(0.25 * Math.PI + 0.4 * y));
// 弧度转为实际距离
x = (W / 2) + (W / (2 * Math.PI)) * x;
y = (H / 2) - (H / (2 * mill)) * y;
return new Point(x, y);
}
/**
* xy轴转坐标
*
* @param x
* @param y
* @return 坐标点
*/
private static LatLon xyToLatLon(double x, double y) {
//实际距离 转为弧度
x = (x - (W / 2)) / (W / (2 * Math.PI));
y = -1 * (y - (H / 2)) / (H / (2 * mill));
// 米勒投影的转换反转
y = (Math.atan(Math.pow(Math.E, y / 1.25)) - 0.25 * Math.PI) / 0.4;
//将经度从弧度转换为度数
double lon = 180 / Math.PI * x;
//将纬度从弧度转换为度数
double lat = 180 / Math.PI * y;
return new LatLon(lon, lat);
}
/**
* 获取两条直线相交的点
*
* @param segmentLatLonOne 线段一
* @param segmentLatLonTwo 线段二
* @return 相交点坐标 为null 不相交
*/
public static LatLon getIntersectPoint(SegmentLatLon segmentLatLonOne, SegmentLatLon segmentLatLonTwo) {
//先判断有没有相交 (延长线不算) 不相交返回null 相交执行获取交点坐标 (如需获取延长线交点注释此方法)----
if (!segIntersect(segmentLatLonOne, segmentLatLonTwo)) {
return null;
}
//----
//转换对象
Point[] points = segmentLatLonToPoint(segmentLatLonOne, segmentLatLonTwo);
//获取两条直线相交的点
Point latLon = getIntersectPoint(points[0], points[1], points[2], points[3]);
if (latLon != null) {
return xyToLatLon(latLon.x, latLon.y);
}
return null;
}
/**
* 获取两条直线相交的点
*
* @param p1 线段一 开始点
* @param p2 线段一 结束点
* @param p3 线段二 开始点
* @param p4 线段二 结束点
* @return
*/
public static Point getIntersectPoint(Point p1, Point p2, Point p3, Point p4) {
double A1 = p1.getY() - p2.getY();
double B1 = p2.getX() - p1.getX();
double C1 = A1 * p1.getX() + B1 * p1.getY();
double A2 = p3.getY() - p4.getY();
double B2 = p4.getX() - p3.getX();
double C2 = A2 * p3.getX() + B2 * p3.getY();
double det_k = A1 * B2 - A2 * B1;
if (Math.abs(det_k) < 0.00001) {
return null;
}
double a = B2 / det_k;
double b = -1 * B1 / det_k;
double c = -1 * A2 / det_k;
double d = A1 / det_k;
double x = a * C1 + b * C2;
double y = c * C1 + d * C2;
return new Point(x, y);
}
/**
* 验证两条线有没有相交
*
* @param segmentLatLonOne 线段1
* @param segmentLatLonTwo 线段2
* @return true 相交
*/
public static boolean segIntersect(SegmentLatLon segmentLatLonOne, SegmentLatLon segmentLatLonTwo) {
//转换对象
Point[] points = segmentLatLonToPoint(segmentLatLonOne, segmentLatLonTwo);
//验证两条线有没有相交
return segIntersect(points[0], points[1], points[2], points[3]) > 0;
}
/**
* 线段转换为点对象
*
* @param segmentLatLonOne 线段一
* @param segmentLatLonTwo 线段二
* @return 点对象数组
*/
private static Point[] segmentLatLonToPoint(SegmentLatLon segmentLatLonOne, SegmentLatLon segmentLatLonTwo) {
//线段1
Double oneStartLat = segmentLatLonOne.getStartLatLon().getLat();
Double oneStartLon = segmentLatLonOne.getStartLatLon().getLon();
Double oneEndLat = segmentLatLonOne.getEndLatLon().getLat();
Double oneEndLon = segmentLatLonOne.getEndLatLon().getLon();
// 线段2
Double twoStartLat = segmentLatLonTwo.getStartLatLon().getLat();
Double twoStartLon = segmentLatLonTwo.getStartLatLon().getLon();
Double twoEndLat = segmentLatLonTwo.getEndLatLon().getLat();
Double twoEndLon = segmentLatLonTwo.getEndLatLon().getLon();
Point[] points = new Point[4];
//将经纬度转换成X和Y轴
points[0] = millierConvertion(oneStartLat, oneStartLon);
points[1] = millierConvertion(oneEndLat, oneEndLon);
points[2] = millierConvertion(twoStartLat, twoStartLon);
points[3] = millierConvertion(twoEndLat, twoEndLon);
return points;
}
/**
* 验证两条线有没有相交
*
* @param A 线段一 开始点
* @param B 线段一 结束点
* @param C 线段二 开始点
* @param D 线段二 结束点
* @return
*/
public static int segIntersect(Point A, Point B, Point C, Point D) {
Point intersection = new Point();
if (Math.abs(B.getY() - A.getY()) + Math.abs(B.getX() - A.getX()) + Math.abs(D.getY() - C.getY())
+ Math.abs(D.getX() - C.getX()) == 0) {
if ((C.getX() - A.getX()) + (C.getY() - A.getY()) == 0) {
log.info("ABCD是同一个点!");
} else {
log.info("AB是一个点,CD是一个点,且AC不同!");
}
return 0;
}
if (Math.abs(B.getY() - A.getY()) + Math.abs(B.getX() - A.getX()) == 0) {
if ((A.getX() - D.getX()) * (C.getY() - D.getY()) - (A.getY() - D.getY()) * (C.getX() - D.getX()) == 0) {
log.info("A、B是一个点,且在CD线段上!");
} else {
log.info("A、B是一个点,且不在CD线段上!");
}
return 0;
}
if (Math.abs(D.getY() - C.getY()) + Math.abs(D.getX() - C.getX()) == 0) {
if ((D.getX() - B.getX()) * (A.getY() - B.getY()) - (D.getY() - B.getY()) * (A.getX() - B.getX()) == 0) {
log.info("C、D是一个点,且在AB线段上!");
} else {
log.info("C、D是一个点,且不在AB线段上!");
}
return 0;
}
if ((B.getY() - A.getY()) * (C.getX() - D.getX()) - (B.getX() - A.getX()) * (C.getY() - D.getY()) == 0) {
log.info("线段平行,无交点!");
return 0;
}
intersection
.setX(((B.getX() - A.getX()) * (C.getX() - D.getX())
* (C.getY() - A.getY()) - C.getX()
* (B.getX() - A.getX()) * (C.getY() - D.getY()) + A
.getX() * (B.getY() - A.getY()) * (C.getX() - D.getX()))
/ ((B.getY() - A.getY()) * (C.getX() - D.getX()) - (B
.getX() - A.getX()) * (C.getY() - D.getY())));
intersection
.setY(((B.getY() - A.getY()) * (C.getY() - D.getY())
* (C.getX() - A.getX()) - C.getY()
* (B.getY() - A.getY()) * (C.getX() - D.getX()) + A
.getY() * (B.getX() - A.getX()) * (C.getY() - D.getY()))
/ ((B.getX() - A.getX()) * (C.getY() - D.getY()) - (B
.getY() - A.getY()) * (C.getX() - D.getX())));
if ((intersection.getX() - A.getX()) * (intersection.getX() - B.getX()) <= 0
&& (intersection.getX() - C.getX())
* (intersection.getX() - D.getX()) <= 0
&& (intersection.getY() - A.getY())
* (intersection.getY() - B.getY()) <= 0
&& (intersection.getY() - C.getY())
* (intersection.getY() - D.getY()) <= 0) {
if ((A.getX() == C.getX() && A.getY() == C.getY()) || (A.getX() == D.getX() && A.getY() == D.getY())
|| (B.getX() == C.getX() && B.getY() == C.getY()) || (B.getX() == D.getX() && B.getY() == D.getY())) {
log.info("线段相交于端点上");
return 2;
} else {
log.info("线段相交于点(" + intersection.getX() + ","
+ intersection.getY() + ")!");
//相交
return 1;
}
} else {
log.info("线段相交于虚交点(" + intersection.getX() + ","
+ intersection.getY() + ")!");
//相交但不在线段上
return -1;
}
}
/**
* 点对象
*/
public static class Point {
private double x;
private double y;
public Point() {
}
public Point(double x, double y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return x + ","+ y ;
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
}
}
二、线段坐标实体
package cn.wys.core;
/**
* @program: Wys
* @description 线段坐标实体
* @author: wys
* @create: 2020-11-27 10:44
**/
public class SegmentLatLon {
/**
* 开始点的坐标
*/
private LatLon startLatLon;
/**
* 结束点的坐标
*/
private LatLon endLatLon;
public SegmentLatLon(LatLon startLatLon, LatLon endLatLon) {
this.startLatLon = startLatLon;
this.endLatLon = endLatLon;
}
public SegmentLatLon() {
}
public LatLon getStartLatLon() {
return startLatLon;
}
public void setStartLatLon(LatLon startLatLon) {
this.startLatLon = startLatLon;
}
public LatLon getEndLatLon() {
return endLatLon;
}
public void setEndLatLon(LatLon endLatLon) {
this.endLatLon = endLatLon;
}
}
三、经纬度实体
package cn.wys.core;
/**
* @program: Wys
* @description 经纬度实体
* @author: wys
* @create: 2020-11-26 10:44
**/
public class LatLon {
/**
* 经度
*/
private Double lon;
/**
* 纬度
*/
private Double lat;
public LatLon() {
}
public LatLon(Double lon, Double lat) {
this.lon = lon;
this.lat = lat;
}
public Double getLon() {
return lon;
}
public void setLon(Double lon) {
this.lon = lon;
}
public Double getLat() {
return lat;
}
public void setLat(Double lat) {
this.lat = lat;
}
@Override
public String toString() {
return lon +"," + lat ;
}
}
对您有帮助的话点个赞吧,谢谢。
本文地址:https://blog.csdn.net/wuyuanshun/article/details/110471988
上一篇: Windows下安装配置JDK
下一篇: Java数据类型及类型转换