Reputation: 28905
I have an interesting problem. Using Java graphics, I'd like to draw a circle with parallel lines in the circle that are spaced with some pre defined gap constant. The circle has a known x and y position and a radius. The lines should start from the center of the circle and should move outward thereof. For example,
I'd imaging it would be easiest to first draw the lines to fill up the whole square as follows:
and then perhaps draw 4 polygons and fill them in white white. The 4 polygons are labeled as follows:
As you can see, a polygon in this case is defined by a left top point (x,y), edges of width and height defined by the radius of the circle, and then an arc from (x+radius, y+radius).
Feedback needed:
IMPORTANT: note that while this solution has vertical lines, the lines should be defined in terms of some angle theta. That is, they can be angled (but all parallel to each other).
If someone could provide code that actually draws this, I would be forever thankful!! :)
public void draw(Graphics g, int x, int y, int radius, int lineGap, int lineThickness, int theta) {
//g = the graphics object
//x,y = the top left coordinate of the square
//radius = the radius of the circle, the width of the rectangle, the height of the rectangle
//lineGap = the gap in between each of the lines
//lineThickness = the thickness of the lines in pixels
//theta = the angle that the lines should be at, relative to the y axis
}
Upvotes: 1
Views: 5226
Reputation: 347314
Simple change the graphics clipping...
public class SimplePaint02 {
public static void main(String[] args) {
new SimplePaint02();
}
public SimplePaint02() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
@Override
public Dimension getPreferredSize() {
return new Dimension(100, 100);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int radius = Math.min(getWidth(), getHeight());
int x = (getWidth() - radius) / 2;
int y = (getHeight()- radius) / 2;
BufferedImage buffer = new BufferedImage(radius, radius, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = buffer.createGraphics();
Ellipse2D circle = new Ellipse2D.Float(0, 0, radius, radius);
Shape clip = g2d.getClip();
g2d.setClip(circle);
int gap = getWidth() / 10;
g2d.setColor(Color.RED);
for (int index = 0; index < 10; index++) {
g2d.drawLine(index * gap, 0, index * gap, radius);
}
g2d.setClip(clip);
g2d.setColor(Color.BLUE);
g2d.draw(circle);
g2d.dispose();
g.drawImage(buffer, x, y, this);
}
}
}
Update
I should point out that you should NEVER modify any graphics context's clipping that is rendering to the screen, this can seriously screw up the screen rendering ;)
Updated #2
Example showing the use of an AffinTransformation
to support rotation...
public class CirlceDraw {
public static void main(String[] args) {
new CirlceDraw();
}
public CirlceDraw() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
@Override
public Dimension getPreferredSize() {
return new Dimension(100, 100);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int radius = Math.min(getWidth(), getHeight());
int x = (getWidth() - radius) / 2;
int y = (getHeight() - radius) / 2;
BufferedImage buffer = new BufferedImage(radius, radius, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = buffer.createGraphics();
Ellipse2D circle = new Ellipse2D.Float(0, 0, radius, radius);
Shape clip = g2d.getClip();
g2d.setClip(circle);
AffineTransform at = g2d.getTransform();
g2d.setTransform(AffineTransform.getRotateInstance(Math.toRadians(33), radius / 2, radius / 2));
int gap = getWidth() / 10;
g2d.setColor(Color.RED);
for (int index = 0; index < 10; index++) {
g2d.drawLine(index * gap, 0, index * gap, radius);
}
g2d.setTransform(at);
g2d.setClip(clip);
g2d.setColor(Color.BLUE);
g2d.draw(circle);
g2d.dispose();
g.drawImage(buffer, x, y, this);
}
}
}
Upvotes: 3
Reputation: 4810
Using the ol' Pythagorean Thereom, this simple bit of algebra follows...
r is the radius of the circle.
x is a variable you'll make iterate through the circle, in increments you can easily work out from knowing the radius and the spacing.
Knowing the height of each line (and their x position), it won't be a challenge centering the verticle lines parallel to the cirlce center (if your placement coordinates specify the top left corner as they usually do, you'll want to place it at y = circle_center - (line_length / 2)
Note also, that if you do specify the coordinates of the vertical lines via the top left corner, you'll need to consider how thick they are when calculating the x coordinate.
This is extremely simple, using the x value suggested by the circle.
true_x = suggested_x - (line_width / 2)
Refer to other more sensible answers for dealing with angled lines
This procedure remains as a demonstration of the sensibility of using a clip over finding the exact domain/range of each line (and because I wasted so much of my life on it).
Here's where the fun ended for me.
Oomph! Replace that last m with 'tan(theta)'
Upvotes: 5
Reputation: 24895
I would use trigonometry.
The x
of your line is given by the cosinus of the angle from origin (center of the circle). So, arccos(x)
would give you which is the angle.
Once you have the angle, you can have its maxim height by using the sinus sin
function.
Of course, all java trig functions work with radians (360 degrees = 2*PI radians).
Upvotes: 1