java 克里金插值+等值线划分示例

安稳与你 提交于 2020-04-28 11:48:43

最近项目原因需要用到克里金和等直线算法 ,在网上找了许久都不太满意,不是话说到一半就是 示例不正确,要不就是没库等等,捣鼓许久弄出来,把示例代码发出来分享一下。

首先了说明一下为什么要使用到克里金算法 因为气象方面很多气象站点零散的分布在地图各个位置,在这零散的位置上就可能会产生区域覆盖不完整的情况,这个时候就需要做插值覆盖。而等直线的意义跟插值业务一样,因为在地图上热力图的绘制需要大量格点数据来支撑绘制所以,就会出现在绘制热力图的时候光是下载格点数据都是很大的,这个取决于格点密度,密度越大那么数据量就会很大,在网络传输过程中光是下载这个数据都需要花费很多时间,更别说绘制了。所以等值线数据就尤为的重要。例如:

 

 

 

 

 

根据区域划分成勾勒出线的坐标,其内的值都是等值范围这样的数据就不会很多,当然等值范围越精确数据也会递增。

这次示例使用到的库wContour和geo,因为代码不复杂 加上代码也有注释,所以我就不细致解释下去了直接上demo

package kriginDemo.test;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import org.json.simple.JSONObject;
import com.alibaba.fastjson.JSON;

import krigingDemo.util.CommonMethod;
import krigingDemo.util.KrigingUtil;
import wContour.Contour;
import wContour.Interpolate;
import wContour.Global.Border;
import wContour.Global.PointD;
import wContour.Global.PolyLine;
import wContour.Global.Polygon;

public class Test {
	 /**
     * 通过本地文件访问json并读取
     *
     * @param path:json文件路径
     * @return:json文件的内容
     */
    public static String readFile(String path) {
        StringBuffer laststr = new StringBuffer();
        File file = new File(path);// 打开文件
        BufferedReader reader = null;
        try {
            FileInputStream in = new FileInputStream(file);
            reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));// 读取文件
            String tempString = null;
            while ((tempString = reader.readLine()) != null) {
                laststr = laststr.append(tempString);
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException el) {
                }
            }
        }
        return laststr.toString();
    }
    
    private static String getPolygonGeoJson(List<Polygon> cPolygonList) {
        String geo = null;
        String geometry = " { \"type\":\"Feature\",\"geometry\":";
        String properties = ",\"properties\":{ \"hvalue\":";

        String head = "{\"type\": \"FeatureCollection\"," + "\"features\": [";
        String end = "  ] }";
        if (cPolygonList == null || cPolygonList.size() == 0) {
            return null;
        }
        try {
            for (Polygon pPolygon : cPolygonList) {

                List<Object> ptsTotal = new ArrayList<Object>();
                List<Object> pts = new ArrayList<Object>();

                PolyLine pline = pPolygon.OutLine;

                for (PointD ptD : pline.PointList) {
                    List<Double> pt = new ArrayList<Double>();
                    pt.add(ptD.X);
                    pt.add(ptD.Y);
                    pts.add(pt);
                }

                ptsTotal.add(pts);

                if (pPolygon.HasHoles()) {
                    for (PolyLine cptLine : pPolygon.HoleLines) {
                        List<Object> cpts = new ArrayList<Object>();
                        for (PointD ccptD : cptLine.PointList) {
                            List<Double> pt = new ArrayList<Double>();
                            pt.add(ccptD.X);
                            pt.add(ccptD.Y);
                            cpts.add(pt);
                        }
                        if (cpts.size() > 0) {
                            ptsTotal.add(cpts);
                        }
                    }
                }

                JSONObject js = new JSONObject();
                js.put("type", "Polygon");
                js.put("coordinates", ptsTotal);
                double hv = pPolygon.HighValue;
                double lv = pPolygon.LowValue;

                if (hv == lv) {
                    if (pPolygon.IsClockWise) {
                        if (!pPolygon.IsHighCenter) {
                            hv = hv - 0.1;
                            lv = lv - 0.1;
                        }

                    } else {
                        if (!pPolygon.IsHighCenter) {
                            hv = hv - 0.1;
                            lv = lv - 0.1;
                        }
                    }
                } else {
                    if (!pPolygon.IsClockWise) {
                        lv = lv + 0.1;
                    } else {
                        if (pPolygon.IsHighCenter) {
                            hv = hv - 0.1;
                        }
                    }

                }

                geo = geometry + js.toString() + properties + hv
                        + ", \"lvalue\":" + lv + "} }" + "," + geo;

            }
            if (geo.contains(",")) {
                geo = geo.substring(0, geo.lastIndexOf(","));
            }

            geo = head + geo + end;
        } catch (Exception e) {
            e.printStackTrace();
            return geo;
        }
        return geo;
    }
    
    
    
	public static void main(String[] args) {
		 //雅安样本数据
		 double[][]  trainData = JSON.parseObject(readFile("G:\\t.json"), double[][].class);
		 
		 KrigingUtil kriging = new KrigingUtil(KrigingUtil.SPHERICAL_MODEL, 0, 100);
		 kriging.train(trainData[2], trainData[0], trainData[1]);
		 //经度起点
		 double left = 101.91;
		 //经度结束点
		 double right =103.395;
		 //维度起点
		 double bottom = 28.845;
		 //维度结束点
		 double top = 30.935;
		 
		 double[] bottomLeft = {left, bottom};
		 double[] topLeft = {left, top};
		 double[] topRight = {right, top};
		 double[] bottomRight = {right, bottom};
		 double[][][] polygons = {{bottomLeft, topLeft, topRight, bottomRight}};
		 //计算经纬度格点距离
		 double xWidth = Math.abs(right - left) / 297;
		 double yWidth = Math.abs(top - bottom) / 418;
		 //克里金插值
		 KrigingUtil.Grid grid = kriging.grid(polygons, xWidth, yWidth);
		 
		 //等值线阈值
		 double[] dataInterval = new double[]{10,20,25,30,35};
		 //异常数据样本
		 double _undefData = -9999.0;
		 double[] _X = new double[420];
		 double[] _Y = new double[298]; 
		
		 
		 Interpolate.createGridXY_Num(101.91,28.845,103.395,30.935, _X,  _Y);
		 int[][] S1 = new int[grid.A.length][grid.A[0].length];
		 //绘线
		 List<Border> _borders = Contour.tracingBorders(grid.A, _X, _Y,S1, _undefData);
		 List<PolyLine> cPolylineList = new ArrayList<PolyLine>();
		 cPolylineList = Contour.tracingContourLines(grid.A, _X, _Y, dataInterval.length, dataInterval, _undefData, _borders, S1);// 生成等值线
		 cPolylineList = Contour.smoothLines(cPolylineList);// 平滑
		 List<Polygon> cPolygonList = new ArrayList<Polygon>();
		 cPolygonList = Contour.tracingPolygons(grid.A, cPolylineList,_borders, dataInterval);
		 String geojsonpogylon = getPolygonGeoJson(cPolygonList);
		 CommonMethod cm = new CommonMethod();
		 cm.append2File("G:\\data.json",geojsonpogylon);
		 
		 
	}

}

		 double[][]  trainData = JSON.parseObject(readFile("G:\\t.json"), double[][].class);

这个数据是我的样本数据

 //计算经纬度格点距离
		 double xWidth = Math.abs(right - left) / 297;
		 double yWidth = Math.abs(top - bottom) / 418;

这个297和418 是我自己计算的值意思是从开始经纬度 和结束经纬度 以0.005为格点距离计算出来的数值

 CommonMethod cm = new CommonMethod();
		 cm.append2File("G:\\data.json",geojsonpogylon);

最后将JSON 输出到文件 因为数据也是比较大的

最后可以将生成的等值线JSON 贴入这里来看看效果http://geojson.io/#map=8/29.893/102.651

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!