Thursday, January 30, 2014

Trammel Archimedes di JavaFX

Berikut ini saya berikan contoh animasi javaFX yakni dalam membuat trammel Archimedes.



Adapun source code nya adalah
package fjr.ellipse;

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;


// @author moh_fajar 
// @date: 31-1-2014

public class EllipseExp extends Application {

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

 Timeline animation;
 GraphicsContext gc; 
 Canvas canvas; 
 Trammel tr ;
 
 double angle; 

 double canvasWidth = 450 , canvasHeight = 350 ; 
 @Override
 public void start(Stage primaryStage) throws Exception {
  Group root = new Group();
  Group child = new Group(); 
  primaryStage.setScene(new Scene(root,500, 500));
  angle = 45; 
  tr = new Trammel(200, 150 , 100, 60, angle);
  canvas = new Canvas(canvasWidth, canvasHeight); 
  gc = canvas.getGraphicsContext2D(); 
  root.getChildren().add(child); 
  child.getChildren().addAll(canvas);
  animation = new Timeline();
  animation.getKeyFrames().addAll(
    new KeyFrame(Duration.millis(10),
      new EventHandler() {
       @Override
       public void handle(ActionEvent arg0) {
        angle-= Math.PI/200 ; 
        tr.setAngle(angle);
        tr.calculatePosition();
        draw(gc);
       }
      }));

  primaryStage.show();
  
  animation.setCycleCount(Timeline.INDEFINITE);
  animation.setAutoReverse(false);
  animation.play(); 
 }
 
 void draw(GraphicsContext gc){
  gc.setFill(Color.WHITE);
  gc.fillRect(0, 0, canvasWidth, canvasHeight);
  gc.setStroke(Color.BLACK);
  gc.strokeRect(0, 0, canvasWidth, canvasHeight);
  gc.setFill(Color.RED);
  gc.fillRect(tr.x, tr.y, 5, 5);
  gc.setFill(Color.BLUE);
  gc.fillRect(tr.x1, tr.y1, 5, 5);
  
  gc.setFill(Color.GREENYELLOW);
  gc.fillRect(tr.x2, tr.y2, 5, 5);
  
  gc.setStroke(Color.RED);
  gc.strokeLine(tr.x, tr.y, tr.x2, tr.y2);
  
  
  gc.setStroke(Color.BLACK);
  gc.strokeLine(tr.x2, tr.y1 - 110 , tr.x2, tr.y1 + 110);
  gc.strokeLine(tr.x2- 200, tr.y1  , tr.x2 + 200, tr.y1 );
  
  gc.setStroke(Color.BLACK);
  gc.strokeOval(tr.getXCorrection() -   tr.getA(), tr.getYCorrection() -  
      tr.getB(), 2 * tr.getA() , 2 * tr.getB());
 }

 class Trammel {

  double angle;
  double p, q;

  public double x, y; // posisi dari rod
  public double x1, y1 ; // posisi dari pivot 1 
  public double x2, y2 ; // posisi dari pivot 2

  
  double xCorrection; 
  double yCorrection; 
  /*
   * Dalam Trammel Archimedes, terdapat dua titik pivot yakni A dan B.
   * Sementara yang men-trace elipse adalah titik C pada ujung trammel.
   * Jarak A ke B adalah p, sementara jarak B ke C adalah q, dengan
   * demikian lintasan titik C ditentukan oleh x = (p + q) cos \theta y =
   * q sin theta.  lihat: http://en.wikipedia.org/wiki/Trammel_of_Archimedes
   */

  public Trammel(double x, double y, double p, double q, double angle) {
   this.xCorrection = x; 
   this.yCorrection = y; 
   
   this.p = p;
   this.q = q;
   this.angle = angle; 
  }

  
  public void setAngle(double angle) {
   this.angle = angle;
  }

  public void calculatePosition() {
   x = xCorrection+  (p + q) * Math.cos(angle);
   y = yCorrection + (q) * Math.sin(angle);
   
   x1 = x - q * Math.cos(angle); 
   y1 = y -  q * Math.sin(angle);
   
   x2 = x1 -   p * Math.cos(angle); 
   y2 = y1 -   p * Math.sin(angle); 
  }
  
  public double getA(){return (p+q);}
  public double getB(){return q ;}
  public double getXCorrection() {return xCorrection;}
  public double getYCorrection() {return yCorrection; }
 }

}

No comments: