简体   繁体   中英

How to reverse the polarities of Y-axis when using Graphics in Java?

The essential question of what I am trying to ask is: How would I make a graph in which the line at y=0 is actually at y=*some number* and that as my Y increases, Java's y decreases?

I am attempting to make a line graph which documents change of populations of animals. I need to make the graph's Y=0 around the y=980 line. I also need to make something that would notice an increase in population and graph it as a decrease in y (to make the line go UP). What I'm trying to say is that I need to create a line graph that looks like a line graph.

I have attempted multiple different things, which each give me a different result based on different inputs. I have successfully created the graph that starts around the y=980 line and goes up, as shown by the image below. The method I used for this was to draw the lines (for the graph itself) and then to take the absolute value of the difference of 10 times the value minus 90, as shown by

g.drawLine((125), (y+1)*93, width, (y+1)*93);
g.drawString(Math.abs(y*10-90) + " alive", (80), (y+1)*93);

This completely works for the graph, but when trying to implement it into the graphing of the lines, I receive mixed results.

For this project, I have 3 populations: predators of my animal, prey of my animal, and my animal. I want to graph the population size of all of these. When using the previously shown method, I successfully graph the first value of the population of the predators. The other two, however, are on the opposite side of the graph from where they must be. (eg my animal's population size is set to start at 90, but on the graph it is around the mid-20s, as also shown by the graph below). The code I used for each of these is:

// predator animal line
g.setColor(Color.red);
g.drawLine(i*93+125, (Math.abs((predatorAnimalAmt[i]*10)-90)), (i+1)*93+125, (Math.abs((predatorAnimalAmt[i+1]*10)-90)));
g.drawLine(100, height-45, 120, height-45);
g.drawString("PREDATOR", 30, height-40);
// prey animal line
g.setColor(Color.green);
g.drawLine(i*93+125, (Math.abs((preyAnimalAmt[i]*10)-90)), (i+1)*93+125, (Math.abs((preyAnimalAmt[i+1]*10)-90)));
g.drawLine(100, height-60, 120, height-60);
g.drawString("PREY", 30, height-55);
// our animal's line
g.setColor(Color.blue);
g.drawLine(i*93+125, (Math.abs((ourAnimalAmt[i]*10)-90)), (i+1)*93+125, (Math.abs((ourAnimalAmt[i+1]*10)-90)));
g.drawLine(100, height-75, 120, height-75);
g.drawString("OUR ANIMAL", 30, height-70);

Here is my code in this class (there are other classes accessible in my github page )

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.image.BufferStrategy;
import java.util.ArrayList;
import java.util.Random;

// ALL OF MY CLASSES
import natural.selection.main.animalia.Animal;
import natural.selection.main.animalia.OurAnimal;
import natural.selection.main.animalia.Predator;
import natural.selection.main.animalia.Prey;

public class MainApp implements Runnable {

private Display display;
private int width, height;
public String title;

private boolean running = false;
private Thread thread;

private Random random = new Random();

private BufferStrategy bs;
private Graphics g;

private ArrayList<Animal> allAnimals = new ArrayList<>();
private int[] animalAmt = new int[20];

private ArrayList<Prey> allPreyAnimals = new ArrayList<>();
private int[] preyAnimalAmt = new int[20];
private ArrayList<OurAnimal> allOurAnimals = new ArrayList<>();
private int[] ourAnimalAmt = new int[20];
private ArrayList<Predator> allPredatorAnimals = new ArrayList<>();
private int[] predatorAnimalAmt = new int[20];

public MainApp(String title, int width, int height){
    this.width = width;
    this.height = height;
    this.title = title;
}

private void init(){
    display = new Display(title, width, height);

    for(int i=0; i<90; i++) {
        OurAnimal animal = new OurAnimal(random.nextInt(10), random.nextInt(10), random.nextInt(10), random.nextInt(10), random.nextInt(10), random.nextInt(10));
        allOurAnimals.add(animal);
        allAnimals.add(animal);
    }
    for(int i=0; i<(80+random.nextInt(10)); i++) {
        Prey animal = new Prey(random.nextInt(10), random.nextInt(10), random.nextInt(10), random.nextInt(10), random.nextInt(10), random.nextInt(10));
        allPreyAnimals.add(animal);
        allAnimals.add(animal);
    }
    for(int i=0; i<(50+random.nextInt(10)); i++) {
        Predator animal = new Predator(random.nextInt(10), random.nextInt(10), random.nextInt(10), random.nextInt(10), random.nextInt(10), random.nextInt(10));
        allPredatorAnimals.add(animal);
        allAnimals.add(animal);
    }
    animalAmt[0] = allAnimals.size();
    preyAnimalAmt[0] = allPreyAnimals.size();
    ourAnimalAmt[0] = allOurAnimals.size();
    predatorAnimalAmt[0] = allPredatorAnimals.size();
}

private void tick() {

}

// Amount of weeks to simulate
private int weeksToSim = 20;

private void render(){
    bs = display.getCanvas().getBufferStrategy();
    if(bs == null){
        display.getCanvas().createBufferStrategy(3);
        return;
    }
    g = bs.getDrawGraphics();
    //Clear Screen
    g.clearRect(0, 0, width, height);
    //Draw Here!

    g.setColor(Color.black);

    // LINE GRAPH OF SPECIES COUNT
    // Draw the graph
    for(int x=0; x<weeksToSim; x++) {
        g.drawLine(x*93+125, height-100, x*93+125, 0);
        g.drawString("Week " + (x+1), x*93+125-20, height-80);
    }
    for(int y=0; y<10; y++) {
        g.drawLine((125), (y+1)*93, width, (y+1)*93);
        g.drawString(Math.abs(y*10-90) + " alive", (80), (y+1)*93);
    }
    // Draw the line
    for(int i=0; i<(animalAmt.length-1); i++) {
        // predator animal line
        g.setColor(Color.red);
        g.drawLine(i*93+125, (Math.abs((predatorAnimalAmt[i]*10)-90)), (i+1)*93+125, (Math.abs((predatorAnimalAmt[i+1]*10)-90)));
        g.drawLine(100, height-45, 120, height-45);
        g.drawString("PREDATOR", 30, height-40);
        // prey animal line
        g.setColor(Color.green);
        g.drawLine(i*93+125, (Math.abs((preyAnimalAmt[i]*10)-90)), (i+1)*93+125, (Math.abs((preyAnimalAmt[i+1]*10)-90)));
        g.drawLine(100, height-60, 120, height-60);
        g.drawString("PREY", 30, height-55);
        // our animal's line
        g.setColor(Color.blue);
        g.drawLine(i*93+125, (Math.abs((ourAnimalAmt[i]*10)-90)), (i+1)*93+125, (Math.abs((ourAnimalAmt[i+1]*10)-90)));
        g.drawLine(100, height-75, 120, height-75);
        g.drawString("OUR ANIMAL", 30, height-70);
    }

    //End Drawing!
    bs.show();
    g.dispose();
}

public void run(){

    init();

    int fps = 60;
    double timePerTick = 1000000000 / fps;
    double delta = 0;
    long now;
    long lastTime = System.nanoTime();
    long timer = 0;
    int ticks = 0;

    Toolkit.getDefaultToolkit().sync();

    while(running){
        now = System.nanoTime();
        delta += (now - lastTime) / timePerTick;
        timer += now - lastTime;
        lastTime = now;

        if(delta >= 1){
            tick();
            render();
            ticks++;
            delta--;
        }

        if(timer >= 1000000000){
            System.out.println("Ticks and Frames: " + ticks);
            ticks = 0;
            timer = 0;
        }
    }

    stop();

}

public int getWidth(){
    return width;
}

public int getHeight(){
    return height;
}

public synchronized void start(){
    if(running)
        return;
    running = true;
    thread = new Thread(this);
    thread.start();
}

public synchronized void stop(){
    if(!running)
        return;
    running = false;
    try {
        thread.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}   
}

How would I go about making all of the points correct with just one formula without completely disrupting all of my code?

Here is what I get as a result of my code:

结果图

Let's extract this functionality into two functions that calculate the correct x and y position for a given week and count . This way, you can change the chart layout by just changing a single function instead of multiple lines scattered throughout the code:

private int getChartX(double week) {
    return (int)Math.round(week * 93 + 32);
}

private int getChartY(double count) {
    return (int)Math.round(930 - count * 9.3);
}

Using these functions, you can re-structure your drawing code like this:

// Draw the graph
for(int week = 1; week <= weeksToSim; week++) {
    int x = getChartX(week);
    g.drawLine(x, getChartY(0), x, 0);
    g.drawString("Week " + week, x-20, getChartY(0) + 20);
}
for(int y=0; y<10; y++) {
    int count = 10 * y;
    int y = getChartY(count);
    g.drawLine(getChartX(1),  y, width, y);
    g.drawString(count + " alive", getChartX(1) - 45, y);
}
// Draw the line
for(int i=0; i<(animalAmt.length-1); i++) {
    int week = i + 1;
    // predator animal line
    g.setColor(Color.red);
    g.drawLine(getChartX(week), getChartY(predatorAnimalAmt[i]), getChartX(week + 1), getChartY(predatorAnimalAmt[i + 1]));
    ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM