1 #[cfg(feature = "arbitrary")] 2 use quickcheck::{Arbitrary, Gen}; 3 4 use num::{Bounded, One, Zero}; 5 use rand::distributions::{Distribution, Standard}; 6 use rand::Rng; 7 8 use alga::general::ClosedDiv; 9 use crate::base::allocator::Allocator; 10 use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1, U2, U3, U4, U5, U6}; 11 use crate::base::{DefaultAllocator, Scalar, VectorN}; 12 13 use crate::geometry::Point; 14 15 impl<N: Scalar, D: DimName> Point<N, D> 16 where DefaultAllocator: Allocator<N, D> 17 { 18 /// Creates a new point with uninitialized coordinates. 19 #[inline] new_uninitialized() -> Self20 pub unsafe fn new_uninitialized() -> Self { 21 Self::from(VectorN::new_uninitialized()) 22 } 23 24 /// Creates a new point with all coordinates equal to zero. 25 /// 26 /// # Example 27 /// 28 /// ``` 29 /// # use nalgebra::{Point2, Point3}; 30 /// // This works in any dimension. 31 /// // The explicit crate::<f32> type annotation may not always be needed, 32 /// // depending on the context of type inference. 33 /// let pt = Point2::<f32>::origin(); 34 /// assert!(pt.x == 0.0 && pt.y == 0.0); 35 /// 36 /// let pt = Point3::<f32>::origin(); 37 /// assert!(pt.x == 0.0 && pt.y == 0.0 && pt.z == 0.0); 38 /// ``` 39 #[inline] origin() -> Self where N: Zero40 pub fn origin() -> Self 41 where N: Zero { 42 Self::from(VectorN::from_element(N::zero())) 43 } 44 45 /// Creates a new point from a slice. 46 /// 47 /// # Example 48 /// 49 /// ``` 50 /// # use nalgebra::{Point2, Point3}; 51 /// let data = [ 1.0, 2.0, 3.0 ]; 52 /// 53 /// let pt = Point2::from_slice(&data[..2]); 54 /// assert_eq!(pt, Point2::new(1.0, 2.0)); 55 /// 56 /// let pt = Point3::from_slice(&data); 57 /// assert_eq!(pt, Point3::new(1.0, 2.0, 3.0)); 58 /// ``` 59 #[inline] from_slice(components: &[N]) -> Self60 pub fn from_slice(components: &[N]) -> Self { 61 Self::from(VectorN::from_row_slice(components)) 62 } 63 64 /// Creates a new point from its homogeneous vector representation. 65 /// 66 /// In practice, this builds a D-dimensional points with the same first D component as `v` 67 /// divided by the last component of `v`. Returns `None` if this divisor is zero. 68 /// 69 /// # Example 70 /// 71 /// ``` 72 /// # use nalgebra::{Point2, Point3, Vector3, Vector4}; 73 /// 74 /// let coords = Vector4::new(1.0, 2.0, 3.0, 1.0); 75 /// let pt = Point3::from_homogeneous(coords); 76 /// assert_eq!(pt, Some(Point3::new(1.0, 2.0, 3.0))); 77 /// 78 /// // All component of the result will be divided by the 79 /// // last component of the vector, here 2.0. 80 /// let coords = Vector4::new(1.0, 2.0, 3.0, 2.0); 81 /// let pt = Point3::from_homogeneous(coords); 82 /// assert_eq!(pt, Some(Point3::new(0.5, 1.0, 1.5))); 83 /// 84 /// // Fails because the last component is zero. 85 /// let coords = Vector4::new(1.0, 2.0, 3.0, 0.0); 86 /// let pt = Point3::from_homogeneous(coords); 87 /// assert!(pt.is_none()); 88 /// 89 /// // Works also in other dimensions. 90 /// let coords = Vector3::new(1.0, 2.0, 1.0); 91 /// let pt = Point2::from_homogeneous(coords); 92 /// assert_eq!(pt, Some(Point2::new(1.0, 2.0))); 93 /// ``` 94 #[inline] from_homogeneous(v: VectorN<N, DimNameSum<D, U1>>) -> Option<Self> where N: Scalar + Zero + One + ClosedDiv, D: DimNameAdd<U1>, DefaultAllocator: Allocator<N, DimNameSum<D, U1>>,95 pub fn from_homogeneous(v: VectorN<N, DimNameSum<D, U1>>) -> Option<Self> 96 where 97 N: Scalar + Zero + One + ClosedDiv, 98 D: DimNameAdd<U1>, 99 DefaultAllocator: Allocator<N, DimNameSum<D, U1>>, 100 { 101 if !v[D::dim()].is_zero() { 102 let coords = v.fixed_slice::<D, U1>(0, 0) / v[D::dim()]; 103 Some(Self::from(coords)) 104 } else { 105 None 106 } 107 } 108 } 109 110 /* 111 * 112 * Traits that build points. 113 * 114 */ 115 impl<N: Scalar + Bounded, D: DimName> Bounded for Point<N, D> 116 where DefaultAllocator: Allocator<N, D> 117 { 118 #[inline] max_value() -> Self119 fn max_value() -> Self { 120 Self::from(VectorN::max_value()) 121 } 122 123 #[inline] min_value() -> Self124 fn min_value() -> Self { 125 Self::from(VectorN::min_value()) 126 } 127 } 128 129 impl<N: Scalar, D: DimName> Distribution<Point<N, D>> for Standard 130 where 131 DefaultAllocator: Allocator<N, D>, 132 Standard: Distribution<N>, 133 { 134 #[inline] sample<'a, G: Rng + ?Sized>(&self, rng: &mut G) -> Point<N, D>135 fn sample<'a, G: Rng + ?Sized>(&self, rng: &mut G) -> Point<N, D> { 136 Point::from(rng.gen::<VectorN<N, D>>()) 137 } 138 } 139 140 #[cfg(feature = "arbitrary")] 141 impl<N: Scalar + Arbitrary + Send, D: DimName> Arbitrary for Point<N, D> 142 where 143 DefaultAllocator: Allocator<N, D>, 144 <DefaultAllocator as Allocator<N, D>>::Buffer: Send, 145 { 146 #[inline] arbitrary<G: Gen>(g: &mut G) -> Self147 fn arbitrary<G: Gen>(g: &mut G) -> Self { 148 Self::from(VectorN::arbitrary(g)) 149 } 150 } 151 152 /* 153 * 154 * Small points construction from components. 155 * 156 */ 157 macro_rules! componentwise_constructors_impl( 158 ($($doc: expr; $D: ty, $($args: ident:$irow: expr),*);* $(;)*) => {$( 159 impl<N: Scalar> Point<N, $D> 160 where DefaultAllocator: Allocator<N, $D> { 161 #[doc = "Initializes this point from its components."] 162 #[doc = "# Example\n```"] 163 #[doc = $doc] 164 #[doc = "```"] 165 #[inline] 166 pub fn new($($args: N),*) -> Self { 167 unsafe { 168 let mut res = Self::new_uninitialized(); 169 $( *res.get_unchecked_mut($irow) = $args; )* 170 171 res 172 } 173 } 174 } 175 )*} 176 ); 177 178 componentwise_constructors_impl!( 179 "# use nalgebra::Point1;\nlet p = Point1::new(1.0);\nassert!(p.x == 1.0);"; 180 U1, x:0; 181 "# use nalgebra::Point2;\nlet p = Point2::new(1.0, 2.0);\nassert!(p.x == 1.0 && p.y == 2.0);"; 182 U2, x:0, y:1; 183 "# use nalgebra::Point3;\nlet p = Point3::new(1.0, 2.0, 3.0);\nassert!(p.x == 1.0 && p.y == 2.0 && p.z == 3.0);"; 184 U3, x:0, y:1, z:2; 185 "# use nalgebra::Point4;\nlet p = Point4::new(1.0, 2.0, 3.0, 4.0);\nassert!(p.x == 1.0 && p.y == 2.0 && p.z == 3.0 && p.w == 4.0);"; 186 U4, x:0, y:1, z:2, w:3; 187 "# use nalgebra::Point5;\nlet p = Point5::new(1.0, 2.0, 3.0, 4.0, 5.0);\nassert!(p.x == 1.0 && p.y == 2.0 && p.z == 3.0 && p.w == 4.0 && p.a == 5.0);"; 188 U5, x:0, y:1, z:2, w:3, a:4; 189 "# use nalgebra::Point6;\nlet p = Point6::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0);\nassert!(p.x == 1.0 && p.y == 2.0 && p.z == 3.0 && p.w == 4.0 && p.a == 5.0 && p.b == 6.0);"; 190 U6, x:0, y:1, z:2, w:3, a:4, b:5; 191 ); 192 193 macro_rules! from_array_impl( 194 ($($D: ty, $len: expr);*) => {$( 195 impl <N: Scalar> From<[N; $len]> for Point<N, $D> { 196 fn from (coords: [N; $len]) -> Self { 197 Self { 198 coords: coords.into() 199 } 200 } 201 } 202 )*} 203 ); 204 205 from_array_impl!(U1, 1; U2, 2; U3, 3; U4, 4; U5, 5; U6, 6); 206