I'm making an application about space physics, so I do lots with orbits. Naturally, I encounter the Ellipse2D.Double to draw my orbits on the screen.
Whenever my JPanel refreshes, I draw the orbit of a body using an Ellipse2D, as well as the body itself with a different method.
Essentially, I discovered that when numbers get very large (whether it be the size of the orbits get large or the visualization is zoomed in very far), the position of the body and the Ellipse2D do not line up.
I calculate the position of the body using a conversion from polar coordinates to rectangular coordinates, and I leave the math for the Ellipse2D up to the geom package.
Take a look at this code sample. It's the most self-contained version of my problem that I can make, since scale of the circle has to be very large:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.math.BigDecimal;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class EllipseDemo extends JPanel {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(500, 500);
frame.add(new EllipseDemo());
frame.setVisible(true);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
// These values allow for a very zoomed in view of a piece of the circle
BigDecimal[] circleCenter = { new BigDecimal(-262842.5), new BigDecimal(-93212.8) };
BigDecimal circleRadius = new BigDecimal(279081.3);
// Draw the circle at the given center, with the given width and height
// x = centerx - radius, y = centery - radius, w = h = radius * 2
g2d.draw(new Ellipse2D.Double(circleCenter[0].subtract(circleRadius).doubleValue(),
circleCenter[1].subtract(circleRadius).doubleValue(), circleRadius.multiply(new BigDecimal(2)).doubleValue(),
circleRadius.multiply(new BigDecimal(2)).doubleValue()));
// Get a rectangular conversion of a point on the circle at this angle
BigDecimal angle = new BigDecimal(0.34117696217);
BigDecimal[] rectangular = convertPolarToRectangular(new BigDecimal[] {
circleRadius, angle });
// Draw a line from the center of the circle to the point
g2d.draw(new Line2D.Double(circleCenter[0].doubleValue(), circleCenter[1].doubleValue(),
circleCenter[0].add(rectangular[0]).doubleValue(), circleCenter[1]
.add(rectangular[1]).doubleValue()));
}
public BigDecimal[] convertPolarToRectangular(BigDecimal[] polar) {
BigDecimal radius = polar[0];
BigDecimal angle = polar[1];
BigDecimal x = radius.multiply(new BigDecimal(Math.cos(angle.doubleValue())));
BigDecimal y = radius.multiply(new BigDecimal(Math.sin(angle.doubleValue())));
return new BigDecimal[] { x, y };
}
}
The code above essentially draws a circle on the screen very far away with a large radius. I've picked the dimension so that a piece of the circle is visible in the small window.
Then it draws a line from the center of the circle to a point on the circle that's visible in the window: I picked an angle that was visible on the window and used geometry to convert that angle and the radius of the circle into rectangular coordinates.
This is what the program displays:
Notice that the line doesn't actually end up touching the ellipse. Now, I decided I had to find out whether it was the point I calculated or the ellipse that were incorrect. I did the math on my calculator, and found that the line was correct, and the ellipse incorrect:
Considering that the calculator is probably not wrong, I am led to believe the Ellipse2D is not drawing correctly. However, I tried many other angles, and this is the pattern I found:
And that leads me to believe the calculations are somehow wrong.
So that's my problem. Should I be using something other than Ellipse2D? Maybe Ellipse2D is not accurate enough? I used BigDecimals in my code sample because I thought it would give me more precision - is that the wrong approach? My ultimate goal is to be able to calculate the rectangular position of a point on an ellipse at a specific angle.
Thanks in advance.
You see this error because Ellipse2D is approximated by four cubic curves. To make sure just take a look at its path iterator defining shape border: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/awt/geom/EllipseIterator.java#187
To improve quality we should approximate ellipse by higher number of cubic curves. Here is an extention of standard java implementation with changeable number of segments:
class BetterEllipse extends Ellipse2D.Double {
private int segments;
public BetterEllipse(int segments, double x, double y, double w, double h) {
super(x, y, w, h);
this.segments = segments;
}
public int getSegments() {
return segments;
}
#Override
public PathIterator getPathIterator(final AffineTransform affine) {
return new PathIterator() {
private int index = 0;
#Override
public void next() {
index++;
}
#Override
public int getWindingRule() {
return WIND_NON_ZERO;
}
#Override
public boolean isDone() {
return index > getSegments() + 1;
}
#Override
public int currentSegment(double[] coords) {
int count = getSegments();
if (index > count)
return SEG_CLOSE;
BetterEllipse ellipse = BetterEllipse.this;
double x = ellipse.getCenterX() + Math.sin(2 * Math.PI * index / count) * ellipse.getWidth() / 2;
double y = ellipse.getCenterY() + Math.cos(2 * Math.PI * index / count) * ellipse.getHeight() / 2;
if (index == 0) {
coords[0] = x;
coords[1] = y;
if (affine != null)
affine.transform(coords, 0, coords, 0, 1);
return SEG_MOVETO;
}
double x0 = ellipse.getCenterX() + Math.sin(2 * Math.PI * (index - 2) / count) * ellipse.getWidth() / 2;
double y0 = ellipse.getCenterY() + Math.cos(2 * Math.PI * (index - 2) / count) * ellipse.getHeight() / 2;
double x1 = ellipse.getCenterX() + Math.sin(2 * Math.PI * (index - 1) / count) * ellipse.getWidth() / 2;
double y1 = ellipse.getCenterY() + Math.cos(2 * Math.PI * (index - 1) / count) * ellipse.getHeight() / 2;
double x2 = x;
double y2 = y;
double x3 = ellipse.getCenterX() + Math.sin(2 * Math.PI * (index + 1) / count) * ellipse.getWidth() / 2;
double y3 = ellipse.getCenterY() + Math.cos(2 * Math.PI * (index + 1) / count) * ellipse.getHeight() / 2;
double x1ctrl = x1 + (x2 - x0) / 6;
double y1ctrl = y1 + (y2 - y0) / 6;
double x2ctrl = x2 + (x1 - x3) / 6;
double y2ctrl = y2 + (y1 - y3) / 6;
coords[0] = x1ctrl;
coords[1] = y1ctrl;
coords[2] = x2ctrl;
coords[3] = y2ctrl;
coords[4] = x2;
coords[5] = y2;
if (affine != null)
affine.transform(coords, 0, coords, 0, 3);
return SEG_CUBICTO;
}
#Override
public int currentSegment(float[] coords) {
double[] temp = new double[6];
int ret = currentSegment(temp);
for (int i = 0; i < coords.length; i++)
coords[i] = (float)temp[i];
return ret;
}
};
}
}
And here is how you can use it in your code instead of standard one (I use 100 segments here):
g2d.draw(new BetterEllipse(100, circleCenter[0].subtract(circleRadius).doubleValue(),
circleCenter[1].subtract(circleRadius).doubleValue(), circleRadius.multiply(new BigDecimal(2)).doubleValue(),
circleRadius.multiply(new BigDecimal(2)).doubleValue()));
Related
As you can see on the image, I have a p1 and p2 objects with (x,y) coordinates which I know the values, and I know radius of all these circle objects.
However, I want to calculate new position x,y which would be p3 center point. Basically, as you can see it's p2 position + radius.
I am doing this for java game which is based on libgdx. I would appreciate any math or java language directions/examples.
See code comments for explanation.
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import javax.swing.*;
class CenteredCircle extends Ellipse2D.Double {
CenteredCircle(Point2D.Double p, double radius) {
super(p.x - radius, p.y - radius, 2 * radius, 2 * radius);
}
}
public class CircleDemo extends JFrame {
public CircleDemo() {
int width = 640; int height = 480;
setSize(new Dimension(width, height));
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
JPanel p = new JPanel() {
#Override
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
// center p1
Point2D.Double p1 = new Point2D.Double(getSize().width/2, getSize().height/2);
double radius = 130.0;
// big circle
Shape circle2 = new CenteredCircle(p1, radius);
g2d.draw(circle2);
// 12 small circles
for (int angle = 0; angle < 360; angle += 30) {
// this is the magic part
// a polar co-ordinate has a length and an angle
// by changing the angle we rotate
// the transformed co-ordinate is the center of the small circle
Point2D.Double newCenter = polarToCartesian(radius, angle);
// draw line just for visualization
Line2D line = new Line2D.Double(p1.x, p1.y, p1.x + newCenter.x, p1.y+ newCenter.y);
g2d.draw(line);
// draw the small circle
Shape circle = new CenteredCircle(
new Point2D.Double(p1.x + newCenter.x, p1.y + newCenter.y),
radius/4);
g2d.draw(circle);
}
}
};
setTitle("Circle Demo");
getContentPane().add(p);
}
public static void main(String arg[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new CircleDemo();
}
});
}
static Point2D.Double polarToCartesian(double r, double theta) {
theta = (theta * Math.PI) / 180.0; // multiply first, then divide to keep error small
return new Point2D.Double(r * Math.cos(theta), r * Math.sin(theta));
}
// not needed, just for completeness
public static Point2D.Double cartesianToPolar(double x, double y) {
return new Point2D.Double(Math.sqrt(x * x + y * y), (Math.atan2(y, x) * 180) / Math.PI);
}
}
Now using libgdx for the graphics. Thus no need for polar co-ordinates, on the outside.
I am not doing frame rate relative animation. Therefore, this is no perfect match to your code.
Using the following calculation (if (theta >= 360) { theta = 0.0f; }) at the end of the render method will let the animation restart with its original value.
package org.demo;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.ScreenUtils;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
public class CircleDemo extends ApplicationAdapter {
ShapeRenderer shapeRenderer;
float theta = 0.0f;
#Override
public void create () {
shapeRenderer = new ShapeRenderer();
}
#Override
public void render () {
ScreenUtils.clear(0, 0.4f, 0.4f, 1);
Vector2 p1 = new Vector2( Gdx.graphics.getWidth() / 2.0f , Gdx.graphics.getHeight() / 2.0f);
Vector2 smallCircleCenter = new Vector2(150.0f, 0.0f);
smallCircleCenter.add(p1); // translate center by p1
shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
// static lines and circles
for (int angle = 0; angle < 360; angle += 30) {
Vector2 lineEnd = new Vector2(smallCircleCenter);
lineEnd.rotateAroundDeg(p1, angle);
shapeRenderer.line(p1, lineEnd);
shapeRenderer.circle(lineEnd.x, lineEnd.y, 20);
}
// animated line and circle in red
shapeRenderer.setColor(0.75f, 0, 0, 1);
Vector2 movingCircleCenter = new Vector2(smallCircleCenter);
movingCircleCenter.rotateAroundDeg(p1, theta);
shapeRenderer.line(p1, movingCircleCenter);
shapeRenderer.circle(movingCircleCenter.x, movingCircleCenter.y, 20);
shapeRenderer.setColor(1, 1, 1, 1);
shapeRenderer.end();
theta++;
// for the screenshot stop at 90 degrees
if (theta >= 90) {
theta = 90.0f;
}
}
#Override
public void dispose () {
shapeRenderer.dispose();
}
}
So I wrote a test in my project, based on your approach:
package com.bigbang.test.impl;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
import com.bigbang.Game;
import com.bigbang.graphics.g2d.shapes.impl.Ellipse;
import com.bigbang.graphics.g2d.shapes.impl.Line;
import com.bigbang.graphics.gl.Color;
import com.bigbang.math.BBMath;
public class PolarToCartesianTest extends AbstractTest {
private Array<GraphicalObject> graphicalObjectArray;
private GraphicalObject dynamicGraphicalObject;
private float radius, smallCircleRadius;
private float centerX, centerY;
public PolarToCartesianTest(Game game) {
super(game);
}
#Override
public void create() {
radius = 200f;
centerX = game.getScreenController().getScreenWidth() / 2;
centerY = game.getScreenController().getScreenHeight() / 2;
smallCircleRadius = radius / 4;
graphicalObjectArray = new Array<>();
for (int angle = 0; angle < 360; angle += 30) {
GraphicalObject graphicalObject = new GraphicalObject();
graphicalObject.angle = angle;
graphicalObjectArray.add(graphicalObject);
}
dynamicGraphicalObject = new GraphicalObject();
game.getCameraController().getCamera().position.x = game.getScreenController().getScreenWidth() / 2;
game.getCameraController().getCamera().position.y = game.getScreenController().getScreenHeight() / 2;
}
#Override
public void update(float deltaTime) {
for (GraphicalObject graphicalObject : graphicalObjectArray) {
Vector2 polarToCartesianPosition = BBMath.polarToCartesian(radius, graphicalObject.angle);
graphicalObject.line.x1 = centerX + 0;
graphicalObject.line.y1 = centerY + 0;
graphicalObject.line.x2 = centerX + polarToCartesianPosition.x;
graphicalObject.line.y2 = centerY + polarToCartesianPosition.y;
graphicalObject.line.color = Color.WHITE_COLOR;
graphicalObject.ellipse.x = centerX + polarToCartesianPosition.x;
graphicalObject.ellipse.y = centerY + polarToCartesianPosition.y;
graphicalObject.ellipse.width = 2 * smallCircleRadius;
graphicalObject.ellipse.height = 2 * smallCircleRadius;
graphicalObject.ellipse.color = Color.WHITE_COLOR;
}
float shift = 0;
float theta = (shift * smallCircleRadius) * (centerY / centerX);
Vector2 pos = BBMath.polarToCartesian(radius, theta);
dynamicGraphicalObject.line.color = new Color(Color.RED);
dynamicGraphicalObject.line.x1 = centerX + 0;
dynamicGraphicalObject.line.y1 = centerY + 0;
dynamicGraphicalObject.line.x2 = centerX + pos.x;
dynamicGraphicalObject.line.y2 = centerY + pos.y;
dynamicGraphicalObject.ellipse.x = centerX + pos.x;
dynamicGraphicalObject.ellipse.y = centerY + pos.y;
dynamicGraphicalObject.ellipse.width = 2 * smallCircleRadius;
dynamicGraphicalObject.ellipse.height = 2 * smallCircleRadius;
dynamicGraphicalObject.ellipse.color = new Color(Color.RED);
}
#Override
public void draw() {
game.getShapeRenderer().begin(ShapeRenderer.ShapeType.Line);
for (GraphicalObject graphicalObject : graphicalObjectArray) {
graphicalObject.line.draw();
graphicalObject.ellipse.draw();
}
dynamicGraphicalObject.line.draw();
dynamicGraphicalObject.ellipse.draw();
game.getShapeRenderer().end();
}
class GraphicalObject {
Ellipse ellipse;
Line line;
float angle;
public GraphicalObject() {
this.ellipse = new Ellipse(game);
this.line = new Line(game);
}
}
}
Which is same math like in your example, with some modifications:
However, you can notice I have this dynamicGraphicalObject (red circle), which I want to shift position around circle by using theta value calculated as (shift * smallCircleRadius) * (centerY / centerX);. This works perfect for shift=0 value. It's properly positioned/overlapping white. But if I would change shift variable to 1, 2, 3, or 11, you can see that it's not precisely aligned with white circles. Is this floating point issue or am I missing something in calculation of theta ?
shift values used: 2,6 and 11 in order by images
--
SOLUTION:
float fixPrecision = 1.1f;
float theta = (shift * fixPrecision) + ((shift * smallCircleRadius) * (centerY / centerX));
I have to draw a ring using lines (drawLine) in Java that should look like the attached picture. We are provided with the classDrawingPanel that can be found here.
I've made a regular circle using lines, but I'm unsure how to get the ring shape. I'm new to programming and this is my first post, so apologies if I've missed something important.
This is my code so far:
public static int panelSize = 400;
public static void drawCircle()
{
double radius = 200;
int x2 = 200;
int y2 = 200;
DrawingPanel dp = new DrawingPanel(panelSize, panelSize);
dp.setBackground(Color.CYAN);
Graphics dpGraphics = dp.getGraphics();
dpGraphics.setColor(Color.RED);
for (int circle = 0; circle <= 360; circle++)
{
int x = (int)(x2 + Math.sin(circle * (Math.PI / 180)) * radius);
int y = (int)(y2 + Math.cos (circle * (Math.PI / 180)) * radius);
dpGraphics.drawLine(x, y, x2, y2);
}
}
This is what the final result should look like:
Such a figure can be drawn by drawing a line from one point to a point farther away on the circle, passing the starting point several times.
This is what I came up with:
// Radius
int radius = 200;
// center of the circle
int centerX = 300, centerY = 300;
// The number of edges. Set to 5 for a pentagram
int mod = 136;
// The number of "points" to skip - set to 2 for a pentagram
int skip = 45;
// Precalculated multipier for sin/cos
double multi = skip * 2.0 * Math.PI / mod;
// First point, calculated by hand
int x1 = centerX; // sin(0) = 0
int y1 = centerY + radius; // cos(0) == 1
for (int circle = 1; circle <= mod; circle++)
{
// Calculate the end point of the line.
int x2 = (int) (centerX + radius * Math.sin(circle * multi));
int y2 = (int) (centerY + radius * Math.cos(circle * multi));
dpGraphics.drawLine(x1, y1, x2, y2);
// Next start point for the line is the current end point
x1 = x2;
y1 = y2;
}
The result looks like this:
I am unable to create several instances of the waveClock object even though I have put it in an array and marked the centre positions for each object. I would like to create 4 objects in one window, all responding to different sound frequencies/beat onsets etc
Could someone shed some light on how to go about this? I believe it may be an issue with the centerX and centerY variables in the waveClock class
ArrayList<waveClock> waveClocks = new ArrayList<waveClock>();
//global variables
float angnoise, radiusnoise;
float xnoise, ynoise;
float angle = -PI/6;
float radius;
float strokeCol = 254;
int strokeChange = -1;
int speed; //changes speed of visualisation once beat is detected?
void setup()
//for every waveClock we need 180 pixels width, then add 20 pixels for first gap
size(740, 650);
background(255);
//code is called
waveClocks.add(new waveClock(100, height/2, minRadius, bassColour, lowBassBand, highBassBand, numberOfLowOnsetsThreshold));
waveClocks.add(new waveClock(280, height/2, minRadius, midColour, lowMidBand, highMidBand, numberOfMidOnsetsThreshold));
waveClocks.add(new waveClock(460, height/2, minRadius, highColour, lowHighBand, highHighBand, numberOfHighOnsetsThreshold));
waveClocks.add(new waveClock(640, height/2, minRadius, veryHighColour, lowVeryHighBand, highVeryHighBand, numberOfVeryHighOnsetsThreshold));
//set the min and max radius of each of the viz circles
/* for (int i = 0; i < waveClocks.size(); i++) {
//go through the arraylist of waveClocks and set the min and max radius of each circle
waveClocks.get(i).setMinMaxRadius(minRadius, maxRadius);
}*/
song.play();
beat = new BeatDetect(song.bufferSize(), song.sampleRate());
bl = new BeatListener(beat, song);
}
void draw() {
//clear the screen by painting it black
//background(0);
for (int i = 0; i < waveClocks.size(); i++) {
//has there been a beat in the range? get(circle ID).low band, high band etc.
if (beat.isRange(waveClocks.get(i).getLowBand(), waveClocks.get(i).getHighBand(), waveClocks.get(i).getOnsetThreshold())) {
waveClocks.get(i).setMaxRadius();
}
//waveClocks.get(i).drawCircle();
waveClocks.get(i).drawWaveClock();
}
}
waveClock class in a separate tab
//class is an architecture blueprint
//objects are the actual buildings built from the methods (can make as many as you like)
//constructor is the builder/constructor literally
class waveClock {
float centerX; //co-ordinates of circle's position
float centerY; //co-ordinates of circle's position
float radius; //avg radius
// float minRadius; //smallest size it can be
// float maxRadius; //biggest size it can be
color col; //colour
int onsetThreshold; //
int lowBand; //looks at lowest band of frequency and makes circle sensitive to it
int highBand; //looks at highest band of frequency and makes circle sensitive to it
boolean onset; //has there been an onset (beat has occurred or not?)
//the constructor
waveClock(float x, float y, float r, color c, int lb, int hb, int t) {
centerX = x;
centerY = y;
radius = r;
col = c;
lowBand = lb;
highBand = hb;
onsetThreshold = t;
}
void drawWaveClock() {
radiusnoise += 0.005;
radius = (noise(radiusnoise)*350) + 1;
angnoise += 0.005;
angle += (noise(angnoise)*6) - 3;
if (angle > 360) {
angle -= 360;
} else if (angle < 0) {
angle += 360;
}
xnoise += 0.01;
ynoise =+ 0.01;
float centerX = width/2 + (noise(xnoise)*100) - 50;
float centerY = height/2 + (noise(ynoise)*100) - 50;
float rad = radians(angle);
float x1 = centerX + (radius*cos(rad));
float y1 = centerY + (radius*sin(rad));
float opprad = rad + PI;
float x2 = centerX + (radius*cos(opprad));
float y2 = centerY + (radius*sin(opprad));
strokeCol += strokeChange;
if (strokeCol > 354) {
strokeChange = -1;
} else if (strokeCol < 0) {
strokeChange = 1;
}
stroke(strokeCol, 60);
strokeWeight(1);
line(x1, y1, x2, y2);
}
}
You aren't ever using the class-level centerX and centerY variables. Instead, you're recalculating a new centerX and centerY in the drawWaveClock() function.
float centerX = width/2 + (noise(xnoise)*100) - 50;
float centerY = height/2 + (noise(ynoise)*100) - 50;
These are all drawn from the center of the screen, so the waves will end up in the same position.
In the future, please try to narrow your problem down to a MCVE that demonstrates the problem. Also please use proper naming conventions- classes start with an upper-case letter, for example. Good luck.
I have this code to draw some vertex and edges, and
I have tried almost all the possibilities that were within my reach, but I believe the bug is in the method rotate or in the construtor
but I'm not sure
public static int CONFIG_NODE_DIAMETER = 20; //pixels
//construtor
public GraphDraw(Graph<V, E> graph) {
//count of vertex
int N = graph.numVertex();
double width = this.getWidth();
double height = this.getHeight();
Point2D center = new Point2D(width / 2, height / 2);
double angleIncrement = 360f / N;
//get all vertex from graph
ArrayList<Vertex<V>> vertex = graph.getVertex();
//draw the line and point
boolean first = true;
Point2D p = null;
for (Vertex<V> v : vertex ) { {
if (first) {
if (width > height) {
p = new Point2D(center.getX(),
center.getY() - height / 2 + CONFIG_NODE_DIAMETER * 2);
} else {
p = new Point2D(center.getX(),
center.getY() - width / 2 + CONFIG_NODE_DIAMETER * 2);
}
first = false;
} else {
p = rotate(p, center, angleIncrement);
}
}
}
}
the method that makes the rotation between 2 points
private static Point2D rotate(Point2D point, Point2D pivot, double angle_degrees) {
double angle = Math.toRadians(angle_degrees);
double sin = Math.sin(angle);
double cos = Math.cos(angle);
//translate to origin
Point2D result = point.subtract(pivot);
// rotate point
Point2D rotatedOrigin = new Point2D(
result.getX() * cos - result.getY() * sin,
result.getX() * sin + result.getY() * cos);
// translate point back
result = rotatedOrigin.add(pivot);
return result;
}
I wanna do like the image below and I tried to rotate but it is not working
any suggestion?
in this link, you can check all method in class GraphDraw, and I dont put because the post would be extensive
I am going to try my best to give context for the below code. This is a method used to draw a circle and its center point in a 50x50 white square background. The following variables were used:
xc,yx - the center coordinates used to compute the circle
r - the radius of the circle
STEP - how often a new point is drawn on the circumference of the circle
x,y - the coordinates of each point that will make up the circle
Right now, my method uses a for loop to compute each points R,G, and B coordinates along the circumference of the circle based on the center point and the radius. What I am trying to do is anti-alias my output circle so that the round parts are not as jagged. However, I want to do this using only math and variables and I do not want to use any of Java's build in methods. Thank you to anyone who can help or point me in the right direction.
Below is my routine:
protected void proc_21() {
info = "Draw anti-aliased circle";
int xc = (int) rand(1, imgW - 2);
int yc = (int) rand(1, imgH - 2);
int r = (int) rand(4, 0.35f * (imgW + imgH));
int STEP = (2 * (int) Math.PI * r) * 57;
System.out.printf("circle centered at (%d,%d), radius = %d, draw in %d steps. \n", xc,yc,r,STEP);
for (int i = 0; i < STEP; i++) {
int x = (int) Math.round(xc + r * Math.cos(i));
int y = (int) Math.round(yc + r * Math.sin(i));
if (0 <= x && x < imgW) {
if ( 0 <= y && y < imgH) {
imgNew.setR(x, y, 0);
imgNew.setG(x, y, 0);
imgNew.setB(x, y, 1);
}
}
}
// set center to red
imgNew.setR(xc, yc, 1);
imgNew.setG(xc, yc, 0);
imgNew.setB(xc, yc, 0);
}