CGAL AlphaShape2算法提取有序边界

在查看“CGAL AlphaShape算法提取有序边界”相关博客(例:https://blog.csdn.net/kw123472/article/details/122176426?spm=1001.2014.3001.5501)后发现很多人不知道怎么从CGAL提取的边界散点中提取按顺序排列的边界集合,进而导致新增了“对无序散点进行有序排列”的算法需求,其实CGAL本身就提供了有序的先验信息;

官网实例代码:

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Alpha_shape_2.h>
#include <CGAL/Alpha_shape_vertex_base_2.h>
#include <CGAL/Alpha_shape_face_base_2.h>
#include <CGAL/Delaunay_triangulation_2.h>
#include <CGAL/algorithm.h>
#include <fstream>
#include <iostream>
#include <list>
#include <vector>
typedef CGAL::Exact_predicates_inexact_constructions_kernel  K;
typedef K::FT                                                FT;
typedef K::Point_2                                           Point;
typedef K::Segment_2                                         Segment;
typedef CGAL::Alpha_shape_vertex_base_2<K>                   Vb;
typedef CGAL::Alpha_shape_face_base_2<K>                     Fb;
typedef CGAL::Triangulation_data_structure_2<Vb,Fb>          Tds;
typedef CGAL::Delaunay_triangulation_2<K,Tds>                Triangulation_2;
typedef CGAL::Alpha_shape_2<Triangulation_2>                 Alpha_shape_2;
typedef Alpha_shape_2::Alpha_shape_edges_iterator            Alpha_shape_edges_iterator;
template <class OutputIterator>
void alpha_edges( const Alpha_shape_2& A, OutputIterator out)
{
  Alpha_shape_edges_iterator it = A.alpha_shape_edges_begin(),
                             end = A.alpha_shape_edges_end();
  for( ; it!=end; ++it)
    *out++ = A.segment(*it);
}
template <class OutputIterator>
bool file_input(OutputIterator out)
{
  std::ifstream is("data/fin", std::ios::in);
  if(is.fail())
  {
    std::cerr << "unable to open file for input" << std::endl;
    return false;
  }
  int n;
  is >> n;
  std::cout << "Reading " << n << " points from file" << std::endl;
  std::copy_n(std::istream_iterator<Point>(is), n, out);
  return true;
}
// Reads a list of points and returns a list of segments
// corresponding to the Alpha shape.
int main()
{
  std::list<Point> points;
  if(! file_input(std::back_inserter(points)))
    return -1;
  Alpha_shape_2 A(points.begin(), points.end(),
                  FT(10000),
                  Alpha_shape_2::GENERAL);
  std::vector<Segment> segments;
  alpha_edges(A, std::back_inserter(segments));
  std::cout << "Alpha Shape computed" << std::endl;
  std::cout << segments.size() << " alpha shape edges" << std::endl;
  std::cout << "Optimal alpha: " << *A.find_optimal_alpha(1)<<std::endl;
  return 0;
}

Alpha shape返回的结果都存在segments这个集合里面,通过观察Segment结构体后会发现,这是一个线段,其中存在两个点,线段起点和终点,其实边界顺序就已经知道了;
伪代码如下:

struct point2{
double x;
double y;
}

std::vector<point2> hull;
std::vector<bool> bUse;
bUse.resize(segments.size(),false);
point2 lastPoint;
bool pair =true;
while(pair){
pair=false;
for(int =0;i<segments.size();i++){
if(bUse[i])continue;
point2 begin =point2(segments[i].vector(0).x,segments[i].vector(0).y);
point2 end =point2(segments[i].vector(1).x,segments[i].vector(1).y);
if(i==0){
bUse[i]=true;
hull.push_back(begin);
hull.push_back(end);
lastPoint =end;
pair =true;
break;
}
if(abs(begin.x-lastPoint.x)<0.00001&&abs(begin.y-lastPoint.y)<0.00001){
bUse[i]=true;
hull.push_back(end);
lastPoint =end;
pair =true;
break;
}
if(abs(end.x-lastPoint.x)<0.00001&&abs(end.y-lastPoint.y)<0.00001){
bUse[i]=true;
hull.push_back(begin);
lastPoint =begin;
pair =true;
break;
}
}
}
  大致意思就是遍历所有线段将首尾相连,最后得到的hull向量即有序的点集;(纯手撸代码,如有错误还望包涵)

再论“对无序散点进行有序排列”的算法,目前看到最多的是以下策略:
– 先计算所有点的重心,再计算每个点与重心点的极角,进行排序;
这样做对凸多边形有用,但是对于凹多边形,用重心和顶点连线计算的正切值,貌似不一定是有序的!
例如"S"型点集,重心则在外部;
若有好的方法希望不吝赐教;

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值