Dreieck aus Pixeln zeichnen

Goldenprime

Mitglied
Hallo,
ich würde gerne ein Dreieck auf ein BufferedImage Zeichnen, ohne dabei java.awt.Graphics zu benutzen. Das heißt jetzt also, dass alles was ich habe die Methode img.setRGB() (also die Methode um ein einzelnes Pixel anzusteuern) und die Koordinaten der Eckpunkte der Dreiecks sind. Mein erster Lösungsansatz sah ungefähr so aus:

Java:
public static void fill_triangle(int[][] c, BufferedImage img, int[] rgb) {
Arrays.sort(c, new Comparator<int[]>() {      
            @Override
            public int compare(int[] o2, int[] o1) {
                return Integer.compare(o2[1], o1[1]);
            }
        });
        double f1 = (double)(c[0][0] - c[1][0]) / (double)(c[1][1] - c[0][1]);
        double f2 = (double)(c[0][0] - c[2][0]) / (double)(c[2][1] - c[0][1]);
        double f3 = (double)(c[1][0] - c[2][0]) / (double)(c[2][1] - c[1][1]);    
        
        //double f4 = (double)(c[0][2] - c[1][2]) / (double)(c[0][0] - c[1][0]);
        //double f5 = (double)(c[0][2] - c[2][2]) / (double)(c[0][0] - c[2][0]);
        
        int i1 = 1; int i2 = 1; int rx1 = 0; int rx2 = 0; int ry = 0;
        while(c[0][1] + i1 <= c[2][1] ) {
            if(c[0][1] + i1 <= c[1][1]) {
                rx1 = c[0][0]-(int)((i1-1) * f1);
                ry = c[0][1] + (i1-1);
            }
            else {
                rx1 = (int)(c[1][0]-((i2-1) * f3));
                ry = c[0][1] + (i1-1);
                i2++;
            }
            rx2 = c[0][0]-(int)((i1-1) * f2);
            i1++;
            DVL(rx1, rx2, ry, img, rgb);
        }
        if(c[0][1] == c[1][1] && c[1][1] == c[2][1]) {
            DVL(c[0][0], c[1][0], c[0][1], img, rgb);
            DVL(c[1][0], c[2][0], c[0][1], img, rgb);
            DVL(c[0][0], c[2][0], c[0][1], img, rgb);
        }
        else if(c[0][1] == c[1][1]) {
            DVL(c[0][0],c[1][0],c[0][1], img, rgb);
        }
        
        
    }
    
    
    public static void DVL(int x1, int x2, int y, BufferedImage img, int[] rgb) {
        int i = 0;
        if (x1 < x2) {
            while(i + x1 <= x2) {
                if(x1 + i < DISPLAY.screenSizeL[0] && x1 + i >= 0 && y >= 0 && y < DISPLAY.screenSizeL[1]) {
                img.setRGB(x1 + i, y, Color.HSBtoRGB(rgb[0], rgb[1], rgb[2]));
                }
                i++;
            }
        }
        else if (x1 > x2) {
            while(i + x2 <= x1) {
                if(x2 + i < DISPLAY.screenSizeL[0] && x2 + i >= 0 && y >= 0 && y < DISPLAY.screenSizeL[1]) {
                img.setRGB(x2 + i, y, Color.HSBtoRGB(rgb[0], rgb[1], rgb[2]));
                
                }
                i++;
            }
        }
        else {
            if(x2< DISPLAY.screenSizeL[0] && x2 >= 0 && y >= 0 && y < DISPLAY.screenSizeL[1]) {
            img.setRGB(x2, y, Color.HSBtoRGB(rgb[0], rgb[1], rgb[2]));
            }
        }
        
    }

Leider ist dieser Code nicht effizient genug und er zeichnet auch kein 100% korrekten Dreiecke.
Es währe super, wenn mir jemand sagen könnte, wie man so etwas besser machen könnte.
 
Schon fertig?
Java:
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;

import javax.swing.JFrame;

public class Dreieck {
    public static void drawLine(int x0, int y0, int x1, int y1, BufferedImage buf, int rgb) {
        if (Math.abs(y1 - y0) < Math.abs(x1 - x0)) {
            if (x0 > x1)
                drawLineLow(x1, y1, x0, y0, buf, rgb);
            else
                drawLineLow(x0, y0, x1, y1, buf, rgb);
        } else {
            if (y0 > y1)
                drawLineHigh(x1, y1, x0, y0, buf, rgb);
            else
                drawLineHigh(x0, y0, x1, y1, buf, rgb);
        }
    }

    public static void drawLineLow(int x0, int y0, int x1, int y1, BufferedImage buf, int rgb) {
        int dx = x1 - x0;
        int dy = y1 - y0;
        int yi = 1;
        if (dy < 0) {
            yi = -1;
            dy = -dy;
        }
        int D = (2 * dy) - dx;
        int y = y0;
        for (int x = x0; x <= x1; x++) {
            buf.setRGB(x, y, rgb);
            if (D > 0) {
                y = y + yi;
                D = D + (2 * (dy - dx));
            } else {
                D = D + 2 * dy;
            }
        }
    }

    public static void drawLineHigh(int x0, int y0, int x1, int y1, BufferedImage buf, int rgb) {
        int dx = x1 - x0;
        int dy = y1 - y0;
        int xi = 1;
        if (dx < 0) {
            xi = -1;
            dx = -dx;
        }
        int D = (2 * dx) - dy;
        int x = x0;
        for (int y = y0; y <= y1; y++) {
            buf.setRGB(x, y, rgb);
            if (D > 0) {
                x = x + xi;
                D = D + (2 * (dx - dy));
            } else {
                D = D + 2 * dx;
            }
        }
    }

    public static void drawDreieck(int x0, int y0, int x1, int y1, int x2, int y2, BufferedImage buf, int rgb) {
        drawLine(x0, y0, x1, y1, buf, rgb);
        drawLine(x0, y0, x2, y2, buf, rgb);
        drawLine(x1, y1, x2, y2, buf, rgb);
    }

    public static void main(String[] args) {
        BufferedImage img = new BufferedImage(300, 300, BufferedImage.TYPE_INT_RGB);
        drawDreieck(50, 50, 50, 250, 250, 150, img, Color.red.getRGB());
        Canvas c = new Canvas() {
            private static final long serialVersionUID = 1L;

            @Override
            public void paint(Graphics g) {
                g.drawImage(img, 0, 0, null);
            }

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(img.getWidth(), img.getHeight());
            }
        };
        JFrame f = new JFrame();
        f.add(c);
        f.pack();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
    }
}
 
Schon fertig?
Java:
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;

import javax.swing.JFrame;

public class Dreieck {
    public static void drawLine(int x0, int y0, int x1, int y1, BufferedImage buf, int rgb) {
        if (Math.abs(y1 - y0) < Math.abs(x1 - x0)) {
            if (x0 > x1)
                drawLineLow(x1, y1, x0, y0, buf, rgb);
            else
                drawLineLow(x0, y0, x1, y1, buf, rgb);
        } else {
            if (y0 > y1)
                drawLineHigh(x1, y1, x0, y0, buf, rgb);
            else
                drawLineHigh(x0, y0, x1, y1, buf, rgb);
        }
    }

    public static void drawLineLow(int x0, int y0, int x1, int y1, BufferedImage buf, int rgb) {
        int dx = x1 - x0;
        int dy = y1 - y0;
        int yi = 1;
        if (dy < 0) {
            yi = -1;
            dy = -dy;
        }
        int D = (2 * dy) - dx;
        int y = y0;
        for (int x = x0; x <= x1; x++) {
            buf.setRGB(x, y, rgb);
            if (D > 0) {
                y = y + yi;
                D = D + (2 * (dy - dx));
            } else {
                D = D + 2 * dy;
            }
        }
    }

    public static void drawLineHigh(int x0, int y0, int x1, int y1, BufferedImage buf, int rgb) {
        int dx = x1 - x0;
        int dy = y1 - y0;
        int xi = 1;
        if (dx < 0) {
            xi = -1;
            dx = -dx;
        }
        int D = (2 * dx) - dy;
        int x = x0;
        for (int y = y0; y <= y1; y++) {
            buf.setRGB(x, y, rgb);
            if (D > 0) {
                x = x + xi;
                D = D + (2 * (dx - dy));
            } else {
                D = D + 2 * dx;
            }
        }
    }

    public static void drawDreieck(int x0, int y0, int x1, int y1, int x2, int y2, BufferedImage buf, int rgb) {
        drawLine(x0, y0, x1, y1, buf, rgb);
        drawLine(x0, y0, x2, y2, buf, rgb);
        drawLine(x1, y1, x2, y2, buf, rgb);
    }

    public static void main(String[] args) {
        BufferedImage img = new BufferedImage(300, 300, BufferedImage.TYPE_INT_RGB);
        drawDreieck(50, 50, 50, 250, 250, 150, img, Color.red.getRGB());
        Canvas c = new Canvas() {
            private static final long serialVersionUID = 1L;

            @Override
            public void paint(Graphics g) {
                g.drawImage(img, 0, 0, null);
            }

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(img.getWidth(), img.getHeight());
            }
        };
        JFrame f = new JFrame();
        f.add(c);
        f.pack();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
    }
}
Danke für die Antwort, ich habe meine Frage etwas schlecht formuliert. Eigentlich suche ich nach einer Möglichkeit das Dreieck Auszufüllen. Der Grund warum ich hierfür nicht die fillPolygon Methode benutze ist der, dass bevor ein Pixel gezeichnet wird erst noch eine Bedingung geprüft werden muss. Und da ich keine Ahnung habe wie ich das anstellen soll brauche ich eben einen Ersatz für diese Methode.
 
Hier habe ich etwas, aber SO hat dabei geholfen: https://stackoverflow.com/questions...ermine-whether-a-2d-point-is-within-a-polygon

u1.png

u2.png

Java:
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.Arrays;

import javax.swing.JFrame;

public class Dreieck {
    public static class Polygon {
        int[] xs;
        int[] ys;
        int l;

        public Polygon(int[] xs, int[] ys) {
            this.xs = xs;
            this.ys = ys;
            this.l = xs.length;
        }

        boolean pointProbablyInRect(int x, int y) {
            int xmin = Arrays.stream(xs).min().getAsInt();
            int ymin = Arrays.stream(ys).min().getAsInt();
            int xmax = Arrays.stream(xs).max().getAsInt();
            int ymax = Arrays.stream(ys).max().getAsInt();
            if (x < xmin || x > xmax || y < ymin || y > ymax) {
                // Definitely not within the polygon!
                return false;
            }
            return true;
        }

        boolean pointDefinitelyInPolygon(int x, int y) {
            if (pointProbablyInRect(x, y)) {
                boolean b = false;
                int i, j;
                for (i = 0, j = l - 1; i < l; j = i++) {
                    if (((ys[i] > y) != (ys[j] > y)) && (x < (xs[j] - xs[i]) * (y - ys[i]) / (ys[j] - ys[i]) + xs[i]))
                        b = !b;
                }
                return b;
            }
            return false;
        }
    }

    public static void drawLine(int x0, int y0, int x1, int y1, BufferedImage buf, int rgb) {
        if (Math.abs(y1 - y0) < Math.abs(x1 - x0)) {
            if (x0 > x1)
                drawLineLow(x1, y1, x0, y0, buf, rgb);
            else
                drawLineLow(x0, y0, x1, y1, buf, rgb);
        } else {
            if (y0 > y1)
                drawLineHigh(x1, y1, x0, y0, buf, rgb);
            else
                drawLineHigh(x0, y0, x1, y1, buf, rgb);
        }
    }

    public static void drawLineLow(int x0, int y0, int x1, int y1, BufferedImage buf, int rgb) {
        int dx = x1 - x0;
        int dy = y1 - y0;
        int yi = 1;
        if (dy < 0) {
            yi = -1;
            dy = -dy;
        }
        int D = (2 * dy) - dx;
        int y = y0;
        for (int x = x0; x <= x1; x++) {
            buf.setRGB(x, y, rgb);
            if (D > 0) {
                y = y + yi;
                D = D + (2 * (dy - dx));
            } else {
                D = D + 2 * dy;
            }
        }
    }

    public static void drawLineHigh(int x0, int y0, int x1, int y1, BufferedImage buf, int rgb) {
        int dx = x1 - x0;
        int dy = y1 - y0;
        int xi = 1;
        if (dx < 0) {
            xi = -1;
            dx = -dx;
        }
        int D = (2 * dx) - dy;
        int x = x0;
        for (int y = y0; y <= y1; y++) {
            buf.setRGB(x, y, rgb);
            if (D > 0) {
                x = x + xi;
                D = D + (2 * (dx - dy));
            } else {
                D = D + 2 * dx;
            }
        }
    }

    public static void drawDreieck(Polygon p, BufferedImage buf, int rgb) {
        drawLine(p.xs[0], p.ys[0], p.xs[1], p.ys[1], buf, rgb);
        drawLine(p.xs[0], p.ys[0], p.xs[2], p.ys[2], buf, rgb);
        drawLine(p.xs[1], p.ys[1], p.xs[2], p.ys[2], buf, rgb);
    }

    public static void fillDreieck(Polygon p, BufferedImage buf, int rgb) {
        for (int y = 0; y < buf.getHeight(); y++) {
            for (int x = 0; x < buf.getWidth(); x++) {
                if (p.pointDefinitelyInPolygon(x, y))
                    buf.setRGB(x, y, rgb);
            }
        }
    }

    public static void main(String[] args) {
        Polygon dreieck = new Polygon(new int[] { 50, 50, 250 }, new int[] { 50, 250, 150 });
        BufferedImage img = new BufferedImage(300, 300, BufferedImage.TYPE_INT_RGB);
        fillDreieck(new Polygon(new int[] { 0, 0, 300, 300 }, new int[] { 0, 300, 300, 0 }), img, Color.white.getRGB());
        fillDreieck(dreieck, img, Color.yellow.getRGB());
        drawDreieck(dreieck, img, Color.red.getRGB());
        Canvas c = new Canvas() {
            private static final long serialVersionUID = 1L;

            @Override
            public void paint(Graphics g) {
                g.drawImage(img, 0, 0, null);
            }

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(img.getWidth(), img.getHeight());
            }
        };
        JFrame f = new JFrame();
        f.add(c);
        f.pack();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
    }
}
 

Zurück
Oben