Dessiner un graphique vectoriel en Java 7


J'essaie de créer du code dans Swing / JPanel qui prend des variables (modifiables) et dessine un graphique comme ceci:

image

Je n'ai aucune idée par où commencer. L'idée est, il y aurait des points clés sur l'hexagone, une pour chaque variable, et une ligne serait de tracer entre chaque point, puis l'espace à l'intérieur de la forme personnalisée serait ombragée. Des idées?

Prototype de code

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

public class DrawPolygon extends JPanel {

int xOffset = 0;
int yOffset = 0;
int sizeModifer = 50;
int numOfPoints = 8;
int linePosition = 80;
double sizeMultiplier = 1;

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);

    Polygon[] polygons = new Polygon[5];
    for (int i = 0; i < polygons.length; i++){
        polygons[i] = new Polygon();
        for (int q = 0; q < numOfPoints; q++) {
            polygons[i].addPoint(
                xOffset + (int) (linePosition + (sizeModifer*sizeMultiplier)
                * Math.cos(q * 2 * Math.PI / numOfPoints)),
                yOffset + (int) ((linePosition - 10) + (sizeModifer*sizeMultiplier)
                * Math.sin(q * 2 * Math.PI / numOfPoints)));
        }//built points
        sizeMultiplier = sizeMultiplier - 0.2;
    }//build polygon arrays

    Polygon innerPolygon = new Polygon();
    for (int i = 0; i < numOfPoints; i++) {
        int randomRange = 5 + (int) (Math.random() * ((sizeModifer - 5) + 1));
        innerPolygon.addPoint(
            xOffset + (int) (linePosition + randomRange
            * Math.cos(i * 2 * Math.PI / numOfPoints)),
            yOffset + (int) ((linePosition - 10) + randomRange
            * Math.sin(i * 2 * Math.PI / numOfPoints)));
    }
    Graphics2D g2d = (Graphics2D) g;
    g2d.setRenderingHint(
        RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);
    g2d.setStroke(new BasicStroke(1));

    for (int i = 0; i < polygons.length; i++){
        g2d.setColor(Color.green);
        g2d.fill(polygons[i]);
        g2d.setColor(Color.black);
        g2d.draw(polygons[i]);
    }//draw polygons from arrays

    double distanceModifier = 1;
    for (int i = 0; i < numOfPoints; i++) {
        g2d.drawString("test"+(i+1),
            xOffset + (int) (linePosition + (sizeModifer*distanceModifier)
            * Math.cos(i * 2 * Math.PI / numOfPoints)),
            yOffset + (int) ((linePosition - 10) + (sizeModifer*distanceModifier)
            * Math.sin(i * 2 * Math.PI / numOfPoints)));
        distanceModifier = distanceModifier +.01;
    }

    g2d.setColor(new Color(255,213,200,90));
    g2d.fill(innerPolygon);
    g2d.setColor(Color.red);
    g2d.draw(innerPolygon);
}

@Override
public Dimension getPreferredSize() {
    // TODO calculate size based on geometry
    return new Dimension(160, 160);
}

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setTitle("Show Different Polygons");
            frame.add(new DrawPolygon());
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
    });
}

}

Author: Community, 0000-00-00

3 answers

JFreeChart comprend un SpiderWebPlot, sur la photo dans la démo, en vertu de Divers et discuté ici. Alors que SpiderWebChartDemo1 contient cinq catégories, votre image semble en contenir six.

image

 5
Author: trashgod, 2013-02-24 03:24:22

Bien sûr. Je suis sûr qu'il doit déjà y avoir des bibliothèques Java pour le faire; par exemple, Sonar montre un diagramme similaire à celui-ci. Il est généralement préférable d'utiliser le composant de quelqu'un d'autre au lieu d'écrire le vôtre si possible. Habituellement, j'utiliserais JFreeChart, mais il semble que cela n'ait pas un tel composant.

Si vous voulez écrire le vôtre, il vous suffit de faire quelques calculs simples de l'emplacement de chaque point sur le Web. Du centre, vous commenceriez par dessiner un ligne à 0 degrés. Ensuite, chaque ligne radiale suivante serait tournée par 2*pi/n radians. Vous pouvez appliquer une trigonométrie simple pour déterminer les coordonnées cartésiennes (x, y) à partir des angles et du rayon de chaque hexagone. Enfin, vous superposeriez la zone remplie. Donc, un algorithme pourrait être quelque chose comme ça. Dans le pseudocode suivant, le paramètre values est une liste de petits entiers positifs représentant chaque point du polygone comme un décalage par rapport au centre du diagramme. Pour un hexagon, par conséquent, vous auriez six valeurs dans cette liste.

function drawGraph(values):

    steps = maximum value from values
    lines = number of values

    webWidth = min(width, height)
    centerX = width / 2
    centerY = height / 2

    // Draw lines

    for radialLineNumber in 0..lines:
        angle = radialLineNumber * 2 * pi / lines;
        draw line from (centerX, centerY) to (centerX + cos(angle)*webWidth, centerY + sin(angle) * webWidth))
        edgePolygon = blank polygon
        for edgeNumber in 1..steps:
            x = centerX + cos(angle) * webWidth * edgeNumber / steps
            y = centerY + sin(angle) * webWidth * edgeNumber / steps
            add (x, y) to edgePolygon
        stroke polygon edgePolygon

    // Draw polygon

    areaPolygon = blank polygon
    radialLineNumber = 0
    for value in values:
        angle = radialLineNumber * 2 * pi / lines;
        x = centerX + cos(angle) * value * webWidth / steps
        y = centerY + sin(angle) * value * webWidth / steps
        add (x, y) to areaPolygon
    fill polygon areaPolygon

Je vous laisse le soin de traduire ce pseudocode en un vrai JComponent. Toutes les fonctions que j'ai utilisées sont soit sur Math ou Graphics2D. Vous pouvez définir l'opacité du polygone de zone avant de le dessiner.

 3
Author: Eric Galluzzo, 2013-02-23 21:04:53

Quelques notes sur votre exemple:

  • Utiliser les fonctions de Graphics2D pour rendre votre Polygon, qui implémente Shape.

  • Remplacer getPreferredSize(), tel que discuté ici.

  • Les objets Swing GUI doivent être construits et manipulés uniquement sur le thread de répartition des événements .

image

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

public class DrawPolygon extends JPanel {

    int xOffset = 0;
    int yOffset = 0;
    int sizeModifer = 50;
    int numOfPoints = 8;
    int linePosition = 80;

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Polygon outerPolygon = new Polygon();
        for (int i = 0; i < numOfPoints; i++) {
            outerPolygon.addPoint(
                xOffset + (int) (linePosition + sizeModifer
                * Math.cos(i * 2 * Math.PI / numOfPoints)),
                yOffset + (int) ((linePosition - 10) + sizeModifer
                * Math.sin(i * 2 * Math.PI / numOfPoints)));
        }
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setColor(Color.cyan);
        g2d.fill(outerPolygon);
        g2d.setStroke(new BasicStroke(2));
        g2d.setColor(Color.red);
        g2d.draw(outerPolygon);
    }

    @Override
    public Dimension getPreferredSize() {
        // TODO calculate size based on geometry
        return new Dimension(160, 160);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setTitle("Show Different Polygons");
                frame.add(new DrawPolygon());
                frame.pack();
                frame.setLocationByPlatform(true);
                frame.setVisible(true);
            }
        });
    }
}

Addendum: Sur la base des commentaires, cette révision restaure l'original innerPolygon.

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

public class DrawPolygon extends JPanel {

    int xOffset = 0;
    int yOffset = 0;
    int sizeModifer = 50;
    int numOfPoints = 8;
    int linePosition = 80;

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Polygon outerPolygon = new Polygon();
        for (int i = 0; i < numOfPoints; i++) {
            outerPolygon.addPoint(
                xOffset + (int) (linePosition + sizeModifer
                * Math.cos(i * 2 * Math.PI / numOfPoints)),
                yOffset + (int) ((linePosition - 10) + sizeModifer
                * Math.sin(i * 2 * Math.PI / numOfPoints)));
        }
        Polygon innerPolygon = new Polygon();
        for (int i = 0; i < numOfPoints; i++) {
            int randomRange = 5 + (int) (Math.random() * ((sizeModifer - 5) + 1));
            innerPolygon.addPoint(
                xOffset + (int) (linePosition + randomRange
                * Math.cos(i * 2 * Math.PI / numOfPoints)),
                yOffset + (int) ((linePosition - 10) + randomRange
                * Math.sin(i * 2 * Math.PI / numOfPoints)));
        }
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setStroke(new BasicStroke(2));
        g2d.setColor(Color.cyan);
        g2d.fill(outerPolygon);
        g2d.setColor(Color.red);
        g2d.draw(outerPolygon);
        g2d.setColor(Color.blue);
        g2d.fill(innerPolygon);
        g2d.setColor(Color.red);
        g2d.draw(innerPolygon);
    }

    @Override
    public Dimension getPreferredSize() {
        // TODO calculate size based on geometry
        return new Dimension(160, 160);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setTitle("Show Different Polygons");
                frame.add(new DrawPolygon());
                frame.pack();
                frame.setLocationByPlatform(true);
                frame.setVisible(true);
            }
        });
    }
}
 2
Author: trashgod, 2017-05-23 11:53:27