Desenhar retas a partir do centro do circulo

20 respostas
J

Bom dia amigos!

Bem, tenho uma dúvida: Como eu faço para que sejam desenhadas um certo número de retas partindo do centro do círculo?

Abaixo um código que eu gostaria de fazer isso. Este código desenha 8 círculos concentricos. Agora eu preciso desenhar a partir do centro, retas como se fosse uma tela de radar.

Seria como seu estivesse fatiando os círculos a partir do centro.

import javax.swing.JPanel;
import java.awt.*;
import java.math.*;

public class CirclesJPanel extends JPanel {
 
 public void paintComponent( Graphics g ) {
    
    Graphics2D g2d = (Graphics2D)g;
	g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
    super.paintComponent( g );
	
	for ( int topLeft = 0; topLeft < 80; topLeft += 10 ) {
	
	
		int radius = 160 - ( topLeft * 2 );
        
		g2d.drawArc( topLeft + 10, topLeft + 25, radius, radius, 0, 360 );
	} 
 }

 }

20 Respostas

E

Sabe um pouco de trigonometria? Se souber, ajuda.

Quantos segmentos de reta você quer desenhar? Em que ângulos?

J

entanglement:
Sabe um pouco de trigonometria? Se souber, ajuda.

Quantos segmentos de reta você quer desenhar? Em que ângulos?

O numero de retas inicialmente, pode ser 8, depois vai ser variavel, como se fossem divididas em pizza, com porcoes de tamanho iguais. Tais retas devem comecar no centro do circulo e chegar ate no final do grafico. Se puderem me ajudar, ficaria muito grato. Conheco e tenho mais experiencia com outras parte do java, agora que estou precisando trabalhar com graficos.

Abaixo a forma pretendida:

Depois que eu conseguir criar esta forma, preciso pintar alguns pedacinhos individualmente, assim como no imagem. Mas por hora, preciso apenas de uma maneira com o codigo acima de criar aquela grade. Grato.

E

É melhor aprender a pintar já os pedaços, isso pode ser feito com fillArc mesmo. No seu caso em particular, é bem mais fácil você já pintar os pedaços que desenhar os segmentos de reta, já que você está com dificuldades com trigonometria.
http://java.sun.com/javase/6/docs/api/java/awt/Graphics.html#fillArc(int,%20int,%20int,%20int,%20int,%20int)

http://www.jchq.net/applets/arc_demo.htm

J

entanglement:
É melhor aprender a pintar já os pedaços, isso pode ser feito com fillArc mesmo. No seu caso em particular, é bem mais fácil você já pintar os pedaços que desenhar os segmentos de reta, já que você está com dificuldades com trigonometria.
http://java.sun.com/javase/6/docs/api/java/awt/Graphics.html#fillArc(int,%20int,%20int,%20int,%20int,%20int)

http://www.jchq.net/applets/arc_demo.htm

Amigo, esse é um grafico de níveis. Existe alguma funcao que me posicione no centro deste circulo? Ele irá funcionar assim: Cada fatia corresponde a um setor, e cada pedaco desta fatia representa um nivel, ou seja, neste caso como tenho 8 circulos, quando for fatiado em partes iguais, cada fatia devera possui 8 níveis.

valeu.

E

Infelizmente o meu proxy não está me deixando visualizar sua imagem. Você quer algo parecido com isto?

J

[quote=entanglement]Infelizmente o meu proxy não está me deixando visualizar sua imagem. Você quer algo parecido com isto?

Amigo, postei em outro image hosting, v c agora agora da pra vc ver a imagem, é um trabalho pra facul, eh um grafico diferente dos demais.

Nao sei se estou burlando alguma regra do forum, mas to postando aqui tbem o link direto da imagem:
[URL]http://www.glowfoto.com/static_image/29-094525L/4516/png/06/2010/img4/glowfoto[/URL]

Da um olhada ai, valeu!

E

Ah, beleza, isso não é tão difícil de desenhar. Vou ver se monto um exemplo depois do almoço.

V

João, por que você duplicou o tópico e criou outro usuário?

Seu tópico original era aqui:
http://www.guj.com.br/posts/list/210927.java#1072525

Você poderia ter continuado a complementar as informações por lá, pois eu ainda receberia um e-mail.

Você chegou a ler os artigos que indiquei?
No terceiro link, havia a explicação de como achar um ponto que está na superficie de uma circunferência.

J

entanglement:
Ah, beleza, isso não é tão difícil de desenhar. Vou ver se monto um exemplo depois do almoço.

Valeu amigo, estou aguardando sua ajuda. Acho que o mais complicado mesmo seria tipo: Se uma fatia tem 5 niveis, pintar 5 pedacinhos. se outra fatia tem nivel 2, pintar 2 pedacinhos.

Fiquei meio que sem tempo pra terminar este grafico, pois estou com atividades em PVM, Corba e simulacao. Caso conseguir me ajudar com um exemplo ficaria muito grato!

J

ViniGodoy:
João, por que você duplicou o tópico e criou outro usuário?

Seu tópico original era aqui:
http://www.guj.com.br/posts/list/210927.java#1072525

Você poderia ter continuado a complementar as informações por lá, pois eu ainda receberia um e-mail.

Você chegou a ler os artigos que indiquei?
No terceiro link, havia a explicação de como achar um ponto que está na superficie de uma circunferência.

Bom dia, nao estava conseguindo receber o email de alteracao de senha da outra conta, caso voce puder apagar o outro topico e manter este eu agradeceria muito. Acho que estava no tema errado aquele outro tambem ne? To apertadaço com o tempo aqui, trab de sistemas distribuidos, simulacao de redes e tava precisando de ajuda!! :smiley:

Aliás, voce está de parabéns com os seus artigos.

V

Ok, já que a trigonometria está difícil, vou te passar a fórmula.

x2 = cos(angle) * size + x1 y2 = sin(angle) * size + y1

Onde x1 e y1 são as coordenadas do ponto no centro da circunferência, e x2 e y2 são as coordenadas do ponto resultante, size é o tamanho do segmento de reta e angle é o ângulo que deve ser traçado em relação ao eixo x. Lembrando que o ângulo é em radianos e vai de 0 até 2*PI.

Agora é só fazer um for.

Se você usar vetores, fica mais fácil ainda. Se v1 for o vetor que marca o centro do circulo, v2 é definido por:

E
package guj;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Arc2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JPanel;

public class GraficoNivel extends JPanel {

    public static class Valor {
        private double valor;
        private String legenda;
        public Valor (double valor, String legenda) {
            this.valor = valor; this.legenda = legenda;
        }
        public double getValor() {
            return valor;
        }
        public void setValor(double valor) {
            this.valor = valor;
        }
        public String getLegenda() {
            return legenda;
        }
        public void setLegenda(String legenda) {
            this.legenda = legenda;
        }
    };
    
    public GraficoNivel() {
        super();
    }
    private List<Valor> valores = new ArrayList<Valor>();
    public void add (Valor valor) {
        valores.add (valor);
        System.out.println (valores);
    }
    public void clear() {
        valores.clear();
    }
    public void setDivisoes (int nDivisoes) {
        this.nDivisoes = nDivisoes;
    }
    
    private void normalize (Graphics2D g2d, Dimension dim) {
        g2d.translate(dim.width / 2, dim.height / 2);
        g2d.scale((dim.width - 2) / 2, -(dim.height - 2) / 2);
    }
    
    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        // Devemos a princípio determinar as dimensões, de forma que possamos normalizar
        // para um sistema de coordenadas com -1 <= x <= +1 e -1 <= y <= +1, e com o 
        // eixo dos x apontando para cima, não para baixo.
        normalize (g2d, getSize());
        g2d.setStroke(new BasicStroke(0.01f));
        // Vamos desenhar as fatias, de acordo om seus respectivos raios
        for (int i = 1; i <= valores.size(); ++i) {
            double radius = valores.get(i-1).getValor();
            double angle = 360 / valores.size();
            g2d.setPaint (new Color ((int) (255 * i / valores.size()), (int) (255 * i / valores.size()), (int) (255 * i / valores.size())));
            System.out.println (radius);
            Arc2D.Double d = new Arc2D.Double (-radius, -radius, 2 * radius, 2 * radius, 270- (int) (angle * (i-1)), (int) angle, Arc2D.PIE);
            g2d.fill (d);
        }
        g2d.setPaint(Color.BLACK);
        // Vamos desenhar agora os raios (um para cada Valor)
        System.out.println (valores.size());
        for (int i = 0; i < valores.size(); ++i) {
            double theta = 2 * Math.PI * i / valores.size();
            g2d.draw (new Line2D.Double(0, 0, Math.sin(theta), Math.cos(theta)));
        }
        // Agora, vamos desenhar a quantidade de subdivisões
        for (int i = 1; i <= nDivisoes; ++i) {
            double radius = i * 1.0 / nDivisoes;
            Ellipse2D.Double d = new Ellipse2D.Double(-radius, -radius, 2*radius, 2*radius); 
            g2d.draw(d);
        }
        g2d.dispose();
    }
    
    private int nDivisoes = 3;
}

Exemplo de uso.

package guj;

import java.awt.BorderLayout;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class ExemploGraficoNivel extends JFrame {

    private static final long serialVersionUID = 1L;
    private JPanel jContentPane = null;
    private GraficoNivel grfNivel = null;

    private GraficoNivel getGrfNivel() {
        if (grfNivel == null) {
            grfNivel = new GraficoNivel();
            grfNivel.setDivisoes(5);
            grfNivel.add (new GraficoNivel.Valor(0.5, "meio"));
            grfNivel.add (new GraficoNivel.Valor(0.7, "meio"));
            grfNivel.add (new GraficoNivel.Valor(0.9, "meio"));
            grfNivel.add (new GraficoNivel.Valor(1.2, "meio"));
            grfNivel.add (new GraficoNivel.Valor(0.6, "meio"));
        }
        return grfNivel;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                ExemploGraficoNivel thisClass = new ExemploGraficoNivel();
                thisClass.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                thisClass.setVisible(true);
            }
        });
    }
    public ExemploGraficoNivel() {
        super();
        initialize();
    }

    private void initialize() {
        this.setSize(300, 300);
        this.setContentPane(getJContentPane());
        this.setTitle("Teste Gráfico Nível");
    }
    private JPanel getJContentPane() {
        if (jContentPane == null) {
            jContentPane = new JPanel();
            jContentPane.setLayout(new BorderLayout());
            jContentPane.add(getGrfNivel(), BorderLayout.CENTER);
        }
        return jContentPane;
    }
}


J
entanglement:
package guj;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Arc2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JPanel;

public class GraficoNivel extends JPanel {

    public static class Valor {
        private double valor;
        private String legenda;
        public Valor (double valor, String legenda) {
            this.valor = valor; this.legenda = legenda;
        }
        public double getValor() {
            return valor;
        }
        public void setValor(double valor) {
            this.valor = valor;
        }
        public String getLegenda() {
            return legenda;
        }
        public void setLegenda(String legenda) {
            this.legenda = legenda;
        }
    };
    
    public GraficoNivel() {
        super();
    }
    private List<Valor> valores = new ArrayList<Valor>();
    public void add (Valor valor) {
        valores.add (valor);
        System.out.println (valores);
    }
    public void clear() {
        valores.clear();
    }
    public void setDivisoes (int nDivisoes) {
        this.nDivisoes = nDivisoes;
    }
    
    private void normalize (Graphics2D g2d, Dimension dim) {
        g2d.translate(dim.width / 2, dim.height / 2);
        g2d.scale((dim.width - 2) / 2, -(dim.height - 2) / 2);
    }
    
    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        // Devemos a princípio determinar as dimensões, de forma que possamos normalizar
        // para um sistema de coordenadas com -1 <= x <= +1 e -1 <= y <= +1, e com o 
        // eixo dos x apontando para cima, não para baixo.
        normalize (g2d, getSize());
        g2d.setStroke(new BasicStroke(0.01f));
        // Vamos desenhar as fatias, de acordo om seus respectivos raios
        for (int i = 1; i <= valores.size(); ++i) {
            double radius = valores.get(i-1).getValor();
            double angle = 360 / valores.size();
            g2d.setPaint (new Color ((int) (255 * i / valores.size()), (int) (255 * i / valores.size()), (int) (255 * i / valores.size())));
            System.out.println (radius);
            Arc2D.Double d = new Arc2D.Double (-radius, -radius, 2 * radius, 2 * radius, 270- (int) (angle * (i-1)), (int) angle, Arc2D.PIE);
            g2d.fill (d);
        }
        g2d.setPaint(Color.BLACK);
        // Vamos desenhar agora os raios (um para cada Valor)
        System.out.println (valores.size());
        for (int i = 0; i < valores.size(); ++i) {
            double theta = 2 * Math.PI * i / valores.size();
            g2d.draw (new Line2D.Double(0, 0, Math.sin(theta), Math.cos(theta)));
        }
        // Agora, vamos desenhar a quantidade de subdivisões
        for (int i = 1; i <= nDivisoes; ++i) {
            double radius = i * 1.0 / nDivisoes;
            Ellipse2D.Double d = new Ellipse2D.Double(-radius, -radius, 2*radius, 2*radius); 
            g2d.draw(d);
        }
        g2d.dispose();
    }
    
    private int nDivisoes = 3;
}
Exemplo de uso.
package guj;

import java.awt.BorderLayout;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class ExemploGraficoNivel extends JFrame {

    private static final long serialVersionUID = 1L;
    private JPanel jContentPane = null;
    private GraficoNivel grfNivel = null;

    private GraficoNivel getGrfNivel() {
        if (grfNivel == null) {
            grfNivel = new GraficoNivel();
            grfNivel.setDivisoes(5);
            grfNivel.add (new GraficoNivel.Valor(0.5, "meio"));
            grfNivel.add (new GraficoNivel.Valor(0.7, "meio"));
            grfNivel.add (new GraficoNivel.Valor(0.9, "meio"));
            grfNivel.add (new GraficoNivel.Valor(1.2, "meio"));
            grfNivel.add (new GraficoNivel.Valor(0.6, "meio"));
        }
        return grfNivel;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                ExemploGraficoNivel thisClass = new ExemploGraficoNivel();
                thisClass.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                thisClass.setVisible(true);
            }
        });
    }
    public ExemploGraficoNivel() {
        super();
        initialize();
    }

    private void initialize() {
        this.setSize(300, 300);
        this.setContentPane(getJContentPane());
        this.setTitle("Teste Gráfico Nível");
    }
    private JPanel getJContentPane() {
        if (jContentPane == null) {
            jContentPane = new JPanel();
            jContentPane.setLayout(new BorderLayout());
            jContentPane.add(getGrfNivel(), BorderLayout.CENTER);
        }
        return jContentPane;
    }
}

Muito obrigado a todos, principalmente ao amigo entanglement!!

J

Tentei colocar legenda em cada fatia mas ta saindo esquisito e as vezes nem sai. Alguma ideia de como posso colocar do lado de fora de cada fatia? Ou qual seriam as medidas que eu deveria considerar?

Abraco.

E

Acho que você não vai mais poder evitar fazer algumas contas, não? Você talvez tenha de achar um ponto no meio de cada fatia, e a partir desse ponto, posicionar sua legenda.

J

Voce poderia me dar um exemplo em uma fatia deste codigo por favor ? Depois contribuo com algum bom artigo aqui no GUJ. Estou com um projeto de software para a faculdade que algumas tarefas foram divididas entre os grupos. So que me foram delegadas outras tarefas que ainda nao foram concluidas. Obrigado.

E

Vou dar uma sugestão.

É que se você pensar bem, o posicionamento das legendas não é tão simples quanto parece; poderíamos ter de reduzir o desenho, e ficar puxando retas a partir do centro de cada fatia, o que é um pouquinho chato de fazer.

Eu já vi muitos gráficos em que a legenda era por cores, não diretamente sobre o desenho.

Então você poderia escolher umas cores bem diferentes (em vez dos diversos tons de cinza que usei) e então pôr a legenda do lado do desenho, talvez usando uma série de JLabels em que as cores do background fossem as cores do desenho.

J

entanglement:
Vou dar uma sugestão.

É que se você pensar bem, o posicionamento das legendas não é tão simples quanto parece; poderíamos ter de reduzir o desenho, e ficar puxando retas a partir do centro de cada fatia, o que é um pouquinho chato de fazer.

Eu já vi muitos gráficos em que a legenda era por cores, não diretamente sobre o desenho.

Então você poderia escolher umas cores bem diferentes (em vez dos diversos tons de cinza que usei) e então pôr a legenda do lado do desenho, talvez usando uma série de JLabels em que as cores do background fossem as cores do desenho.


Entao rapaz, eu comecei a fazer isso, coloquei um ArrayList para pegar as cores de todas as fatias coloridas. Mas nao estou conseguindo desenhar do lado do grafico. Pode me dar uma forca? E vc acha que o BorderLayout seria o melhor para este caso?

Obrigado pela rapida resposta.

E

Eu acho que não seria necessário desenhar do lado do gráfico (até porque você precisaria de mexer um pouco na parte de conversão de coordenadas. Você deve ter visto que, conforme o gráfico é redimensionado, o círculo fica na verdade como uma elipse e ocupa todo o gráfico).

Eu acho que você pode enquadrar esse gráfico em um JFrame ou JDialog (por exemplo), e pôr as legendas em JLabels ao lado do gráfico. É mais fácil.

J

entanglement:
Eu acho que não seria necessário desenhar do lado do gráfico (até porque você precisaria de mexer um pouco na parte de conversão de coordenadas. Você deve ter visto que, conforme o gráfico é redimensionado, o círculo fica na verdade como uma elipse e ocupa todo o gráfico).

Eu acho que você pode enquadrar esse gráfico em um JFrame ou JDialog (por exemplo), e pôr as legendas em JLabels ao lado do gráfico. É mais fácil.


Ele esta dentro de um Applet, o Jframe do grafico esta de dentro do ContentPane do Applet. Instanciei outro JPanel e estou usando o BorderLayout so que ele apertou muito para o lado. Tem alguma sugestao de LayoutManager que nao vai sufocar meu outro frame para o canto?

Criado 29 de junho de 2010
Ultima resposta 2 de jul. de 2010
Respostas 20
Participantes 3