Java 等式 5((θ/β) - cos(2πθ/β)) 的 Swing GUI - 绘制连续图形
Java Swing GUI for equation 5((θ/β) - cos(2πθ/β)) - to draw continuous graph
这是我之前问题的扩展post在这里 --
我已经根据 post 中提供的答案实施了 Java 程序,这是我的程序:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class DisplacementFunctionNew extends JFrame {
public DisplacementFunctionNew() {
setLayout(new BorderLayout());
add(new CosGraph(), BorderLayout.CENTER);
}
public static void main(String[] args) {
DisplacementFunctionNew frame = new DisplacementFunctionNew();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(6000, 6000);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setTitle("SineWave");
}
class CosGraph extends JPanel {
public void paintComponent(Graphics g) {
int graphHeight = 5; // Declared this to set the height of graph based on the value given here.
super.paintComponent(g);
int xBase = 100;
int top = 100;
int yScale = 100;
int xAxis = 360;
int yBase = top + yScale;
g.drawLine(xBase, top, xBase, top + 2 * yScale);
g.drawLine(xBase, yBase, xBase + xAxis, yBase);
g.setColor(Color.red);
double maxY = 0;
for (int i = 0; i < 360; i++) {
maxY = Math.max(maxY, Math.abs(getValue(i)));
}
int x, y;
for (int i = 0; i < 360; i++) {
x = xBase + i;
y = yBase - (int) (getValue(i)*graphHeight / maxY * yScale);
g.drawLine(x, y, x, y);
}
}
private double getValue(int theta) {
int beta = 45;
double b = (theta / (double) beta);
double angle = 2 * Math.PI * (b);
double c = Math.cos(angle);
double s = (b - c);
return s;
}
}
}
现在在这个程序中我想要一个名为 graphHeight
的变量来帮助增加图形的高度。如果我将变量的值指定为 1
那么我可以看到这样的输出:
现在,如果我尝试将高度增加到 5
,那么我会得到图形,但它显示的不是平滑的或连续的曲线,我得到的输出如下:
有人可以帮助我如何获得平滑连续曲线的输出吗?
您使用 graphHeight
定义下一个要绘制的点的 y g.drawLine(x, y, x, y);
。绘制点之间的距离将与 graphHeight
变量有关
您正在使用点绘制曲线。您在 x 轴上的每个位置放置一个点——这样做很有意义。
当图很小的时候,看起来还不错,因为这些点的y间隔比较小。但是,随着图形大小的增加,此缺陷变得更加明显。
这里的解决方法是用线条填充垂直的space。您有几个选项可以准确实施此操作:
- 从 [
x(i), y(i)]
到 [x(i+1),y(i+1)]
画一条线 -- 这很简单,但看起来可能不是您想要的样子。
- 从 [
x(i), y(i)]
到 [x(i),y(i+1)]
画一条线 -- 这仍然很简单,但它不会很正确:你继续向上,这样你就可以成为一个完整的人像素关闭。
- 从 [
x(i), y(i)]
到 [x(i),(y(i)+y(i+1))/2]
画一条线,然后从 [x(i+1), (y(i)+y(i+1))/2]
到 [x(i+1),y(i+1)]
画一条线——这就是 1 应该做的(忽略抗锯齿) ), 并且将是您可能的选项中最正确的。
我建议数字 3。请注意,您可以使用以下形式的循环来实现它:
int lastY = yBase - (int) (getValue(0)*graphHeight / maxY * yScale);
for (int i = 1; i < 360; i++) {
x = xBase + i;
y = yBase - (int) (getValue(i)*graphHeight / maxY * yScale);
g.drawLine(x-1, lastY, x-1, (y+lastY)/2);
g.drawLine(x, (y+lastY)/2, x, y);
}
如果一个像素的重叠让您感到困扰,您可以让它更复杂一点,例如第二行从 +/- 1 像素开始(取决于函数是增加还是减少)。
或者,您可以通过使用 for 循环手动绘制直线来实现数字 3,基本上编写 Bresenham 直线算法的特例版本。
这是我之前问题的扩展post在这里 --
我已经根据 post 中提供的答案实施了 Java 程序,这是我的程序:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class DisplacementFunctionNew extends JFrame {
public DisplacementFunctionNew() {
setLayout(new BorderLayout());
add(new CosGraph(), BorderLayout.CENTER);
}
public static void main(String[] args) {
DisplacementFunctionNew frame = new DisplacementFunctionNew();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(6000, 6000);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setTitle("SineWave");
}
class CosGraph extends JPanel {
public void paintComponent(Graphics g) {
int graphHeight = 5; // Declared this to set the height of graph based on the value given here.
super.paintComponent(g);
int xBase = 100;
int top = 100;
int yScale = 100;
int xAxis = 360;
int yBase = top + yScale;
g.drawLine(xBase, top, xBase, top + 2 * yScale);
g.drawLine(xBase, yBase, xBase + xAxis, yBase);
g.setColor(Color.red);
double maxY = 0;
for (int i = 0; i < 360; i++) {
maxY = Math.max(maxY, Math.abs(getValue(i)));
}
int x, y;
for (int i = 0; i < 360; i++) {
x = xBase + i;
y = yBase - (int) (getValue(i)*graphHeight / maxY * yScale);
g.drawLine(x, y, x, y);
}
}
private double getValue(int theta) {
int beta = 45;
double b = (theta / (double) beta);
double angle = 2 * Math.PI * (b);
double c = Math.cos(angle);
double s = (b - c);
return s;
}
}
}
现在在这个程序中我想要一个名为 graphHeight
的变量来帮助增加图形的高度。如果我将变量的值指定为 1
那么我可以看到这样的输出:
现在,如果我尝试将高度增加到 5
,那么我会得到图形,但它显示的不是平滑的或连续的曲线,我得到的输出如下:
有人可以帮助我如何获得平滑连续曲线的输出吗?
您使用 graphHeight
定义下一个要绘制的点的 y g.drawLine(x, y, x, y);
。绘制点之间的距离将与 graphHeight
变量有关
您正在使用点绘制曲线。您在 x 轴上的每个位置放置一个点——这样做很有意义。
当图很小的时候,看起来还不错,因为这些点的y间隔比较小。但是,随着图形大小的增加,此缺陷变得更加明显。
这里的解决方法是用线条填充垂直的space。您有几个选项可以准确实施此操作:
- 从 [
x(i), y(i)]
到[x(i+1),y(i+1)]
画一条线 -- 这很简单,但看起来可能不是您想要的样子。 - 从 [
x(i), y(i)]
到[x(i),y(i+1)]
画一条线 -- 这仍然很简单,但它不会很正确:你继续向上,这样你就可以成为一个完整的人像素关闭。 - 从 [
x(i), y(i)]
到[x(i),(y(i)+y(i+1))/2]
画一条线,然后从 [x(i+1), (y(i)+y(i+1))/2]
到[x(i+1),y(i+1)]
画一条线——这就是 1 应该做的(忽略抗锯齿) ), 并且将是您可能的选项中最正确的。
我建议数字 3。请注意,您可以使用以下形式的循环来实现它:
int lastY = yBase - (int) (getValue(0)*graphHeight / maxY * yScale);
for (int i = 1; i < 360; i++) {
x = xBase + i;
y = yBase - (int) (getValue(i)*graphHeight / maxY * yScale);
g.drawLine(x-1, lastY, x-1, (y+lastY)/2);
g.drawLine(x, (y+lastY)/2, x, y);
}
如果一个像素的重叠让您感到困扰,您可以让它更复杂一点,例如第二行从 +/- 1 像素开始(取决于函数是增加还是减少)。
或者,您可以通过使用 for 循环手动绘制直线来实现数字 3,基本上编写 Bresenham 直线算法的特例版本。