信号与系统课程设计:频分复用系统设计

这是信号与系统的实验报告。我信号与系统总共就扣了几分,也不知道是期末扣的,还是实验扣的。即使全是实验扣的,这实验也算做的挺好的。于是把报告发出来给大家参考。 这是大作业,频分复用系统设计

实验目的

本次实验尝试设计一种频分复用系统,接收三个带限信号,通过选取不同的调制频率\(\omega_c\),将所需传输的信号的频谱搬移到不同频段,在同一物理信道中传输多路信号。频分复用的原理框图如下:

img

实验过程

读取信号

输入信号以列表的方式给出,表的形式如下:

\(t\) \(f_1(t)\) \(f_2(t)\) \(f_3(t)\)
-10 -0.0498 0.0032 0.0031
-9.9 -0.0424 0.0023 0.0032
-9.8 -0.0344 0.0015 0.0031
-9.7 -0.0258 0.0008 0.003
-9.6 -0.0167 0.0004 0.0028
-9.5 -0.0073 0.0001 0.0025
9.8 -0.0344 0.0015 0.0031
9.9 -0.0424 0.0023 0.0032

读取数据相关的程序如下:

1
2
3
4
5
6
7
8
9
10
int cnt = 0;
double T[MAXN], f1[MAXN], f2[MAXN], f3[MAXN];
tf tf_f1[MAXN], tf_f2[MAXN], tf_f3[MAXN];
while (scanf("%lf%lf%lf%lf", &T[cnt], &f1[cnt], &f2[cnt], &f3[cnt]) != EOF) {
tf_f1[cnt] = (tf) {T[cnt], f1[cnt]};
tf_f2[cnt] = (tf) {T[cnt], f2[cnt]};
tf_f3[cnt] = (tf) {T[cnt], f3[cnt]};
++cnt;
}
int length = cnt;

其中tf结构体是为运算方便定义的结构,其中有两个double型量,即tf,用来存储时间-信号表。

原始信号的波形如下:

image-20220616164757519

获取原始信号的频域图像,分析频域特征

对三个原始信号作傅里叶变换,并绘制频域图像:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
double W[MAXN], F1[MAXN], F2[MAXN], F3[MAXN];
cnt = 0;
for (double w = -3.0; w <= 3.0; w += 0.01) {
W[cnt] = w;
F1[cnt] = fourierTransform(w, tf_f1, length);
F2[cnt] = fourierTransform(w, tf_f2, length);
F3[cnt] = fourierTransform(w, tf_f3, length);
++cnt;
}
Graph inputWSignal(WIDTH, HIGHT, 0.0, 0.0, 8, 8, 1, 1, line_blue, grid, background, axis, "inputW.ppm");
inputWSignal.drawXY(W, F1, cnt, line_blue);
inputWSignal.drawXY(W, F2, cnt, line_green);
inputWSignal.drawXY(W, F3, cnt, line_red);
inputWSignal.draw();

其中fourierTransform函数定义如下:

1
2
3
4
5
6
7
8
double fourierTransform(double w, tf f[], int length) {
double ans = 0.0;
double step = f[1].t - f[0].t;
for (int i = 0; i < length; ++i) {
ans = ans + f[i].f * cos(w * f[i].t) * step;
}
return ans;
}

绘制出的频域波形如下:

image-20220616164823488

可以看出,输入的三个信号都是带限信号。有: \[ \omega_{m1}=1\\ \omega_{m2}=2\\ \omega_{m3}=\frac \pi 2 \] 因此,我们可以使用频分复用的方法把这三个信号合在一个信道中传输。

频域搬移和信道组合

由公式: \[ g(t)=\sum_{i=1}^3 f_i(t)\cos(\omega_it) \] 我们可以将这三个信号的频域进行搬移,并组合在一个信道中进行传输。其中\(\cos(\omega_it)\)就起到了幅度调制,频域搬移的作用。这是因为: \[ \begin{aligned} \mathscr{F}[f(t)\cos(\omega_0 t)]&=\frac{1}{2\pi}\mathscr{F}[f(t)]\bigotimes\mathscr{F}[\cos(\omega_0 t)]\\ &=\frac{1}{2\pi}F(\omega)\bigotimes\pi[\delta(\omega+\omega_0)+\delta(\omega-\omega_0)]\\ &=\frac 12[F(\omega+\omega_0)-F(\omega-\omega_0)] \end{aligned} \] 在选择载波频率时,考虑到原始采样频率为\(f=10\text{Hz}\),所以载波频率分别选择 \[ \omega_1=5,\omega_2=12.5,\omega_3=20 \] 这部分的代码是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
double omega1 = 5.0, omega2 = 12.5, omega3 = 20.0;
double g[MAXN];
cnt = 0;
tf tf_g[MAXN];
int g_length = 0;
for (double t = -10.0; t <= 10.0; t += 0.1) {
g[cnt] = (f1[cnt] * cos(omega1 * t) + f2[cnt] * cos(omega2 * t) + f3[cnt] * cos(omega3 * t));
tf_g[cnt] = (tf) {t, g[cnt]};
++cnt;
}
g_length = cnt;
Graph GT(WIDTH, HIGHT, 0.0, 0.0, 22, 3, 1, 1, line_blue, grid, background, axis, "GT.ppm");
GT.drawXY(T, g, cnt, line_blue);
double G[MAXN], w2[MAXN];
cnt = 0;
for (double w = -40; w <= 40; w += 0.1) {
w2[cnt] = w;
G[cnt] = fourierTransform(w, tf_g, g_length);
++cnt;
}
Graph GW(WIDTH, HIGHT, 0.0, 0.0, 85, 5, 5, 1, line_blue, grid, background, axis, "GW.ppm");
GW.drawXY(w2, G, cnt, line_blue);

同时分别画出了\(g(t)\)的时域、频域图像,如下:

时域图像:

image-20220616172004693

频域图像:

image-20220616171953072

可见:已经实现了频域搬移。

使用带通滤波器接受信号

在解调过程中,使用带通滤波器接受信号。对于三个信号,分别采用中心频率为\(\omega_i\),通过频带宽度为\(\omega_{mi}\)的带通滤波器。信号\(g(t)\)经过带通滤波器以后,被分为了三路信号。对这三路信号,每一路再乘以\(\cos(\omega_i t)\),就把频带移动到了中间。如下图所示:

image-20220616172628586

我们再对这三个信号过一个低通滤波器,就能恢复出原来的信号了。

这部分的代码如下:

  1. 通过带通滤波器分开三路信号:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    double G1[MAXN], G2[MAXN], G3[MAXN];
    wF wF_g1[MAXN], wF_g2[MAXN], wF_g3[MAXN];
    cnt = 0;
    memset(G1, 0, sizeof(G1));
    memset(G2, 0, sizeof(G2));
    memset(G3, 0, sizeof(G3));
    for (double w = -40; w <= 40; w += 0.1) {
    G1[cnt] = G[cnt] * bandPassFilter(5.0, 5.0, w);
    G2[cnt] = G[cnt] * bandPassFilter(12.5, 5.0, w);
    G3[cnt] = G[cnt] * bandPassFilter(20.0, PI, w);
    wF_g1[cnt] = (wF) {w, G1[cnt]};
    wF_g2[cnt] = (wF) {w, G2[cnt]};
    wF_g3[cnt] = (wF) {w, G3[cnt]};
    ++cnt;
    }
  2. 分别再乘以\(\cos(\omega_i t)\)再次搬移频域

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    int G1length = cnt;
    cnt = 0;
    double fG1[MAXN], fG2[MAXN], fG3[MAXN];
    tf tf_fG1[MAXN], tf_fG2[MAXN], tf_fG3[MAXN];
    for (double t = -10.0; t <= 10.0; t += 0.1) {
    fG1[cnt] = fourierInvTransform(t, wF_g1, G1length);
    fG2[cnt] = fourierInvTransform(t, wF_g2, G1length);
    fG3[cnt] = fourierInvTransform(t, wF_g3, G1length);
    fG1[cnt] *= cos(omega1 * t);
    fG2[cnt] *= cos(omega2 * t);
    fG3[cnt] *= cos(omega3 * t);
    tf_fG1[cnt] = (tf) {t, fG1[cnt]};
    tf_fG2[cnt] = (tf) {t, fG2[cnt]};
    tf_fG3[cnt] = (tf) {t, fG3[cnt]};
    ++cnt;
    }
  3. 通过低通滤波器,恢复原始信号,并绘制出输出信号

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    double GfG1[MAXN], GfG2[MAXN], GfG3[MAXN];
    wF wf_gfg1[MAXN], wf_gfg2[MAXN], wf_gfg3[MAXN];
    cnt = 0;
    for (double w = -40; w <= 40; w += 0.1) {
    GfG1[cnt] = fourierTransform(w, tf_fG1, g_length);
    GfG2[cnt] = fourierTransform(w, tf_fG2, g_length);
    GfG3[cnt] = fourierTransform(w, tf_fG3, g_length);
    GfG1[cnt] *= bandPassFilter(0, 5, w)*2.0;
    GfG2[cnt] *= bandPassFilter(0, 5, w)*2.0;
    GfG3[cnt] *= bandPassFilter(0, 5, w)*2.0;
    wf_gfg1[cnt] = (wF) {w, GfG1[cnt]};
    wf_gfg2[cnt] = (wF) {w, GfG2[cnt]};
    wf_gfg3[cnt] = (wF) {w, GfG3[cnt]};
    ++cnt;
    }
    length = cnt;
    double finalf1[MAXN], finalf2[MAXN], finalf3[MAXN];
    cnt = 0;
    for (double t = -10; t <= 10; t += 0.1) {
    finalf1[cnt] = fourierInvTransform(t, wf_gfg1, length);
    finalf2[cnt] = fourierInvTransform(t, wf_gfg2, length);
    finalf3[cnt] = fourierInvTransform(t, wf_gfg3, length);
    ++cnt;
    }
    Graph outputSignal(WIDTH, HIGHT, 0.0, 0.0, 22, 3, 1, 1, line_blue, grid, background, axis, "output.ppm");
    outputSignal.drawXY(T, finalf1, cnt, line_blue);
    outputSignal.drawXY(T, finalf2, cnt, line_green);
    outputSignal.drawXY(T, finalf3, cnt, line_red);
    return 0;

输出信号的波形如下:

image-20220616173101518

可以看出,本次实验较好地完成了频分复用信号传输的任务。

计算三个信号的均方误差,有:

1
2
3
MSE1 = 0.000048221
MSE2 = 0.000000652
MSE3 = 0.000000173

可以看出,这个系统的效果还是比较理想。

实验心得体会

本次实验我综合运用了《信号与系统》课程的相关知识,如奈奎斯特采样定理、傅里叶变换的相关内容,完成了综合信号传输系统的设计,对我的学习非常的有帮助。

附录

本次实验完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#include <set>
#include <queue>
#include <algorithm>
#include <map>
#include "arrayToPPM2.hpp"

#define LL long long
#define MAXN 3000
#define WIDTH 1920
#define HIGHT 1080
#define forvec(TYPE,NAME,IT) for(vector<TYPE>::iterator IT=NAME.begin();IT!=NAME.end();++IT)
#define forset(TYPE,NAME,IT) for(set<TYPE>::iterator IT=NAME.begin();IT!=NAME.end();++IT)

const double EPS = 1e-11;
const double PI = acos(-1.0);
typedef double (*fun_p)(double);

using namespace std;

typedef struct {
double t, f;
} tf;

typedef struct wF {
double w, F;
} wF;

double fourierInvTransform(double t, wF f[], int length) {
double ans = 0.0;
double step = f[1].w - f[0].w;
for (int i = 0; i < length; ++i) {
ans = ans + f[i].F * cos(t * f[i].w) * step;
}
return ans / (2.0 * PI);
}

double fourierTransform(double w, tf f[], int length) {
double ans = 0.0;
double step = f[1].t - f[0].t;
for (int i = 0; i < length; ++i) {
ans = ans + f[i].f * cos(w * f[i].t) * step;
}
return ans;
}

double bandPassFilter(double center, double band, double w) {
if (fabs(w - center) < (band / 2.0) || fabs(w + center) < (band / 2.0))
return 1.0;
else
return 0.0;
//return (fabs(w - center) < (band / 2.0)) ? 1.0 : 0.0;
}

int main() {
freopen("inputSignal.txt", "r", stdin);
PPMdata background, axis, grid, line_blue, line_green, line_red;
background = makePPMdata(255, 255, 251);
axis = makePPMdata(28, 28, 28);
grid = makePPMdata(189, 192, 186);
line_blue = makePPMdata(0, 92, 175);
line_green = makePPMdata(66, 96, 45);
line_red = makePPMdata(193, 50, 142);
int cnt = 0;
double T[MAXN], f1[MAXN], f2[MAXN], f3[MAXN];
tf tf_f1[MAXN], tf_f2[MAXN], tf_f3[MAXN];
while (scanf("%lf%lf%lf%lf", &T[cnt], &f1[cnt], &f2[cnt], &f3[cnt]) != EOF) {
tf_f1[cnt] = (tf) {T[cnt], f1[cnt]};
tf_f2[cnt] = (tf) {T[cnt], f2[cnt]};
tf_f3[cnt] = (tf) {T[cnt], f3[cnt]};
++cnt;
}
int length = cnt;
Graph inputSignal(WIDTH, HIGHT, 0.0, 0.0, 22, 3, 1, 1, line_blue, grid, background, axis, "input.ppm");
inputSignal.drawXY(T, f1, cnt, line_blue);
inputSignal.drawXY(T, f2, cnt, line_green);
inputSignal.drawXY(T, f3, cnt, line_red);
inputSignal.draw();

double W[MAXN], F1[MAXN], F2[MAXN], F3[MAXN];
cnt = 0;
for (double w = -3.0; w <= 3.0; w += 0.01) {
W[cnt] = w;
F1[cnt] = fourierTransform(w, tf_f1, length);
F2[cnt] = fourierTransform(w, tf_f2, length);
F3[cnt] = fourierTransform(w, tf_f3, length);
++cnt;
}
Graph inputWSignal(WIDTH, HIGHT, 0.0, 0.0, 8, 8, 1, 1, line_blue, grid, background, axis, "inputW.ppm");
inputWSignal.drawXY(W, F1, cnt, line_blue);
inputWSignal.drawXY(W, F2, cnt, line_green);
inputWSignal.drawXY(W, F3, cnt, line_red);
inputWSignal.draw();

double omega1 = 5.0, omega2 = 12.5, omega3 = 20.0;
double g[MAXN];
cnt = 0;
tf tf_g[MAXN];
int g_length = 0;
for (double t = -10.0; t <= 10.0; t += 0.1) {
g[cnt] = (f1[cnt] * cos(omega1 * t) + f2[cnt] * cos(omega2 * t) + f3[cnt] * cos(omega3 * t));
tf_g[cnt] = (tf) {t, g[cnt]};
++cnt;
}
g_length = cnt;
Graph GT(WIDTH, HIGHT, 0.0, 0.0, 22, 3, 1, 1, line_blue, grid, background, axis, "GT.ppm");
GT.drawXY(T, g, cnt, line_blue);
double G[MAXN], w2[MAXN];
cnt = 0;
for (double w = -40; w <= 40; w += 0.1) {
w2[cnt] = w;
G[cnt] = fourierTransform(w, tf_g, g_length);
++cnt;
}
Graph GW(WIDTH, HIGHT, 0.0, 0.0, 85, 5, 5, 1, line_blue, grid, background, axis, "GW.ppm");
GW.drawXY(w2, G, cnt, line_blue);

double G1[MAXN], G2[MAXN], G3[MAXN];
wF wF_g1[MAXN], wF_g2[MAXN], wF_g3[MAXN];
cnt = 0;
memset(G1, 0, sizeof(G1));
memset(G2, 0, sizeof(G2));
memset(G3, 0, sizeof(G3));
for (double w = -40; w <= 40; w += 0.1) {
G1[cnt] = G[cnt] * bandPassFilter(5.0, 5.0, w);
G2[cnt] = G[cnt] * bandPassFilter(12.5, 5.0, w);
G3[cnt] = G[cnt] * bandPassFilter(20.0, PI, w);
wF_g1[cnt] = (wF) {w, G1[cnt]};
wF_g2[cnt] = (wF) {w, G2[cnt]};
wF_g3[cnt] = (wF) {w, G3[cnt]};
++cnt;
}
int G1length = cnt;
Graph Gerr(WIDTH, HIGHT, 0.0, 0.0, 85, 5, 5, 1, line_blue, grid, background, axis, "Gerr.ppm");
cnt = 0;
double fG1[MAXN], fG2[MAXN], fG3[MAXN];
tf tf_fG1[MAXN], tf_fG2[MAXN], tf_fG3[MAXN];
for (double t = -10.0; t <= 10.0; t += 0.1) {
fG1[cnt] = fourierInvTransform(t, wF_g1, G1length);
fG2[cnt] = fourierInvTransform(t, wF_g2, G1length);
fG3[cnt] = fourierInvTransform(t, wF_g3, G1length);
fG1[cnt] *= cos(omega1 * t);
fG2[cnt] *= cos(omega2 * t);
fG3[cnt] *= cos(omega3 * t);
tf_fG1[cnt] = (tf) {t, fG1[cnt]};
tf_fG2[cnt] = (tf) {t, fG2[cnt]};
tf_fG3[cnt] = (tf) {t, fG3[cnt]};
++cnt;
}
double GfG1[MAXN], GfG2[MAXN], GfG3[MAXN];
wF wf_gfg1[MAXN], wf_gfg2[MAXN], wf_gfg3[MAXN];
cnt = 0;
for (double w = -40; w <= 40; w += 0.1) {
GfG1[cnt] = fourierTransform(w, tf_fG1, g_length);
GfG2[cnt] = fourierTransform(w, tf_fG2, g_length);
GfG3[cnt] = fourierTransform(w, tf_fG3, g_length);
GfG1[cnt] *= bandPassFilter(0, 5, w)*2.0;
GfG2[cnt] *= bandPassFilter(0, 5, w)*2.0;
GfG3[cnt] *= bandPassFilter(0, 5, w)*2.0;
wf_gfg1[cnt] = (wF) {w, GfG1[cnt]};
wf_gfg2[cnt] = (wF) {w, GfG2[cnt]};
wf_gfg3[cnt] = (wF) {w, GfG3[cnt]};
++cnt;
}
length = cnt;
double finalf1[MAXN], finalf2[MAXN], finalf3[MAXN];
double MSE[4];
cnt = 0;
for (double t = -10; t <= 10; t += 0.1) {
finalf1[cnt] = fourierInvTransform(t, wf_gfg1, length);
finalf2[cnt] = fourierInvTransform(t, wf_gfg2, length);
finalf3[cnt] = fourierInvTransform(t, wf_gfg3, length);
MSE[1]+=(finalf1[cnt]-f1[cnt])*(finalf1[cnt]-f1[cnt]);
MSE[2]+=(finalf2[cnt]-f2[cnt])*(finalf2[cnt]-f2[cnt]);
MSE[3]+=(finalf3[cnt]-f3[cnt])*(finalf3[cnt]-f3[cnt]);
++cnt;
}
for(int i=1;i<=3;++i) MSE[i]/=(cnt*1.0);
for(int i=1;i<=3;++i) printf("MSE%d = %.9lf\n",i,MSE[i]);
Graph outputSignal(WIDTH, HIGHT, 0.0, 0.0, 22, 3, 1, 1, line_blue, grid, background, axis, "output.ppm");
outputSignal.drawXY(T, finalf1, cnt, line_blue);
outputSignal.drawXY(T, finalf2, cnt, line_green);
outputSignal.drawXY(T, finalf3, cnt, line_red);
return 0;
}

"arrayToPPM2.hpp"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
#define INF 999999999
#include "cstdio"
#include "cstdlib"
#include "cstring"
#include "cmath"

#define linerFunc(x1,y1,x2,y2,x) ((x-x1)*(y2-y1)/(x2-x1)+y1)
#define linerFuncY(x1,y1,x2,y2,y) ((y-y1)*(x2-x1)/(y2-y1)+x1)

typedef double (*fun_P) (double);

typedef struct {
int r, g, b;
} PPMdata;

template<class T>
void swap(T &a, T &b) {
T c(a);
a = b;
b = c;
}

PPMdata makePPMdata(int r, int g, int b) {
PPMdata ans;
ans.r = r, ans.g = g, ans.b = b;
return ans;
}

class Graph {
private:
PPMdata **matrix;
int width;
int height;
double centerX;
double centerY;
double rangeX;
double rangeY;
double gridX;
double gridY;
PPMdata line, grid, bgc, axis;
char *fileName;

double stepX, stepY;
bool drawed;
public:
Graph(int idth,
int eight,
double enterX,
double enterY,
double angeX,
double angeY,
double ridX,
double ridY,
PPMdata ine,
PPMdata rid,
PPMdata ack,
PPMdata xis,
char *fName);
~Graph();
bool drawLine(double x1, double x2, double y1, double y2,PPMdata color);
void drawPoint(double x, double y, int size,PPMdata color);
void drawPos(int u, int v, PPMdata color);
bool drawXY(double *x, double *y, int arrayLen,PPMdata color);
int num2MatPos(double num, bool flag);
void draw();
};

Graph::Graph(int idth,
int eight,
double enterX,
double enterY,
double angeX,
double angeY,
double ridX,
double ridY,
PPMdata ine,
PPMdata rid,
PPMdata ack,
PPMdata xis,
char *fName) {
width = idth;
height = eight;
centerX = enterX;
centerY = enterY;
rangeX = angeX;
rangeY = angeY;
gridX = ridX;
gridY = ridY;
line = ine;
grid = rid;
bgc = ack;
axis = xis;
fileName = fName;
drawed = 0;

if (height % 2) ++height;
if (width % 2) ++width;
matrix = (PPMdata **) malloc(sizeof(PPMdata *) * height);
for (int i = 0; i < height; i++) {
matrix[i] = (PPMdata *) calloc(width, sizeof(PPMdata));
}

stepX = rangeX / (width * 1.0);
stepY = rangeY / (height * 1.0);

for (int i = 0; i < height; ++i) {
for (int j = 0; j < width; ++j) {
matrix[i][j] = bgc;
}
}
for (int i = 0; centerX + i * gridX <= centerX + rangeX / 2; ++i) {
for (int j = 0; j < height; ++j) {
drawPos(num2MatPos(centerX + i * gridX, 1), j, grid);
drawPos(num2MatPos(centerX - i * gridX, 1), j, grid);
}
}
for (int i = 0; centerY + i * gridY <= centerY + rangeY / 2; ++i) {
for (int j = 0; j < width; ++j) {
drawPos(j, num2MatPos(centerY + i * gridY, 0), grid);
drawPos(j, num2MatPos(centerY - i * gridY, 0), grid);
}
}
for (int i = 0; i < width; ++i) {
drawPos(i, height / 2, axis);
}

for (int i = 0; i < height; ++i) {
drawPos(width / 2, i, axis);
}

}

Graph::~Graph() {
if (drawed == 0) {
draw();
}
fprintf(stderr, "Object has been deleted!\n");
}

void Graph::draw() {
if (drawed) {
fprintf(stderr, "This Graph has been drawed in %s.\n", fileName);
}
freopen(fileName, "w", stdout);
printf("P3\n");
printf("%d %d\n", width, height);
printf("255\n");
for (int i = height - 1; i >= 0 ; --i) {
for (int j = 0; j < width; ++j) {
printf("%d %d %d", matrix[i][j].r, matrix[i][j].g, matrix[i][j].b);
printf(" ");
}
printf("\n");
}
fclose(stdout);
freopen("CON", "w", stdout);
drawed = 1;
}

int Graph::num2MatPos(double num, bool flag) {
//flag=1 x else y
if (flag) {
return (int)(width / 2 + (num - centerX) / rangeX * width);
} else {
return (int)(height / 2 + (num - centerY) / rangeY * height);
}
}

void Graph::drawPoint(double x, double y, int size,PPMdata color) {
int u = num2MatPos(x, 1);
int v = num2MatPos(y, 0);
for (int i = -1 * size; i <= size; ++i) {
for (int j = -1 * size; j <= size; ++j) {
int U = u + i, V = v + j;
if (U >= width || U < 0 || V >= height || V < 0) continue;
else matrix[V][U] = color;
}
}
}

void Graph::drawPos(int u, int v, PPMdata color) {
if (u >= width || u < 0 || v >= height || v < 0) {
return;
} else matrix[v][u] = color;
}

bool Graph::drawLine(double x1, double y1, double x2, double y2,PPMdata color) {
int u1, u2, v1, v2;
u1 = num2MatPos(x1, 1);
u2 = num2MatPos(x2, 1);
v1 = num2MatPos(y1, 0);
v2 = num2MatPos(y2, 0);
if (u1 >= width || u1 < 0 || u2 >= width || u2 < 0 || v1 >= height || v1 < 0 || v2 >= height || v2 < 0) {
fprintf(stderr, "drawLineError:out of range.\n");
return 0;
}
double k = INF;
if (u2 != u1)
k = (v2 * 1.0 - v1 * 1.0) / (u2 * 1.0 - u1 * 1.0);
if (fabs(k) >= 2.0) {
if (y1 > y2) {
swap(x1, x2);
swap(y1, y2);
}
k=(x2-x1)/(y2-y1);
double x11=x1;
for (double y = y1; y <= y2; y += stepY) {
drawPoint(x11, y, 1,color);
x11+=stepY*k;
}
} else {
if(x1>x2){
swap(x1,x2);
swap(y1,y2);
}
k=(y2-y1)/(x2-x1);
double y11=y1;
for (double x = x1; x <= x2; x += stepX) {
drawPoint(x, y11, 1,color);
y11+=stepX*k;
}
}
return 1;
}

bool Graph::drawXY(double *x, double *y_save, int arrayLen,PPMdata color) {

double *y = (double*)malloc(sizeof(double) * (arrayLen + 2));
for (int i = 0; i < arrayLen; ++i)
y[i] = y_save[i];
for (int i = 0; i < arrayLen; ++i) {
if (x[i] < x[i - 1] && i >= 1) {
fprintf(stderr, "drawXYError:X is not increasing.\n");
return 0;
}
if (!(x[i] > centerX - (rangeX / 2.0) && x[i] < centerX + (rangeX / 2.0))) {
fprintf(stderr, "drawXYError:X out of range.\n");
return 0;
}
if (!(y[i] > centerY - (rangeY / 2.0) && y[i] < centerY + (rangeY / 2.0))) {
if (y[i] > centerY + (rangeY / 2.0)) y[i] = centerY + (rangeY / 2.0);
if (y[i] < centerY - (rangeY / 2.0)) y[i] = centerY - (rangeY / 2.0);
}
}
for (int i = 1; i < arrayLen; ++i) {
if (i >= arrayLen) break;
drawLine(x[i - 1], y[i - 1], x[i], y[i],color);
}
free(y);
return 1;
}

信号与系统课程设计:频分复用系统设计
https://suzumiyaakizuki.github.io/2022/06/16/信号大作业/
作者
SuzumiyaAkizuki
发布于
2022年6月16日
许可协议