Suponha que eu tenha 4 pontos (são bidimensionais), que são diferentes um do outro, e quero saber se eles formam um quadrado. Como fazer isso? (deixe o processo o mais simples possível.)
Suponha que eu tenha 4 pontos (são bidimensionais), que são diferentes um do outro, e quero saber se eles formam um quadrado. Como fazer isso? (deixe o processo o mais simples possível.)
Respostas:
Supondo que seu quadrado possa ser girado em relação ao sistema de coordenadas que você possui, não se pode confiar na repetição dos valores X e Y em seus quatro pontos.
O que você pode fazer é calcular as distâncias entre cada um dos quatro pontos. Se você acha que o seguinte é verdadeiro, você tem um quadrado:
Existem dois pontos, digamos A e C, que estão à distância x um do outro, e dois outros pontos, digamos B e D, que também estão à distância x um do outro.
Cada ponto {A, B, C, D} está a uma distância igual dos dois pontos que não estão x afastados. ie: Se A está x longe de C, então ele estará z longe de B e D.
Aliás, a distância z terá que ser SQRT (( x ^ 2) / 2), mas você não precisa confirmar isso. Se as condições 1 e 2 forem verdadeiras, você terá um quadrado. NOTA: Algumas pessoas estão preocupadas com a ineficiência da raiz quadrada. Não disse que você deveria fazer esse cálculo, apenas disse que se o fizesse obteria um resultado previsível!
O mínimo de trabalho que você precisaria fazer seria escolher um ponto, digamos A e calcular a distância para cada um dos outros três pontos. Se você puder descobrir que A é x de um ponto e z de dois outros pontos, basta verificar esses dois outros pontos um contra o outro. Se eles também são x um do outro, então você tem um quadrado. ou seja:
Como AB = AD, verifique BD:
Só para ter certeza, você precisa verificar os outros lados: BC e CD.
Como AC = BD e AB = AD = BC = CD, esse é, portanto, um quadrado.
Ao longo do caminho, se você encontrar mais de duas distâncias distintas, a figura não poderá ser um quadrado, para que você possa parar de procurar.
Exemplo de trabalho de implementação
Eu criei um exemplo de trabalho no jsfiddle (veja aqui ). Na minha explicação do algoritmo, utilizo os pontos arbitrários A, B, C e D. Esses pontos arbitrários estão em uma determinada ordem, a fim de percorrer o exemplo. O algoritmo funciona mesmo que os pontos estejam em uma ordem diferente; no entanto, o exemplo não funciona necessariamente se esses pontos estiverem em uma ordem diferente.
Agradecemos a: meshuai, Blrfl, MSalters e Bart van Ingen Schenau pelos comentários úteis para melhorar esta resposta.
Escolha três dos quatro pontos.
Descubra se é um triângulo isósceles direito, verificando se um dos três vetores entre pontos é igual a outro girado em 90 graus.
Nesse caso, calcule o quarto ponto por adição de vetor e compare-o com o quarto ponto fornecido.
Observe que isso não requer raízes quadradas caras, nem mesmo multiplicação.
sqrt
menos que seja crucial! Você não precisa degradar cálculos inteiros para FP ... para não mencionar piorar a precisão do cálculo FP.
Eu acho que a solução mais fácil é a seguinte:
Primeiro, calcule o centro dos 4 pontos: center = (A + B + C + D)/4
Depois calcule o vetor A - center
. Deixe isso serv := (x,y)
Seja v2
o vetor v
girado em 90 graus:v2 := (-y, x)
Agora os outros pontos devem ser center - v
, center + v2
e center - v2
.
A vantagem desta solução é que você não precisa usar raízes quadradas.
Sinto muito, mas algumas respostas não se aplicam.
Para o caso, você mede 3 arestas (digamos AB, AC e AD) para descobrir que duas têm o mesmo tamanho (digamos AC e AD) e uma é maior (digamos AB). Então você mede o CD para ver se é do mesmo tamanho de AB e descobre que é. Em vez de um quadrado, você pode ter a figura abaixo, e isso a torna uma solução errada.
Depois, tente outra solução: meça todas as distâncias pelo menos uma vez: AB, AC, AD, BC, BD, CD. Então você descobre que 4 deles são iguais e os outros 2 também são iguais entre si. Mas você pode ter uma foto como abaixo:
Portanto, essas respostas não estão corretas, apesar dos altos votos que receberam.
Uma solução possível: se as duas medidas iguais não conectam o mesmo ponto. Portanto: se AB e CD são do mesmo comprimento, todas as outras combinações (AC, AD, BC, BD) também são iguais, você tem um quadrado. Se você tem o mesmo ponto de maior comprimento (AB e AC é o maior e todos os outros são iguais), você tem uma das imagens acima.
Deixe os quatro pontos terem vetores de coordenadas a, b, c, d.
Então vamos chamar suas diferenças w = (ad), x = (ba), y = (cb), z = (dc).
Então w é ortogonal a a se você pode criar w a partir de uma rotação de 90 graus. Matematicamente, a matriz de rotação de 90 graus no espaço 2 é ((0, -1), (1, 0)). Assim, a condição de w ser girado em 90 graus resulta em
(w_1 == -x_2 e w_2 == x_1)
Se isso for válido, será necessário verificar se w == -yex == -z ou
((w_1 == -y_1 e w_2 == -y_2) e (x_1 == -z_1 e x_2 == -z_2))
Se essas três relações se mantiverem, a, b, c, d formam um quadrado orientado.
Semelhante à resposta por starblue
Escolha três dos quatro pontos.
Procure um vértice em ângulo reto entre eles : Verificando se o produto escalar de qualquer um dos dois vetores é zero. Se não for encontrado, não é um quadrado.
Verifique se os vértices adjacentes a esse ângulo também estão em ângulo reto. Caso contrário, não é um quadrado.
Verifique se as diagonais são perpendiculares : se o produto escalar dos vetores entre o primeiro e o quarto vértice e os outros dois vértices (diagonais) for zero, será um quadrado.
Eu acho que você pode fazer isso com adição e subtração simples e encontrar min / max. Termos (corresponde ao diagrama de outras pessoas):
Se 4 pontos compartilham apenas 2 x valores e 2 y, você tem um quadrado nivelado.
Caso contrário, você terá um quadrado se seus pontos satisfizerem o seguinte:
Explicação: Os segmentos de linha AC e BD devem se encontrar em seus pontos médios. Assim (Ax + Cx) / 2 é o ponto médio da CA e (Bx + Dx) / 2 é o ponto médio do BD. Multiplique cada lado desta equação por 2 para obter minha primeira equação. A segunda equação é a mesma para os valores Y. As formas em losango (romboides) satisfarão essas propriedades, portanto, é necessário verificar se você possui lados iguais - se a largura é igual à altura. Essa é a terceira equação.
Existem algumas boas respostas aqui, mas a pergunta foi feita pela abordagem mais simples. Pensei nisso rapidamente e é assim que eu faria.
Você pode dizer se quatro pontos representam um quadrado (mesmo que rotacionado), mas encontrando a média dos quatro pontos.
R = (A+B+C+D)/4
Depois de obter a média, a distância entre cada ponto e a média teria que ser a mesma para todos os quatro pontos.
if(dist(R,A) == dist(R,B) == dist(R,C) == dist(R,D) then
print "Is Square"
else
print "Is Not Square"
EDITAR:
Meu erro. Isso indicaria apenas se os pontos do formulário estavam em um círculo. Se você também verificar a distância entre os pontos, deve ser um quadrado.
if(dist(R,A) == dist(R,B) == dist(R,C) == dist(R,D) AND
(dist(A,B) == dist(B,C) == dist(C,D) == dist(A,D) then
print "Is Square"
else
print "Is Not Square"
Isso pressupõe que os pontos A, B, C, D não cruzam (como em uma ordem de enrolamento válida).
isso não é uma resposta de acordo com os padrões estabelecidos, mas espero que ajude:
[Copiado do link abaixo para que você não precise abrir o link] Python 76 caracteres
def S(A):c=sum(A)/4.0;return set(A)==set((A[0]-c)*1j**i+c for i in range(4))
A função S recebe uma lista de números complexos como entrada (A). Se conhecermos o centro e o canto de um quadrado, podemos reconstruí-lo girando o canto 90.180 e 270 graus em torno do ponto central (c). No plano complexo, a rotação de 90 graus sobre a origem é feita multiplicando o ponto por i. Se a nossa forma original e o quadrado reconstruído tiverem os mesmos pontos, deve ter sido um quadrado.
Isto foi retirado de: Determine se 4 pontos formam um quadrado
Se você gosta da resposta, digo, dedique alguns momentos para agradecer à pessoa ou vote sua resposta nessa página.
Ideia básica (isso responde à questão de saber se eu estava contribuindo com algo novo, o que foi perguntado pelo bot quando eu cliquei para fornecer uma resposta):
Minha solução em R é apresentada abaixo. Estou assumindo que existem exatamente quatro pontos e que, pela declaração do problema, já foi determinado que os pontos são únicos.
sumsq <- function(x) sum(x^2)
quadrances.xy <- function(xy) vapply(
as.data.frame(t(diff(xy)), optional=T), sumsq, 1)
Veja os trabalhos de Norman Wildberger, especialmente seus vídeos no YouTube ( peixes reais, números reais, empregos reais e segs.) E seu livro Divine Proportions para uma discussão sobre "quadrance".
xy
refere-se a um tipo de matriz da aceite por R plot
, points
e lines
funções.
A aplicação de as.data.frame
é um truque para fazer com que R faça as coisas em colunas.
A optional=T
cláusula elimina nomes que, de qualquer maneira, não são usados.
quadrances.xy..i2. <- function(xy, i2) vapply(
as.data.frame(i2, optional=T),
function(k) quadrances.xy(m[k,]),
1)
Essa é uma função para calcular as quadraturas entre os pontos especificados, onde pares de pontos são especificados pelo i2
argumento. O i2
símbolo refere-se a uma matriz de índice que possui uma coluna por índice e 2 elementos por coluna (o mesmo tipo de matriz retornado pela combn
função).
quadrance.every.xy <- function(xy, .which=combn(nrow(xy), 2))
quadrances.xy..i2.(xy, .which)
O .which
argumento é apresentado como um argumento apenas para expô-lo formals
e tentar comunicar o que está acontecendo.
is.square.xy <- function(xy) {
qq <- sort(quadrance.every.xy(xy))
all(qq[2:4] == qq[1]) && # ALL SIDES (SHORT QUADRANCES) EQUAL
qq[5] == qq[6] # ALL DIAGONALS (LONG QUADRANCES) EQUAL
}
Eu disse que "simples" não incluía funções de múltiplas linhas. Você terá que desculpar esta função de duas linhas.
xy <- t(matrix(c(3,0, 7,3, 4,7, 0,4), ncol=4))
xy
# [,1] [,2]
# [1,] 3 0
# [2,] 7 3
# [3,] 4 7
# [4,] 0 4
is.square.xy(xy)
# [1] TRUE
Observe que as quatro primeiras funções são úteis por si só, além da pergunta sobre os quatro pontos.
Suponha quatro pontos A = (ax, ay), B = (bx, by), C = (cx, cy), D = (dx, dy) e eles formam os pontos de um quadrado em ordem anti-horária. Movemos os pontos para que A esteja em (0, 0) subtraindo ax de bx, cx e dx e subtraindo ay de by, cy e dy, definindo ax = ay = 0.
Se os pontos são exatamente os cantos de um quadrado em ordem anti-horária, então, dados A e B, podemos calcular onde C e D estão: Deveríamos ter (cx, cy) = (bx - por, bx + por) e (dx, dy) = (-por, bx). Portanto, calculamos a distância ao quadrado de onde C e D estão, para onde devem estar: errC = (cx - bx + by) ^ 2 + (cy - bx - by) ^ 2 e errD = (dx + by) ^ 2 + (dy - bx) ^ 2. Nós os adicionamos e dividimos por (bx ^ 2 + por ^ 2), dando err = (errC + errD) / (bx ^ 2 + por ^ 2).
O erro resultante seria 0 se um quadrado perfeito, ou um número pequeno se quase um quadrado, e o número permaneceria inalterado, exceto por erros de arredondamento, se convertermos, escalarmos ou girarmos os pontos do quadrado. Assim, podemos usar o erro para decidir o quão bom temos um quadrado.
Mas não sabemos a ordem dos pontos. B e D devem estar à mesma distância de A; se multiplicarmos isso pela raiz quadrada de 2, essa deve ser a distância de A a C. Usamos isso para descobrir qual ponto é C: Calcular distB = bx ^ 2 + por ^ 2, distD = dx ^ 2 + dy ^ 2 Se distD ≥ 1,5 distB, então trocamos C e D; se distB ≥ 1,5 distD, então trocamos C e B. Agora C está certo.
Também podemos descobrir quais pontos são B e D: se adivinhamos errado qual deles é B e qual é D, então nosso cálculo coloca D no lugar completamente errado, exatamente o oposto de onde ele está. Portanto, se errD ≥ (bx ^ 2 + por ^ 2), então trocamos B e D.
Isso organizará B, C e D corretamente se tivermos um quadrado de fato ou pelo menos aproximadamente um quadrado. Mas se não temos nem um quadrado, sabemos que o cálculo do erro no final mostrará isso.
Resumo:
Se soubermos a ordem dos pontos, isso pode obviamente ser simplificado.
A solução é semelhante à mídia pensante.
Primeiro passo:
x = (A+B+C+D)/4
f=0
if(dist(x,A) == dist(x,B) == dist(x,C) == dist(x,D)
f=1
else
f=0
Esta propriedade é seguida por quadrado porque é cíclica. agora um círculo para seguir essa propriedade. então agora verifique
if(A.B==B.C==C.D==D.A==0)
f=1
else
f=0
if (f==1)
square
else
not square
Aqui AB significa produto escalar de A e B