[Resolvido]Como usar o Line2D?

1 resposta
T

Eu estou fazendo um applet que desenha polígonos unindo pontos do click do mouse
Cada click determina um vértice do polígono e a cada 2 vértices tem uma ARESTA
caso a aresta passo por algum ponto, eu preciso identificar este ponto e destacá-lo.

Eu tentei criar uma linha da classe Line2D.Float a cada 2 vértices e usar o método contains dessa linha em cada ponto, mas não funcionou em nada T_T
Alguém sabe a forma correta de usar?

Código do Applet:
import javax.swing.JApplet;

public class NewJApplet1 extends JApplet {
    @Override
    public void init() {
        add(new NewClass1(this.getWidth(), this.getHeight()));
    }
}
Código do JPanel usado no Applet:
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.util.LinkedList;
import java.util.List;
import javax.swing.JPanel;

public class NewClass1 extends JPanel{

    Point malha[][];            //Matriz que armazena os pontos da malha
    Point area;                 // area.x = largura do applet, area.y = altura do applet
    Point foco;                 // variavel responsavel por aramzenar qual ponto está sob o foco do mouse
    List<Point> vertices;       // Lista dos vértices
    List<Point> pontosAresta;   // Lista dos pontos nas arestas
    GeneralPath path;           // Path para desenhar o Polígono
    int passo;                  // distância entre os pontos da malha
    int k;                      // Quantidade de pontos em cada linha
    int l;                      // Quantidade de pontos em cada coluna

    NewClass1(int width, int height) {
        
        //inicia as variáveis
        foco = new Point();
        vertices = new LinkedList<Point>();
        pontosAresta = new LinkedList<Point>();        
        path = new GeneralPath();
        
        area = new Point(width, height); //obtém a largura e altura do Applet        
        
        desenhaMalha(10); //desenha a malha de pontos com 10px de espaçamento entre cada

        addMouseMotionListener(new MouseAdapter() {
            @Override
            public void mouseMoved(MouseEvent e) {
                
                /* Sempre que o mouse se mover atribui à variável foco o ponto 
                 mais próximo do mouse, que esteja há uma distância (passo/2) ou
                 menor */
                
                foco.setLocation(-1, -1);
                for (int i = 0; i < k; i++) {
                    if (((malha[i][0].x - (passo / 2)) < e.getX())
                            && (e.getX() < (malha[i][0].x + (passo / 2)))) {
                        for (int j = 0; j < l; j++) {
                            if (((malha[i][j].y - (passo / 2)) < e.getY())
                                    && (e.getY() < (malha[i][j].y + (passo / 2)))) {
                                foco.setLocation(malha[i][j]);
                            }
                        }
                    }
                }
                repaint();
            }
        });

        addMouseListener(new MouseAdapter() {
            
            @Override
            public void mouseClicked(MouseEvent e) {
                
                if ((foco.x > 0)) {                 // se o click foi sobre um ponto
                    vertices.add(new Point(foco));  // adiciona esse ponto como vértice                                    
                }
                
                // A CADA CLICK O PATH TODO É REFEITO
                path.reset();                       // limpa o path
                if (!vertices.isEmpty()) {          // e se houverem vértices
                    path.moveTo(vertices.get(0).x, vertices.get(0).y); // começa a desenhar o path no primeiro vértice
                    for (Point p : vertices) {      // e para cada vértice
                        path.lineTo(p.x, p.y);      // desenha uma linhapartindo do primeiro
                    }
                    // ESSA FUNÇÃO DEVERIA OBTER OS PONTOS QUE ESTÃO NAS ARESTAS (ENTRE 2 VÉRTICES)
                    getPontosNasArestas();
                }
                repaint();
                }
        });

    }

    /* Função responsável por desenhar a malha de pontos*/
    public void desenhaMalha(int passo) {

        this.passo = passo; //passo é a distância entre cada ponto em pixels
        k = area.x / passo; //k é o número de pontos nas linhas
        l = area.y / passo; // l é o número de pontos nas colunas

        malha = new Point[k][l];            // inicia a malha
        for (int i = 0; i < k; i++) {       // popula a malha com seus determinados pontos
            for (int j = 0; j < l; j++) {
                malha[i][j] = new Point(i * passo, j * passo);
            }
        }
        repaint();
    }

    // ESSA FUNÇÃO DEVERIA OBTER OS PONTOS QUE ESTÃO NAS ARESTAS (ENTRE 2 VÉRTICES)
    private void getPontosNasArestas() {

        pontosAresta.clear();                   // limpa a variável que armazena os pontos nas arestas
        Line2D linha = new Line2D.Float();      // inicializa uma Linha2D

        if (vertices.size() > 1) {              // caso haja mais de 1 vértice
            for (int h = 0; h < (vertices.size() - 1); h++) {
                linha.setLine(vertices.get(h), vertices.get(h + 1)); // desenha uma linha a cada 2 vértices
                for (int i = 0; i < k; i++) {                        // testa cada ponto da malha
                    for (int j = 0; j < l; j++) {
                        if (linha.contains(malha[i][j])){           // se a linha contiver o ponto
                            pontosAresta.add(malha[i][j]);          // adiciona o ponto no vetor de pontos nas arestas
                        }
                    }
                }
            }
        }
    }

    @Override
    public void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.setColor(Color.WHITE);
        g2d.fillRect(0, 0, area.x, area.y);

        Graphics2D g2d2 = (Graphics2D) g.create();
        g2d2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d2.setColor(Color.BLUE);
        g2d2.draw(path);
        AlphaComposite

        alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, (float) 0.1);
        g2d2.setComposite(alpha);
        g2d2.fill(path);
        g2d.setColor(Color.black);
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);

        for (int i = 0; i < k; i++) {
            for (int j = 0; j< l; j++) {
                g2d.drawOval((malha[i][j].x - 1), (malha[i][j].y - 1), 1, 1);
            }
        }

        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        if (!vertices.isEmpty()) {
            g2d.setColor(Color.blue);
            for (Point p : vertices) {
                g2d.fillOval((p.x - 3), (p.y - 3), 6, 6);
            }
        }

        if (!pontosAresta.isEmpty()) {
            g2d.setColor(Color.red);
            for (Point p : pontosAresta) {
                g2d.fillOval((p.x - 2), (p.y - 2), 4, 4);
            }
        }

        if (foco.x > 0) {
            g2d.setColor(Color.red);
            g2d.fillOval((foco.x - 2), (foco.y - 2), 4, 4);
        }
            g2d.dispose();
    }
}

1 Resposta

T

eu achei a resposta e como acabei encontrando esse meu tópico nas minhas buscas no google, vou colocar ela aqui pra quem acabar nesse problema ache a solução tb^^

essa função aqui:
// ESSA FUNÇÃO DEVERIA OBTER OS PONTOS QUE ESTÃO NAS ARESTAS (ENTRE 2 VÉRTICES)  
    private void getPontosNasArestas() {  
  
        pontosAresta.clear();                   // limpa a variável que armazena os pontos nas arestas  
        Line2D linha = new Line2D.Float();      // inicializa uma Linha2D  
  
        if (vertices.size() > 1) {              // caso haja mais de 1 vértice  
            for (int h = 0; h < (vertices.size() - 1); h++) {  
                linha.setLine(vertices.get(h), vertices.get(h + 1)); // desenha uma linha a cada 2 vértices  
                for (int i = 0; i < k; i++) {                        // testa cada ponto da malha  
                    for (int j = 0; j < l; j++) {  
                        if (linha.contains(malha[i][j])){           // se a linha contiver o ponto  
                            pontosAresta.add(malha[i][j]);          // adiciona o ponto no vetor de pontos nas arestas  
                        }  
                    }  
                }  
            }  
        }  
    }
esta testando se o ponto está na linha com o método contains da classe Line2D:
if (linha.contains(malha[i][j])){           // se a linha contiver o ponto  
                            pontosAresta.add(malha[i][j]);          // adiciona o ponto no vetor de pontos nas arestas  
                        }
porém, esse método não serve pra isso, ele é usado em Shapes pra ver se a Shape(que é um conjunto de linhas) contém o ponto e como uma linha somente não possui área, quando se utiliza este método com uma linha ele SEMPRE retorna false.

No meu caso uma solução foi:

if ((linha.ptLineDist(malha[i][j]) == 0)                // se o ponto está na reta da linha
                            // e se estiver entre a coordenada x do inicio da linha e a coordenada x do fim da linha
                            && (((vertices.get(h).x <= malha[i][j].x) && (vertices.get(h + 1).x >= malha[i][j].x)) 
                            || ((vertices.get(h).x >= malha[i][j].x) && (vertices.get(h + 1).x <= malha[i][j].x)))
                            // e se estiver entre a coordenada y do inicio da linha e a coordenada y do fim da linha
                            && (((vertices.get(h).y <= malha[i][j].y) && (vertices.get(h + 1).y >= malha[i][j].y)) 
                            || ((vertices.get(h).y >= malha[i][j].y) && (vertices.get(h + 1).y <= malha[i][j].y)))){          
                            pontosAresta.add(new Point(malha[i][j]));           // adiciona o ponto no vetor de pontos nas arestas
                        }

eu usei o método ptLineDist que retorna a distância entre o ponto e a linha, e caso o ponto esteja na mesma reta que a linha, retorna 0.

no meu caso, como eu queria ver se arestas continham pontos, eu precisava limitar isso a largura e altura da aresta.

Criado 22 de janeiro de 2010
Ultima resposta 23 de jan. de 2010
Respostas 1
Participantes 1