基于JAVA的图形填充

Hydra

发布日期: 2019-08-09 13:58:24 浏览量: 262
评分:
star star star star star star star star star star_border
*转载请注明来自write-bug.com

Overview

计算机图形学期末PJ

  • 多边形区域填充

  • 3D立方体投影展示程序

Requirements

JDK1.6

How to run

  1. 1. git clone https://github.com/whimsycwd/GemetoryPJ.git
  2. 2. mvn clean compile
  3. 3. mvn exec:java -Dexec.mainClass="base.FillPolygon" # 多边形填充
  4. 4. mvn exec:java -Dexec.mainClass="bonus.Cube" # 3D立方体投影

Hot to Operate

多边形填充

  • 鼠标点击n个点

  • 最后一个点双击

  • 这n个点组成的的多边形内部被染色

示例:

3D立方体投影

  • w and s : Pitch

  • a and d : Yaw

  • q and e : Roll

实现算法

多边形填充

  • 跨立实验判断线段相交
  1. public double cross(Point a, Point b, Point c) {
  2. return (double) (b.x - a.x) * (c.y - a.y) - (double) (b.y - a.y) * (c.x - a.x);
  3. }
  4. public int sign(double value) {
  5. if (value > 1e-8) return 1;
  6. if (value < -1e-8) return -1;
  7. return 0;
  8. }
  9. public boolean intersection(Point a, Point b, Point c, Point d) {
  10. if (sign(cross(a,b,c)) * sign(cross(a, b, d)) > 0) return false;
  11. if (sign(cross(c,d,a)) * sign(cross(c,d,b)) > 0) return false;
  12. return true;
  13. }
  • 针对每个像素, 采用射线法, 奇数个与多边形相交的点则为内部点.
  1. private void fill() {
  2. Point sp = new Point(9998, 9999);
  3. int n = nodes.size();
  4. for (int i = 0; i < WIDTH; ++i) {
  5. for (int j = 0; j < HEIGHT; ++j) {
  6. int intersectionNumber = 0;
  7. for (int k = 0; k < nodes.size(); ++k) {
  8. if (intersection(nodes.get(k), nodes.get((k + 1) % n), new Point(i,j), sp)) {
  9. ++intersectionNumber;
  10. }
  11. }
  12. if (intersectionNumber % 2 == 1) {
  13. Graphics g = p.getGraphics();
  14. g.drawLine(i, j, i, j);
  15. }
  16. }
  17. }

3D立方体投影

  • 图形旋转参考右手系旋转的方式
  1. // rotate along axis X
  2. double [][] matrixAlpha = new double[4][4];
  3. matrixAlpha[0][0] = 1;
  4. matrixAlpha[1][1] = Math.cos(alpha);
  5. matrixAlpha[1][2] = Math.sin(alpha);
  6. matrixAlpha[2][1] = -Math.sin(alpha);
  7. matrixAlpha[2][2] = Math.cos(alpha);
  8. matrixAlpha[3][3] = 1;
  9. // rotate along axis Y;
  10. double [][] matrixBeta = new double[4][4];
  11. matrixBeta[0][0] = Math.cos(beta);
  12. matrixBeta[0][2] = -Math.sin(beta);
  13. matrixBeta[1][1] = 1;
  14. matrixBeta[2][0] = Math.sin(beta);
  15. matrixBeta[2][2] = Math.cos(beta);
  16. matrixBeta[3][3] = 1;
  17. double [][] matrixGamma = new double[4][4];
  18. matrixGamma[0][0] = Math.cos(gamma);
  19. matrixGamma[0][1] = Math.sin(gamma);
  20. matrixGamma[1][0] = -Math.sin(gamma);
  21. matrixGamma[1][1] = Math.cos(gamma);
  22. matrixGamma[2][2] = 1;
  23. matrixGamma[3][3] = 1;
  24. g.setColor(Color.white);
  25. g.clearRect(p.getX(), p.getY(), p.getWidth(), p.getHeight());
  26. Point3D [] points2 = new Point3D[8];
  27. for (int i = 0; i < 8; ++i) {
  28. double [] row = new double[4];
  29. row[0] = points[i].getX();
  30. row[1] = points[i].getY();
  31. row[2] = points[i].getZ();
  32. row[3] = 1;
  33. row = multiply(row, matrixAlpha);
  34. row = multiply(row, matrixBeta);
  35. row = multiply(row, matrixGamma);
  36. points2[i] = new Point3D(row[0], row[1], row[2]);
  37. drawDot(g, row[0], row[1]);
  38. }
  • 面染色采用 P497 画家算法, 先对平面的Z重心进行排序, 由远及近进行染色.
  1. // fill in color
  2. double [] center = new double[6];
  3. for (int i = 0; i < 6; ++i) {
  4. center[i] = avg(points2, facet[i]);
  5. }
  6. int [] idx = new int[6];
  7. for (int i = 0; i < 6; ++i) {
  8. idx[i] = i;
  9. }
  10. for (int i = 0; i < 6; ++i) {
  11. for (int j = i+1; j < 6; ++j) {
  12. if (center[idx[i]] > center[idx[j]]) {
  13. int t = idx[i];
  14. idx[i] = idx[j];
  15. idx[j] = t;
  16. }
  17. }
  18. }
  19. for (int i = 0; i < 6; ++i) {
  20. Polygon polygon = new Polygon();
  21. for (int j = 0; j < 4; ++j) {
  22. int nodeId = facet[idx[i]][j];
  23. polygon.addPoint(transform(points2[nodeId].getX()), transform(points2[nodeId].getY()));
  24. }
  25. g.setColor(penColor[idx[i]]);
  26. g.fillPolygon(polygon);
  27. }

遇到的困难

  • Point3D类属于javafx包, 不是标准包, 最终改为自定义的类

  • 图形渲染闪烁问题, 从AWT转化为Swing, 用其框架自动的Double-Buffering来避免闪烁问题, 其中在画图的时候应传递同一个Graphics 否则会导致画布刷新, 从而展示不出新的东西.

参考文献

上传的附件 cloud_download 基于JAVA的图形填充.zip ( 325.37kb, 1次下载 )
error_outline 下载需要8点积分

发送私信

希望从来不会放弃你,是你放弃了希望

15
文章数
23
评论数
最近文章
eject