web-dev-qa-db-ja.com

点が三角形の内側にあるかどうかを判別

プログラムは3つの座標の値を読み取る必要があります

  • P1(x1、y1)
  • P2(x2、y2)
  • P3(x3、y3)

同様に別の座標P(x、y)と、この点が上の3点から形成される三角形の内側にあるかどうかを判断します。

39
KevinKZ

これを行う適切な方法は、三角形の3つのポイントを指定して、4番目のポイントの 重心座標 を計算することです。それらを計算する公式は、セクション「重心座標への変換」の最後に記載されていますが、ここでは、数学にあまり詳しくない説明を提供したいと考えています。

簡単にするために、値pointおよびxを持つ構造体yがあると仮定します。ポイントを次のように定義しました。

point p1(x1, y1);
point p2(x2, y2);
point p3(x3, y3);

point p(x,y); // <-- You are checking if this point lies in the triangle.

現在、重心座標は、一般にalphabeta、およびgammaと呼ばれ、次のように計算されます。

float alpha = ((p2.y - p3.y)*(p.x - p3.x) + (p3.x - p2.x)*(p.y - p3.y)) /
        ((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
float beta = ((p3.y - p1.y)*(p.x - p3.x) + (p1.x - p3.x)*(p.y - p3.y)) /
       ((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
float gamma = 1.0f - alpha - beta;

alphabeta、およびgammaのすべてが0より大きい場合、_pポイントは、p1p2、およびp3で構成される三角形内にあります。

この背後にある説明は、三角形内のポイントは、三角形のポイントと3つの係数(各ポイントに1つ、[0,1]の範囲内)を使用して記述できるということです。

p = (alpha)*p1 + (beta)*p2 + (gamma)*p3

この関数を再配置すると、重心座標を計算するための式が得られますが、そのための手順は問題の範囲を超えているように感じます。それらは、私が上にリンクしたウィキペディアのページで提供されています。

ポイントpが3つのポイントによって記述される領域内にあるためには、各係数が0より大きくなければなりません。

56
kevintodisco

P1、P2、およびP3の代わりに、ポイントをA、B、およびCと仮定します。

          A(10,30)
            / \
           /   \
          /     \
         /   P   \      P'
        /         \
B (0,0) ----------- C(20,0) 

アルゴリズム:

1) Calculate area of the given triangle, i.e., area of the triangle ABC in the above diagram. 

    Area A = [ x1(y2 - y3) + x2(y3 - y1) + x3(y1-y2)]/2

2) Calculate area of the triangle PAB. We can use the same formula for this. Let this area be A1.
3) Calculate area of the triangle PBC. Let this area be A2.
4) Calculate area of the triangle PAC. Let this area be A3.
5) If P lies inside the triangle, then A1 + A2 + A3 must be equal to A.

以下にCのプログラムを示します。

#include <stdio.h>
#include <stdlib.h>

/* A utility function to calculate area of triangle formed by (x1, y1), 
   (x2, y2) and (x3, y3) */
float area(int x1, int y1, int x2, int y2, int x3, int y3)
{
   return abs((x1*(y2-y3) + x2*(y3-y1)+ x3*(y1-y2))/2.0);
}

/* A function to check whether point P(x, y) lies inside the triangle formed 
   by A(x1, y1), B(x2, y2) and C(x3, y3) */
bool isInside(int x1, int y1, int x2, int y2, int x3, int y3, int x, int y)
{   
   /* Calculate area of triangle ABC */
   float A = area (x1, y1, x2, y2, x3, y3);

   /* Calculate area of triangle PBC */  
   float A1 = area (x, y, x2, y2, x3, y3);

   /* Calculate area of triangle PAC */  
   float A2 = area (x1, y1, x, y, x3, y3);

   /* Calculate area of triangle PAB */   
   float A3 = area (x1, y1, x2, y2, x, y);

   /* Check if sum of A1, A2 and A3 is same as A */
   return (A == A1 + A2 + A3);
}

/* Driver program to test above function */
int main()
{
   /* Let us check whether the point P(10, 15) lies inside the triangle 
      formed by A(0, 0), B(20, 0) and C(10, 30) */
   if (isInside(0, 0, 20, 0, 10, 30, 10, 15))
     printf ("Inside");
   else
     printf ("Not Inside");

   return 0;
}

時間: O(1)

スペース: O(1)

14
Jerky

与えられた3つのポイントの平均を取ります。この新しいポイントP4は常に三角形の内側にあります。

次に、PとP4が3行それぞれの同じ側にあるかどうかを確認しますP1P2P2P3およびP3P1。これを行うには、外積の兆候を確認します(P -> P1) x (P -> P2)および(P4 -> P1) x (P4 -> P2)(P-> P1はPからP1へのベクトル)、次に他の2つのペア。

5
irrelephant