개발/C++
[Boost Geometry] points -> polygon cluster
njsung
2022. 8. 10. 18:28
반응형
[개요]
DFS(Depth First Search)를 활용해 분포되어있는 boost point들을 boost polygon으로 클러스터화 하는 function
[결과]
[코드 원본]
//INCLUDE LIBRARY
#include <boost/geometry.hpp>
#include <iostream>
#include <vector>
#include <fstream>
//MAKE NAMESPACE
namespace bg = boost::geometry;
namespace bgi = boost::geometry::index;
//DEFINITION POINT, CLUSTER
typedef bg::model::point<double, 2, bg::cs::cartesian> point_t;
typedef std::vector<point_t> cluster_t;
//DIRECTION ARRAY
int dx[] = { -1,0,1,0 };
int dy[] = { 0,1,0,-1 };
void DFS(std::vector<point_t> points, std::vector<bool> &used, int index, cluster_t &cluster)
{
const auto& point = points.at(index);
for (int j = 0; j < points.size(); ++j)
{
if (index == j) continue;
if (used[j]) continue;
const auto& p = points.at(j);
double x2 = bg::get<0>(p);
double y2 = bg::get<1>(p);
if (boost::geometry::distance(point, p) == 1)
{
std::cout << j << " ";
cluster.emplace_back(p);
used[j] = true;
DFS(points, used, j, cluster);
}
}
}
int main()
{
std::vector<point_t> points;
std::ofstream svg("boost_test.svg");
boost::geometry::svg_mapper<point_t> mapper(svg, 600, 600);
boost::geometry::model::box<point_t> box(point_t(-15,-15),point_t(15,15));
mapper.add(box);
mapper.map(box, "fill-opacity:1.0;fill:rgb(255,255,255);stroke:rgb(255,255,255);stroke-width:2", 2);
int xy[10][10];
for (double x = 0.0; x <= 10.0; x += 1.0)
{
for (double y = 0.0; y <= 10.0; y += 1.0)
{
if( (int)x % 5 != 0 && (int)y % 5 != 0 )
points.push_back(point_t{ x, y });
}
}
std::vector<cluster_t> clusters;
std::vector<bool> used(points.size(),false);
for (auto p : points)
{
mapper.add(p);
mapper.map(p, "fill-opacity:1.0;fill:rgb(153,4,100);stroke:rgb(153,104,100);stroke-width:1", 1);
}
for (int i=0;i<points.size();++i)
{
const auto& point = points.at(i);
if (used[i]) continue;
double x1 = bg::get<0>(point);
double y1 = bg::get<1>(point);
cluster_t cluster;
cluster.emplace_back(point);
std::cout << i << " ";
DFS(points, used, i, cluster);
used[i] = true;
clusters.emplace_back(cluster);
std::cout << std::endl;
}
auto draw = [&](boost::geometry::svg_mapper<point_t>& mapper, boost::geometry::model::polygon<point_t, false> p, double r, double g, double b)
{
std::string option = "fill - opacity:1.0;fill:rgb(" + std::to_string(r) +","+ std::to_string(g) + "," + std::to_string(b) + "; stroke:rgb(255, 255, 255); stroke - width:1";
mapper.add(p);
mapper.map(p, option, 1);
};
for (size_t i = 0; i < clusters.size(); ++i) {
std::cout << "Cluster " << i << std::endl;
auto r = (255.0 * ((double)i / clusters.size())) ;
auto g = (255.0 * ((double)i / clusters.size())) ;
auto b = (255.0 * ((double)i / clusters.size())) ;
std::string option = "fill - opacity:1.0;fill:rgb(" + std::to_string(r) + "," + std::to_string(g) + "," + std::to_string(b) + "; stroke:rgb(255, 255, 255); stroke - width:1";
std::cout << option << std::endl;
boost::geometry::model::polygon<point_t, false> poly;
boost::geometry::model::polygon<point_t, false> results;
for (int x = 0; x < clusters[i].size(); ++x)
{
poly.outer().emplace_back(clusters[i][x]);
}
boost::geometry::convex_hull(poly, results);
mapper.add(results);
mapper.map(results, "fill-opacity:1.0;fill:rgb(153,4,100);stroke:rgb(153,104,100);stroke-width:1", 1);
}
}
[코드 해석]
- DFS Function
- point(x, y)의 집합인 points를 순회하며, 조건으로 제시한 거리보다 가까이 있는 point들을 찾는 함수
- 특정 point로부터 시작하며 클러스터에 해당하는 경우 다음 연산에서 제외
- mapper
- 디버그를 위해 svg로 출력하기 위한 도구
- boost svg mapper를 사용
- convex_hull
- point들을 outer ring에 처리한 이후, OBB를 계산하기 위해 사용
- inner ring을 제외하고 outline만 살리는 로직으로 다각형 polygon을 구현할 수 있음
반응형