Embalaje de polígonos dentro de un polígono con ArcGIS Desktop?


25

Tengo una trama booleana.

En las áreas grises del ráster, me gustaría ajustar un polígono de tamaño determinado dentro de una extensión contigua.

Básicamente, tengo un polígono irregular, y me gustaría "ajustar" un polígono conocido dentro de la extensión del polígono irregular tantas veces como sea posible.

La dirección del polígono no importa, y podría ser un cuadrado. Me gustaría que se ajustara gráficamente, pero si solo adjuntara un número al polígono (# que encaja) eso también funcionaría.

Estoy usando ArcGIS Desktop 10.


8
Este es un problema muy difícil. Se necesita mucho trabajo solo para ajustar tantos círculos en un cuadrado como sea posible, por ejemplo. Cuando el polígono original es complicado, como en la ilustración, necesita algunos procedimientos de optimización potentes. El mejor método que he encontrado para este problema es el recocido simulado, pero eso no estará disponible en ArcGIS y tomaría una secuencia de comandos extremadamente astuta para hacerlo (ArcGIS es demasiado lento). ¿Tal vez podría relajar un poco sus requisitos, como ajustar el polígono más pequeño una cantidad suficiente de veces, en lugar de tantas como sea posible?
whuber

1
@whuber Gracias por editar mi publicación. Sí, un número suficiente de veces funcionaría. O, ¿qué tal en una orientación de ángulo dado. ex. en la imagen de arriba, he ajustado el polígono tantas veces como pude en esa orientación, si los hubiera girado 90 grados, podría encajar uno más ...
Thad

1
Sí, pero también está lleno de trampas. Algunos son elementales. Por ejemplo, el texto publicado y publicado por ESRI, "Conociendo ArcView GIS" (para la versión 3) incluyó un ejercicio en el que un rectángulo que representa un campo de fútbol se colocó interactivamente dentro de un polígono. El problema era que la respuesta del ejercicio era incorrecta porque el autor no pudo proyectar los datos y los errores en el uso de coordenadas geográficas fueron lo suficientemente grandes como para afectar el resultado. La respuesta se veía bien en el SIG, pero si alguien hubiera intentado construir ese campo, habrían descubierto que no había suficiente espacio para ello :-).
whuber

66
@whuber Supongo que pensaron que una cifra de "parque de pelota" era suficiente.
Kirk Kuykendall

2
En el caso general de un polígono irregular dentro de un polígono irregular, este es un problema computacionalmente insoluble: encontrar una solución óptima no es un objetivo plausible en todos los casos, y es probable que sea NP completo desde una perspectiva técnica: qué casos no se pueden predeterminar. Si restringe el problema de manera significativa, es probable que algunos algoritmos de ajuste aleatorio iterativo le proporcionen números razonablemente altos . Creo que si esta es una tarea es que no están buscando la respuesta correcta , están buscando enfoques creativos.
MappingTomorrow

Respuestas:


22

Hay muchas formas de abordar este problema. El formato ráster de los datos sugiere un enfoque basado en ráster; Al revisar esos enfoques, una formulación del problema como un programa lineal de enteros binarios parece prometedora, porque está muy en el espíritu de muchos análisis de selección de sitios GIS y puede adaptarse fácilmente a ellos.

En esta formulación, enumeramos todas las posiciones y orientaciones posibles de los polígonos de relleno, a los que me referiré como "mosaicos". Asociado con cada mosaico hay una medida de su "bondad". El objetivo es encontrar una colección de mosaicos no superpuestos cuya bondad total sea lo más grande posible. Aquí, podemos tomar la bondad de cada mosaico como el área que cubre. (En entornos de decisión más sofisticados y ricos en datos, podemos calcular la bondad como una combinación de propiedades de las celdas incluidas dentro de cada mosaico, propiedades quizás relacionadas con la visibilidad, proximidad a otras cosas, etc.)

Las limitaciones de este problema son simplemente que no pueden superponerse dos mosaicos dentro de una solución.

Esto se puede enmarcar un poco más abstracta, de una manera favorable para computación eficiente, mediante la enumeración de las células en el polígono para ser llenado (la "región") 1, 2, ..., M . Cualquier ubicación de mosaico se puede codificar con un vector indicador de ceros y unos, dejando que los correspondientes a las celdas cubiertas por el mosaico y los ceros en otros lugares. En esta codificación, toda la información necesaria sobre una colección de mosaicos se puede encontrar sumando sus vectores indicadores (componente por componente, como de costumbre): la suma será distinta de cero exactamente donde al menos un mosaico cubre una celda y la suma será mayor de uno en cualquier lugar, dos o más fichas se superponen (La suma cuenta efectivamente la cantidad de superposición).

Una más pequeña abstracción: el conjunto de posibles colocaciones de baldosas en sí puede ser enumerado, por ejemplo 1, 2, ..., N . La selección de cualquier conjunto de ubicaciones de mosaicos en sí corresponde a un vector indicador donde los que designan los mosaicos que se colocarán.

Aquí hay una pequeña ilustración para arreglar las ideas . Se acompaña con el código de Mathematica utilizado para hacer los cálculos, de modo que la dificultad de programación (o falta de ella) puede ser evidente.

Primero, representamos una región para ser en mosaico:

region =  {{0, 0, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}};

Figura 1: región

Si numeramos sus celdas de izquierda a derecha, comenzando en la parte superior, el vector indicador para la región tiene 16 entradas:

Flatten[region]

{0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}

Usemos el siguiente mosaico, junto con todas las rotaciones por múltiplos de 90 grados:

tileSet = {{{1, 1}, {1, 0}}};

Figura 2: azulejo

Código para generar rotaciones (y reflexiones):

apply[s_List, alpha] := Reverse /@ s;
apply[s_List, beta] := Transpose[s];
apply[s_List, g_List] := Fold[apply, s, g];
group = FoldList[Append, {}, Riffle[ConstantArray[alpha, 4], beta]];
tiles = Union[Flatten[Outer[apply[#1, #2] &, tileSet, group, 1], 1]];

(Este cálculo algo opaco se explica en una respuesta en /math//a/159159 , que muestra que simplemente produce todas las rotaciones y reflexiones posibles de un mosaico y luego elimina cualquier resultado duplicado).

Supongamos que colocamos el mosaico como se muestra aquí:

Figura 3: colocación de azulejos

Las celdas 3, 6 y 7 están cubiertas en esta ubicación. Eso es designado por el vector indicador

{0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}

Si desplazamos este mosaico una columna a la derecha, ese vector indicador sería

{0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}

La combinación de tratar de colocar fichas en ambas posiciones simultáneamente está determinada por la suma de estos indicadores,

{0, 0, 1, 1, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0}

El 2 en la séptima posición muestra estas superposiciones en una celda (segunda fila hacia abajo, tercera columna desde la izquierda). Debido a que no queremos superposición, requeriremos que la suma de los vectores en cualquier solución válida no debe tener entradas superiores a 1.

Resulta que para este problema, 29 combinaciones de orientación y posición son posibles para los mosaicos. (Esto se encontró con una simple codificación que implica una búsqueda exhaustiva). Podemos representar las 29 posibilidades dibujando sus indicadores como vectores de columna . (El uso de columnas en lugar de filas es convencional). Aquí hay una imagen de la matriz resultante, que tendrá 16 filas (una para cada celda posible en el rectángulo) y 29 columnas:

makeAllTiles[tile_, {n_Integer, m_Integer}] := 
  With[{ m0 = Length[tile], n0 = Length[First[tile]]},
   Flatten[
    Table[ArrayPad[tile, {{i, m - m0 - i}, {j, n - n0 - j}}],  {i, 0, m - m0}, {j, 0, n - n0}], 1]];
allTiles = Flatten[ParallelMap[makeAllTiles[#, ImageDimensions[regionImage]] & , tiles], 1];
allTiles = Parallelize[
   Select[allTiles, (regionVector . Flatten[#]) >= (Plus @@ (Flatten[#])) &]];
options = Transpose[Flatten /@ allTiles];

Figura 4: matriz de opciones

(Los dos vectores indicadores anteriores aparecen como las dos primeras columnas a la izquierda). El lector de ojos agudos puede haber notado varias oportunidades para el procesamiento paralelo: estos cálculos pueden tomar unos segundos.

Todo lo anterior puede reiniciarse de manera compacta utilizando la notación matricial:

  • F es este conjunto de opciones, con M filas y N columnas.

  • X es el indicador de un conjunto de ubicaciones de baldosas, de longitud N .

  • b es un N- vector de unos.

  • R es el indicador de la región; Es un vector M.

La "bondad" total asociada con cualquier solución posible X , es igual a RFX , porque FX es el indicador de las celdas cubiertas por X y el producto con R suma estos valores. (Podríamos ponderar R si deseamos que las soluciones favorezcan o eviten ciertas áreas de la región). Esto debe ser maximizado. Porque podemos escribirlo como ( RF ). X , es una función lineal de X : esto es importante. (En el siguiente código, la variable ccontiene RF ).

Las restricciones son que

  1. Todos los elementos de X deben ser no negativos;

  2. Todos los elementos de X deben ser menores que 1 (que es la entrada correspondiente en b );

  3. Todos los elementos de X deben ser integrales.

Las restricciones (1) y (2) hacen de este un programa lineal , mientras que el tercer requisito lo convierte en un programa lineal entero .

Existen muchos paquetes para resolver programas lineales enteros expresados ​​exactamente de esta forma. Son capaces de manejar valores de M y N en decenas o incluso cientos de miles. Probablemente sea lo suficientemente bueno para algunas aplicaciones del mundo real.


Como nuestra primera ilustración, calculé una solución para el ejemplo anterior usando el comando de Mathematica 8 LinearProgramming. (Esto minimizará una función objetivo lineal. La minimización se convierte fácilmente en maximización al negar la función objetivo). Devolvió una solución (como una lista de mosaicos y sus posiciones) en 0.011 segundos:

b = ConstantArray[-1, Length[options]];
c = -Flatten[region].options;
lu = ConstantArray[{0, 1}, Length[First[options]]];
x = LinearProgramming[c, -options, b, lu, Integers, Tolerance -> 0.05];
If[! ListQ[x] || Max[options.x] > 1, x = {}];
solution = allTiles[[Select[x Range[Length[x]], # > 0 &]]];

Figura 5: solución

Las celdas grises no están en la región en absoluto; los glóbulos blancos no estaban cubiertos por esta solución.

Puede resolver (a mano) muchas otras inclinaciones que son tan buenas como esta, pero no puede encontrar ninguna mejor. Esa es una limitación potencial de este enfoque: le brinda una mejor solución, incluso cuando hay más de una. (Hay algunas soluciones: si reordenamos las columnas de X , el problema no cambia, pero el software a menudo elige una solución diferente como resultado. Sin embargo, este comportamiento es impredecible).

Como segunda ilustración , para ser más realistas, consideremos la región en la pregunta. Al importar la imagen y volver a muestrearla, la representé con una cuadrícula de 69 por 81:

Figura 6: Región

La región comprende 2156 celdas de esta cuadrícula.

Para hacer las cosas interesantes, y para ilustrar la generalidad de la configuración de la programación lineal, tratemos de abarcar la mayor parte posible de esta región con dos tipos de rectángulos:

Figura 7: azulejos

Uno mide 17 por 9 (153 celdas) y el otro mide 15 por 11 (165 celdas). Podríamos preferir usar el segundo, porque es más grande, pero el primero es más delgado y puede caber en lugares más estrechos. ¡Veamos!

El programa ahora involucra N = 5589 posibles ubicaciones de mosaicos. ¡Es bastante grande! Después de 6.3 segundos de cálculo, a Mathematica se le ocurrió esta solución de diez mosaicos:

Figura 8: solución

Debido a algo de la holgura ( .eg, podríamos mover el mosaico inferior izquierdo hasta cuatro columnas a su izquierda), obviamente hay algunas otras soluciones que difieren ligeramente de esta.


1
Una versión anterior de esta solución (pero no tan buena) aparece en el sitio de Mathematica en Mathica.stackexchange.com/a/6888 . También vale la pena señalar que se puede usar una variación menor de la formulación para resolver el problema de cubrir completamente la región con la menor cantidad de mosaicos posible (permitiendo algunas superposiciones, por supuesto): esto resolvería el "parche de baches" problema.
whuber

1
En interés del espacio, esta respuesta no describe algunas mejoras potencialmente útiles. Por ejemplo, después de encontrar todas las posiciones de mosaico posibles (como vectores indicadores), puede agregarlas todas para encontrar qué celdas pueden estar cubiertas por algún mosaico. El conjunto de tales celdas se divide en dos componentes conectados separados en el segundo ejemplo. Esto significa que el problema puede resolverse independientemente en los dos componentes, reduciendo sustancialmente su tamaño (y, por lo tanto, el tiempo de cálculo). Tales simplificaciones iniciales tienden a ser importantes para abordar problemas del mundo real.
whuber

Gran esfuerzo y respuesta. La respuesta de Chris también fue útil. ¡Gracias a todos por la ayuda! Funciona, y me hizo moverme en la dirección correcta nuevamente.
Thad

¡Guauu! Estaba interesado en un problema similar y esta publicación me dio una nueva perspectiva. Gracias. ¿Qué sucede si R es más grande (por ejemplo, 140x140120000), ¿hay alguna forma de reducir el costo de cálculo? ¿Conoces algún documento relacionado con este problema? Mis palabras clave de búsqueda no me conducen de la manera correcta (hasta ahora).
nimcap

@nimcap Esta es una clase importante de problemas, por lo que mucha investigación continúa. Las palabras clave para buscar comenzarían con un "programa lineal de enteros mixtos" y se ramificarían a partir de allí según lo que encuentre.
whuber

5

El enlace a Algoritmos genéticos para el embalaje de polígonos , que se proporciona en mi respuesta a una pregunta similar en el algoritmo de búsqueda para colocar el número máximo de puntos dentro del área restringida con un espaciado mínimo. , podría ser útil Parece que el método podría generalizarse para trabajar con formas de contenedor arbitrarias (y no solo rectángulos).


Ese documento tiene algunas buenas ideas (+1), pero todos sus algoritmos se centran, de manera fundamental, en empacar polígonos dentro de regiones rectangulares . Esto se debe a que representa empaques con una estructura de datos discreta (una secuencia de polígonos junto con sus orientaciones) que representa un conjunto de procedimientos en los que los polígonos se deslizan , paralelos a los lados del cuadrado, hacia una esquina designada. Parece que una codificación discreta tan simple sería menos efectiva para regiones más complicadas. Tal vez una simplificación inicial de las regiones en la cuadrícula ayudaría.
whuber

2

Para el subconjunto altamente restringido que mencionó (mosaico cuadrado / triangular en un bache), suponiendo las optimizaciones explícitas anteriores, este pseudocódigo debería llegar a una respuesta aproximada simplemente llevándolo a través de las posibilidades con una resolución bruta de alta resolución. No funcionará correctamente para situaciones en las que la rotación de mosaicos individuales puede ver ganancias, como mosaicos rectangulares o un contenedor altamente irregular. Esto es 1 millón de iteraciones, puede intentar más si es necesario.

Suponga un cuadrado con lados de longitud L

Cree un patrón de cuadros de tablero de ajedrez, que sea al menos de las dimensiones de la extensión del contenedor, más al menos 1L en cada dirección.

N = 0

DX = 0

DY = 0

DR = 0

Restablecer la posición del tablero de ajedrez al centroide original

Para (R = 1: 100)

Para (Y = 1: 100)

Para (X = 1: 100)

M = Contar el número de cuadrados completamente dentro del contenedor

Si (M> N)

DR = R

DY = Y

DX = X

N = M

Mueva el tablero de ajedrez hacia el este por L / 100

Restablecer tablero de ajedrez este

Mueva el tablero de ajedrez hacia el norte por L / 100

Restablecer tablero de ajedrez norte

Gire el tablero de ajedrez en 3.6 grados CW alrededor de su centroide

DY = DY * L

DX = DX * L

Restablecer el tablero de ajedrez a su posición original y rotación

Print DR & "," & DX & ", y" & DY & "son la matriz final de traducción / rotación"

Girar tablero de ajedrez por DR

Traducir tablero de damas por DX, DY

Seleccione cuadrados que estén completamente dentro del contenedor

Cuadrados de exportación


Si intenta este procedimiento en una región de 2 por 5 con una celda que falta en el medio de un borde largo, encontrará que solo puede colocar un cuadrado de 2 por 2 en él. Sin embargo, dos de esos cuadrados encajan fácilmente. El problema es que no son parte de un patrón regular de "tablero de ajedrez". Esta dificultad es una de las cosas que hace que este problema sea bastante difícil.
whuber

1
Sip. Si tiene una forma de contenedor lo suficientemente irregular que puede soportar múltiples patrones regulares no contiguos del orden de unas pocas celdas cada uno, esto termina muy lejos de ser óptimo. Agregar cosas como esa a la posibilidad de espacio aumenta el tiempo de procesamiento muy rápidamente y requiere un cierto grado de planificación para el caso particular al que se dirige.
MappingTomorrow
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.