Como puede ver en la figura, la pregunta es:
¿Cómo encontrar el rectángulo de área mínima (MAR) ajustado en los puntos dados?
y una pregunta de apoyo es:
¿Hay alguna solución analítica para el problema?
(Un desarrollo de la pregunta será ajustar un cuadro (3D) a un grupo de puntos en una nube de puntos 3D).
Como primera etapa, propongo encontrar el casco convexo para los puntos que reforma el problema (eliminando esos puntos que no están involucrados en la solución) para: ajustar un MAR a un polígono. El método requerido proporcionará X ( centro del rectángulo ), D ( dos dimensiones ) y A ( ángulo ).
Mi propuesta de solución:
- Encuentre el centroide del polígono (vea ¿ Encontrar el centro de geometría del objeto? )
- [S] Ajustar un rectángulo ajustado simple, es decir, paralelo a los ejes X e Y
- puede usar la
minmax
función para X e Y de los puntos dados (por ejemplo, vértices de polígonos)
- puede usar la
- Almacene el área del rectángulo ajustado
- Gire el polígono sobre el centroide por ejemplo, 1 grado
- Repita desde [S] hasta completar una rotación completa
- Informe el ángulo del área mínima como resultado
Me parece prometedor, sin embargo, existen los siguientes problemas:
- elegir una buena resolución para el cambio de ángulo podría ser un desafío,
- el costo de cálculo es alto,
- La solución no es analítica sino experimental.
Para complementar la gran solución de @ julien, aquí hay una implementación funcional
R
que podría servir como pseudocódigo para guiar cualquier implementación específica de SIG (o aplicarse directamenteR
, por supuesto). La entrada es una matriz de coordenadas de puntos. La salida (el valor dembr
) es una matriz de los vértices del rectángulo límite mínimo (con el primero repetido para cerrarlo). Tenga en cuenta la ausencia total de cualquier cálculo trigonométrico.Aquí hay un ejemplo de su uso:
El tiempo está limitado por la velocidad del algoritmo de casco convexo, porque el número de vértices en el casco es casi siempre mucho menor que el total. La mayoría de los algoritmos de casco convexo son asintóticamente O (n * log (n)) para n puntos: puede calcular casi tan rápido como puede leer las coordenadas.
fuente
Acabo de implementar esto yo mismo y publiqué mi respuesta en StackOverflow , pero pensé que soltaría mi versión aquí para que otros la vean:
Aquí hay cuatro ejemplos diferentes de esto en acción. Para cada ejemplo, generé 4 puntos aleatorios y encontré el cuadro delimitador.
También es relativamente rápido para estas muestras en 4 puntos:
fuente
points = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
, y la salidaarray([[1.00000000e+00, 6.12323400e-17], [0.00000000e+00, 0.00000000e+00], [6.12323400e-17, 1.00000000e+00], [1.00000000e+00, 1.00000000e+00]])
es el cuadrado de la unidad (incluidos algunos errores de redondeo de coma flotante). Nota: un cuadrado es solo un rectángulo con lados iguales, así que supongo que si puede manejar un cuadrado, se generaliza a todos los rectángulos.Hay una herramienta en Whitebox GAT ( http://www.uoguelph.ca/~hydrogeo/Whitebox/ ) llamada Minimum Bounding Box para resolver este problema exacto. También hay una herramienta mínima de casco convexo allí también. Varias de las herramientas en la caja de herramientas Forma de parche, por ejemplo, orientación y alargamiento de parche, se basan en encontrar el cuadro de límite mínimo.
fuente
Encontré este hilo mientras buscaba una solución de Python para un rectángulo delimitador de área mínima.
Aquí está mi implementación , para la cual los resultados fueron verificados con Matlab.
El código de prueba se incluye para polígonos simples, y lo estoy usando para encontrar el cuadro de límite mínimo 2D y las direcciones de los ejes para un PointCloud 3D.
fuente
Gracias la respuesta de @ whuber. Es una gran solución, pero lenta para grandes nubes de puntos. Encontré que la
convhulln
función en el paquete Rgeometry
es mucho más rápida (138 s frente a 0.03 s para 200000 puntos). Pegué mis códigos aquí para que cualquiera sea interesante para una solución más rápida.Dos métodos obtienen la misma respuesta (ejemplo para 2000 puntos):
fuente
Simplemente recomiendo la función incorporada de OpenCV
minAreaRect
, que encuentra un rectángulo girado del área mínima que encierra el conjunto de puntos 2D de entrada. Para ver cómo usar esta función, puede consultar este tutorial .fuente