Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ CGAL,矩形中的裁剪voronoi图_C++_Cgal_Voronoi - Fatal编程技术网

C++ CGAL,矩形中的裁剪voronoi图

C++ CGAL,矩形中的裁剪voronoi图,c++,cgal,voronoi,C++,Cgal,Voronoi,我正在使用CGAL和Qt绘制Voronoi图。我使用了CGAL::Voronoi\u图2,因为我需要这些面。以下是示例代码: for(Face_iterator f = VD.faces_begin(); f != VD.faces_end(); f++) { Ccb_halfedge_circulator ec_start = (f)->ccb(); Ccb_halfedge_circulator ec = ec_start; do

我正在使用CGAL和Qt绘制Voronoi图。我使用了
CGAL::Voronoi\u图2
,因为我需要这些面。以下是示例代码:

for(Face_iterator f = VD.faces_begin(); f != VD.faces_end(); f++)
    {
        Ccb_halfedge_circulator ec_start = (f)->ccb();
        Ccb_halfedge_circulator ec = ec_start;
        do {
            if (!ec->has_source())
            {
            }
            else
                QpolyF << QPointF(((Halfedge_handle)ec)->source()->point().x(), ((Halfedge_handle)ec)->source()->point().y());
        } while ( ++ec != ec_start );
        VectPolygon.push_back(QpolyF);
        QpolyF.clear();}
for(Face_迭代器f=VD.faces_begin();f!=VD.faces_end();f++)
{
Ccb_半边环行器ec_开始=(f)->Ccb();
Ccb_半边缘_循环器ec=ec_启动;
做{
如果(!ec->has_source())
{
}
其他的
QpolyF source()->point().x(),((半边_句柄)ec)->source()->point().y());
}而(++ec!=ec_开始);
矢量多边形。推回(QpolyF);
QpolyF.clear();}
我需要剪辑无限远处有光源或目标的光线。如果我使用从_delaunay裁剪的_voronoi _生成voronoi,它只会生成线段而不是面。这些是typedef:

typedef K::Line_2                                           Line_2;
typedef CGAL::Delaunay_triangulation_2<K>                   Delaunay_triangulation_2;
typedef Delaunay_triangulation_2::Face_iterator             dt_Face_iterator;
typedef Delaunay_triangulation_2::Edge_circulator           dt_Edge_circulator;

// typedefs for defining the adaptor
typedef CGAL::Exact_predicates_inexact_constructions_kernel                  K;
typedef CGAL::Delaunay_triangulation_2<K>                                    DT;
typedef CGAL::Delaunay_triangulation_adaptation_traits_2<DT>                 AT;
typedef CGAL::Delaunay_triangulation_caching_degeneracy_removal_policy_2<DT> AP;
typedef CGAL::Voronoi_diagram_2<DT,AT,AP>                                    VD;


// typedef for the result type of the point location
typedef AT::Site_2                    Site_2;
typedef AT::Point_2                   Point_2;

typedef VD::Locate_result               Locate_result;
typedef VD::Vertex_handle               Vertex_handle;
typedef VD::Face_handle                 Face_handle;
typedef VD::Face_iterator               Face_iterator;
typedef VD::Halfedge_handle             Halfedge_handle;
typedef VD::Ccb_halfedge_circulator     Ccb_halfedge_circulator;
typedef K::Line_2 Line_2;
typedef CGAL::Delaunay_三角剖分2 Delaunay_三角剖分2;
typedef Delaunay_三角剖分_2::Face_迭代器dt_Face_迭代器;
typedef Delaunay_三角剖分_2::Edge_循环器dt_Edge_循环器;
//用于定义适配器的typedef
typedef CGAL::精确谓词不精确结构内核K;
typedef CGAL::Delaunay_三角剖分_2DT;
typedef CGAL::Delaunay_三角剖分_适应_特征_2 AT;
typedef CGAL::Delaunay_三角剖分_缓存_退化_删除_策略_2 AP;
typedef CGAL::Voronoi_图2 VD;
//点位置的结果类型的typedef
typedef AT::Site_2 Site_2;
typedef AT::Point_2 Point_2;
typedef VD::Locate_result Locate_result;
typedef VD::顶点句柄顶点句柄;
typedef VD::面\手柄面\手柄;
typedef VD::Face_迭代器Face_迭代器;
typedef VD::半边\手柄半边\手柄;
类型定义VD::Ccb_半边缘_循环器Ccb_半边缘_循环器;

我知道用CGAL可以做到这一点,但我现在找到了一个解决办法。在Qt中,QPolygon类具有查找相交多边形的功能<代码>多边形::相交(多边形)。 结果如下:


这里有一些实验代码:将voronoi图裁剪成矩形,结果是HDS。请参见测试目录中的main.cpp

以下内容将生成随机点云,找到其Voronoi图,将该图裁剪到云的边界框,并生成已知的文本多边形

我不确定如何将其与Qt集成,但是,假设一旦有了多边形,这部分就很容易了(ish)

//查找一组点的裁剪Voronoi图并将其保存为WKT
//使用:g++main.cpp-Wall-lCGAL-lgmp编译
//作者:理查德·巴恩斯(rbarnes.org)
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
//用于将无限光线转换为长线段
常数int射线长度=1000;
typedef CGAL::精确谓词\精确构造\内核K;
typedef CGAL::规则的_三角剖分_过滤的_特征_2特征;
typedef CGAL::正则_三角剖分_2 RT2;
typedef CGAL::常规三角剖分法(Regular_triangulation)(u adaption)(u traits)(u 2 AT);
typedef CGAL::正则三角剖分简并消除策略2 DRP;
typedef CGAL::Voronoi_图2 VD;
int main(int argc,字符**argv){
std::向量wpoints;
标准:计算精度(4);
std::cout.setf(std::ios::fixed);
//生成的随机点
对于(int i=0;ik::段_2{
//其中一个将成功,另一个将具有空指针
常量K::段2*dseg=CGAL::对象转换(&seg\u obj);
常数K::光线2*dray=CGAL::对象投射(&seg\U obj);
如果(dseg){//好的,我们有一个片段
返回*dseg;
}否则{//必须是光线
const auto&source=dray->source();
const auto dsx=source.x();
const auto dsy=source.y();
const auto&dir=dray->direction();
const auto tpoint=K::Point_2(dsx+RAY_LENGTH*dir.dx(),dsy+RAY_LENGTH*dir.dy());
如果(传出)
返回K::段2(
dray->source(),
T点
);
其他的
返回K::段2(
t点,
dray->source()
);
}
};
//WKT CSV输出的第一行
std::couthas_target()){
const CGAL::Object nseg_dual=vd.dual().dual(ec->next()->dual());
const auto next_seg=ConvertToSeg(nseg_dual,ec->next()->has_target());
pgon.push_back(下一个seg.target());
}
}而(++ec!=ec_开始)//循环直到我们回到开始
//为了裁剪Voronoi图,我们需要转换边界框
//变成一个多边形。你会认为这是一个简单的方法。但是那里
//没有(或者我还没有找到)。
CGAL::多边形_2 b多边形;
bpoly.push_back(K::Point_2(bbox.xmin(),bbox.ymin());
bpoly.push_back(K::Point_2(bbox.xmax(),bbox.ymin());
bpoly.push_back(K::Point_2(bbox.xmax(),bbox.ymax());
bpoly.push_back(K::Point_2(bbox.xmin(),bbox.ymax());
//执行交叉。由于CGAL非常通用,它认为
//结果可能是多个带孔的多边形。
std::列表isect;
CGAL::交叉点(pgon、bpoly、std::背面插入器(isect));
//但我们更清楚。凸多边形与长方体的交点为
//始终是一个没有孔的多边形。让我们断言这一点。
断言(isect.size()==1);
//并恢复感兴趣的多边形
auto&poly_w_holes=isect.front();
自动和多边形外部=多边形带孔。外部边界();
//将多边形打印为WKT多边形

std::coutWhy你对下面的例子不满意吗:?正如我说的,我需要脸,但CGAL中的例子只给出了片段。还有“2D范围和邻居搜索”非常接近,但我不确定
//Finds the cropped Voronoi diagram of a set of points and saves it as WKT
//Compile with: g++ main.cpp -Wall -lCGAL -lgmp
//Author: Richard Barnes (rbarnes.org)
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Regular_triangulation_filtered_traits_2.h>
#include <CGAL/Regular_triangulation_adaptation_traits_2.h>
#include <CGAL/Regular_triangulation_adaptation_policies_2.h>
#include <CGAL/Regular_triangulation_2.h>
#include <CGAL/Voronoi_diagram_2.h>
#include <CGAL/Boolean_set_operations_2.h>
#include <CGAL/bounding_box.h>
#include <CGAL/Polygon_2.h>
#include <iostream>
#include <cstdint>

//Used to convert otherwise infinite rays into looooong line segments
const int RAY_LENGTH = 1000;

typedef CGAL::Exact_predicates_exact_constructions_kernel K;
typedef CGAL::Regular_triangulation_filtered_traits_2<K>  Traits;

typedef CGAL::Regular_triangulation_2<Traits> RT2;
typedef CGAL::Regular_triangulation_adaptation_traits_2<RT2>         AT;
typedef CGAL::Regular_triangulation_degeneracy_removal_policy_2<RT2> DRP;
typedef CGAL::Voronoi_diagram_2<RT2, AT, DRP> VD;

int main(int argc, char **argv){
  std::vector<RT2::Weighted_point> wpoints;

  std::cout.precision(4);
  std::cout.setf(std::ios::fixed);

  //Generated random points
  for(int i=0;i<100;i++)
    //Weight of 0 gives a Voronoi diagram. Non-zero weight gives a power diagram
    wpoints.push_back(RT2::Weighted_point(K::Point_2(rand()%100,rand()%100), 0)); 

  //Find the bounding box of the points. This will be used to crop the Voronoi
  //diagram later.
  const K::Iso_rectangle_2 bbox = CGAL::bounding_box(wpoints.begin(), wpoints.end());

  //Create a Regular Triangulation from the points
  RT2 rt(wpoints.begin(), wpoints.end());
  rt.is_valid();

  //Wrap the triangulation with a Voronoi diagram adaptor. This is necessary to
  //get the Voronoi faces.
  VD vd(rt);

  //CGAL often returns objects that are either segments or rays. This converts
  //these objects into segments. If the object would have resolved into a ray,
  //that ray is intersected with the bounding box defined above and returned as
  //a segment.
  const auto ConvertToSeg = [&](const CGAL::Object seg_obj, bool outgoing) -> K::Segment_2 {
    //One of these will succeed and one will have a NULL pointer
    const K::Segment_2 *dseg = CGAL::object_cast<K::Segment_2>(&seg_obj);
    const K::Ray_2     *dray = CGAL::object_cast<K::Ray_2>(&seg_obj);
    if (dseg) { //Okay, we have a segment
      return *dseg;
    } else {    //Must be a ray
      const auto &source = dray->source();
      const auto dsx     = source.x();
      const auto dsy     = source.y();
      const auto &dir    = dray->direction();
      const auto tpoint  = K::Point_2(dsx+RAY_LENGTH*dir.dx(),dsy+RAY_LENGTH*dir.dy());
      if(outgoing)
        return K::Segment_2(
          dray->source(),
          tpoint
        );
      else
        return K::Segment_2(
          tpoint,
          dray->source()
        );
    }
  };

  //First line of WKT CSV output
  std::cout<<"\"id\",\"geom\"\n";

  int fnum = 0;
  //Loop over the faces of the Voronoi diagram in some arbitrary order
  for(VD::Face_iterator fit = vd.faces_begin(); fit!=vd.faces_end();++fit,fnum++){
    CGAL::Polygon_2<K> pgon;

    //Edge circulators traverse endlessly around a face. Make a note of the
    //starting point so we know when to quit.
    VD::Face::Ccb_halfedge_circulator ec_start = fit->ccb();

    //Current location of the edge circulator
    VD::Face::Ccb_halfedge_circulator ec = ec_start;

    do {
      //A half edge circulator representing a ray doesn't carry direction
      //information. To get it, we take the dual of the dual of the half-edge.
      //The dual of a half-edge circulator is the edge of a Delaunay triangle.
      //The dual of the edge of Delaunay triangle is either a segment or a ray.
      // const CGAL::Object seg_dual = rt.dual(ec->dual());
      const CGAL::Object seg_dual = vd.dual().dual(ec->dual());

      //Convert the segment/ray into a segment
      const auto this_seg = ConvertToSeg(seg_dual, ec->has_target());

      pgon.push_back(this_seg.source());

      //If the segment has no target, it's a ray. This means that the next
      //segment will also be a ray. We need to connect those two rays with a
      //segment. The following accomplishes this.
      if(!ec->has_target()){
        const CGAL::Object nseg_dual = vd.dual().dual(ec->next()->dual());
        const auto next_seg = ConvertToSeg(nseg_dual, ec->next()->has_target());
        pgon.push_back(next_seg.target());
      }
    } while ( ++ec != ec_start ); //Loop until we get back to the beginning

    //In order to crop the Voronoi diagram, we need to convert the bounding box
    //into a polygon. You'd think there'd be an easy way to do this. But there
    //isn't (or I haven't found it).
    CGAL::Polygon_2<K> bpoly;
    bpoly.push_back(K::Point_2(bbox.xmin(),bbox.ymin()));
    bpoly.push_back(K::Point_2(bbox.xmax(),bbox.ymin()));
    bpoly.push_back(K::Point_2(bbox.xmax(),bbox.ymax()));
    bpoly.push_back(K::Point_2(bbox.xmin(),bbox.ymax()));

    //Perform the intersection. Since CGAL is very general, it believes the
    //result might be multiple polygons with holes.
    std::list<CGAL::Polygon_with_holes_2<K>> isect;
    CGAL::intersection(pgon, bpoly, std::back_inserter(isect));

    //But we know better. The intersection of a convex polygon and a box is
    //always a single polygon without holes. Let's assert this.
    assert(isect.size()==1);

    //And recover the polygon of interest
    auto &poly_w_holes = isect.front();
    auto &poly_outer   = poly_w_holes.outer_boundary();

    //Print the polygon as a WKT polygon
    std::cout<<fnum<<", "
    "\"POLYGON ((";
    for(auto v=poly_outer.vertices_begin();v!=poly_outer.vertices_end();v++)
      std::cout<<v->x()<<" "<<v->y()<<", ";
    std::cout<<poly_outer.vertices_begin()->x()<<" "<<poly_outer.vertices_begin()->y()<<"))\"\n";
  }

  return 0;
}