Home

Resume

Blog

Teikitu


// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //
//  »Project«   Teikitu Gaming System (TgS) (∂)
//  »File«      TgS Collision - F - Disk-Point.c_inc
//  »Author«    Andrew Aye (EMail: mailto:andrew.aye@gmail.com, Web: http://www.andrewaye.com)
//  »Version«   4.0
//  »Keywords«  Collision;Distance;Closest;Intersect;Penetrate;Sweep;Disk;Point;
// ------------------------------------------------------------------------------------------------------------------------------ //
//  Copyright: © 2002-2010, Andrew Aye.  All Rights Reserved.
//  This software is free for non-commercial use. Redistribution and use in source and binary forms, with or without modification,
//  are permitted provided that the following conditions are met: 
//    Redistributions of source code must retain this copyright notice, this list of conditions and the following disclaimers. 
//    Redistributions in binary form must reproduce this copyright notice, this list of conditions and the following
//      disclaimers in the documentation and other materials provided with the distribution. 
//  Neither the names of the copyright owner nor the names of its contributors may be used to endorse or promote products derived
//  from this software without specific prior written permission. 
//  The intellectual property rights of the algorithms used reside with Andrew Aye.  You may not use this software, in whole or
//  in part, in support of any commercial product without the express written consent of the author.
//  There is no warranty or other guarantee of fitness of this software for any purpose. It is provided solely "as is".
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //
// == Collision ================================================================================================================= //

// ---- tgCO_F_DistSq_DK_VT ----------------------------------------------------------------------------------------------------- //
// Input:  psDK0: Disk - The set of points on the plane that are at or less than the radius value.
// Input:  pvS0: Point, not necessarily in the plane.
// Return: Minimal distance between the two primitives or negative type max if they intersect or are invalid.
// ------------------------------------------------------------------------------------------------------------------------------ //
TYPE V(tgCO_F_DistSq_DK_VT)( V(CPCU_TgDISK) psDK0, V(CPCU_TgVEC) pvS0 )
{
    V(C_TgVEC)                          vDS = V(F_SUB_VV)( pvS0, &psDK0->m.m.vOrigin );
    const TYPE                          fDS_DS = V(F_LSQ)( &vDS );

    TgASSERT_PARAM( V(tgGM_Is_Valid_DK)( psDK0 ) && V(F_Is_Point_Valid)( pvS0 ) );

    if (fDS_DS <= F(KTgEPS))
    {
        return (fDS_DS); // Quick Out - the point is within tolerance of circle origin.
    }
    else
    {
        const TYPE                          fDS_N = V(F_DOT_VV)( &vDS, &psDK0->m.m.vNormal );
        V(C_TgVEC)                          vK0 = V(F_MUL_SV)( fDS_N, &psDK0->m.m.vNormal );
        V(C_TgVEC)                          vPDS = V(F_SUB_VV)( &vDS, &vK0 );
        const TYPE                          fPDS_PDS = V(F_LSQ)( &vPDS );

        if (fPDS_PDS <= psDK0->m_fRadiusSq)
        {
            return (fDS_N*fDS_N); // Quick Out - the point is directly above the disk
        }
        else
        {
            V(C_TgVEC)                          vK1 = V(F_MUL_SV)( psDK0->m_fRadius / F(tgPM_SQRT)( fPDS_PDS ), &vPDS );
            V(C_TgVEC)                          vK2 = V(F_SUB_VV)( &vDS, &vK1 );

            return (V(F_LSQ)( &vK2 ));
        };
    };
}


// ---- tgCO_F_ClosestSq_DK_VT -------------------------------------------------------------------------------------------------- //
// Input:  psDK0: Disk - The set of points on the plane that are at or less than the radius value.
// Input:  pvS0: Point, not necessarily in the plane.
// Output: vDK0: Point of closest proximity on the circle.
// Return: Minimal distance between the two primitives or negative type max if they intersect or are invalid.
// ------------------------------------------------------------------------------------------------------------------------------ //
TYPE V(tgCO_F_ClosestSq_DK_VT)( V(PCU_TgVEC) pvDK0, V(CPCU_TgDISK) psDK0, V(CPCU_TgVEC) pvS0 )
{
    V(C_TgVEC)                          vDS = V(F_SUB_VV)( pvS0, &psDK0->m.m.vOrigin );
    const TYPE                          fDS_DS = V(F_LSQ)( &vDS );

    TgASSERT_PARAM( V(tgGM_Is_Valid_DK)( psDK0 ) && V(F_Is_Point_Valid)( pvS0 ) );

    if (fDS_DS <= F(KTgEPS))
    {
        *pvDK0 = psDK0->m.m.vOrigin;
        return (fDS_DS);  // Quick Out - the point is within tolerance of circle origin.
    }
    else
    {
        const TYPE                          fDS_N = V(F_DOT_VV)( &vDS, &psDK0->m.m.vNormal );
        V(C_TgVEC)                          vK0 = V(F_MUL_SV)( fDS_N, &psDK0->m.m.vNormal );
        V(C_TgVEC)                          vPDS = V(F_SUB_VV)( &vDS, &vK0 );
        const TYPE                          fPDS_PDS = V(F_LSQ)( &vPDS );
    
        if (fPDS_PDS <= psDK0->m_fRadiusSq)
        {
            *pvDK0 = V(F_ADD_VV)( &psDK0->m.m.vOrigin, &vPDS );
            return (fDS_N*fDS_N); // Quick Out - the point is directly above the disk
        }
        else
        {
            V(C_TgVEC)                          vK1 = V(F_MUL_SV)( psDK0->m_fRadius / F(tgPM_SQRT)( fPDS_PDS ), &vPDS );
            V(C_TgVEC)                          vK3 = V(F_ADD_VV)( &psDK0->m.m.vOrigin, &vK1 );
            V(C_TgVEC)                          vK4 = V(F_SUB_VV)( pvS0, &vK3 );

            *pvDK0 = vK3;
            return (V(F_LSQ)( &vK4 ));
        };
    };
}