web-dev-qa-db-ja.com

平面上の4つの点が長方形を形成しているかどうかを確認するには

4ポイント(関数への引数)が四角形を形成する場合にtrueを返し、それ以外の場合にfalseを返す関数(好きなようにポイントを表す)の記述方法をCスタイルの疑似コードで誰かに教えてもらえますか?

私は最初に等しいx値を持つ2つの異なる点のペアを見つけようとし、次にy軸に対してこれを行うソリューションを考え出しました。しかし、コードはかなり長いです。他の人が思いつくものを知りたいだけです。

55
pete
  • 角点の重心を見つける:cx =(x1 + x2 + x3 + x4)/ 4、cy =(y1 + y2 + y3 + y4)/ 4
  • 重心から四隅すべてまでの距離の二乗が等しいかどうかをテストします
bool isRectangle(double x1, double y1,
                 double x2, double y2,
                 double x3, double y3,
                 double x4, double y4)
{
  double cx,cy;
  double dd1,dd2,dd3,dd4;

  cx=(x1+x2+x3+x4)/4;
  cy=(y1+y2+y3+y4)/4;

  dd1=sqr(cx-x1)+sqr(cy-y1);
  dd2=sqr(cx-x2)+sqr(cy-y2);
  dd3=sqr(cx-x3)+sqr(cy-y3);
  dd4=sqr(cx-x4)+sqr(cy-y4);
  return dd1==dd2 && dd1==dd3 && dd1==dd4;
}

(もちろん、実際には、2つの浮動小数点数aとbが等しいかどうかのテストは、有限の精度で行う必要があります。例:abs(a-b)<1E-6)

59
Curd
struct point
{
    int x, y;
}

// tests if angle abc is a right angle
int IsOrthogonal(point a, point b, point c)
{
    return (b.x - a.x) * (b.x - c.x) + (b.y - a.y) * (b.y - c.y) == 0;
}

int IsRectangle(point a, point b, point c, point d)
{
    return
        IsOrthogonal(a, b, c) &&
        IsOrthogonal(b, c, d) &&
        IsOrthogonal(c, d, a);
}

順序が事前にわからない場合は、もう少し複雑なチェックが必要です。

int IsRectangleAnyOrder(point a, point b, point c, point d)
{
    return IsRectangle(a, b, c, d) ||
           IsRectangle(b, c, a, d) ||
           IsRectangle(c, a, b, d);
}
39
Vlad
  • 四辺形を変換して、その頂点の1つが原点に来るようにします
  • 残りの3つの点は、原点からの3つのベクトルを形成します
  • それらの1つは対角線を表す必要があります
  • 他の2つは側面を表す必要があります
  • 平行四辺形の規則 によって、辺が対角線を形成する場合、平行四辺形ができます。
  • 側面が直角を形成する場合、それは直角の平行四辺形です
  • 平行四辺形の反対の角度は等しい
  • 平行四辺形の連続した角度は補足です
  • したがって、すべての角度は直角です
  • それは長方形です
  • ただし、コードの方がはるかに簡潔です:-)

    static bool IsRectangle(
       int x1, int y1, int x2, int y2, 
       int x3, int y3, int x4, int y4)
    {
        x2 -= x1; x3 -= x1; x4 -= x1; y2 -= y1; y3 -= y1; y4 -= y1;
        return
            (x2 + x3 == x4 && y2 + y3 == y4 && x2 * x3 == -y2 * y3) ||
            (x2 + x4 == x3 && y2 + y4 == y3 && x2 * x4 == -y2 * y4) ||
            (x3 + x4 == x2 && y3 + y4 == y2 && x3 * x4 == -y3 * y4);
    }
    
  • (浮動小数点値で動作させる場合は、ヘッダーのint宣言を盲目的に置換しないでください。これは悪い習慣です。浮動小数点の結果を比較するときは、常にエラーの上限を使用して作業する必要があります。

5
Andras Vass

1つのポイントから他の3つのポイントまでの距離は直角三角形を形成する必要があります。

 |// | 
 |// | 
 |// | 
 |/___ /___|
d1 = sqrt( (x2-x1)^2 + (y2-y1)^2 ) 
d2 = sqrt( (x3-x1)^2 + (y3-y1)^2 ) 
d3 = sqrt( (x4-x1)^2 + (y4-y1)^2 ) 
if d1^2 == d2^2 + d3^2 then it's a rectangle

簡素化:

d1 = (x2-x1)^2 + (y2-y1)^2
d2 = (x3-x1)^2 + (y3-y1)^2
d3 = (x4-x1)^2 + (y4-y1)^2
if d1 == d2+d3 or d2 == d1+d3 or d3 == d1+d2 then return true
4
1. Find all possible distances between given 4 points. (we will have 6 distances)
2. XOR all distances found in step #1
3. If the result after XORing is 0 then given 4 points are definitely vertices of a square or a rectangle otherwise, return false (given 4 points do not form a rectangle).
4. Now, to differentiate between square and rectangle 
   a. Find the largest distance out of 4 distances found in step #1. 
   b. Check if the largest distance / Math.sqrt (2) is equal to any other distance.
   c. If answer is No, then given four points form a rectangle otherwise they form a square.

ここでは、rectangle/squareおよびBit Magicの幾何学的プロパティを使用しています。

プレイ中の長方形のプロパティ

  1. 長方形の反対側と対角線の長さは同じです。
  2. 長方形の対角線の長さがその長さのsqrt(2)倍である場合、長方形は正方形です。

ビットマジック

  1. 等しい値の数値のXORは0を返します。

四角形の4つの角の間の距離は常に3つのペアを形成します。1つは対角線用、もう1つは長さが異なる各辺用です。すべての値のXORを実行すると、四角形に対して0が返されます。

3
vineet kapoor

ポイントがA、B、C、Dで、順序がわかっている場合は、ベクトルを計算します。

x = B-A、y = C-B、z = D-Cおよびw = A-D

次に、内積(x dot y)、(y dot z)、(z dot w)、および(w dot x)を取ります。それらがすべてゼロの場合は、長方形になります。

3
Axel Gneiting

傾きが2である場合、2つの星形の直線は垂直であることがわかります。これは、平面が指定されているため、3つの連続する直線の傾きを求め、それらを乗算して、実際に垂直かどうかを確認するためです。ラインL1、L2、L3があるとします。 L1がL2に垂直で、L2がL3に垂直である場合、それは長方形であり、m(L1)* m(L2)=-1およびm(L2)* m(L3)=-1の勾配になります。長方形であることを意味します。コードは次のとおりです

bool isRectangle(double x1,double y1,
        double x2,double y2,
        double x3,double y3,
        double x4,double y4){
    double m1,m2,m3;
    m1 = (y2-y1)/(x2-x1);
    m2 = (y2-y3)/(x2-x3);
    m3 = (y4-y3)/(x4-x3);

    if((m1*m2)==-1 && (m2*m3)==-1)
        return true;
    else
        return false;
}
1
manugupt1

内積の提案をさらに一歩進めて、点の3つの点によって作成された2つのベクトルが垂直であるかどうかを確認し、xとyが4番目の点と一致するかどうかを確認します。

ポイントがある場合[Ax、Ay] [Bx、By] [Cx、Cy] [Dx、Dy]

ベクトルv = B-Aベクトルu = C-A

v(dot)u/|v||u| == cos(theta)

したがって(v.u == 0)の場合、直角の線が2つあります。

私は実際にはCプログラミングを知らないが、ここにいくつかの「メタ」プログラミングがあります:P

if (v==[0,0] || u==[0,0] || u==v || D==A) {not a rectangle, not even a quadrilateral}

var dot = (v1*u1 + v2*u2); //computes the "top half" of (v.u/|v||u|)
if (dot == 0) { //potentially a rectangle if true

    if (Dy==By && Dx==Cx){
     is a rectangle
    }

    else if (Dx==Bx && Dy==Cy){
     is a rectangle
    }
}
else {not a rectangle}

これには平方根はなく、ゼロで除算する可能性はありません。以前の投稿でこれらの問題について言及している人に気づいたので、別の方法を提供すると思いました。

したがって、計算上、vとuを取得するには4つの減算、2つの乗算、1つの加算が必要であり、1〜7の等式のどこかをチェックする必要があります。

多分私はこれを作っているかもしれませんが、減算と乗算が「より速い」計算であることをどこかで読んだことを漠然と覚えています。変数/配列の宣言とその値の設定も非常に速いと思いますか?

申し訳ありませんが、私はこの種のものに非常に新しいので、私は今書いたものへのいくつかのフィードバックが大好きです。

編集:以下の私のコメントに基づいてこれを試してください:

A = [a1,a2];
B = [b1,b2];
C = [c1,c2];
D = [d1,d2];

u = (b1-a1,b2-a2);
v = (c1-a1,c2-a2);

if ( u==0 || v==0 || A==D || u==v)
    {!rectangle} // get the obvious out of the way

var dot = u1*v1 + u2*v2;
var pgram = [a1+u1+v1,a2+u2+v2]
if (dot == 0 && pgram == D) {rectangle} // will be true 50% of the time if rectangle
else if (pgram == D) {
    w = [d1-a1,d2-a2];

    if (w1*u1 + w2*u2 == 0) {rectangle} //25% chance
    else if (w1*v1 + w2*v2 == 0) {rectangle} //25% chance

    else {!rectangle}
}
else {!rectangle}
1
David Meister

私は最近、同様の課題に直面しましたが、Pythonでは、これがPythonで思いついたものです。おそらく、この方法は価値があるかもしれません。アイデアは6本の線があり、セットに作成された場合、長さ、幅、対角線の3つの一意の線の距離が残っている必要があるということです。

def con_rec(a,b,c,d): 
        d1 = a.distanceFromPoint(b)
        d2 = b.distanceFromPoint(c)
        d3 = c.distanceFromPoint(d)
        d4 = d.distanceFromPoint(a)
        d5 = d.distanceFromPoint(b)
        d6 = a.distanceFromPoint(c)
        lst = [d1,d2,d3,d4,d5,d6] # list of all combinations 
        of point to point distances
        if min(lst) * math.sqrt(2) == max(lst): # this confirms a square, not a rectangle
            return False
        z = set(lst) # set of unique values in ck
        if len(lst) == 3: # there should be three values, length, width, diagonal, if a 
        4th, it's not a rectangle
            return True
        else: # not a rectangle
            return False
0
Mike M.

これは、軸に沿った長方形のテスト用の私のアルゴリズム提案ですが、Pythonでの提案です。

アイデアは、最初のポイントをピボットとして取得し、他のすべてのポイントは同じ幅と高さに適合している必要があり、(1、2)などの場合を考慮して、セットを介してすべてのポイントが異なることを確認します、(1、2)、(10、30)、(10、30)。

from collections import namedtuple

Point = namedtuple('Point', ('x', 'y'))

def is_rectangle(p1, p2, p3, p4) -> bool:
    width = None
    height = None

    # All must be distinct
    if (len(set((p1, p2, p3, p4))) < 4):
        return False

    pivot = p1

    for point in (p2, p3, p4):
        candidate_width = point.x - pivot.x
        candidate_height = point.y - pivot.y

        if (candidate_width != 0):
            if (width is None):
                width = candidate_width
            Elif (width != candidate_width):
                return False

        if (candidate_height != 0):
            if (height is None):
                height = candidate_height
            Elif (height != candidate_height):
                return False

    return width is not None and height is not None

# Some Examples
print(is_rectangle(Point(10, 50), Point(20, 50), Point(10, 40), Point(20, 40)))
print(is_rectangle(Point(100, 50), Point(20, 50), Point(10, 40), Point(20, 40)))
print(is_rectangle(Point(10, 10), Point(20, 50), Point(10, 40), Point(20, 40)))
print(is_rectangle(Point(10, 30), Point(20, 30), Point(10, 30), Point(20, 30)))
print(is_rectangle(Point(10, 30), Point(10, 30), Point(10, 30), Point(10, 30)))
print(is_rectangle(Point(1, 2), Point(10, 30), Point(1, 2), Point(10, 30)))
print(is_rectangle(Point(10, 50), Point(80, 50), Point(10, 40), Point(80, 40)))
0
Pedro Lopes

これらの4点を確認するにはどうすればよいですか平行四辺形を作成まず、存在するかどうかを確認1つの直角
1。 平行四辺形の検証

_input 4 points A, B, C, D;_

if(A, B, C, D are the same points), exit;// not a rectangle;

else form 3 vectors, AB, AC, AD, verify(AB=AC+AD || AC=AB+AD || AD=AB+AC), \\if one of them satisfied, this is a parallelogram;

2 .直角を検証

_through the last step, we could find which two points are the adjacent points of A;_

_We need to find out if angle A is a right angle, if it is, then rectangle._

バグがあるかどうかは知りませんでした。ある場合はそれを理解してください。

0
bob wong