Предположим, что соседние страны имеют общие вершины и ребра (если нет, проблема становится намного сложнее).
Для каждого региона пройдите полигоны, соответствующие странам региона, и создайте список вершин и ребер. Каждое ребро должно иметь указатели на две вершины, которые являются его конечными точками, а каждая вершина должна иметь указатели на ребра, конечной точкой которых она является.
Добавляя вершины в список, убедитесь, что они являются уникальными. Другими словами, если вы добавляете вершину с координатами (x,y)
, если такая точка уже есть в списке, не добавляйте новую. Это означает, что вам, возможно, придется проверять каждую новую вершину на соответствие тем, которые уже есть в списке. Вы можете ускорить это, разбив ограничивающий прямоугольник области, скажем, на n
x n
корзин, в которых вы можете хранить вершины. Когда приходит новая вершина, найдите ее корзину и сравните ее с другими вершинами в этой корзине.
Когда вы добавляете ребра в список ребер, делайте то же самое - если ребро (v0, v1) добавляется, проверьте, существует ли существующее ребро (v0, v1) или (v1, v0). За исключением этого случая, удалите существующее ребро из списка и не добавляйте новое ребро. Это потому, что эти два края «взаимно отменяют» друг друга - они из соседних стран. И не забудьте исключить указатели ребер в списке вершин, которые соответствуют удаленному ребру.
Когда вы это сделаете, у вас должен быть список ребер, которые не разделены между двумя странами. Это края, которые формируют границу региона. Вы также должны иметь список вершин, некоторые из которых указывают на два ребра, а другие указывают на отсутствие ребер. Прежние вершины находятся на границе области.
Теперь выберите ребро из списка ребер и удалите его (и удалите соответствующие указатели ребер из вершин, которые являются его конечными точками) из списка ребер. Перейдите к одной из конечных точек вершины, и она будет указывать на другой край. Таким образом, вы будете идти от края к краю вдоль границы региона. Добавьте эти ребра в ваш regionShape, удалив их из списка ребер. В конце концов вы вернетесь к конечной точке вашего первого ребра, и у вас будет замкнутый цикл.
Если в списке ребер остались какие-либо ребра, запустите процесс еще раз, чтобы извлечь еще один контур границы, и продолжайте, пока все петли границы не будут извлечены и список ребер не будет пустым.
Я упомянул одну оптимизацию, которая заключается в пространственном расположении вершин в бункеры, чтобы вы могли быстрее проверить их равенство. Другая оптимизация заключается в том, чтобы избежать физического удаления ребер из списков, а просто пометить их как «удаленные».