【问题标题】:creating a slope in Java在 Java 中创建斜坡
【发布时间】:2019-07-01 17:16:56
【问题描述】:

我试图在 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);

    }
}

【问题讨论】:

  • 根据角度,您应该迭代xy
  • 它没有“点之间的间隙”。这根本不是一条线。您绘制了各个点,为什么您期望它们确实是连接的?
  • @f1sh 他在问如何做到没有间隙。所有的线实际上都是点,只是没有间隙。
  • 好吧,如果m 比 1 大,那么你显然会有差距,那么你需要越过y 并将1 / m 添加到x。如果您注意到您还需要处理负值,则加分。

标签: java


【解决方案1】:

两个循环:只有当 deltaX > deltaY 时才循环 x++。 否则你只循环 y++。

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

fyi,您正在尝试生成图像,您也可以在矩阵中设置整数并制作屏幕外原始图像(BufferedImage 及其 .setRGB() 方法),稍后再绘制。这可能会更快并避免可见的绘画延迟。

【讨论】:

    【解决方案2】:

    通常这是通过使用一种算法来完成的,该算法不仅仅沿着 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...
    

    之所以使用 1.41 (sqrt(2)) 作为允许的最大距离,是因为与屏幕底部成 45 度角的像素仍然会显示为连接。

    现在,在您的绘图中,您需要对值进行四舍五入以与确切的像素对齐。有很多方法可以做到这一点。最简单的就是四舍五入到下一个有效值,这在大多数情况下都有效。它确实有一个不幸的副作用,那就是你的线条会出现锯齿状的台阶(四舍五入会使像素移动得更多,台阶会显得锯齿状)。这种锯齿状被称为“混叠”,因为真实点是通过该点的非真实表示(别名)呈现的。

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

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

    【讨论】:

    • 当然,我的方法和 user2023577 都会遇到垂直线等问题。但是如果您遵循任何一种方法,您很可能可以轻松处理这些问题。通常它是通过伪造一个无穷小的斜率来完成的,这个斜率不会在屏幕上被察觉,但足够大以避免除以零错误
    【解决方案3】:

    基于Bresenham算法,这里有一个java实现 假定x2 &gt; x1 and y2 &gt; 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;
                }
            }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-28
      相关资源
      最近更新 更多