管理3D坐标以在星系中导航

0.1.0 2022-01-22 21:11 UTC

This package is auto-updated.

Last update: 2024-09-23 04:08:03 UTC


README

介绍

此库提供在3D系统中表示和操作地理对象的功能。

它最初是为了表示星系中的多个天体而构建的。

它需要PHP 8.1来使用枚举。

表示坐标的类

这些类允许在不同的3D坐标系中表示一个点。

每个类都允许转换到其他坐标系。

Point3D

表示一个3D点,由(x, y, z)笛卡尔坐标标识。

PointSpherical

表示一个3D点,由(r, θ, φ)球坐标标识,如物理学中使用的,遵循ISO 80000-2:2019约定

  • r表示径向距离
  • θ表示倾角
  • φ表示方位角

此类可以使用θ代替倾角表示高度,但在将其转换为圆柱或笛卡尔坐标之前,需要将θ切换回倾角

  $point->theta += M_PI_2
  $cylindricalPoint = $point->toCylindrical()

PointPolarZ

表示一个3D点,由(ρ, φ, z)圆柱坐标标识

  • (ρ, φ)表示类似于2D的极坐标
    • ρ表示径向距离
    • φ表示方位角
  • z表示高度或轴向坐标

此表示法遵循ISO 31-11:1992标准。

表示坐标的替代方案

Octocube

将3D坐标映射到一个立方体,分为8个部分。

每个部分称为扇区,编号为1到8

   _____ _______
  /  5  /  6  / |
 /- - -/- - -/  |
/_____/____ / | |
|     |     | |/|
|  7  |  8  | / | 2
|_____|_____|/| |
|     |     | |/
|  3  |  4  | /
|_____|_____|/

点(0, 0, 0)位于立方体中心。

*使用八面体来表示八分体

正如二维平面可以划分为象限一样,三维空间可以划分为八分体。请参阅https://en.wikipedia.org/wiki/Octant_(solid_geometry)

要获取八分体的符号列表,而不是其编号,可以使用方法getBaseVector

获取离中心更远的点

如果您有一个点P,并想获取另一个点,该点保证会离中心更远,并且永远不会达到另一个八分体(即该点将属于同一个八分体),则可以使用

$point = new Point3D(-7, 4, -5);
$sector = Octocube::getSectorFromPoint3D($point);
echo "Point belongs to sector C", $sector;

$vector = Octocube::getBaseVector($sector);
$point->translate(...$vector);
echo $point;

此代码将输出

Point belongs to sector C1
xyz: [-8.00, 5.00, -6.00]

此技术在地图构建器中已过测试,在需要无限期增加构建内容的情况下。

辅助类

数学

方法

  • equals(a, b, Ɛ):使用公式|a - b| < Ɛ比较两个浮点数ab
  • normalizeAngle(a):将角度a归一化到[0, 2π[区间。
  • normalizeAngle(a, λ):将角度a归一化到[λ, λ + 2π[区间。

常量

  • M_EPSILON:Ɛ的默认值。

陷阱

不要使用==或===运算符比较浮点数

在比较两个浮点数时,我们的库会注意使用|a - b| < Ɛ,并提供一个Math::equals方法。

在您的代码中,您也需要这样做。例如,您想避免这种场景

$point = new PointSpherical(...);
// Some transformations for $point
if ($point->phi === 0.0) {
   // No inclination
}

您可以使用if (Math::equals($point->phi, 0.0)) {}

三角学和浮点数会产生很大的误差范围

需要非常小心的一种情况是涉及大量的三角学运算。在我们的库中有一个地方特别会发生这种情况:PointSpherical::distance多次将r.r'与余弦和正弦相乘。您的点越远,您乘以的舍入误差就越多,包括由浮点数和cos/sin函数引入的。

此类代码的示例

$point_a = new PointSpherical(116.645456, 2.131662, 1.893856);
$point_b = new PointSpherical(113.703512, 2.165501, -0.726525);
$distance = $point_a->distance($point_b);

此距离有一个10^-5的误差范围。

如果您需要计算距离,使用Point3D可以获得更高的精度。PointPolarZ的距离方法也相当精确。