Files
create/src/Mod/Mesh/App/WildMagic4/Wm4Intersector1.cpp
2025-11-02 15:49:56 -06:00

299 lines
9.2 KiB
C++

// SPDX-License-Identifier: LGPL-2.1-or-later
// 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)
#include "Wm4FoundationPCH.h"
#include "Wm4Intersector1.h"
namespace Wm4
{
//----------------------------------------------------------------------------
template <class Real>
Intersector1<Real>::Intersector1 (Real fU0, Real fU1, Real fV0, Real fV1)
{
assert(fU0 <= fU1 && fV0 <= fV1);
m_afU[0] = fU0;
m_afU[1] = fU1;
m_afV[0] = fV0;
m_afV[1] = fV1;
m_fFirstTime = (Real)0.0;
m_fLastTime = (Real)0.0;
m_iQuantity = 0;
}
//----------------------------------------------------------------------------
template <class Real>
Intersector1<Real>::Intersector1 (Real afU[2], Real afV[2])
{
assert(afU[0] <= afU[1] && afV[0] <= afV[1]);
for (int i = 0; i < 2; i++)
{
m_afU[i] = afU[i];
m_afV[i] = afV[i];
}
m_fFirstTime = (Real)0.0;
m_fLastTime = (Real)0.0;
m_iQuantity = 0;
}
//----------------------------------------------------------------------------
template <class Real>
Intersector1<Real>::~Intersector1 ()
{
}
//----------------------------------------------------------------------------
template <class Real>
Real Intersector1<Real>::GetU (int i) const
{
assert(0 <= i && i < 2);
return m_afU[i];
}
//----------------------------------------------------------------------------
template <class Real>
Real Intersector1<Real>::GetV (int i) const
{
assert(0 <= i && i < 2);
return m_afV[i];
}
//----------------------------------------------------------------------------
template <class Real>
bool Intersector1<Real>::Test ()
{
return m_afU[0] <= m_afV[1] && m_afU[1] >= m_afV[0];
}
//----------------------------------------------------------------------------
template <class Real>
bool Intersector1<Real>::Find ()
{
if (m_afU[1] < m_afV[0] || m_afU[0] > m_afV[1])
{
m_iQuantity = 0;
}
else if (m_afU[1] > m_afV[0])
{
if (m_afU[0] < m_afV[1])
{
m_iQuantity = 2;
m_afOverlap[0] = (m_afU[0] < m_afV[0] ? m_afV[0] : m_afU[0]);
m_afOverlap[1] = (m_afU[1] > m_afV[1] ? m_afV[1] : m_afU[1]);
if (m_afOverlap[0] == m_afOverlap[1])
{
m_iQuantity = 1;
}
}
else // m_afU[0] == m_afV[1]
{
m_iQuantity = 1;
m_afOverlap[0] = m_afU[0];
}
}
else // m_afU[1] == m_afV[0]
{
m_iQuantity = 1;
m_afOverlap[0] = m_afU[1];
}
return m_iQuantity > 0;
}
//----------------------------------------------------------------------------
template <class Real>
bool Intersector1<Real>::Test (Real fTMax, Real fSpeedU, Real fSpeedV)
{
Real fDiffSpeed, fInvDiffSpeed, fDiffPos;
if (m_afU[1] < m_afV[0])
{
// [u0,u1] initially to the left of [v0,v1]
fDiffSpeed = fSpeedU - fSpeedV;
if (fDiffSpeed > (Real)0.0)
{
// the intervals must move towards each other
fDiffPos = m_afV[0] - m_afU[1];
if (fDiffPos <= fTMax*fDiffSpeed)
{
// the intervals intersect within the specified time
fInvDiffSpeed = ((Real)1.0)/fDiffSpeed;
m_fFirstTime = fDiffPos*fInvDiffSpeed;
m_fLastTime = (m_afV[1] - m_afU[0])*fInvDiffSpeed;
return true;
}
}
}
else if (m_afU[0] > m_afV[1])
{
// [u0,u1] initially to the right of [v0,v1]
fDiffSpeed = fSpeedV - fSpeedU;
if ( fDiffSpeed > (Real)0.0 )
{
// the intervals must move towards each other
fDiffPos = m_afU[0] - m_afV[1];
if (fDiffPos <= fTMax*fDiffSpeed)
{
// the intervals intersect within the specified time
fInvDiffSpeed = ((Real)1.0)/fDiffSpeed;
m_fFirstTime = fDiffPos*fInvDiffSpeed;
m_fLastTime = (m_afU[1] - m_afV[0])*fInvDiffSpeed;
return true;
}
}
}
else
{
// the intervals are initially intersecting
m_fFirstTime = 0.0f;
if (fSpeedV > fSpeedU)
{
m_fLastTime = (m_afU[1] - m_afV[0])/(fSpeedV - fSpeedU);
}
else if (fSpeedV < fSpeedU)
{
m_fLastTime = (m_afV[1] - m_afU[0])/(fSpeedU - fSpeedV);
}
else
{
m_fLastTime = Math<Real>::MAX_REAL;
}
return true;
}
return false;
}
//----------------------------------------------------------------------------
template <class Real>
bool Intersector1<Real>::Find (Real fTMax, Real fSpeedU, Real fSpeedV)
{
Real fDiffSpeed, fInvDiffSpeed, fDiffPos;
if (m_afU[1] < m_afV[0])
{
// [u0,u1] initially to the left of [v0,v1]
fDiffSpeed = fSpeedU - fSpeedV;
if (fDiffSpeed > (Real)0.0)
{
// the intervals must move towards each other
fDiffPos = m_afV[0] - m_afU[1];
if (fDiffPos <= fTMax*fDiffSpeed)
{
// the intervals intersect within the specified time
fInvDiffSpeed = ((Real)1.0)/fDiffSpeed;
m_fFirstTime = fDiffPos*fInvDiffSpeed;
m_fLastTime = (m_afV[1] - m_afU[0])*fInvDiffSpeed;
m_iQuantity = 1;
m_afOverlap[0] = m_afU[0] + m_fFirstTime*fSpeedU;
return true;
}
}
}
else if (m_afU[0] > m_afV[1])
{
// [u0,u1] initially to the right of [v0,v1]
fDiffSpeed = fSpeedV - fSpeedU;
if (fDiffSpeed > (Real)0.0)
{
// the intervals must move towards each other
fDiffPos = m_afU[0] - m_afV[1];
if (fDiffPos <= fTMax*fDiffSpeed)
{
// the intervals intersect within the specified time
fInvDiffSpeed = ((Real)1.0)/fDiffSpeed;
m_fFirstTime = fDiffPos*fInvDiffSpeed;
m_fLastTime = (m_afU[1] - m_afV[0])*fInvDiffSpeed;
m_iQuantity = 1;
m_afOverlap[0] = m_afV[1] + m_fFirstTime*fSpeedV;
return true;
}
}
}
else
{
// the intervals are initially intersecting
m_fFirstTime = 0.0f;
if (fSpeedV > fSpeedU)
{
m_fLastTime = (m_afU[1] - m_afV[0])/(fSpeedV - fSpeedU);
}
else if (fSpeedV < fSpeedU)
{
m_fLastTime = (m_afV[1] - m_afU[0])/(fSpeedU - fSpeedV);
}
else
{
m_fLastTime = Math<Real>::MAX_REAL;
}
if (m_afU[1] > m_afV[0])
{
if (m_afU[0] < m_afV[1])
{
m_iQuantity = 2;
m_afOverlap[0] = (m_afU[0] < m_afV[0] ? m_afV[0] : m_afU[0]);
m_afOverlap[1] = (m_afU[1] > m_afV[1] ? m_afV[1] : m_afU[1]);
}
else // m_afU[0] == m_afV[1]
{
m_iQuantity = 1;
m_afOverlap[0] = m_afU[0];
}
}
else // m_afU[1] == m_afV[0]
{
m_iQuantity = 1;
m_afOverlap[0] = m_afU[1];
}
return true;
}
m_iQuantity = 0;
return false;
}
//----------------------------------------------------------------------------
template <class Real>
Real Intersector1<Real>::GetFirstTime () const
{
return m_fFirstTime;
}
//----------------------------------------------------------------------------
template <class Real>
Real Intersector1<Real>::GetLastTime () const
{
return m_fLastTime;
}
//----------------------------------------------------------------------------
template <class Real>
int Intersector1<Real>::GetQuantity () const
{
return m_iQuantity;
}
//----------------------------------------------------------------------------
template <class Real>
Real Intersector1<Real>::GetOverlap (int i) const
{
assert(0 <= i && i < m_iQuantity);
return m_afOverlap[i];
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// explicit instantiation
//----------------------------------------------------------------------------
template WM4_FOUNDATION_ITEM
class Intersector1<float>;
template WM4_FOUNDATION_ITEM
class Intersector1<double>;
//----------------------------------------------------------------------------
}