简体   繁体   中英

C# GDI+ curve drawing issue

I'm trying to draw a series of connected segments, but the curved segments seem to produce an artifact, whereby the outer side of the curve is not smooth at all, but very jagged. This is part of a GIS program I am making.

For these lines, the line itself needs to be quite wide, as this represents the range of data that can be collected on this line for the GIS data. There also has to be an area directly under the line where no data is collected. This also can be wide, but not as wide as the main line.

I have done this using a graphics path, which I then widen and use as a clipping region to block the area directly under the line. I then draw the actual line. The sample code below does this, with made up values for ease of regenerating.

This works fine with straight lines, but with curved lines there are very irregular shapes on the outside of the curves. I have no idea why this happens.

Any ideas would be much appreciated, cheers,

Greg

I made this sample code using a basic form with a picturebox and a button on it, whereby when I clicked the button it would execute this method:

    private void drawCurvedLine()
    {
        //initialise the plot area:
        Bitmap image = new Bitmap(pictureBox1.Width, pictureBox1.Height);
        pictureBox1.BackgroundImage = image;

        Graphics g = Graphics.FromImage(image);

        //the width of the pen represents the width of a sonar swathe:
        Pen widePen = new Pen(new SolidBrush(Color.FromArgb(80, Color.Blue)), 50);

        PointF[] points = new PointF[4];

        //first straight:
        points[0] = new PointF(287.284149F,21.236269F);
        points[1] = new PointF(183.638443F,406.936249F);

        //second straight:
        points[2] = new PointF(130.842773F, 515.574036F);
        points[3] = new PointF(-1950.91321F, 3491.868F);

        //graphics path for the line:
        GraphicsPath gPath = new GraphicsPath();

        gPath.AddLine(points[0], points[1]);
        gPath.AddArc(new RectangleF(-445.464447F,3.84924316F,640.067444F,640.067444F), -(90 - 105.0412369999982F), 10.8775282F);
        gPath.AddArc(new RectangleF(-445.464417F, 3.84915161F, 640.067444F, 640.067444F), -(90 - 115.91811484539707F), 10.8775091F);
        gPath.AddLine(points[2], points[3]);

        //widen the line to the width equal to what the fish will not be able to see:
        gPath.Widen(new Pen(Color.White, 10));

        //now exclude that widened line from the main graphics:
        g.ExcludeClip(new Region(gPath));

        //draw the swathe line:
        g.DrawPath(widePen, gPath);

        //reset the clipping for the next line:
        g.ResetClip();
    }

Try to use a separate GraphicsPath for excluded region:

private void drawCurvedLine()
{
    //initialise the plot area:
    Bitmap image = new Bitmap(pictureBox1.Width, pictureBox1.Height);
    pictureBox1.BackgroundImage = image;

    using(Graphics g = Graphics.FromImage(image))
    {
        PointF[] points = new PointF[4];

        //first straight:
        points[0] = new PointF(287.284149F, 21.236269F);
        points[1] = new PointF(183.638443F, 406.936249F);

        //second straight:
        points[2] = new PointF(130.842773F, 515.574036F);
        points[3] = new PointF(-1950.91321F, 3491.868F);

        //graphics path for the line:
        using(GraphicsPath gPath = new GraphicsPath())
        {
            gPath.AddLine(points[0], points[1]);
            gPath.AddArc(new RectangleF(-445.464447F, 3.84924316F, 640.067444F, 640.067444F), -(90 - 105.0412369999982F), 10.8775282F);
            gPath.AddArc(new RectangleF(-445.464417F, 3.84915161F, 640.067444F, 640.067444F), -(90 - 115.91811484539707F), 10.8775091F);
            gPath.AddLine(points[2], points[3]);

            //widen the line to the width equal to what the fish will not be able to see:
            using(GraphicsPath innerPath = (GraphicsPath)gPath.Clone())
            {
                using(Pen pen = new Pen(Color.White, 10))
                {
                    innerPath.Widen(pen);
                }

                //now exclude that widened line from the main graphics:
                using(Region reg = new Region(innerPath))
                {
                    g.ExcludeClip(reg);

                    //draw the swathe line:
                    //the width of the pen represents the width of a sonar swathe:
                    using(Pen widePen = new Pen(new SolidBrush(Color.FromArgb(80, Color.Blue)), 50))
                    {
                        g.DrawPath(widePen, gPath);
                    }

                    //reset the clipping for the next line:
                    g.ResetClip();
                }
            }
        }

    }
}

Set the smoothing mode properly on your Graphics instance. Take a look here .

Try setting the CompositingQuality, the InterpolationMode and the SmoothingMode properties to increase the quality of your Graphics object:

using(Graphics g = Graphics.FromImage(image))
{
    g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
    g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
    g.SmoothingMode = SmoothingMode.AntiAlias;
    //...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM