点在球体内当且仅当(x−cx)²+(y−cy)²+(z−cz)²≤r²,通过比较平方距离与半径平方避免开方运算,提升效率并减少浮点误差。
直接看球心到点的距离是否小于等于半径。这是最可靠、最高效的方法,不需要任何额外库或几何运算。
关键点在于:三维欧氏距离的平方比开方更快,也避免浮点误差和 sqrt 调用开销。所以实际比较 dx*dx + dy*dy + dz*dz 和 r*r 即可。
(cx, cy, cz),半径为 r,待测点为 (x, y, z)
dist_sq = (x - cx)*(x - cx) + (y - cy)*(y - cy) + (z - cz)*(z - cz)
dist_sq —— 注意用 <code> 包含球面本身
== 和 的陷阱
用 float 或 double 表示坐标时,直接用 == 判断是否“刚好在球面上”几乎总会失败。哪怕数学上相等,计算过程中的舍入误差会让 dist_sq 略大于或略小于 r*r。
dist_sq == r * r 来判断球面abs(dist_sq - r*r) 判定表面,<code>dist_sq 判定严格内部
double 且坐标在 [-1000, 1000] 范围,1e-9 通常够用;若坐标很大(如 1e6),eps 也要按比例放大std::hypot 会更安全吗?不会,而且更慢。虽然 std::hypot(x,y,z)(C++17 起支持三参数)能防止中间结果溢出,但球体判断根本不需要真实距离值——只需要和 r 比较,而 r*r 是已知常量。直接算平方和既快又稳定。
立即学习“C++免费学习笔记(深入)”;
std::hypot 内部做了多步缩放和 sqrt,纯属浪费hypot
别把球体参数硬编码成全局变量,也别每次传 7 个独立参数。推荐用结构体封装球体,并重载 operator() 或写清晰命名的函数。
struct Sphere { double cx, cy, cz, r; };
bool is_inside(const Sphere& s, double x, double y, double z)
const Sphere* —— 指针带来空指针风险,且无必要r*r 存在 Sphere 里预计算,省去每次乘法最易被忽略的是:球体半径为负时行为未定义。实际代码中应加断言或提前返回 false,否则 r*r 仍是正数,逻辑看似正常但语义错误。