package com.mapbar.algorithm;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;
/**
* 点到直线,线段的距离
*
* @author chenlly
*
*/
public class PointToLineDis {
private static GeometryFactory factory = new GeometryFactory();
private static WKTReader reader = new WKTReader();
// 直线方程一般式 Ax + By + C = 0;
private double A;
private double B;
private double C;
/**
* 求直线方程的一般式
*
* @param point1
* @param point2
* 直线l经过的两个点
*/
public void lineExp(Point point1, Point point2) {
/**
* 由起始点和终止点构成的直线方程一般式的系数A
*/
A = (point1.getY() - point2.getY())
/ Math.sqrt(Math.pow((point1.getY() - point2.getY()), 2)
+ Math.pow((point1.getX() - point2.getX()), 2));
/**
* 由起始点和终止点构成的直线方程一般式的系数
*/
B = (point2.getX() - point1.getX())
/ Math.sqrt(Math.pow((point1.getY() - point2.getY()), 2)
+ Math.pow((point1.getX() - point2.getX()), 2));
/**
* 由起始点和终止点构成的直线方程一般式的系数
*/
C = (point1.getX() * point2.getY() - point2.getX() * point1.getY())
/ Math.sqrt(Math.pow((point1.getY() - point2.getY()), 2)
+ Math.pow((point1.getX() - point2.getX()), 2));
}
/**
* 点到直线方程的距离 此公式需要证明
*
* @param x
* @param y
* @return
*/
public double alLine(double x, double y) {
double d = Math.abs(A * (x) + B * (y) + C)/Math.sqrt(Math.pow(A,2)+Math.pow(B,2));
return d;
}
/**
* 点到线段的距离 计算线段和计算点到直线的距离类似,不同Y点在包含l线段的投影可能不是线段上的点,投影可能在起点之前或者终点之后
*
* @param x
* @param y
* @return
*/
public double alSegmentDis(double x, double y, Point point1, Point point2) {
double dis = 0;
double a, b, c;
a = lineDis(point1.getX(), point1.getY(), point2.getX(), point2.getY());// 线段的长度
b = lineDis(point1.getX(), point1.getY(), x, y); // point1到点的距离
c = lineDis(point2.getX(), point2.getY(), x, y);//point2到点的距离
if (c + b == a) {// 点在线段上
dis = 0;
return dis;
}
if (c * c >= a * a + b * b) { // 组成直角三角形或钝角三角形,投影在point1延长线上,
dis = b;
return dis;
}
if (b * b >= a * a + c * c) {// 组成直角三角形或钝角三角形,投影在point2延长线上,
dis = c;
return dis;
}
// 组成锐角三角形,则求三角形的高
double p = (a + b + c) / 2;// 半周长
double s = Math.sqrt(p * (p - a) * (p - b) * (p - c));// 海伦公式求面积
dis = 2 * s / a;// 返回点到线的距离(利用三角形面积公式求高)
return dis;
}
/**
* 计算两点之间的距离
* @param x1
* @param y1
* @param x2
* @param y2
* @return
*/
private double lineDis(double x1, double y1, double x2, double y2) {
double lineLength = 0;
lineLength = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
return lineLength;
}
public static void main(String[] args) throws ParseException {
PointToLineDis pl = new PointToLineDis();
// 直线经过的两个点
String line = "LINESTRING (-5 6, -4 8)";
Geometry geometry = reader.read(line);
Coordinate[] coords = geometry.getCoordinates();
Point point1 = factory.createPoint(coords[0]);
Point point2 = factory.createPoint(coords[1]);
// 求直线方程一般式
pl.lineExp(point1, point2);
// 点(x,y)
double x = 2;
double y = -1;
double d1 = pl.alLine(x, y);
System.out.println("result:" + d1);// result:9.391485505499116
double x1 = -3;
double y1 = 3;
double d2 = pl.alSegmentDis(x1, y1, point1, point2);
System.out.println("result:" + d2);// result:3.605551275463989
}
}