简体   繁体   English

Java2D:如何使用 GeneralPath 绘制圆的切片

[英]Java2D: how to draw the slice of a circle with GeneralPath

I want to create a wheel of fortune game for practice.我想创建一个命运之轮游戏来练习。 I created the wheel slices using GeneralPath, but I'm having issues finding out what is supposed to be the beizer point to have a perfect circle.我使用 GeneralPath 创建了轮切片,但我在找出什么应该是具有完美圆圈的 beizer 点时遇到了问题。 Take a look at the screenshot and you'll see the issue.看一下屏幕截图,您会发现问题所在。

在此处输入图像描述

I don't know the formula I should use to get the proper value, now I'm basically just guessing with:我不知道我应该使用什么公式来获得正确的值,现在我基本上只是在猜测:

        path.moveTo(x, y); // the center

        this.firstPointX = x + wSize * Math.cos(angle*i);
        this.firstPointY = y + wSize * Math.sin(angle*i);

        path.lineTo(this.firstPointX, this.firstPointY);

        this.secondPointX = x + wSize * Math.cos(angle*(i+1));
        this.secondPointY = y + wSize * Math.sin(angle*(i+1));

        path.moveTo(x, y); // back to the center
        path.lineTo(this.secondPointX, this.secondPointY);

        this.beizerX = x + (THIS IS THE VALUE I NEED) * Math.cos((angle*i+angle/2));
        this.beizerY = y + (THIS IS THE VALUE I NEED) * Math.sin((angle*i+angle/2));

        path.curveTo(this.secondPointX, this.secondPointY, this.beizerX, this.beizerY, this.firstPointX, this.firstPointY);

        path.closePath();

Why not just use Arc2D or simply draw a circle and 6 lines?为什么不直接使用Arc2D或简单地画一个圆和 6 条线? Then the basic problem is how to determine two points on a circle (start point and end point, which is 180 degrees away)那么基本问题就是如何确定圆上的两点(起点和终点,相隔180度)

Maybe something like...也许像...

旋转我

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private GeneralPath gp = new GeneralPath();

        public TestPane() {

            //GeneralPath gp = new GeneralPath();
            gp.append(new Ellipse2D.Double(0, 0, 200, 200), true);

            for (double angle = 0; angle < 180; angle += 30) {
                Point2D startPoint = pointOnCircle(angle, 100);
                Point2D endPoint = pointOnCircle(angle + 180, 100);

                gp.moveTo(startPoint.getX(), startPoint.getY());
                gp.lineTo(endPoint.getX(), endPoint.getY());
            }

        }

        protected Point2D pointOnCircle(double degrees, double radius) {
            double origin = radius;
            double rads = Math.toRadians(degrees);
            double x = origin + (Math.cos(rads) * radius);
            double y = origin + (Math.sin(rads) * radius);

            return new Point2D.Double(x, y);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(300, 300);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            RenderingHints hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHints(hints);
            g2d.translate(50, 50);
            g2d.draw(gp);
            g2d.dispose();
        }
    }

}

Arc2D

Because, you know, you can因为,你知道,你可以

再给我旋转一些

import java.awt.Dimension;
import java.awt.EventQueue;
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.GeneralPath;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private GeneralPath gp = new GeneralPath();

        public TestPane() {
            gp.append(new Ellipse2D.Double(0, 0, 200, 200), true);

            for (double angle = 0; angle < 360; angle += 30) {
                Arc2D arc = new Arc2D.Double(0, 0, 200, 200,
                        angle,
                        30,
                        Arc2D.PIE);
                gp.append(arc, false);
            }

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(300, 300);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            RenderingHints hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHints(hints);
            g2d.translate(50, 50);
            g2d.draw(gp);
            g2d.dispose();
        }
    }

}

I tried to use arches but I had trouble rotating them.我尝试使用拱门,但无法旋转它们。

Easy as Pi像 Pi 一样简单

像 Pi 一样简单

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private GeneralPath gp = new GeneralPath();
        private double spinValue = 0;

        public TestPane() {
            gp.append(new Ellipse2D.Double(0, 0, 200, 200), true);

            for (double angle = 0; angle < 360; angle += 30) {
                Arc2D arc = new Arc2D.Double(0, 0, 200, 200,
                        angle,
                        30,
                        Arc2D.PIE);
                gp.append(arc, false);
            }

            Timer timer = new Timer(5, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    spinValue += 0.01;
                    repaint();
                }
            });
            timer.start();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(300, 300);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            RenderingHints hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHints(hints);

            Rectangle2D bounds = gp.getBounds2D();
            double x = (getWidth() - bounds.getWidth()) / 2d;
            double y = (getHeight() - bounds.getHeight()) / 2d;

            AffineTransform at = AffineTransform.getTranslateInstance(x, y);
            at.rotate(spinValue, bounds.getCenterX(), bounds.getCenterY());

            g2d.transform(at);
            g2d.draw(gp);
            g2d.dispose();
        }
    }

}

I also would like to fill the single slices with gradients and animate indipendently with rotations and such我也想用渐变填充单个切片,并用旋转等独立动画

Then you can't use a single Path , as it's treated as a single graphical element, you will need to use individual slices, so I would highly recommend using Arc2D as it would be simple to maintain a list of them and simply transform the Graphics context as needed然后你不能使用单个Path ,因为它被视为单个图形元素,你需要使用单独的切片,所以我强烈建议使用Arc2D因为维护它们的列表并简单地转换Graphics会很简单根据需要上下文

I resurrect an ancient topic so I really sorry about that.我复活了一个古老的话题,所以我真的很抱歉。 ) But i faced a similar problem recently and here is my solution. )但我最近遇到了类似的问题,这是我的解决方案。

Here's a picture described my decision这是一张描述我决定的图片

And finally my code (variables names are got from the topicstarter's post).最后是我的代码(变量名称来自 topicstarter 的帖子)。

    // x, y                                        - center;
    // wSize                                       - radius of the circle
    // angle = 2 * Math.PI / (number_of_sectors)   - sector angle 
    
    // before the cycle 
    double bezierAngle = Math.atan(Math.tan(angle/4) * 4/3);
    double bezierRadius = wSize / Math.cos(bezierAngle); 
    

    // inside the cycle 
    path.moveTo(x, y); // center

    firstPointX = x + wSize * Math.cos(angle*i);
    firstPointY = y + wSize * Math.sin(angle*i);

    path.lineTo(firstPointX, firstPointY);

    firstBezierX = x + bezierRadius * Math.cos(angle*i + bezierAngle);
    firstBezierY = y + bezierRadius * Math.sin(angle*i + bezierAngle);
    
    secondBezierX = x + bezierRadius * Math.cos(angle*(i+1) - bezierAngle);
    secondBezierY = y + bezierRadius * Math.sin(angle*(i+1) - bezierAngle);
    
    secondPointX = x + wSize * Math.cos(angle*(i+1));
    secondPointY = y + wSize * Math.sin(angle*(i+1));

    path.curveTo(firstBezierX, firstBezierY, secondBezierX, secondBezierY, secondPointX, secondPointY);
    
    path.lineTo(x, y); // back to the center

    path.closePath();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM