/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//* vim: set ts=8 sts=2 et sw=2 tw=80: *//* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */#ifndef MOZILLA_BASEPOINT3D_H_#define MOZILLA_BASEPOINT3D_H_#include"mozilla/Assertions.h"namespacemozilla{namespacegfx{/** * Do not use this class directly. Subclass it, pass that subclass as the * Sub parameter, and only use that subclass. This allows methods to safely * cast 'this' to 'Sub*'. */template<classT,classSub>structBasePoint3D{union{struct{Tx,y,z;};Tcomponents[3];};// ConstructorsBasePoint3D():x(0),y(0),z(0){}BasePoint3D(TaX,TaY,TaZ):x(aX),y(aY),z(aZ){}voidMoveTo(TaX,TaY,TaZ){x=aX;y=aY;z=aZ;}voidMoveBy(TaDx,TaDy,TaDz){x+=aDx;y+=aDy;z+=aDz;}// Note that '=' isn't defined so we'll get the// compiler generated default assignment operatorT&operator[](intaIndex){MOZ_ASSERT(aIndex>=0&&aIndex<=2);return*((&x)+aIndex);}constT&operator[](intaIndex)const{MOZ_ASSERT(aIndex>=0&&aIndex<=2);return*((&x)+aIndex);}booloperator==(constSub&aPoint)const{returnx==aPoint.x&&y==aPoint.y&&z==aPoint.z;}booloperator!=(constSub&aPoint)const{returnx!=aPoint.x||y!=aPoint.y||z!=aPoint.z;}Suboperator+(constSub&aPoint)const{returnSub(x+aPoint.x,y+aPoint.y,z+aPoint.z);}Suboperator-(constSub&aPoint)const{returnSub(x-aPoint.x,y-aPoint.y,z-aPoint.z);}Sub&operator+=(constSub&aPoint){x+=aPoint.x;y+=aPoint.y;z+=aPoint.z;return*static_cast<Sub*>(this);}Sub&operator-=(constSub&aPoint){x-=aPoint.x;y-=aPoint.y;z-=aPoint.z;return*static_cast<Sub*>(this);}Suboperator*(TaScale)const{returnSub(x*aScale,y*aScale,z*aScale);}Suboperator/(TaScale)const{returnSub(x/aScale,y/aScale,z/aScale);}Sub&operator*=(TaScale){x*=aScale;y*=aScale;z*=aScale;return*static_cast<Sub*>(this);}Sub&operator/=(TaScale){x/=aScale;y/=aScale;z/=aScale;return*static_cast<Sub*>(this);}Suboperator-()const{returnSub(-x,-y,-z);}SubCrossProduct(constSub&aPoint)const{returnSub(y*aPoint.z-aPoint.y*z,z*aPoint.x-aPoint.z*x,x*aPoint.y-aPoint.x*y);}TDotProduct(constSub&aPoint)const{returnx*aPoint.x+y*aPoint.y+z*aPoint.z;}TLength()const{returnsqrt(x*x+y*y+z*z);}// Invalid for points with distance from origin of 0.voidNormalize(){*this/=Length();}voidRobustNormalize(){// If the distance is infinite, we scale it by 1/(the maximum value of T)// before doing normalization, so we can avoid getting a zero point.Tlength=Length();if(mozilla::IsInfinite(length)){*this/=std::numeric_limits<T>::max();length=Length();}*this/=length;}friendstd::ostream&operator<<(std::ostream&stream,constBasePoint3D<T,Sub>&aPoint){returnstream<<'('<<aPoint.x<<','<<aPoint.y<<','<<aPoint.z<<')';}};}// namespace gfx}// namespace mozilla#endif /* MOZILLA_BASEPOINT3D_H_ */