// Wild Magic Source Code // David Eberly // http://www.geometrictools.com // Copyright (c) 1998-2007 // // This library is free software; you can redistribute it and/or modify it // under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation; either version 2.1 of the License, or (at // your option) any later version. The license is available for reading at // either of the locations: // http://www.gnu.org/copyleft/lgpl.html // http://www.geometrictools.com/License/WildMagicLicense.pdf // The license applies to versions 0 through 4 of Wild Magic. // // Version: 4.0.0 (2006/06/28) namespace Wm4 { //---------------------------------------------------------------------------- template Mapper3::Mapper3 (int iVQuantity, const Vector3* akVertex, Real fEpsilon) { assert(iVQuantity > 0 && akVertex && fEpsilon >= (Real)0.0); m_bExtremeCCW = false; // Compute the axis-aligned bounding box for the input points. m_kMin = akVertex[0]; m_kMax = m_kMin; int aiIMin[3], aiIMax[3], i, j; for (j = 0; j < 3; j++) { aiIMin[j] = 0; aiIMax[j] = 0; } for (i = 1; i < iVQuantity; i++) { for (j = 0; j < 3; j++) { if (akVertex[i][j] < m_kMin[j]) { m_kMin[j] = akVertex[i][j]; aiIMin[j] = i; } else if (akVertex[i][j] > m_kMax[j]) { m_kMax[j] = akVertex[i][j]; aiIMax[j] = i; } } } // Determine the maximum range for the bounding box. Vector3 kRange = m_kMax - m_kMin; m_fMaxRange = kRange[0]; m_aiExtreme[0] = aiIMin[0]; m_aiExtreme[1] = aiIMax[0]; if (kRange[1] > m_fMaxRange) { m_fMaxRange = kRange[1]; m_aiExtreme[0] = aiIMin[1]; m_aiExtreme[1] = aiIMax[1]; } if (kRange[2] > m_fMaxRange) { m_fMaxRange = kRange[2]; m_aiExtreme[0] = aiIMin[2]; m_aiExtreme[1] = aiIMax[2]; } m_kOrigin = akVertex[m_aiExtreme[0]]; // Test if the point set is (nearly) a point. if (m_fMaxRange < fEpsilon) { m_iDimension = 0; m_aiExtreme[1] = m_aiExtreme[0]; m_aiExtreme[2] = m_aiExtreme[0]; m_aiExtreme[3] = m_aiExtreme[0]; m_akDirection[0] = Vector3::ZERO; m_akDirection[1] = Vector3::ZERO; m_akDirection[2] = Vector3::ZERO; return; } // Test if the point set is (nearly) a line segment. m_akDirection[0] = akVertex[m_aiExtreme[1]] - m_kOrigin; m_akDirection[0].Normalize(); Real fLMax = (Real)0.0, fL, fDot; m_aiExtreme[2] = m_aiExtreme[0]; for (i = 0; i < iVQuantity; i++) { Vector3 kDiff = akVertex[i] - m_kOrigin; fDot = m_akDirection[0].Dot(kDiff); Vector3 kProj = kDiff - fDot*m_akDirection[0]; fL = kProj.Length(); if (fL > fLMax) { fLMax = fL; m_aiExtreme[2] = i; } } if (fLMax < fEpsilon*m_fMaxRange) { m_iDimension = 1; m_aiExtreme[2] = m_aiExtreme[1]; m_aiExtreme[3] = m_aiExtreme[1]; m_akDirection[1] = Vector3::ZERO; m_akDirection[2] = Vector3::ZERO; return; } // Test if the point set is (nearly) a planar polygon. m_akDirection[1] = akVertex[m_aiExtreme[2]] - m_kOrigin; fDot = m_akDirection[0].Dot(m_akDirection[1]); m_akDirection[1] -= fDot*m_akDirection[0]; m_akDirection[1].Normalize(); m_akDirection[2] = m_akDirection[0].Cross(m_akDirection[1]); fLMax = (Real)0.0; Real fMaxSign = (Real)0.0, fSign; m_aiExtreme[3] = m_aiExtreme[0]; for (i = 0; i < iVQuantity; i++) { Vector3 kDiff = akVertex[i] - m_kOrigin; fL = m_akDirection[2].Dot(kDiff); fSign = Math::Sign(fL); fL = Math::FAbs(fL); if (fL > fLMax) { fLMax = fL; fMaxSign = fSign; m_aiExtreme[3] = i; } } if (fLMax < fEpsilon*m_fMaxRange) { m_iDimension = 2; m_aiExtreme[3] = m_aiExtreme[2]; return; } m_iDimension = 3; m_bExtremeCCW = (fMaxSign > (Real)0.0 ? true : false); } //---------------------------------------------------------------------------- template Mapper3::~Mapper3 () { } //---------------------------------------------------------------------------- template const Vector3& Mapper3::GetMin () const { return m_kMin; } //---------------------------------------------------------------------------- template const Vector3& Mapper3::GetMax () const { return m_kMax; } //---------------------------------------------------------------------------- template Real Mapper3::GetMaxRange () const { return m_fMaxRange; } //---------------------------------------------------------------------------- template int Mapper3::GetDimension () const { return m_iDimension; } //---------------------------------------------------------------------------- template const Vector3& Mapper3::GetOrigin () const { return m_kOrigin; } //---------------------------------------------------------------------------- template const Vector3& Mapper3::GetDirection (int i) const { assert(0 <= i && i < 3); return m_akDirection[i]; } //---------------------------------------------------------------------------- template int Mapper3::GetExtremeIndex (int i) const { assert(0 <= i && i < 4); return m_aiExtreme[i]; } //---------------------------------------------------------------------------- template bool Mapper3::GetExtremeCCW () const { return m_bExtremeCCW; } //---------------------------------------------------------------------------- } //namespace Wm4