各辺の左(右)にある点は三角形の内側にあります。テスト対象の点と三角形の頂点の1つと三角形の辺にある3つのベクトルのいずれかのクロスベクトル積(実際にはその1つの要素)を計算することができます(すべてクロック単位またはすべて反時計方向に)。すべての3の計算されたコンポーネントが同じ符号を持つかどうかを確認します(3つすべて負または3つすべて正)。これは、ポイントが入っていることを教えてくれるでしょう。速く、精度を問題なく、少なくとも、整数をタスクに使用する場合は問題ありません。
三角形のいずれかの辺が間違っていることがわかると、すべての点の計算を停止することがあります。 Cで
サンプルコード:
#include <stdio.h>
#define SCREEN_HEIGHT 22
#define SCREEN_WIDTH 78
// Simulated frame buffer
char Screen[SCREEN_HEIGHT][SCREEN_WIDTH];
void SetPixel(int x, int y, char color)
{
if ((x < 0) || (x >= SCREEN_WIDTH) ||
(y < 0) || (y >= SCREEN_HEIGHT))
return;
Screen[y][x] = color;
}
void Visualize(void)
{
int x, y;
for (y = 0; y < SCREEN_HEIGHT; y++)
{
for (x = 0; x < SCREEN_WIDTH; x++)
printf("%c", Screen[y][x]);
printf("\n");
}
}
typedef struct
{
int x, y;
} Point2D;
int main(void)
{
// triangle vertices
Point2D vx0 = { SCREEN_WIDTH/2, SCREEN_HEIGHT/7 };
Point2D vx1 = { SCREEN_WIDTH * 6/7, SCREEN_HEIGHT * 2/3 };
Point2D vx2 = { SCREEN_WIDTH/7, SCREEN_HEIGHT * 6/7 };
// vectors lying on triangle sides
Point2D v0, v1, v2;
// current point coordinates
int x, y;
// calculate side vectors
v0.x = vx1.x - vx0.x;
v0.y = vx1.y - vx0.y;
v1.x = vx2.x - vx1.x;
v1.y = vx2.y - vx1.y;
v2.x = vx0.x - vx2.x;
v2.y = vx0.y - vx2.y;
// process all points
for (y = 0; y < SCREEN_HEIGHT; y++)
for (x = 0; x < SCREEN_WIDTH; x++)
{
int z1 = (x - vx0.x) * v0.y - (y - vx0.y) * v0.x;
int z2 = (x - vx1.x) * v1.y - (y - vx1.y) * v1.x;
int z3 = (x - vx2.x) * v2.y - (y - vx2.y) * v2.x;
if ((z1 * z2 > 0) && (z1 * z3 > 0))
SetPixel(x, y, '+'); // point is to the right (left) of all vectors
else
SetPixel(x, y, '-');
}
// draw triangle vertices
SetPixel(vx0.x, vx0.y, '0');
SetPixel(vx1.x, vx1.y, '1');
SetPixel(vx2.x, vx2.y, '2');
// visualize the result
Visualize();
return 0;
}
出力(ideone):
------------------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------
---------------------------------------0--------------------------------------
--------------------------------------++++------------------------------------
------------------------------------++++++++----------------------------------
----------------------------------+++++++++++++-------------------------------
--------------------------------+++++++++++++++++-----------------------------
------------------------------++++++++++++++++++++++--------------------------
----------------------------++++++++++++++++++++++++++------------------------
--------------------------+++++++++++++++++++++++++++++++---------------------
-------------------------++++++++++++++++++++++++++++++++++-------------------
-----------------------+++++++++++++++++++++++++++++++++++++++----------------
---------------------+++++++++++++++++++++++++++++++++++++++++++--------------
-------------------+++++++++++++++++++++++++++++++++++++++++++++++1-----------
-----------------++++++++++++++++++++++++++++++++++++-------------------------
---------------++++++++++++++++++++++++---------------------------------------
-------------++++++++++++-----------------------------------------------------
-----------2------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------
念頭に置くべき明らかなアプローチは、境界ボックスを計算し、その座標に基づいて最初にスクリーンすることです。 –
あなたのカウント機能を投稿すると、人々がアルゴリズムを超えて提供できる他の最適化の罠があるかもしれません。 –
あなたの時間制約は何ですか?ミリ秒ですか?秒?それが秒であれば、アレクセイ・フランツェの答えを使って線形検索を行うだけです。ミリ秒またはサブミリ秒の場合、いくつかの空間分割ツリー、たとえばクワッドツリーの使用を検討してください。 – JPvdMerwe