基于CGAL进行正球面多边形布尔运算(二)

4 篇文章 0 订阅

#include <CGAL/Nef_polyhedron_S2.h>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Nef_polyhedron_S2.h>
//#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
//#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Lazy_exact_nt.h>
#include <CGAL/Exact_rational.h>

#include <math.h>
#include <iomanip>

//遇到浮点数精度问题,会导致Nef_polyhedron构造失败
//typedef CGAL::Lazy_exact_nt<doublet>           LazyFloat;
//typedef CGAL::Lazy_exact_nt<CGAL::MP_Float>    LazyFloat;
//typedef CGAL::Simple_cartesian<LazyFloat> Kernel;
//typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;

//找了很久得到的解决方法!!!
typedef CGAL::Quotient<CGAL::MP_Float> Exact_NT; // doesn't do exact sqrt()
typedef CGAL::Lazy_exact_nt<Exact_NT>  LazyFloat;
typedef CGAL::Simple_cartesian<LazyFloat> Kernel;


typedef CGAL::Nef_polyhedron_S2<Kernel> Nef_polyhedron;
typedef Nef_polyhedron::Sphere_point            Nef_Sphere_point;
typedef Nef_polyhedron::Sphere_segment          Nef_Sphere_segment;
typedef Nef_polyhedron::SVertex_const_handle    SVertex_const_handle;
typedef Nef_polyhedron::SVertex_const_iterator  SVertex_const_iterator;
typedef Nef_polyhedron::SHalfedge_const_iterator SHalfedge_const_iterator;

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
const static double Rad2Deg = 180.0 / M_PI;
const static double Deg2Rad = M_PI / 180.0;


//通过经纬度创建球面的点,归一化的,输入单位:角度制
Nef_Sphere_point createPoint(double lon0, double lat0)
{
    //假定:X轴为经纬度为<0,0>的方向,Z轴指北
    double lon = lon0 * Deg2Rad;
    double lat = lat0 * Deg2Rad;
    LazyFloat x = std::cos(lat) * std::cos(lon);
    LazyFloat y = std::cos(lat) * std::sin(lon);
    LazyFloat z = std::sin(lat);

    Nef_Sphere_point pt(x, y, z);
    std::cout << std::setprecision(14) << std::setiosflags(std::ios::fixed)
              << "Sphere_point \t" << lon0 << ", \t" << lat0 << ": \t" << pt << "\n";
    return pt;
}

//从归一化的三维点得到经纬高,alt期望为0(TODO 1: 但是没有符合期望,暂不理解)
void getLLA(double x, double y, double z, double &lon, double &lat, double &alt)
{
    lon = 0;
    lat = 0;
    alt = 0;

    double rr = x*x + y*y +z*z;
    //assert(std::fabs(rr-1.0) < 0.001);
    double r = std::sqrt(rr);

    alt = r - 1.0;
    double z_r = z / r;

    lon = Rad2Deg * atan2(y, x);
    lat = Rad2Deg * asin(z_r);
}



int main()
{
    //注意:先不考虑扁率,仅考虑正球面上的布尔运算
    //面目标1 经、纬度:<0,0> <30,0> <30,30>
    //面目标2 经、纬度:<0,15> <60,15> <60,45> <0,45>

    //LazyFloat::set_relative_precision_of_to_double(1e-3); //1e-30, TODO 2: 好像没毛影响,暂不理解


    Nef_Sphere_point   cz1 = createPoint(0, 0);
    Nef_Sphere_point   cz2 = createPoint(30,0);
    Nef_Sphere_point   cz3 = createPoint(30,30);

    Nef_Sphere_point   dd1 = createPoint(0, 15);
    Nef_Sphere_point   dd2 = createPoint(60,15);
    Nef_Sphere_point   dd3 = createPoint(60,45);
    Nef_Sphere_point   dd4 = createPoint(0, 45);

    //Nef_polyhedron构造方法参考官方:Nef_S2/nef_s2_construction.cpp
    Nef_Sphere_segment cz_s1(cz1,cz2);
    Nef_Sphere_segment cz_s2(cz2,cz3);
    Nef_Sphere_segment cz_s3(cz3,cz1);
    Nef_Sphere_segment dd_s1(dd1,dd2);
    Nef_Sphere_segment dd_s2(dd2,dd3);
    Nef_Sphere_segment dd_s3(dd3,dd4);
    Nef_Sphere_segment dd_s4(dd4,dd1);
    //std::cout << "cz_s2: " << cz_s1.source() << "," << cz_s1.target() << "," << cz_s1.is_short() << std::endl;

    Nef_Sphere_segment triangle[]  = { cz_s1, cz_s2, cz_s3 };
    Nef_Sphere_segment rectangle[] = { dd_s1, dd_s2, dd_s3, dd_s4 };

    const Nef_polyhedron N1(triangle,     triangle+3, Nef_polyhedron::INCLUDED);
    const Nef_polyhedron N2(rectangle,    rectangle+4, Nef_polyhedron::INCLUDED);
    const Nef_polyhedron N3 = N1 * N2;

    //---- 以下是Nef_polyhedron_S2遍历相关的代码 ----
    //std::cout << N3.is_empty() << "\n" << N3 << "\n\n";

    const Nef_polyhedron::Sphere_map &m = N3.sphere_map();
    Nef_polyhedron::Const_decorator D(&m);

    std::cout << "vert count: " << D.number_of_svertices()<< "\n";
    std::cout << "edge count: " << D.number_of_sedges()   << "\n";
    std::cout << "loop count: " << D.number_of_sloops()   << "\n";
    std::cout << "face count: " << D.number_of_sfaces()   << "\n";
    std::cout << "\n\n ------------------------\n";

    //遍历Nef_polyhedron_S2的顶点
    int i = 1;
    for (SVertex_const_iterator it = D.svertices_begin(); it != D.svertices_end(); i++, ++it)
    {
        double lon = 0, lat = 0, alt = 0;
        double x = CGAL::to_double(it->point().x());
        double y = CGAL::to_double(it->point().y());
        double z = CGAL::to_double(it->point().z());
        getLLA(x, y, z, lon, lat, alt);

        std::cout << std::setprecision(14) << std::setiosflags(std::ios::fixed)
                  << i << ":"
                  //<< it->point() //Sphere_point SM_items::SVertex::point();
                  << "| "  << it->point().x()
                  << ", " << it->point().y()
                  << ", " << it->point().z()
                  << "| " << lon
                  << "; " << lat
                  << "; " << alt
                  << std::endl;
    }

    //TODO 3: 先遍历面,再获取面相关的点,参考https://doc.cgal.org/latest/Manual/devman_iterators_and_circulators.html (Iterators, Circulators and Handles)
    //TODO 4: 暂不理解为什么会有多个面number_of_sfaces,按照理解应该只有一个,随后从特征上排除非真正的结果

    return 0;
}

/*
输出:
=====================================================================================
Sphere_point    0.00000000000000,       0.00000000000000:       1.00000000000000 0.00000000000000 0.00000000000000
Sphere_point    30.00000000000000,      0.00000000000000:       0.86602540378444 0.50000000000000 0.00000000000000
Sphere_point    30.00000000000000,      30.00000000000000:      0.75000000000000 0.43301270189222 0.50000000000000
Sphere_point    0.00000000000000,       15.00000000000000:      0.96592582628907 0.00000000000000 0.25881904510252
Sphere_point    60.00000000000000,      15.00000000000000:      0.48296291314453 0.83651630373781 0.25881904510252
Sphere_point    60.00000000000000,      45.00000000000000:      0.35355339059327 0.61237243569579 0.70710678118655
Sphere_point    0.00000000000000,       45.00000000000000:      0.70710678118655 0.00000000000000 0.70710678118655
vert count: 7
edge count: 7
loop count: 0
face count: 2


 ------------------------
1:| 0.35355339059327, 0.61237243569579, 0.70710678118655| 59.99999999999999; 45.00000000000001; 0.00000000000000
2:| 0.70710678118655, 0.00000000000000, 0.70710678118655| 0.00000000000000; 45.00000000000001; 0.00000000000000
3:| 0.75000000000000, 0.43301270189222, 0.50000000000000| 30.00000000000000; 30.00000000000000; 0.00000000000000
4:| 0.48296291314453, 0.83651630373781, 0.25881904510252| 59.99999999999999; 15.00000000000000; 0.00000000000000
5:| 0.34987976320958, 0.20200317547305, 0.12500000000000| 30.00000000000000; 17.19212373402097; -0.57709796452986
6:| 0.34987976320958, 0.09375000000000, 0.10825317547305| 15.00000000000000; 16.63922203701361; -0.62194754173052
7:| 0.96592582628907, 0.00000000000000, 0.25881904510252| 0.00000000000000; 15.00000000000000; 0.00000000000000

=====================================================================================
*/

//新增的两个交点
//5:| 0.34987976320958, 0.20200317547305, 0.12500000000000| 30.00000000000000; 17.19212373402097; -0.57709796452986
//6:| 0.34987976320958, 0.09375000000000, 0.10825317547305| 15.00000000000000; 16.63922203701361; -0.62194754173052

PS/TODO:还有一些"土豆"没有挖。。。

尝试查看例子、文档找到的关键代码如下,尽管还未充分理解

//遇到浮点数精度问题,会导致Nef_polyhedron构造失败
//typedef CGAL::Lazy_exact_nt<doublet>           LazyFloat;
//typedef CGAL::Lazy_exact_nt<CGAL::MP_Float>    LazyFloat;
//typedef CGAL::Simple_cartesian<LazyFloat> Kernel;
//typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;

//找了很久得到的解决方法!!!
typedef CGAL::Quotient<CGAL::MP_Float> Exact_NT; // doesn't do exact sqrt()
typedef CGAL::Lazy_exact_nt<Exact_NT>  LazyFloat;
typedef CGAL::Simple_cartesian<LazyFloat> Kernel;

【参考链接】
https://doc.cgal.org/latest/Nef_S2/index.html
https://doc.cgal.org/latest/Number_types/index.html
https://doc.cgal.org/latest/Manual/devman_iterators_and_circulators.html
https://www.cgal.org/FAQ.html#kernels

.../cgal-5.5.2/number_types/test/Number_types/Lazy_exact_nt.cpp

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
CGAL是一个计算几何的C++,其提供了许多用于算法设计和实现的数据结构和函数。其中就包括了维平面多边型的布尔运算操作,包括求交集、并集、差集等。这些运算在计算机图形学、地理信息系统、自动化设计等领域都有广泛的应用。 在测试CGAL维平面多边形布尔运算性能时,需要考虑多个因素,如多边形的大小、数量、形状以及计算机的硬件配置等。我将分别从这些方面来介绍CGAL维平面多边形布尔运算性能测试的结果。 1. 多边形的大小和数量 测试表明,CGAL能够处理非常大的多边形,例如含有上万个点的多边形。然而,多边形的大小和数量还是会对运算时间产生影响。当多边形数目增加时,运算时间也相应增加。实验表明,当多边形数量为几百到几千时,CGAL处理多边形布尔运算的时间较长,需要几秒钟到几分钟不等。当多边形数量超过一万时,运算时间将变得非常长,可能需要花费数十分钟的时间。 2. 多边形的形状 当多边形的形状很简单时,例如多边形和矩形,CGAL的运算时间非常短,可以在毫秒或几秒钟内完成。但如果多边形有大量的凹角和复杂的几何形状,CGAL的运算时间将变长。实验表明,当多边形具有纽结、孔洞等复杂形状时,CGAL的运算时间可能会增加几倍或更多。 3. 计算机硬件配置 CGAL维平面多边形布尔运算的性能还与计算机硬件配置有关。例如,处理大型多边形时,需要更快的处理器和更大的内存。此外,CGAL还可以利用多个处理器来并行处理大型多边形,这将极大地提高计算速度。 综上所述,CGAL维平面多边形布尔运算的性能测试结果取决于多方面因素。在对运算性能进行测试时,需要综合考虑多边形的大小、数量、形状以及计算机的硬件配置等因素。当然,在实际应用中,还需要根据具体情况选择最适合自己的算法和数据结构。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

piaopiaolanghua

感谢鼓励,再接再厉!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值