Im trying to create a slope in java. I can use the DrawLine function and it'll create a perfect one but I dont want to use that but rather create my own function for it. The problem is that it has gaps between the dots.
import java.applet.Applet;
import java.awt.Graphics;
public class slope extends Applet{
public void drawLine(int x1, int y1, int x2, int y2, Graphics g) {
double m = (y2 - y1) / (double)(x2-x1);
double y = y1;
for (int x =x1; x < x2; x++) {
drawPoint(x,(int)y,g);
y +=m;
}
}
public void paint(Graphics g) {
drawLine(20, 10, 300, 700, g); //has spaces between the dots
g.drawLine(20, 10, 300, 700); //this is perfect
}
private void drawPoint(int x, int y, Graphics g) {
g.drawLine(x, y, x, y);
}
}
Elementary geometry tells us that the slope between two points in the change in y over the change in x. So m = (y1 - y2)/(x1 - x2) , where all of these values are doubles, and x1 and y1 belong to the same point. Then the formula for the line between two points is y - y1 = m(x - x1) .
Java Applet | Draw a line using drawLine() method x1 – It takes the first point's x coordinate. y1 – It takes first point's y coordinate. x2 – It takes second point's x coordinate. y2 – It takes second point's y coordinate.
Generally this is done by using an algorithm that doesn't step only along the x or y axis, but adjust the update increment by a variable amount, such that each dot is at most sqrt(2)
away from each other.
So, if you think you have a point at the x value, but when you calculate it, you find that it is 3.5 pixels away (because the slope is very steep), you fall into a routine that calculates (typically recursively) an intermediate pixel between that x step
(x, y)
(0, 0) to (1, 5) distance 5.09
-> fill routine
(0, 0) to (0.5, 2.5) distance 2.69
-> fill routine
(0, 0) to (0.25, 1.25) distance 1.34 < 1.41
(0.25, 1.25) to (0.5, 2.5) distance 1.34 < 1.41
(0.5, 2.5) to (0.75, 3.75) distance 1.34 < 1.41
(0.75, 3.75) to (1, 5) distance 1.34 < 1.41
(1, 5) to (2, 10) etc...
The reason one uses 1.41 (sqrt(2)) as the maximum distance allowed is because a of pixels at a 45 degree angle from the bottom of the screen would still appear connected.
Now, in your plotting, you'll need to round the values to align to the exact pixels. There are a number of ways to do this. The simplest is just to round to the next valid value, and this works most of the time. It does have one unfortunate side effect, that is your line will appear to have jagged steps (where the rounding is moving the pixel more, the step will appear more jagged). This jaggedness is called "aliasing" as the true point is presenting through a non-true representation of the point (the alias).
A second approach is to alternatively darken both pixels proportionally, based on how close the point is. A point that is at (0.5) on the x axis would darken both pixels by 50% while a point that is at (0.25) would darken the 0 pixel by 75% and the 1 pixel by 25%. This is anti-aliasing, and may result in a line that is slightly more fuzzy, but appears to be straighter. This fuzziness can be somewhat combated by drawing a thicker line.
I hope this gives you some idea of the math behind many of the higher quality drawing routines, and certainly there are approaches that are even more sophisticated than the one I just presented.
Two loops: you loop over x++ only when deltaX > deltaY. else you loop over y++ only.
Dual stepping x and y in the same loop, deciding which should be incremented (assuming you have x as a function of y too) could lead to slower drawing due to extra tests and adjacent pixels may look like a dot in the line. You'd need to play with color intensity to do antialiasing by hand (gold plating). Two loops is much simpler.
fyi, you are trying to generate an image, you could also just set ints in a matrix and make an offscreen raw image (BufferedImage and it's .setRGB() method), which you draw later. That would likely be faster and avoid visible painting delays.
Based on the Bresenham Algorithm, here is a java implementation that
assumes x2 > x1 and y2 > y1
and uses integer arithmetic
import java.applet.Applet;
import java.awt.*;
public class Slope extends Applet{
private int x1 = 20, y1 = 10;
private int x2 = 300, y2 = 700;
@Override
public void paint(Graphics g) {
drawLine(x1, y1, x2, y2, g);
//g.drawLine(x1, y1, x2, y2, g);
}
private void drawPoint(int x, int y, Graphics g) {
g.drawLine(x,y,x,y);
}
@Override
public void init(){
this.setSize(500,700);
}
private void drawLine(int x1,int y1,int x2,int y2,Graphics g){
int dx = x2 - x1;
int dy = y2 - y1;
int xi = 1;
int D = 2*dx - dy;
int x = x1;
for(int y = y1; y <y2; y++) {
drawPoint(x,y,g);
if(D > 0) {
x = x + xi;
D = D - 2 * dy;
}
D = D + 2 * dx;
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With