記事ディレクトリ
1凸包の問題
簡単に言えば、平面上の点のセットが与えられた場合、すべての点を含む最小の凸多角形を見つけることは凸包の問題です。
凸包_Baidu百科事典(baidu.com)は、凸包を次のように説明しています。
凸包は計算幾何学(グラフィックス)の概念です。
実数ベクトル空間Vでは、与えられた集合Xに対して、Xを含むすべての凸集合の共通部分SはXの凸包と呼ばれます。Xの凸包は、Xのすべての点(X1、... Xn)の凸結合によって構築できます。
2次元のユークリッド空間では、凸包はすべての点を囲む輪ゴムとして想像できます。
大まかに言えば、2次元平面上の点のセットが与えられた場合、凸包は、セット内のすべての点を含むことができる最も外側の点を接続することによって形成される凸多角形です。
凸包に関するいくつかのブログ:
2コードの実装
点のセットの2D凸包を計算し、凸包の点座標を出力します。
下の図に示すように、緑の点は凸包の点、赤の点は凸包の内側の点、紫の線は凸包の輪郭です。
2.1配列配列で凸包点を抽出する
コード:
#include <iostream>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/convex_hull_2.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::Point_2 Point_2;
int main()
{
//定义二维点数组,并赋初值
Point_2 points[10] = {
Point_2(1,1),Point_2(2,5), Point_2(3,2),Point_2(4,1), Point_2(5,5),Point_2(5,7),Point_2(6,3),Point_2(7,5), Point_2(8,2), Point_2(10,4) };
//定义凸包点数组,用于接收提取的凸包点
Point_2 result[10];
//执行凸包提取
Point_2 *ptr = CGAL::convex_hull_2(points, points + 10, result);
//输出凸包点
std::cout << ptr - result << " 个凸包点:" << std::endl;
for (int i = 0; i < ptr - result; i++) {
std::cout << result[i] << std::endl;
}
return 0;
}
出力結果:
6 个凸包点:
1 1
4 1
8 2
10 4
5 7
2 5
凸包関数convex_hull_2
の説明:
convex_hull_2(ForwardIterator first, ForwardIterator last,
OutputIterator result )
{
return convex_hull_points_2(first, last, result);
}
凸包関数convex_hull_2
は3つの引数を受け入れます。最初の2つは入力パラメーターでありpoints
、それぞれ入力配列の開始ポインターと終了ポインターです。3番目のパラメーターは出力パラメーターでありresult
、結果配列の開始ポインターです。ptr
この関数は、 Receiveによって、最後に書き込まれた凸包ポイント(下の画像の破線のボックスで表されます)の直後に、結果配列にポインターを返します。したがって、ポインターの差ptr-result
は、凸包上にあるポイントの数を示します。
2.2ベクトルで凸包点を抽出する
以下では、配列の代わりにSTL標準テンプレートライブラリのベクトルを使用して凸包を抽出します
コード:
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/convex_hull_2.h>
#include <vector>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::Point_2 Point_2;
typedef std::vector<Point_2> Points;
int main()
{
Points points; //输入向量
points.push_back(Point_2(1, 1));
points.push_back(Point_2(2, 5));
points.push_back(Point_2(3, 2));
points.push_back(Point_2(4, 1));
points.push_back(Point_2(5, 5));
points.push_back(Point_2(5, 7));
points.push_back(Point_2(6, 3));
points.push_back(Point_2(7, 5));
points.push_back(Point_2(8, 2));
points.push_back(Point_2(10, 4));
Points result; //凸包向量
CGAL::convex_hull_2(points.begin(), points.end(), std::back_inserter(result));
std::cout << result.size() << "个凸包点" << std::endl;
for (auto val : result)
{
std::cout << val << std::endl;
}
return 0;
}
出力結果:
6个凸包点
1 1
4 1
8 2
10 4
5 7
2 5
ArrayとVectorを使用すると、結果はどちらの方法でも同じですが、後者の方が簡潔です。