zoukankan      html  css  js  c++  java
  • 三次贝塞尔曲线平滑多边形

    #pragma once
    
    #include "opencv.hpp"
    #include "StdStrFile.h"
    
    void CurvePoly(const std::vector<cv::Point>& vPtsInput, std::vector<cv::Point> &curvePoint);
    #include "CurvePoly.h"
    
    //三次贝塞尔曲线  
    float bezier3funcX(float uu, cv::Point *controlP){
        float part0 = controlP[0].x * uu * uu * uu;
        float part1 = 3 * controlP[1].x * uu * uu * (1 - uu);
        float part2 = 3 * controlP[2].x * uu * (1 - uu) * (1 - uu);
        float part3 = controlP[3].x * (1 - uu) * (1 - uu) * (1 - uu);
        return part0 + part1 + part2 + part3;
    }
    float bezier3funcY(float uu, cv::Point *controlP){
        float part0 = controlP[0].y * uu * uu * uu;
        float part1 = 3 * controlP[1].y * uu * uu * (1 - uu);
        float part2 = 3 * controlP[2].y * uu * (1 - uu) * (1 - uu);
        float part3 = controlP[3].y * (1 - uu) * (1 - uu) * (1 - uu);
        return part0 + part1 + part2 + part3;
    }
    
    void CurvePoly(const std::vector<cv::Point>& vPtsInput, std::vector<cv::Point> &curvePoint)
    {
        //控制点收缩系数 ,经调试0.6较好,cv::Point是opencv的,可自行定义结构体(x,y)
        int originCount = vPtsInput.size();
        float scale = 0.6;
        cv::Point* midpoints = new cv::Point[originCount];
        //生成中点       
        for (int i = 0; i < originCount; i++){
            int nexti = (i + 1) % originCount;
            midpoints[i].x = (vPtsInput[i].x + vPtsInput[nexti].x) / 2.0;
            midpoints[i].y = (vPtsInput[i].y + vPtsInput[nexti].y) / 2.0;
        }
    
        //平移中点  
        cv::Point* extrapoints = new cv::Point[2 * originCount];
        for (int i = 0; i < originCount; i++){
            int nexti = (i + 1) % originCount;
            int backi = (i + originCount - 1) % originCount;
            cv::Point midinmid;
            midinmid.x = (midpoints[i].x + midpoints[backi].x) / 2.0;
            midinmid.y = (midpoints[i].y + midpoints[backi].y) / 2.0;
            int offsetx = vPtsInput[i].x - midinmid.x;
            int offsety = vPtsInput[i].y - midinmid.y;
            int extraindex = 2 * i;
            extrapoints[extraindex].x = midpoints[backi].x + offsetx;
            extrapoints[extraindex].y = midpoints[backi].y + offsety;
            //朝 originPoint[i]方向收缩   
            int addx = (extrapoints[extraindex].x - vPtsInput[i].x) * scale;
            int addy = (extrapoints[extraindex].y - vPtsInput[i].y) * scale;
            extrapoints[extraindex].x = vPtsInput[i].x + addx;
            extrapoints[extraindex].y = vPtsInput[i].y + addy;
    
            int extranexti = (extraindex + 1) % (2 * originCount);
            extrapoints[extranexti].x = midpoints[i].x + offsetx;
            extrapoints[extranexti].y = midpoints[i].y + offsety;
            //朝 originPoint[i]方向收缩   
            addx = (extrapoints[extranexti].x - vPtsInput[i].x) * scale;
            addy = (extrapoints[extranexti].y - vPtsInput[i].y) * scale;
            extrapoints[extranexti].x = vPtsInput[i].x + addx;
            extrapoints[extranexti].y = vPtsInput[i].y + addy;
        }
    
        CStdStrFile ssf;
        std::vector<cv::Point> vResPts;
    
        cv::Point controlPoint[4];
        //生成4控制点,产生贝塞尔曲线
        for (int i = 0; i < originCount; i++)
        {
            controlPoint[0] = vPtsInput[i];
            int extraindex = 2 * i;
            controlPoint[1] = extrapoints[extraindex + 1];
            int extranexti = (extraindex + 2) % (2 * originCount);
            controlPoint[2] = extrapoints[extranexti];
            int nexti = (i + 1) % originCount;
            controlPoint[3] = vPtsInput[nexti];
            float u = 1;
            while (u >= 0){
                int px = bezier3funcX(u, controlPoint);
                int py = bezier3funcY(u, controlPoint);
                //u的步长决定曲线的疏密  
                u -= 0.05;
                cv::Point tempP = cv::Point(px, py);
                //存入曲线点   
                if (!ssf.VectorContains(vResPts, tempP))
                {
                    vResPts.push_back(tempP);
                }
            }
        }
    
        //这样做是为了让函数输入和输出可以使用同一个参数
        curvePoint = vResPts;
    
        delete[] midpoints;
        midpoints = nullptr;
        delete[] extrapoints;
        extrapoints = nullptr;
    }
  • 相关阅读:
    [转]Linq to SQL中的实体继承
    [转贴][WCF Security] 3. X509 身份验证
    [转贴]十大网站设计错误
    [转载].NET设计模式(1):开篇
    [转自JeffreyZhao]不妨来做个尝试:UpdatePanel for ASP.NET MVC
    [转]如何快速生成100万不重复的8位均匀分布的随机编号?
    [转贴]X.509 & RSA
    [c#]Webservice中如何实现方法重载(overload)以及如何传送不能序列化的对象作参数
    (Head First 设计模式)学习笔记(2) 观察者模式(气象站实例)
    (Head First 设计模式)学习笔记(1)
  • 原文地址:https://www.cnblogs.com/autumoonchina/p/7700091.html
Copyright © 2011-2022 走看看