長方形交差問題(Rectangular Intersection)
1.概要
平面走査法とヒープ探索木(priority search
trees)を組み合わせて、交差する長方形のペアを列挙する。
◆機能
水平線分と垂直線分を辺とする長方形を対象とする。
長方形Ri=[x1:x2]×[y1:y2]の集合Rを蓄えて、交差する長方形のペア(Ri,Rj)を全て求める。
ついでに、交差する長方形のグループを求める。
長方形R1,R2が同じグループであるのは、交差ペア(Ri,Rj)を枝とする無向グラフで
R1からR2に至るパスが存在することである。
◆理論性能(交差長方形のペアを列挙)
・メモリ : N
・時 間 : N(logN)+K
N:長方形の数。K:交差する長方形のペア数。
◆機能
水平線分と垂直線分を辺とする長方形を対象とする。
長方形Ri=[x1:x2]×[y1:y2]の集合Rを蓄えて、交差する長方形のペア(Ri,Rj)を全て求める。
ついでに、交差する長方形のグループを求める。
長方形R1,R2が同じグループであるのは、交差ペア(Ri,Rj)を枝とする無向グラフで
R1からR2に至るパスが存在することである。
◆理論性能(交差長方形のペアを列挙)
・メモリ : N
・時 間 : N(logN)+K
N:長方形の数。K:交差する長方形のペア数。
2.長方形のペアを列挙するアルゴリズム(Algorithm of rectangular intersection)
入力:長方形Ri=[x1:x2]×[y1:y2]の集合Rとする。
全ての長方形の左辺のX座標x1を昇順に並べた列をSとする。
垂直線分[y1:y2]の集合Dを空にする。(走査線上の長方形の垂直線分の集合)
右のX座標x2のヒープHを空にする。(走査線上の長方形の右辺の集合)
S内の最小のX座標aを垂直な走査線とする。
ヒープHからx2<aの長方形Riを削除すると共に、集合Dからも削除する。
列Sを参照してaを左座標とする全ての長方形Riに対して、
Riの垂直線分[y1,y2]と交差するD内の線分[y3,y4]に対して、
線分[y3,y4]に対応する長方形Rjとのペア(Ri,Rj)を交差ペアとする。
Riの垂直線分[y1,y2]をDに追加する。
Riの右辺の座標x2をHに追加する
aより次に大きいS内のX座標を新たにaとして、上記を繰り返す。
Sが空になったら終了する。
集合Dをヒープ探索木で構成することで、線分の追加/削除をO(logM)の手間で、
質問線分と交差する線分をO(logM+K)の手間で計算できる。
MはD内の線分数、Kは交差する線分数である。
全ての長方形の左辺のX座標x1を昇順に並べた列をSとする。
垂直線分[y1:y2]の集合Dを空にする。(走査線上の長方形の垂直線分の集合)
右のX座標x2のヒープHを空にする。(走査線上の長方形の右辺の集合)
S内の最小のX座標aを垂直な走査線とする。
ヒープHからx2<aの長方形Riを削除すると共に、集合Dからも削除する。
列Sを参照してaを左座標とする全ての長方形Riに対して、
Riの垂直線分[y1,y2]と交差するD内の線分[y3,y4]に対して、
線分[y3,y4]に対応する長方形Rjとのペア(Ri,Rj)を交差ペアとする。
Riの垂直線分[y1,y2]をDに追加する。
Riの右辺の座標x2をHに追加する
aより次に大きいS内のX座標を新たにaとして、上記を繰り返す。
Sが空になったら終了する。
集合Dをヒープ探索木で構成することで、線分の追加/削除をO(logM)の手間で、
質問線分と交差する線分をO(logM+K)の手間で計算できる。
MはD内の線分数、Kは交差する線分数である。
3.交差する長方形のグループを求めるアルゴリズム
ペアを列挙するアルゴリズムにおいて、交差する長方形のペア(Ri,Rj)が得られたところで、
Ri,Rjが属するグループをユニオンファインド木を用いてマージする。
マージの手間は、グループの大きさにほぼ無関係で定数時間である。
長方形番号の小さい順に調べて、ユニオンファインド木にグループ番号を設定する。
単独のユニオンファインド木には、グループ番号0を設定する。
単独でないユニオンファインド木には、1から始まる連番をグループ番号として設定する。
すべての長方形に、それが属するユニオンファインド木の番号を設定する。
なお、交差ペア(Ri,Rj)を得る必要が無く、グループ化するだけならば、O(NlogN)の
アルゴリズムが報告されている。
Ri,Rjが属するグループをユニオンファインド木を用いてマージする。
マージの手間は、グループの大きさにほぼ無関係で定数時間である。
長方形番号の小さい順に調べて、ユニオンファインド木にグループ番号を設定する。
単独のユニオンファインド木には、グループ番号0を設定する。
単独でないユニオンファインド木には、1から始まる連番をグループ番号として設定する。
すべての長方形に、それが属するユニオンファインド木の番号を設定する。
なお、交差ペア(Ri,Rj)を得る必要が無く、グループ化するだけならば、O(NlogN)の
アルゴリズムが報告されている。
4.測定性能
長方形数 (N) | グループ | ペア数 (K) | 計算時間 N(logN) + K |
10 | 0 | 0 | 0.00 |
32 | 1 | 60 | 0.00 |
100 | 3 | 166 | 0.16 |
316 | 163 | 1797 | 0.47 |
1000 | 142 | 224 | 1.40 |
3162 | 168 | 200 | 4.17 |
10000 | 203 | 208 | 14.10 |
31623 | 201 | 201 | 52.00 |
100000 | 202 | 202 | 172.00 |
実行時間の単位は1msでclock()関数の戻り値だが、分解能は1msの精度ではない。
長方形集合は左下座標を[0, 2**31)、辺の長さを[0, 20*(2**31-1)/N)区間の一様乱数で生成している。
◆測定環境
Endeavor MT8000
OS | WindowsXP |
CPU | Pentium4 650(3.4GHz) |
メモリ | 3GB(PC3200) |
測定日 | 2012年 7月 |
5.使用例
◆ダウンロード(ダウンロードのページからもダウンロードできます)
sample03.zip 421 KB (432,085 バイト) ソース付き
5.1 インストール
ダウンロードしたファイルを、任意のディレクトリに解凍します。
5.2 アンインストール
インストール時に作成したディレクトリごとファイルを削除します。
5.3 使用例
#include
#include "rectPairDLL.h"
Rect ri[] = { //x1, x2, y1, y2 サンプル長方形
{ 12, 21, 55, 60, 0},
{ 15, 26, 17, 18, 0},
{ 9, 22, 11, 13, 0},
{ 10, 23, 14, 42, 0},
{ 8, 35, 17, 30, 0},
{ 31, 39, 16, 19, 0},
{ 12, 19, 15, 25, 0},
{ 24, 41, 6, 9, 0},
{ 16, 29, 59, 70, 0},
{-20, -6,-30,-10, 0},
{-15, 10,-20, 0, 0}
};
void sample1()
{
int g_num, a_num, p_num, i, n, list[ sizeof(ri)/sizeof(ri[0]) ];
n = sizeof(ri)/sizeof(ri[0]);
//交差する長方形のペアとグループ数を求める
g_num = rectPairs_20161231(ri, n, 0); //2016/12/31まで使用可能です。
printf("グループ数 = %d(孤立の長方形はグループから除外)\n", g_num);
// i 番目(0始まり)の長方形と交差する長方形の個数と番号を取得する
i = 1;
a_num = rectAdjacentLlist(list, i, 0);
printf(" %d 番目の長方形と交差する長方形の数 = %d\n", i, a_num);
if( a_num > 0 ) {
printf(" %d 番目の長方形と交差する長方形の番号\n", i);
for( i = 0; i < a_num; ++i ) printf(" %d\n", list[i]);
}
//交差した長方形のペア数を取得する
p_num = rectOvlpNum();
printf("長方形のペア数 = %d\n", p_num);
//使用した領域を開放する
rectPairFree ();
return;
}
5.4 実行結果
グループ数 = 3(孤立の長方形はグループから除外)
1 番目の長方形と交差する長方形の数 = 3
1 番目の長方形と交差する長方形の番号
4
6
3
長方形のペア数 = 9
sample03.zip 421 KB (432,085 バイト) ソース付き
5.1 インストール
ダウンロードしたファイルを、任意のディレクトリに解凍します。
5.2 アンインストール
インストール時に作成したディレクトリごとファイルを削除します。
5.3 使用例
#include
#include "rectPairDLL.h"
Rect ri[] = { //x1, x2, y1, y2 サンプル長方形
{ 12, 21, 55, 60, 0},
{ 15, 26, 17, 18, 0},
{ 9, 22, 11, 13, 0},
{ 10, 23, 14, 42, 0},
{ 8, 35, 17, 30, 0},
{ 31, 39, 16, 19, 0},
{ 12, 19, 15, 25, 0},
{ 24, 41, 6, 9, 0},
{ 16, 29, 59, 70, 0},
{-20, -6,-30,-10, 0},
{-15, 10,-20, 0, 0}
};
void sample1()
{
int g_num, a_num, p_num, i, n, list[ sizeof(ri)/sizeof(ri[0]) ];
n = sizeof(ri)/sizeof(ri[0]);
//交差する長方形のペアとグループ数を求める
g_num = rectPairs_20161231(ri, n, 0); //2016/12/31まで使用可能です。
printf("グループ数 = %d(孤立の長方形はグループから除外)\n", g_num);
// i 番目(0始まり)の長方形と交差する長方形の個数と番号を取得する
i = 1;
a_num = rectAdjacentLlist(list, i, 0);
printf(" %d 番目の長方形と交差する長方形の数 = %d\n", i, a_num);
if( a_num > 0 ) {
printf(" %d 番目の長方形と交差する長方形の番号\n", i);
for( i = 0; i < a_num; ++i ) printf(" %d\n", list[i]);
}
//交差した長方形のペア数を取得する
p_num = rectOvlpNum();
printf("長方形のペア数 = %d\n", p_num);
//使用した領域を開放する
rectPairFree ();
return;
}
5.4 実行結果
グループ数 = 3(孤立の長方形はグループから除外)
1 番目の長方形と交差する長方形の数 = 3
1 番目の長方形と交差する長方形の番号
4
6
3
長方形のペア数 = 9
6.開発環境
Visual Studio 2005 C++