Java: Draw a circular spiral using drawArc

10,590

Solution 1

Your idea is almost right. I did some modifications. You need to inverse the angle to draw the other side of the spiral and use fixed point to startAngle.

import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.JFrame;

public class CircSpiral extends JPanel {

    public void paintComponent(Graphics g) {
        int x = getSize().width / 2 - 10;
        int y = getSize().height/ 2 - 10;
        int width = 20;
        int height = 20;
        int startAngle = 0;
        int arcAngle = 180;
        int depth = 10;
        for (int i = 0; i < 10; i++) {
            if (i % 2 == 0) {
                //   g.drawArc(x + 10, y + 10, width, height, startAngle + 10, -arcAngle);
                //  x = x - 5;
                y = y - depth;
                width = width + 2 * depth;
                height = height + 2 * depth;
                g.drawArc(x, y, width, height, startAngle, -arcAngle);
            } else {
                //  g.drawArc(x + 10, y + 10, width, height, startAngle + 10, arcAngle);
                x = x - 2 * depth;
                y = y - depth;
                width = width + 2 * depth;
                height = height + 2 * depth;
                g.drawArc(x, y, width, height, startAngle, arcAngle);
            }
        }
    }

    public static void main(String[] args) {
        CircSpiral panel = new CircSpiral();
        JFrame application = new JFrame();
        application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        application.add(panel);
        application.setSize(300, 300);
        application.setVisible(true);
    }
}

Solution 2

If this were my project, yes I'd draw my arcs in a loop, but within the loop, I'd try to make the arc's bounding box bigger but still centered over the same location. To do this I'd decrement x and y by some small constant, say DELTA (which I'd set to == 1), and I'd increment width and height by 2 * DELTA. I'd also leave my arcAngle unchanged but rather would change my startAngle in the loop like so: startAngle = startAngle - arcAngle;.

For example, this:

import java.awt.Dimension;
import java.awt.Graphics;

import javax.swing.JPanel;
import javax.swing.JFrame;

@SuppressWarnings("serial")
public class CircSpiral extends JPanel {
   private static final int DELTA = 1;
   private static final int ARC_ANGLE = 20;
   private static final int PREF_W = 300;
   private static final int PREF_H = PREF_W;
   private static final int LOOP_MAX = 400;

   public void paintComponent(Graphics g) {
      int x = PREF_W / 2;
      int y = PREF_H / 2;
      int width = 1;
      int height = 1;
      int startAngle = 0;
      int arcAngle = ARC_ANGLE;
      for (int i = 0; i < LOOP_MAX; i++) {
         g.drawArc(x, y, width, height, startAngle, arcAngle);
         x = x - DELTA;
         y = y - DELTA;
         width += 2 * DELTA;
         height += 2 * DELTA;
         startAngle = startAngle - arcAngle;
      }
   }

   @Override
   public Dimension getPreferredSize() {
      if (isPreferredSizeSet()) {
         return super.getPreferredSize();
      }
      return new Dimension(PREF_W, PREF_H);
   }

   public static void main(String[] args) {
      CircSpiral panel = new CircSpiral();
      JFrame application = new JFrame();
      application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      application.add(panel);
      application.pack();
      application.setLocationRelativeTo(null);
      application.setVisible(true);
   }
}

Would result in this:

enter image description here

Solution 3

The following code will output this image:

enter image description here

import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.JFrame;

public class CircSpiral extends JPanel {
    public void paintComponent(Graphics g) {
        int centerX = getWidth() / 2;
        int centerY = getHeight() / 2;

        int numIterations = 5;

        int arcWidth = 10;
        int arcGrowDelta = 30;

        for (int i = 0; i < numIterations; i++) {
            g.drawArc(centerX - arcWidth, centerY - arcWidth, 2 * arcWidth, 2 * arcWidth, 0, 180);
            arcWidth += arcGrowDelta;
            g.drawArc(centerX - arcWidth, centerY - arcWidth, 2 * arcWidth - arcGrowDelta, 2 * arcWidth, 180, 180);
        }
    }

    public static void main(String[] args) {
        CircSpiral panel = new CircSpiral();
        JFrame application = new JFrame();
        application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        application.add(panel);
        application.setSize(300, 300);
        application.setVisible(true);
    }
}

The idea is very simple, just draw the upper half of a circle, like this:

enter image description here

Then increment the arc size by a constant factor and draw the bottom half of the circle but making the end point of this circle and the upper circle match, for it, just substrate the arcGrowDelta from the bottom circle width:

enter image description here

And repeat.

Share:
10,590
user3266259
Author by

user3266259

Updated on June 04, 2022

Comments

  • user3266259
    user3266259 almost 2 years

    I'm working on a java programming exercise where we have to draw a circular spiral using the drawArc method so that the result looks similar to this: enter image description here

    I've been working on this for a while and this is what I have so far:

    import java.awt.Graphics;
    import javax.swing.JPanel;
    import javax.swing.JFrame;
    
    public class CircSpiral extends JPanel {
       public void paintComponent(Graphics g) {
          int x = 100;
          int y = 120;
          int width = 40;
          int height = 60;
          int startAngle = 20;
          int arcAngle = 80;
          for (int i = 0; i < 5; i++) {
             g.drawArc(x, y, width, height, startAngle, arcAngle);
             g.drawArc(x + 10, y + 10, width, height, startAngle + 10, arcAngle);
             x = x + 5;
             y = y + 5;
             startAngle = startAngle - 10;
             arcAngle = arcAngle + 10;
          }
       }
    
       public static void main(String[] args) {
          CircSpiral panel = new CircSpiral();
          JFrame application = new JFrame();
          application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          application.add(panel);
          application.setSize(300, 300);
          application.setVisible(true);
       }
    }
    

    My code gives me this result: enter image description here

    I know the problem lies in my arguments for the drawArc method because the numbers aren't right, but I don't know how to go about making the numbers go in a circular manner. Any help is appreciated. Thank you!