in UVAtlas/isochart/packingcharts.cpp [582:753]
inline static VertexLocation CalculateVertexLocationToBorder(
VERTEX_ARRAY& aBorder, // a vertical Border.
size_t dwBorderStart,
size_t dwBorderEnd,
XMFLOAT2& point,// a vertex
float fGutter, // the min distance between two sub-chart
float& fDistance, // the distance from the vertex to the Border.
Axis TangentAxis)
{
VertexLocation higherPosition;
VertexLocation lowerPosition;
Axis RadialAxis;
if (XAxis == TangentAxis)
{
higherPosition = AboveBorder;
lowerPosition = BelowBorder;
RadialAxis = YAxis;
}
else
{
higherPosition = RightToBorder;
lowerPosition = LeftToBorder;
RadialAxis = XAxis;
}
fDistance = FLT_MAX;
// 1. Find correspond segment along scan direction
size_t i;
for (i = dwBorderStart; i < dwBorderEnd + 1; i++)
{
if (VECTOR_ITEM(&point, TangentAxis) <
VECTOR_ITEM(&aBorder[i]->uv, TangentAxis))
{
break;
}
}
// No correspond segment.
if (dwBorderStart == i)
{
return NotDefined;
}
// fIntersection stores intersection between the border and beeline
// crossing the vertex along axises TangentAxis and RadialAxis
float fIntersection = 0;
float fExtraDistance = 0;
// 2. No corresponding segment or some vertices at the end of the border have
// equal value with vertex in scan direction.
if (i == dwBorderEnd + 1)
{
float fMax = -FLT_MAX;
float fMin = FLT_MAX;
for (size_t j = 0; j <= dwBorderEnd; j++)
{
if (IsInZeroRange(
VECTOR_ITEM(&point, TangentAxis) -
VECTOR_ITEM(&aBorder[j]->uv, TangentAxis)))
{
if (fMax < VECTOR_ITEM(&aBorder[j]->uv, RadialAxis))
{
fMax = VECTOR_ITEM(&aBorder[j]->uv, RadialAxis);
}
if (fMin > VECTOR_ITEM(&aBorder[j]->uv, RadialAxis))
{
fMin = VECTOR_ITEM(&aBorder[j]->uv, RadialAxis);
}
}
}
if (fMax < fMin)
{
return NotDefined;
}
if (VECTOR_ITEM(&point, RadialAxis) > fMax)
{
fIntersection = fMax;
}
else if (VECTOR_ITEM(&point, RadialAxis) < fMin)
{
fIntersection = fMin;
}
else
{
return NotDefined;
}
fExtraDistance = fGutter;
}
// 3. Has corresponding segment
else
{
XMVECTOR vBiasVector = XMVectorSubtract(XMLoadFloat2(&(aBorder[i]->uv)), XMLoadFloat2(&(aBorder[i - 1]->uv)));
XMFLOAT2 biasVector;
XMStoreFloat2(&biasVector, vBiasVector);
// If the beeline crossing the vertex also crosses the aBorder[i]->uv, and
// aBorder[i-1]->uv, then, easy to decide the intersection
if (IsInZeroRange(VECTOR_ITEM(&biasVector, TangentAxis)))
{
float fMin, fMax;
if (VECTOR_ITEM(&aBorder[i]->uv, RadialAxis)
> VECTOR_ITEM(&aBorder[i - 1]->uv, RadialAxis))
{
fMax = VECTOR_ITEM(&aBorder[i]->uv, RadialAxis);
fMin = VECTOR_ITEM(&aBorder[i - 1]->uv, RadialAxis);
}
else
{
fMax = VECTOR_ITEM(&aBorder[i - 1]->uv, RadialAxis);
fMin = VECTOR_ITEM(&aBorder[i]->uv, RadialAxis);
}
if (VECTOR_ITEM(&point, RadialAxis) > fMax)
{
fIntersection = fMax;
}
else if (VECTOR_ITEM(&point, TangentAxis) < fMin)
{
fIntersection = fMin;
}
else
{
return NotDefined;
}
fExtraDistance = fGutter;
}
else
{
// (y-y[i-1]) / (y[i]-y[i-1]) = (x-x[i-1]) / (x[i]-x[i-1])
fIntersection =
VECTOR_ITEM(&aBorder[i - 1]->uv, RadialAxis)
+ VECTOR_ITEM(&biasVector, RadialAxis)
* (VECTOR_ITEM(&point, TangentAxis) -
VECTOR_ITEM(&aBorder[i - 1]->uv, TangentAxis))
/ VECTOR_ITEM(&biasVector, TangentAxis);
/*
// this calculation sometimes provides bad answers. Instead, just add fGutter * sqrt(2)
fExtraDistance =
fGutter * fabsf(XMVectorGetX(XMVector2Length(vBiasVector)) /
VECTOR_ITEM(&biasVector, TangentAxis));
*/
fExtraDistance = fGutter * 1.4143f; // multiply by worst-case of sqrt(2)
}
}
fDistance = fIntersection - VECTOR_ITEM(&point, RadialAxis);
if (fDistance < 0)
{
fDistance = -fDistance;
}
fDistance -= fExtraDistance;
if (fIntersection < VECTOR_ITEM(&point, RadialAxis))
{
return higherPosition;
}
else if (fIntersection > VECTOR_ITEM(&point, RadialAxis))
{
return lowerPosition;
}
else
{
return NotDefined;
}
}