Итак, учитывая двумерный массив точек, как найти все многоугольники, в которых каждая точка координаты многоугольника (по диагонали примыкает) к следующей?
Например, это изображение:
Я заинтересован в затоплении области, ограниченной замкнутой цепочкой точек (каждая координата примыкает к следующей, образующей замкнутую петлю), относительно ее формы.Я не заинтересован в идентификации отдельных полигонов, а только в заполнении полигона.Каждая точка имеет метку (1, 2, 3, + и т. Д.), Где 0 не установлено. Так, например:
- Желтый - это квадрат, где центральная точка заполняется.
- Оранжевый квадрат больше, но углы прилегают друг к другу только по диагонали.
- Зеленый - это форма, в которой, если вы следуете цепочке точек, вы не всегда можете повернуть направо.
- Красный не являетсядопустимая форма, поскольку ее точечная цепь не закрыта.
- Синий не является допустимой формой, поскольку его точечная цепь не закрыта, ребро не закрывает ее.
Я смотрел навыпуклая оболочка, но это дает мне оболочку всех точек, которая меня не интересует.
Пара правил: - Каждая точка имеет значение от 1 до 10. - Область может быть заполнена, только если закрыто Pointchain имеет ту же самую метку.- Цепочки точек, которые не являются замкнутыми, не являются действительными регионами.- x / y координаты точек - целые числа.
Я реализую это в Java, и я попробовал это: https://github.com/Merowech/java-concave-hull/blob/master/ConcaveHull.java
Но с учетом карты, подобной этой:
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 1, 0, 1, 0, 1, 0, 2, 2, 0, 0, 0, 0, 2, 0
0, 1, 0, 0, 0, 1, 2, 0, 0, 2, 0, 0, 0, 0, 0
0, 0, 1, 0, 1, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0
0, 0, 0, 1, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 3, 3, 3, 0, 0, 3, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0
Это дает мне в качестве вывода:
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 1, 0, 0, 0, 1, 0, 2, 2, 0, 0, 0, 0, 2, 0
0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0
Я также попробовал DBSCAN, который в итоге не смог игнорировать маленькие кластеры рядом с большим кластером с той же меткой
Обновление:
Простая заливка не будет работать, поскольку необходимо, чтобы все окружающие пиксели многоугольника имели одинаковое значение:
public static void floodFill(int[][] map, int fill, Point loc) {
if (loc.x < 0 || loc.x >= map[0].length || loc.y < 0 || loc.y >= map.length) throw new IllegalArgumentException();
int old = map[loc.y][loc.x];
// Checks trivial case where loc is of the fill color
if (fill == old) return;
floodLoop(map, loc.x, loc.y, fill, old);
}
// Recursively fills surrounding pixels of the old color
private static void floodLoop(int[][] map, int x, int y, int fill, int old) {
int[] aux = {255, 255, 255, 255};
// finds the left side, filling along the way
int fillL = x;
do {
map[y][fillL] = fill;
fillL--;
} while (fillL >= 0 && map[y][fillL] == old);
fillL++;
// find the right right side, filling along the way
int fillR = x;
do {
map[y][fillR] = fill;
fillR++;
} while (fillR <= map[0].length - 1 && map[y][fillR] == old);
fillR--;
// checks if applicable up or down
for (int i = fillL; i <= fillR; i++) {
if (y > 0 && map[y-1][i] == old) floodLoop(map, i, y - 1,
fill, old);
if (y < map.length - 1 && map[y+1][i] == old) floodLoop(
map, i, y + 1, fill, old);
}
}
public static int[][] map = new int[][]
{
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 2, 2, 2, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0},
{0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 2, 0, 2, 0, 0, 3, 0, 0, 0, 0, 3, 0, 0, 3, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 3, 0, 0, 0, 3, 0, 3, 0, 3, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0, 3, 3, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 4, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 4, 0, 4, 0, 0, 0, 0, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
};
public static int[][] expected_result = new int[][]
{
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0},
{0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0},
{0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 2, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0},
{0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 2, 2, 2, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 3, 3, 3, 3, 3, 0, 3, 3, 3, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0, 3, 3, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 4, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 4, 0, 4, 0, 0, 0, 0, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
};
private static void printMap(int[][] map)
{
for (int y = 0; y < map.length; y++)
{
for (int x = 0; x < map[0].length; x++)
{
System.out.print(map[y][x] + " ,");
}
System.out.println();
}
}
public static void main(String[] args)
{
int[][] copy = map.clone();
floodFill(copy, 1, new Point(0,0));
printMap(copy);
}