• CurveBrokenLine


    //2015.11.23
    #include <iostream>
    #include <vector>
    #include <stack>
    #include "Defines.h"
    #include "OneSeg.h"
    
    //定义点
    typedef struct _MyPoint
    {
        bool flag;
        double x;
        double y;
    
        _MyPoint(double _x = 0.0, double _y = 0.0, bool _flag = false)
        {
            x = _x;
            y = _y;
            flag = _flag;
        }
    }MyPoint;
    
    double CalcAngle(MyPoint first, MyPoint cen, MyPoint second)
    {
        double dx1, dx2, dy1, dy2; 
        double angle; 
    
        dx1 = first.x - cen.x; 
        dy1 = first.y - cen.y; 
    
        dx2 = second.x - cen.x; 
    
        dy2 = second.y - cen.y; 
    
        double c = (double)sqrt(dx1 * dx1 + dy1 * dy1) * (double)sqrt(dx2 * dx2 + dy2 * dy2); 
    
        if (c == 0) return -1; 
    
        angle = (double)acos((dx1 * dx2 + dy1 * dy2) / c); 
    
        return angle / PAI * 180; 
    }
    
    /* cp 在此是四个元素的数组:
    cp[0] 为起点,或上图中的 P0
    cp[1] 为第一控制点,或上图中的 P1
    cp[2] 为第二控制点,或上图中的 P2
    cp[3] 为结束点,或上图中的 P3
    t 为参数值,0 <= t <= 1 */
    MyPoint PointOnCubicBezier(MyPoint* cp, double t)
    {
        double ax, bx, cx; double ay, by, cy;
        double tSquared, tCubed; MyPoint result;
        /* 计算多项式系数 */
        cx = 3.0 * (cp[1].x - cp[0].x);
        bx = 3.0 * (cp[2].x - cp[1].x) - cx;
        ax = cp[3].x - cp[0].x - cx - bx;
        cy = 3.0 * (cp[1].y - cp[0].y);
        by = 3.0 * (cp[2].y - cp[1].y) - cy;
        ay = cp[3].y - cp[0].y - cy - by;
        /* 计算t位置的点值 */
        tSquared = t * t;
        tCubed = tSquared * t;
        result.x = (ax * tCubed) + (bx * tSquared) + (cx * t) + cp[0].x;
        result.y = (ay * tCubed) + (by * tSquared) + (cy * t) + cp[0].y;
        return result;
    }
    /* ComputeBezier 以控制点 cp 所产生的曲线点,填入 MyPoint 结构数组。
    调用方必须分配足够的空间以供输出,<sizeof(MyPoint) numberOfPoints> */
    void ComputeBezier( MyPoint* cp, int numberOfPoints, MyPoint* curve )
    {
        double dt; int i;
        dt = 1.0 / ( numberOfPoints - 1 );
        for( i = 0; i < numberOfPoints; i++)
            curve[i] = PointOnCubicBezier( cp, i*dt );
    }
    
    int FindSplit(std::vector<MyPoint>& V, int& i, int& j, int* f, double* dist)
    {
        if (i + 1 > j)
        {
            return -1;
        }
    
        *f = i + 1;
        COneSeg os(V[i].x, V[i].y, V[j].x, V[j].y);
        *dist = os.GapFromPoint(cv::Point2d(V[*f].x, V[*f].y));
        for (int m = *f + 1; m < j; ++m)
        {
            double dTmpGap = os.GapFromPoint(cv::Point2d(V[m].x, V[m].y));
            if (dTmpGap > *dist)
            {
                *dist = dTmpGap;
                *f = m;
            }
        }
    
        return 0;
    }
    
    int DouglasPeucker(std::vector<MyPoint>& V, int &i, int &j, double e)
    {
        if (V.size() <= 2)
        {
            //不需要处理
            return -1;
        }
    
        double dist = 9999;
        int f = 0;            //最大距离的点的序号
        std::stack<int> tempVertex;            //STL实现的栈
        tempVertex.push(j);
    
        do
        {
            //循环i和j之间距离直线ij最大的点
            FindSplit(V, i, j, &f, &dist);
    
            if (dist > e)      //大于阈值
            {
                V[f].flag = true;
    
                j = f;    //更新B值
    
                tempVertex.push(f);                    //记录最大距离点,放入栈中存储
                continue;
            }
    
            else
            {
                if (!tempVertex.empty() && j != tempVertex.top())    //判断后一点是否和当前栈顶相等
                {
                    i = f;
                    j = tempVertex.top();
                    continue;
                }
                else
                {
                    if (j != V.size())        //判断最后一个点是否和当前线段的B点重合
                    {
                        i = j;
                        if (!tempVertex.empty())
                        {
                            std::deque<int> cont = tempVertex._Get_container();
                            if (cont.size() > 1) //栈中至少还有两个点
                            {
                                j = cont[cont.size() - 2];
                            }
                            else if (cont.size() == 1)    //栈中只有一个点
                            {
                                j = cont[cont.size() - 1];
                            }
                            tempVertex.pop();
                            continue;
                        }
                    }
                }
            }
        } while (!tempVertex.empty());
    
        //保留首尾,去掉无用的点
        for (int i = 1; i < V.size() - 1;)
        {
            if (V[i].flag == false)
            {
                V.erase(V.begin() + i);
            }
            else
            {
                i++;
            }
        }
    
        return int(tempVertex.size());
    }
    
    int GetLineKeyPt(double* pX, double* pY, const int nNum, double** pOutX, double** pOutY, int *pOutNum, double dGap = 10.0)
    {
        std::vector<MyPoint> V;
        for (int m = 0; m < nNum; ++m)
        {
            V.push_back(MyPoint(pX[m], pY[m]));
        }
    
        int i = 0;
        int j = int(V.size() - 1);
    
        DouglasPeucker(V, i, j, dGap);
    
        //输出
        *pOutNum = (int)V.size();
        *pOutX = new double[*pOutNum];
        *pOutY = new double[*pOutNum];
        for (int i = 0; i < *pOutNum; ++i)
        {
            (*pOutX)[i] = V[i].x;
            (*pOutY)[i] = V[i].y;
        }
    
        V.clear();
    
        return 0;
    }
    
    double Length(MyPoint p1, MyPoint p2)
    {
        return sqrt((p1.y - p2.y) * (p1.y - p2.y) + (p1.x - p2.x) * (p1.x - p2.x));
    }
    
    double Slope(MyPoint p1, MyPoint p2)
    {
        if (std::fabs(p1.x - p2.x) <= 1e-7)
        {
            return DBL_MAX;
        }
    
        return (p1.y - p2.y) / (p1.x - p2.x);
    }
    
    double GapFromPoint(MyPoint p1, MyPoint p2, const MyPoint& pt )
    {
        double k = Slope(p1, p2);
    
        if (k == DBL_MAX)
        {
            //垂直的时候直接返回差值
            return fabs(p1.x - pt.x);
        }
    
        double b = p1.y - k * p1.x;
    
        return fabs(k * pt.x - pt.y + b) / sqrt( 1 + k * k);
    }
    
    bool IsPointInHalfLine(MyPoint p1, MyPoint p2, const MyPoint& pt, const double dDiff /*= 1.0*/ )
    {
        return GapFromPoint(p1, p2, pt) <= dDiff;
    }
    
    MyPoint GetCenter(MyPoint p1, MyPoint p2)
    {
        return MyPoint((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
    }
    
    bool GetPointInSeg(MyPoint p1, MyPoint p2, MyPoint& pRes, const double dGap /*= 10*/ )
    {
        if (Length(p1, p2) < dGap)
        {
            return false;
        }
    
        if (p1.y == p2.y)
        {
            if (p1.x < p2.x)
            {
                pRes = MyPoint(p2.x - dGap, p1.y);
            }
            else
            {
                pRes = MyPoint(p2.x + dGap, p1.y);
            }
    
            return true;
        }
    
        if (p1.x == p2.x)
        {
            if (p1.y < p2.y)
            {
                pRes = MyPoint(p1.x, p2.y - dGap);
            }
            else
            {
                pRes = MyPoint(p1.x, p2.y + dGap);
            }
            return true;
        }
    
        double dResX = p2.x - (p2.x - p1.x) * dGap / Length(p1, p2);
        double dResY = p1.y - (p1.y - p2.y)*(Length(p1, p2) - dGap)/Length(p1, p2);
    
        pRes = MyPoint(dResX, dResY);
    
        return true;
    }
    
    double TwoPointsGap(const double x1, const double y1, const double x2, const double y2)
    {
        return sqrt((y1 - y2) * (y1 - y2) + (x1 - x2) * (x1 - x2));
    }
    
    double TwoPointsGap(const MyPoint& p1, const MyPoint& p2)
    {
        return TwoPointsGap(p1.x, p1.y, p2.x, p2.y);
    }
    
    int RemovePointByGap(double** pX, double** pY, int* nNum, const double& dGap = 1.0)
    {
        int nOldNum = *nNum;
    
        if (nOldNum < 3)
        {
            return -1;
        }
    
        //获取输入
        std::vector<MyPoint> vPts(nOldNum);
        std::vector<MyPoint> vOut;
        for (int i = 0; i < nOldNum; ++i)
        {
            vPts[i] = MyPoint((*pX)[i], (*pY)[i]);
        }
    
        //取顺序的两个点
        MyPoint ptStart, ptCurrent;
        ptStart = vPts[0];
        ptCurrent = vPts[1];
        vOut.push_back(ptStart);
        for (int i = 1; i < nOldNum - 1; ++i)
        {
            ptCurrent = vPts[i];
            double dLength = Length(ptStart, ptCurrent);
            if (dLength > dGap)
            {
                vOut.push_back(ptCurrent);
                ptStart = ptCurrent;
            }
        }
    
        vOut.push_back(MyPoint((*pX)[nOldNum - 1], (*pY)[nOldNum - 1]));
        //释放原来的值
        delete[] (*pX);
        delete[] (*pY);
        *pX = NULL;
        *pY = NULL;
        *nNum = (int)vOut.size();
        *pX = new double[*nNum];
        *pY = new double[*nNum];
        for (int i = 0; i < *nNum; ++i)
        {
            (*pX)[i] = vOut[i].x;
            (*pY)[i] = vOut[i].y;
        }
    
        //注意这里不能delete,因为外部还会使用
    
        return 0;
    }
    
    int CurveBrokenLine(std::vector<cv::Point>& vPts)
    {
        int nNum = vPts.size();
        MyPoint* pt = new MyPoint[nNum];
        for (int i = 0; i < nNum; ++i)
        {
            pt[i] = MyPoint(vPts[i].x, vPts[i].y);
        }
    
        for (int i = 0; i < nNum - 3; ++i)
        {
            ComputeBezier(pt, 4, pt);
        }
    
        for (int i = 0; i < nNum; ++i)
        {
            vPts[i] = cv::Point(pt[i].x, pt[i].y);
        }
    
        delete[] pt;
        pt = nullptr;
    
        return 0;
    }
    
    int SmoothBrokenLine(double* pX, double* pY, const int nNum)
    {
        if (nNum < 4)
        {
            return -1;
        }
    
        const int nBezierNum = 4;
        int nTime = nNum / 4;
        MyPoint* pPts = new MyPoint[nBezierNum];
        MyPoint* pOut = new MyPoint[nBezierNum];
        for (int i = 0; i < nTime; ++i)
        {
    
            for (int j = 0; j < nBezierNum; ++j)
            {
                pPts[j] = MyPoint(pX[i * 4 + j], pY[i * 4 + j]);
            }
            ComputeBezier(pPts, 4, pOut);
            for (int j = 0; j < nBezierNum; ++j)
            {
                pX[i * 4 + j] = pOut[j].x;
                pY[i * 4 + j] = pOut[j].y;
            }
        }
    
        //最后4个结果再次拟合
        for (int j = 0; j < nBezierNum; ++j)
        {
            pPts[j] = MyPoint(pX[nNum - 4 + j], pY[nNum - 4 + j]);
        }
    
        ComputeBezier(pPts, 4, pOut);
        for (int j = 0; j < nBezierNum; ++j)
        {
            pX[nNum - 4 + j] = pOut[j].x;
            pY[nNum - 4 + j] = pOut[j].y;
        }
    
        delete[] pPts;
        delete[] pOut;
        pPts = NULL;
        pOut = NULL;
    
        return 0;
    }
  • 相关阅读:
    [cf1097F]Alex and a TV Show
    [cf1097E]Egor and an RPG game
    2.2 物理层下面的传输媒体
    2.1 物理层的基本概念
    8 垃圾回收
    7 直接内存
    6 方法区
    1.5 计算机网络体系结构
    1.4 计算机网络的性能指标
    1.3 计算机网络的定义和分类
  • 原文地址:https://www.cnblogs.com/autumoonchina/p/7064863.html
Copyright © 2020-2023  润新知