【问题标题】:Drawing Four Leaf Rose in Java用Java画四叶玫瑰
【发布时间】:2015-06-24 20:46:55
【问题描述】:

画四叶玫瑰真的很麻烦:这是练习:

画出“四叶玫瑰”,其极坐标方程为 r =cos(2θ) 。让 θ 以 100 步从 0 变为 2*pi。每次计算 r,然后使用公式从极坐标计算 (x, y) 坐标 x = r ⋅ cos( θ ) , y = r ⋅ sin(θ )

我的代码:

public Rose(double awidth, double aheight)
{
    width = awidth;
    height = aheight;
    theta = 0;
}


 public void drawRose(Graphics2D g2)
{
      Ellipse2D.Double test ; 
  double r = 0;
  for(int i = 0; i <= 100; i++)
   {
          r = Math.cos(Math.toRadians(2*theta)    );
      x = r *(    Math.cos(  Math.toRadians(theta) ) * width )  + 300;
          y = r * (  Math.sin(  Math.toRadians(theta) )   * height ) + 300 ;
     test = new Ellipse2D.Double(x, y, width, height);  
     theta += 3.6;
     g2.draw(test);
   }        
}

}

任何帮助将不胜感激。

【问题讨论】:

  • 您的实施到底有什么问题?
  • 我自己,我不会创建 Ellipse2D 对象,而是使用公式创建 List&lt;Point&gt;,然后在列表中的点之间画线。
  • 我还没有了解List
  • @MarsAtomic,它不会画出四叶玫瑰

标签: java polar-coordinates


【解决方案1】:

你最大的错误在这里:

test = new Ellipse2D.Double(x, y, width, height);  

您正在创建 100 个椭圆,其中的点位于玫瑰上,但具有所需玫瑰的高度和宽度。您真的不想要 100 个椭圆,而是想要连接您创建的 x 和 y 点之间的线,即将当前 x、y 与之前创建的 x、y 连接(只要有之前的 x 和y)。

一种方法是通过这些建议,但还有其他方法可以做到这一点:

  • 使用Path2D 对象,具体实现是Path2D.Double,用于保存数据点。在创建数据点之前创建它。
  • 使用从 0 到 100 的 for 循环,并在类的构造函数中执行此操作
  • 在循环中设置双 theta
  • 在循环中设置你的双 r 变量
  • 计算 x 和 y 双点
  • 通过将 x 和 y 点乘以比例因子来缩放它们,以使绘图具有一定的大小。我用的是 150.0
  • 通过添加平移常数来平移 x 和 y 值。我使用了 200,它在 400 x 400 JPanel 中运行良好。否则,玫瑰的中心将位于 0、0 处,并且只有四分之一可见。
  • 在 for 循环的第一次迭代中,调用 Path2D 的 moveTo(...) 方法添加起点
  • 在所有其他迭代中调用lineTo(...) 方法。这将在相邻点之间绘制一条线。
  • 在 for 循环之后,通过调用 closePath() 来关闭路径。
  • 通过将您的 Graphics 参数转换为 Graphics2D 对象(实际上您不需要此参数,因为您的 draw 方法获取一个 Grahpics2D 对象)并使用 Graphics2D 对象调用draw(path),在您的 JPanel 的 paintComponent 方法中绘制路径,传入你的 Path2D 对象。

例如,这是创建的:

使用此代码:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.geom.Path2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

@SuppressWarnings("serial")
public class RosePanel extends JPanel {
   private static final int PREF_W = 400;
   private static final int PREF_H = PREF_W;
   private static final int MAX = 100;
   private static final double SCALE = 150.0;
   private static final double DELTA_X = 200;
   private static final double DELTA_Y = DELTA_X;
   private static final Color ROSE_COLOR = Color.red;
   private static final Stroke ROSE_STROKE = new BasicStroke(8f);
   private Path2D path = new Path2D.Double();

   public RosePanel() {

      for (int i = 0; i < MAX; i++) {
         double theta = i * 2 * Math.PI / MAX;
         double r = Math.cos(2 * theta);
         double dX = SCALE * r * Math.cos(theta) + DELTA_X;
         double dY = SCALE * r * Math.sin(theta) + DELTA_Y;
         if (i == 0) {
            path.moveTo(dX, dY);
         } else {
            path.lineTo(dX, dY);
         }
      }
      path.closePath();
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g;
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
      g2.setColor(ROSE_COLOR);
      g2.setStroke(ROSE_STROKE);
      g2.draw(path);
   }

   @Override
   public Dimension getPreferredSize() {
      if (isPreferredSizeSet()) {
         return super.getPreferredSize();
      }
      return new Dimension(PREF_W, PREF_H);
   }

   private static void createAndShowGui() {
      RosePanel mainPanel = new RosePanel();

      JFrame frame = new JFrame("RosePanel");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

请注意,除了翻译和缩放之外,我的代码和您的代码之间的主要区别在于我正在连接创建的点之间的线。

【讨论】:

  • 您的建议看起来不错。但是,我仍然是 Java 的新手。我知道的东西是循环等基础知识,如何制作类......我刚刚挑选了一本书,我正在学习Java并尝试解决每章末尾的所有问题
  • @UstazMohammed:见编辑回答。你最大的错误是当你不需要也不想要椭圆时,你试图创建 100 个椭圆。你想连接点。
  • 我明白,但我使用的书没有提到 Path2D 类。哎呀,我在我的 Java 库中找不到它。没有 Path 类,还有另一种方法。我应该使用直线而不是椭圆吗?感谢您的时间和耐心。
  • 试试看会发生什么。
  • 我的 Java 库中没有 Path2D 类。有没有其他方法只使用直线或椭圆??
猜你喜欢
  • 1970-01-01
  • 2022-12-09
  • 1970-01-01
  • 1970-01-01
  • 2013-06-20
  • 2022-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多