Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.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构造球面多面体_C++_Cgal - Fatal编程技术网

C++ CGAL构造球面多面体

C++ CGAL构造球面多面体,c++,cgal,C++,Cgal,我是CGAL新手,目前需要使用CGAL计算球面多面体面积。然而,我停留在第一步,即从球体点构造球体多面体。这是我的密码 typedef CGAL::Simple_笛卡尔K; typedef CGAL::Nef_多面体\ u S2 Nef_多面体; typedef Nef_多面体::球体点球体点; typedef Nef_多面体::球体_段球体_段; typedef Nef_多面体::SVertex_const_迭代器SVertex_const_迭代器; 球面点p1(1,0,0),p2(0,0,1

我是CGAL新手,目前需要使用CGAL计算球面多面体面积。然而,我停留在第一步,即从球体点构造球体多面体。这是我的密码

typedef CGAL::Simple_笛卡尔K;
typedef CGAL::Nef_多面体\ u S2 Nef_多面体;
typedef Nef_多面体::球体点球体点;
typedef Nef_多面体::球体_段球体_段;
typedef Nef_多面体::SVertex_const_迭代器SVertex_const_迭代器;
球面点p1(1,0,0),p2(0,0,1),p3(1,-1,0);
球面_段s1(p1,p2),s2(p2,p3),s3(p3,p1);
std::向量tri({s1,s2,s3});
Nef_多面体S(tri.begin(),tri.end());
int i=0;
for(SVertex_const_iterator it=S.svertices_begin();it!=S.svertices_end();++it)
{
Sphere_point p=it->point();

std::cout创建一个包含三段的球形多边形后,您将得到六个顶点,因为您不仅探索多边形,还探索整个多边形,将球体划分为多个面。每个面都由一个外半边圈(在最简单的情况下)限定,它可以包含孔,也可以由半边的循环限定。下面的代码显示了如何逐个探索此类分区的面:

#include <iostream>
#include <sstream>
#include <string>
#include <vector>

#include <CGAL/Exact_rational.h>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Nef_polyhedron_S2.h>

using Kernel = CGAL::Simple_cartesian<CGAL::Exact_rational>;
using SPolygon = CGAL::Nef_polyhedron_S2<Kernel>;
using SPoint = SPolygon::Sphere_point;
using SSegment = SPolygon::Sphere_segment;

using std::cout;
using std::endl;

std::string pointAsString(const SPoint& P)
{
  std::stringstream ss;
  ss << "(" << P.x() << "," << P.y() << "," << P.z() << ")";
  return ss.str();
}

std::string halfEdgeCycleAsString(const SPolygon::SHalfedge_const_iterator HEIT)
{
  std::stringstream ss;
  auto heit = HEIT; 
  while (true)
  {
    ss << pointAsString(heit->source()->point()) << " => " << pointAsString(heit->target()->point());
    heit = heit->snext();
    if (heit != HEIT)
    {
      ss << ", ";
    }
    else
    {
      break;
    }
  }
  return ss.str();
}

void printFaces(const SPolygon& P)
{
  unsigned i = 0;
  for (auto fit = P.sfaces_begin(); fit != P.sfaces_end(); ++fit)
  {
    cout << "face #" << i++ << ":" << endl;
    for (auto fcit = fit->sface_cycles_begin(); fcit != fit->sface_cycles_end(); ++fcit)
    {
      cout << "  face boundary:" << endl;
      if (fcit.is_svertex())
      {
        const SPolygon::SVertex_const_handle vit = fcit;
        cout << "    vertex " << pointAsString(vit->point()) << endl;
      }
      else if (fcit.is_shalfedge())
      {
        const SPolygon::SHalfedge_const_handle heit = fcit;
        cout << "    halfedge cycle [" << halfEdgeCycleAsString(heit) << "]" << endl;
      }
      else if (fcit.is_shalfloop())
      {
        const SPolygon::SHalfloop_const_handle hlit = fcit;
        cout << "    halfloop (" << hlit->circle() << ")" << endl;
      }
    }
  }
}

int main()
{
  const SPoint p1(1, 0, 0),  p2(0, 0, 1), p3(1, -1, 0);
  const std::vector<SSegment> v{{p1, p2}, {p2, p3}, {p3, p1}};
  const SPolygon p(v.cbegin(), v.cend());
  p.print_statistics();
  printFaces(p);
}
代码中的另一个问题-您不应该在
Simple_cartesian
内核中使用
double
数字,因为此内核需要有理数,支持精确计算。此外,如果您有非整数输入数据,则需要将其转换为有理数:

SPoint p(1, 0, CGAL::Exact_rational(119, 31)); 
如果在此处使用
119/31
,则此z坐标将四舍五入为
3


更新。您只能遍历DCEL的一部分,这对您很重要-例如,您创建的多边形的所有边。一种方法如下:

int main()
{
  const SPoint p1(1, 0, 0),  p2(0, 0, 1), p3(1, -1, 0);
  const std::vector<SSegment> v{{p1, p2}, {p2, p3}, {p3, p1}};
  const SPolygon p(v.cbegin(), v.cend());
  // ------ locate the starting vertex of this polygon and output its halfedge cycle
  const auto h = p.locate(p1);
  SPolygon::SVertex_const_handle vh = nullptr;
  if (CGAL::assign(vh, h))
  {
    cout << halfEdgeCycleAsString(vh->out_sedge()) << endl;
  }
  else
  {
    cout << "Vertex is not found" << endl;
  }
}
intmain()
{
常数点p1(1,0,0),p2(0,0,1),p3(1,-1,0);
常数std::向量v{p1,p2},{p2,p3},{p3,p1};
康斯特·斯波利贡(v.cbegin(),v.cend());
//------定位此多边形的起始顶点并输出其半边循环
常数自动h=p.locate(p1);
SPolygon::SVertex_const_handle vh=nullptr;
如果(CGAL::分配(vh,h))
{

cout out_sedge())创建一个包含三段的球形多边形后,您将得到六个顶点,因为您不仅探索多边形,还探索整个多边形,将球体划分为多个面。每个面都由一个外半边圈(在最简单的情况下)限定,它可以包含孔,也可以由半边的循环限定。下面的代码显示了如何逐个探索此类分区的面:

#include <iostream>
#include <sstream>
#include <string>
#include <vector>

#include <CGAL/Exact_rational.h>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Nef_polyhedron_S2.h>

using Kernel = CGAL::Simple_cartesian<CGAL::Exact_rational>;
using SPolygon = CGAL::Nef_polyhedron_S2<Kernel>;
using SPoint = SPolygon::Sphere_point;
using SSegment = SPolygon::Sphere_segment;

using std::cout;
using std::endl;

std::string pointAsString(const SPoint& P)
{
  std::stringstream ss;
  ss << "(" << P.x() << "," << P.y() << "," << P.z() << ")";
  return ss.str();
}

std::string halfEdgeCycleAsString(const SPolygon::SHalfedge_const_iterator HEIT)
{
  std::stringstream ss;
  auto heit = HEIT; 
  while (true)
  {
    ss << pointAsString(heit->source()->point()) << " => " << pointAsString(heit->target()->point());
    heit = heit->snext();
    if (heit != HEIT)
    {
      ss << ", ";
    }
    else
    {
      break;
    }
  }
  return ss.str();
}

void printFaces(const SPolygon& P)
{
  unsigned i = 0;
  for (auto fit = P.sfaces_begin(); fit != P.sfaces_end(); ++fit)
  {
    cout << "face #" << i++ << ":" << endl;
    for (auto fcit = fit->sface_cycles_begin(); fcit != fit->sface_cycles_end(); ++fcit)
    {
      cout << "  face boundary:" << endl;
      if (fcit.is_svertex())
      {
        const SPolygon::SVertex_const_handle vit = fcit;
        cout << "    vertex " << pointAsString(vit->point()) << endl;
      }
      else if (fcit.is_shalfedge())
      {
        const SPolygon::SHalfedge_const_handle heit = fcit;
        cout << "    halfedge cycle [" << halfEdgeCycleAsString(heit) << "]" << endl;
      }
      else if (fcit.is_shalfloop())
      {
        const SPolygon::SHalfloop_const_handle hlit = fcit;
        cout << "    halfloop (" << hlit->circle() << ")" << endl;
      }
    }
  }
}

int main()
{
  const SPoint p1(1, 0, 0),  p2(0, 0, 1), p3(1, -1, 0);
  const std::vector<SSegment> v{{p1, p2}, {p2, p3}, {p3, p1}};
  const SPolygon p(v.cbegin(), v.cend());
  p.print_statistics();
  printFaces(p);
}
代码中的另一个问题-您不应该在
Simple_cartesian
内核中使用
double
数字,因为此内核需要有理数,支持精确计算。此外,如果您有非整数输入数据,则需要将其转换为有理数:

SPoint p(1, 0, CGAL::Exact_rational(119, 31)); 
如果在此处使用
119/31
,则此z坐标将四舍五入为
3


更新。您只能遍历DCEL的一部分,这对您很重要-例如,您创建的多边形的所有边。一种方法如下:

int main()
{
  const SPoint p1(1, 0, 0),  p2(0, 0, 1), p3(1, -1, 0);
  const std::vector<SSegment> v{{p1, p2}, {p2, p3}, {p3, p1}};
  const SPolygon p(v.cbegin(), v.cend());
  // ------ locate the starting vertex of this polygon and output its halfedge cycle
  const auto h = p.locate(p1);
  SPolygon::SVertex_const_handle vh = nullptr;
  if (CGAL::assign(vh, h))
  {
    cout << halfEdgeCycleAsString(vh->out_sedge()) << endl;
  }
  else
  {
    cout << "Vertex is not found" << endl;
  }
}
intmain()
{
常数点p1(1,0,0),p2(0,0,1),p3(1,-1,0);
常数std::向量v{p1,p2},{p2,p3},{p3,p1};
康斯特·斯波利贡(v.cbegin(),v.cend());
//------定位此多边形的起始顶点并输出其半边循环
常数自动h=p.locate(p1);
SPolygon::SVertex_const_handle vh=nullptr;
如果(CGAL::分配(vh,h))
{

cout out_sedge())谢谢你的回答,内容非常丰富。我还有两个简单的问题。1)我能从球体多面体的边界(可能是定向的)构造球体多面体吗分段?因为这里我不需要整个曲面的分区。2)对于类型为
Exact\u rational
的内核,我可以使用
to\u rational
将双倍数转换为有理类型吗?@yang-当你创建一个球形多边形时,你会创建一个相应的DCEL,它定义了一个分区。所以像
SVertex\u const\u这样的迭代器可以erator
将迭代此分区。但是,您可以忽略此分区,只迭代您刚刚创建的多边形-使用函数
locate
查找包含多边形第一个点的DCEL对象,将此对象转换为顶点控制柄,并使用
out\u sedge
函数查找t他是你的前半身polygon@yang-至于
to_rational
函数-是的,您可以使用它。但是
精确的\u rational
构造函数可以将双精度转换为有理数-看起来simpler@yang-请查看我的更新谢谢你的回复,内容非常丰富。我还有两个简短的问题。1)我可以构建仅从其边界开始的球面多面体(可能是定向的)分段?因为这里我不需要整个曲面的分区。2)对于类型为
Exact\u rational
的内核,我可以使用
to\u rational
将双倍数转换为有理类型吗?@yang-当你创建一个球形多边形时,你会创建一个相应的DCEL,它定义了一个分区。所以像
SVertex\u const\u这样的迭代器可以erator
将迭代此分区。但是,您可以忽略此分区,只迭代您刚刚创建的多边形-使用函数
locate
查找包含多边形第一个点的DCEL对象,将此对象转换为顶点控制柄,并使用
out\u sedge
函数查找t他是你的前半身polygon@yang-至于
to_rational
函数-是的,您可以使用它。但是
精确的\u rational
构造函数可以将双精度转换为有理数-看起来simpler@yang-请查看我的更新
SPoint p(1, 0, CGAL::Exact_rational(119, 31)); 
int main()
{
  const SPoint p1(1, 0, 0),  p2(0, 0, 1), p3(1, -1, 0);
  const std::vector<SSegment> v{{p1, p2}, {p2, p3}, {p3, p1}};
  const SPolygon p(v.cbegin(), v.cend());
  // ------ locate the starting vertex of this polygon and output its halfedge cycle
  const auto h = p.locate(p1);
  SPolygon::SVertex_const_handle vh = nullptr;
  if (CGAL::assign(vh, h))
  {
    cout << halfEdgeCycleAsString(vh->out_sedge()) << endl;
  }
  else
  {
    cout << "Vertex is not found" << endl;
  }
}