inline static VertexLocation CalculateVertexLocationToBorder()

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;
        }
    }