C++ 四舍五入轮廓的起点和终点

C++ 四舍五入轮廓的起点和终点,c++,c,graphics,vector,C++,C,Graphics,Vector,我使用以下算法生成多边形轮廓: void OGLSHAPE::GenerateLinePoly(std::vector<DOUBLEPOINT> &input, int width) { OutlineVec.clear(); if(input.size() < 2) { return; } if(connected) { input.push_back(input[0]);

我使用以下算法生成多边形轮廓:

void OGLSHAPE::GenerateLinePoly(std::vector<DOUBLEPOINT> &input, int width)
{
    OutlineVec.clear();
    if(input.size() < 2)
    {
        return;
    }


    if(connected)
    {
        input.push_back(input[0]);
        input.push_back(input[1]);
    }


    float w = width / 2.0f;

    //glBegin(GL_TRIANGLES);
    for( size_t i = 0; i < input.size()-1; ++i )
    {
        POINTFLOAT cur;
        cur.x = input[i].point[0];
        cur.y = input[i].point[1];


        POINTFLOAT nxt;


        nxt.x = input[i+1].point[0];
        nxt.y = input[i+1].point[1];

        POINTFLOAT b;
        b.x = nxt.x - cur.x;
        b.y = nxt.y - cur.y;

        b = normalize(b);



        POINTFLOAT b_perp;
        b_perp.x = -b.y;
        b_perp.y = b.x;


        POINTFLOAT p0;
        POINTFLOAT p1;
        POINTFLOAT p2;
        POINTFLOAT p3;

        p0.x = cur.x + b_perp.x * w;
        p0.y = cur.y + b_perp.y * w;

        p1.x = cur.x - b_perp.x * w;
        p1.y = cur.y - b_perp.y * w;

        p2.x = nxt.x + b_perp.x * w;
        p2.y = nxt.y + b_perp.y * w;

        p3.x = nxt.x - b_perp.x * w;
        p3.y = nxt.y - b_perp.y * w;

        OutlineVec.push_back(p0.x);
        OutlineVec.push_back(p0.y);
        OutlineVec.push_back(p1.x);
        OutlineVec.push_back(p1.y);
        OutlineVec.push_back(p2.x);
        OutlineVec.push_back(p2.y);

        OutlineVec.push_back(p2.x);
        OutlineVec.push_back(p2.y);
        OutlineVec.push_back(p1.x);
        OutlineVec.push_back(p1.y);
        OutlineVec.push_back(p3.x);
        OutlineVec.push_back(p3.y);



        // only do joins when we have a prv
        if( i == 0 ) continue;


        POINTFLOAT prv;
        prv.x = input[i-1].point[0];
        prv.y = input[i-1].point[1];

        POINTFLOAT a;
        a.x = prv.x - cur.x;
        a.y = prv.y - cur.y;

        a = normalize(a);

        POINTFLOAT a_perp;
        a_perp.x = a.y;
        a_perp.y = -a.x;

        float det = a.x * b.y  - b.x * a.y;
        if( det > 0 )
        {
            a_perp.x = -a_perp.x;
            a_perp.y = -a_perp.y;

            b_perp.x = -b_perp.x;
            b_perp.y = -b_perp.y;
        }

        // TODO: do inner miter calculation

        // flip around normals and calculate round join points
        a_perp.x = -a_perp.x;
        a_perp.y = -a_perp.y;

        b_perp.x = -b_perp.x;
        b_perp.y = -b_perp.y;

        size_t num_pts = 4;

        std::vector< POINTFLOAT> round( 1 + num_pts + 1 );
        POINTFLOAT nc;
        nc.x = cur.x + (a_perp.x * w);
        nc.y = cur.y + (a_perp.y * w);

        round.front() = nc;

        nc.x = cur.x + (b_perp.x * w);
        nc.y = cur.y + (b_perp.y * w);

        round.back() = nc;

        for( size_t j = 1; j < num_pts+1; ++j )
        {
            float t = (float)j/(float)(num_pts+1);
            if( det > 0 )
         {
             POINTFLOAT nin;
             nin = slerp2d( b_perp, a_perp, 1.0f-t );
             nin.x *= w;
             nin.y *= w;

             nin.x += cur.x;
             nin.y += cur.y;

             round[j] = nin;
         }
            else
         {
             POINTFLOAT nin;
             nin = slerp2d( a_perp, b_perp, t );
             nin.x *= w;
             nin.y *= w;

             nin.x += cur.x;
             nin.y += cur.y;

             round[j] = nin;
         }
        }

        for( size_t j = 0; j < round.size()-1; ++j )
        {

            OutlineVec.push_back(cur.x);
            OutlineVec.push_back(cur.y);


            if( det > 0 )
         {
             OutlineVec.push_back(round[j + 1].x);
             OutlineVec.push_back(round[j + 1].y);
             OutlineVec.push_back(round[j].x);
             OutlineVec.push_back(round[j].y);
         }
            else
         {

             OutlineVec.push_back(round[j].x);
             OutlineVec.push_back(round[j].y);

             OutlineVec.push_back(round[j + 1].x);
             OutlineVec.push_back(round[j + 1].y);
         }
        }
    }

}

POINTFLOAT multiply(const POINTFLOAT &a, float b)
{
    POINTFLOAT result;
    result.x = a.x * b;
    result.y = a.y * b;
    return result;
}

POINTFLOAT normalize(const POINTFLOAT &a)
{
    return multiply(a, 1.0f/sqrt(a.x*a.x+a.y*a.y));
}


POINTFLOAT slerp2d( const POINTFLOAT &v0, 
                   const POINTFLOAT &v1, float t )
{
    float dot = (v0.x * v1.x + v0.y * v1.y);

    if( dot < -1.0f ) dot = -1.0f;
    if( dot > 1.0f ) dot = 1.0f;

    float theta_0 = acos( dot );
    float theta = theta_0 * t;

    POINTFLOAT v2;
    v2.x = -v0.y;
    v2.y = v0.x;

    POINTFLOAT result;
    result.x = v0.x * cos(theta) + v2.x * sin(theta);
    result.y = v0.y * cos(theta) + v2.y * sin(theta);

    return result;
}
void OGLSHAPE::GenerateLinePoly(std::vector&input,int-width)
{
OutlineVec.clear();
if(input.size()<2)
{
返回;
}
如果(已连接)
{
输入。推回(输入[0]);
输入。推回(输入[1]);
}
浮子w=宽度/2.0f;
//glBegin(GL_三角形);
对于(size_t i=0;i0)
{
a_perp.x=-a_perp.x;
a_perp.y=-a_perp.y;
b_perp.x=-b_perp.x;
b_perp.y=-b_perp.y;
}
//TODO:执行内部斜接计算
//翻转法线并计算圆形连接点
a_perp.x=-a_perp.x;
a_perp.y=-a_perp.y;
b_perp.x=-b_perp.x;
b_perp.y=-b_perp.y;
大小/数量/分=4;
标准:向量四舍五入(1+num\u pts+1);
点浮点数控;
nc.x=电流x+(a_perp.x*w);
nc.y=当前y+(a_perp.y*w);
圆形前()=nc;
nc.x=电流x+(b_perp.x*w);
nc.y=电流y+(b_perp.y*w);
round.back()=nc;
对于(大小j=1;j0)
{
点花素;
nin=slerp2d(b_perp,a_perp,1.0f-t);
nin.x*=w;
年y*=w;
nin.x+=电流x;
年y+=当前y;
圆形[j]=nin;
}
其他的
{
点花素;
nin=slerp2d(a_perp,b_perp,t);
nin.x*=w;
年y*=w;
nin.x+=电流x;
年y+=当前y;
圆形[j]=nin;
}
}
对于(大小j=0;j0)
{
OutlineVec.push_back(圆形[j+1].x);
Outlineveec.向后推(圆形[j+1].y);
OutlineVec.push_back(圆形[j].x);
OutlineVec.push_back(圆形[j].y);
}
其他的
{
OutlineVec.push_back(圆形[j].x);
OutlineVec.push_back(圆形[j].y);
OutlineVec.push_back(圆形[j+1].x);
Outlineveec.向后推(圆形[j+1].y);
}
}
}
}
点浮点乘法(常量点浮点和a、浮点b)
{
点浮点结果;
结果x=a.x*b;
结果y=a.y*b;
返回结果;
}
POINTFLOAT规范化(常量POINTFLOAT&a)
{
返回乘法(a,1.0f/sqrt(a.x*a.x+a.y*a.y));
}
点浮点slerp2d(常数点浮点和v0,
常量点浮点和v1,浮点t)
{
浮点数=(v0.x*v1.x+v0.y*v1.y);
如果(点<-1.0f)点=-1.0f;
如果(点>1.0f)点=1.0f;
浮点θ0=acos(点);
浮点θ=θ0*t;
点浮点v2;
v2.x=-v0.y;
v2.y=v0.x;
点浮点结果;
结果x=v0.x*cos(θ)+v2.x*sin(θ);
结果y=v0.y*cos(θ)+v2.y*sin(θ);
返回结果;
}
我注意到矢量绘图应用程序允许圆化线段的开始和结束。如何修改直线生成算法,以使未连接线段的起点和终点圆整

我的意思见以下示例:

谢谢

编辑
再想一想,贝塞尔曲线就没那么有用了,因为它们需要您添加额外的点,然后您需要区分哪些路径应该绘制为直线,哪些路径应该绘制为曲线

本质上,您需要一个具有以下原型的函数:

void DrawRoundedRectangle(Rectangle rect, Angle angle);
我的主要观点仍然是,渲染矩形坐标的代码不需要修改,添加任何舍入都取决于渲染代码

我相信GDI+能够做到这一点

如果我可以问的话,您开发的是什么平台,使用的是什么库?:)

原创帖子

生成线条的算法基本上可以保持不变。渲染代码需要将点连接为贝塞尔曲线,而不是直线

所以你基本上需要一个贝塞尔渲染库。我在Windows上使用了GDI+<