2

I want to draw a figure using float or double values, to be precise.

I use:

g.drawOval(0, 0, 10, 10);

to draw a circle, but I only can use integer values.

Is there any statement that use float/double values that do the same?

Here is a picture: Problem

The circles have to be centered, and I can't. Any solution?

Code:

import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JPanel;

public class Bulls_EYE extends JPanel
{
    int red, green, blue;
    int height, width;
    int heightOval = 475, widthOval = 475;
    Random rValue = new Random();

    public void paint (Graphics g)
    {           
        super.paint(g);

        for (int idx = 0; idx < 100; idx++)
        {
        g.setColor(new Color(red = 1 + rValue.nextInt(255), green = 1 + rValue.nextInt(255), blue = 1 + rValue.nextInt(255)));
        g.fillOval(width+2*idx, height+2*idx, widthOval-5*idx, heightOval-5*idx);
        }
    }
}
Roman C
  • 49,761
  • 33
  • 66
  • 176
Nuno Batalha
  • 151
  • 2
  • 5
  • 16
  • 1
    could this link help you? it's an implementation of graphics but allowing float values for drawOval --> http://sf-library.googlecode.com/svn-history/r16/trunk/SF/src/com/studiofortress/sf/graphics/GraphicsGL.java – luchosrock Mar 28 '13 at 19:41

3 Answers3

2

You can use the Arc2D class for drawing circles with float/double precision, since it is a Shape and the Graphics2D class can draw shapes.

@Override
protected void paintComponent(Graphics g) {
    Graphics2D g2d = (Graphics2D) g;
    Shape circle = new Arc2D.Double(
            // Same values as used in the fillOval function,
            // but with double precision.
            x, y, width, height,
            // Draw a full circle (yes, in degrees).
            0, 360,
            // Connect the endpoint with the startpoint.
            Arc2D.CORD
    );
    // Paint the circle.
    g2d.fill(circle);
}

In a similar way, you can draw rectangles by using the Rectangle2D class.

Also, please use the paintComponent function instead of the paint function, as explained here.

Edit:
As Gerhard explains in his comment, using Ellipse2D is of course much better and clearer in this case as shown here:

@Override
protected void paintComponent(Graphics g) {     Graphics2D g2d = (Graphics2D) g;
    Shape circle = new Ellipse2D.Double(x, y, width, height);
    g2d.fill(circle);
}
Kaj Wortel
  • 61
  • 6
  • Instead of using 'Arc2D.Double', you might want to use 'Ellipse2D.Float' or 'Ellipse2D.Double'. – Gerhard Apr 01 '23 at 08:56
1

I think it's an interesting question but needs more context. Drawing primitives are usually expressed in pixel coordinates so fractions of a pixel do not make much sense.

If you want precision like a CAD application note that what is displayed on the screen is only an approximation of the underlying model due to the limitations of the display.

You can represent your models precisely in memory (with limitations in floating point representation) and draw the approximation on the screen.

Update

Based on your last update:

We know from the JavaDoc that fillOval takes as parameters (x, y, w, h) where x, y are the upper left coordinates, and w, h are the width and height.

If for each concentric circle you move the upper left coordinates inward, in this case by 2 px, to keep them centered, you must also reduce the width and height by twice that amount. Change the following line:

g.fillOval(width+2*idx, height+2*idx, widthOval-5*idx, heightOval-5*idx);

To

int dx, dy, dw, dh;
dx = 2*idx;
dy = 2*idx;
dw = 2*dx; // note this is 4*idx not 5*idx like you have currently
dh = 2*dy;
g.fillOval(width+dx, height+dy, widthOval-dw, heightOval-dh);

Note that your width and height variables being used in the first and second parameters really doesn't have anything to do with width and height but instead are providing a beginning offset from the origin where the oval is drawn.

Dave Rager
  • 8,002
  • 3
  • 33
  • 52
  • Fractions of a pixel make sense. The idea is called antialiasing. See my answer about how to do this properly: http://stackoverflow.com/a/31221395/1143274 – Evgeni Sergeev Jul 04 '15 at 14:12
  • @EvgeniSergeev antialiasing is beyond the scope of this question and it still isn't "fractions of a pixel". Antialiasing fakes it using multiple pixels of gradient values to give the illusion of smooth lines and curves. There is no such thing as a fraction of a pixel. You can't draw between pixels. They are addressed using whole numbers. OPs original question was vague and I was answering why pixel coordinates are expressed as integer values and not floats or doubles. – Dave Rager Jul 06 '15 at 20:11
0

There is no reason you should do this, because when drawing an oval with the given coordinates, they are referred to pixels on the screen. Since you can't draw between pixels, 1 is the smallest unit you can use. If you want to round the values before drawing, you can use

g.drawOval(Math.round(a),Math.round(b),Math.round(x),Math.round(y)

which will round the float a, b, x and y before drawing the oval. The only reason I can see is that you calculate the coordinates and the result is a float, then you need to round it like above.

D180
  • 722
  • 6
  • 20
  • okay then just forget my answer. The next time please make clear what you want though :) – D180 Mar 28 '13 at 20:05
  • 1
    Another answer with no clue about antialiasing. Think about it this way: what happens if we draw it on a larger pixel grid (i.e. higher resolution), and then scale the image, e.g. to half-by-half the size, blending four neighbouring pixels into one colour? You can do the same, bypassing this actual procedure. Java library API can do this already. Just different method calls need to be used: http://stackoverflow.com/a/31221395/1143274 – Evgeni Sergeev Jul 04 '15 at 14:17