powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Задачка про остров
25 сообщений из 421, страница 12 из 17
Задачка про остров
    #39931279
exp98
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Моя хотел бы доставать это из облака-мыл-ру-публик.
Как выше iOracleDev в Моя картинка ... mypict
...
Рейтинг: 0 / 0
Задачка про остров
    #39931288
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
exp98
iOracleDev
Моя картинка ... mypict
Забавно, ужели вот так диффузно вода порсачивается сквозь точечное облако?

Как понимаю вы все у финиша. Вопрос у меня теперь. Я слышал, выговорили про срезы. Основа алгоритма какая? Делать попикселные срезы, в каждом искать замкнутые контуры, затем просуммировать внутренности контуров, границы не считать, так?
Без никаких деревьев или графов, да?


Финиш пройден, проверил 3 варианта (графы идут лесом):

1) Нарезаем слоями по высоте и заполняем водой каждый слой по отдельности.
Отладил не сразу из-за проблемы слияния ручейков. Работает, но медленно.
Плюс в том, что результаты можно использовать для отладки.

2) Ставим по периметру бесконечной высоты стены, заливаем все это водой под завязку, а потом срезаем лишнюю воду,
проходя по высотам снизу вверх. Простейшая рекурсия. Работает быстрее т.к. каждая ячейка считается 1 раз.

3) Тот же вариант без рекурсии. Чуть быстрее.

Скорость всех вариантов заметно зависит от организации данных.
...
Рейтинг: 0 / 0
Задачка про остров
    #39931343
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Конвертировал PNG/jpg картинки с ландшафтами в полу-текстовый pgm с помошью Линуксового convert.

Хм... странно получается только заголовок текстовый. А туловище битмапы не-текстовый (не принтабельный вид).
Оно вроде-бы не страшно но я хотел сохранить эту текстовую природу. Это поможет в топике легче
разбирать различные ситуации.

Пришлось потратить еще час времени чтоб написать на java пару утилит для PPM(цветные) PGM(черно белые) конвертеры
с чисто текстовым представлением.
...
Рейтинг: 0 / 0
Задачка про остров
    #39931361
iOracleDev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
exp98
Забавно, ужели вот так диффузно вода порсачивается сквозь точечное облако?

Как понимаю вы все у финиша. Вопрос у меня теперь. Я слышал, выговорили про срезы. Основа алгоритма какая? Делать попикселные срезы, в каждом искать замкнутые контуры, затем просуммировать внутренности контуров, границы не считать, так?
Без никаких деревьев или графов, да?

Мой вариант простой, иду сверху срезая высоты, например пусть будет полное затопление и максимальная высота острова 255, тогда первый срез будет на высоте 255, при этом плитки на том же уровне считаются для среза сухими.

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

Отработал уровень, в итоге для 255 уровня получаю плитки с временным статусом и плитки которые статус не получили, далее прохожу по всем плиткам и снимаю временный статус, если временный статус не был установлен ставлю постоянный статус, если плитка имеет ту же высоту что и обрабатываемый срез (255), то она получает постоянный статус "сухая", если плитка имеет меньшую высоту и не имела временный статус она получает постоянный статус "под водой". Таким образом все плитки того же уровня получили статус "сухая", плитки имеющие уровень ниже и оказавшиеся в замкнутых контурах получили статус "под водой".

Считаем следующий уровень 254, точно также поиском в ширину от периметра, плитки получившие постоянный статус на предыдущих уровнях недоступны (не зависимо от того сухие они или под водой, их статус уже постоянный), точно также получаем плитки с временным статусом - те до которых поиск смог добраться, плитки того же уровня и замкнутые контуры ограниченные плитками того же уровня или плитками имеющими постоянный статус недоступны для поиска, он не может в них пробраться. Далее повторяем процедуру, снимаем временный статус и для плиток того же уровня ставим статус "сухая", для остальных не имевших временного статуса ставим статус "под водой", постоянные статусы полученные на предыдущих уровнях уже неизменны до конца расчета.

Если наводнение не полное и не покрывает остров целиком, то для самого верхнего уровня все плитки не получившие временный статус получают постоянный статус "сухая", даже если их уровень ниже уровня наводнения, поскольку вода не имела к ним доступа.

Картинки подъема воды делал просто считая последовательно по одному срезу, задавая уровень подъема воды и уровень океана после отлива одинаковым.
...
Рейтинг: 0 / 0
Задачка про остров
    #39931362
iOracleDev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov
1) Нарезаем слоями по высоте и заполняем водой каждый слой по отдельности.
Отладил не сразу из-за проблемы слияния ручейков. Работает, но медленно.
Плюс в том, что результаты можно использовать для отладки.

Откуда ты там ручейки взял?
...
Рейтинг: 0 / 0
Задачка про остров
    #39931367
Фотография Имя пользователя1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
exp98,

Мой вариант здесь: 22077648
Пока не заводил, нет времени.

Там никаких срезов, сплошной поиск в ширину, правда, для обработки озёр хочу вместо оного сделать построчный floodfill, это даст ускорение на кейсах с большими лужами, особенно в виде лабиринтов. В общем, говнокодить придётся много )
...
Рейтинг: 0 / 0
Задачка про остров
    #39931429
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
iOracleDev
Aleksandr Sharahov
1) Нарезаем слоями по высоте и заполняем водой каждый слой по отдельности.
Отладил не сразу из-за проблемы слияния ручейков. Работает, но медленно.
Плюс в том, что результаты можно использовать для отладки.

Откуда ты там ручейки взял?


начни реализовывать floodfill, сразу поймешь )
...
Рейтинг: 0 / 0
Задачка про остров
    #39931515
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Саш. А твои сорцы где-то опубликованы в последней версии?
...
Рейтинг: 0 / 0
Задачка про остров
    #39931527
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton
Саш. А твои сорцы где-то опубликованы в последней версии?


Сорцы 22081712 .
Пример карты и результат 22081766 .
Там же чуть ниже еще, если надо, процедура генерации случайной карты и датчик случайных чисел.
...
Рейтинг: 0 / 0
Задачка про остров
    #39931635
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov
mayton
Саш. А твои сорцы где-то опубликованы в последней версии?


Сорцы 22081712 .
Пример карты и результат 22081766 .
Там же чуть ниже еще, если надо, процедура генерации случайной карты и датчик случайных чисел.

Я смогу воспроизвести его под Linux Free Pascal (fpc) правда с твоей помошью и если аккуратно
выкосить создание формочек.

Потом я сделаю некий сравнительный тест твоего сорца и iOracleDev-s.

И еще особо меня интересовали эвристики основанные на предварительном анализе карты.
Например шум и пики - один подход. Множество горизонтальных плато - другой.
...
Рейтинг: 0 / 0
Задачка про остров
    #39931801
iOracleDev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov
начни реализовывать floodfill, сразу поймешь )

Закраска области ограничена областью, при этом если эта область внутри концентрической системы, то без костылей она будет закрашена не в тот цвет, потому что нужный цвет лежит за границей доступной области в общем я не вижу других логичных алгоритмов кроме поиска в ширину по срезам или без срезов, но для каждой точки, что в плане производительности тоже не очень.
...
Рейтинг: 0 / 0
Задачка про остров
    #39931805
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вавилонскую башню (спираль) я так и неосилил. Подниму в топике Программинга - отдельно.
...
Рейтинг: 0 / 0
Задачка про остров
    #39932419
exp98
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
это типа такого, только с градиентной беговой дорожкой внутри?

И ... забыл спросить, у вас пикселы 6-угольные в сечении?
...
Рейтинг: 0 / 0
Задачка про остров
    #39932439
iOracleDev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
exp98
И ... забыл спросить, у вас пикселы 6-угольные в сечении?

Мы упростили для визуализации, хотя если у вас на мониторе и в графических файлах пиксели шестиугольные, то мы идем к вам))
...
Рейтинг: 0 / 0
Задачка про остров
    #39932441
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не совсем. Не стенки. А спиральная дорога вокруг горы.

Я искал формулу вида z = f(x,y)
...
Рейтинг: 0 / 0
Задачка про остров
    #39932442
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
iOracleDev
exp98
И ... забыл спросить, у вас пикселы 6-угольные в сечении?

Мы упростили для визуализации, хотя если у вас на мониторе и в графических файлах пиксели шестиугольные, то мы идем к вам))

Топик стартовал как решение графовых задач с 6й степенью вершин.

Но для визуализации что 4 что 6 степени одинаковы.
...
Рейтинг: 0 / 0
Задачка про остров
    #39932496
exp98
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спсб за пояснения.
Искал способ примазаться к чужой славе, но здесь всё схвачено)
mayton
формулу вида z = f(x,y)
Теоретически можно, возиться долго лень. Это же типа отображения полоски в 3Д или как кожура, с мандарина аккуратной полоской срезанная.
Предлагаю брутальный способ закраски (даже танцуя не от пикселов к цвету, а лучами как получится, с перекрытиями). Спираль - это точки радиуса, а будет полуоткрытый ]отрезок], не идеальный асфальт на дороге, конечно, с камешками. Раз уж ввязался.
...
Рейтинг: 0 / 0
Задачка про остров
    #39932501
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
параметрически ? Как f(R,phi)
...
Рейтинг: 0 / 0
Задачка про остров
    #39932502
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
По поводу Rust. Я был неправ. Завяз в мелочах. Задача чуть более широкая а мелкие технические вопросы постоянно
меня блокируют. Я попробую реализовать на Java. А потом уже с экспериментами.
...
Рейтинг: 0 / 0
Задачка про остров
    #39932523
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov
mayton
Саш. А твои сорцы где-то опубликованы в последней версии?


Сорцы 22081712 .
Пример карты и результат 22081766 .
Там же чуть ниже еще, если надо, процедура генерации случайной карты и датчик случайных чисел.

Не удалось мне собрать на FPC под Linux твой исходник. Надо что-то добавить.

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
#!/bin/bash
fpc -Mdelphi -CX -O3 -XX -vewnhi -Fi. -Fu. -FU. islands.lpr

Hint: Start of reading config file /etc/fpc.cfg
Hint: End of reading config file /etc/fpc.cfg
Free Pascal Compiler version 3.0.4+dfsg-18ubuntu2 [2018/08/29] for x86_64
Copyright (c) 1993-2017 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling islands.lpr
islands.lpr(96) Fatal: Syntax error, "BEGIN" expected but "end of file" found
Fatal: Compilation aborted
Error: /usr/bin/ppcx64 returned an error exitcode


Я не знаток и не могу за 10 минут пофиксить языковые недочеты. Больше тратить время не хочется.
Демотивирует. 96 строка - это конец исходника.
...
Рейтинг: 0 / 0
Задачка про остров
    #39932526
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton,
просто вызывалку нужно добавить в конец
Что-то вроде
Код: pascal
1.
2.
3.
4.
5.
BEGIN
   writeln('function returns: ',FillWater());
   readln;
END.
  

.
...
Рейтинг: 0 / 0
Задачка про остров
    #39932527
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Уже лучше. Бинарник собрался.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Hint: Start of reading config file /etc/fpc.cfg
Hint: End of reading config file /etc/fpc.cfg
Free Pascal Compiler version 3.0.4+dfsg-18ubuntu2 [2018/08/29] for x86_64
Copyright (c) 1993-2017 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling islands.lpr
Linking islands
/usr/bin/ld.bfd: warning: link.res contains output sections; did you forget -T?
100 lines compiled, 0.1 sec
2 hint(s) issued



Работает секунд 10 потом выдает число

Код: pascal
1.
2.
~/git/probe/islands/sharahov$ ./islands
function returns: 3288343446



Не вижу функционала загрузки картинок.
Насколько я понимаю Саша решил генерить карты белым шумом.
Это несоклко сужает поле для экспериментов.
...
Рейтинг: 0 / 0
Задачка про остров
    #39932528
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вобщем нужно доработать. Переделать HEX ячейки в пикселы. И заргужать вот с таких вот картинок.

https://people.sc.fsu.edu/~jburkardt/data/pgma/pgma.html

Без этого мы не сможем сравнивать алгоритмы.
...
Рейтинг: 0 / 0
Задачка про остров
    #39932559
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
iOracleDev
Кто захочет поразвлекаться, исходные данные в массиве, списком и графом
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
public class Hexagon {

    public static final int NUMBER_OF_SIDES = 6;
    private int height;
    private String status;

    // индексы ребер
    //   1 /\ 2
    //  0 |  | 3
    //   5 \/ 4
    private Hexagon[] hexagonSides = new Hexagon[NUMBER_OF_SIDES];

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public void setHexagonSides(Hexagon[] hexagonSides) {
        this.hexagonSides = hexagonSides;
    }

    public Hexagon getHexagonSide(int side) {
        return hexagonSides[side];
    }

    public void setHexagonSide(int side, Hexagon hexagon) {
        this.hexagonSides[side] = hexagon;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public Hexagon(int height) {
        this.height = height;
    }

    @Override
    public String toString() {
        return Integer.toString(this.height);
    }
}



Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
import java.util.ArrayList;

public class Main {

    public static void main(String[] args) {

        //   1 /\ 2
        //  0 |  | 3
        //   5 \/ 4

        //         / \ / \ / \                    / \ / \ / \
        //        | 0 | 1 | 2 |                  | 1 | 4 | 3 |
        //       / \ / \ / \ / \                / \ / \ / \ / \
        //      | 3 | 4 | 5 | 6 |              | 1 | 5 | 1 | 5 |
        //     / \ / \ / \ / \ / \            / \ / \ / \ / \ / \
        //    | 7 | 8 | 9 | 10| 11|          | 2 | 3 | 2 | 4 | 6 |
        //     \ / \ / \ / \ / \ /            \ / \ / \ / \ / \ /
        //      | 12| 13| 14| 15|              | 2 | 6 | 4 | 2 |
        //       \ / \ / \ / \ /                \ / \ / \ / \ /
        //        | 16| 17| 18|                  | 3 | 1 | 2 |
        //         \ / \ / \ /                    \ / \ / \ /

        int[][] array = new int[][] {
                {0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 1, 4, 3, 0},
                {0, 0, 1, 5, 1, 5, 0},
                {0, 2, 3, 2, 4, 6, 0},
                {0, 2, 6, 4, 2, 0, 0},
                {0, 3, 1, 2, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0}
        };

        // массив шестиугольников
        Hexagon[][] arrayHexagons = new Hexagon[array.length][array[0].length];
        // список шестиугольников
        ArrayList <Hexagon> listOfHexagons = new ArrayList<>(20);

        // заполняем массив и список, ссылки в массиве и списке на одни и те же шестиугольники
        for (int i = 0; i < array.length; i++ ) {
            for (int k = 0; k < array[i].length; k++) {
                if (array[i][k] > 0) {
                    arrayHexagons[i][k] = new Hexagon(array[i][k]);
                    listOfHexagons.add(arrayHexagons[i][k]);
                } else {
                    arrayHexagons[i][k] = null;
                }
            }
        }

        // записываем связи шестиугольников друг с другом
        for (int i = 1; i < array.length - 1; i++ ) {
            for (int k = 1; k < array[i].length - 1; k++) {
                if (array[i][k] > 0) {
                    arrayHexagons[i][k].setHexagonSides(new Hexagon[] {
                                    arrayHexagons[i][k-1], arrayHexagons[i-1][k], arrayHexagons[i-1][k+1],
                                    arrayHexagons[i][k+1], arrayHexagons[i+1][k], arrayHexagons[i+1][k-1] });
                }
            }
        }

        System.out.println(listOfHexagons);
        System.out.println("====================================");
        for (Hexagon[] h1: arrayHexagons) {
            for (Hexagon h2: h1) {
                if (h2 != null) {
                    System.out.print(h2 + " - ");
                    for (int i = 0; i < Hexagon.NUMBER_OF_SIDES; i++) {
                        System.out.print(h2.getHexagonSide(i) + ((i+1 < Hexagon.NUMBER_OF_SIDES) ? ", " : ""));
                    }
                    System.out.println();
                }
            }
        }
    }
}


iOracleDev.

Это последняя версия твоего исходника?
...
Рейтинг: 0 / 0
Задачка про остров
    #39932578
iOracleDev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton,

Нет, вот исходник:
iOracleDev
Мой вариант, он конечно не оптимален в плане реализации, зато квадратно-гнездовой и по нему можно проверять более оптимальные варианты.
Площадка:

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
public class Node {

    public final int NUMBER_OF_NEIGHBOURS;
    private int height;
    private char status;

    private Node[] neighbours;

    public Node(int height) {
        this(height, 4);
    }

    public Node(int height, int NUMBER_OF_NEIGHBOURS) {
        this.NUMBER_OF_NEIGHBOURS = NUMBER_OF_NEIGHBOURS;
        this.height = height;
        this.neighbours = new Node[this.NUMBER_OF_NEIGHBOURS];
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public void setNeighbours(Node[] neighbours) {
        this.neighbours = neighbours;
    }

    public Node getNeighbour(int neighbour) {
        return neighbours[neighbour];
    }

    public void setNeighbour(int neighbour, Node node) {
        this.neighbours[neighbour] = node;
    }

    public char getStatus() {
        return status;
    }

    public void setStatus(char status) {
        this.status = status;
    }

    @Override
    public String toString() {
        return Integer.toString(this.height);
    }
}



Превращение картинки в массив и обратно
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class GrayRgbBmpArray {

    public final int mask = 0b00000000_00000000_00000000_11111111;
    public int[][] imageInByte;
    public int[][] outputArray;
    private String fullInputFileName;
    private String fullOutputFileName;
    private BufferedImage originalImage;

    public GrayRgbBmpArray(String fullInputFileName, String fullOutputFileName) {
        this.fullInputFileName = fullInputFileName;
        this.fullOutputFileName = fullOutputFileName;
    }

    static BufferedImage deepCopy(BufferedImage bi) {
        ColorModel cm = bi.getColorModel();
        boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
        WritableRaster raster = bi.copyData(null);
        //System.out.println(cm.toString() + " " + raster.toString());
        return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
    }

    public void readToArray() {
        try {
            originalImage = ImageIO.read(new File(fullInputFileName));
            imageInByte = new int[originalImage.getHeight()][originalImage.getWidth()];
            outputArray = new int[originalImage.getHeight()][originalImage.getWidth()];
            int input, blue_channel, invert;
            for (int i = 0; i< originalImage.getHeight(); i++) {
                for (int k = 0; k < originalImage.getWidth(); k++) {
                    input = originalImage.getRGB(k, i);
                    //System.out.println(Integer.toBinaryString(input));
                    blue_channel =  input & mask;
                    invert = blue_channel ^ mask;
                    //System.out.println(invert);
                    imageInByte[i][k] = invert;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void writeToFile(int underWaterColorX, int  underWaterColorY) {
        if (outputArray == null || outputArray.length == 0 || outputArray[0].length == 0) {
            System.out.println("Нет данных для вывода в файл");
            return;
        }

        int height = outputArray.length;
        int width = outputArray[0].length;
        int blue_channel;
        // координаты пикселя исходного изображения с которого берется цвет для закраски затопленных плиток
        int underWaterColor = originalImage.getRGB(underWaterColorX, underWaterColorY);
        // результирующую картинку создаем как копию исходной
        BufferedImage image = deepCopy(originalImage);

        for (int i = 0; i < height; i++) {
            for (int k = 0; k < width; k++) {
                if (outputArray[i][k] == -1) {
                    // для затопленных плиток высота установлена в -1
                    image.setRGB(k,i, underWaterColor);
                } else {
                    blue_channel = outputArray[i][k]^mask;
                    image.setRGB(k,i, 0b11111111_00000000_00000000_00000000
                            | blue_channel << 16 | blue_channel << 8 | blue_channel);
                }
            }
        }

        try {
            ImageIO.write(image, "bmp", new FileOutputStream(fullOutputFileName));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}



Сам расчет, на входе массив, на выходе тоже массив
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
    public static int[][] Calculate(int[][] inputArray, int oceanLevel, int maxLevel) {
        // oceanLevel - уровень океана, ячейки граничащие с океаном на этом уровне сухие
        // maxLevel - максимальный уровень подъема воды
        if (inputArray == null || oceanLevel < 0 || maxLevel < oceanLevel) {
            System.out.println("Неконсистентные параметры");
            return null;
        }

        // массив четырехсвязных узлов (плиток)
        int height = inputArray.length;  // строки
        int width = inputArray[0].length; // столбцы
        Node[][] nodes = new Node[height][width];

        int underWater = oceanLevel - 1;
        int maxIslandLevel = 0;

        // заполняем массив узлами
        for (int i = 0; i < height; i++ ) {
            for (int k = 0; k < width; k++) {
                nodes[i][k] = new Node(inputArray[i][k]);
                nodes[i][k].setStatus('n');  // статус еще не определялся
                // определяем максимальную высоту (уровень) острова
                if (inputArray[i][k] > maxIslandLevel) {
                    maxIslandLevel = inputArray[i][k];
                }
            }
        }

        // если заданный уровень океана выше уровня острова, нет смысла считать пустые слои
        int startLevel;
        if (maxIslandLevel < maxLevel) {
            startLevel = maxIslandLevel;
        } else {
            startLevel = maxLevel;
        }

        // записываем связи узлов
        for (int i = 0; i < height; i++ ) {
            for (int k = 0; k < width; k++) {
                nodes[i][k].setNeighbours(new Node[] {  (k > 0) ? nodes[i][k-1] : null,
                                                        (i > 0) ? nodes[i-1][k] : null,
                                                        (k+1 < width) ? nodes[i][k+1] : null,
                                                        (i+1 < height) ? nodes[i+1][k] : null } );
            }
        }

        char st;  // переменная для кеширования статуса
        Node tmpNode; // переменная для кеширования узла
        Node nextNode; // в эту переменную сохраняем следующий узел при обходе периметра
        Node neighbourNode; // переменная для перебора соседей

        Queue<Node> queue = new LinkedList<>();
        for (int currentLevel = startLevel; currentLevel > underWater ; currentLevel--) {
            // на каждом уровне для каждой плитки ниже текущего уровня от периметра проводим поиск в ширину,
            // если она ниже текущего уровня и не имеет установленных постоянных статусов, то ставим временный
            // статус w - под водой, плитки раные текущему уровню или превышающие его не переходим
            // они являются барьером на текущем уровне
            queue.clear(); // очередь для поиска в ширину

            // обходим периметр и помещаем его в очередь на поиск в ширину
            tmpNode = nodes[0][0];
            int direction = 2; // начинаем идти вправо из нулевого узла
            while (tmpNode != null) {
                st = tmpNode.getStatus();
                if (st != 'D' && st != 'W' && tmpNode.getHeight() < currentLevel) {
                    tmpNode.setStatus('w');
                    queue.add(tmpNode);
                }

                nextNode = tmpNode.getNeighbour(direction);
                // если дошли до конца измерения, меняем направление на следующее
                if (nextNode == null) {
                    if (direction == 2) {
                        direction = 3;
                    }
                    else if (direction == 3)
                    {
                        direction = 0;
                    }
                    else if (direction == 0)
                    {
                        direction = 1;
                    } else {
                        break;
                    }
                    nextNode = tmpNode.getNeighbour(direction);
                }
                tmpNode = nextNode;
            }

            int processedNodes = queue.size();
            // выполняем для очереди поиск в ширину добавляя следующие узлы для обхода в очередь
            while (!queue.isEmpty()) {
                tmpNode = queue.poll();
                for (int j = 0; j < tmpNode.NUMBER_OF_NEIGHBOURS; j++) {
                    neighbourNode = tmpNode.getNeighbour(j);
                    if (neighbourNode == null) {
                        continue;
                    }

                    st = neighbourNode.getStatus();
                    if (st == 'w' || st == 'D' || st == 'W' || neighbourNode.getHeight() >= currentLevel) {
                        continue;
                    }
                    neighbourNode.setStatus('w');
                    queue.add(neighbourNode);
                    processedNodes++;
                }
            }

            System.out.println("Level = " + currentLevel + ",  processedNodes = " + processedNodes);

            // все плитки не имеющие постоянного статуса D (dry) или W (wet) и не имеющие временного
            // статуса w получают постоянный статус, статус w сбрасывается в u - unknown
            for (int i = 0; i < height; i++ ) {
                for (int k = 0; k < width; k++) {
                    tmpNode = nodes[i][k];
                    st = tmpNode.getStatus();
                    if (st == 'D' || st == 'W') {
                        continue;
                    }

                    if (tmpNode.getHeight() == currentLevel) {
                        tmpNode.setStatus('D');
                    } else if (st == 'w') {
                        tmpNode.setStatus('u');
                    } else if (currentLevel == maxLevel) {
                        tmpNode.setStatus('D');
                    } else {
                        tmpNode.setStatus('W');
                    }
                }
            }
        }

        for (int i = 0; i < height; i++ ) {
            for (int k = 0; k < width; k++) {
                // плитки не получившие постоянный статус и находящиеся ниже уровня океана
                tmpNode = nodes[i][k];
                st = tmpNode.getStatus();
                if (st != 'D' && st != 'W') {
                    tmpNode.setStatus('W');
                }
            }
        }

        // формируем результирующий массив
        int[][] outputArray = new int[height][width];
        for (int i = 0; i < height; i++ ) {
            for (int k = 0; k < width; k++) {
                tmpNode = nodes[i][k];
                if (tmpNode.getStatus() == 'W') {
                    outputArray[i][k] = -1;
                } else {
                    outputArray[i][k] = tmpNode.getHeight();
                }
            }
        }

        return outputArray;
    }
}



Использование:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
        // на входе нужен файл с 8-битной глубиной цвета и использованием 256 градаций серого, если хочется чтобы 
        // затопленные плитки имели цвет отличный от градаций серого, можно добавить цветной пиксель
        GrayRgbBmpArray grba = new GrayRgbBmpArray("C:\\temp\\test.bmp", "C:\\temp\\output.bmp");
        // считываем исходную картинку в массив
        grba.readToArray();
        // расчет, остаточный уровень океана может быть от 0 до 255, максимальный уровень подъема при наводнении от 0 до инта
        // если нужно затопить весь отсров уровень должен быть больше 255
        // можно устанавливать равные, тогда получим вид острова затопленного до определенной высоты
        // если собрать последовательно сверху такие срезы, то можно сделать гифку отлива))
        grba.outputArray = Island.Calculate(grba.imageInByte, 1, 260);
        // выводим результат в файл, цвет для затопленных плиток берется от пикселя исходной картинки с координатами (0,0)
        // можно указать любую другую координату для цветного пикселя в исходном файле
        grba.writeToFile(0, 0);


...
Рейтинг: 0 / 0
25 сообщений из 421, страница 12 из 17
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Задачка про остров
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]