web-dev-qa-db-ja.com

4点が正方形を形成しているかどうかを確認する方法は?

互いに異なる4つのポイント(2次元)があり、それらが正方形を形成しているかどうかを知りたいと仮定します。どうやってするの? (プロセスはできるだけ単純にします。)

35
MarshalSHI

配置した座標系に対して正方形が回転する可能性があると仮定すると、4点でX値とY値の繰り返しがあるとは限りません。

あなたができることは、4つのポイントのそれぞれの間の距離を計算することです。次のことが当てはまる場合、正方形があります。

  1. 互いに距離xであるAとCの2つのポイントと、距離xでもあるBとDの2つのポイントがあります。 互いに。

  2. 各ポイント{A、B、C、D}は、x離れていない2つのポイントから等しい距離です。つまり、AがCからx離れている場合、BとDの両方からz離れます。

ちなみに、距離zはSQRT((x^ 2)/ 2)である必要がありますが、必要はありませんこれを確認します。条件1と2が真の場合、正方形になります。 注:一部の人々は平方根の非効率性を心配しています。あなたがこの計算をするべきだとは言わなかったが、あなたがそうすれば予測可能な結果が得られるだろうと私は言った!

Illustration of Square Rules

必要な最低限の作業は、Aと言う点を選択して、他の3つの点それぞれまでの距離を計算することです。 Aが1つの点からxであり、他の2つの点からzであることがわかった場合は、これら2つを確認するだけです。互いに他のポイント。それらも互いにxである場合、正方形になります。例:

  • AB =z
  • AC =x
  • AD =z

AB = ADなので、BDを確認します。

  • BD =x

念のため、反対側のBCとCDを確認する必要があります。

  • BC =z
  • CD =z

AC = BDであり、AB = AD = BC = CDなので、これは正方形になります。

途中で、3つ以上の異なるエッジ距離が見つかった場合、図は正方形になることができないので、見るのをやめることができます。


実用的な実装例

私はjsfiddleで動作する例を作成しました( ここ を参照)。アルゴリズムの説明では、任意の点A、B、C、およびDを使用します。例を説明するために、これらの任意の点は特定の順序になっています。 algorithmは、ポイントの順序が異なっていても機能しますが、の例これらのポイントの順序が異なる場合、必ずしも機能するとは限りません。


ありがとうございました:meshuai、Bllfl、MSalters、およびBart van Ingen Schenauは、この回答を改善するのに役立つコメントを提供してくれました。

65
Joel Brown

4点のうち3点をピックします。

ポイント間の3つのベクトルのいずれかが90度回転した別のベクトルと等しいかどうかをチェックして、それが二等辺三角形であるかどうかを確認します。

もしそうなら、ベクトル加算によって4番目の点を計算し、それを与えられた4番目の点と比較します。

これは、乗算でさえ、高価な平方根を必要としないことに注意してください。

24
starblue

私は最も簡単な解決策は次のとおりだと思います:

  • まず、4つのポイントの中心を計算します。center = (A + B + C + D)/4

  • 次に、ベクトル_A - center_を計算します。これをv := (x,y)とします

  • _v2_を90度回転したベクトルvとします:v2 := (-y, x)

  • これで、他のポイントは_center - v_、_center + v2_および_center - v2_になります。

このソリューションの利点は、平方根をまったく使用する必要がないことです。

17
Elian Ebbing

申し訳ありませんが、一部の回答は当てはまりません。

3つのエッジ(AB、AC、ADとしましょう)を測定して、2つのエッジが同じサイズ(ACとADとしましょう)で、1つのエッジが大きい(ABとしましょう)ことを確認した場合。次に、CDを測定してABと同じサイズであるかどうかを確認し、同じであることを確認します。正方形の代わりに、下の画像を使用することもできますが、これは間違った解決策になります。

Not a square...

次に、他の解決策を試します。AB、AC、AD、BC、BD、CDなど、すべての距離を少なくとも1回は測定します。次に、4つが等しいこと、他の2つも等しいことがわかります。ただし、次のような画像を使用できます。

And that's not a square, too...

したがって、彼らが受け取った高い賛成票にもかかわらず、それらの答えは正しくありません。

1つの可能な解決策:2つの等しいメジャーが同じポイントを接続しない場合。つまり、ABとCDが同じ長さであれば、他のすべての組み合わせ(AC、AD、BC、BD)も等しく、正方形になります。最大の長さを作る同じポイントがある場合(ABとACが最大で、他のすべてが等しい)、上の写真の1つを持っています。

5
woliveirajr

4つの点に座標ベクトルa、b、c、dがあるとします。

次に、それらの差をw =(a-d)、x =(b-a)、y =(c-b)、z =(d-c)と呼びます。

次に、90度の回転でaからwを作成できる場合、wはaに直交します。数学的には、2空間の90度回転行列は((0、-1)、(1、0))です。したがって、wが90度回転したaであるかどうかの条件は、

(w_1 == -x_2およびw_2 == x_1)

これが当てはまる場合は、w == -yおよびx == -zであることを確認する必要があります。

((w_1 == -y_1およびw_2 == -y_2)および(x_1 == -z_1およびx_2 == -z_2))

これら3つの関係が成り立つ場合、a、b、c、dは方向付けられた正方形を作成します。

3
Mark Salzer

簡単な足し算と引き算と最小/最大を見つけることでこれを行うことができると思います。用語(他の人の図と一致):

  • 最も高いy値を持つポイント=> A
  • 最も高いx => B
  • 最も低いy => C
  • 最低x => D

4つのポイントが2つのx値と2つのy値のみを共有する場合は、レベルの正方形になります。

それ以外の場合、ポイントが次の条件を満たす場合は正方形になります。

  • A.x + C.x = B.x + D.x
  • A.y + C.y = B.y + D.y
  • A.y-C.y = B.x-D.x

説明:線分A-CとB-Dはそれらの中間点で交わる必要があります。したがって、(A.x + C.x)/ 2はA-Cの中点であり、(B.x + D.x)/ 2はB-Dの中点です。この方程式の各辺に2を掛けて、最初の方程式を取得します。 2番目の方程式はY値についても同じです。菱形(菱形)はこれらの特性を満たすため、幅が高さと同じであることを確認する必要があります。これが3番目の方程式です。

2
GlenPeterson

starblueの回答に似ています

4つのポイントのうち3つを選択します。

それらの中で直角の頂点を探す:3つのベクトルのいずれか2つのドット積がゼロかどうかをチェックします。見つからない場合、正方形ではありません。

この角度に隣接する頂点も直角かどうかを確認します。そうでない場合、正方形ではありません。

対角線が垂直かどうかを確認:最初の4番目の頂点と他の2つの頂点(対角線)の間のベクトルのドット積がゼロの場合、その正方形です。

2
Max

enter image description here

ここにいくつかの良い答えがありますが、質問は最も簡単なアプローチを求めました。私はこれを少し考えました、そしてこれは私がそれをする方法です。

4つのポイントが(回転した場合でも)正方形を表しているかどうかはわかりますが、4つのポイントの平均がわかります。

R = (A+B+C+D)/4

平均が得られたら、各ポイントと平均の間の距離は、4つのポイントすべてで同じでなければなりません。

if(dist(R,A) == dist(R,B) == dist(R,C) == dist(R,D) then
   print "Is Square"
else
   print "Is Not Square"

編集:

私の間違い。フォームポイントが円上にあるかどうかだけがわかります。ポイント間の距離も確認する場合は、正方形である必要があります。

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"

これは、点A、B、C、Dが交差しないことを前提としています(有効な巻き順がある場合など)。

2
Reactgular

これは設定された基準による答えではありませんが、これが役立つことを願っています:

[下のリンクからコピーしたので、リンクを開く必要はありません] Python 76文字

def S(A):c=sum(A)/4.0;return set(A)==set((A[0]-c)*1j**i+c for i in range(4))

関数Sは、複素数のリストを入力として受け取ります(A)。正方形の中心と1つの角の両方がわかっている場合は、中心点を中心に角を90度、180度、および270度回転させることにより、正方形を再構築できます(c)。複雑な平面では、原点を中心とした90度の回転は、点にiを掛けることによって行われます。元の形状と再構成された正方形が同じ点を持っている場合、それは正方形であったに違いありません。

これは、以下から取得されました 4ポイントが正方形を形成するかどうかを決定する

答えが気に入ったら、少し時間を取ってその人に感謝するか、そのページで彼の答えに投票してください。

1
bad_keypoints

基本的なアイデア(これは、何かを提供するかどうかという質問に答えます。これは、クリックして回答を提供するときにボットから尋ねられました):

  • 対角線が等しい菱形は正方形です。
  • 「可能な限りシンプル」には以下が含まれます:
    • 分割なし、
    • 平方根なし、
    • 分岐なし、
    • 検索なし、
    • 角度チェックや追跡を行わない
    • ベクトルなし、
    • 変換なし、
    • 複素数はありません、
    • 複数行機能なし、および
    • 特別なパッケージのインポートなし(組み込みのもののみを使用)。
    • (そして帝国の絡み合いはありません!)

Rでの私の解決策を以下に示します。 正確に4つのポイントがあり、問題のステートメントごとに、ポイントが一意であると既に判断されていると想定しています。

sumsq <- function(x) sum(x^2)

quadrances.xy <- function(xy) vapply(
    as.data.frame(t(diff(xy)), optional=T), sumsq, 1)

ノーマンワイルドバーガーの作品、特に彼のYouTubeビデオ( 実際の魚、実数、実際の仕事 et seq。)と彼の本 Divine Proportions を参照して、「四分法」の説明を確認してください。 」

xyは、Rのplotpoints、およびlines関数によって受け入れられる一種の行列を指します。

の適用 as.data.frameは、Rに列単位で処理を行わせるためのトリックです。

optional=T句は、とにかく使用されていない名前を削除します。

quadrances.xy..i2. <- function(xy, i2) vapply(
    as.data.frame(i2, optional=T),
    function(k) quadrances.xy(m[k,]),
    1)

これは、指定されたポイント間の四分位を計算する関数です。ポイントのペアはi2引数。 i2シンボルは、インデックスごとに1つの列を持ち、列ごとに2要素を持つインデックス行列を指します(combn function)。

quadrance.every.xy <- function(xy, .which=combn(nrow(xy), 2))
        quadrances.xy..i2.(xy, .which)

.whichは、それをformalsに公開し、何が起こっているのかを伝えようとするための引数として提示されています。

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
}

「シンプル」にはマルチライン関数が含まれていないと私は言った。この2行の関数を言い訳にする必要があります。

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

最初の4つの関数は、4つの点に関する質問を除いて、それ自体で有用であることに注意してください。

0
Ana Nimbus

4つの点A =(ax、ay)、B =(bx、by)、C =(cx、cy)、D =(dx、dy)を想定し、それらは反時計回りの順序で正方形の点を形成します。 Aが(0、0)になるようにポイントを移動するには、bx、cx、およびdxからaxを減算し、by、cy、およびdyからayを減算して、ax = ay = 0を設定します。

点が反時計回りの順序で正方形の隅である場合、AとBを指定すると、CとDがどこにあるかを計算できます:(cx、cy)=(bx-by、bx + by)と(dx、dy)=(-by、bx)。したがって、CとDが存在する場所からそれらがあるべき場所までの距離の2乗を計算します。errC=(cx-bx + by)^ 2 +(cy-bx-by)^ 2、およびerrD =(dx + by)^ 2 +(dy-bx)^ 2。これらを追加し、(bx ^ 2 + by ^ 2)で除算すると、err =(errC + errD)/(bx ^ 2 + by ^ 2)が得られます。

完全な正方形の場合、結果のerrは0、ほぼ正方形の場合は小さい数になり、正方形のポイントを変換、スケーリング、または回転した場合の丸め誤差を除いて、数値は変化しません。したがって、errを使用して、正方形の大きさを判断できます。

しかし、ポイントの順序はわかりません。 BとDはAから同じ距離でなければなりません。これに2の平方根を掛けると、AからCまでの距離になります。これを使用して、Cである点を特定します。distB= bx ^ 2 + by ^ 2を計算します。distD= dx ^ 2 + dy ^ 2。 distD≥1.5 distBの場合、CとDを入れ替えます。 distB≥1.5 distDの場合、CとBを入れ替えます。Cは正しいです。

また、どの点がBとDであるかを判断することもできます。どちらがBでどれがDであるかを誤って推測した場合、計算ではDを完全に間違った場所に配置します。したがって、errD≥(bx ^ 2 + by ^ 2)の場合、BとDを入れ替えます。

これにより、B、C、Dが正しく配置されます。しかし、おおよその正方形さえない場合は、最後のエラー計算でこれが表示されることがわかります。

概要:

  1. Bx、cx、dxからaxを減算します。 by、cy、dyからayを引きます。
  2. DistB = bx ^ 2 + by ^ 2、distD = dx ^ 2 + dy ^ 2とします。
  3. DistD≥1.5 * distBの場合、CとDを入れ替えて、distDを再計算します。
  4. それ以外の場合、distB≥1.5 * distDの場合、BとCを入れ替えて、distBを再計算します。
  5. ErrD =(dx + by)^ 2 +(dy-bx)^ 2とします。
  6. ErrD≥distBの場合、BとDを交換し、distBとdistDを交換して、errDを再計算します。
  7. ErrC =(cx-bx + by)^ 2 +(cy-bx-by)^ 2とします。
  8. Err =(errC + errD)/ distBとします。
  9. Errの値に応じて、正方形があるかほぼ正方形かを決定します。

ポイントの順序がわかっている場合、これは明らかに簡略化できます。

0
gnasher729