在Java中创建坡度

在Java中创建坡度,java,Java,我正在尝试用java创建一个斜坡。我可以使用DrawLine函数,它将创建一个完美的函数,但我不想使用它,而是为它创建我自己的函数。问题是它在点之间有间隙 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) {

我正在尝试用java创建一个斜坡。我可以使用DrawLine函数,它将创建一个完美的函数,但我不想使用它,而是为它创建我自己的函数。问题是它在点之间有间隙

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);

    }
}
import java.applet.applet;
导入java.awt.Graphics;
公共类斜坡扩展小程序{
公共空白绘制线(图x1、图y1、图x2、图y2、图g){
双m=(y2-y1)/(双)(x2-x1);
双y=y1;
对于(int x=x1;x

两个循环:仅当deltaX>deltaY时才在x++上循环。 否则您只能在y++上循环

在同一个循环中,双步进x和y,决定哪个应该递增(假设x也是y的函数),由于额外的测试和相邻像素可能看起来像线中的点,可能会导致绘制速度变慢。您需要使用颜色强度来手动执行抗锯齿(镀金)。两个循环要简单得多


仅供参考,如果您试图生成图像,也可以在矩阵中设置int,然后生成屏幕外的原始图像(BuffereImage及其.setRGB()方法),稍后再绘制。这可能会更快,并避免可见的绘制延迟。

通常,这是通过使用一种算法来完成的,该算法不仅沿x或y轴进行步进,还可以通过可变量调整更新增量,使每个点彼此之间的距离最多为
sqrt(2)

因此,如果您认为在x值处有一个点,但当您计算它时,您发现它距离3.5像素(因为斜率非常陡峭),那么您将陷入一个例程,该例程计算(通常递归地)x步长之间的中间像素

(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...
(x,y)
(0,0)至(1,5)距离5.09
->填充程序
(0,0)至(0.5,2.5)距离2.69
->填充程序
(0,0)到(0.25,1.25)距离1.34<1.41
(0.25,1.25)到(0.5,2.5)距离1.34<1.41
(0.5,2.5)到(0.75,3.75)距离1.34<1.41
(0.75,3.75)到(1,5)距离1.34<1.41
(1,5)至(2,10)等。。。
使用1.41(sqrt(2))作为允许的最大距离的原因是,与屏幕底部成45度角的一组像素看起来仍然是连接的

现在,在打印中,需要将值舍入以与精确的像素对齐。有很多方法可以做到这一点。最简单的方法就是四舍五入到下一个有效值,这在大多数情况下都有效。它确实有一个不幸的副作用,那就是你的线条看起来会有锯齿状的台阶(如果圆角移动的像素越多,台阶就会显得越锯齿状)。这种锯齿称为“锯齿”,因为真实点通过点的非真实表示(别名)呈现

第二种方法是根据点的接近程度,按比例交替地使两个像素变暗。x轴上位于(0.5)的点将使两个像素变暗50%,而位于(0.25)的点将使0像素变暗75%,使1像素变暗25%。这是消除混叠,可能会导致线条稍微模糊,但看起来更直。这种模糊性可以通过画一条粗线来消除

我希望这能让您了解许多高质量绘图例程背后的数学原理,当然还有比我刚才介绍的更复杂的方法。

基于该算法,下面是一个java实现 假设
x2>x1和y2>y1
,并使用整数算术

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;
            }
        }
}
import java.applet.applet;
导入java.awt.*;
公共类斜坡扩展小程序{
私有整数x1=20,y1=10;
私有整数x2=300,y2=700;
@凌驾
公共空间涂料(图g){
抽绳(x1、y1、x2、y2、g);
//g、 抽绳(x1、y1、x2、y2、g);
}
专用空心绘图点(整数x、整数y、图形g){
g、 抽绳(x,y,x,y);
}
@凌驾
公共void init(){
这个。设置大小(500700);
}
专用虚线(图x1、图y1、图x2、图y2、图g){
int dx=x2-x1;
int dy=y2-y1;
int席=1;
int D=2*dx-dy;
int x=x1;
对于(int y=y1;y 0){
x= x+席;
D=D-2*dy;
}
D=D+2*dx;
}
}
}

根据角度的不同,您应该在
x
y
上迭代。它没有“点之间的间隙”。这根本不是一条线。你画的是单个的点,为什么你希望它们是相互连接的呢?@f1sh他在问如何在没有间隙的情况下做到这一点。所有的线实际上都是点,只是没有间隙。好吧,如果
m
大于1,那么很明显,你会有间隙,所以你需要检查
y
并将
1/m
添加到
x
。如果你注意到你也需要处理负值,那就需要额外加分。当然,我的方法和user2023577都会遇到垂直线等问题。但是如果你采用任何一种方法,很可能你可以轻松处理这些问题。一般来说,它是通过假装一个极小的斜率来完成的,这个斜率在屏幕上是看不到的,但是它足够大,可以避免被零除的错误