简体   繁体   English

在圆的边上画动圆

[英]Drawing moving circle on edge of circle

I'm having troubles with my drawing: 我在绘画时遇到麻烦:

Basically, I have an arc drawn: 基本上,我画了一条弧:

g.drawArc(x1-75, y2, 150, 150, 90, 180);

and from what I'm getting, this draws me left half of a circle, based on rectangle(well, square in that case) with the edge of 150 and left right corner x1-75,y2. 从我得到的结果中,这得出了我的一个圆的左半部分,该矩形是基于矩形(在这种情况下是正方形),其边缘为150,左角为x1-75,y2。 It's radius should be 75. 半径应为75。

Now I'm drawing a small point: 现在,我要指出一点:

g.fillOval(x-5, y-5, 10, 10);

and I set 然后我设定

x = x1 + (75*cos(3*Math.PI/2));
y = y2 + 75 + (75*sin(3*Math.PI/2));

which I believe should set the small circle on the bottom of the arc. 我认为应该在圆弧的底部设置一个小圆圈。

Let's have 让我们

int n = 0; 

Now I have a timer, that for every tick does 现在我有一个计时器,每一个刻度

n += 1;

and repaints component. 并重新绘制组件。

Shouldn't this code: 此代码不应该:

if(n < 180){
x = (int) (x1 + (75*(Math.cos(3*Math.PI/2 - n*Math.PI/180))));
y = (int) (y2 + 75 + (75*-(Math.sin(3*Math.PI/2 - n*Math.PI/180))));
}

lead the small circle around the arc in clockwise direction? 沿顺时针方向绕弧线引导小圆圈?

Instead it seems to me it jumps to random point on screen and stays there. 相反,在我看来,它跳到屏幕上的随机点并停留在该位置。

This gets a lot easier with any kind of Object Oriented Model. 使用任何一种面向对象的模型,这都变得容易得多。 Start with a circle object that keeps track of its location and its radius, and is able to paint itself when given a graphics object. 从一个圆形对象开始,该对象跟踪其位置和半径,并在给定图形对象时能够绘制自身。

From there, I surrounded that with a CircleOrbit object that keeps track of: 从那里开始,我用一个CircleOrbit对象围绕了该对象,该对象跟踪:

  • A center circle that is not moving center 中心圆不移动center
  • An orbiting circle orbiter that changes its position as time goes on 随着时间的流逝而改变其位置的绕圈orbiter
  • The tick (orbiting position). 刻度线(轨道位置)。 I implemented it as degrees, but that could easily change. 我将其实现为度,但是可以轻松更改。

I then added a method to recalculate the position of the oribiter at a given tick amount, updateOrbiterLoc() . 然后我添加了一个方法来重新计算的位置oribiter在给定的tick量, updateOrbiterLoc() From there it is fairly simple to create a helper to both increase the tick and update the orbiter location, and a simple JPanel subclass to paint the CircleOrbit . 从那里开始,创建一个既增加刻度线又更新轨道器位置的助手非常简单,并创建一个简单的JPanel子类来绘制CircleOrbit

Finally, in the main method, I created a simple JFrame holding the JPanel subclass, and created a timer to call the tick() method and repaint the frame. 最后,在main方法中,我创建了一个包含JPanel子类的简单JFrame ,并创建了一个计时器来调用tick()方法并重新绘制框架。

The circle starts on the x-axis and rotates clockwise. 圆从x轴开始,然后顺时针旋转。 The rotation speed is determined by TIMER_DELAY . 旋转速度由TIMER_DELAY确定。

Here's a basic runnable implementation that gets the job done. 这是完成任务的基本可运行实现。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Point2D;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;


public class CircleOrbit{

    private Circle center;
    private Circle orbiter;
    private int tick;

    //Amount in degrees * this const = amount in radians
    private static final double DEG_TO_RAD = Math.PI / 180;

    private static final int TIMER_DELAY = 25;

    /** Constructor for a CircleOrbit object.
     * Uses the given circle as the center circle, creates an
     * orbiter circle 1/10th the radius of the center and
     * on the x-axis of the center circle to start.
     * These constants should probably be pulled out to final ints
     * in a real implementation.
     */
    public CircleOrbit(Circle center){
        this.center = center;
        orbiter = new Circle(new Point2D.Double(), center.radius/10);
        tick = 0;
        updateOrbiterLoc();
    }

    /** Updates the location of the orbiter circle based on tick */
    private void updateOrbiterLoc(){
        Point2D.Double d = new Point2D.Double();
        final double xCenter = center.center.x;
        final double yCenter = center.center.y;
        final double rad = center.radius;
        d.setLocation(xCenter + rad * Math.cos(tick * DEG_TO_RAD),
                      yCenter + rad * Math.sin(tick * DEG_TO_RAD));
        orbiter.setCenter(d);
    }

    /** Increases tick and recalculates the position of the orbiter */
    public void tick(){
        tick += 1;
        updateOrbiterLoc();
    }

    /** Draws both of the circles in this CircleOrbit */
    public void draw(Graphics2D g){
        center.draw(g);
        orbiter.draw(g);
    }

    /** Creates a new panel to draw this orbit */
    public OrbitPanel getPanel(){
        return new OrbitPanel();
    }

    public static void main(String[] args){
        JFrame f = new JFrame();

        final CircleOrbit c = new CircleOrbit(new Circle(new Point2D.Double(250, 250), 200));

        final OrbitPanel o = c.getPanel();
        f.add(o, BorderLayout.CENTER);
        f.pack();
        f.setVisible(true);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final Timer t = new Timer(TIMER_DELAY, null);
        t.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                c.tick();
                o.repaint();
                t.restart();
            }
        });
        t.start();
    }

    @SuppressWarnings("serial")
    class OrbitPanel extends JPanel{

        public OrbitPanel(){

            //Quick and dirty way of making sure the panel is big enough
            setPreferredSize(new Dimension(
                    (int)(center.center.x + center.radius * 1.1), 
                    (int)(center.center.y + center.radius * 1.1)
                ));
        }

        @Override
        public void paintComponent(Graphics g){
            super.paintComponent(g);
            g.setColor(Color.BLACK);
            CircleOrbit.this.draw((Graphics2D)g);
        }
    }

    static class Circle {

        private Point2D.Double center;
        private double radius;

        public Circle(Point2D.Double c, double r){
            center = c;
            radius = r;
        }

        public void setCenter(Point2D.Double c){
            center = c;
        }

        public void draw(Graphics2D g){
            int x = (int)(center.x - radius);
            int y = (int)(center.y - radius);
            int size = (int)(radius * 2);
            g.drawOval(x, y, size, size);
        }

        public String toString(){
            return center.toString() + " r=" + radius;
        }
    }
}

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

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