static HRESULT GenerateAccumulationLines()

in UVAtlas/isochart/imtcomputation.cpp [860:1010]


    static HRESULT GenerateAccumulationLines(
        std::vector<DOUBLEVECTOR2>& keyPointList, // all key points on the lines, composite a convex polygon
        std::vector<DOUBLEVECTOR2>& above, // above line when applying 2 times accumulation
        std::vector<DOUBLEVECTOR2>& below)// below line when applying 2 times accumulation
    {
        if (keyPointList.empty())
        {
            return S_OK;
        }

        for (size_t ii = 0; ii < keyPointList.size() - 1; ii++)
        {
            for (size_t jj = ii + 1; jj < keyPointList.size();)
            {
                if (IsInZeroRangeDouble(keyPointList[jj].x - keyPointList[ii].x) &&
                    IsInZeroRangeDouble(keyPointList[jj].y - keyPointList[ii].y))
                {
                    keyPointList.erase(keyPointList.begin() + ptrdiff_t(jj));
                }
                else
                {
                    jj++;
                }
            }
        }
        if (keyPointList.size() < 3)
        {
            return S_OK;
        }

        // 1. Find the left most point
        DOUBLEVECTOR2 leftMost = { DBL_MAX, DBL_MAX };
        DOUBLEVECTOR2 rightMost = { -DBL_MAX, -DBL_MAX };
        DOUBLEVECTOR2 tempV;
        double fTemp;

        std::unique_ptr<double[]> tanList(new (std::nothrow) double[keyPointList.size()]);
        if (!tanList)
        {
            return E_OUTOFMEMORY;
        }

        double* pTanList = tanList.get();

        uint32_t dwLeftMost = 0;
        for (uint32_t ii = 0; ii < keyPointList.size(); ii++)
        {
            if (leftMost.x > keyPointList[ii].x ||
                (leftMost.x == keyPointList[ii].x && leftMost.y > keyPointList[ii].y))
            {
                leftMost = keyPointList[ii];
                dwLeftMost = ii;
            }
            if (rightMost.x < keyPointList[ii].x ||
                (rightMost.x == keyPointList[ii].x && rightMost.y > keyPointList[ii].y))
            {
                rightMost = keyPointList[ii];
            }
        }
        keyPointList[dwLeftMost] = keyPointList[0];
        keyPointList[0] = leftMost;

        // 2. Sort points along the counter clock-wise direction.
        for (size_t ii = 1; ii < keyPointList.size(); ii++)
        {
            double fy = keyPointList[ii].y - leftMost.y;
            double fx = keyPointList[ii].x - leftMost.x;

            if (IsInZeroRangeDouble(fx))
            {
                if (IsInZeroRangeDouble(fy))
                {
                    pTanList[ii] = -DBL_MAX;
                }
                else if (fy > 0)
                {
                    pTanList[ii] = DBL_MAX;
                }
                else
                {
                    pTanList[ii] = -DBL_MAX;
                }
            }
            else
            {
                pTanList[ii] = fy / fx;
            }
        }

        for (size_t ii = 1; ii < keyPointList.size() - 1; ii++)
        {
            for (size_t jj = ii + 1; jj < keyPointList.size(); jj++)
            {
                if (pTanList[ii] > pTanList[jj])
                {
                    tempV = keyPointList[ii];
                    keyPointList[ii] = keyPointList[jj];
                    keyPointList[jj] = tempV;

                    fTemp = pTanList[ii];
                    pTanList[ii] = pTanList[jj];
                    pTanList[jj] = fTemp;
                }
            }
        }

        // 3. Get above & below lines.
        try
        {
            uint32_t dwCur = 0;
            do
            {
                below.push_back(keyPointList[dwCur]);
                dwCur++;
            } while (dwCur < keyPointList.size()
                && keyPointList[dwCur - 1].x < keyPointList[dwCur].x);

            assert(keyPointList[dwCur - 1].x == rightMost.x);
            assert(keyPointList[dwCur - 1].y == rightMost.y);

            if (keyPointList[keyPointList.size() - 1].x > leftMost.x)
            {
                above.push_back(leftMost);
            }

            for (size_t jj = keyPointList.size() - 1; jj > 0; jj--)
            {
                above.push_back(keyPointList[jj]);

                if (keyPointList[jj].x >= rightMost.x)
                {
                    break;
                }
            }
        }
        catch (std::bad_alloc&)
        {
            return E_OUTOFMEMORY;
        }

        for (size_t ii = 0; ii < above.size() - 1; ii++)
        {
            assert(above[ii].x <= above[ii + 1].x);
        }
        for (size_t ii = 0; ii < below.size() - 1; ii++)
        {
            assert(below[ii].x <= below[ii + 1].x);
        }

        return S_OK;
    }