Khashayar
Khashayar

Reputation: 3

Drawing concentric / rotating figures using MVC

As mentioned in the title, I'm trying to draw rotating and / or concentric figures onto a panel using MVC. Those figures are Circles, Ellipses and Astroids.

I was given the parametric equation I'm supposed to use in the task description:

    x = r_x * cos^power(phi * PI/180) and y = r_y * sin^power(phi * PI/180).   

Power is 1 (so a normal cos/sin) for circles/ellipses and 3 for Astroids.

I am also supposed to solve this using MVC, which is somewhat new to me, so sometimes I'm unsure whether I can do something or should not do it, lest I violate the MVC character. Phi is used to calculate a certain point on the circle(or Ellipses) and thus can be used to calculate only 3,4,5 etc points, drawing a triangle, square, pentagon etc.

I managed to calculate and draw simple figures using the above formulas. The problem I'm now facing is rotating and/or making them concentric.

Here's the code I'm using right now (the important part):

DescView(mostly basic stuff like setting up Buttons, Labels etc)

public DescView(){      
    model = new DescModel();
    createGUI(); // creates and sets up the frame
    createCanvas(); // creates the Panel which is drawn upon(own Class, see below)
    createChoiceStuff(); // creates Buttons, Labels, Textfields for Choices
    createPanels(); // creates and places the Panel for Choices
    addContentToPanels(); // adds the Buttons etc to the Panel
    frame.setVisible(true);

    controller = new DescController(model, this);
}

Canvas (inner Class to DescView):

class Canvas extends JPanel{

    DescModel model;
    int temp = 0;

    public Canvas(DescModel _model){
        this.model = _model;
    }

    public void paintComponent(Graphics _graphics){
        super.paintComponent(_graphics);


        //First while loop: Used to prevent drawing when Points is Empty
        //which it always is when the program starts.
        while(!model.getPoints().isEmpty()){
            //second loop: Keeps drawing a Line using a Collection(Points) until
            //the last element would go out of bounds.
            //drawLine takes the first 4 Elements from Points, then the 2,3,4,5
            //and so on.
            while(3 + temp < model.getPoints().size()){
                _graphics.drawLine(model.getPoints().get(0 + temp), model.getPoints().get(1 + temp), model.getPoints().get(2 + temp), model.getPoints().get(3 + temp));
                temp += 2;
            }
            //drawing the last Line from the two last Points to the first two
            _graphics.drawLine(model.getPoints().get(model.getPoints().size() - 2), model.getPoints().getLast(), model.getPoints().getFirst(), model.getPoints().get(1));

            //resetting temp and Points so they can be used again
            temp = 0;
            model.getPoints().clear();
        }               
    }   

DescController

public class DescController implements ActionListener {

    DescModel model;
    DescView view;

    DescController(DescModel _model, DescView _view){       
         this.model = _model;
         this.view = _view;

        view.addViewListener(this); 
    }

    @Override
    public void actionPerformed(ActionEvent ae) {
        //asks the model to calculate a circle(or a part of it, depending on degree = phi)
        //as you can see, Cirlce and Ellipse doe the same(which is good), unless RadiusX
        //and RadiusY are different. After the calculation the Canvas is oredered to
        //repainted
        if(ae.getSource() == view.getBtCirlce()){
            model.calcNumbers(Integer.parseInt(view.getTfRadiusX().getText()), Integer.parseInt(view.getTfRadiusY().getText()), 1, Integer.parseInt(view.getTfDegree().getText()));     
            view.getCanvas().repaint();
        }
        else if(ae.getSource() == view.getBtEllipse()){
            model.calcNumbers(Integer.parseInt(view.getTfRadiusX().getText()), Integer.parseInt(view.getTfRadiusY().getText()), 1, Integer.parseInt(view.getTfDegree().getText()));
            view.getCanvas().repaint();
        }
        else if(ae.getSource() == view.getBtAstroid()){
            model.calcNumbers(Integer.parseInt(view.getTfRadiusX().getText()), Integer.parseInt(view.getTfRadiusY().getText()), 3, Integer.parseInt(view.getTfDegree().getText()));         
            view.getCanvas().repaint();
        }
        else if(ae.getSource() == view.getBtInfo()){
            view.showInfo();
        }
        else if(ae.getSource() == view.getBtQuit()){
            System.exit(0);
        }
    }
}

DescModel

public class DescModel {
    int x = 1;
    int y = 1;

    LinkedList<Integer> points = new LinkedList<Integer>();

    public DescModel() {
    }
    //calculates X and Y coordinates one by one. Phi is used to calculate only a
    //certain number of points. For example for phi = 90 a Square is drawn
    //and a full circle for phi = 1 (if X = Y).
    //addOffset is used to place the figure in the middle of Canvas, which
    //has a width and height of 600.
    public void calcNumbers(int _radiusX, int _radiusY, int _potenz, int _phi){
        for(int i = 1; i <= 360 / _phi; i++){
            calcX(_radiusX, _potenz, _phi * i);
            calcY(_radiusY, _potenz, _phi * i);
        }
        addOffset();
    }   
    //Calculates using the above formula and adds the point to the Collection
    private void calcX(int _radiusX, int _potenz, int _phi){
        x = 300 + (int)(_radiusX * Math.pow(Math.cos(_phi * (Math.PI / 180)), _potenz));
        addToPoints(x);
    }

    private  void calcY(int _radiusY, int _potenz, int _phi){
        y = 300 + (int)(_radiusY * Math.pow(Math.sin(_phi * (Math.PI / 180)), _potenz));
        addToPoints(y);
    }

    private void addOffset(){
        for(int i = 0; i < points.size(); i++){
        }
    }

    private void addToPoints(int _number){
        points.add(_number);
    }
}

Now the next thing I want to / have to do is allowing the option of rotating with a fixed radius and drawing the same thing concentric. Obviously I could run the same model.calcNumbers() with smaller parameters. However, I'm not sure I can do that, since the view should not make a call to the model directly right? And even if that would be allowed, if I were to call repaint, the old circle would disappear. Using the same array also wouldn't work, since then I would draw circles which all had a single line connecting them. Regarding rotation, I'd probably add a certain value to each point and then draw it again. How would I go about that drawing part though? Same problem as with concentric: The old picture would be gone.

Thanks in advance for any help.

Edit: Since there appears to be some confusion: I don't need an animation of this. It'd be enough to have a set of shapes. For Example: Draw a circle with radius 100, another with radius 90, next with radius 80 etc.

On a side note: This is the first question for me, so any tips regarding formatting, formulating the question better etc. are of course welcome.

Upvotes: 0

Views: 418

Answers (1)

trashgod
trashgod

Reputation: 205805

This AnimationTest illustrates the basic approach using a simpler parametric equation. For rotations, you can use AffineTransform, as shown here and here. Finally, this answer elaborates on how Swing uses the MVC pattern.

Upvotes: 1

Related Questions