I'm trying to make a simple function drawer in Java.
I'm using the ScriptEngine API to parse the equation from a string, but it gets very slow while drawing.
Is there another way to do the same thing?
Here is the code:
private String v;
#Override
public void init(){
setSize(600,600);
v = JOptionPane.showInputDialog("Input function:");
}
#Override
public void paint(Graphics g){
drawQuadrants(g);
drawEquation(g);
}
private void drawEquation(Graphics g) {
g.setColor(Color.BLUE);
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
v = v.replace("sin", "Math.sin")
.replace("cos", "Math.cos")
.replace("sen", "Math.sin")
.replace("tan", "Math.tan")
.replace("tg", "Math.tan")
.replace("log", "Math.log")
.replace("Log(x)","(Math.log(x)/Math.LN10)");
for(double x0 = -10;x0<=10;x0+=0.001){
engine.put("x", x0);
try {
double y0 = (Double)engine.eval(v);
drawPoint(g,x0,-y0);
} catch (HeadlessException | ScriptException e) {
e.printStackTrace();
}
}
}
private void drawQuadrants(Graphics g) {
g.setColor(Color.BLACK);
g.drawLine(0, 300, 600, 300);
g.drawLine(300, 0, 300, 600);
g.setFont(new Font("Arial",Font.BOLD,15));
g.drawString("x", 580, 320);
g.drawString("y", 280, 20);
for(int l = 0;l<=600;l+=30){
g.drawLine(l, 297, l, 303);
}
for(int l = 0;l<=600;l+=30){
g.drawLine(297, l, 303, l);
}
}
private void drawPoint(Graphics g, double x0, double y0) {
int newx0 = (int)map((float)x0, (float)-10, (float)10, (float)0.0, (float)600.0);
int newy0 = (int)map((float)y0, (float)-10, (float)10, (float)0.0, (float)600.0);
g.drawOval(newx0, newy0, 1, 1);
}
public static final float map(float value, float start1, float stop1, float start2, float stop2)
{
return start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1));
}
Well you could always try my code,it is simple fast and elegant.It can also plot any graph by using an external parser.
import javax.swing.*;
import java.awt.*;
import java.util.Scanner;
import net.objecthunter.exp4j.*;
class math extends JFrame
{
public static void main(String args[])
{
math m=new math();
m.setVisible(true);
m.setLocationRelativeTo(null);
}
public void paintallies(Graphics G1,double sf)
{int i;
Graphics2D g21=(Graphics2D) G1;
g21.setColor(Color.GREEN);
for(i=0;i<=600;i=(int) (i+sf))
{
g21.drawLine(i,0,i,600);
g21.drawLine(0,i,600,i);
}
}
public void paintaxes(Graphics G1)
{
Graphics2D g21=(Graphics2D) G1;
g21.setColor(Color.BLACK);
g21.drawLine(300,0,300,600);//y axis
g21.drawLine(0,300,600,300); //x axis
}
public void paint(Graphics G)
{
int i;
double j,k;
Scanner s=new Scanner(System.in);
System.out.println("Enter input");
String input=s.nextLine();
System.out.println("Enter scale factor");
double sf=s.nextDouble();
double sff=300/sf;
double kf=sff;
double count=0;
Graphics g2=(Graphics) G;
paintallies(G,sf);
paintaxes(G);
g2.translate(300,300);
do
{
kf=kf-(1/sf);
count++;
}while(kf>=0);
double counts=2*count;
Color c=Color.RED;
g2.setColor(c.darker());
double yarr[]=new double[(int)counts];
double xarr[]=new double[(int)counts];
Expression E=new ExpressionBuilder(input).variables("x").build();
j=-sff; k=-sff;
for(i=0;i<counts;i++)
{
xarr[i]=j;
j=j+(1/sf);
E.setVariable("x",k);
yarr[i]=E.evaluate();
k=k+(1/sf);
xarr[i]=sf*xarr[i];
yarr[i]=-sf*yarr[i];
}
for(i=0;i<counts;i++)
{
if(i==counts-1)
{
break;
}
else
{
g2.drawLine((int)xarr[i],(int)yarr[i],(int)xarr[i+1],(int)yarr[i+1]);
}
}
}
math()
{
super("Grapher");
setSize(600,600);
setResizable(true);
}
}
One low-hanging fruit may be to increase the value in the for-loop step in the drawEquation() method. When choosing this value, take into consideration that you have ~ 2K to 3K pixels max horizontally. Yet, you're iterating over 20K points on the X axis. Try x0+=0.01 first, then adjust as needed. This may cause your program to run in 1/10th the time.
It would be much faster if you
- make ScriptEngineManager mgr object as member variable and create it once (in constructor of your class)
invoke parsing and calcuations from drawEquation only when text in input dialog changes, not in every draw. You could save computed values in two arrays (one array for x, another one for y values).
As general rule (for every graphic engime I do know), onDraw method should be small and fast.
do not perform object cration and initalization in onDraw. That crates A LOT of work for garbage collector.
do not perform extensive computation in onDraw, if those computation may be performed before.
EDIT:
Calculate and draw only points you need to draw. You need to know width of your Graphic objects, compute increment value of the for loop and have only g.width() number of iterations. More iterations is just a waste- you are drawing many points in the same screen location.
Related
I'm currently working on a program which enables user to draw various geometric shapes. However, I got some issues on calculating and placing the angle objects onto my Canvas panel accurately. The angle object is basically an extension of the Arc2D object, which provides a additional method called computeStartAndExtent(). Inside my Angle class, this method computes and finds the necessary starting and extension angle values:
private void computeStartAndExtent()
{
double ang1 = Math.toDegrees(Math.atan2(b1.getY2() - b1.getY1(), b1.getX2() - b1.getX1()));
double ang2 = Math.toDegrees(Math.atan2(b2.getY2() - b2.getY1(), b2.getX2() - b2.getX1()));
if(ang2 < ang1)
{
start = Math.abs(180 - ang2);
extent = ang1 - ang2;
}
else
{
start = Math.abs(180 - ang1);
extent = ang2 - ang1;
}
start -= extent;
}
It is a bit buggy code that only works when I connect two lines to each other, however, when I connect a third one to make a triangle, the result is like the following,
As you see the ADB angle is the only one that is placed correctly. I couldn't figure how to overcome this. If you need some additional info/code please let me know.
EDIT: b1 and b2 are Line2D objects in computeStartAndExtent() method.
Thank you.
There are some of things that can be made to simplify the calculation:
Keep the vertices ordered, so that it is always clear how to calculate the vertex angles pointing away from the corner
Furthermore, always draw the polygon to the same direction; then you can always draw the angles to the same direction. The example below assumes the polygon is drawn clockwise. The same angle calculation would result in the arcs drawn outside given a polygon drawn counterclockwise.
Example code; is not quite the same as yours as I don't have your code, but has similar functionality:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.Arc2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Polygon extends JPanel {
private static final int RADIUS = 20;
private final int[] xpoints = {
10, 150, 80, 60
};
private final int[] ypoints = {
10, 10, 150, 60
};
final Arc2D[] arcs;
Polygon() {
arcs = new Arc2D[xpoints.length];
for (int i = 0; i < arcs.length; i++) {
// Indices of previous and next corners
int prev = (i + arcs.length - 1) % arcs.length;
int next = (i + arcs.length + 1) % arcs.length;
// angles of sides, pointing outwards from the corner
double ang1 = Math.toDegrees(Math.atan2(-(ypoints[prev] - ypoints[i]), xpoints[prev] - xpoints[i]));
double ang2 = Math.toDegrees(Math.atan2(-(ypoints[next] - ypoints[i]), xpoints[next] - xpoints[i]));
int start = (int) ang1;
int extent = (int) (ang2 - ang1);
// always draw to positive direction, limit the angle <= 360
extent = (extent + 360) % 360;
arcs[i] = new Arc2D.Float(xpoints[i] - RADIUS, ypoints[i] - RADIUS, 2 * RADIUS, 2 * RADIUS, start, extent, Arc2D.OPEN);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(160, 160);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawPolygon(xpoints, ypoints, xpoints.length);
Graphics2D g2d = (Graphics2D) g;
for (Shape s : arcs) {
g2d.draw(s);
}
}
public static void main(String args[]){
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Polygon");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Polygon());
frame.pack();
frame.setVisible(true);
}
});
}
}
Results in:
I'm trying to make a game where you are an oval and you have 2 ovals following you. When you press 's' the 2 ovals following you circle around you. The problem is that I can't make the ovals do a 360 turn.
Code:
public class apples extends JFrame {
public static int x, y;
public static int userWIDTH = 15;
public static int userHEIGHT = 15;
public static int defenseWIDTH = 5;
public static int defenseHEIGHT = 5;
public static int defenseX;
public static int defenseY;
private Image dbImage;
private Graphics dbg;
public class AL extends KeyAdapter {
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if(keyCode == e.VK_LEFT) {
if(!(x < 15)) {
x += -10;
}
}
else if(keyCode == e.VK_RIGHT) {
if(!(x > 810)) {
x += 10;
}
}
else if(keyCode == e.VK_S) {
//Not sure how to make the 2 ovals circle while following the player.
}
}
public void keyReleased(KeyEvent e) {
}
}
public apples() {
super("Dodgem");
setSize(840, 620);
setResizable(true);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
addKeyListener(new AL());
x = (this.getWidth() - (userWIDTH + userHEIGHT)) / 2;
y = (this.getHeight() - (userWIDTH + userHEIGHT)) / 2;
}
public void paint(Graphics g) {
dbImage = createImage(getWidth(), getHeight());
dbg = dbImage.getGraphics();
paintComponent(dbg);
g.drawImage(dbImage, 0, 0, this);
}
public void paintComponent(Graphics g) {
g.fillOval(x, y, userWIDTH, userHEIGHT);
defenseX = x;
defenseY = y;
g.fillOval(defenseX - 20, defenseY + 20, defenseWIDTH, defenseHEIGHT);
g.fillOval(defenseX + 20, defenseY - 20, defenseWIDTH, defenseHEIGHT);
repaint();
}
public static void main(String[] args) {
new apples();
}
Also, this is an example if it helps...
The two ovals have to "spin".
Sorry for my ignorance, and in advance, thank you.
In order to make something move in a cricle around a point you need to use the parametric equation for a circle. It is described fully on wikipedia: http://en.wikipedia.org/wiki/Circle
The equation can be written in parametric form using the trigonometric functions sine and cosine as:
x = a + r cos t
y = b + r sin t
where t is a parametric variable in the range 0 to 2π, interpreted geometrically as the angle that the ray from (a, b) to (x, y) makes with the x-axis.
In other words, if your target is at (a,b) then to circle around it with radius r you need to plug those variables into the equations above, with t being the angle between 0 and 2π that you want the chaser to be at.
If you want the chaser to transition between chasing and circling then you will need to determine the starting angle using elementary trigonometry.
I have recently started using a mac to develop on and i am having a strange problem.
Take the Program below:
public class Driver {
public static void main(String [ ] args) {
SolarSystem SSpanel = new SolarSystem(600, 600);
SSpanel.drawSolarObject(0, 0, 30, "YELLOW");
}
}
the SolarSystem class extends JFrame and basically when the new SolarSystem is created it makes a panel of that size.
the drawSolarObjects basically draws a circle of a certain colour and size. finishedDrawing actually makes the object appear on the panel.
The example above does work but I have more complex requirements which involve putting this into a while loop.
this is where it gets weird, if i run the below program with cmd on a windows computer it works fine and prints the yellow circle to the screen. On my mac, adding this while loop causes it to just create the panel but not paint the yellow circle.
public class Driver{
public static void main(String [ ] args) {
boolean oMove = true;
SolarSystem SSpanel = new SolarSystem(600, 600);
while(oMove){
SSpanel.drawSolarObject(0, 0, 30, "YELLOW");
SSpanel.finishedDrawing();
}
}
}
I put a print into my loop to check it was running through it and that showed that it was definitely running through the loop.
Does anyone know what could be causing this?
Ive am adding the functions so you can get a better picture
SolarSystem Constructer:
public SolarSystem(int width, int height)
{
this.width = width;
this.height = height;
this.setTitle("The Solar System");
this.setSize(width, height);
this.setBackground(Color.BLACK);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
drawSolarObject Function:
public void drawSolarObject(double distance, double angle, double diameter, String col)
{
Color colour = this.getColourFromString(col);
double centreOfRotationX = ((double) width) / 2.0;
double centreOfRotationY = ((double) height) / 2.0;
double rads = Math.toRadians(angle);
double x = (int) (centreOfRotationX + distance * Math.sin(rads)) - diameter / 2;
double y = (int) (centreOfRotationY + distance * Math.cos(rads)) - diameter / 2;
synchronized (this)
{
if (things.size() > 1000)
{
System.out.println("\n\n");
System.out.println(" ********************************************************* ");
System.out.println(" ***** Only 1000 Entities Supported per Solar System ***** ");
System.out.println(" ********************************************************* ");
System.out.println("\n\n");
this.dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
}
else
{
SolarObject t = new SolarObject((int)x, (int)y, (int)diameter, colour);
things.add(t);
}
}
}
finishedDrawing function:
public void finishedDrawing()
{
try
{
this.repaint();
Thread.sleep(30);
}
catch (Exception e) { }
synchronized (this)
{
things.clear();
}
}
This all works fine on a windows PC
Your code risks tying up the Swing event thread preventing it from drawing on your GUI, and effectively freezing your program. Instead use a Swing Timer, not a while loop to achieve your goal.
e.g.,
final SolarSystem SSpanel = new SolarSystem(600, 600);
int timerDelay = 100;
new Timer(timerDelay, new ActionListener() {
public void actionPerformed(ActionEvent e) {
// do repeated action in here
}
}).start();
As an aside, I was going to place,
SSpanel.drawSolarObject(0, 0, 30, "YELLOW");
SSpanel.finishedDrawing();
inside my timer code, but it wouldn't make sense because this code isn't "dynamic" and doesn't change anything or do any animation.
I stumbled upon a problem which i would like to solve it using Java. User inputs Larger Rectangle dimension (i.e L_width and L_height) and smaller rectangle dimension (i.e S_width and S_height). I would like to place as many smaller rectangle inside the larger rectangle and show it graphically.
for example: When the Larger Rectangle size is 4 x 5 and smaller rectangle size is 2 x 2, then the maximum number of smaller rectangle that i would be able to place it inside the larger rectangle is 4. I would like to show them graphically.
As im new to java, i wanted to know how i can approach this problem from programmatic point of view and what concept i have to use to achieve the same.
Initial code for calculating the maximum number of rectangles. Can any1 help me to show this result graphically using java
// Code Starts
import java.awt.Graphics;
import java.util.Scanner;
import javax.swing.JComponent;
import javax.swing.JFrame;
//Class to store the output of layout
class layout{
private int Cnt_BW_CW=0; // BoardWidth and CardWidth are arranged together
private int Cnt_BW_CH=0;
private int option=0; // Option 1: width-width Option 2: width-height
public int getCnt_BW_CW (){
return Cnt_BW_CW;
}
public int getCnt_BW_CH (){
return Cnt_BW_CH;
}
public int getoption (){
return option;
}
public void setCnt_BW_CW (int newValue){
Cnt_BW_CW = newValue;
}
public void setCnt_BW_CH (int newValue){
Cnt_BW_CH = newValue;
}
public void setoption (int newValue){
option = newValue;
}
}
// Stores the Dimension
class Dimension{
private float w,h;
Scanner input = new Scanner( System.in );
public Dimension(){
System.out.print( "Enter Width: " );
w = input.nextInt();
System.out.print( "Enter Height: " );
h = input.nextInt();
}
public Dimension(float width, float height){
w = width;
h = height;
}
public float getWidth (){
return w;
}
public float getHeight (){
return h;
}
public void setWidth (float newWidth){
w = newWidth;
}
public void setHeight (float newHeight){
h = newHeight;
}
}
class MyCanvas extends JComponent {
private static final long serialVersionUID = 1L;
public void paint(Graphics g) {
g.drawRect (10, 10, 200, 200);
}
}
public class boundedRect {
#SuppressWarnings("unused")
public static void main(String[] a) {
Dimension Board = new Dimension();
Dimension Card = new Dimension();
int Cnt =0;
Cnt = NumOfRect(Board, Card);
System.out.printf( "Number of Cards:%d",Cnt );
JFrame window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setBounds(30, 30, 300,300);
window.getContentPane().add(new MyCanvas());
window.setVisible(true);
}
public static int NumOfRect(Dimension b,Dimension c){
float bw,bh,cw,ch;
int bw_cw,bh_ch,bw_ch,bh_cw;
int SameDimensionCnt,DiffDimensionCnt;
int count;
layout Result = new layout();
bw =b.getWidth(); bh = b.getHeight();
cw =c.getWidth(); ch = c.getHeight();
if (bw < cw || bh < ch){
System.out.println( "Board and Card Dimension mismatch" );
System.exit(0);
}
bw_cw = (int)Math.floor(bw/cw);
bh_ch = (int)Math.floor(bh/ch);
SameDimensionCnt = bw_cw * bh_ch;
Result.setCnt_BW_CW(SameDimensionCnt);
bw_ch = (int)Math.floor(bw/ch);
bh_cw = (int)Math.floor(bh/cw);
DiffDimensionCnt = bw_ch * bh_cw;
Result.setCnt_BW_CH(DiffDimensionCnt);
System.out.printf( "Matching BW x CW: %d\n",SameDimensionCnt );
System.out.printf( "Matching BW x CH: %d\n",DiffDimensionCnt );
if (SameDimensionCnt < DiffDimensionCnt ){
count = DiffDimensionCnt;
System.out.println( "Align Board Width and Card Height" );
Result.setoption(2);
}else {
count = SameDimensionCnt;
System.out.println( "Align Board Width and Card Width" );
Result.setoption(1);
}
return count;
}
}
So you want to tile a large rectangle with a number of smaller rectangles. First define a class to represent the small rectangles, and create a data structure (probably an ArrayList) to hold them. Use a nested for loop to walk over the area of the large rectangle in S_width/S_height steps, and create as many small rectangles as will fit. Add them to the ArrayList as they are created. Search for ArrayList on Google to find the Java docs if you need them.
Then you need to write the code to draw them on the screen. For that, look up the official Java Tutorial on Google and read the section on graphics.
Try writing the code first and if you have problems, post your code here (you can edit the question).
I know the following code will move an object in a straight line. How can I get the object to travel in a wavy line? I know that something extra is required for the x variable.
public void draw(Graphics2D g)
{
g.setColor(Color.WHITE);
g.fillOval ((int) (x - r), (int) (y - r), (int)
(2 * r),
(int) (2 * r));
y++;
if (y - r > height)
y = -r;
}
Use the sine or cosine function to calculate y as a function of x.
Multiply the sine or cosine function to increase the amplitude (how high it goes)
y = 100 * sin(x) // will make it have peaks of -100 and 100
Divide the x to increase the period. (distance between peaks)
y = sin(x/2) // will make it take twice the x distance between peaks.
Something like this:
public void draw(Graphics2D g)
{
g.setColor(Color.WHITE);
g.fillOval ((int) (x - r), (int) (y - r), (int)
(2 * r),
(int) (2 * r));
x++; // Left to right movement
// Example, modify the multipliers as necessary
y = 100 * Math.sin(Math.toDegrees(x/4))
}
Including a sin(x) or cos(x) in your function will provide a regular wave pattern, irregular pattern needs a more sophisticated function
I know you already accepted an answer, but here's something to draw additional inspiration from that I whipped up...
package wavy;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Wavy {
public static void main(String[] args) {
final JFrame frame = new JFrame("Wavy!");
final WavyPanel wp = new WavyPanel();
frame.getContentPane().add(wp, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final Ticker t = new Ticker(wp);
final Repainter r = new Repainter(wp);
frame.pack();
frame.setVisible(true);
final Timer tickTimer = new Timer();
final Timer paintTimer = new Timer();
paintTimer.schedule(r, 1000, 50);
tickTimer.schedule(t, 1000, 10);
}
private static class WavyPanel extends JPanel {
private final Dimension size = new Dimension(640, 480);
private int amplitude = 50;
private int frequency = 5;
private int x = 0;
private double y = size.height / 2;
private int yBase = 0;
WavyPanel() {
super(true);
}
#Override
protected void paintComponent(final Graphics g) {
final Graphics2D g2 = (Graphics2D)g;
g2.setColor(Color.WHITE);
g2.fillRect(0, 0, size.width, size.height);
g2.setColor(Color.BLACK);
g2.fillOval(x, (int)y, 30, 30);
}
#Override
public Dimension getPreferredSize() {
return size;
}
#Override
public Dimension getMinimumSize() {
return size;
}
#Override
public Dimension getMaximumSize() {
return size;
}
public void tick() {
//Move a pixel to the right; loop over to the left when reaching edge
x = (++x) % size.width;
//Length of one full wave = panel width divided by frequency
final int waveLength = size.width / frequency;
//Incrementing yBase; capping off at wavelength
yBase = (++yBase) % waveLength;
//Normalizing to [0..1]
final double normalized = (double)yBase / (double)waveLength;
//Full wave at 2*pi, means...
final double radians = normalized * Math.PI * 2;
//Getting the sine
final double sine = Math.sin(radians);
//Multiplying with amplitude, add to center position and we have our y
y = (int)(sine * amplitude) + size.height/2;
}
}
private static class Ticker extends TimerTask {
private final WavyPanel panel;
Ticker(final WavyPanel panel) {
this.panel = panel;
}
#Override
public void run() {
panel.tick();
}
}
private static class Repainter extends TimerTask {
private final WavyPanel panel;
Repainter(final WavyPanel panel) {
this.panel = panel;
}
#Override
public void run() {
panel.repaint();
}
}
}
This should run at an approximate 20 frames per second. You can increase this by setting the second argument of paintTimer.schedule(r, 1000, 50) lower. The speed of movement can be altered by lowering (speeding up) or increasing (slower) the second argument of tickTimer.schedule(t, 1000, 50).
Changing the amplitude field of WavyPanel will change how high/low the circle moves. Changing the frequency to a higher value will result in shorter waves, while a lower value will produce longer waves.
With some additional work you could add in controls to change the amplitude and frequency on-the-fly. Some additional notes:
You may wish to add some safeguard to the tick() method to make sure that when one invocation is already running, additional ones are skipped until the first one is done. Otherwise the calculations could fail for short tick intervals. A semaphore could be used here.
Since trigonometric calculations aren't exactly the cheapest, you may consider caching some results (e.g. in an array) for re-use if many similar animations are to be played or if there's a lot more drawing going on.
I hope I'm interpreting this right. Could use the sine or cosine of either your x or y coordinate. I'm not at a machine with java so I can't make an example at the moment..
You're right that you need to update both the x and y variables to get a wavy line. Here's the general strategy for a horizontal line that is wavy up and down:
Choose a function f(x) that has the shape you want. This will be used to calculate values for y. (For instance, you can use y = amplitude * Math.sin(frequency * x) to get a regular sine wave of a given amplitude and frequency.)
If necessary, write the code that implements your function.
Set x to some initial value.
In draw, before you paint the oval, calculate y = f(x);. Paint the oval and then increment x. If necessary, reset x so it stays in range.
If you want a vertical line that is wavy left and right, just reverse the roles of x and y in the above. If you want the oval to go in the reverse direction, just decrement instead of increment in step 4.
this sample is for point(Line with one length) on sinus graph and clock using.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class RunSwing extends JPanel {
static int x1 = 500;
static int y1 = 500;
static int x2 = x1;
static int y2 = y1;
final static int vectorLength = 100;
final static int sinx2 = x2;
final static int siny2 = y2;
static double count = 0;
private static RunSwing run = new RunSwing();
final Timer print = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(final ActionEvent e) {
//increaseSinusGraph();
increaseClockVector();
count+=6; //for clock for 1 second
/*count++;//for sinus*/
if (count % 360 == 0)
System.out.println((count / 360) + " minute passed");
}
});
RunSwing() {
print.start();
}
public static void main(String[] args) {
JFrame frame = new JFrame("amir");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(run);
frame.setSize(1100, 700);
frame.setVisible(true);
}
static void increaseClockVector() {
double cos = Math.cos(Math.toRadians(count));
double sin = Math.sin(Math.toRadians(count));
y2 = siny2 + (int) (vectorLength * sin);
x2 = sinx2 + (int) (vectorLength * cos);
}
static void increaseSinusGraph() {
double sin = Math.sin(Math.toRadians(count));
y2 = siny2 + (int) (vectorLength * sin);
x2++;
}
private void createPoint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.drawLine(x2, y2, x2 + 1, y2 + 1);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(new Color(0, 0, 0));
g.drawLine(x1, y1, x2, y2);//for clock
/*g.drawLine(x2, y2, x2+1, y2+1);//for sinus*/
repaint();
}
}