欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

绘制图形并填充

程序员文章站 2022-03-28 15:01:44
...
        =====文件名:DrawShape.h=====
#ifndef __DRAWINGS_H_INCLUDED__
#define __DRAWINGS_H_INCLUDED__

#include <wx/dc.h>
#include <wx/dcmemory.h>


//------------------------------------------------------------------------------

wxColour ChangeBrightness(const wxColour &ar_color, int percents)
{
    return wxColour(wxMin(255,int(ar_color.Red  ())*percents/100),
                    wxMin(255,int(ar_color.Green())*percents/100),
                    wxMin(255,int(ar_color.Blue ())*percents/100));
}

//------------------------------------------------------------------------------

void DrawGradientRect (wxDC& dc, wxRect rect, wxColour color_top, wxColour color_bottom, int a_transparency_percent=0)
{
    if (a_transparency_percent > 100) a_transparency_percent = 100;
    if (a_transparency_percent < 0) a_transparency_percent = 0;

    if (a_transparency_percent == 0)
    {
        dc.SetPen(*wxTRANSPARENT_PEN);
        int R0=color_top.Red(),
            G0=color_top.Green(),
            B0=color_top.Blue(),
            R1=color_bottom.Red(),
            G1=color_bottom.Green(),
            B1=color_bottom.Blue();
        int y;
        for (y=rect.GetTop(); y<=rect.GetBottom(); y++)
        {
            int R=R0+(R1-R0)*(y-rect.GetTop())/rect.GetHeight(),
                G=G0+(G1-G0)*(y-rect.GetTop())/rect.GetHeight(),
                B=B0+(B1-B0)*(y-rect.GetTop())/rect.GetHeight();
            dc.SetBrush(wxBrush(wxColour(R,G,B),wxSOLID));
            dc.DrawRectangle(rect.GetLeft(),y,rect.GetWidth(),1);
        }
    }
    else
    {
        wxBitmap bmp(rect.GetWidth(), rect.GetHeight());

        wxMemoryDC mem_dc;
        mem_dc.SelectObject(bmp);

        int R0=color_top.Red(),    G0=color_top.Green(), B0=color_top.Blue(),
            R1=color_bottom.Red(), G1=color_bottom.Green(), B1=color_bottom.Blue();
        for (int y=0; y<rect.GetHeight(); ++y)
        {
            int R=R0+((R1-R0)*y)/(rect.GetHeight() - 1),
                G=G0+((G1-G0)*y)/(rect.GetHeight() - 1),
                B=B0+((B1-B0)*y)/(rect.GetHeight() - 1);
            mem_dc.SetPen(wxPen(wxColour(R,G,B), 1, wxSOLID));
            mem_dc.DrawLine(0, y, rect.GetWidth()-1, y);
        }

        mem_dc.SelectObject(wxNullBitmap);

        wxImage img;
        img = bmp.ConvertToImage();
        img.InitAlpha();

        unsigned char *alpha_plane = img.GetAlpha();
        int alpha = (a_transparency_percent*255)/100;
        memset(alpha_plane, alpha, rect.GetWidth()*rect.GetHeight());

        wxBitmap final_bmp(img, 32);
        dc.DrawBitmap(final_bmp, rect.GetLeftTop(), true);
    }
}

//------------------------------------------------------------------------------

void DrawGradientCircle(wxDC& dc, wxPoint center, int radius, wxColour color_top, wxColour color_bottom)
{
    dc.SetPen(*wxTRANSPARENT_PEN);
    int R0=color_top.Red(),
        G0=color_top.Green(),
        B0=color_top.Blue(),
        R1=color_bottom.Red(),
        G1=color_bottom.Green(),
        B1=color_bottom.Blue();
    int y;
    for (y=-radius; y<=radius; y++)
    {
        int R=R0+(R1-R0)*(y+radius)/(2*radius),
            G=G0+(G1-G0)*(y+radius)/(2*radius),
            B=B0+(B1-B0)*(y+radius)/(2*radius);
        dc.SetBrush(wxBrush(wxColour(R,G,B),wxSOLID));
        double r=y;
        if (r<0)
            r=-r;
        r=wxMax(0.0,r-0.5);
        int x=int(sqrt(double(radius*radius-r*r))+0.5);
        dc.DrawRectangle(center.x-x,center.y+y,x*2+1,1);
    }
}

//------------------------------------------------------------------------------

void DrawGradientSphere(wxDC& dc, wxPoint center, int radius, wxColour color)
{
    dc.SetPen(*wxTRANSPARENT_PEN);
    int R0=color.Red(),
        G0=color.Green(),
        B0=color.Blue();
    int dcol=wxMin(255-R0,wxMin(255-G0,255-B0));
    int R1=R0+dcol,
        G1=G0+dcol,
        B1=B0+dcol;
    wxColour dark=ChangeBrightness(color,50);
    int R2=dark.Red(),
        G2=dark.Green(),
        B2=dark.Blue();
    int R,G,B;
    for (int y=radius*2; y>0; y--)
    {
        if (y>radius)
        {
            R=R0+(R2-R0)*(y-radius)/radius;
            G=G0+(G2-G0)*(y-radius)/radius;
            B=B0+(B2-B0)*(y-radius)/radius;
        }
        else
        {
            R=R1+(R0-R1)*y/radius;
            G=G1+(G0-G1)*y/radius;
            B=B1+(B0-B1)*y/radius;
        }
        dc.SetBrush(wxColour(R,G,B));
        dc.DrawEllipse(center.x-(radius*2-y)/6-(y+1)/2,
                       center.y-(radius*2-y)/6-(y+1)/2,
                       y+1,
                       y+1);
    }
/*    int y;
    int h=radius*2/3;
    for (y=-radius; y<=radius; y++)
    {
        if (y+radius<h)
        {
            R=R0+(R1-R0)*(y+radius)/h;
            G=G0+(G1-G0)*(y+radius)/h;
            B=B0+(B1-B0)*(y+radius)/h;
        }
        else if (y+radius<2*h)
        {
            R=R1+(R0-R1)*(y+radius-h)/h;
            G=G1+(G0-G1)*(y+radius-h)/h;
            B=B1+(B0-B1)*(y+radius-h)/h;
        }
        else
        {
            R=R0+(R2-R0)*(y+radius-2*h)/h;
            G=G0+(G2-G0)*(y+radius-2*h)/h;
            B=B0+(B2-B0)*(y+radius-2*h)/h;
        }
        dc.SetBrush(wxBrush(wxColour(R,G,B),wxSOLID));
        double r=y;
        if (r<0)
            r=-r;
        r=wxMax(0.0,r-0.5);
        int x=int(sqrt(double(radius*radius-r*r))+0.5);
        dc.DrawRectangle(center.x-x,center.y+y,x*2+1,1);
    }
*/
}

//------------------------------------------------------------------------------

void DrawCylinderHor(wxDC& dc, wxRect rect, wxColour color)
{
    dc.SetPen(*wxTRANSPARENT_PEN);
    int R=color.Red(),
        G=color.Green(),
        B=color.Blue();
    int dcol=wxMin(255-R,wxMin(255-G,255-B));
    R+=dcol;
    G+=dcol;
    B+=dcol;
    wxColour dark=ChangeBrightness(color,50);
    int h=rect.height/3;
    DrawGradientRect(dc,wxRect(rect.x,rect.y    ,rect.width,h),color,wxColour(R,G,B));
    DrawGradientRect(dc,wxRect(rect.x,rect.y+h  ,rect.width,h),wxColour(R,G,B),color);
    DrawGradientRect(dc,wxRect(rect.x,rect.y+h*2,rect.width,rect.height-h*2),color,dark);
}

//------------------------------------------------------------------------------

void CalcEllipsePoint (wxRect rect, wxPoint *pts)
{
    double a=rect.width;
    double b=rect.height;
    a/=2;
    b/=2;
    pts[0]=wxPoint(rect.x,rect.y+rect.height/2);
    pts[rect.width]=wxPoint(rect.x+rect.width,rect.y+rect.height/2);
    for (int x=1; x<rect.width; x++)
    {
        double x1=double(rect.width)/2-x;
        double y=b/a*sqrt(wxMax(0,a*a-x1*x1));
        pts[x              ].x=
        pts[rect.width*2-x].x=rect.x+x;
        pts[x              ].y=int(rect.y+double(rect.height)/2+y);
        pts[rect.width*2-x].y=int(rect.y+double(rect.height)/2-y);
    }
}

void DrawCylinderVer(wxDC& dc, wxRect rect, wxColour color)
{
    wxPoint *pts=new wxPoint[rect.width*2];
    wxRect el_rect=rect;
    el_rect.y-=rect.width/4;
    el_rect.height=rect.width/2;
    CalcEllipsePoint(el_rect,pts);
    dc.SetBrush(color);
    dc.SetPen(color);
    dc.DrawPolygon(rect.width*2,pts);

    int R1=color.Red(),
        G1=color.Green(),
        B1=color.Blue();
    int dcol=wxMin(255-R1,wxMin(255-G1,255-B1));
    int R2=R1+dcol,
        G2=G1+dcol,
        B2=B1+dcol;
    wxColour dark=ChangeBrightness(color,50);
    int R3=color.Red(),
        G3=color.Green(),
        B3=color.Blue();
    int w_3=rect.width/3;
    for (int i=0; i<=rect.width; i++)
    {
        wxColour col;
        if (i<w_3)
            col=wxColour(R1+i*(R2-R1)/w_3,
                         G1+i*(G2-G1)/w_3,
                         B1+i*(B2-B1)/w_3);
        else if (i<w_3*2)
            col=wxColour(R2+(i-w_3)*(R1-R2)/w_3,
                         G2+(i-w_3)*(G1-G2)/w_3,
                         B2+(i-w_3)*(B1-B2)/w_3);
        else
            col=wxColour(R1+(i-w_3*2)*(R3-R1)/w_3,
                         G1+(i-w_3*2)*(G3-G1)/w_3,
                         B1+(i-w_3*2)*(B3-B1)/w_3);
        dc.SetPen(col);
        dc.DrawLine(rect.x+i,pts[i].y,rect.x+i,pts[i].y+rect.height);
    }
    delete[] pts;
}

//------------------------------------------------------------------------------

void DrawCylinderVerHatch(wxDC& dc, wxRect rect, wxColour color)
{
    wxPoint *pts=new wxPoint[rect.width*2+2];
    wxRect el_rect=rect;
    el_rect.y-=rect.width/4;
    el_rect.height=rect.width/2;
    CalcEllipsePoint(el_rect,pts);
    for (int i=rect.width*2+1; i>=0; i--)
    {
        if (i==rect.width*2+1)
            pts[i]=pts[0];
        else if (i>rect.width)
        {
            pts[i].x=pts[i-1].x;
            pts[i].y=pts[i-1].y;
        }
        else if (i<=rect.width)
            pts[i].y+=rect.height;
    }
    dc.SetBrush(wxBrush(color, wxBDIAGONAL_HATCH));
    dc.SetPen(color);
    dc.DrawPolygon(rect.width*2+2,pts);
    CalcEllipsePoint(el_rect,pts);
    dc.SetBrush(*wxWHITE);
    dc.DrawPolygon(rect.width*2,pts);
}

//------------------------------------------------------------------------------

void DrawCylinderVerContour(wxDC& dc, wxRect rect, wxColour color)
{
    wxPoint *pts=new wxPoint[rect.width*2+2];
    wxRect el_rect=rect;
    el_rect.y-=rect.width/3;
    el_rect.height=rect.width*2/3;
    CalcEllipsePoint(el_rect,pts);
    for (int i=rect.width*2+1; i>=0; i--)
    {
        if (i==rect.width*2+1)
            pts[i]=pts[0];
        else if (i>rect.width)
        {
            pts[i].x=pts[i-1].x;
            pts[i].y=pts[i-1].y;
        }
        else if (i<=rect.width)
            pts[i].y+=rect.height;
    }
    dc.SetBrush(*wxTRANSPARENT_BRUSH);
    dc.SetPen(color);
    dc.DrawPolygon(rect.width*2+2,pts);
}
////////////////////////////////////////////////////////////////////////////////

#endif // __DRAWINGS_H_INCLUDED__