Drawing Smooth Curves in Java Graphics

10,822

Solution 1

You need to enable antaliasing for Graphics2D object.

Do it like this

Graphics graphics = ...
Graphics2D g2d = (Graphics2D) graphics;

g2d.setRenderingHint(
    RenderingHints.KEY_ANTIALIASING,
    RenderingHints.VALUE_ANTIALIAS_ON);

// You can also enable antialiasing for text:

g2d.setRenderingHint(
    RenderingHints.KEY_TEXT_ANTIALIASING,
    RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

Do this before drawing anything using the graphics object.

Also see the RenderingHints javadoc.

Solution 2

Use the Graphics2D with the antialising:

 Graphics2D g2 = (Graphics2D)g;
 g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
     RenderingHints.VALUE_ANTIALIAS_ON);
 //...
 g2.draw(gp);
Share:
10,822
stk1234
Author by

stk1234

Updated on June 04, 2022

Comments

  • stk1234
    stk1234 almost 2 years

    I am trying to draw smooth, bezier-type curves to fit a set of data I have in order to plot it in a java graphics drawing. Below is the code I am currently using to plot. It is plotting the points just fine, except that the curves have sharp edges and sometimes have small fractures in them. Is there a better way that I can make a smooth, fitted curve using java graphics?

    int numProfiles = speedList.size();
            int lenOfList;
            System.out.println();
            System.out.println("Creating a new general path");
    
            //BasicStroke boldStroke = new BasicStroke(.3f);
            //((Graphics2D)g).setStroke(boldStroke);
            for (int i=0; i<numProfiles; i++){
                GeneralPath gp = new GeneralPath();
                g.setColor(colors[i]);
                lenOfList = speedList.get(i).length;
                if (lenOfList < 3) {
                    double xPlotVal1 = xMarginLeft + (((speedList.get(i)[0].getVal() - xMin) / (xMax - xMin)) * width);
                    double yPlotVal1 = yMarginTopAxisTop + (((depthList.get(i)[0].getVal() - yMin) / (yMax - yMin)) * height);
    
                    double xPlotVal2 = xMarginLeft + (((speedList.get(i)[1].getVal() - xMin) / (xMax - xMin)) * width);
                    double yPlotVal2 = yMarginTopAxisTop + (((depthList.get(i)[1].getVal() - yMin) / (yMax - yMin)) * height);
    
                    g.drawLine((int) xPlotVal1, (int) yPlotVal1, (int) xPlotVal2, (int) yPlotVal2);
    
                } else {
                    System.out.println("More than 2 pts");
                    for (int j = 0; j < (lenOfList - 2); j++) {
    
                        double xPlotVal1 = xMarginLeft + (((speedList.get(i)[j].getVal() - xMin) / (xMax - xMin)) * width);
                        double yPlotVal1 = yMarginTopAxisTop + (((depthList.get(i)[j].getVal() - yMin) / (yMax - yMin)) * height);
    
                        double xPlotVal2 = xMarginLeft + (((speedList.get(i)[j + 1].getVal() - xMin) / (xMax - xMin)) * width);
                        double yPlotVal2 = yMarginTopAxisTop + (((depthList.get(i)[j + 1].getVal() - yMin) / (yMax - yMin)) * height);
    
                        double xPlotVal3 = xMarginLeft + (((speedList.get(i)[j + 2].getVal() - xMin) / (xMax - xMin)) * width);
                        double yPlotVal3 = yMarginTopAxisTop + (((depthList.get(i)[j + 2].getVal() - yMin) / (yMax - yMin)) * height);
                        gp.moveTo(xPlotVal1, yPlotVal1);
    
                        if (j==0) gp.moveTo(xPlotVal1, yPlotVal1);
                        //  gp.moveTo(xPlotVal1, yPlotVal1);
                        gp.curveTo(xPlotVal1, yPlotVal1, xPlotVal2, yPlotVal2,
                                xPlotVal3, yPlotVal3);
    
                    }
                    ((Graphics2D) g).draw(gp);
                }
            }
    

    Here is a picture of what it's drawing:
    enter image description here

    //June 26, 2012 at 7:34AM //Here is the updated code after I added the rendering hint

        // the profiles
        Graphics2D g2d = (Graphics2D)g;
        int numProfiles = speedList.size();
        int lenOfList;
        for (int i=0; i<numProfiles; i++){
            GeneralPath gp = new GeneralPath();
            g2d.setColor(colors[i]);
    
            lenOfList = speedList.get(i).length;
            if (lenOfList < 3) {
                double xPlotVal1 = xMarginLeft + (((speedList.get(i)[0].getVal() - xMin) / (xMax - xMin)) * width);
                double yPlotVal1 = yMarginTopAxisTop + (((depthList.get(i)[0].getVal() - yMin) / (yMax - yMin)) * height);
    
                double xPlotVal2 = xMarginLeft + (((speedList.get(i)[1].getVal() - xMin) / (xMax - xMin)) * width);
                double yPlotVal2 = yMarginTopAxisTop + (((depthList.get(i)[1].getVal() - yMin) / (yMax - yMin)) * height);
    
                g2d.drawLine((int) xPlotVal1, (int) yPlotVal1, (int) xPlotVal2, (int) yPlotVal2);
    
            } else {
                for (int j = 0; j < (lenOfList - 2); j++) {
    
                    double xPlotVal1 = xMarginLeft + (((speedList.get(i)[j].getVal() - xMin) / (xMax - xMin)) * width);
                    double yPlotVal1 = yMarginTopAxisTop + (((depthList.get(i)[j].getVal() - yMin) / (yMax - yMin)) * height);
    
                    double xPlotVal2 = xMarginLeft + (((speedList.get(i)[j + 1].getVal() - xMin) / (xMax - xMin)) * width);
                    double yPlotVal2 = yMarginTopAxisTop + (((depthList.get(i)[j + 1].getVal() - yMin) / (yMax - yMin)) * height);
    
                    double xPlotVal3 = xMarginLeft + (((speedList.get(i)[j + 2].getVal() - xMin) / (xMax - xMin)) * width);
                    double yPlotVal3 = yMarginTopAxisTop + (((depthList.get(i)[j + 2].getVal() - yMin) / (yMax - yMin)) * height);
                    gp.moveTo(xPlotVal1, yPlotVal1);
    
                    if (j==0) gp.moveTo(xPlotVal1, yPlotVal1);      //only move at the begining of the curve drawing
                    //  gp.moveTo(xPlotVal1, yPlotVal1);
                    gp.curveTo(xPlotVal1, yPlotVal1, xPlotVal2, yPlotVal2,
                            xPlotVal3, yPlotVal3);
    
                }
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                 g2d.draw(gp);
            }
        }
    

    Here is the newest picture. I am not sure why it's making my background grid lines disappear. I plot the grid lines after I plot the colored profiles. enter image description here

  • stk1234
    stk1234 almost 12 years
    Hmm. I tried the Rendering Hint code and it is still drawing the same picture.
  • npe
    npe almost 12 years
    Post the updated code, perhaps your enabling the hints too late, or on the wrong object. And post your java version too.
  • stk1234
    stk1234 almost 12 years
    Ok, just posted the updated version in my original post below the first try at the code.
  • npe
    npe almost 12 years
    Well, I can see the difference on the new image - the lines are slightly smoother. As to the gridlines - they are visible, but are really faint, you may want to disable anti-aliasing for them (using setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_OFF).
  • stk1234
    stk1234 almost 12 years
    Okay, awesome. The grid lines are back. The curves are smoother--but there is still that sharp corner with the pink one and the hairline split in the green one.
  • npe
    npe almost 12 years
    I'd say, that's because of how your path is build. It just contains those points.