立方体の位置を移動する

立方体の位置を移動する

 次は立方体の表示位置を移動することをしてみたいと思います。
中心部分だけ拡大すると角っこが見えなくなってしまいます。そこで絵を動かしてあちこち見えるようにしたいと思います。
処理は、フレームのなかで、ビューポートを動かしてあちこち覗き見るといったことになります。
マウスドラッグは立方体を回転するのに使っていますので、Altキーを押しながらのドラッグで立方体が移動するようにします。 またマウスのダブルクリックで立方体の表示中心が移動するようにも変更しました。結構面倒です。

最初は、GFrame()の修正ヶ所です。


import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.event.WindowEvent;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToolBar;
import javax.swing.JButton;

public class GFrame extends JFrame{

		  private MaPane MPane = null;
		  private GCanvas GCan = null;
		  private int DispWidth;
		  private int DispHeight;
		  private JPanel jPanel1 = new JPanel();
		  private BorderLayout borderLayout1 = new BorderLayout();
		  private JScrollPane jScrollPane1 = new JScrollPane();
		  private JButton jButton1 = new JButton();
		  private JToolBar jToolBar1 = new JToolBar();
		  /**
		   * メインフレームを作成する。
		   */
		  
		  public GFrame(Dimension Size){
		    this.DispWidth = Size.width;
		    this.DispHeight = Size.height;
		    // フレームの作成
		    initial();
		  }

		  /**
		   * フレームのイニシャル
		   */
		  void initial(){
		    // キャンバスの作成
		    GCan = new GCanvas();
		    MPane = new MaPane(GCan);	//add
		    // フレームの初期化
		    jInit();
		    jScrollPane1.setViewportView(MPane);
		    Viewp.setViewport(jScrollPane1.getViewport());
		    setSize(DispWidth, DispHeight);
		    setVisible(true);

		    Viewp.initCent();
		    Viewp.setFrameCent(Viewp.FrameSize.x/2,Viewp.FrameSize.y/2);

		    MPane.setLayerSize();
		    // 再描画
		    GCan.repaint();
		  }

		  /**
		   * イベント初期化処理。
		   */
		  private void jInit() {
		    this.addWindowListener(new java.awt.event.WindowAdapter() {
		      public void windowClosing(WindowEvent e) {
		        this_windowClosing(e);
		      }
		    });
		    this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
		    this.setTitle("ここはタイトル(^o^) ^o^ ^o^");
		    jButton1.setToolTipText("Reset");
		    jButton1.setBorder(null);
		    jButton1.setText("Reset");
		    jButton1.addActionListener(new java.awt.event.ActionListener() {
		      public void actionPerformed(ActionEvent e) {
		        jButton1_actionPerformed(e);
		      }
		    });	
		    jToolBar1.add(jButton1, null);
		    jPanel1.setLayout(borderLayout1);
		    this.getContentPane().add(jPanel1,  BorderLayout.CENTER);
		    jPanel1.add(jToolBar1, BorderLayout.NORTH);
		    jPanel1.add(jScrollPane1, BorderLayout.CENTER);

		// マウスアクションリスナー
		    jScrollPane1.addMouseListener(new java.awt.event.MouseAdapter() {
		    	public void mousePressed(MouseEvent e) {
		    		jScrollPane1_mousePressed(e);
		    	}
		     public void mouseReleased(MouseEvent e) {
		          jScrollPane1_mouseReleased(e);
		          }
		     public void mouseClicked(MouseEvent e) {
		          jScrollPane1_mouseClicked(e);
		     }
		    });
		    jScrollPane1.setWheelScrollingEnabled(false);
		    jScrollPane1.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
		        public void mouseDragged(MouseEvent e) {
		          jScrollPane1_mouseDragged(e);
		        }
		      });
		    jScrollPane1.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
		    jScrollPane1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
		    jScrollPane1.setWheelScrollingEnabled(false);
		    jScrollPane1.addMouseWheelListener(new MouseWheelListener() {
		      public void mouseWheelMoved(MouseWheelEvent e) {
		        jScrollPane1_mouseWheelMoved(e);
		      }
		    });
		  }

		  /**
		   * クローズボタンアクションリスナ
		   */
		  private void this_windowClosing(WindowEvent e) {
		    // 確認ダイアログの表示
			  if(JOptionPane.showConfirmDialog(this, "アプリケーションを終了します",
					  this.getTitle(),
					  JOptionPane.OK_CANCEL_OPTION)
					  != JOptionPane.YES_OPTION) { // OK
				  return;
			  }
			  System.exit(0);
		  }
		  
		  /**
		   * resetボタンアクションリスナ		   * 
		   */
		  void jButton1_actionPerformed(ActionEvent e) {
			  CubeVert.setangl();
			  Viewp.initRatio();
			  Viewp.setFactor(Viewp.initFactor);
			  MPane.setLayerSize();
			  GCan.repaint();
		  }
		  
		  /**
		   * マウスアクションリスナ
		   */	
		  // マウスプレスイベント
		  private void jScrollPane1_mousePressed(MouseEvent e) {
			  this_x = e.getX();
			  this_y = e.getY();
//			  del_x=e.getX();
//			  del_y=e.getY();
			  flagRotato = true;
			    
			  if (e.isAltDown()) {
			    	flgMapMove = true;
			    	
			    }
		  }

		  // マウスドラッグイベント。
		  private void jScrollPane1_mouseDragged(MouseEvent e) {
			if( this_x != -1 ) {
				if(flgMapMove){
			      /* 移動中 */
			    	  Viewp.moveCenter((e.getX() - this_x), (e.getY() - this_y));
			    	  GCan.repaint();             // 地図描画
			      }else if(flagRotato){
			    	  double dx =e.getX() - this_x;
			          double dy =e.getY() - this_y;
					  phi=dy*sense;
					  theta = dx*sense;
					  CubeVert.setangl(phi,theta);
					  CubeVert.rotate();
					  GCan.repaint(); 
			      }
				  this_x=e.getX();
				  this_y=e.getY();
			    }
		  }
		  //マウスホイールイベント
		private void jScrollPane1_mouseWheelMoved(MouseWheelEvent e) {
		    // 地図倍率変更
		    Viewp.changeFactor(0.1* e.getWheelRotation());
		    MPane.setLayerSize();
		    GCan.repaint();             // 地図描画
		   
		}
		
		 // マウスクリックイベント
		  private void jScrollPane1_mouseClicked(MouseEvent e) {
		    if ( e.getClickCount() > 1 ) {
		        // ダブルクリック->表示位置変更
		    	Viewp.moveCenter(e.getX()-Viewp.getp_x( ),
		        		e.getY()-Viewp.getp_y( ));
			    GCan.repaint();             // 地図描画	        
		      }
		    }
		  
		  private void jScrollPane1_mouseReleased(MouseEvent e) {
			    this_x = this_y = -1;
			    flgMapMove = false;
			    flagRotato = false;
		  }
		  
		  
		   //タイマー処理
		public void Reset1sec() {
			javax.swing.Timer tm;
			tm = new javax.swing.Timer(1000, new ActionListener(){
				public void actionPerformed (ActionEvent e) {
			        if(tmh){jButton1.setText("Reset");}else{jButton1.setText("   ");}
			        if(tmh){jButton1.setForeground(Color.red);}else{jButton1.setForeground(Color.gray);}
					if(tmh){tmh=false;}else{tmh=true;}     	    		
				}
			});
		    // タイマ起動
			tm.start();				
	}
	boolean flgMapMove = false;   //移動中
	boolean flagRotato = false;   //回転中
	private int this_x = -1;     // 現在位置x
	private int this_y = -1;     // 現在位置y
	  
	boolean tmh=true;	
	double phi=0,theta=0;
	double sense=0.01;

}

次は、Viewpクラスです。移動を行うために、フレームの中央であったり、ビューの位置であったり、色々な変更を加えています。


import java.awt.Point;
import java.awt.geom.Rectangle2D;

import javax.swing.JViewport;

public class Viewp {
	  // 表示倍率 初期値
	  static double initFactor = 1.0;
	  /** 表示倍率 */
	  static double Factor = 1.0;	//倍率
	  static double miniFactor=0.3; 
	  /** フレームサイズ(初期値)。 */
	  static Data2d FrameSize_i = new Data2d(1600.0d,1600.0d); 
	  /** フレームサイズ(Frame_i×倍率)。 */
	  static Data2d FrameSize = new Data2d(FrameSize_i.x ,FrameSize_i.y );   // 表示サイズ(FremeDist×倍率)
	  static Data2d FrameCent = new Data2d(250d,250d);
	  //ビュー比率
	  static double initRatio=0.5;
	  static Data2d FrameRatio=new Data2d(initRatio,initRatio);
	  
	  static JViewport viewPort;// ビューポート
	  private Viewp(){
	  }

	  static void setViewport(JViewport v){      //ビューポートの設定
	    viewPort = v;
	  }

	  //フレームサイズの設定を行う。
	  static void setFrameSize_i(double x, double y){
	    setFrameSize(x*Factor, y*Factor);
	  }

	   // フレーム中央の設定を行う
	  static void setFrameCent(double x, double y){
	    FrameCent.setData2d(x, y);
	  }
 	  
	 //倍率の設定を行う
	  static void setFactor(double dx){
	    // 倍率更新
	    Factor=dx;
	    // フレームサイズ更新
	    setFrameSize(FrameSize_i.x*Factor, FrameSize_i.y*Factor);
	    // 表示中央位置更新
	    setFrameCent(FrameSize.x/2, FrameSize.y/2);
	    setViewPort(); //ビューを移動する
	  }
	  
		 //ビューを中心に移動する
	static void setViewPort(){
	    double difx = FrameSize.x*FrameRatio.x - viewPort.getWidth()/2;
	    double dify = FrameSize.y*FrameRatio.y - viewPort.getHeight()/2;
	    if(difx < 0){difx=0;}
	    if(dify < 0){dify=0;}
	    // ビューポートを移動
	    Point p = viewPort.getViewPosition();
	    p.setLocation(difx, dify);
	    viewPort.setViewPosition(p);
	}
	  
	 //倍率を変更する
	static void changeFactor(double f){
		double size;
		size = Factor+f;
	    if(size > miniFactor){
	      // 倍率変更
	      setFactor(Factor+f);
	    }
	  }

	  //フレームサイズの設定を行う
	  static void setFrameSize(double dx, double dy){
	    FrameSize.setData2d(dx, dy);
	  }
	  
//フレームサイズXを取得する。
	  static int getFrameSizeX(){
	    return (int) FrameSize.x;
	  }

//フレームサイズYを取得する。
	  static int getFrameSizeY(){
	    return (int) FrameSize.y;
	  }
//ビュー位置との差を求める	  
	 static int getp_x(  ) {
		  Point p = viewPort.getViewPosition();
		  return((int)(FrameCent.x-p.x));
		  }
	static int getp_y(  ) {
		  Point p = viewPort.getViewPosition();
		  return((int)(FrameCent.y-p.y));
	} 
	  static void initCent(){

		    // ビューポイントを初期化
		    Point p = new Point((int)Math.round(FrameSize.x*initRatio-viewPort.getWidth()/2),
		                             (int)Math.round(FrameSize.y*initRatio-viewPort.getHeight()/2));
		    // ビューポートを移動
		    viewPort.setViewPosition(p);
		    // ビュー比率を中央に設定
		    setRatio(initRatio,initRatio);
		  }
	  
	  //ビュー位置の更新を行う
	  static void moveCenter(int x,int y){
	    // ビューポートを移動
	    Point p = viewPort.getViewPosition();
	    if((p.x -= x) < 0){      // 左端を越えた
	      p.x=0;
	    }
	    if((p.y -= y) < 0){      // 上端を越えた
	      p.y=0;
	    }
	    viewPort.setViewPosition(p);
	    // ビュー比率を更新
	    setRatio((double)(p.x+viewPort.getWidth()/2)/FrameSize.x,
	             (double)(p.y+viewPort.getHeight()/2)/FrameSize.y);
	    }
	  
	  // ビュー比率の設定を行う
	  static void initRatio(){
		    FrameRatio.setData2d(initRatio, initRatio);
	  }  
	  
	  static void setRatio(double x,double y){
	    if(x < 0) x = 0d;
	    if(y < 0) y = 0d;
	    if(x > 1) x = 1d;
	    if(y > 1) y = 1d;
	    FrameRatio.setData2d(fx, fy);
	  }
}

/**
 * xy位置情報クラス
 */
class Data2d {
	double x=0.0;
	double y=0.0;

  public Data2d(){ }

  // double 位置情報
  public Data2d(double x,double y){
    this.x = x;
    this.y = y;
  }
  public void setData2d(double x,double y){
	    this.x = x;
	    this.y = y;
  }
}

変更は、上の二つのクラスファイルのみのはずです。
 動作させると、左マウスのドラッグで立方体が回転、ホイールで拡大縮小、左Wクリックで中央が移動、altキーとドラッグで立方体の絵が移動、なんてことができましたでしょうか。
できるはずなんですけど。



次は立方体もどきの面の表と裏を色を変えて表現してみましょう。







ちとプログラムファイルが増えてきましたので、javaファイルを添付しておきましょう。