/*************************************************************************** * Copyright (c) 2005 Imetric 3D GmbH * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #include "PreCompiled.h" #include "Tools.h" #include "Vector3D.h" using namespace Base; template Vector3<_Precision>::Vector3 (_Precision fx, _Precision fy, _Precision fz) : x(fx), y(fy), z(fz) { } template Vector3<_Precision>::Vector3 (const Vector3<_Precision>& rcVct) : x(rcVct.x), y(rcVct.y), z(rcVct.z) { } template _Precision& Vector3<_Precision>::operator [] (unsigned short usIndex) { switch (usIndex) { case 0: return x; case 1: return y; case 2: return z; } return x; } template const _Precision& Vector3<_Precision>::operator [] (unsigned short usIndex) const { switch (usIndex) { case 0: return x; case 1: return y; case 2: return z; } return x; } template Vector3 <_Precision>Vector3<_Precision>::operator + (const Vector3<_Precision>& rcVct) const { Vector3<_Precision> cVctRes; cVctRes.x = x + rcVct.x; cVctRes.y = y + rcVct.y; cVctRes.z = z + rcVct.z; return cVctRes; } template Vector3<_Precision> Vector3<_Precision>::operator & (const Vector3<_Precision>& rcVct) const { Vector3<_Precision> cVctRes; cVctRes.x = x * (_Precision) fabs(rcVct.x); cVctRes.y = y * (_Precision) fabs(rcVct.y); cVctRes.z = z * (_Precision) fabs(rcVct.z); return cVctRes; } template Vector3<_Precision> Vector3<_Precision>::operator - (const Vector3<_Precision>& rcVct) const { Vector3<_Precision> cVctRes; cVctRes.x = x - rcVct.x; cVctRes.y = y - rcVct.y; cVctRes.z = z - rcVct.z; return cVctRes; } template Vector3<_Precision> Vector3<_Precision>::operator - (void) const { return Vector3(-x, -y, -z); } template Vector3<_Precision>& Vector3<_Precision>::operator += (const Vector3<_Precision>& rcVct) { x += rcVct.x; y += rcVct.y; z += rcVct.z; return *this; } template Vector3<_Precision>& Vector3<_Precision>::operator -= (const Vector3<_Precision>& rcVct) { x -= rcVct.x; y -= rcVct.y; z -= rcVct.z; return *this; } template Vector3<_Precision>& Vector3<_Precision>::operator *= (_Precision fScale) { x *= fScale; y *= fScale; z *= fScale; return *this; } template Vector3<_Precision>& Vector3<_Precision>::operator /= (_Precision fDiv) { x /= fDiv; y /= fDiv; z /= fDiv; return *this; } template Vector3<_Precision> Vector3<_Precision>::operator * (_Precision fScale) const { return Vector3<_Precision>(this->x*fScale,this->y*fScale,this->z*fScale); } template Vector3<_Precision> Vector3<_Precision>::operator / (_Precision fDiv) const { return Vector3<_Precision>(this->x/fDiv,this->y/fDiv,this->z/fDiv); } template Vector3<_Precision>& Vector3<_Precision>::operator = (const Vector3<_Precision>& rcVct) { x = rcVct.x; y = rcVct.y; z = rcVct.z; return *this; } template _Precision Vector3<_Precision>::operator * (const Vector3<_Precision>& rcVct) const { return (x * rcVct.x) + (y * rcVct.y) + (z * rcVct.z); } template _Precision Vector3<_Precision>::Dot (const Vector3<_Precision>& rcVct) const { return (x * rcVct.x) + (y * rcVct.y) + (z * rcVct.z); } template Vector3<_Precision> Vector3<_Precision>::operator % (const Vector3<_Precision>& rcVct) const { Vector3<_Precision> cVctRes; cVctRes.x = (y * rcVct.z) - (z * rcVct.y); cVctRes.y = (z * rcVct.x) - (x * rcVct.z); cVctRes.z = (x * rcVct.y) - (y * rcVct.x); return cVctRes; } template Vector3<_Precision> Vector3<_Precision>::Cross(const Vector3<_Precision>& rcVct) const { Vector3<_Precision> cVctRes; cVctRes.x = (y * rcVct.z) - (z * rcVct.y); cVctRes.y = (z * rcVct.x) - (x * rcVct.z); cVctRes.z = (x * rcVct.y) - (y * rcVct.x); return cVctRes; } template bool Vector3<_Precision>::operator != (const Vector3<_Precision>& rcVct) const { return !((*this) == rcVct); } template bool Vector3<_Precision>::operator == (const Vector3<_Precision>& rcVct) const { return (fabs (x - rcVct.x) <= traits_type::epsilon()) && (fabs (y - rcVct.y) <= traits_type::epsilon()) && (fabs (z - rcVct.z) <= traits_type::epsilon()); } template Vector3<_Precision>& Vector3<_Precision>::ProjectToPlane (const Vector3<_Precision> &rclBase, const Vector3<_Precision> &rclNorm) { Vector3<_Precision> clTemp(rclNorm); *this = *this - (clTemp *= ((*this - rclBase) * clTemp) / clTemp.Sqr()); return *this; } template void Vector3<_Precision>::ProjectToPlane (const Vector3 &rclBase, const Vector3 &rclNorm, Vector3 &rclProj) const { Vector3<_Precision> clTemp(rclNorm); rclProj = *this - (clTemp *= ((*this - rclBase) * clTemp) / clTemp.Sqr()); } template _Precision Vector3<_Precision>::DistanceToPlane (const Vector3<_Precision> &rclBase, const Vector3<_Precision> &rclNorm) const { return ((*this - rclBase) * rclNorm) / rclNorm.Length(); } template _Precision Vector3<_Precision>::Length (void) const { return (_Precision)sqrt ((x * x) + (y * y) + (z * z)); } template _Precision Vector3<_Precision>::DistanceToLine (const Vector3<_Precision> &rclBase, const Vector3<_Precision> &rclDirect) const { return (_Precision) fabs((rclDirect % Vector3(*this - rclBase)).Length() / rclDirect.Length()); } template Vector3<_Precision> Vector3<_Precision>::DistanceToLineSegment(const Vector3& rclP1, const Vector3& rclP2) const { _Precision len2 = Base::DistanceP2(rclP1, rclP2); if (len2 == 0) return rclP1; Vector3<_Precision> p2p1 = rclP2-rclP1; Vector3<_Precision> pXp1 = *this-rclP1; _Precision dot = pXp1 * p2p1; _Precision t = clamp<_Precision>(dot/len2, 0, 1); Vector3<_Precision> dist = t * p2p1 - pXp1; return dist; } template Vector3<_Precision>& Vector3<_Precision>::ProjectToLine (const Vector3<_Precision> &rclPoint, const Vector3<_Precision> &rclLine) { return (*this = ((((rclPoint * rclLine) / rclLine.Sqr()) * rclLine) - rclPoint)); } template Vector3<_Precision> Vector3<_Precision>::Perpendicular(const Vector3<_Precision> &rclBase, const Vector3<_Precision> &rclDir) const { _Precision t = ((*this - rclBase) * rclDir) / (rclDir * rclDir); return rclBase + t * rclDir; } template _Precision Vector3<_Precision>::Sqr (void) const { return (_Precision) ((x * x) + (y * y) + (z * z)); } template void Vector3<_Precision>::Set (_Precision fX, _Precision fY, _Precision fZ) { x = fX; y = fY; z = fZ; } template void Vector3<_Precision>::ScaleX (_Precision f) { x *= f; } template void Vector3<_Precision>::ScaleY (_Precision f) { y *= f; } template void Vector3<_Precision>::ScaleZ (_Precision f) { z *= f; } template void Vector3<_Precision>::Scale (_Precision fX, _Precision fY, _Precision fZ) { x *= fX; y *= fY; z *= fZ; } template void Vector3<_Precision>::MoveX (_Precision f) { x += f; } template void Vector3<_Precision>::MoveY (_Precision f) { y += f; } template void Vector3<_Precision>::MoveZ (_Precision f) { z += f; } template void Vector3<_Precision>::Move (_Precision fX, _Precision fY, _Precision fZ) { x += fX; y += fY; z += fZ; } template void Vector3<_Precision>::RotateX (_Precision f) { Vector3 cPt (*this); _Precision fsin, fcos; fsin = (_Precision)sin (f); fcos = (_Precision)cos (f); y = (cPt.y * fcos) - (cPt.z * fsin); z = (cPt.y * fsin) + (cPt.z * fcos); } template void Vector3<_Precision>::RotateY (_Precision f) { Vector3 cPt (*this); _Precision fsin, fcos; fsin = (_Precision)sin (f); fcos = (_Precision)cos (f); x = (cPt.z * fsin) + (cPt.x * fcos); z = (cPt.z * fcos) - (cPt.x * fsin); } template void Vector3<_Precision>::RotateZ (_Precision f) { Vector3 cPt (*this); _Precision fsin, fcos; fsin = (_Precision)sin (f); fcos = (_Precision)cos (f); x = (cPt.x * fcos) - (cPt.y * fsin); y = (cPt.x * fsin) + (cPt.y * fcos); } template Vector3<_Precision> & Vector3<_Precision>::Normalize (void) { _Precision fLen = Length (); if (fLen != (_Precision)0.0 && fLen != (_Precision)1.0) { x /= fLen; y /= fLen; z /= fLen; } return *this; } template _Precision Vector3<_Precision>::GetAngle (const Vector3 &rcVect) const { _Precision divid, fNum; divid = Length() * ((Vector3<_Precision>&)rcVect).Length(); if ((divid < -1e-10f) || (divid > 1e-10f)) { fNum = (*this * rcVect) / divid; if (fNum < -1) return traits_type::pi(); else if (fNum > 1) return 0.0F; else return _Precision(acos(fNum)); } else return traits_type::maximum(); // division by zero } template void Vector3<_Precision>::TransformToCoordinateSystem (const Vector3 &rclBase, const Vector3 &rclDirX, const Vector3 &rclDirY) { Vector3 clVectX, clVectY, clVectZ, clVectOld; clVectX = rclDirX; clVectY = rclDirY; clVectZ = rclDirX % rclDirY; clVectX.Normalize(); clVectY.Normalize(); clVectZ.Normalize(); clVectOld = *this - rclBase; x = clVectX * clVectOld; y = clVectY * clVectOld; z = clVectZ * clVectOld; } // explicit template instantiation namespace Base { template class BaseExport Vector3; template class BaseExport Vector3; }