Во-первых, спасибо пользователю @Lemonkingsman за идею для данного поста
Во-вторых, в посте будут рассчитаны только площади государств на основной карте, то есть здесь не будет Энканомии (так как у меня нет возможности перевести пиксели с карты в метры), Разлома (так как в принципе глупо считать площадь шахты, которая находится под землями государства-владельца) и Архипелага Золотого Яблока (возможно выпущу пост конкретно о нем чуть попозже, на данный момент я не закончил ивент с этой локацией и толком не разобрался с заменой островов)
В-третьих, приятного прочтения :)
Для самых нетерпеливых или тех, кто не хочет погружаться в математику, результаты всех расчетов в конце поста
Итак, перед тем как начинать расчеты, нужно определиться, что будет считаться территорией государства. В моем случае это (помимо суши) будут различные заливы, проливы и бухты, а также острова и в некоторых случаях прибрежные к островам воды. Это сделает расчеты несколько проще (вернее сделает их менее долгими и нудными для меня), ну и помимо этого, подобные объекты в реальности также считаются территорией страны. Также я не буду учитывать территориальные воды, так как будет довольно проблематично отмерять от берегов по 12 миль (страны на карте в GI довольно маленькие)
С понятием площади разобрались. Теперь, перед тем как перейти к работе с картой, определим площадь одного пикселя карты в квадратных метрах. Это нам понадобится позже, чтобы площадь из пикселей перевести в метры. Для этого я воспользуюсь уже имеющейся у себя меткой на карте, до которой мне известно расстояние из конкретной точки:
Черный отрезок - отрезок между меткой и указанной выше точкой
Сразу понятно, что площадь пикселя будет равна квадрату длины пикселя. Длину же пикселя можно вычислить как отношение длин данного отрезка в метрах и в пикселях (уж простите за такое количество слов пиксели). Через Paint находим координаты обеих точек (если быть точнее, то находим длину отрезка по оси Ox и по оси Oy, Paint это показывает сам) (сразу добавлю, что все операции с картой делались при максимальном удалении/масштабировании (то есть так, чтобы как можно больше территорий было видно)). И затем через теорему Пифагора находим искомую длину отрезка в пикселях, затем находим длину самого пикселя, а затем и его площадь:
Теперь можем полноценно перейти к карте
И в первую очередь нам нужно ту территорию, которую мы видим на карте превратить из просто изображения в какой-то контур, то есть аппроксимировать. Я это буду делать с помощью отрезков: так гораздо проще, да и погрешность будет незначительной. Попутно с рисованием отрезков записываем координаты каждой точки, в которой заканчиваются отрезки (так как контур замкнутый, то точка, в которой заканчивается один отрезок, будет началом другого отрезка)
Вот так получилось упростить карту у меня. Также можно заметить, что некоторые очень малые острова я обозначил окружностями. С ними будет и результат точнее, и расчеты проще. А еще как же я теперь ненавижу Инадзуму, на которую ушло больше всего времени, бумаги, и получилась она хуже всех
Итак, теперь у нас есть более-менее простые контуры, как определить их площадь? В первую очередь скорее всего приходит идея разбить контур на прямоугольники и прямоугольные треугольники и считать площадь так. Да, так можно сделать, но лично я не готов тратить часов 10 на разбиение всех этих контуров, да и решение получится каким-то слишком топорным. Поэтому я использую 2 козыря у себя в рукаве, первый из которых - это интеграл:
"Занимательная математика. Производные и интегралы. Манга" с.92
Второй же козырь - программирование
В совокупности можно получить довольно простую программу, которая по точкам посчитает площадь контура
Начнем с математических основ программы, то есть выведем в общем виде и линейную функцию, описывающую данный отрезок, и интеграл этой функции в пределах существования отрезка (функции)
Начнем естественно с самой линейной функции. Нам известны 2 точки, которые принадлежат отрезку, а значит можно составить систему уравнений, из которой можно найти коэффициенты k и b для уравнения функции y = k*x + b
Коэффициент b можно было бы выразить и через координаты точек, а не через k, но в случае с программой будет проще правильней последний вариант
Теперь перейдем к интегралу. Но перед этим тем, кто с интегрированием не знаком, советую ознакомиться с формулами и свойствами, которые будут использованы:
В качестве пределов интегрирования берем точки x1 и x2, а затем находим определенный интеграл:
Теперь определимся как будем считать площадь контура (хотя по нормальному это нужно было бы описать перед переходом к интегралам, но да ладно). Мы будем суммировать полученные интегралы, в результате чего получим число равное площади этого контура. В данном случае получится так, что интегралы "нижней" части контура будет больше искомой площади на некоторое число S, а интегралы "верхней" части контура как раз таки вычтут это S и мы получим то, что ищем. Правда есть небольшой нюанс, в зависимости он направления обхода контура (с правилами Кирхгофа это никак не связано :) ) Площадь получится либо положительной, либо отрицательной, однако для обоих случаев модули будут равны и друг другу, и искомой площади
Приступим к программированию
Подробное описание работы кода в конце поста
Программа работает довольно просто. Сначала вводим количество точек в контуре, затем вводим x-овые и y-овые координаты этих точек через Enter. Вот например площадь треугольника (как наиболее простой вариант), заодно показан нюанс с положительной и отрицательной площадью
Вершины треугольника имеют координаты (1; 3); (-3; -2); (3; -3)
Затем считаем количество точек в каждом контуре и вводим эти точки в программу (каждый контур отдельно). По итогу получим площади контуров в пикселях, что можем легко перевести в квадратные метры (так как контуров много, то суммируем площади контуров, относящихся к одному региону плюс прибавляем площади островов, обозначенных окружностями). А также в качестве дополнения (чтобы результаты расчетов не были таким скудными) я решил посчитать площади государств с учетом масштабирования игровой карты, о чем писал в своем прошлом посте (для получения масштабированной площади, нужно обычную умножить на квадрат масштаба: поскольку и длина, и ширина пикселя увеличатся в M раз, то площадь одного пикселя увеличится в M^2 раз, а так как от перемены мест сомножителей произведение не меняется, то и умножать можно площадь в кв. метрах, а не в пикселях)
В верхней таблице площади в пикселях, в квадратных метрах, а также площади при усредненном значении масштаба для каждого варианта расчета, в нижней таблице площади при каждом из значений масштаба (в кв. км).
Что делать с этой информацией - не знаю) Можно сравнивать страны по площади, можно считать сколько квадратных километров вы уже закрыли на 100% или на сколько процентов закрыт вообще весь мир)
Описание работы кода
В первую очередь мы видим классы Point и line, это классы для точек и отрезков соответственно. Сам по себе класс - по сути шаблон для какой-либо переменной (объекта).
В нашем случае у точек будут встроены поля (это как переменная, только встроенная в шаблон объекта), в которых содержится информация об их координатах. Также у точек будет метод, которым мы задаем значения этим точкам (public void ex(...){...})
У отрезков будут также 2 поля: коэффициенты k и b, а также 2 метода: первый через координаты точек, лежащих на отрезке, определяет значения полей (public void ex(...){...}), а второй находит интеграл отрезка (public double integrate(...){...}). Также в первый метод встроена защита от случаев, когда отрезок вертикален, то есть k = , когда такое происходит, метод зануляет оба поля (все отрезки считаются обособленно друг от друга, поэтому ошибки не возникает) (интегралы вертикального отрезка и отрезка, лежащего на оси Ox (то есть с нулевыми полями) равны 0)
Надеюсь более-менее понятно для тех кто не разбирается в программировании) Впрочем ладно, дальше будет проще
Третий класс Program содержит в себе саму программу (это такая особенность языка C#). Начиная с 31 строки: создаем переменную, которая отвечает за количество точек и вводим ее значение; создаем массив точек и переменные для ввода координат; пишем цикл, при помощи которого вводим все значения координат точек; создаем массив отрезков и переменную, обозначающую площадь контура; пишем цикл, в котором при помощи методов класса line находим значения полей и значение интеграла, последнее прибавляем к прежде созданной переменной; производим операции из цикла над последним отрезком (его нет в цикле, так как для него нужно обращаться к первой вершине контура и к последней вершине контура, что проще сделать вне цикла); выводим в консоль значение площади. Console.ReadKey() нужно чтобы после выполнения программы она сразу же не закрылась
На этом все. Надеюсь пост был познавательным, интересным и привлек внимание читателей к математике и программированию. Спасибо за внимание, и побольше всем закрытых на 100% квадратных километров карты :)