3.4 点(Points

点是二维或三维空间中的零维位置(zero-dimensional location)。 pbrt 中的 Point2Point3 类以直观的方式表示点:使用相对于坐标系的 \( x \) 、 \( y \) 、 \( z \) (在三维中)坐标。尽管向量也使用相同的表示法,但点表示位置而向量表示方向这一性质导致了它们在处理方式上存在许多重要差异。文本中用 \( \text{p} \) 表示点。

在本节中,我们将继续仅在此处包含 Point3 类的三维空间点方法的实现。

/** Point3 定义 */
template <typename T>
class Point3 : public Tuple3<Point3, T> {
  public:
    /** Point3 公有方法 */
};

与向量一样,为常用的点类型使用较短的类型名称是有帮助的。

/** Point3* 定义 */
using Point3f = Point3<Float>;
using Point3i = Point3<int>;

将一种元素类型的点(如 Point3f )转换为另一种元素类型的点(如 Point3i )以及将一个点转换为具有不同基础元素类型的向量是非常有用的。以下构造函数和转换运算符提供了这些转换。两者都需要显式转换,以便在源代码中清楚地表明它们的使用。

/** Point3 公有方法 */
template <typename U>
explicit Point3(Point3<U> p)
    : Tuple3<pbrt::Point3, T>(T(p.x), T(p.y), T(p.z)) {}
template <typename U>
explicit Point3(Vector3<U> v)
    : Tuple3<pbrt::Point3, T>(T(v.x), T(v.y), T(v.z)) {}

有某些 Point3 方法可以返回或接受 Vector3 。例如,可以将一个点与向量相加,从而在给定方向上偏移该点以获得一个新点。类似的方法(未在文中包含)也允许从一个点中减去一个向量。

/** Point3 公有方法 */
template <typename U>
auto operator+(Vector3<U> v) const -> Point3<decltype(T{} + U{})> {
    return {x + v.x, y + v.y, z + v.z};
}
template <typename U>
Point3<T> &operator+=(Vector3<U> v) {
    x += v.x;    y += v.y;    z += v.z;
    return *this;
}

或者,可以用一个点减去另一个点,从而获得它们之间的向量,如图 3.7 所示。

图 3.7:获取两点之间的向量。 向量 \( \mathbf{v} = \text{p}' - \text{p} \) 是通过对点 \( \text{p}' \) 和 \( \text{p} \) 进行分量减法得到的。

/** Point3 公有方法 */
template <typename U>
auto operator-(Point3<U> p) const -> Vector3<decltype(T{} - U{})> {
    return {x - p.x, y - p.y, z - p.z};
}

两个点之间的距离可以通过相减来计算它们之间的向量,然后计算该向量的长度。请注意,我们可以直接使用 auto 作为返回类型,并让其根据 Length() 的返回类型进行设置;没有必要使用 TupleLength 类型特征来查找该类型。

/** Point3 内联函数 */
template <typename T>
auto Distance(Point3<T> p1, Point3<T> p2) { return Length(p1 - p2); }

两个点之间的平方距离可以使用 LengthSquared() 进行类似的计算。

/** Point3 内联函数 */
template <typename T>
auto DistanceSquared(Point3<T> p1, Point3<T> p2) {
    return LengthSquared(p1 - p2);
}