Java 窗口 绘制图形 #3

写在前面:

  高数下学到第二章,突发奇想要写一个程序画二元函数图像

  思路分了三层:

  ①抽象层:

    因变量z,自变量x、y,坐标原点x0、y0、z0

  ②投影实现层:

    屏幕投影坐标px、py,x轴与屏幕水平方向夹角theta1,z轴与屏幕铅直方向夹角theta2,缩放变量S

    分两种情况考虑了:

      1)单纯以z轴为旋转轴

        yp=S*z

        xp=S*(-x*sintheta1 + y*costheta2)

      2)以原点为定点旋转

        yp=S*(z*costheta2-x*sintheta2+y*costheta2) 这个经检验是错的

        xp=S*(-x*sintheta1 + y*costheta2)

  ③操作层:演草纸上写的和实际程序写的不一样,略

  运行效果:

  可以缩放、平移,但目前只能做到绕y轴旋转(因为绕原点旋转的代码挂了)

  pong友建议用矩阵做投影变换,有空试试

代码如下:

  1 package my_package;
  2 
  3 import java.awt.*;
  4 import java.awt.event.MouseAdapter;
  5 import java.awt.event.MouseEvent;
  6 import java.awt.event.MouseMotionAdapter;
  7 import java.awt.event.MouseWheelEvent;
  8 import java.awt.event.MouseWheelListener;
  9 import java.io.*;
 10 import javax.swing.JFrame;
 11 import javax.swing.JPanel;
 12 
 13 public class PonysAlgorithm2 extends JFrame
 14 {
 15     private static final long serialVersionUID = 1L;
 16     static int pony_winx=800,pony_winy=600;//窗口的长和宽
 17     static int pony_scale=2,pony_scale_tmp=4;//视图缩放变量
 18     static int theta1=0,theta2=0;//水平旋转角度,铅直旋转角度
 19     static int pony_square=250;//绘制xy正方形区域趋边长的一半
 20     static int pony_px=pony_winx/2,pony_py=pony_winy/2;//屏幕投影变量px和py
 21     
 22     static int pony_framex_ori,pony_framey_ori;//鼠标移动辅助变量
 23     static int pony_theta1_tmp,pony_theta2_tmp;//角度随鼠标移动变化辅助变量
 24     static int pony_px_tmp,pony_py_tmp;//屏幕投影量随鼠标移动变化辅助变量
 25     static int pony_project_x_tmp,pony_project_y_tmp;//屏幕投影量计算辅助变量
 26     static float pony_precision=40.0f;//绘制精度,但绘制点数只受pony_square影响,不受精度影响
 27     
 28     static double pony_project_x(double x, double y){//计算在屏幕上的投影px
 29         return (y*Math.cos(theta1/180.0f)-x*Math.sin(theta1/180.0f))*pony_scale;
 30     }
 31     static double pony_project_y(double z, double x, double y){//计算在屏幕上的投影py
 32         return z*pony_scale;
 33     }
 34     static double pony_z(double x, double y){//计算函数值
 35         return x*x/4-y*y/9;
 36     }
 37     
 38     public static void main(String[] args) throws Exception
 39     {
 40         JFrame ponyFrame=new JFrame("Pony's Algorithm II");
 41         ponyFrame.setLayout(null);
 42         JPanel ponyJPanel=new JPanel(){
 43             private static final long serialVersionUID = 1L;
 44             public void paint(Graphics g){
 45                 super.paint(g);
 46                 for(int y=-pony_square;y<=pony_square;++y)
 47                 {
 48                     g.setColor(Color.getHSBColor(0.54f+0.2f*(y+pony_square)/(pony_square*2.0f), 1.0f, 1.0f));
 49                     for(int x=-pony_square;x<=pony_square;++x)
 50                     {
 51                         pony_project_x_tmp=pony_px+(int)pony_project_x(x/pony_precision,y/pony_precision);
 52                         pony_project_y_tmp=pony_py+(int)pony_project_y(pony_z(x/pony_precision,y/pony_precision),x/pony_precision,y/pony_precision);
 53                         g.drawLine(pony_project_x_tmp, pony_project_y_tmp, pony_project_x_tmp, pony_project_y_tmp);
 54                     }
 55                 }
 56             }
 57         };
 58         
 59         /*Whole*/
 60         ponyFrame.setSize(pony_winx,pony_winy);
 61         ponyFrame.setResizable(false);
 62         ponyFrame.setLocationRelativeTo(null);
 63         ponyFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
 64         
 65         /*ICON*/
 66         File directory = new File("");
 67         ponyFrame.setIconImage(Toolkit.getDefaultToolkit().getImage(directory.getCanonicalPath()+"\icons\2.png"));
 68         
 69         /*DRAW*/
 70         ponyJPanel.setBounds(0, 0, pony_winx, pony_winy);
 71         ponyFrame.add(ponyJPanel);
 72         
 73         /*MOUSE*/
 74         ponyFrame.addMouseListener(new MouseAdapter() {
 75             @Override
 76             public void mousePressed(MouseEvent e) {//当任意鼠标键按下时,记录变量
 77                 pony_framex_ori=e.getXOnScreen();
 78                 pony_framey_ori=e.getYOnScreen();
 79                 pony_theta1_tmp=theta1;
 80                 pony_theta2_tmp=theta2;
 81                 pony_px_tmp=pony_px;
 82                 pony_py_tmp=pony_py;
 83             }
 84         });
 85         ponyFrame.addMouseMotionListener(new MouseMotionAdapter() {//当鼠标键按下并移动时,记录变量
 86             @Override
 87             public void mouseDragged(MouseEvent e) {//两个角度的改变
 88                 if(e.isShiftDown() && e.getButton()==0){
 89                     theta1=pony_theta1_tmp-(e.getXOnScreen()-pony_framex_ori)/2;
 90                     theta2=pony_theta2_tmp+(e.getYOnScreen()-pony_framey_ori)/2;
 91                 }
 92                 else if(e.getButton()==0){//两个投影坐标的改变
 93                     pony_px=pony_px_tmp+(e.getXOnScreen()-pony_framex_ori)/1;
 94                     pony_py=pony_py_tmp+(e.getYOnScreen()-pony_framey_ori)/1;
 95                 }
 96                 ponyJPanel.repaint();
 97             }
 98         });
 99         ponyFrame.addMouseWheelListener(new MouseWheelListener() {//鼠标滚轮滚动时,对图像进行缩放
100             @Override
101             public void mouseWheelMoved(MouseWheelEvent e) {
102                     if(e.getWheelRotation()==1) {
103                         if(pony_scale_tmp>2) {
104                             pony_scale_tmp-=1;
105                             pony_scale=pony_scale_tmp/2;
106                             ponyJPanel.repaint();
107                         }
108                     }
109                     if(e.getWheelRotation()==-1) {
110                         pony_scale_tmp+=1;
111                         pony_scale=pony_scale_tmp/2;
112                         ponyJPanel.repaint();
113                     }
114             }
115         });
116         
117         ponyFrame.setVisible(true);
118         return;
119     }
120 }

  十分良心加了注释哈哈

附件:

*jar所在目录*\icons\

2.png

原文地址:https://www.cnblogs.com/Antigonae/p/13953450.html