namespace TGS {
namespace COL {
template <typename TYPE, int DIM>
TYPE Box_DoF3( TYPE *ptyLN0, PC_(VECTOR,DIM) ptvDS, M_(VECTOR,DIM) tvD0, CR_(BOX,DIM) tgBX0 )
{
T_(VECTOR,DIM) tvD1_D1, tvD1_MN, tvD1_MX, tvMN_MN, tvMX_MX;
C_(VECTOR,DIM) tvMN = MATH::F_SUB( *ptvDS, tgBX0.Query_ExtentList() );
C_(VECTOR,DIM) tvMX = MATH::F_ADD( *ptvDS, tgBX0.Query_ExtentList() );
C_(VECTOR,DIM) tvD1xMN = MATH::F_CX( tvD0, tvMN );
tvD1_D1 = MATH::F_MUL( tvD0, tvD0 );
tvD1_MN = MATH::F_MUL( tvD0, tvMN );
tvD1_MX = MATH::F_MUL( tvD0, tvMX );
tvMN_MN = MATH::F_MUL( tvMN, tvMN );
tvMX_MX = MATH::F_MUL( tvMX, tvMX );
const TYPE tyD1_D1 = MATH::F_LSQ( tvD0 );
TgUINT i0, i1, i2;
if (tvD1xMN.Z() >= TYPE(0.0))
{
i0 = tvD1xMN.X() >= TYPE(0.0) ? 2 : 1;
i1 = tvD1xMN.X() >= TYPE(0.0) ? 0 : 2;
i2 = tvD1xMN.X() >= TYPE(0.0) ? 1 : 0;
}
else
{
i0 = tvD1xMN.Y() >= TYPE(0.0) ? 0 : 2;
i1 = tvD1xMN.Y() >= TYPE(0.0) ? 1 : 0;
i2 = tvD1xMN.Y() >= TYPE(0.0) ? 2 : 1;
}
(*ptvDS)(i0) = tgBX0.Query_Extent(i0);
if (tvD0(i0)*tvMX(i2) >= tvD0(i2)*tvMN(i0) && tvD0(i0)*tvMX(i1) >= tvD0(i1)*tvMN(i0))
{
const TYPE tyINV = TYPE(1.0) / tvD0(i0);
(*ptvDS)(i1) -= tvD0(i1)*tvMN(i0)*tyINV;
(*ptvDS)(i2) -= tvD0(i2)*tvMN(i0)*tyINV;
*ptyLN0 = -tvMN(i0)*tyINV;
return (TYPE(0.0));
};
const TYPE tyTMP = tvMX(i1) - tvD0(i1)*(tvD1_MN(i0) + tvD1_MX(i2)) / (tvD1_D1(i0) + tvD1_D1(i2));
if (tvD0(i0)*tvMX(i1) >= tvD0(i1)*tvMN(i0) || (tyTMP >= TYPE(0.0) && tvD0(i0)*tvMX(i2) < tvD0(i2)*tvMN(i0)))
{
const TYPE tyLength = TYPE(2.0)*tgBX0.Query_Extent(i1);
const TYPE tyT = P::FSEL(tyLength - tyTMP, P::FSEL( tyTMP, tyTMP, TYPE(0.0) ), tyLength );
const TYPE tyTB = tvMX(i1) - tyT;
const TYPE tyDT = tvD1_MN(i0) + tvD1_MX(i2) + tvD0(i1)*tyTB;
const TYPE tyPM = -tyDT / tyD1_D1;
(*ptvDS)(i1) = -tgBX0.Query_Extent(i1) + tyT;
(*ptvDS)(i2) = -tgBX0.Query_Extent(i2);
*ptyLN0 = tyPM;
return (tvMN_MN(i0) + tvMX_MX(i2) + tyDT*tyPM + tyTB*tyTB);
}
else
{
const TYPE tyTMP = tvMX(i2) - tvD0(i2)*(tvD1_MN(i0) + tvD1_MX(i1)) / (tvD1_D1(i0) + tvD1_D1(i1));
const TYPE tyLength = TYPE(2.0)*tgBX0.Query_Extent(i2);
const TYPE tyT = P::FSEL(tyLength - tyTMP, P::FSEL( tyTMP, tyTMP, TYPE(0.0) ), tyLength );
const TYPE tyTB = tvMX(i2) - tyT;
const TYPE tyDT = tvD1_MN(i0) + tvD1_MX(i1) + tvD0(i2)*tyTB;
const TYPE tyPM = -tyDT / tyD1_D1;
(*ptvDS)(i1) = -tgBX0.Query_Extent(i1);
(*ptvDS)(i2) = -tgBX0.Query_Extent(i2) + tyT;
*ptyLN0 = tyPM;
return (tvMN_MN(i0) + tvMX_MX(i1) + tyDT*tyPM + tyTB*tyTB);
};
};
template TgFLOAT32 Box_DoF3( P_TgFLOAT32, PC_TgF4VECTOR, M_TgF4VECTOR, CR_TgF4BOX );
template <typename TYPE, int DIM>
TYPE Box_DoF2( TYPE *ptyLN0, PC_(VECTOR,DIM) ptvDS, M_(VECTOR,DIM) tvD0, C_TgINT i0, C_TgINT i1, C_TgINT i2, CR_(BOX,DIM) tgBX0 )
{
const TYPE tyMinDT0 = (*ptvDS)(i0) - tgBX0.Query_Extent(i0);
const TYPE tyMinDT1 = (*ptvDS)(i1) - tgBX0.Query_Extent(i1);
const TYPE tyMinDT1_DN0 = tvD0(i0)*tyMinDT1;
const TYPE tyMinDT0_DN1 = tvD0(i1)*tyMinDT0;
T_(VECTOR,DIM) tvD1_D1;
tvD1_D1 = MATH::F_MUL( tvD0, tvD0 );
if (tyMinDT0_DN1 >= tyMinDT1_DN0)
{
(*ptvDS)(i0) = tgBX0.Query_Extent(i0);
const TYPE tyMaxDT1 = (*ptvDS)(i1) + tgBX0.Query_Extent(i1);
const TYPE tyDT = tyMinDT0_DN1 - tvD0(i0)*tyMaxDT1;
if (tyDT >= TYPE(0.0))
{
const TYPE tyTMP0 = TYPE(1.0) / (tvD1_D1(i0) + tvD1_D1(i1));
(*ptvDS)(i1) = -tgBX0.Query_Extent(i1);
*ptyLN0 = -(tvD0(i0)*tyMinDT0 + tvD0(i1)*tyMaxDT1)*tyTMP0;
return (tyDT*tyDT*tyTMP0);
}
else
{
const TYPE tyTMP0 = TYPE(1.0) / tvD0(i0);
(*ptvDS)(i1) -= tyMinDT0_DN1*tyTMP0;
*ptyLN0 = -tyMinDT0*tyTMP0;
return (TYPE(0.0));
}
}
else
{
(*ptvDS)(i1) = tgBX0.Query_Extent(i1);
const TYPE tyMaxDT0 = (*ptvDS)(i0) + tgBX0.Query_Extent(i0);
const TYPE tyDT = tyMinDT1_DN0 - tvD0(i1)*tyMaxDT0;
if (tyDT >= TYPE(0.0))
{
const TYPE tyTMP0 = TYPE(1.0) / (tvD1_D1(i0) + tvD1_D1(i1));
(*ptvDS)(i0) = -tgBX0.Query_Extent(i0);
*ptyLN0 = -(tvD0(i0)*tyMaxDT0 + tvD0(i1)*tyMinDT1)*tyTMP0;
return (tyDT*tyDT*tyTMP0);
}
else
{
const TYPE tyTMP0 = TYPE(1.0) / tvD0(i1);
(*ptvDS)(i0) -= tyMinDT1_DN0*tyTMP0;
*ptyLN0 = -tyMinDT1*tyTMP0;
return (TYPE(0.0));
}
}
}
template TgFLOAT32 Box_DoF2( P_TgFLOAT32, PC_TgF4VECTOR, M_TgF4VECTOR, C_TgINT, C_TgINT, C_TgINT, CR_TgF4BOX );
template <typename TYPE, int DIM, bool bC0, bool bC1>
TYPE TTgCSQ_BXLN<TYPE,DIM,bC0,bC1>::DO(
TYPE *ptyB0, TYPE *ptyB1, TYPE *ptyB2, TYPE *ptyLN0, CR_(BOX,DIM) tgBX0, M_(VECTOR,DIM) tvS0, M_(VECTOR,DIM) tvD0
) {
T_(VECTOR,DIM) tvDS = MATH::F_SUB( tvS0, tgBX0.Query_Origin() );
const TYPE tyD1_X0 = MATH::F_DOT( tvD0, tgBX0.Query_AxisUnit0() );
const TYPE tyD1_X1 = MATH::F_DOT( tvD0, tgBX0.Query_AxisUnit1() );
const TYPE tyD1_X2 = MATH::F_DOT( tvD0, tgBX0.Query_AxisUnit2() );
const TYPE tyDS_X0 = MATH::F_DOT( tvDS, tgBX0.Query_AxisUnit0() );
const TYPE tyDS_X1 = MATH::F_DOT( tvDS, tgBX0.Query_AxisUnit1() );
const TYPE tyDS_X2 = MATH::F_DOT( tvDS, tgBX0.Query_AxisUnit2() );
T_(VECTOR,DIM) tvDN;
tvDS = MATH::F_SETV<TYPE,DIM>(
P::FSEL(tyD1_X0, tyDS_X0,-tyDS_X0),
P::FSEL(tyD1_X1, tyDS_X1,-tyDS_X1),
P::FSEL(tyD1_X2, tyDS_X2,-tyDS_X2)
);
tvDN = MATH::F_SETV<TYPE,DIM>( P::ABS(tyD1_X0), P::ABS(tyD1_X1), P::ABS(tyD1_X2) );
TYPE tyDistSq = TYPE(0.0);
switch ((Near_Zero( tvD0.X() ) ? 0 : 1) + (Near_Zero( tvD0.Y() ) ? 0 : 2) + (Near_Zero( tvD0.Z() ) ? 0 : 4)) {
case 7: {
tyDistSq += Box_DoF3( ptyLN0, &tvDS, tvDN, tgBX0 );
*ptyB0 = P::FSEL( tyD1_X0, tvDS.X(), -tvDS.X() );
*ptyB1 = P::FSEL( tyD1_X1, tvDS.Y(), -tvDS.Y() );
*ptyB2 = P::FSEL( tyD1_X2, tvDS.Z(), -tvDS.Z() );
break;
}
case 6: {
tyDistSq += Box_DoF2( ptyLN0, &tvDS, tvDN, 0,1,2, tgBX0 );
const TYPE tyT2 = P::ABS( tvDS.Z() ) - tgBX0.Query_Extent2();
const TYPE tyZ = P::FSEL( tyT2, P::Copy_Sign( tgBX0.Query_Extent2(), tvDS.Z() ), tvDS.Z() );
tyDistSq += P::FSEL( tyT2, tyT2*tyT2, TYPE(0.0) );
*ptyB0 = P::FSEL( tyD1_X0, tvDS.X(), -tvDS.X() );
*ptyB1 = P::FSEL( tyD1_X1, tvDS.Y(), -tvDS.Y() );
*ptyB2 = P::FSEL( tyD1_X2, tyZ, -tyZ );
break;
}
case 5: {
tyDistSq += Box_DoF2( ptyLN0, &tvDS, tvDN, 0,2,1, tgBX0 );
const TYPE tyT1 = P::ABS( tvDS.Y() ) - tgBX0.Query_Extent1();
const TYPE tyY = P::FSEL( tyT1, P::Copy_Sign( tgBX0.Query_Extent1(), tvDS.Y() ), tvDS.Y() );
tyDistSq += P::FSEL( tyT1, tyT1*tyT1, TYPE(0.0) );
*ptyB0 = P::FSEL( tyD1_X0, tvDS.X(), -tvDS.X() );
*ptyB1 = P::FSEL( tyD1_X1, tyY, -tyY );
*ptyB2 = P::FSEL( tyD1_X2, tvDS.Z(), -tvDS.Z() );
break;
}
case 3: {
tyDistSq += Box_DoF2( ptyLN0, &tvDS, tvDN, 1,2,0, tgBX0 );
const TYPE tyT0 = P::ABS( tvDS.X() ) - tgBX0.Query_Extent0();
const TYPE tyX = P::FSEL( tyT0, P::Copy_Sign( tgBX0.Query_Extent0(), tvDS.X() ), tvDS.X() );
tyDistSq += P::FSEL( tyT0, tyT0*tyT0,TYPE(0.0) );
*ptyB0 = P::FSEL( tyD1_X0, tyX, -tyX );
*ptyB1 = P::FSEL( tyD1_X1, tvDS.Y(), -tvDS.Y() );
*ptyB2 = P::FSEL( tyD1_X2, tvDS.Z(), -tvDS.Z() );
break;
}
case 4: {
const TYPE tyT1 = P::ABS( tvDS.Y() ) - tgBX0.Query_Extent1();
const TYPE tyT2 = P::ABS( tvDS.Z() ) - tgBX0.Query_Extent2();
const TYPE tyY = P::FSEL( tyT1, P::Copy_Sign( tgBX0.Query_Extent1(), tvDS.Y() ), tvDS.Y() );
const TYPE tyZ = P::FSEL( tyT2, P::Copy_Sign( tgBX0.Query_Extent2(), tvDS.Z() ), tvDS.Z() );
tyDistSq += P::FSEL( tyT1, tyT1*tyT1,TYPE(0.0) ) + P::FSEL( tyT2, tyT2*tyT2,TYPE(0.0) );
*ptyB0 = TYPE(0.0);
*ptyB1 = P::FSEL( tyD1_X1, tyY, -tyY );
*ptyB2 = P::FSEL( tyD1_X2, tyZ, -tyZ );
*ptyLN0 = -(tvDS.X() / tvDN.X());
break;
}
case 2: {
const TYPE tyT0 = P::ABS( tvDS.X() ) - tgBX0.Query_Extent0();
const TYPE tyT2 = P::ABS( tvDS.Z() ) - tgBX0.Query_Extent2();
const TYPE tyX = P::FSEL( tyT0, P::Copy_Sign( tgBX0.Query_Extent0(), tvDS.X() ), tvDS.X() );
const TYPE tyZ = P::FSEL( tyT2, P::Copy_Sign( tgBX0.Query_Extent2(), tvDS.Z() ), tvDS.Z() );
tyDistSq += P::FSEL( tyT0, tyT0*tyT0,TYPE(0.0) ) + P::FSEL( tyT2, tyT2*tyT2,TYPE(0.0) );
*ptyB0 = P::FSEL( tyD1_X0, tyX, -tyX );
*ptyB1 = TYPE(0.0);
*ptyB2 = P::FSEL( tyD1_X2, tyZ, -tyZ );
*ptyLN0 = -(tvDS.Y() / tvDN.Y());
break;
}
case 1: {
const TYPE tyT0 = P::ABS( tvDS.X() ) - tgBX0.Query_Extent0();
const TYPE tyT1 = P::ABS( tvDS.Y() ) - tgBX0.Query_Extent1();
const TYPE tyX = P::FSEL( tyT0, P::Copy_Sign( tgBX0.Query_Extent0(), tvDS.X() ), tvDS.X() );
const TYPE tyY = P::FSEL( tyT1, P::Copy_Sign( tgBX0.Query_Extent1(), tvDS.Y() ), tvDS.Y() );
tyDistSq += P::FSEL( tyT0, tyT0*tyT0,TYPE(0.0) ) + P::FSEL( tyT1, tyT1*tyT1,TYPE(0.0) );
*ptyB0 = P::FSEL( tyD1_X0, tyX, -tyX );
*ptyB1 = P::FSEL( tyD1_X1, tyY, -tyY );
*ptyB2 = TYPE(0.0);
*ptyLN0 = -(tvDS.Z() / tvDN.Z());
break;
}
case 0: {
const TYPE tyT0 = P::ABS( tvDS.X() ) - tgBX0.Query_Extent0();
const TYPE tyT1 = P::ABS( tvDS.Y() ) - tgBX0.Query_Extent1();
const TYPE tyT2 = P::ABS( tvDS.Z() ) - tgBX0.Query_Extent2();
const TYPE tyX = P::FSEL( tyT0, P::Copy_Sign( tgBX0.Query_Extent0(), tvDS.X() ), tvDS.X() );
const TYPE tyY = P::FSEL( tyT1, P::Copy_Sign( tgBX0.Query_Extent1(), tvDS.Y() ), tvDS.Y() );
const TYPE tyZ = P::FSEL( tyT2, P::Copy_Sign( tgBX0.Query_Extent2(), tvDS.Z() ), tvDS.Z() );
tyDistSq += P::FSEL( tyT0, tyT0*tyT0,TYPE(0.0) ) + P::FSEL( tyT1, tyT1*tyT1,TYPE(0.0) ) + P::FSEL( tyT2, tyT2*tyT2,TYPE(0.0) );
*ptyB0 = P::FSEL( tyD1_X0, tyX, -tyX );
*ptyB1 = P::FSEL( tyD1_X1, tyY, -tyY );
*ptyB2 = P::FSEL( tyD1_X2, tyZ, -tyZ );
*ptyLN0 = TYPE(0.0);
break;
}
};
if (bC0 && *ptyLN0 < TYPE(0.0))
{
*ptyLN0 = TYPE(0.0);
return (F_ClosestSq( ptyB0,ptyB1,ptyB2, tgBX0, tvS0 ));
};
if (bC1 && *ptyLN0 > TYPE(1.0))
{
*ptyLN0 = TYPE(1.0);
return (F_ClosestSq( ptyB0,ptyB1,ptyB2, tgBX0, MATH::F_ADD( tvS0, tvD0 ) ));
};
return (tyDistSq);
};
template <typename TYPE, int DIM, bool bC0, bool bC1>
TgRESULT TTgCLP_BXLN<TYPE,DIM,bC0,bC1>::DO( TYPE *ptyLN0, TYPE *ptyLN1, CR_(BOX,DIM) tgBX0, M_(VECTOR,DIM) tvS0, M_(VECTOR,DIM) tvD0 )
{
TgASSERT( tgBX0.Is_Valid() );
T_(VECTOR,DIM) tvDS = MATH::F_SUB( tvS0, tgBX0.Query_Origin() );
TYPE tyDS_N,tyD1_N;
TYPE tyMin = -LIMITS<TYPE>::MAX;
TYPE tyMax = LIMITS<TYPE>::MAX;
tyDS_N = MATH::F_DOT(tgBX0.Query_AxisUnit0(),tvDS);
tyD1_N = MATH::F_DOT(tgBX0.Query_AxisUnit0(),tvD0);
if (bC0 && tyDS_N < -tgBX0.Query_Extent0())
{
if (tyD1_N < TYPE(0.0) || (bC1 && (tyDS_N + tyD1_N < -tgBX0.Query_Extent0())))
{
return (TgE_NOINTERSECT);
};
}
else if (bC0 && tyDS_N > tgBX0.Query_Extent0())
{
if (tyD1_N > TYPE(0.0) || (bC1 && (tyDS_N + tyD1_N > tgBX0.Query_Extent0())))
{
return (TgE_NOINTERSECT);
};
};
if (tyD1_N < -LIMITS<TYPE>::EPSILON)
{
tyMin = P::FSEL( tyDS_N + tyD1_N*tyMin - tgBX0.Query_Extent0(), (tgBX0.Query_Extent0() - tyDS_N) / tyD1_N, tyMin );
tyMax = P::FSEL( tyDS_N + tyD1_N*tyMax + tgBX0.Query_Extent0(), tyMax, -(tgBX0.Query_Extent0() + tyDS_N) / tyD1_N );
}
else if (tyD1_N > LIMITS<TYPE>::EPSILON)
{
tyMin = P::FSEL( tyDS_N + tyD1_N*tyMin + tgBX0.Query_Extent0(), tyMin, -(tgBX0.Query_Extent0() + tyDS_N) / tyD1_N );
tyMax = P::FSEL( tyDS_N + tyD1_N*tyMax - tgBX0.Query_Extent0(), (tgBX0.Query_Extent0() - tyDS_N) / tyD1_N, tyMax );
};
tyDS_N = MATH::F_DOT(tgBX0.Query_AxisUnit1(),tvDS);
tyD1_N = MATH::F_DOT(tgBX0.Query_AxisUnit1(),tvD0);
if (bC0 && tyDS_N < -tgBX0.Query_Extent1())
{
if (tyD1_N < TYPE(0.0) || (bC1 && (tyDS_N + tyD1_N < -tgBX0.Query_Extent1())))
{
return (TgE_NOINTERSECT);
};
}
else if (bC0 && tyDS_N > tgBX0.Query_Extent1())
{
if (tyD1_N > TYPE(0.0) || (bC1 && (tyDS_N + tyD1_N > tgBX0.Query_Extent1())))
{
return (TgE_NOINTERSECT);
};
};
if (tyD1_N < -LIMITS<TYPE>::EPSILON)
{
tyMin = P::FSEL( tyDS_N + tyD1_N*tyMin - tgBX0.Query_Extent1(), (tgBX0.Query_Extent1() - tyDS_N) / tyD1_N, tyMin );
tyMax = P::FSEL( tyDS_N + tyD1_N*tyMax + tgBX0.Query_Extent1(), tyMax, -(tgBX0.Query_Extent1() + tyDS_N) / tyD1_N );
}
else if (tyD1_N > LIMITS<TYPE>::EPSILON)
{
tyMin = P::FSEL( tyDS_N + tyD1_N*tyMin + tgBX0.Query_Extent1(), tyMin, -(tgBX0.Query_Extent1() + tyDS_N) / tyD1_N );
tyMax = P::FSEL( tyDS_N + tyD1_N*tyMax - tgBX0.Query_Extent1(), (tgBX0.Query_Extent1() - tyDS_N) / tyD1_N, tyMax );
};
tyDS_N = MATH::F_DOT(tgBX0.Query_AxisUnit2(),tvDS);
tyD1_N = MATH::F_DOT(tgBX0.Query_AxisUnit2(),tvD0);
if (bC0 && tyDS_N < -tgBX0.Query_Extent2())
{
if (tyD1_N < TYPE(0.0) || (bC1 && (tyDS_N + tyD1_N < -tgBX0.Query_Extent2())))
{
return (TgE_NOINTERSECT);
};
}
else if (bC0 && tyDS_N > tgBX0.Query_Extent2())
{
if (tyD1_N > TYPE(0.0) || (bC1 && (tyDS_N + tyD1_N > tgBX0.Query_Extent2())))
{
return (TgE_NOINTERSECT);
};
};
if (tyD1_N < -LIMITS<TYPE>::EPSILON)
{
tyMin = P::FSEL( tyDS_N + tyMin*tyD1_N - tgBX0.Query_Extent2(), (tgBX0.Query_Extent2() - tyDS_N) / tyD1_N, tyMin );
tyMax = P::FSEL( tyDS_N + tyMax*tyD1_N + tgBX0.Query_Extent2(), tyMax, -(tgBX0.Query_Extent2() + tyDS_N) / tyD1_N );
}
else if (tyD1_N > LIMITS<TYPE>::EPSILON)
{
tyMin = P::FSEL( tyDS_N + tyMin*tyD1_N + tgBX0.Query_Extent2(), tyMin, -(tgBX0.Query_Extent2() + tyDS_N) / tyD1_N );
tyMax = P::FSEL( tyDS_N + tyMax*tyD1_N - tgBX0.Query_Extent2(), (tgBX0.Query_Extent2() - tyDS_N) / tyD1_N, tyMax );
};
if (tyMin > tyMax || tyMin <= -LIMITS<TYPE>::MAX || tyMax >= LIMITS<TYPE>::MAX)
{
return (TgE_FAIL);
};
if (bC0)
{
*ptyLN0 = P::FSEL( *ptyLN0, *ptyLN0, TYPE(0.0) );
*ptyLN1 = P::FSEL( *ptyLN1, *ptyLN1, TYPE(0.0) );
};
if (bC1)
{
*ptyLN0 = P::FSEL( *ptyLN0 - TYPE(1.0), *ptyLN0, TYPE(1.0) );
*ptyLN1 = P::FSEL( *ptyLN1 - TYPE(1.0), *ptyLN1, TYPE(1.0) );
};
return (TgS_OK);
};
template struct TTgCSQ_BXLN<TgFLOAT32,4,0,0>;
template struct TTgCSQ_BXLN<TgFLOAT32,4,1,0>;
template struct TTgCSQ_BXLN<TgFLOAT32,4,1,1>;
template struct TTgCLP_BXLN<TgFLOAT32,4,0,0>;
template struct TTgCLP_BXLN<TgFLOAT32,4,1,0>;
template struct TTgCLP_BXLN<TgFLOAT32,4,1,1>;
};
};