一、需求
1. 已知B点、C点、c线长和b线长,求A点坐标;
1. 通过B、C两点作为圆心,绘制半径为c、b的圆;
2. 求出A1、A2的坐标;
3. 选取自己想要的那个点;
2. 三维向量计算直线上的一点;
二、代码
- 计算图片中A点坐标
private NEZ calculateAPoint(NEZ nezG, NEZ nezD, float gkL1, float dkL2) {
// 判断距离
double dist = Geometry.getDistance(nezG.N, nezG.E, nezD.N, nezD.E);
if ((dist > (gkL1 + dkL2)) || (dkL2 > (dist + gkL1)) || (gkL1 > (dist + dkL2))) { // 相等满足
return null;
}
// 求出K点的坐标
List resultXYList = calculatePointsOfTwoCircles(nezG, nezD, gkL1, dkL2);
if (resultXYList.size() <= 0) {
return null;
}
// 判断在直线右侧的点
NEZ nezK;
if (resultXYList.size() == 2) {
nezK = new NEZ(resultXYList.get(1), resultXYList.get(0), 0);
} else if (resultXYList.size() == 4) {
NEZ nez1 = new NEZ(resultXYList.get(1), resultXYList.get(0), 0);
NEZ nez2 = new NEZ(resultXYList.get(3), resultXYList.get(2), 0);
if (!isLeft(nezG, nezD, nez1)) {
nezK = nez1;
} else {
nezK = nez2;
}
} else {
return null;
}
// 高程内插:按距离加权平均
nezK.Z = (nezD.Z * gkL1 + nezD.Z * dkL2) / (gkL1 + dkL2);
return nezK;
}
/**
* 判断点是否在线的左侧
* @param a 开始点
* @param b 结束点
* @param c 计算点
* @return 是否在左侧
* @WXS 2023-2-10
*/
private boolean isLeft(NEZ a, NEZ b, NEZ c) {
return ((b.E - a.E) * (c.N - a.N) - (b.N - a.N) * (c.E - a.E)) > 0;
}
/**
* 计算两个圆的交点坐标
*
* @param nezA 第一个点
* @param nezB 第二个点
* @param r1 第一个点圆半径
* @param r2 第二个点圆半径
* @return 点xy数组
* @WXS 2023-2-10
*/
private List calculatePointsOfTwoCircles(NEZ nezA, NEZ nezB, float r1, float r2) {
List resultList = new ArrayList<>();
float x1 = (float) nezA.E;
float y1 = (float) nezA.N;
float x2 = (float) nezB.E;
float y2 = (float) nezB.N;
float dx = x2 - x1;
float dy = y2 - y1;
// 两个圆相离或包含
double dis2 = Math.pow(dx, 2) + Math.pow(dy, 2);
if (dis2 > Math.pow((r1 + r2), 2) || dis2 < Math.pow((r1 - r2), 2)) {
return resultList;// 失败
}
// 计算两个圆心的连线与x轴的角度t
double t = Math.atan2(dy, dx);
// 计算两个圆心的连线与圆心与交点之间的夹角a
double a = Math.acos((r1 * r1 - r2 * r2 + dis2) / (2 * r1 * Math.sqrt(dis2)));
// 计算交点
double x3 = x1 + r1 * Math.cos(t + a);
double y3 = y1 + r1 * Math.sin(t + a);
double x4 = x1 + r1 * Math.cos(t - a);
double y4 = y1 + r1 * Math.sin(t - a);
if (sgn(a) == 0) {
resultList.add((float) x3);
resultList.add((float) y3);
} else {
resultList.add((float) x3);
resultList.add((float) y3);
resultList.add((float) x4);
resultList.add((float) y4);
}
return resultList;
}
private int sgn(double dk) {
if (dk == 0) {
return 0;
} else if (dk > 0) {
return 1;
} else {
return -1;
}
}
/**
* 四舍五入
*
* @param d
* @param prec 保存小数位数
* @WXS 2023-2-10
*/
private double roundPrec(double d, int prec) {
return new BigDecimal(d).setScale(prec, BigDecimal.ROUND_HALF_UP).doubleValue();
}
- 三维向量计算直线上的一点;
// ->GK 直线的向量
Vector3 directionVector3 = new Vector3(nezK.E - nezG.E, nezK.N - nezG.N, nezK.Z - nezG.Z);
// 向量单位化
directionVector3.normalize();
// 向量乘移动长度
Vector3 changeVector3 = Vector3.opMultiply(directionVector3, mcs.getNewGK());
Vector3 centerV3 = new Vector3(E, Z, N);
Vector3 centerResultV3 = Vector3.opAddition(changeVector3, centerV3);
Vector3 的代码
package com.zhd.opengl.base;
import java.util.List;
public class Vector3 implements Cloneable {
private double x;
private double y;
private double z;
public Vector3() {
}
public Vector3(double value) {
this.x = value;
this.y = value;
this.z = value;
}
public Vector3(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
public Vector3(List array) {
if (array.size() != 3) {
throw new IllegalArgumentException("The dimension of the array must be three.");
} else {
this.x = (Double) array.get(0);
this.y = (Double) array.get(1);
this.z = (Double) array.get(2);
}
}
public static Vector3 getZero() {
return new Vector3(0.0D, 0.0D, 0.0D);
}
public static Vector3 getUnitX() {
return new Vector3(1.0D, 0.0D, 0.0D);
}
public static Vector3 getUnitY() {
return new Vector3(0.0D, 1.0D, 0.0D);
}
public static Vector3 getUnitZ() {
return new Vector3(0.0D, 0.0D, 1.0D);
}
public static Vector3 getNaN() {
return new Vector3(0.0D / 0.0, 0.0D / 0.0, 0.0D / 0.0);
}
public static boolean isNaN(Vector3 u) {
return Double.isNaN(u.getX()) || Double.isNaN(u.getY()) || Double.isNaN(u.getZ());
}
public static double dotProduct(Vector3 u, Vector3 v) {
return u.getX() * v.getX() + u.getY() * v.getY() + u.getZ() * v.getZ();
}
public static Vector3 crossProduct(Vector3 u, Vector3 v) {
double a = u.getY() * v.getZ() - u.getZ() * v.getY();
double b = u.getZ() * v.getX() - u.getX() * v.getZ();
double c = u.getX() * v.getY() - u.getY() * v.getX();
return new Vector3(a, b, c);
}
public static double distance(Vector3 u, Vector3 v) {
return Math.sqrt((u.getX() - v.getX()) * (u.getX() - v.getX()) + (u.getY() - v.getY()) * (u.getY() - v.getY()) + (u.getZ() - v.getZ()) * (u.getZ() - v.getZ()));
}
public static double squareDistance(Vector3 u, Vector3 v) {
return (u.getX() - v.getX()) * (u.getX() - v.getX()) + (u.getY() - v.getY()) * (u.getY() - v.getY()) + (u.getZ() - v.getZ()) * (u.getZ() - v.getZ());
}
public static double angleBetween(Vector3 u, Vector3 v) {
double cos = dotProduct(u, v) / (u.modulus() * v.modulus());
if (cos >= 1.0D) {
return 0.0D;
} else {
return cos <= -1.0D ? Math.PI : Math.acos(cos);
}
}
public static Vector3 midPoint(Vector3 u, Vector3 v) {
return new Vector3((v.getX() + u.getX()) * 0.5D, (v.getY() + u.getY()) * 0.5D, (v.getZ() + u.getZ()) * 0.5D);
}
public static boolean arePerpendicular(Vector3 u, Vector3 v) {
return arePerpendicular(u, v, 1.0E-12D);
}
public static boolean arePerpendicular(Vector3 u, Vector3 v, double threshold) {
return MathHelper.isZero(dotProduct(u, v), threshold);
}
public static boolean areParallel(Vector3 u, Vector3 v) {
return areParallel(u, v, 1.0E-12D);
}
public static boolean areParallel(Vector3 u, Vector3 v, double threshold) {
double a = u.getY() * v.getZ() - u.getZ() * v.getY();
double b = u.getZ() * v.getX() - u.getX() * v.getZ();
double c = u.getX() * v.getY() - u.getY() * v.getX();
if (!MathHelper.isZero(a, threshold)) {
return false;
} else if (!MathHelper.isZero(b, threshold)) {
return false;
} else {
return MathHelper.isZero(c, threshold);
}
}
public static Vector3 round(Vector3 u, int numDigits) {
if (numDigits >= 0 && numDigits <= 15) {
return new Vector3((double) Math.round(u.getX() * Math.pow(10.0D, (double) numDigits)) / Math.pow(10.0D, (double) numDigits), (double) Math.round(u.getY() * Math.pow(10.0D, (double) numDigits)) / Math.pow(10.0D, (double) numDigits), (double) Math.round(u.getZ() * Math.pow(10.0D, (double) numDigits)) / Math.pow(10.0D, (double) numDigits));
} else {
throw new IllegalArgumentException("numDigits must be 0 < numDigits < 15");
}
}
public static Vector3 opAddition(Vector3 u, Vector3 v) {
return new Vector3(u.getX() + v.getX(), u.getY() + v.getY(), u.getZ() + v.getZ());
}
public static Vector3 opSubtraction(Vector3 u, Vector3 v) {
return new Vector3(u.getX() - v.getX(), u.getY() - v.getY(), u.getZ() - v.getZ());
}
public static Vector3 OpUnaryNegation(Vector3 u) {
return new Vector3(-u.getX(), -u.getY(), -u.getZ());
}
public static Vector3 opMultiply(Vector3 u, double a) {
return new Vector3(u.getX() * a, u.getY() * a, u.getZ() * a);
}
public static Vector3 opMultiply(double a, Vector3 u) {
return new Vector3(u.getX() * a, u.getY() * a, u.getZ() * a);
}
public static Vector3 opDivision(Vector3 u, double a) {
double invEscalar = 1.0D / a;
return new Vector3(u.getX() * invEscalar, u.getY() * invEscalar, u.getZ() * invEscalar);
}
public static Vector3 opDivision(double a, Vector3 u) {
return new Vector3(a / u.getX(), a / u.getY(), a / u.getZ());
}
public double getX() {
return this.x;
}
public void setX(double aXValue) {
this.x = aXValue;
}
public double getY() {
return this.y;
}
public void setY(double aYValue) {
this.y = aYValue;
}
public double getZ() {
return this.z;
}
public void setZ(double aZValue) {
this.z = aZValue;
}
public double getItem(int index) {
switch (index) {
case 0:
return this.x;
case 1:
return this.y;
case 2:
return this.z;
default:
throw new IllegalArgumentException("index");
}
}
public void setItem(int index, double value) {
switch (index) {
case 0:
this.x = value;
break;
case 1:
this.y = value;
break;
case 2:
this.z = value;
break;
default:
throw new IllegalArgumentException("index");
}
}
public void normalize() {
double mod = this.modulus();
if (MathHelper.isZero(mod, 1.0E-12D)) {
throw new ArithmeticException("Cannot normalize a zero vector.");
} else {
double modInv = 1.0D / mod;
this.x *= modInv;
this.y *= modInv;
this.z *= modInv;
}
}
public double modulus() {
return Math.sqrt(dotProduct(this, this));
}
public double[] toArray() {
double[] u = new double[]{this.x, this.y, this.z};
return u;
}
public boolean equals(Vector3 obj, double threshold) {
return MathHelper.isEqual(obj.getX(), this.x, threshold) && MathHelper.isEqual(obj.getY(), this.y, threshold) && MathHelper.isEqual(obj.getZ(), this.z, threshold);
}
public boolean equals(Object obj) {
if (obj == null) {
return false;
} else if (this == obj) {
return true;
} else {
return obj instanceof Vector3 ? this.equals((Vector3) obj, 1.0E-12D) : false;
}
}
public int hashCode() {
return Double.valueOf(this.getX()).hashCode() ^ Double.valueOf(this.getY()).hashCode() ^ Double.valueOf(this.getZ()).hashCode();
}
public String toString() {
return String.format("%1$s %2$s %3$s", this.x, this.y, this.z);
}
public String toString(IFormatProvider provider) {
return String.format("%1$s %2$s %3$s", String.valueOf(this.x), String.valueOf(this.y), String.valueOf(this.z));
}
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException var2) {
var2.printStackTrace();
return null;
}
}
}
参考文章
- https://zhuanlan.zhihu.com/p/539383874