三点根据一元二次方程生成一条数据集计算与第四个点最近的三维距离

/**
 * Author:domjun
 * description:Calculate spatial distances
 * usage:
 * 1 getInstance()->get an instance
 * 2 calculatedSpatial()->getLocation3Dlist
 * 3 getSpatial()->getSpatialData
 */
public class SpatialDisUtil {
    public float Data_fitting_a = 0, Data_fitting_b = 0, Data_fitting_c = 0;
    private List<Location3D> outlist;
    private static SpatialDisUtil INSTANCE;

    public static SpatialDisUtil getInstance() {
        if (INSTANCE == null) {
            synchronized (SpatialDisUtil.class) {
                if (INSTANCE == null) {
                    INSTANCE = new SpatialDisUtil();
                }
            }
        }
        return INSTANCE;
    }

    private SpatialDisUtil() {

    }

    /**
     * @param location3D
     * @param spatialDataCall
     * Calculate the closest horizontal, vertical,
     * and three-dimensional distances between latitude
     * and longitude points and the dataset
     */
    public void getSpatial(Location3D location3D,SpatialDataCall spatialDataCall) {
        try {
            float hdis = calculateLineDistance(getOutlist().get(0), location3D);
            float vdis = Math.abs(location3D.getAltitude() - getOutlist().get(0).getAltitude());
            float sdis = (float) Math.sqrt(Math.pow(hdis, 2) + Math.pow(vdis, 2));
            for (int i = 1; i < getOutlist().size(); i++) {
            	float hdiss = calculateLineDistance(getOutlist().get(i), location3D);
            	float vdiss = Math.abs(location3D.getAltitude() - getOutlist().get(i).getAltitude());
            	float sdiss = (float) Math.sqrt(Math.pow(hdiss, 2) + Math.pow(vdiss, 2));
                if (sdiss < sdis) {
                    hdis = hdiss;
                    vdis = vdiss;
                    sdis =sdiss;
                }
            }
            spatialDataCall.dataCall(hdis,vdis,sdis);
        } catch (Exception e) {
            e.printStackTrace();
            spatialDataCall.dataCall(0,0,0);
        }
    }

    /**
     * @param a start point
     * @param b any point
     * @param c end point
     * @param spatialCalculatCall
     * Enter three latitude and longitude points to get the fitting set
     * If the distance between point A and point C is more than 5000 meters, it cannot be calculated
     */
    public void calculatedSpatial(Location3D a, Location3D b, Location3D c, SpatialCalculatCall spatialCalculatCall) {
        try {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    outlist = new ArrayList<>();
                    List<Location3D> location3DList = new ArrayList<>();
                    long num = (int) (calculateLineDistance(a, c) * 1000);
                    if (num > 5000000) {
                        spatialCalculatCall.calculatSucces(false,INSTANCE);
                        return;
                    }
                    location3DList.add(a);
                    location3DList.add(b);
                    location3DList.add(c);
                    Data_fitting(location3DList);
                    float latdif = (float) ((c.getLatitude() - a.getLatitude()) / num);
                    float londif = (float) ((c.getLongitude() - a.getLongitude()) / num);
                    outlist.add(a);
                    for (int i = 0; i < num; i++) {
                        Location3D location3D = new Location3D(a.getLatitude() + (latdif * (i + 1)), a.getLongitude() + (londif * (i + 1)));
                        float dis = calculateLineDistance(a, location3D);
                        float y = (float) ((Math.pow(dis, 2) * Data_fitting_a) + (dis * Data_fitting_b) + Data_fitting_c);
                        location3D.setAltitude(y);

                        outlist.add(location3D);
                    }
                    outlist.add(c);
                    setOutlist(outlist);
                    spatialCalculatCall.calculatSucces(true,INSTANCE);
                }
            }).start();
        } catch (Exception e) {
            e.printStackTrace();
            spatialCalculatCall.calculatSucces(false,INSTANCE);
        }
    }

    //The unary quadratic equation ABC is calculated from three latitude and longitude points
    private void Data_fitting(List<Location3D> terrainInformation) {
        try {
            final WeightedObservedPoints obs = new WeightedObservedPoints();
            for (int i = 0; i < terrainInformation.size(); i++) {
                float X = calculateLineDistance(terrainInformation.get(0), terrainInformation.get(i));
                float Y = terrainInformation.get(i).getAltitude();
                obs.add(X, Y);
            }
            final PolynomialCurveFitter fitter = PolynomialCurveFitter.create(2);
            final double[] coeff = fitter.fit(obs.toList());
            Data_fitting_a = (float) coeff[2];
            Data_fitting_b = (float) coeff[1];
            Data_fitting_c = (float) coeff[0];
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //The distance is calculated from xyz using latitude and longitude as the origin
    private Location3D xyzToLonLat(Location3D location3D,float x,float y,float z){
        try {
            double lat=location3D.getLatitude();
            double lon=location3D.getLongitude();
            double a = 6378137;
            double b = 6356752.3142;
            double PI = 3.141592653589793238;
            double f = 1 / 298.2572236;
            float dis= (float) Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
            float dist= (float) Math.sqrt(Math.pow(dis, 2) + Math.pow(z, 2));
            float brng = (float) Math.atan2(x,y);
            if(brng>180){
                brng=brng-360;
            }
            else if(brng<-180) {
                brng=brng+360;
            }
            if(brng<0){
                brng=brng+360;
            }
            double alpha1 = brng * PI / 180.0;
            double sinAlpha1 = Math.sin(alpha1);
            double cosAlpha1 = Math.cos(alpha1);
            double tanU1 = (1 - f) * Math.tan( lat * PI / 180.0);
            double cosU1 = 1 / Math.sqrt((1 + tanU1 * tanU1));
            double sinU1 = tanU1 * cosU1;
            double sigma1 = Math.atan2(tanU1, cosAlpha1);
            double sinAlpha = cosU1 * sinAlpha1;
            double cosSqAlpha = 1 - sinAlpha * sinAlpha;
            double uSq = cosSqAlpha * (a * a - b * b) / (b * b);
            double A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));
            double B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));
            double cos2SigmaM=0;
            double sinSigma=0;
            double cosSigma=0;
            double sigma = dist / (b * A), sigmaP = 2 * Math.PI;
            while (Math.abs(sigma - sigmaP) > 1e-12) {
                cos2SigmaM = Math.cos(2 * sigma1 + sigma);
                sinSigma = Math.sin(sigma);
                cosSigma = Math.cos(sigma);
                double deltaSigma = B * sinSigma * (cos2SigmaM + B / 4 * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)
                        - B / 6 * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)));
                sigmaP = sigma;
                sigma = dist / (b * A) + deltaSigma;
            }
            double tmp = sinU1 * sinSigma - cosU1 * cosSigma * cosAlpha1;
            double lat2 = Math.atan2(sinU1 * cosSigma + cosU1 * sinSigma * cosAlpha1,
                    (1 - f) * Math.sqrt(sinAlpha * sinAlpha + tmp * tmp));
            double lambda = Math.atan2(sinSigma * sinAlpha1, cosU1 * cosSigma - sinU1 * sinSigma * cosAlpha1);
            double C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha));
            double L = lambda - (1 - C) * f * sinAlpha
                    * (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));
            LatLng get_LatLng =new LatLng(  lat2 * PI / 180.0,lon+( L * PI / 180.0));
            return new Location3D(get_LatLng.latitude,get_LatLng.longitude,location3D.getAltitude()+z);

        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    //Calculate the distance between two points
    private float calculateLineDistance(Location3D var0, Location3D var1) {
        try {
            double var4 = var0.longitude;
            double var6 = var0.latitude;
            double var8 = var1.longitude;
            double var10 = var1.latitude;
            var4 *= 0.01745329251994329D;
            var6 *= 0.01745329251994329D;
            var8 *= 0.01745329251994329D;
            var10 *= 0.01745329251994329D;
            double var12 = Math.sin(var4);
            double var14 = Math.sin(var6);
            double var16 = Math.cos(var4);
            double var18 = Math.cos(var6);
            double var20 = Math.sin(var8);
            double var22 = Math.sin(var10);
            double var24 = Math.cos(var8);
            double var26 = Math.cos(var10);
            double[] var28 = new double[3];
            double[] var29 = new double[3];
            var28[0] = var18 * var16;
            var28[1] = var18 * var12;
            var28[2] = var14;
            var29[0] = var26 * var24;
            var29[1] = var26 * var20;
            var29[2] = var22;
            double var30 = Math.sqrt((var28[0] - var29[0]) * (var28[0] - var29[0]) + (var28[1] - var29[1]) * (var28[1] - var29[1]) + (var28[2] - var29[2]) * (var28[2] - var29[2]));
            return (float) (Math.asin(var30 / 2.0D) * 1.27420015798544E7D);
        } catch (Exception e) {
            e.printStackTrace();
            return 0f;
        }
    }

    public List<Location3D> getOutlist() {
        return outlist;
    }

    public void setOutlist(List<Location3D> outlist) {
        this.outlist = outlist;
    }

    public interface SpatialCalculatCall {
        void calculatSucces(boolean success,SpatialDisUtil spatialDisUtil);
    }

    public interface SpatialDataCall {
        void dataCall(float hdis, float vdis, float sdis);
    }
}

需要导入jar包commons-math3-3.6.1.jar

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值