zoukankan      html  css  js  c++  java
  • Bezier n阶通用版本C++实现

    #pragma once
    #include "gstl.h"
    #include <vector>
    #include "SmoothSampling.h"
    
    using namespace gstl;
    
    /*
        n阶 bezier 曲线通用公式
    */
    class GachaBazier
    {
    public:
        GachaBazier(const Vector2<f32>& start,const Vector2<f32>& dest);
        void addCtrlPoint(const Vector2<f32>& ctrlPoint);
        Vector2<f32> getInterpolatePos(float t);
    private:
        float getKanbudong(float n, float i);
        float getJieCheng(int n);
    
    private:
        Vector2<f32>    m_start;
        Vector2<f32>    m_dest;
        std::vector<Vector2<f32>>    m_ctrl;
    };
    
    class GachaBezierSmooth : public BoloScriptFastLib,public GachaBazier
    {
    generatedBoloObject(GachaBezierSmooth,"GachaBezierSmooth");
        GachaBezierSmooth();
        virtual ~GachaBezierSmooth();
    public:
        void sampling(int fSamplingNum = 100);
        float getSmoothY(float fx);
        vec2 getMinSampling();
        vec2 getMaxSampling();
    
        void setStart(vec2 tStart);
        void setEnd(vec2 tEnd);
    
    private:
        SmoothSampling m_tSmoothSampling;
        // 网页上 看到的 起始点和目标点都是 写死的 0,0  1,1 两个点, 对应返回的百分比需要按比例变大变小
        vec2 m_tStart;
        vec2 m_tEnd;
    };
    
    
    /*
        3次贝塞尔曲线差值器
        http://cubic-bezier.com
    
        css3 3次贝塞尔曲线 cubic-bezier
        https://blog.csdn.net/zhaozjc112/article/details/52909172/
    
        起点永远算作 (0,0) 终点永远算作 (1,1)
    
        控制点有且只有2个
        (m_x1,m_y1) (m_x2,m_y2)
    */
    class GachaCubicBezierInter
    {
    public:
        GachaCubicBezierInter();
        ~GachaCubicBezierInter();
    
        void setPt1(float x,float y);
        void setPt2(float x,float y);
        void prepare();
    
        f32 getY(float x);
    private:
        Vector2<f32>    m_pt1;
        Vector2<f32>    m_pt2;
        GachaBazier*    m_bezier = nullptr;
    };
    #include "GachaBezierInter.h"
    #include <math.h>
    #include <cassert>
    
    extern float clampf(float& v, float min, float max);
    
    GachaBazier::GachaBazier(const Vector2<f32>& start, const Vector2<f32>& dest)
    {
        m_start = start;
        m_dest = dest;
        m_ctrl.push_back(m_start);
        m_ctrl.push_back(m_dest);
    }
    
    void GachaBazier::addCtrlPoint(const Vector2<f32>& point) {
        Vector2<f32> pt = point;
        size_t len = m_ctrl.size();
        m_ctrl.insert(m_ctrl.begin() + len - 1, pt);
    }
    
    
    Vector2<f32> GachaBazier::getInterpolatePos(float t) 
    {
        //t = clampf(t, -1.f, 1.f);
        if (t < -1.f)
        {
            printf("dddaaa
    ");
        }
        if (t < 0.f)
        {
            printf("fsfdsa
    ");
        }
        if (t > 1.f)
        {
            printf("ddd
    ");
        }
        Vector2<f32> pt;
        assert(m_ctrl.size() >= 2);
    
        int n = m_ctrl.size() - 1;
        for (int i = 0; i <= n; i++) {
            pt.x += getKanbudong(n, i) * pow((1 - t), n - i) * pow(t, i) * m_ctrl[i].x;
            pt.y += getKanbudong(n, i) * pow((1 - t), n - i) * pow(t, i) * m_ctrl[i].y;
        }
    
        return pt;
    }
    
    float GachaBazier::getKanbudong(float n, float i) {
        return getJieCheng(n) / (getJieCheng(i) * getJieCheng(n - i));
    }
    
    float GachaBazier::getJieCheng(int n) {
        float result = 1.0f;
        for (int i = 1; i <= n; i++) {
            result *= i;
        }
        return result;
    }
    
    //////////////////////////////////////////////////////////////////////////
    
    GachaBezierSmooth::~GachaBezierSmooth()
    {
    
    }
    
    GachaBezierSmooth::GachaBezierSmooth() : GachaBazier(vec2::zero, vec2(1.f, 1.f))
    {
    
    }
    
    void GachaBezierSmooth::setStart(vec2 tStart)
    {
        m_tStart = tStart;
    }
    
    void GachaBezierSmooth::setEnd(vec2 tEnd)
    {
        m_tEnd = tEnd;
    }
    
    void GachaBezierSmooth::sampling(int fSamplingNum)
    {
        // 需要添加对应的采样点
        float fDelay = 1.f / fSamplingNum;
        for (float i = 0.f; i < 1.f; i += fDelay)
        {
            vec2 tVec2 = getInterpolatePos(i);
            tVec2 = (m_tEnd - m_tStart) * tVec2 + m_tStart;
            m_tSmoothSampling.insertPoint(tVec2.x, tVec2.y);
        }
    }
    
    float GachaBezierSmooth::getSmoothY(float fx)
    {
        return m_tSmoothSampling.getSmooth(fx);
    }
    
    vec2 GachaBezierSmooth::getMinSampling()
    {
        auto it = m_tSmoothSampling.m_sortMpSampling.begin();
        if (it == m_tSmoothSampling.m_sortMpSampling.end())
        {
            return vec2::zero;
        }
        return vec2(it->first, it->second);
    }
    vec2 GachaBezierSmooth::getMaxSampling()
    {
        if (m_tSmoothSampling.m_sortMpSampling.size() <= 0)
        {
            return vec2::zero;
        }
        auto it = m_tSmoothSampling.m_sortMpSampling.end();
        it--;
        return vec2(it->first, it->second);
    }
    
    SC_Entry GachaBezierSmooth_setStart(BoloScriptFast* stack, BoloScriptFastLib* ptr)
    {
        GachaBezierSmooth* pGachaBezierSmooth = dynamic_cast<GachaBezierSmooth*>(ptr);
        float fx = bolo_float(stack);
        float fy = bolo_float(stack);
        pGachaBezierSmooth->setStart(vec2(fx, fy));
        return SC_Entry();
    }
    
    SC_Entry GachaBezierSmooth_setEnd(BoloScriptFast* stack, BoloScriptFastLib* ptr)
    {
        GachaBezierSmooth* pGachaBezierSmooth = dynamic_cast<GachaBezierSmooth*>(ptr);
        float fx = bolo_float(stack);
        float fy = bolo_float(stack);
        pGachaBezierSmooth->setEnd(vec2(fx, fy));
        return SC_Entry();
    }
    
    SC_Entry GachaBezierSmooth_addCtrlPoint(BoloScriptFast* stack, BoloScriptFastLib* ptr)
    {
        GachaBezierSmooth* pGachaBezierSmooth = dynamic_cast<GachaBezierSmooth*>(ptr);
        float fx = bolo_float(stack);
        float fy = bolo_float(stack);
        pGachaBezierSmooth->addCtrlPoint(vec2(fx, fy));
        return SC_Entry();
    }
    
    SC_Entry GachaBezierSmooth_sampling(BoloScriptFast* stack, BoloScriptFastLib* ptr)
    {
        GachaBezierSmooth* pGachaBezierSmooth = dynamic_cast<GachaBezierSmooth*>(ptr);
        int nSamplingNum = bolo_int(stack);
        pGachaBezierSmooth->sampling(nSamplingNum);
        return SC_Entry();
    }
    
    SC_Entry GachaBezierSmooth_getSmoothY(BoloScriptFast* stack, BoloScriptFastLib* ptr)
    {
        GachaBezierSmooth* pGachaBezierSmooth = dynamic_cast<GachaBezierSmooth*>(ptr);
        float fx = bolo_float(stack);
        return pGachaBezierSmooth->getSmoothY(fx);
    }
    
    SC_Entry GachaBezierSmooth_getMinSampling(BoloScriptFast* stack, BoloScriptFastLib* ptr)
    {
        GachaBezierSmooth* pGachaBezierSmooth = dynamic_cast<GachaBezierSmooth*>(ptr);
        vec2 tPos = pGachaBezierSmooth->getMinSampling();
        SC_Entry* pVec = new SC_Entry[2]
        {
            tPos.x, tPos.y
        };
        return SC_Entry(pVec, 2);
    }
    
    SC_Entry GachaBezierSmooth_getMaxSampling(BoloScriptFast* stack, BoloScriptFastLib* ptr)
    {
        GachaBezierSmooth* pGachaBezierSmooth = dynamic_cast<GachaBezierSmooth*>(ptr);
        vec2 tPos = pGachaBezierSmooth->getMaxSampling();
        SC_Entry* pVec = new SC_Entry[2]
        {
            tPos.x, tPos.y
        };
        return SC_Entry(pVec, 2);
    }
    
    
    void GachaBezierSmooth::registerReflection(s32 id)
    {
        registerFunc(id, "setStart", GachaBezierSmooth_setStart);
        registerFunc(id, "setEnd", GachaBezierSmooth_setEnd);
        registerFunc(id, "addCtrlPoint", GachaBezierSmooth_addCtrlPoint);
        registerFunc(id, "sampling", GachaBezierSmooth_sampling);
        registerFunc(id, "getSmoothY", GachaBezierSmooth_getSmoothY);
        registerFunc(id, "getMinSampling", GachaBezierSmooth_getMinSampling);
        registerFunc(id, "getMaxSampling", GachaBezierSmooth_getMaxSampling);
        
    }
    
    ///////////////////////////////
    
    GachaCubicBezierInter::GachaCubicBezierInter()
    {
        m_pt1.x = 0.f;
        m_pt1.y = 0.f;
        m_pt2.x = 1.f;
        m_pt2.y = 1.f;
    
        Vector2<f32> start(0.f, 0.f);
        Vector2<f32> dest(1.f,1.f);
        m_bezier = new GachaBazier(start,dest);
    }
    
    GachaCubicBezierInter::~GachaCubicBezierInter()
    {
        delete m_bezier;
        m_bezier = nullptr;
    }
    
    f32 GachaCubicBezierInter::getY(float x)
    {
        Vector2<f32> pos = m_bezier->getInterpolatePos(x);
        return pos.y;
    }
    
    void GachaCubicBezierInter::setPt1(float x, float y)
    {
        m_pt1.x = x;
        m_pt1.y = y;
    }
    
    void GachaCubicBezierInter::setPt2(float x, float y)
    {
        m_pt2.x = x;
        m_pt2.y = y;
    }
    
    void GachaCubicBezierInter::prepare()
    {
        m_bezier->addCtrlPoint(m_pt1);
        m_bezier->addCtrlPoint(m_pt2);
    }
  • 相关阅读:
    htpasswd命令
    GitHub访问速度慢的解决方法
    easyui datagrid 首次不加载做法
    Excel日常操作
    补偿接口中循环一直执行sql的问题
    rabbitMq无法消费发送的q的问题
    Unicode与中文转换工具类方法(转)
    idea 一些插件配置
    线程安全的集合类、CopyOnWrite机制介绍(转)
    java websocket学习
  • 原文地址:https://www.cnblogs.com/zijian-yang/p/13273692.html
Copyright © 2011-2022 走看看