找风眼程序

package com.example.demo.findwindeye;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.io.*;
import java.math.BigDecimal;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 找风眼
 * 总体思路,在撒点范围内画框,框框不停往右移动
 * 移动的过程中做计算:只要四边的方向在画圆(上下边的点方向相对,左右边的点方向相对,且相邻边顺行)说明中心点是风眼
 */
public class Main {

    private static JSONArray data = null;
    private static List<Point> allPoints = null;
    private static List<Double> sortedX = null;
    private static List<Double> sortedY = null;
    private static int calPointTotalNum = 4;
    private static int calAddPointNum = calPointTotalNum - 1;
    /**
     * 台风速度大于1720cm。来自百度百科
     */
    private static double TYPHOON_SPEED = 17.20;



    static {
        try{
            JSONObject jsonObject = readFile();
            data = jsonObject.getJSONArray("data");
            allPoints = JSONArray.parseArray(data.toString(),Point.class);


            sortedX = data.stream().map(o->{
                JSONObject o1 = (JSONObject) o;
                return o1.getDouble("x");
            }).distinct().sorted().collect(Collectors.toList());

            sortedY = data.stream().map(o->{
                JSONObject o1 = (JSONObject) o;
                return o1.getDouble("y");
            }).distinct().sorted(Comparator.reverseOrder()).collect(Collectors.toList());

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

    private static JSONObject readFile()throws Exception {

        RandomAccessFile ra = new RandomAccessFile(
                "C:\\study\\workspace\\demo\\src\\main\\java\\com\\example\\demo\\xml2json\\json" +
                        "\\LoDo_160913_0040_7.860M_Current.json","r");

        byte[] bytes = new byte[1024 * 1024 * 10];
        int read = ra.read(bytes);

        String data = new String(bytes,0,read);

        return JSONObject.parseObject(data);

    }


    public static void main(String[] args)throws Exception {

        /*
        1、找到最边点,上左,上右,下左,下右
        2、从左上角开始往右移动(先找到步长)
         */

        int xnum = 0, ynum = 0;

        OUT:while (true) {
            while(true){
                Double startX = sortedX.get(xnum), startY = sortedY.get(ynum);
                Double endX = sortedX.get(xnum+ calAddPointNum), endY = sortedY.get(ynum+ calAddPointNum);
//                System.out.println("startX:"+startX+", startY:"+startY+", endX:"+endX+", endY:"+endY);
//                System.out.println("endX:"+endX+", endY:"+endY);
//                MyPolygon myPolygon = getMyPolygen(
//                        //原始点 - 0.000004,用于数据偏差
//                        new BigDecimal(startX.toString()).subtract(new BigDecimal("0.000004")).doubleValue(),
//                        new BigDecimal(startY.toString()).add(new BigDecimal("0.000004")).doubleValue(),
//                        new BigDecimal(endX.toString()).add(new BigDecimal("0.000004")).doubleValue(),
//                        new BigDecimal(endY.toString()).subtract(new BigDecimal("0.000004")).doubleValue()
//                );
                JSONArray pointInPolygon = findPointInPolygon(startX,startY,endX,endY);

                if(pointInPolygon.size() > 0 ){

                    boolean isWindEye = checkIsWindEye(pointInPolygon);
                    if(isWindEye){
                        System.out.println("+++++++++++++++++++++++++\r\n"+pointInPolygon);
                        double midX = new BigDecimal(startX.toString())
                                .add(new BigDecimal(endX.toString()))
                                .divide(new BigDecimal("2")).doubleValue();
                        double midY = new BigDecimal(startY.toString())
                                .add(new BigDecimal(endY.toString()))
                                .divide(new BigDecimal("2")).doubleValue();
                        System.out.println("XY:"+midX+","+midY);

                        if(isTyphoonSpeed(pointInPolygon)){
                            // 超过一半的点为台风速度才是台风
                            System.out.println("是台风速度");
                        } else {
                            System.out.println("不是台风速度风眼");
                        }
                    }
                }
                xnum ++;
                if(xnum + calAddPointNum == sortedX.size()){
                    xnum = 0;
                    break;
                }
            }
            ynum ++;
            if(ynum + calAddPointNum == sortedY.size()){
                break;
            }
        }

        System.out.println("执行结束");


    }

    /**
     * 超过一半的点为台风速度,则为true
     * @param pointInPolygon
     * @return
     */
    private static boolean isTyphoonSpeed(JSONArray pointInPolygon) {

        JSONArray upPoints = findUpPoints(pointInPolygon);
        JSONArray downPoints = findDownPoints(pointInPolygon);
        JSONArray leftPoints = findLeftPoints(pointInPolygon);
        JSONArray rightPoints = findRightPoints(pointInPolygon);

        JSONArray all = new JSONArray();
        all.addAll(upPoints);
        all.addAll(downPoints);
        all.addAll(leftPoints);
        all.addAll(rightPoints);

        int count = 0;

        for (Object o : all) {
            JSONObject o1 = (JSONObject) o;
            Double v = o1.getDouble("v");
            if (v >= TYPHOON_SPEED) {
                count ++;
            }
        }

        if(count > all.size()/2){
            return true;
        }
        return false;

    }


    /**
     * 判断是否有风眼
     *
     * 首先,判断
     *
     * @param pointInPolygon
     * @return
     */
    private static boolean checkIsWindEye(JSONArray pointInPolygon) {
        // 必须包含16个点
//        if(pointInPolygon.size() < 16){
//            return false;
//        }
        // 找出最边边的中间点的方向,只要是成环就是风眼
        Direction upDirection = findUpDirection(pointInPolygon);
//        printDirection(upDirection);
        if(upDirection == Direction.UNKNOWN) return false;

        Direction downDirection = findDownDirection(pointInPolygon);
//        printDirection(downDirection);
        if(downDirection == Direction.UNKNOWN) return false;
        if(upDirection == downDirection) return false;


        Direction leftDirection = findLeftDirection(pointInPolygon);
//        printDirection(leftDirection);
        if(leftDirection == Direction.UNKNOWN) return false;

        Direction rightDirection = findRightDirection(pointInPolygon);
//        printDirection(rightDirection);
        if(rightDirection == Direction.UNKNOWN) return false;
        if(leftDirection == rightDirection) return false;
        System.out.println();

        if(upDirection == Direction.LEFT && leftDirection == Direction.DOWN
            && downDirection == Direction.RIGHT && rightDirection == Direction.UP
            ||
            upDirection == Direction.RIGHT && rightDirection == Direction.DOWN
                && downDirection == Direction.LEFT && leftDirection == Direction.UP
        ){
            return true;
        }


        return false;
    }

    private static void printDirection(Direction dir){
        if(dir == Direction.UNKNOWN){
            System.out.print("o");
        } else if(dir == Direction.UP){
            System.out.print("^");
        } else if(dir == Direction.DOWN){
            System.out.print("v");
        } else if(dir == Direction.LEFT){
            System.out.print("<");
        } else if(dir == Direction.RIGHT){
            System.out.print(">");
        }
    }

    private static Direction findRightDirection(JSONArray pointInPolygon) {
        JSONArray rightPoints = findRightPoints(pointInPolygon);

//        if(rightPoints.size() < 4) return Direction.UNKNOWN;
        Direction rightDirection = Direction.UNKNOWN;
        // 所有的点都必须有同一方向
        for(Object o : rightPoints){
            JSONObject o1 = (JSONObject) o;
            Double d = o1.getDouble("d");

            // 直上直下的过滤掉
            if(d == 90 || d == -90){
                return Direction.UNKNOWN;
            }

            // 当前点的方向
            Direction pointDir;
            if(d > -90 && d < 90){
                pointDir = Direction.UP;
            } else {
                pointDir = Direction.DOWN;
            }


            if(rightDirection == Direction.UNKNOWN){
                // 上的方向未定义时与当前点一致
                rightDirection = pointDir;
            } else if(pointDir != rightDirection){
                // 如果上方向已经定义,且当前点与上方向点不一至,说明该点不是风眼 <-  ->
                return Direction.UNKNOWN;
            }
        }

        return rightDirection;
    }

    private static Direction findLeftDirection(JSONArray pointInPolygon) {

        JSONArray leftPoints = findLeftPoints(pointInPolygon);

//        if(leftPoints.size() < 4) return Direction.UNKNOWN;
        Direction leftDirection = Direction.UNKNOWN;
        // 所有的点都必须有同一方向
        for(Object o : leftPoints){
            JSONObject o1 = (JSONObject) o;
            Double d = o1.getDouble("d");

            // 直上直下的过滤掉
            if(d == 90 || d == -90){
                return Direction.UNKNOWN;
            }

            // 当前点的方向
            Direction pointDir;
            if(d > -90 && d < 90){
                pointDir = Direction.UP;
            } else {
                pointDir = Direction.DOWN;
            }


            if(leftDirection == Direction.UNKNOWN){
                // 上的方向未定义时与当前点一致
                leftDirection = pointDir;
            } else if(pointDir != leftDirection){
                // 如果上方向已经定义,且当前点与上方向点不一至,说明该点不是风眼 <-  ->
                return Direction.UNKNOWN;
            }
        }

        return leftDirection;

    }

    private static JSONArray findLeftPoints(JSONArray pointInPolygon) {

        Optional<Double> x1 = pointInPolygon.stream().map(o -> {
            JSONObject o1 = (JSONObject) o;
            return o1.getDouble("x");
        }).min(Comparator.comparing(Double::doubleValue));

        Double minx = x1.get();

        JSONArray array = new JSONArray();

        pointInPolygon.stream().filter(o->{
            JSONObject o1 = (JSONObject) o;
            return o1.getDouble("x").equals(minx);
        }).forEach(o->array.add(o));

        return array;

    }

    private static JSONArray findRightPoints(JSONArray pointInPolygon) {

        Optional<Double> x1 = pointInPolygon.stream().map(o -> {
            JSONObject o1 = (JSONObject) o;
            return o1.getDouble("x");
        }).max(Comparator.comparing(Double::doubleValue));

        Double maxx = x1.get();

        JSONArray array = new JSONArray();

        pointInPolygon.stream().filter(o->{
            JSONObject o1 = (JSONObject) o;
            return o1.getDouble("x").equals(maxx);
        }).forEach(o->array.add(o));

        return array;

    }

    private static Direction findDownDirection(JSONArray pointInPolygon) {

        JSONArray downPoints = findDownPoints(pointInPolygon);

//        if(downPoints.size() < 4) return Direction.UNKNOWN;
        Direction downDirection = Direction.UNKNOWN;
        // 所有的点都必须有同一方向
        for(Object o : downPoints){
            JSONObject o1 = (JSONObject) o;
            Double d = o1.getDouble("d");

            // 直上直下的过滤掉
            if(d == 0 || d == 180){
                return Direction.UNKNOWN;
            }

            // 当前点的方向
            Direction pointDir;
            if(d > 0){
                pointDir = Direction.RIGHT;
            } else {
                pointDir = Direction.LEFT;
            }


            if(downDirection == Direction.UNKNOWN){
                // 上的方向未定义时与当前点一致
                downDirection = pointDir;
            } else if(pointDir != downDirection){
                // 如果上方向已经定义,且当前点与上方向点不一至,说明该点不是风眼 <-  ->
                return Direction.UNKNOWN;
            }
        }

        return downDirection;
    }

    private static Direction findUpDirection(JSONArray pointInPolygon) {
        // 找上方的点
        JSONArray upPoints = findUpPoints(pointInPolygon);
//        if(upPoints.size() < 4) return Direction.UNKNOWN;
        Direction upDirection = Direction.UNKNOWN;
        // 所有的点都必须有同一方向
        for(Object o : upPoints){
            JSONObject o1 = (JSONObject) o;
            Double d = o1.getDouble("d");

            // 直上直下的过滤掉
            if(d == 0 || d == 180){
                return Direction.UNKNOWN;
            }

            // 当前点的方向
            Direction pointDir;
            if(d > 0){
                pointDir = Direction.RIGHT;
            } else {
                pointDir = Direction.LEFT;
            }


            if(upDirection == Direction.UNKNOWN){
                // 上的方向未定义时与当前点一致
                upDirection = pointDir;
            } else if(pointDir != upDirection){
                // 如果上方向已经定义,且当前点与上方向点不一至,说明该点不是风眼 <-  ->
                return Direction.UNKNOWN;
            }
        }

        return upDirection;

    }

    private static JSONArray findDownPoints(JSONArray pointInPolygon) {
        List<Double> xall = pointInPolygon.stream().map(o -> {
            JSONObject o1 = (JSONObject) o;
            return o1.getDouble("x");
        }).distinct().collect(Collectors.toList());

        JSONArray array = new JSONArray();

        xall.forEach(x->{
            Optional<Object> min = pointInPolygon.stream().filter(o -> {
                // 找到同一列的点
                JSONObject o1 = (JSONObject) o;
                return o1.getDouble("x").equals(x);
            }).min(Comparator.comparing(o -> {
                // 找到同一列最y值是小的点
                JSONObject o1 = (JSONObject) o;
                return o1.getDouble("y");
            }));
            Object o = min.get();
            array.add(o);
        });

        return array;
    }

    private static JSONArray findUpPoints(JSONArray pointInPolygon) {

        List<Double> xall = pointInPolygon.stream().map(o -> {
            JSONObject o1 = (JSONObject) o;
            return o1.getDouble("x");
        }).distinct().collect(Collectors.toList());

        JSONArray array = new JSONArray();

        xall.forEach(x->{
            Optional<Object> max = pointInPolygon.stream().filter(o -> {
                // 找到同一列的点
                JSONObject o1 = (JSONObject) o;
                return o1.getDouble("x").equals(x);
            }).max(Comparator.comparing(o -> {
                // 找到同一列最y值是小的点
                JSONObject o1 = (JSONObject) o;
                return o1.getDouble("y");
            }));
            Object o = max.get();
            array.add(o);

        });


        return array;

    }

    private static JSONArray findPointInPolygon(Double startX, Double startY, Double endX, Double endY) {

        JSONArray objects = new JSONArray();

        for (Object o : data) {
            JSONObject o1 = (JSONObject) o;
            Double x = o1.getDouble("x");
            Double y = o1.getDouble("y");
            if(x < startX || y > startY || x > endX || y < endY) {
                continue;
            } else {
                objects.add(o);
                if(objects.size() >= calPointTotalNum*calPointTotalNum){
                    break;
                }
            }
//            if(myPolygon.contains(x, y)){
//
//            }

        }

        return objects;
    }

    private static MyPolygon getMyPolygen(Double startx, Double starty,Double endX,Double endY) {
        MyPolygon myPolygon = new MyPolygon();
        myPolygon.addPoint(startx, starty);//左下
        myPolygon.addPoint(startx, endY);//左上
        myPolygon.addPoint(endX,endY);//右上
        myPolygon.addPoint(endX, starty);//右下
        return myPolygon;
    }


    public enum Direction {
        UP,
        DOWN,
        LEFT,
        RIGHT,
        UNKNOWN;
    }

}

猜你喜欢

转载自blog.csdn.net/u011498478/article/details/124378990
今日推荐