Como você vê na figura, a pergunta é:
Como encontrar o retângulo de área mínima (MAR) ajustado nos pontos indicados?
e uma pergunta de apoio é:
Existe alguma solução analítica para o problema?
(O desenvolvimento da pergunta será ajustar uma caixa (3D) a um cluster de pontos em uma nuvem de pontos 3D.)
Como primeira etapa, proponho encontrar o casco convexo para os pontos que reformam o problema (removendo esses pontos não estão envolvidos na solução) para: ajustar uma MAR a um polígono. O método necessário fornecerá X ( centro do retângulo ), D ( duas dimensões ) e A ( ângulo ).
Minha proposta de solução:
- Encontre o centróide do polígono (consulte Localização do centro da geometria do objeto? )
- [S] Coloque um retângulo simples, isto é, paralelo aos eixos X e Y
- você pode usar a
minmax
função para X e Y dos pontos dados (por exemplo, vértices do polígono)
- você pode usar a
- Armazene a área do retângulo ajustado
- Gire o polígono em torno do centróide, por exemplo, 1 grau
- Repita de [S] até fazer uma rotação completa
- Relate o ângulo da área mínima como resultado
Parece-me promissor, no entanto, existem os seguintes problemas:
- escolher uma boa resolução para a mudança de ângulo pode ser desafiador,
- o custo da computação é alto,
- a solução não é analítica, mas experimental.
Para complementar a ótima solução da @ julien, aqui está uma implementação funcional
R
, que poderia servir como pseudocódigo para orientar qualquer implementação específica de GIS (ou ser aplicada diretamenteR
, é claro). A entrada é uma matriz de coordenadas de ponto. Saída (o valor dembr
) é uma matriz dos vértices do retângulo delimitador mínimo (com o primeiro repetido para fechá-lo). Observe a ausência completa de quaisquer cálculos trigonométricos.Aqui está um exemplo de seu uso:
O tempo é limitado pela velocidade do algoritmo convexo do casco, porque o número de vértices no casco é quase sempre muito menor que o total. A maioria dos algoritmos de casco convexo são assintoticamente O (n * log (n)) para n pontos: você pode calcular quase tão rápido quanto pode ler as coordenadas.
fonte
Acabei de implementar isso e postei minha resposta no StackOverflow , mas achei que deixaria minha versão aqui para que outras pessoas visualizassem:
Aqui estão quatro exemplos diferentes em ação. Para cada exemplo, gerei 4 pontos aleatórios e encontrei a caixa delimitadora.
Também é relativamente rápido para essas amostras em 4 pontos:
fonte
points = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
, e a saída éarray([[1.00000000e+00, 6.12323400e-17], [0.00000000e+00, 0.00000000e+00], [6.12323400e-17, 1.00000000e+00], [1.00000000e+00, 1.00000000e+00]])
qual é o próprio quadrado da unidade (incluindo alguns erros de arredondamento de ponto flutuante). Nota: um quadrado é apenas um retângulo com lados iguais, portanto, suponho que se ele pode manipular um quadrado, ele generaliza para todos os retângulos.Há uma ferramenta no Whitebox GAT ( http://www.uoguelph.ca/~hydrogeo/Whitebox/ ) chamada Caixa Limite Mínima para resolver esse problema exato. Também existe uma ferramenta mínima de casco convexo. Várias das ferramentas da caixa de ferramentas Patch Shape, por exemplo, orientação e alongamento do patch, são baseadas na localização da caixa delimitadora mínima.
fonte
Me deparei com esse segmento enquanto procurava uma solução Python para um retângulo delimitador de área mínima.
Aqui está minha implementação , para a qual os resultados foram verificados com o Matlab.
O código de teste está incluído para polígonos simples e eu estou usando-o para encontrar a caixa delimitadora 2D mínima e as direções dos eixos para um PointCloud 3D.
fonte
Obrigado @ resposta whuber. É uma ótima solução, mas lenta para grandes nuvens de pontos. Achei que a
convhulln
função no pacote Rgeometry
é muito mais rápida (138 s vs 0,03 s para 200000 pontos). Eu colei meus códigos aqui, pois qualquer um é interessante para uma solução mais rápida.Dois métodos obtêm a mesma resposta (exemplo para 2000 pontos):
fonte
Simplesmente recomendo a função interna do OpenCV
minAreaRect
, que encontra um retângulo girado da área mínima que envolve o conjunto de pontos 2D de entrada. Para ver como usar esta função, pode-se consultar este tutorial .fonte