JAVA 圆中 任意一点 和 角度 计算 哪些点满足


import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * @author wgq
 * @date 2024-01-18 15:03
 */
public class Main {

    protected RTreeBean<Point> troopTreeMap = new RTreeBean<>();

    public static void main(String[] args) {
        new Main().frame();

    }

    BufferedImage image = null;

    public void frame() {

        JFrame frame = new JFrame("Half Circle Drawing");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());
        JButton but = new JButton("确定");
        JTextField txt = new JTextField(20);
        JPanel panel = new JPanel();
        panel.add(new JLabel("x:y"));
        panel.add(txt);
        panel.add(but);
        but.addActionListener(e -> {
            String[] split = txt.getText().split(":");
            resetImage(Integer.parseInt(split[0]), Integer.parseInt(split[1]));
            frame.repaint();
        });
        frame.add(panel, BorderLayout.NORTH);
        frame.add(new MyPanel(), BorderLayout.CENTER);
        frame.setSize(950, 1000);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

        resetImage(25, 15);
        frame.repaint();
    }

    private void resetImage(int rx, int rz) {

        int size = 30;
        int width = 30;
        troopTreeMap = new RTreeBean<>();
        image = new BufferedImage(size * width, size * width, BufferedImage.TYPE_INT_RGB);
        Graphics g = image.getGraphics();
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, image.getWidth(), image.getHeight());
        g.setColor(Color.BLACK);
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                troopTreeMap.add(i, j, new Point(i, j));
                g.drawRect(i * width, j * width, width, width);
            }
        }
        int x = 15;
        int z = 15;
        int range = 10;

        double span = 120;// 角度

        List<Point> result = null;

        result = rectCell(x, z, range);
        g.setColor(Color.gray);
        for (Point p : result) {
            g.fillRect(p.x * width, p.z * width, width, width);
        }

        result = ovalCell(x, z, range);

        g.setColor(Color.BLUE);
        for (Point p : result) {
            g.fillRect(p.x * width, p.z * width, width, width);
        }

        System.out.println("x = " + x + " z = " + z + " rx = " + rx + " rz = " + rz + " calcAngle = " + getDistance(x, z, rx, rz));
        result = semicircleCell(x, z, rx, rz, range, span);
        g.setColor(Color.GREEN);
        for (Point p : result) {
            g.fillRect(p.x * width, p.z * width, width, width);
        }

        g.setColor(Color.RED);
        g.fillRect(x * width, z * width, width, width);
        g.setColor(Color.CYAN);
        g.fillRect(rx * width, rz * width, width, width);

        g.setColor(Color.BLACK);
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                g.drawRect(i * width, j * width, width, width);
                g.drawString(String.valueOf(i), i * width + 2, j * width + width / 2);
                g.drawString(String.valueOf(j), i * width + width / 2, j * width + width - 2);
            }
        }
        g.drawRect(1, 1, size * width - 2, size * width - 2);
        g.setColor(Color.RED);
        g.drawOval((x - range) * width, (x - range) * width, (range * 2 + 1) * width, (range * 2 + 1) * width);
    }


    public List<Point> rectCell(float x, float z, int range) {

        float xMin = x - range;
        float xMax = x + range;
        float yMin = z - range;
        float yMax = z + range;
        return troopTreeMap.query(xMin, xMax, yMin, yMax);
    }

    //  圆形
    public List<Point> ovalCell(float x, float z, int range) {
        List<Point> list = rectCell(x, z, range);
        if (Objects.isNull(list)) {
            return Collections.emptyList();
        }
        for (int i = 0; i < list.size(); i++) {
            Point cell = list.get(i);
            float cx = cell.getX();
            float cz = cell.getZ();
            double val = getDistance(x, 0, z, cx, 0, cz);
            if (val > range) {
                list.remove(cell);
                i--;
            }
        }
        return list;
    }

    public List<Point> semicircleCell(int x, int z, int rx, int rz, int range, double span) {
        List<Point> list = ovalCell(x, z, range);
        // 把绝对坐标换成相对坐标
        List<Point> pointList = new ArrayList<>();
        for (Point p : list) {
            Point point = new Point(p.x - x, p.z - z);
            pointList.add(point);
        }
        rx = rx - x;
        rz = rz - z;

        // 计算两点连线相对于正x轴的角度(弧度)
        double dis = getDistance(rx, rz);

        // 过滤半圆
        for (int i = 0; i < pointList.size(); i++) {
            Point cell = pointList.get(i);
            float cx = cell.getX();
            float cz = cell.getZ();
            // 计算两点连线相对于正x轴的角度(弧度)
            double degrees = getDistance(cx, cz);
            System.out.println("cx = " + cx + " cz = " + cz + " " + (cx + x) + "/" + (cz + z) + " degrees = " + degrees + " == " + (dis - degrees));

            if (degrees == dis) {
                continue;
            }
            if (dis + span / 2 >= 360 && degrees < span / 2) {
                degrees += 360;
            } else if (degrees + span / 2 >= 360 && dis <= span / 2) {
                degrees -= 360;
            }

            if (Math.abs(dis - degrees) > span / 2) {
                pointList.remove(cell);
                i--;
            }
        }
        for (Point p : pointList) {
            p.setX(p.x + x);
            p.setZ(p.z + z);
        }
        return pointList;
    }

    public static double getDistance(double x1, double y1, double x2, double y2) {

        double dx = x2 - x1;
        double dy = y2 - y1;

        double radians = Math.atan2(dy, dx);
        double degrees = Math.toDegrees(radians);

        if (degrees < 0) {
            degrees += 360;
        }
        return degrees;
    }

    public static double getDistance(double x2, double y2) {
        double radians = Math.atan2(y2, x2);
        double degrees = Math.toDegrees(radians);

        if (degrees < 0) {
            degrees += 360;
        }
        return degrees;
    }

    public static double getDistance(float x1, float y1, float z1, float x2, float y2, float z2) {
        return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) + (z2 - z1) * (z2 - z1));
    }

    public static class Point {
        int x;
        int z;

        public Point(int x, int z) {
            this.x = x;
            this.z = z;
        }

        public int getX() {
            return x;
        }


        public int getZ() {
            return z;
        }

        public void setX(int x) {
            this.x = x;
        }

        public void setZ(int z) {
            this.z = z;
        }
    }

    public class MyPanel extends JPanel {
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;
            g2d.drawImage(image, 0, 0, null);
        }
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值