在Java 7中绘制矢量图

时间:2013-02-23 20:23:28

标签: java swing jpanel vector-graphics

我正在尝试在Swing / JPanel中创建一些代码来获取一些(可变的)变量并绘制如下图形:

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;
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);
        }
    });
}

}

3 个答案:

答案 0 :(得分:5)

JFreeChart包含SpiderWebPlot,如{em>其他下的demo所示,并讨论了here。虽然SpiderWebChartDemo1包含五个类别,但您的图片似乎包含六个类别。

image

答案 1 :(得分:3)

不确定。我敢肯定必须有Java库才能做到这一点;例如,Sonar显示与此类似的图表。通常最好使用别人的组件,而不是尽可能自己编写。通常我会使用JFreeChart,但看起来它没有这样的组件。

如果你想自己编写,你只需要对网上每个点的位置做一些简单的计算。从中心开始,您将从0度开始画线。然后每个后续的径向线将旋转2*pi/n弧度。您可以应用一些简单的三角法来计算每个六边形的角度和半径的笛卡尔坐标(x,y)。最后,您将覆盖填充区域。所以算法可能是这样的。在下面的伪代码中,参数values是一个小的正整数列表,表示多边形上的每个点作为距图中心的偏移量。因此,对于六边形,此列表中将包含六个值。

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

我会留给你把这个伪代码翻译成真正的JComponent。我使用的所有功能都在MathGraphics2D上。您可能希望在绘制之前设置区域多边形的不透明度。

答案 2 :(得分:2)

关于你的例子的几点说明:

  • 使用Graphics2D的功能呈现实现Polygon的{​​{1}}。

  • 覆盖Shape,正如here所述。

  • 应在event dispatch thread构建和操作Swing GUI对象。

image

getPreferredSize()

附录:根据评论,此修订版会恢复原始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); } }); } }

innerPolygon