Как найти сектор из координат x и y в круге - PullRequest
0 голосов
/ 19 июня 2019

Обратите внимание, что большинство чисел, которые я буду использовать, являются лишь примерами, поскольку они должны быть динамическими

Я пытаюсь создать круг с динамической высотой, шириной и круговыми секторами, используя иконку полного блока UTF (= █) (затем они используются в голограммах Minecraft, которые центрированы, так что нет связки пробелов для центрирования) .

Допустим, у меня, например, есть круг 25x25 (диаметр 25) с 12 (почти одинаковыми) секторами, каждый из этих секторов будет иметь свой цвет, центр круга (0, 0). Как я смогу «разделить» этот круг на сектора и поместить идентификатор сектора (например, 0-11) в координату?

Ниже вы видите код, который я сейчас использую, метод getSectionNumber вообще не работает и, вероятно, его можно игнорировать:

public class HologramCircle {

    private final int height;
    private final int width;

    public HologramCircle(final int height, final int width) {
        this.height = height;
        this.width = width;
    }

    public List<String> getLines() {
        final float width_r = (float) width / 2;
        final float height_r = (float) height / 2;
        final float ratio = width_r / height_r;

        final double maxblocks_x;
        final double maxblocks_y;

        if ((width_r * 2) % 2 == 0) {
            maxblocks_x = Math.ceil(width_r - .5) * 2 + 1;
        } else {
            maxblocks_x = Math.ceil(width_r) * 2;
        }

        if ((height_r * 2) % 2 == 0) {
            maxblocks_y = Math.ceil(height_r - .5) * 2 + 1;
        } else {
            maxblocks_y = Math.ceil(height_r) * 2;
        }

        final List<String> lines = Lists.newArrayList();

        for (double y = -maxblocks_y / 2 + 1; y <= maxblocks_y / 2 - 1; y++) {
            final StringBuilder line = new StringBuilder();

            for (double x = -maxblocks_x / 2 + 1; x <= maxblocks_x / 2 - 1; x++) {
                if (shouldBeFilled(x, y, width_r, ratio)) {
                    System.out.println(
                            String.format("Section id for x: %s and y: %s is %s", x, y, getSectorNumber(x, y, width_r, 12))
                    );
                    line.append("█");
                }
            }
            lines.add(line.toString());
        }
        return lines;
    }

    private int getSectorNumber(final double x, final double y, final double radius, final int sectorAmount) {
        final double degreesPerSector = 360 / sectorAmount;
        final double rad = Math.atan2(y, x);
        final double degrees = rad * (180 / Math.PI);

        System.out.println("rad: " + rad + ", degrees: " + degrees);

        for (int i = 0; i < sectorAmount; i++) {
            final double startDegrees = degreesPerSector * i;
            final double endDegrees = startDegrees + degreesPerSector;

            if (degrees >= startDegrees && degrees <= endDegrees) {
                return i;
            }
        }

        return -1;
    }

    private double distance(final double x, final double y, final double ratio) {
        return Math.sqrt((Math.pow(y * ratio, 2)) + Math.pow(x, 2));
    }

    private boolean shouldBeFilled(final double x, final double y, final double radius, final float ratio) {
        return distance(x, y, ratio) <= radius;
    }

Мое решение:

Код, который я имел в моем getSectionNumber, уже двигался в правильном направлении, в итоге я просто добавил 180 °, чтобы он достиг диапазона 0-360. Вот код, с которым я столкнулся:

package com.dbsoftwares.dangerwheel.hologram;

import com.google.common.collect.Lists;
import net.md_5.bungee.api.ChatColor;

import java.util.List;

public class HologramCircle {

    private final int height;
    private final int width;

    public HologramCircle(final int height, final int width) {
        this.height = height;
        this.width = width;
    }

    public List<String> getLines() {
        final float width_r = (float) width / 2;
        final float height_r = (float) height / 2;
        final float ratio = width_r / height_r;

        final double maxblocks_x;
        final double maxblocks_y;

        if ((width_r * 2) % 2 == 0) {
            maxblocks_x = Math.ceil(width_r - .5) * 2 + 1;
        } else {
            maxblocks_x = Math.ceil(width_r) * 2;
        }

        if ((height_r * 2) % 2 == 0) {
            maxblocks_y = Math.ceil(height_r - .5) * 2 + 1;
        } else {
            maxblocks_y = Math.ceil(height_r) * 2;
        }

        final List<String> lines = Lists.newArrayList();

        for (double y = -maxblocks_y / 2 + 1; y <= maxblocks_y / 2 - 1; y++) {
            final StringBuilder line = new StringBuilder();

            for (double x = -maxblocks_x / 2 + 1; x <= maxblocks_x / 2 - 1; x++) {
                if (shouldBeFilled(x, y, width_r, ratio)) {
                    final int sector = getSectorNumber(x, y, 12);

                    line.append(ChatColor.values()[sector].toString());
                    line.append("█");
                }
            }
            lines.add(line.toString());
        }
        return lines;
    }

    private int getSectorNumber(final double x, final double y, final int sectorAmount) {
        final double degreesPerSector = 360 / sectorAmount;
        final double rad = Math.atan2(y, x);
        final double degrees = rad * (180 / Math.PI) + 180;

        for (int i = 0; i < sectorAmount; i++) {
            final double startDegrees = degreesPerSector * i;
            final double endDegrees = startDegrees + degreesPerSector;

            if (degrees >= startDegrees && degrees <= endDegrees) {
                return i;
            }
        }

        return -1;
    }

    private double distance(final double x, final double y, final double ratio) {
        return Math.sqrt((Math.pow(y * ratio, 2)) + Math.pow(x, 2));
    }

    private boolean shouldBeFilled(final double x, final double y, final double radius, final float ratio) {
        return distance(x, y, ratio) <= radius;
    }
}

Это мой результат сейчас, он не идеален, но это точно соответствует моим потребностям

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...