#![macro_use] macro_rules! point_impl( ($t: ident, $tv: ident | $($compN: ident),+) => ( /* * * Origin. * */ impl Origin for $t { #[inline] fn origin() -> $t { $t { $($compN: ::zero() ),+ } } #[inline] fn is_origin(&self) -> bool { $(self.$compN.is_zero() )&&+ } } /* * * Point - Point * */ impl> Sub<$t> for $t { type Output = $tv; #[inline] fn sub(self, right: $t) -> $tv { *self.as_vector() - *right.as_vector() } } /* * * Point + Vector * */ impl> Add<$tv> for $t { type Output = $t; #[inline] fn add(self, right: $tv) -> $t { $t::new($(self.$compN + right.$compN),+) } } impl> AddAssign<$tv> for $t { #[inline] fn add_assign(&mut self, right: $tv) { $( self.$compN += right.$compN; )+ } } /* * * Point - Vector * */ impl> Sub<$tv> for $t { type Output = $t; #[inline] fn sub(self, right: $tv) -> $t { $t::new($(self.$compN - right.$compN),+) } } impl> SubAssign<$tv> for $t { #[inline] fn sub_assign(&mut self, right: $tv) { $( self.$compN -= right.$compN; )+ } } /* * * Point as vector. * */ impl $t { /// Converts this point to its associated vector. #[inline] pub fn to_vector(self) -> $tv { $tv::new( $(self.$compN),+ ) } /// Converts a reference to this point to a reference to its associated vector. #[inline] pub fn as_vector(&self) -> &$tv { unsafe { mem::transmute(self) } } #[inline] fn set_coords(&mut self, v: $tv) { $(self.$compN = v.$compN;)+ } } impl PointAsVector for $t { type Vector = $tv; #[inline] fn to_vector(self) -> $tv { self.to_vector() } #[inline] fn as_vector(&self) -> &$tv { self.as_vector() } #[inline] fn set_coords(&mut self, v: $tv) { self.set_coords(v) } } /* * * NumPoint / FloatPoint * */ impl NumPoint for $t where N: BaseNum { } impl FloatPoint for $t where N: BaseFloat + ApproxEq { } /* * * Display * */ impl fmt::Display for $t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // FIXME: differenciate them from vectors ? try!(write!(f, "(")); let mut it = self.iter(); try!(write!(f, "{}", *it.next().unwrap())); for comp in it { try!(write!(f, ", {}", *comp)); } write!(f, ")") } } ); ($t: ident, $tv: ident, $th: ident, $comp_extra: ident | $($compN: ident),+) => ( point_impl!($t, $tv | $($compN),+); /* * * ToHomogeneous / FromHomogeneous * */ impl ToHomogeneous<$th> for $t { fn to_homogeneous(&self) -> $th { let mut res: $th = Origin::origin(); $( res.$compN = self.$compN; )+ res.$comp_extra = ::one(); res } } impl + One + Zero> FromHomogeneous<$th> for $t { fn from(v: &$th) -> $t { let mut res: $t = Origin::origin(); $( res.$compN = v.$compN / v.$comp_extra; )+ res } } ) );