IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 根据面积均分球面 & c++示意代码 -> 正文阅读

[C++知识库]根据面积均分球面 & c++示意代码

参考文献:Malkin Z. A new method to subdivide a spherical surface into equal-area cells[J]. arXiv preprint arXiv:1612.03467, 2016.

一种根据面积均分球面的方法是根据经纬度来分,即将直角坐标 ( x , y , z ) (x,y,z) (x,y,z)转换成极坐标 ( θ , ? , r ) (\theta, \phi, r) (θ,?,r),然后将 θ \theta θ ? \phi ?均分。均分 ? \phi ?(经度)确实能让分出来的小块面积相等,但 θ \theta θ(维度)分块后是不均匀的,如下图
在这里插入图片描述
网上找到一篇博客介绍了两种均分方法:正多面体(柏拉图体regular polyhedron)、Hierarchical Equal Area isoLatitude Pixelization(这个方法甚至专门有个c++库
在这里插入图片描述在这里插入图片描述
但是这两种方法感觉在原理和实现上都很复杂,于是经过一番搜寻找到了论文16年的一篇论文《A new method to subdivide a spherical surface into equal-area cells》

方法

这篇论文的方法跟开头介绍的错误分法都是从经纬度( θ \theta θ ? \phi ?)下手,但它并不是均分。主要步骤分两步:

  • 首先将纬度划分成 x x x
    • 相邻块之间的宽度不完全一样,但是大致相同,而且整个划分关于赤道对称
  • 将每一个纬度带 i ( i = 1 , 2 , . . . , x ) i(i=1,2,...,x) i(i=1,2,...,x),均分成 y i y_i yi?块。
    • 不同纬度带划分的块数不一样。纬度越高块数越少,赤道附近的块接近正方形
    • 同样关于赤道对称
    • 要求划分完成后每一块的面积相等

划分的方法论文中并没有给,只给了将球面均分成46、130、406块的划分方式
在这里插入图片描述
在这里插入图片描述
由于我手边工作的需要,这些划分数量太多了,我就自己手推了 x = 4 x=4 x=4 x = 5 x=5 x=5的划分方式,而且我并没有要求“赤道附近的块接近正方形”

x = 4 x=4 x=4的划分方式

  • 因为关于赤道对称,上半球有两个纬度带,最高纬度带对应角度为 θ \theta θ,第二个为 π / 2 ? θ \pi/2-\theta π/2?θ
  • 最高纬度带的面积可以用球冠面积公式得到
    S 1 = 2 π r h = 2 π r ( 1 ? c o s θ ) r = 2 π r 2 ( 1 ? c o s θ ) S_1=2\pi rh=2\pi r (1-cos\theta)r=2\pi r^2 (1-cos\theta) S1?=2πrh=2πr(1?cosθ)r=2πr2(1?cosθ)
  • 根据半球面积可以计算得到第二个纬度带的面积
    S 2 = S 半 球 ? S 1 = 2 π r 2 ? 2 π r 2 ( 1 ? c o s θ ) = 2 π r 2 c o s θ S_2 = S_{半球}-S_1 = 2\pi r^2 - 2\pi r^2 (1-cos\theta) =2 \pi r^2 cos\theta S2?=S??S1?=2πr2?2πr2(1?cosθ)=2πr2cosθ
  • 假设第一个纬度带分 m m m块,第二个纬度带分 n n n块,则要求
    2 π r 2 ( 1 ? c o s θ ) m = 2 π r 2 c o s θ n ( 1 ? c o s θ ) c o s θ = m n \frac{2\pi r^2 (1-cos\theta)}{m}=\frac{2\pi r^2 cos\theta }{n}\\ \frac{(1-cos\theta)}{cos\theta }=\frac{m}{n} m2πr2(1?cosθ)?=n2πr2cosθ?cosθ(1?cosθ)?=nm?
  • (可选)如果想要让赤道附近的块尽量接近正方形,我们可以大致估算一下 n n n的范围
    • 赤道附近的每个块的高度(纬度带的宽度)为 h = r ? ( π / 2 ? θ ) h=r*(\pi/2-\theta) h=r?(π/2?θ)
    • 赤道附近的纬度带分 n n n块,则我们想要上下边的长度尽量接近高度,即
      l 上 = 2 π r s i n θ n ≈ r ? ( π / 2 ? θ ) → n = 2 π s i n θ π / 2 ? θ l 下 = 2 π r n ≈ r ? ( π / 2 ? θ ) → n = 2 π π / 2 ? θ l_{上}=\frac{2\pi r sin\theta}{n}\approx r*(\pi/2-\theta)\rightarrow n = \frac{2\pi sin\theta}{\pi/2-\theta}\\ l_{下}=\frac{2\pi r }{n} \approx r*(\pi/2-\theta)\rightarrow n = \frac{2\pi}{\pi/2-\theta} l?=n2πrsinθ?r?(π/2?θ)n=π/2?θ2πsinθ?l?=n2πr?r?(π/2?θ)n=π/2?θ2π?
    • 将这两条线画出来可以看到 n n n越大,越接近正方形在这里插入图片描述
  • (可选)如果想要纬度带宽度大致相同,即要求 θ ≈ π / 4 \theta\approx\pi/4 θπ/4,带入之前的公式得
    m n = ( 1 ? c o s θ ) c o s θ ≈ ( 1 ? c o s π / 4 ) c o s π / 4 ≈ 0.414 \frac{m}{n}=\frac{(1-cos\theta)}{cos\theta }\approx \frac{(1-cos\pi/4)}{cos\pi/4 }\approx0.414 nm?=cosθ(1?cosθ)?cosπ/4(1?cosπ/4)?0.414
  • 接下来只要按照想要的划分方式给 m m m n n n赋整数,就能求解 θ \theta θ例如
    • m = 2 , n = 3 , θ = 53.130 ° m=2, n=3, \theta=53.130\degree m=2,n=3,θ=53.130°
    • m = 3 , n = 4 , θ = 55.150 ° m=3, n=4, \theta=55.150\degree m=3,n=4,θ=55.150°
    • m = 3 , n = 5 , θ = 51.318 ° m=3, n=5, \theta=51.318\degree m=3,n=5,θ=51.318°
    • m = 4 , n = 5 , θ = 56.217 ° m=4, n=5, \theta=56.217\degree m=4,n=5,θ=56.217°
    • m = 3 , n = 6 , θ = 48.190 ° m=3, n=6, \theta=48.190\degree m=3,n=6,θ=48.190°
    • m = 3 , n = 7 , θ = 45.573 ° m=3, n=7, \theta=45.573\degree m=3,n=7,θ=45.573°
Total CellCellsLatitudinalLongitudinal
102
3
3
2
0-53.13°
53.13°-90°
90°-126.87°
126.87°-180°
180°
120°
120°
180°
143
4
4
3
0-55.15°
55.15°-90°
90°-124.85°
124.85°-180°
120°
90°
90°
120°
184
5
5
4
0-56.22°
56.22°-90°
90°-123.78°
123.78°-180°
90°
72°
72°
90°
203
7
7
3
0-45.573° / 0 - 0.7954
45.573°-90° / 0.7954 - 1.5708
90°-134.427° / 1.5708 - 2.3462
134.427°-180° / 2.3462 - 3.1416
120° / 2.0944
51.43° / 0.8976
51.43° / 0.8976
120° / 2.0944

x = 5 x=5 x=5的划分方式

  • 虽然 x = 5 x=5 x=5为奇数,但是因为关于赤道对称,这里算上半球有2.5个纬度带,即第三个纬度带只算一半。三个纬度带从高到底对应的角度分别为 θ , ? , π / 2 ? θ ? ? \theta, \phi, \pi/2-\theta-\phi θ,?,π/2?θ??
  • 最高纬度带的面积可以用球冠面积公式得到
    S 1 = 2 π r h = 2 π r ( 1 ? c o s θ ) r = 2 π r 2 ( 1 ? c o s θ ) S_1=2\pi rh=2\pi r (1-cos\theta)r=2\pi r^2 (1-cos\theta) S1?=2πrh=2πr(1?cosθ)r=2πr2(1?cosθ)
  • 根据球冠面积同样可以计算得到第二个纬度带的面积
    S 2 = 2 π r 2 ( 1 ? c o s ( θ + ? ) ) ? 2 π r 2 ( 1 ? c o s θ ) = 2 π r 2 ( c o s θ ? c o s ( θ + ? ) ) S_2 = 2\pi r^2(1-cos(\theta+\phi)) - 2\pi r^2 (1-cos\theta) =2 \pi r^2 ( cos\theta - cos(\theta+\phi)) S2?=2πr2(1?cos(θ+?))?2πr2(1?cosθ)=2πr2(cosθ?cos(θ+?))
  • 根据半球面积可以计算得到最后半个纬度带的面积
    S 2.5 = S 半 球 ? ( S 1 + S 2 ) = 2 π r 2 ? 2 π r 2 ( 1 ? c o s ( θ + ? ) ) = 2 π r 2 c o s ( θ + ? ) S_{2.5} = S_{半球}-(S_1+S_2) = 2\pi r^2 - 2\pi r^2(1-cos(\theta+\phi)) =2 \pi r^2 cos(\theta+\phi) S2.5?=S??(S1?+S2?)=2πr2?2πr2(1?cos(θ+?))=2πr2cos(θ+?)
  • 假设第一个纬度带分 m m m块,第二个纬度带分 n n n块,最后半个纬度带分 o o o块,则要求
    2 π r 2 ( 1 ? c o s θ ) m = 2 π r 2 ( c o s θ ? c o s ( θ + ? ) ) n = 2 ? 2 π r 2 c o s ( θ + ? ) o 1 ? c o s θ m = c o s θ ? c o s ( θ + ? ) n = 2 c o s ( θ + ? ) o \frac{2\pi r^2 (1-cos\theta)}{m}=\frac{2 \pi r^2 ( cos\theta - cos(\theta+\phi))}{n}=2*\frac{2 \pi r^2 cos(\theta+\phi)}{o}\\ \frac{1-cos\theta}{m}=\frac{ cos\theta - cos(\theta+\phi)}{n}=\frac{2cos(\theta+\phi)}{o} m2πr2(1?cosθ)?=n2πr2(cosθ?cos(θ+?))?=2?o2πr2cos(θ+?)?m1?cosθ?=ncosθ?cos(θ+?)?=o2cos(θ+?)?
  • 接下来只要按照想要的划分方式给 m m m n n n o o o赋整数,就能求解 θ \theta θ ? \phi ?例如
    • m = 3 , n = 4 , o = 5 , θ = 46.826 ° , ? = 27.916 ° m=3, n=4, o=5, \theta=46.826\degree, \phi=27.916\degree m=3,n=4,o=5,θ=46.826°,?=27.916°
    • m = 3 , n = 4 , o = 6 , θ = 45.573 ° , ? = 26.969 ° m=3, n=4, o=6, \theta=45.573\degree, \phi=26.969\degree m=3,n=4,o=6,θ=45.573°,?=26.969°
    • m = 4 , n = 5 , o = 6 , θ = 48.190 ° , ? = 27.333 ° m=4, n=5, o=6, \theta=48.190\degree, \phi=27.333\degree m=4,n=5,o=6,θ=48.190°,?=27.333°
Total CellCellsLatitudinalLongitudinal
193
4
5
4
3
0-46.826°
46.826°-74.743°
74.743°-105.257°
105.257°- 133.174°
133.174°-180°
120°
90°
72°
90°
120°
244
5
6
5
4
0-48.190°
48.190°-75.522°
75.522°-104.478°
104.478°- 131.810°
131.810°-180°
90°
72°
60°
72°
90°

c++代码

这里以“统计球形点云落在每个块中的数量”为例,划分方式为 x = 4 , m = 3 , n = 7 x=4, m=3, n=7 x=4,m=3,n=7

/**
 * 统计球形点云落在每个块中的数量
 * @param[in] points n*3的矩阵,存储三维点云
 * @param[out] nums  统计结果,存储顺序北极->南极 & 经度0°->360°
 */
void ClassifyCentroidVector(const Eigen::MatrixXf &points, vector<int> &nums) {
  direct.resize(20);
  Eigen::Vector4f block_theta(0., 0.7954, 1.5708, 2.3462);
  Eigen::Vector4f block_phi(2.0944, 0.8976, 0.8976, 2.0944);
  Eigen::Vector4i offset(0, 3, 10, 17);
  for (int k = 0; k < points.rows(); k++) {
    //笛卡尔坐标系转换为球坐标系
    const float x = points(k, 0), y = points(k, 1), z = points(k, 2);
    float r = sqrt(x * x + y * y + z * z);
    float theta = acos(z / r);
    float fai = atan2(y, x) + M_PI; // 取值范围0-2π
    
    int coord_theta = -1;
    for(int i = 0; i < block_theta.size(); i++)
      if(theta > block_theta(i)){
        coord_theta = i;
        break;
      }
    assert(coord_theta != -1);
    int coord_phi = int(fai/block_phi(coord_theta));
    direct[offset(coord_theta)+coord_phi] += 1;
  }
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-06-26 16:45:42  更:2022-06-26 16:46:51 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/12 13:30:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码