前言
某场景下,只提供了圆弧两点坐标和圆半径,要求连线绘制正确的圆弧。
思路:确定弧上三点可用PostGIS 根据 WKT 弧线类型 CIRCULARSTRING绘制圆弧。
一、根据弧上两点及半径确认弧线中点
Java 代码如下(示例):
//计算两点之间距离(投影坐标)
public static double sqrDistance2D(double x1,double y1,double x2, double y2){
return ( x1 - x2 ) * ( x1 - x2 ) + ( y1 - y2 ) * ( y1 - y2 );
}
public static boolean DoubleNear(double a, double b) {
double epsilon = 4 * Double.MIN_VALUE;
boolean aIsNan = Double.isNaN(a);
boolean bIsNan = Double.isNaN(b);
if (aIsNan || bIsNan) {
return aIsNan && bIsNan;
}
double diff = a - b;
return diff > -epsilon && diff <= epsilon;
}
public static double[] pointOnLineWithDistance(double x1, double y1, double x2, double y2, double distance) {
double x, y;
double dx = x2 - x1;
double dy = y2 - y1;
double length = Math.sqrt(dx * dx + dy * dy);
if (DoubleNear(length, 0.0)) {
x = x1;
y = y1;
} else {
double scaleFactor = distance / length;
x = x1 + dx * scaleFactor;
y = y1 + dy * scaleFactor;
}
double [] result = new double[2];
result[0]=x;
result[1]=y;
return result;
}
//求弧上一点
public static String getCenterPoint( double x1,double y1,double x2,double y2,double radius){
double [] midPoint= new double[2];
midPoint[0]=(x1+x2)/2;
midPoint[1]=(y1+y2)/2;
double midDist =Math.sqrt(sqrDistance2D(x1,y1, midPoint[0],midPoint[1]));
if ( radius < midDist )
{
return "数据不正确";
}
double centerMidDist = Math.sqrt( radius * radius - midDist * midDist );
double dist = radius - centerMidDist;
double midDx = midPoint[0] - x1;
double midDy = midPoint[1]- y1;
//寻找两个可能的中点 有四个结果
List<double[]> possibleMidPoints =new ArrayList<>();
possibleMidPoints.add( pointOnLineWithDistance( midPoint[0],midPoint[1], midPoint[0] - midDy,midPoint[1] + midDx , dist ) );
possibleMidPoints.add( pointOnLineWithDistance( midPoint[0],midPoint[1], midPoint[0] - midDy,midPoint[1] + midDx , 2 * radius - dist ) );
possibleMidPoints.add( pointOnLineWithDistance( midPoint[0],midPoint[1], midPoint[0] + midDy,midPoint[1] - midDx, dist ) );
possibleMidPoints.add( pointOnLineWithDistance( midPoint[0],midPoint[1], midPoint[0] + midDy, midPoint[1]- midDx , 2 * radius - dist ) );
//外圈小圆
double [] result = possibleMidPoints.get(0);
return "POINT(" + result[0] + " " + result[1]+ ")";
}
二、PostGIS 根据三点绘制圆弧函数
代码如下(示例):
ST_GeomFromText('CIRCULARSTRING(x1 y1,x2 y2,x3 y3)')
三、结果
PS:实现=>实线
四、注意事项
本代码是根据QGIS绘制圆弧源码改造,后续可拓展为前端绘制圆弧工具
如需绘制圆弧并入库完整代码及QGIS其它功能源码请关注公众号: