Struct fj_math::Vector

source ·
#[repr(C)]
pub struct Vector<const D: usize> { pub components: [Scalar; D], }
Expand description

An n-dimensional vector

The dimensionality of the vector is defined by the const generic D parameter.

Fields§

§components: [Scalar; D]

The vector components

Implementations§

Construct a Vector from f64 components

Panics

Panics, if the components can not be converted to Scalar. See Scalar::from_f64, which this method uses internally.

Examples found in repository?
src/vector.rs (line 34)
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
    pub fn from_na(vector: nalgebra::SVector<f64, D>) -> Self {
        Self::from_components_f64(vector.into())
    }

    /// Convert the vector into an nalgebra vector
    pub fn to_na(self) -> nalgebra::SVector<f64, D> {
        self.components.map(Scalar::into_f64).into()
    }

    /// Convert to a 1-dimensional vector
    pub fn to_t(self) -> Vector<1> {
        Vector {
            components: [self.components[0]],
        }
    }

    /// Convert the vector into a 2-dimensional vector
    ///
    /// If the vector is 0-, or 1-dimensional, the missing components will be
    /// initialized to zero.
    ///
    /// If the vector has higher dimensionality than two, the superfluous
    /// components will be discarded.
    pub fn to_uv(self) -> Vector<2> {
        let zero = Scalar::ZERO;

        let components = match self.components.as_slice() {
            [] => [zero, zero],
            &[t] => [t, zero],
            &[u, v, ..] => [u, v],
        };

        Vector { components }
    }

    /// Convert the vector into a 3-dimensional vector
    ///
    /// If the vector is 0-, 1-, or 2-dimensional, the missing components will
    /// be initialized to zero.
    ///
    /// If the vector has higher dimensionality than three, the superfluous
    /// components will be discarded.
    pub fn to_xyz(self) -> Vector<3> {
        let zero = Scalar::ZERO;

        let components = match self.components.as_slice() {
            [] => [zero, zero, zero],
            &[t] => [t, zero, zero],
            &[u, v] => [u, v, zero],
            &[x, y, z, ..] => [x, y, z],
        };

        Vector { components }
    }

    /// Compute the magnitude of the vector
    pub fn magnitude(&self) -> Scalar {
        self.to_na().magnitude().into()
    }

    /// Compute a normalized version of the vector
    pub fn normalize(&self) -> Self {
        self.to_na().normalize().into()
    }

    /// Compute the dot product with another vector
    pub fn dot(&self, other: &Self) -> Scalar {
        self.to_na().dot(&other.to_na()).into()
    }

    /// Compute the scalar project of this vector onto another
    pub fn scalar_projection_onto(&self, other: &Self) -> Scalar {
        if other.magnitude() == Scalar::ZERO {
            return Scalar::ZERO;
        }

        self.dot(&other.normalize())
    }
}

impl Vector<1> {
    /// Construct a `Vector` that represents the t-axis
    pub fn unit_t() -> Self {
        Self::from([1.])
    }
}

impl Vector<2> {
    /// Construct a `Vector` that represents the u-axis
    pub fn unit_u() -> Self {
        Self::from([1., 0.])
    }

    /// Construct a `Vector` that represents the v-axis
    pub fn unit_v() -> Self {
        Self::from([0., 1.])
    }

    /// Compute the 2D cross product with another vector
    pub fn cross2d(&self, other: &Self) -> Scalar {
        (self.u * other.v) - (self.v * other.u)
    }

    /// Determine whether this vector is between two other vectors
    pub fn is_between(&self, others: [impl Into<Self>; 2]) -> bool {
        let [a, b] = others.map(Into::into);
        a.cross2d(self) * b.cross2d(self) < Scalar::ZERO
    }
}

impl Vector<3> {
    /// Construct a `Vector` that represents the x-axis
    pub fn unit_x() -> Self {
        Self::from([1., 0., 0.])
    }

    /// Construct a `Vector` that represents the y-axis
    pub fn unit_y() -> Self {
        Self::from([0., 1., 0.])
    }

    /// Construct a `Vector` that represents the z-axis
    pub fn unit_z() -> Self {
        Self::from([0., 0., 1.])
    }

    /// Compute the cross product with another vector
    pub fn cross(&self, other: &Self) -> Self {
        self.to_na().cross(&other.to_na()).into()
    }

    /// Construct a new vector from this vector's x and y components
    pub fn xy(&self) -> Vector<2> {
        Vector::from([self.x, self.y])
    }
}

impl ops::Deref for Vector<1> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        let ptr = self.components.as_ptr() as *const Self::Target;

        // This is sound. We've created this pointer from a valid instance, that
        // has the same size and layout as the target.
        unsafe { &*ptr }
    }
}

impl ops::Deref for Vector<2> {
    type Target = Uv;

    fn deref(&self) -> &Self::Target {
        let ptr = self.components.as_ptr() as *const Self::Target;

        // This is sound. We've created this pointer from a valid instance, that
        // has the same size and layout as the target.
        unsafe { &*ptr }
    }
}

impl ops::Deref for Vector<3> {
    type Target = Xyz;

    fn deref(&self) -> &Self::Target {
        let ptr = self.components.as_ptr() as *const Self::Target;

        // This is sound. We've created this pointer from a valid instance, that
        // has the same size and layout as the target.
        unsafe { &*ptr }
    }
}

impl ops::DerefMut for Vector<1> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        let ptr = self.components.as_mut_ptr() as *mut Self::Target;

        // This is sound. We've created this pointer from a valid instance, that
        // has the same size and layout as the target.
        unsafe { &mut *ptr }
    }
}

impl ops::DerefMut for Vector<2> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        let ptr = self.components.as_mut_ptr() as *mut Self::Target;

        // This is sound. We've created this pointer from a valid instance, that
        // has the same size and layout as the target.
        unsafe { &mut *ptr }
    }
}

impl ops::DerefMut for Vector<3> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        let ptr = self.components.as_mut_ptr() as *mut Self::Target;

        // This is sound. We've created this pointer from a valid instance, that
        // has the same size and layout as the target.
        unsafe { &mut *ptr }
    }
}

impl<const D: usize> Default for Vector<D> {
    fn default() -> Self {
        let components = [Scalar::default(); D];
        Self { components }
    }
}

impl<const D: usize> From<[Scalar; D]> for Vector<D> {
    fn from(components: [Scalar; D]) -> Self {
        Self { components }
    }
}

impl<const D: usize> From<[f64; D]> for Vector<D> {
    fn from(components: [f64; D]) -> Self {
        Self::from_components_f64(components)
    }

Construct a Vector from an nalgebra vector

Examples found in repository?
src/vector.rs (line 257)
256
257
258
    fn from(vector: nalgebra::SVector<f64, D>) -> Self {
        Self::from_na(vector)
    }

Convert the vector into an nalgebra vector

Examples found in repository?
src/vector.rs (line 90)
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
    pub fn magnitude(&self) -> Scalar {
        self.to_na().magnitude().into()
    }

    /// Compute a normalized version of the vector
    pub fn normalize(&self) -> Self {
        self.to_na().normalize().into()
    }

    /// Compute the dot product with another vector
    pub fn dot(&self, other: &Self) -> Scalar {
        self.to_na().dot(&other.to_na()).into()
    }

    /// Compute the scalar project of this vector onto another
    pub fn scalar_projection_onto(&self, other: &Self) -> Scalar {
        if other.magnitude() == Scalar::ZERO {
            return Scalar::ZERO;
        }

        self.dot(&other.normalize())
    }
}

impl Vector<1> {
    /// Construct a `Vector` that represents the t-axis
    pub fn unit_t() -> Self {
        Self::from([1.])
    }
}

impl Vector<2> {
    /// Construct a `Vector` that represents the u-axis
    pub fn unit_u() -> Self {
        Self::from([1., 0.])
    }

    /// Construct a `Vector` that represents the v-axis
    pub fn unit_v() -> Self {
        Self::from([0., 1.])
    }

    /// Compute the 2D cross product with another vector
    pub fn cross2d(&self, other: &Self) -> Scalar {
        (self.u * other.v) - (self.v * other.u)
    }

    /// Determine whether this vector is between two other vectors
    pub fn is_between(&self, others: [impl Into<Self>; 2]) -> bool {
        let [a, b] = others.map(Into::into);
        a.cross2d(self) * b.cross2d(self) < Scalar::ZERO
    }
}

impl Vector<3> {
    /// Construct a `Vector` that represents the x-axis
    pub fn unit_x() -> Self {
        Self::from([1., 0., 0.])
    }

    /// Construct a `Vector` that represents the y-axis
    pub fn unit_y() -> Self {
        Self::from([0., 1., 0.])
    }

    /// Construct a `Vector` that represents the z-axis
    pub fn unit_z() -> Self {
        Self::from([0., 0., 1.])
    }

    /// Compute the cross product with another vector
    pub fn cross(&self, other: &Self) -> Self {
        self.to_na().cross(&other.to_na()).into()
    }

    /// Construct a new vector from this vector's x and y components
    pub fn xy(&self) -> Vector<2> {
        Vector::from([self.x, self.y])
    }
}

impl ops::Deref for Vector<1> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        let ptr = self.components.as_ptr() as *const Self::Target;

        // This is sound. We've created this pointer from a valid instance, that
        // has the same size and layout as the target.
        unsafe { &*ptr }
    }
}

impl ops::Deref for Vector<2> {
    type Target = Uv;

    fn deref(&self) -> &Self::Target {
        let ptr = self.components.as_ptr() as *const Self::Target;

        // This is sound. We've created this pointer from a valid instance, that
        // has the same size and layout as the target.
        unsafe { &*ptr }
    }
}

impl ops::Deref for Vector<3> {
    type Target = Xyz;

    fn deref(&self) -> &Self::Target {
        let ptr = self.components.as_ptr() as *const Self::Target;

        // This is sound. We've created this pointer from a valid instance, that
        // has the same size and layout as the target.
        unsafe { &*ptr }
    }
}

impl ops::DerefMut for Vector<1> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        let ptr = self.components.as_mut_ptr() as *mut Self::Target;

        // This is sound. We've created this pointer from a valid instance, that
        // has the same size and layout as the target.
        unsafe { &mut *ptr }
    }
}

impl ops::DerefMut for Vector<2> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        let ptr = self.components.as_mut_ptr() as *mut Self::Target;

        // This is sound. We've created this pointer from a valid instance, that
        // has the same size and layout as the target.
        unsafe { &mut *ptr }
    }
}

impl ops::DerefMut for Vector<3> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        let ptr = self.components.as_mut_ptr() as *mut Self::Target;

        // This is sound. We've created this pointer from a valid instance, that
        // has the same size and layout as the target.
        unsafe { &mut *ptr }
    }
}

impl<const D: usize> Default for Vector<D> {
    fn default() -> Self {
        let components = [Scalar::default(); D];
        Self { components }
    }
}

impl<const D: usize> From<[Scalar; D]> for Vector<D> {
    fn from(components: [Scalar; D]) -> Self {
        Self { components }
    }
}

impl<const D: usize> From<[f64; D]> for Vector<D> {
    fn from(components: [f64; D]) -> Self {
        Self::from_components_f64(components)
    }
}

impl<const D: usize> From<nalgebra::SVector<f64, D>> for Vector<D> {
    fn from(vector: nalgebra::SVector<f64, D>) -> Self {
        Self::from_na(vector)
    }
}

impl<const D: usize> From<Vector<D>> for [f32; D] {
    fn from(vector: Vector<D>) -> Self {
        vector.components.map(|scalar| scalar.into_f32())
    }
}

impl<const D: usize> From<Vector<D>> for [f64; D] {
    fn from(vector: Vector<D>) -> Self {
        vector.components.map(|scalar| scalar.into_f64())
    }
}

impl<const D: usize> From<Vector<D>> for [Scalar; D] {
    fn from(vector: Vector<D>) -> Self {
        vector.components
    }
}

impl<const D: usize> From<Vector<D>> for nalgebra::SVector<f64, D> {
    fn from(vector: Vector<D>) -> Self {
        vector.to_na()
    }
}

impl<const D: usize> ops::Neg for Vector<D> {
    type Output = Self;

    fn neg(self) -> Self::Output {
        self.to_na().neg().into()
    }
}

impl<V, const D: usize> ops::Add<V> for Vector<D>
where
    V: Into<Self>,
{
    type Output = Self;

    fn add(self, rhs: V) -> Self::Output {
        self.to_na().add(rhs.into().to_na()).into()
    }
}

impl<V, const D: usize> ops::Sub<V> for Vector<D>
where
    V: Into<Self>,
{
    type Output = Self;

    fn sub(self, rhs: V) -> Self::Output {
        self.to_na().sub(rhs.into().to_na()).into()
    }
}

impl<S, const D: usize> ops::Mul<S> for Vector<D>
where
    S: Into<Scalar>,
{
    type Output = Self;

    fn mul(self, rhs: S) -> Self::Output {
        self.to_na().mul(rhs.into().into_f64()).into()
    }
}

impl<S, const D: usize> ops::Div<S> for Vector<D>
where
    S: Into<Scalar>,
{
    type Output = Self;

    fn div(self, rhs: S) -> Self::Output {
        self.to_na().div(rhs.into().into_f64()).into()
    }
More examples
Hide additional examples
src/point.rs (line 163)
162
163
164
165
166
167
168
169
170
171
172
173
174
175
    fn add(self, rhs: V) -> Self::Output {
        self.to_na().add(rhs.into().to_na()).into()
    }
}

impl<V, const D: usize> ops::Sub<V> for Point<D>
where
    V: Into<Vector<D>>,
{
    type Output = Self;

    fn sub(self, rhs: V) -> Self::Output {
        self.to_na().sub(rhs.into().to_na()).into()
    }
src/transform.rs (line 25)
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
    pub fn translation(offset: impl Into<Vector<3>>) -> Self {
        let offset = offset.into();

        Self(nalgebra::Transform::from_matrix_unchecked(
            nalgebra::OMatrix::new_translation(&offset.to_na()),
        ))
    }

    /// Construct a rotation
    ///
    /// The direction of the vector defines the rotation axis. Its length
    /// defines the angle of the rotation.
    pub fn rotation(axis_angle: impl Into<Vector<3>>) -> Self {
        let axis_angle = axis_angle.into();

        Self(nalgebra::Transform::from_matrix_unchecked(
            nalgebra::OMatrix::<_, nalgebra::Const<4>, _>::new_rotation(
                axis_angle.to_na(),
            ),
        ))
    }

    /// Transform the given point
    pub fn transform_point(&self, point: &Point<3>) -> Point<3> {
        Point::from(self.0.transform_point(&point.to_na()))
    }

    /// Inverse transform given point
    pub fn inverse_transform_point(&self, point: &Point<3>) -> Point<3> {
        Point::from(self.0.inverse_transform_point(&point.to_na()))
    }

    /// Transform the given vector
    pub fn transform_vector(&self, vector: &Vector<3>) -> Vector<3> {
        Vector::from(self.0.transform_vector(&vector.to_na()))
    }
src/triangle.rs (line 94)
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
    pub fn cast_local_ray(
        &self,
        origin: Point<3>,
        dir: Vector<3>,
        max_toi: f64,
        solid: bool,
    ) -> Option<Scalar> {
        let ray = Ray {
            origin: origin.to_na(),
            dir: dir.to_na(),
        };

        self.to_parry()
            .cast_local_ray(&ray, max_toi, solid)
            .map(Into::into)
    }

Convert to a 1-dimensional vector

Examples found in repository?
src/point.rs (line 49)
47
48
49
50
51
    pub fn to_t(self) -> Point<1> {
        Point {
            coords: self.coords.to_t(),
        }
    }

Convert the vector into a 2-dimensional vector

If the vector is 0-, or 1-dimensional, the missing components will be initialized to zero.

If the vector has higher dimensionality than two, the superfluous components will be discarded.

Examples found in repository?
src/circle.rs (line 126)
122
123
124
125
126
127
128
129
130
131
132
133
134
    pub fn point_to_circle_coords(
        &self,
        point: impl Into<Point<D>>,
    ) -> Point<1> {
        let vector = (point.into() - self.center).to_uv();
        let atan = Scalar::atan2(vector.v, vector.u);
        let coord = if atan >= Scalar::ZERO {
            atan
        } else {
            atan + Scalar::TAU
        };
        Point::from([coord])
    }

Convert the vector into a 3-dimensional vector

If the vector is 0-, 1-, or 2-dimensional, the missing components will be initialized to zero.

If the vector has higher dimensionality than three, the superfluous components will be discarded.

Examples found in repository?
src/point.rs (line 58)
56
57
58
59
60
    pub fn to_xyz(self) -> Point<3> {
        Point {
            coords: self.coords.to_xyz(),
        }
    }

Compute the magnitude of the vector

Examples found in repository?
src/point.rs (line 64)
63
64
65
    pub fn distance_to(&self, other: &Self) -> Scalar {
        (self.coords - other.coords).magnitude()
    }
More examples
Hide additional examples
src/vector.rs (line 105)
104
105
106
107
108
109
110
    pub fn scalar_projection_onto(&self, other: &Self) -> Scalar {
        if other.magnitude() == Scalar::ZERO {
            return Scalar::ZERO;
        }

        self.dot(&other.normalize())
    }
src/line.rs (line 25)
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
    pub fn from_origin_and_direction(
        origin: Point<D>,
        direction: Vector<D>,
    ) -> Self {
        assert!(
            direction.magnitude() != Scalar::ZERO,
            "Can't construct `Line`. Direction is zero: {direction:?}"
        );

        Self { origin, direction }
    }

    /// Create a line from two points
    ///
    /// Also returns the lines coordinates of the provided points on the new
    /// line.
    ///
    /// # Panics
    ///
    /// Panics, if the points are coincident.
    pub fn from_points(
        points: [impl Into<Point<D>>; 2],
    ) -> (Self, [Point<1>; 2]) {
        let [a, b] = points.map(Into::into);

        let line = Self::from_origin_and_direction(a, b - a);
        let coords = [[0.], [1.]].map(Point::from);

        (line, coords)
    }

    /// Create a line from two points that include line coordinates
    ///
    /// # Panics
    ///
    /// Panics, if the points are coincident.
    pub fn from_points_with_line_coords(
        points: [(impl Into<Point<1>>, impl Into<Point<D>>); 2],
    ) -> Self {
        let [(a_line, a_global), (b_line, b_global)] =
            points.map(|(point_line, point_global)| {
                (point_line.into(), point_global.into())
            });

        let direction = (b_global - a_global) / (b_line - a_line).t;
        let origin = a_global + direction * -a_line.t;

        Self::from_origin_and_direction(origin, direction)
    }

    /// Access the origin of the line
    ///
    /// The origin is a point on the line which, together with the `direction`
    /// field, defines the line fully. The origin also defines the origin of the
    /// line's 1-dimensional coordinate system.
    pub fn origin(&self) -> Point<D> {
        self.origin
    }

    /// Access the direction of the line
    ///
    /// The length of this vector defines the unit of the line's curve
    /// coordinate system. The coordinate `1.` is always were the direction
    /// vector points, from `origin`.
    pub fn direction(&self) -> Vector<D> {
        self.direction
    }

    /// Determine if this line is coincident with another line
    ///
    /// # Implementation Note
    ///
    /// This method only returns `true`, if the lines are precisely coincident.
    /// This will probably not be enough going forward, but it'll do for now.
    pub fn is_coincident_with(&self, other: &Self) -> bool {
        let other_origin_is_not_on_self = {
            let a = other.origin;
            let b = self.origin;
            let c = self.origin + self.direction;

            // The triangle is valid only, if the three points are not on the
            // same line.
            Triangle::from_points([a, b, c]).is_ok()
        };

        if other_origin_is_not_on_self {
            return false;
        }

        let d1 = self.direction.normalize();
        let d2 = other.direction.normalize();

        d1 == d2 || d1 == -d2
    }

    /// Create a new instance that is reversed
    #[must_use]
    pub fn reverse(mut self) -> Self {
        self.direction = -self.direction;
        self
    }

    /// Convert a `D`-dimensional point to line coordinates
    ///
    /// Projects the point onto the line before the conversion. This is done to
    /// make this method robust against floating point accuracy issues.
    ///
    /// Callers are advised to be careful about the points they pass, as the
    /// point not being on the line, intentional or not, will never result in an
    /// error.
    pub fn point_to_line_coords(&self, point: impl Into<Point<D>>) -> Point<1> {
        Point {
            coords: self.vector_to_line_coords(point.into() - self.origin),
        }
    }

    /// Convert a `D`-dimensional vector to line coordinates
    pub fn vector_to_line_coords(
        &self,
        vector: impl Into<Vector<D>>,
    ) -> Vector<1> {
        let t = vector.into().scalar_projection_onto(&self.direction)
            / self.direction.magnitude();
        Vector::from([t])
    }
src/triangle.rs (line 28)
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
    pub fn from_points(
        points: [impl Into<Point<D>>; 3],
    ) -> Result<Self, NotATriangle<D>> {
        let points = points.map(Into::into);

        let area = {
            let [a, b, c] = points.map(Point::to_xyz);
            (b - a).cross(&(c - a)).magnitude()
        };

        // A triangle is not valid if it doesn't span any area
        if area != Scalar::from(0.0) {
            Ok(Self { points })
        } else {
            Err(NotATriangle { points })
        }
    }
src/circle.rs (line 37)
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
    pub fn new(
        center: impl Into<Point<D>>,
        a: impl Into<Vector<D>>,
        b: impl Into<Vector<D>>,
    ) -> Self {
        let center = center.into();
        let a = a.into();
        let b = b.into();

        assert_eq!(
            a.magnitude(),
            b.magnitude(),
            "`a` and `b` must be of equal length"
        );
        assert_ne!(
            a.magnitude(),
            Scalar::ZERO,
            "circle radius must not be zero"
        );
        // Requiring the vector to be *precisely* perpendicular is not
        // practical, because of numerical inaccuracy. This epsilon value seems
        // seems to work for now, but maybe it needs to become configurable.
        assert!(
            a.dot(&b) < Scalar::default_epsilon(),
            "`a` and `b` must be perpendicular to each other"
        );

        Self { center, a, b }
    }

    /// Construct a `Circle` from a center point and a radius
    pub fn from_center_and_radius(
        center: impl Into<Point<D>>,
        radius: impl Into<Scalar>,
    ) -> Self {
        let radius = radius.into();

        let mut a = [Scalar::ZERO; D];
        let mut b = [Scalar::ZERO; D];

        a[0] = radius;
        b[1] = radius;

        Self::new(center, a, b)
    }

    /// Access the center point of the circle
    pub fn center(&self) -> Point<D> {
        self.center
    }

    /// Access the radius of the circle
    pub fn radius(&self) -> Scalar {
        self.a().magnitude()
    }

Compute a normalized version of the vector

Examples found in repository?
src/plane.rs (line 39)
38
39
40
    pub fn normal(&self) -> Vector<3> {
        self.u().cross(&self.v()).normalize()
    }
More examples
Hide additional examples
src/vector.rs (line 109)
104
105
106
107
108
109
110
    pub fn scalar_projection_onto(&self, other: &Self) -> Scalar {
        if other.magnitude() == Scalar::ZERO {
            return Scalar::ZERO;
        }

        self.dot(&other.normalize())
    }
src/line.rs (line 109)
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
    pub fn is_coincident_with(&self, other: &Self) -> bool {
        let other_origin_is_not_on_self = {
            let a = other.origin;
            let b = self.origin;
            let c = self.origin + self.direction;

            // The triangle is valid only, if the three points are not on the
            // same line.
            Triangle::from_points([a, b, c]).is_ok()
        };

        if other_origin_is_not_on_self {
            return false;
        }

        let d1 = self.direction.normalize();
        let d2 = other.direction.normalize();

        d1 == d2 || d1 == -d2
    }

Compute the dot product with another vector

Examples found in repository?
src/plane.rs (line 54)
52
53
54
55
56
57
58
59
60
61
62
    pub fn constant_normal_form(&self) -> (Scalar, Vector<3>) {
        let normal = self.normal();
        let distance = normal.dot(&self.origin().coords);

        (distance, normal)
    }

    /// Determine whether the plane is parallel to the given vector
    pub fn is_parallel_to_vector(&self, vector: &Vector<3>) -> bool {
        self.normal().dot(vector) == Scalar::ZERO
    }
More examples
Hide additional examples
src/vector.rs (line 109)
104
105
106
107
108
109
110
    pub fn scalar_projection_onto(&self, other: &Self) -> Scalar {
        if other.magnitude() == Scalar::ZERO {
            return Scalar::ZERO;
        }

        self.dot(&other.normalize())
    }
src/circle.rs (line 50)
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
    pub fn new(
        center: impl Into<Point<D>>,
        a: impl Into<Vector<D>>,
        b: impl Into<Vector<D>>,
    ) -> Self {
        let center = center.into();
        let a = a.into();
        let b = b.into();

        assert_eq!(
            a.magnitude(),
            b.magnitude(),
            "`a` and `b` must be of equal length"
        );
        assert_ne!(
            a.magnitude(),
            Scalar::ZERO,
            "circle radius must not be zero"
        );
        // Requiring the vector to be *precisely* perpendicular is not
        // practical, because of numerical inaccuracy. This epsilon value seems
        // seems to work for now, but maybe it needs to become configurable.
        assert!(
            a.dot(&b) < Scalar::default_epsilon(),
            "`a` and `b` must be perpendicular to each other"
        );

        Self { center, a, b }
    }

Compute the scalar project of this vector onto another

Examples found in repository?
src/plane.rs (line 67)
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
    pub fn project_vector(&self, vector: &Vector<3>) -> Vector<2> {
        Vector::from([
            self.u().scalar_projection_onto(vector),
            self.v().scalar_projection_onto(vector),
        ])
    }

    /// Project a line into the plane
    pub fn project_line(&self, line: &Line<3>) -> Line<2> {
        let line_origin_relative_to_plane = line.origin() - self.origin();
        let line_origin_in_plane = Point {
            coords: Vector::from([
                self.u()
                    .scalar_projection_onto(&line_origin_relative_to_plane),
                self.v()
                    .scalar_projection_onto(&line_origin_relative_to_plane),
            ]),
        };

        let line_direction_in_plane = self.project_vector(&line.direction());

        Line::from_origin_and_direction(
            line_origin_in_plane,
            line_direction_in_plane,
        )
    }
More examples
Hide additional examples
src/line.rs (line 141)
137
138
139
140
141
142
143
144
    pub fn vector_to_line_coords(
        &self,
        vector: impl Into<Vector<D>>,
    ) -> Vector<1> {
        let t = vector.into().scalar_projection_onto(&self.direction)
            / self.direction.magnitude();
        Vector::from([t])
    }

Construct a Vector that represents the t-axis

Construct a Vector that represents the u-axis

Construct a Vector that represents the v-axis

Compute the 2D cross product with another vector

Examples found in repository?
src/vector.rs (line 139)
137
138
139
140
    pub fn is_between(&self, others: [impl Into<Self>; 2]) -> bool {
        let [a, b] = others.map(Into::into);
        a.cross2d(self) * b.cross2d(self) < Scalar::ZERO
    }

Determine whether this vector is between two other vectors

Construct a Vector that represents the x-axis

Construct a Vector that represents the y-axis

Construct a Vector that represents the z-axis

Compute the cross product with another vector

Examples found in repository?
src/plane.rs (line 39)
38
39
40
    pub fn normal(&self) -> Vector<3> {
        self.u().cross(&self.v()).normalize()
    }
More examples
Hide additional examples
src/triangle.rs (line 28)
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
    pub fn from_points(
        points: [impl Into<Point<D>>; 3],
    ) -> Result<Self, NotATriangle<D>> {
        let points = points.map(Into::into);

        let area = {
            let [a, b, c] = points.map(Point::to_xyz);
            (b - a).cross(&(c - a)).magnitude()
        };

        // A triangle is not valid if it doesn't span any area
        if area != Scalar::from(0.0) {
            Ok(Self { points })
        } else {
            Err(NotATriangle { points })
        }
    }

Construct a new vector from this vector’s x and y components

Trait Implementations§

Used for specifying relative comparisons.
The default tolerance to use when testing values that are close together. Read more
A test for equality that uses the absolute difference to compute the approximate equality of two numbers.
The inverse of AbsDiffEq::abs_diff_eq.
The resulting type after applying the + operator.
Performs the + operation. Read more
Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Returns the “default value” for a type. Read more
The resulting type after dereferencing.
Dereferences the value.
The resulting type after dereferencing.
Dereferences the value.
The resulting type after dereferencing.
Dereferences the value.
Mutably dereferences the value.
Mutably dereferences the value.
Mutably dereferences the value.
The resulting type after applying the / operator.
Performs the / operation. Read more
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Feeds this value into the given Hasher. Read more
Feeds a slice of this type into the given Hasher. Read more
The resulting type after applying the * operator.
Performs the * operation. Read more
The resulting type after applying the - operator.
Performs the unary - operation. Read more
This method returns an Ordering between self and other. Read more
Compares and returns the maximum of two values. Read more
Compares and returns the minimum of two values. Read more
Restrict a value to a certain interval. Read more
This method tests for self and other values to be equal, and is used by ==.
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
This method returns an ordering between self and other values if one exists. Read more
This method tests less than (for self and other) and is used by the < operator. Read more
This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
This method tests greater than (for self and other) and is used by the > operator. Read more
This method tests greater than or equal to (for self and other) and is used by the >= operator. Read more
The resulting type after applying the - operator.
Performs the - operation. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more
Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Should always be Self
The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
Checks if self is actually part of its subset T (and can be converted to it).
Use with care! Same as self.to_subset but without any property checks. Always succeeds.
The inclusion map: converts self to the equivalent element of its superset.
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.