📄 form1.java
字号:
import com.ms.wfc.app.*;
import com.ms.wfc.core.*;
import com.ms.wfc.ui.*;
import com.ms.wfc.html.*;
import com.ms.wfc.io.*;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Toolkit;
public class Form1 extends Form
{
public Form1()
{
super();
initForm();
new iirtwo_explain().showDialog(this);
}
public void dispose()
{
super.dispose();
components.dispose();
}
//定义变量//画图显示类:public int keepleft=50,keepright=50,keepup=50,keepdown=50;//绘图区位置设定public float steppelix=2;//绘图时每两个点之间的象素距离(均匀绘图,引用时转为整数)
public double ysize=100;//绘图的纵向幅度public Color backcolor=Color.BLACK;//默认背景颜色;public Color zbcolor=Color.WHITE;//默认坐标颜色;public Color drawcolor=Color.GREEN;//默认绘图颜色;public Color textcolor=Color.CYAN;//默认字符颜色;//控制变量类:public boolean Xinputed=false,Yinputed=false;//输入序列X【】以及滤波器特性是否已经被定义;public boolean solved=false;//在输入序列已经定义的情况下,是否已经经过处理;public boolean isfft=true;//是否是用快速算法计算
public int displaywhichdata=-1;
//控制显示内容:0时:输入x【】;1:输入h【】;2:输出序列y【】;3:幅频特性;4:相频特性;5:极点位置;//处理数据对象类:
public int MaxLength=4096;//最多可以输入的数据点数public int totallength,current=0;//数组总长度,当前屏幕起始点public int displaynum;//一屏幕可以显示的点数public int N;//基2_fft的N值public int bitlength;
public double x[],y[];//输入序列,单位取样响应;输出序列;(没有扩充成2的N次方,记录原始数据);注意:从1开始定义public complex X[],Y[];//待处理序列;注意:从1开始定义
public int rank,rankMAX=20;//数字滤波器的阶数,以及允许的最大阶数
public double Qc;//数字滤波器的截至频率
public double omiga;
public complex P[],A[];//(从序号0开始)//记录极点位置;记录系统函数Ha(S)部分分式形式的分解系数;
public complex Br[],Ak[];//标准差分方程的系数参数(从0开始定义)
public double K0;//归一化常数
iirfilterset myframe=new iirfilterset();
public double complexabs(complex x){
return Math.sqrt(x.Re*x.Re+x.Im*x.Im);
}
public complex complexadd(complex x,complex y){
complex a=new complex();
a.Re=x.Re+y.Re;
a.Im=x.Im+y.Im;
return a;
}
public complex complexsub(complex x,complex y){
complex a=new complex();
a.Re=x.Re-y.Re;
a.Im=x.Im-y.Im;
return a;
}
public complex complexmult(complex x,complex y){
complex a=new complex();
a.Re=x.Re*y.Re-x.Im*y.Im;
a.Im=x.Im*y.Re+x.Re*y.Im;
return a;
}
public complex complexdiv(complex x,complex y){
complex a=new complex();
complex b=new complex();
b.Re=y.Re;b.Im=-y.Im;
a=complexmult(x,b);
a.Re/=complexabs(y)*complexabs(y);
a.Im/=complexabs(y)*complexabs(y);
return a;
}
public double arch(double x){
return Math.log(x+Math.sqrt(x*x-1))/Math.log(Math.E);
}
public double arsh(double x){ return Math.log(x+Math.sqrt(x*x+1))/Math.log(Math.E);
}public double sh(double x){ return Math.exp(x)/2-Math.exp(-x)/2;
}public double ch(double x){ return Math.exp(x)/2+Math.exp(-x)/2;
}
public int getN(int processlength){//获得基2_fft的N值
for(int i=1;;i++){
if((int)Math.pow(2,i)==processlength){bitlength=i;break;}
if((int)Math.pow(2,i)<processlength&&(int)Math.pow(2,i+1)>processlength){
bitlength=i+1;break;}
}//for
return (int)Math.pow(2,bitlength);
}public void fft(){//fft核心算法
//注:本程序数组从1开始定义,运行此程序之前将要处理的数据存入复数数组X【】;
int NV2,NM1,K,L;
int I,J,IP,LE,LE1;
double tr,ti,ur,ui,wr,wi,mid;
complex T=new complex();
//重新排序
NV2=N/2;NM1=N-1;
J=1;I=1;
do{
if(I<J){
T.Re=X[J].Re;T.Im=X[J].Im;//T=X[J];
X[J].Re=X[I].Re;X[J].Im=X[I].Im;//X[J]=X[I];
X[I].Re=T.Re;X[I].Im=T.Im;//X[I]=T;
}
K=NV2;
while(K<J){
J-=K;K=K/2;}
J+=K;I+=1;
}while(I<=NM1);
//重新排序结束
//fft核心算法开始
L=1;
do{
LE=(int)Math.pow(2,L);
LE1=LE/2;
ur=1;ui=0;
wr=Math.cos(Math.PI/(double)(LE1));wi=-Math.sin(Math.PI/(double)(LE1));
J=1;
do{
I=J;
do{
IP=I+LE1;
tr=X[IP].Re*ur-X[IP].Im*ui;
ti=X[IP].Re*ui+X[IP].Im*ur;//T=X[IP]*U;
X[IP].Re=X[I].Re-tr;
X[IP].Im=X[I].Im-ti;//X[IP]=X[I]-T;
X[I].Re+=tr;
X[I].Im+=ti;//X[I]=X[I]+T;
I=I+LE;
}while(I<=N);
mid=ur;
ur=ur*wr-ui*wi;
ui=mid*wi+ui*wr;//U=U*W;
J=J+1;
}while(J<=LE1);
L=L+1;
}while(L<=bitlength);
//fft核心算法结束
}
public void panel_paint(Object source, PaintEvent e)//这里用的坐标系是panel的坐标,即panel的左上角为(0,0)
{
//一屏可以显示的点数
if(this.displaywhichdata==0||this.displaywhichdata==2||this.displaywhichdata==6||this.displaywhichdata==7){
this.displaynum=(int)((this.panel.getWidth()-1)/this.steppelix);
if(totallength<=displaynum){
scroll.setEnabled(false);this.current=0; this.lastlabel.setText(""); }
else{
scroll.setEnabled(true);
scroll.setMaximum(totallength-displaynum);
this.lastlabel.setText(String.valueOf(this.current+this.displaynum));
}
}
else this.scroll.setEnabled(false);
//设置背景色
panel.setBackColor(backcolor);
if(this.displaywhichdata==0){//显示输入序列x【】
this.currentlabel.setText(String.valueOf(this.current+1));
//绘制坐标
e.graphics.setPen(new Pen(zbcolor,PenStyle.SOLID,3));
e.graphics.drawLine(0,panel.getHeight()/2,panel.getWidth(),panel.getHeight()/2);
//绘制数据
e.graphics.setPen(new Pen(drawcolor,PenStyle.SOLID,1));
for(int i=0;i<=((this.totallength<displaynum)?(this.totallength-1):(displaynum-1));i++){
e.graphics.drawLine((int)(steppelix*i),panel.getHeight()/2,(int)(steppelix*i),panel.getHeight()/2-(int)(this.ysize*x[i+current+1]));
}
}//显示输入序列x【】
if(this.displaywhichdata==2){//显示输出序列y【】
this.currentlabel.setText(String.valueOf(this.current+1));
//绘制坐标
e.graphics.setPen(new Pen(zbcolor,PenStyle.SOLID,3));
e.graphics.drawLine(0,panel.getHeight()/2,panel.getWidth(),panel.getHeight()/2);
//绘制数据
e.graphics.setPen(new Pen(drawcolor,PenStyle.SOLID,1));
for(int i=0;i<=((this.totallength<displaynum)?(this.totallength-1):(displaynum-1));i++){
e.graphics.drawLine((int)(steppelix*i),panel.getHeight()/2,(int)(steppelix*i),panel.getHeight()/2-(int)(this.ysize*y[i+current]));
}
}//显示输入序列y【】
if(this.displaywhichdata==3){//显示幅频特性
this.scroll.setEnabled(false);
int x0=40;
int y0=this.panel.getHeight()-20;
int height=y0-10;
int width=this.panel.getWidth()-x0-10;
//绘制坐标
e.graphics.setPen(new Pen(zbcolor,PenStyle.SOLID,2));
for(int i=0;i<=10;i++){//横向10格纵向10格
e.graphics.drawLine(x0,y0-height*i/10,x0+width,y0-height*i/10);//横向
e.graphics.drawLine(x0+width*i/10,y0-height,x0+width*i/10,y0);//纵向
}
//绘制文字
e.graphics.setTextColor(zbcolor);
for(int i=0;i<=5;i++){//纵向写6个
e.graphics.drawString(String.valueOf(-i*20)+"dB",5,5+height*i/5);
}
e.graphics.drawString("0",x0-5,y0+5);//纵向写6个
for(int i=1;i<5;i++){
e.graphics.drawString(String.valueOf((float)(0.2*i))+"π",x0+width*i/5-10,5+y0);
}
e.graphics.drawString("π",x0+width-5,y0+5);
//画数据
e.graphics.setPen(new Pen(drawcolor,PenStyle.SOLID,2));
for(double w=0;w<=Math.PI;w+=0.01){
double xx=K0;
double nextxx=K0;
for(int i=0;i<P.length;i++){
xx/=Math.sqrt(P[i].Re*P[i].Re+(w-P[i].Im)*(w-P[i].Im));
//if(i<P.length-1){
nextxx/=Math.sqrt(P[i].Re*P[i].Re+((w+0.01)-P[i].Im)*(w+0.01-P[i].Im));
//}
}//for
e.graphics.drawLine(x0+(int)(width*w/Math.PI),10-(int)(10*Math.log(xx)*height/100),x0+(int)(width*(w+0.01)/Math.PI),10-(int)(10*Math.log(nextxx)*height/100));
}//for
double xx=K0;
for(int i=0;i<P.length;i++) xx/=Math.sqrt(P[i].Re*P[i].Re+(Qc-P[i].Im)*(Qc-P[i].Im));
//e.graphics.
//e.graphics.setPixel(x0+(int)(width*Qc/Math.PI),10-(int)(10*Math.log(xx)*height/100),Color.RED);
e.graphics.setPen(new Pen(Color.RED,PenStyle.SOLID,2));
e.graphics.drawLine(x0+(int)(width*Qc/Math.PI)-2,10-(int)(10*Math.log(xx)*height/100)-2,x0+(int)(width*Qc/Math.PI)+2,10-(int)(10*Math.log(xx)*height/100)+2);
e.graphics.drawLine(x0+(int)(width*Qc/Math.PI)-2,10-(int)(10*Math.log(xx)*height/100)+2,x0+(int)(width*Qc/Math.PI)+2,10-(int)(10*Math.log(xx)*height/100)-2);
}//显示幅频特性
if(this.displaywhichdata==4){//显示相频特性
this.scroll.setEnabled(false);
int x0=40;
int y0=this.panel.getHeight()-20;
int height=y0-10;
int width=this.panel.getWidth()-x0-10;
//绘制坐标
e.graphics.setPen(new Pen(zbcolor,PenStyle.SOLID,2));
for(int i=0;i<=10;i++){//横向10格纵向10格
e.graphics.drawLine(x0,y0-height*i/10,x0+width,y0-height*i/10);//横向
e.graphics.drawLine(x0+width*i/10,y0-height,x0+width*i/10,y0);//纵向
}
//绘制文字
e.graphics.setTextColor(zbcolor);
for(int i=0;i<=5;i++){//纵向写6个
e.graphics.drawString(String.valueOf(180-i*72)+"°",2,5+height*i/5);
}
e.graphics.drawString("0°",2,5+height/2);
e.graphics.drawString("0",x0-5,y0+5);//纵向写6个
for(int i=1;i<5;i++){
e.graphics.drawString(String.valueOf((float)(0.2*i))+"π",x0+width*i/5-10,5+y0);
}
e.graphics.drawString("π",x0+width-5,y0+5);
//画数据
e.graphics.setPen(new Pen(drawcolor,PenStyle.SOLID,2));
for(double w=0;w<=Math.PI;w+=0.01){
double xx=0;
double nextxx=0;
for(int i=0;i<P.length;i++){
xx-=Math.atan((w-P[i].Im)/(-P[i].Re));
nextxx-=Math.atan((w+0.01-P[i].Im)/(-P[i].Re));
}//for
while(xx<-Math.PI)xx+=2*Math.PI;
//if(xx>Math.PI)xx-=2*Math.PI;
while(nextxx<-Math.PI)nextxx+=2*Math.PI;
//if(nextxx>Math.PI)nextxx-=2*Math.PI;
//e.graphics.drawLine(x0+(int)(width*w/Math.PI),10+height/2-(int)(((xx<Math.PI)?(xx+2*Math.PI):(xx))*height/Math.PI),x0+(int)(width*(w+0.01)/Math.PI),10+height/2-(int)(((nextxx<Math.PI)?(nextxx+2*Math.PI):(nextxx))*height/Math.PI));
e.graphics.drawLine(x0+(int)(width*w/Math.PI),10+height/2-(int)(xx*height/Math.PI/2),x0+(int)(width*(w+0.01)/Math.PI),10+height/2-(int)(nextxx*height/Math.PI/2));
}//for
}//显示相频特性
if(this.displaywhichdata==5){//S域数字滤波器的极点位置
this.scroll.setEnabled(false);
int x0=panel.getWidth()/2;
int y0=panel.getHeight()/2;
//int r=(int)(this.panel.getHeight()/2/Qc);//半径
//绘制坐标
e.graphics.setPen(new Pen(zbcolor,PenStyle.SOLID,3));
e.graphics.drawLine(0,y0,2*x0,y0);//横轴
e.graphics.drawLine(x0,0,x0,2*y0);//纵轴
e.graphics.setTextColor(zbcolor);
e.graphics.drawString("jΩ",x0+5,5);
e.graphics.drawString("σ",2*x0-10,y0+5);
e.graphics.drawString("0",x0+5,y0+5);
//e.graphics.drawString("Ωc",x0+this.panel.getHeight()/2,y0-15);
e.graphics.drawString("滤波器阶数N="+String.valueOf(rank),300,30);
e.graphics.drawString("截止频率Ωc="+String.valueOf(Qc),300,50);
e.graphics.drawString("通带波动ε="+String.valueOf(omiga),300,70);
double alpha=1/omiga+Math.sqrt(1/omiga/omiga+1);
double a=(Math.pow(alpha,1/(double)rank)-Math.pow(alpha,-1/(double)rank))/2;
double b=(Math.pow(alpha,1/(double)rank)+Math.pow(alpha,-1/(double)rank))/2;
int r=(int)(this.panel.getHeight()/2/Qc/b);//半径
//绘制单位椭圆
e.graphics.setPen(new Pen(zbcolor,PenStyle.DOT,1));
for(double i=0;i<=360;i+=1.5){//i为角度参数
//e.graphics.drawLine(x0+(int)(r*Math.cos(i*Math.PI/180)),y0-(int)(r*Math.sin(i*Math.PI/180)),x0+1+(int)(r*Math.cos((i)*Math.PI/180)),y0+1-(int)(r*Math.sin((i)*Math.PI/180)));
e.graphics.setPixel(x0+(int)(r*a*Qc*Math.cos(i*Math.PI/180)),y0-(int)(r*b*Qc*Math.sin(i*Math.PI/180)));
}
e.graphics.setPen(new Pen(drawcolor,PenStyle.SOLID,2));
for(int i=0;i<P.length;i++){//花极点
e.graphics.drawLine(x0+(int)(r*P[i].Re-2),y0-(int)(r*P[i].Im-2),x0+(int)(r*P[i].Re+2),y0-(int)(r*P[i].Im+2));
e.graphics.drawLine(x0+(int)(r*P[i].Re-2),y0-(int)(r*P[i].Im+2),x0+(int)(r*P[i].Re+2),y0-(int)(r*P[i].Im-2));
}
}//S域数字滤波器的极点位置
if(this.displaywhichdata==6||this.displaywhichdata==7){
this.currentlabel.setText(String.valueOf(this.current+1));
//绘制坐标
e.graphics.setPen(new Pen(zbcolor,PenStyle.SOLID,3));
e.graphics.drawLine(0,panel.getHeight()/2,panel.getWidth(),panel.getHeight()/2);
//绘制数据
e.graphics.setPen(new Pen(drawcolor,PenStyle.SOLID,1));
for(int i=0;i<=((this.totallength<displaynum)?(this.totallength-1):(displaynum-1));i++){
e.graphics.drawLine((int)(steppelix*i),panel.getHeight()/2,(int)(steppelix*i),panel.getHeight()/2-(int)(this.ysize*Math.sqrt(X[i+current+1].Re*X[i+current+1].Re+X[i+current+1].Im*X[i+current+1].Im)));
}
}
}//画图结束
private void menusavefile_click(Object source, Event e)//保存当前数据到文件
{
if(this.displaywhichdata==-1){//当前没有显示任何数据
MessageBox.show("当前没有任何数据可供保存!","警告!",MessageBox.OK+MessageBox.ICONWARNING);
}
else if(this.displaywhichdata==3||this.displaywhichdata==4||this.displaywhichdata==5){//滤波器的频率特性(模拟信号不能保存)
MessageBox.show("当前数据不能保存为离散序列信号!","警告!",MessageBox.OK+MessageBox.ICONWARNING);
}
else{//当前有文件可供保存
SaveFileDialog sfd = new SaveFileDialog();
sfd.setTitle("保存当前数据");
sfd.setFilter("数据文件(*.mydata)|*.mydata");
int result = sfd.showDialog();
if (result == DialogResult.OK) {
File mydata;
mydata=File.create(sfd.getFileName());
if(this.displaywhichdata==0){//如果当前数据是输入序列x【】
mydata.writeInt(this.totallength);//数据长度
for(int i=1;i<=this.totallength;i++){
mydata.writeDouble(x[i]);
}
}
if(this.displaywhichdata==2){//如果当前数据是输出序列y【】
mydata.writeInt(this.totallength);//数据长度
for(int i=0;i<this.totallength;i++){
mydata.writeDouble(y[i]);
}
}
if(this.displaywhichdata==6||this.displaywhichdata==7){
mydata.writeInt(this.totallength);//数据长度
for(int i=1;i<=this.totallength;i++){
mydata.writeDouble(Math.sqrt(X[i].Re*X[i].Re+X[i].Im*X[i].Im));
}
}
mydata.close();//关闭文件
}
}//else:当前有文件可供保存
}
private void menuexit_click(Object source, Event e)
{
this.dispose();
}
private void scroll_valueChanged(Object source, Event e)//拖动滚动条
{
this.current=this.scroll.getValue();
this.panel.invalidate();
}
private void inputXdefault_click(Object source, Event e)//定义x[]:输入典型波形
{
inputdefaultdata myframe=new inputdefaultdata();//从1开始定义的
myframe.max=this.MaxLength;
int result=myframe.showDialog(this);
if(result==DialogResult.YES){//点击确认按钮后,将数据初始化给x[]
x=new double[myframe.data.length];
for(int i=1;i<=x.length-1;i++){//注意!因为数组从1开始初始化,所以序列长度为myframe.data.length-1
x[i]=myframe.data[i];
}
Xinputed=true;//数据初始化完成!
this.displaywhichdata=0;
this.totallength=x.length-1;
this.label1.setText("当前显示数据:输入序列x[]");
this.label3.setText("数据总长度:"+this.totallength+"");
this.timelabel.setText("");
this.ysize=100;
this.steppelix=2;
this.scroll.setValue(0);
this.current=0;
this.panel.invalidate();
solved=false;//尚未处理;
}
}
private void inputXonebyone_click(Object source, Event e)//定义x[]:逐点定义
{
inputonebyone myframe=new inputonebyone();
myframe.max=this.MaxLength;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -