轻松处理任意维度平面
Easily Dealing with Any-Dimensional Planes

原始链接: https://gpfault.net/posts/hyperplanes.html

## 高效平面表示 本文详细介绍了一种简洁高效的代码表示平面(以及通常意义上的N维空间中的超平面)的方法。传统上,平面由法向量和平面内的一个点来定义。然而,作者证明仅存储法向量(`n`)和法向量与平面上任意一点的内积(`dot(n, o)`)就足够了。 这个`dot(n, o)`值表示原点到平面沿法向量方向的距离。这允许快速计算:从*任何*点到平面的距离都可以通过一个内积来找到。确定两个平面是否平行简化为检查它们的法向量的叉积是否为零。 该表示使用模板进行泛化,从而易于应用于二维直线。这种方法简化了平面操作,并通过将变换应用于法向量和平面上派生的原点来简化变换。

这个Hacker News讨论围绕一个资源([https://gpfault.net/](https://gpfault.net/)),详细介绍了如何轻松处理任意维度的平面。一个关键点是点可以被优雅地定义为超平面的交点。 对话强调了当超平面平行时,这种方法自然地包含了“无穷远点”的概念,从而保持了运算符行为的一致性。这基于**射影几何代数**([https://projectivegeometricalgebra.org/projgeomalg.pdf](https://projectivegeometricalgebra.org/projgeomalg.pdf)),它为这些计算提供了一个框架。 此外,讨论还提到了与**保形几何**的联系——将平面表示为中心在无穷远处的球体——并指出Eigen库使用了类似的表示(ax^2 + bx + c + d = 0 在3D中)。本质上,这是一种强大且统一的方法,可以跨不同维度处理几何图元。
相关文章

原文

published on Dec 24 2025

Writing the post from yesterday reminded me of another well-known representation for a geometric primitive, the plane, that makes code pleasing to look at and simple.

Planes

In general, a "plane" is an n-1 dimensional sub-space of an n-dimensional space that is flat. There's a mathematically rigorous definition of what "flat" really means, but intuitive understanding is sufficient for the purposes of this explanation.

To fully specify a plane, we only need two things: the plane's normal vector (which we'll call `n`) and any point within the plane (we'll refer to it as `o`). But we don't actually need to store both the point and the vector in our representation.

By definition, the plane's normal vector should be orthogonal to any vector within the plane (their dot product has to be 0). Therefore, if a point `p` belongs to the plane, the following must be true:


  
  dot(p - o, n) = 0 
  
  

Let's for now assume the 3D case and expand the above expression to individual coordinates (everything works exactly the same for N-dimensional case). We'll get:


  
  (p_x - o_x) * n_x + (p_y - o_y) * n_y + (p_z - o_z) * n_z = 0
  
  // which can be rewritten as 
  
   p_x * n_x + p_y * n_y + p_z * n_z - (o_x * n_x + o_y * n_y + o_z * n_z) = 0
   
   // or otherwise:
   
   dot(p, n) - dot(o, n) = 0
  
  

Turns out that in order to determine whether a point lies on a plane, we actually need just the normal vector and the scalar value `dot(o, n)`. If we recall that the dot product is the length of the projection of one vector onto the other, it's easy to see that `dot(o, n)` is simply the distance from the coordinate space origin to the plane along the direction of the normal vector.

This suggests the following representation:


  
  template <class ScalarT=float, unsigned N = 3>
  using hyperplane = vec<ScalarT, N+1> 
  
  

Assuming that your plane's normal vector is already of unit length, it's really easy to make a new plane (if the normal isn't unit length, you'd have to normalize it first):


  
  template<class ScalarT, unsigned N>
  hyperplane<ScalarT, N> make_hyperplane_fast(vec<ScalarT, N> normal, vec<ScalarT, N> origin) {
    return hyperplane<ScalarT, N> {normal, -dot(normal, origin)};
  }
  
  

Operations With Planes

We used `-dot(normal, origin)` above because this helps us to find the distance from any given point to the plane using a single dot product between N+1 dimensional vectors (assuming the N+1-th coordinate of the point is 1.0):


  
  template<class ScalarT, unsigned N>
  ScalarT point_to_hyperplane_dist(const hyperplane<ScalarT, N>& pl, vec<ScalarT, N> pt) noexcept {
    return dot(pl, vec<ScalarT, N + 1> {pt, (ScalarT)1});
  }
  
  

Checking if two planes are parallel is also trivially easy: we only need to compute the cross product between the normal vectors - it should be zero if and only if the planes are parallel. If the planes are parallel, the distance between them can be found by subtracting the distances of the planes from the coordinate space origin.

If we multiply the normal vector by `dot(o, n)`, we will get the coordinates of a point that lies on the plane. Using this "origin point", we can easily transform the plane from one coordinate system to another: simply apply your transform to both the origin point and the normal, and construct a new plane from the results. Of course, the usual caveats about transforming normal vectors apply.

Generalization

This logic generalizes to higher dimensions (4,5,...-dimensional hyperplanes), but it also generalizes "down" to the 2D case. A "hyperplane" in 2D is just a line, and everything we stated above applies just as well to lines in 2D space - all you have to do is drop N from 3 to 2.


Like this post? Follow me on bluesky for more!

联系我们 contact @ memedata.com