## Expand description

Almost all nontrivial graphics programs are built on a foundation of geometric classes. These classes represent mathematical constructs like points, vectors, and rays.

## Points

A **point** is a zero-dimensional location in 2D or 3D space. The
**Point2** and **Point3** classes in **pbrt** represent points in
the obvious way: using x, y, z (in 3D) coordinates with respect to
a coordinate system. Although the same representation is used for
vectors, the fact that a point represents a position whereas a
vector represents a direction leads to a number of important
differences in how they are treated.

```
use rs_pbrt::core::geometry::{Point3i, Point3f};
fn main() {
let int_origin = Point3i { x: 0, y: 0, z: 0 };
let float_origin = Point3f {
x: 0.0,
y: 0.0,
z: 0.0,
};
println!("int {:?}", int_origin);
println!("float {:?}", float_origin);
}
```

## Vectors

**pbrt** provides both 2D and 3D **vector** classes. Both are
parameterized by the type of the underlying vector element, thus
making it easy to instantiate vectors of both integer and
floating-point types.

```
use rs_pbrt::core::geometry::{Vector3i, Vector3f};
fn main() {
let int_null = Vector3i { x: 0, y: 0, z: 0 };
let float_null = Vector3f {
x: 0.0,
y: 0.0,
z: 0.0,
};
println!("int {:?}", int_null);
println!("float {:?}", float_null);
}
```

## Normals

A surface **normal** (or just normal) is a vector that is
perpendicular to a surface at a particular position. It can be
defined as the cross product of any two nonparallel vectors that
are tangent to the surface at a point. Although normals are
superficially similar to vectors, it is important to distinguish
between the two of them: because normals are defined in terms of
their relationship to a particular surface, they behave
differently than vectors in some situations, particularly when
applying transformations.

```
use rs_pbrt::core::geometry::Normal3f;
fn main() {
let float_null = Normal3f {
x: 0.0,
y: 0.0,
z: 0.0,
};
println!("float {:?}", float_null);
}
```

## Rays

A **ray** is a semi-infinite line specified by its origin and
direction. **pbrt** represents a **Ray** with a **Point3f** for
the origin and a **Vector3f** for the direction. We only need rays
with floating-point origins and directions, so **Ray** isn’t a
template class parameterized by an arbitrary type, as points,
vectors, and normals were.

```
use rs_pbrt::core::geometry::{Ray, Point3f, Vector3f};
use std::cell::Cell;
fn main() {
let origin = Point3f {
x: -5.5,
y: 2.75,
z: 0.0,
};
let direction = Vector3f {
x: 1.0,
y: -8.75,
z: 2.25,
};
let ray = Ray {
o: origin,
d: direction,
t_max: Cell::new(std::f32::INFINITY),
time: 0.0,
medium: None,
differential: None,
};
}
```

### RayDifferentials

**RayDifferential** is a subclass of **Ray** that contains
additional information about two auxiliary rays. These extra rays
represent camera rays offset by one sample in the *x* and *y*
direction from the main ray on the film plane. By determining the
area that these three rays project on an object being shaded, the
**Texture** can estimate an area to average over for proper
antialiasing.

In Rust we don’t have inheritance, therefore we use an
**Option** in the

**Ray**struct, which means the additional information can be present (or not).

## Bounding Boxes

Many parts of the system operate on axis-aligned regions of
space. For example, multi-threading in **pbrt** is implemented by
subdividing the image into rectangular tiles that can be processed
independently, and the bounding volume hierarchy uses 3D boxes to
bound geometric primitives in the scene. The **Bounds2** and
**Bounds3** template classes are used to represent the extent of
these sort of regions. Both are parameterized by a type T that is
used to represent the coordinates of its extents.

```
use rs_pbrt::core::geometry::{Bounds3i, Bounds3f, Point3i, Point3f};
fn main() {
let int_origin = Point3i { x: 0, y: 0, z: 0 };
let int_xyz111 = Point3i { x: 1, y: 1, z: 1 };
let float_origin = Point3f {
x: 0.0,
y: 0.0,
z: 0.0,
};
let float_xyz111 = Point3f {
x: 1.0,
y: 1.0,
z: 1.0,
};
let int_unit_cube = Bounds3i {
p_min: int_origin,
p_max: int_xyz111,
};
let float_unit_cube = Bounds3f {
p_min: float_origin,
p_max: float_xyz111,
};
println!("int {:?}", int_unit_cube);
println!("float {:?}", float_unit_cube);
}
```

## Structs

An iterator over the variants of Self

An iterator over the variants of Self

An iterator over the variants of Self

## Enums

## Functions

Pads the bounding box by a constant factor in both dimensions.

The intersection of two bounding boxes can be found by computing the maximum of their two respective minimum coordinates and the minimum of their maximum coordinates.

Given a bounding box and a point, the **bnd2_union_pnt2()**
function returns a new bounding box that encompasses that point as
well as the original box.

Pads the bounding box by a constant factor in all dimensions.

Construct a new box that bounds the space encompassed by two other bounding boxes.

Given a bounding box and a point, the **bnd3_union_pnt3()**
function returns a new bounding box that encompasses that point as
well as the original box.

Computes the absolute value of the dot product.

Computes the absolute value of the dot product.

Return normal with the absolute value of each coordinate.

Return normal with the absolute value of each coordinate.

Given a normal and a vector in 3D, the cross product is a vector that is perpendicular to both of them.

Product of the Euclidean magnitudes of a normal (and another normal) and the cosine of the angle between them. A return value of zero means both are orthogonal, a value if one means they are codirectional.

Product of the Euclidean magnitudes of a normal (and another normal) and the cosine of the angle between them. A return value of zero means both are orthogonal, a value if one means they are codirectional.

Product of the Euclidean magnitudes of a normal (and a vector) and the cosine of the angle between them. A return value of zero means both are orthogonal, a value if one means they are codirectional.

Product of the Euclidean magnitudes of a normal (and a vector) and the cosine of the angle between them. A return value of zero means both are orthogonal, a value if one means they are codirectional.

Flip a surface normal so that it lies in the same hemisphere as a given normal.

Flip a surface normal so that it lies in the same hemisphere as a given vector.

Apply ceil operation component-wise.

Apply floor operation component-wise.

Determine if a given point is inside the bounding box.

Determine if a given point is inside the bounding box.

Is a 2D point inside a 2D bound?

Is a 2D point inside a 2D bound?

Apply std::cmp::max operation component-wise.

Apply std::cmp::min operation component-wise.

Apply abs operation component-wise.

Apply ceil operation component-wise.

The distance squared between two points is the length of the vector between them squared.

The distance between two points is the length of the vector between them.

Apply floor operation component-wise.

Determine if a given point is inside the bounding box.

Interpolate linearly between two provided points.

When tracing spawned rays leaving the intersection point p, we offset their origins enough to ensure that they are past the boundary of the error box and thus won’t incorrectly re-intersect the surface.

Permute the coordinate values according to the povided permutation.

Permute the coordinate values according to the povided permutation.

Is a 3D point inside a 3D bound?

Is a 3D point inside a 3D bound?

Calculate appropriate direction vector from two angles.

Take three basis vectors representing the x, y, and z axes and return the appropriate direction vector with respect to the coordinate frame defined by them.

Conversion of a direction to spherical angles.

Conversion of a direction to spherical angles. Note that
**spherical_theta()** assumes that the vector **v** has been
normalized before being passed in.

Product of the Euclidean magnitudes of the two vectors and the cosine of the angle between them. A return value of zero means both vectors are orthogonal, a value if one means they are codirectional.

Product of the Euclidean magnitudes of the two vectors and the cosine of the angle between them. A return value of zero means both vectors are orthogonal, a value if one means they are codirectional.

Computes the absolute value of the dot product.

Computes the absolute value of the dot product.

Computes the absolute value of the dot product.

Computes the absolute value of the dot product.

Construct a local coordinate system given only a single 3D vector.

Given a vectors and a normal in 3D, the cross product is a vector that is perpendicular to both of them.

Given two vectors in 3D, the cross product is a vector that is perpendicular to both of them.

Product of the Euclidean magnitudes of a vector (and a normal) and the cosine of the angle between them. A return value of zero means both are orthogonal, a value if one means they are codirectional.

Product of the Euclidean magnitudes of a vector (and a normal) and the cosine of the angle between them. A return value of zero means both are orthogonal, a value if one means they are codirectional.

Product of the Euclidean magnitudes of the two vectors and the cosine of the angle between them. A return value of zero means both vectors are orthogonal, a value if one means they are codirectional.

Return the largest coordinate value.

Return the largest coordinate value.

Return the index of the component with the largest value.

Return the index of the component with the largest value.

Permute the coordinate values according to the povided permutation.

Permute the coordinate values according to the povided permutation.