⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 raytrace.cpp

📁 实现二维非均匀介质下的射线追踪
💻 CPP
字号:

/* 两点射线追踪,设计者:胡治权  原理:参考杨文采《地球物理反演理论》,快速精准射线追踪*/
/*功能:完成两点射线追踪,并将射线在剖面上的交点写入磁盘文件*/
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define PAI 3.1415926

struct dotinform
{ 
	float x;
	float z;
	float nx;
	float nz;
	float tsum;
};/*存放点信息*/

struct jie
{ 
	float s;
	char ch;
	float val;
};/*存放解信息*/
int deltv(float x,float z,float nx,float nz,float *DVX,float *DVZ,float *vp,float *v,float fx,float dx,int xn,
		  float fz ,float dz,int zn);
float raytrace (float *X,float *Z,float *NX,float *NZ,float *T, float v,float dvx,float dvz,float dx,float dz,float fx,float fz,
			   struct dotinform *p,int *k,float xend, float zend);
void main()
{
	FILE *infp,*outfpxz,*outfpp;
	dotinform p[5000];
	char ch[20];
	int ii,ij,is;
	int vtype;
	float *v;
	float fangle ,endangle,dangle;
	float fsx,dsx;
	float fx,dx;
	float fz,dz;
	int   xn,zn,nsx;
    int   k=1,vflag;
    float xend,zend,n,sign;
	float x,z,t,va=0,dvxa=0,dvza=0,nx,nz,alpha,sx;
   
	printf("*******************射线追踪(设计:胡治权)***********************\n");
    printf("***选择输入的速度文件类型:1. 文本文件  2. 二进制文件\n");
    do{
	   scanf("%d",&vtype);
	   if(vtype != 1 && vtype != 2)
		  printf("输入错误,请重新输入\n");
	   }while(vtype !=1 && vtype != 2);
	do{
        printf("***输入速度文件名:");
        scanf("%s",ch);
        if((infp = fopen(ch,"r")) == NULL)
			printf("无法打开指定的速度文件,请核对后重新输入!\n");
	}while(infp == NULL);
	printf("***输入速度网格剖分参数***\n");
	printf("横向起始坐标(数据类型:float):fx=");
	scanf("%f",&fx);
	do{
	   printf("横向采样间隔(数据类型:float>0):dx=");
	   scanf("%f",&dx);
	   if(dx <= 0) printf("dx<=0输入错误,请重新输入!");
	   }while(dx<=0);
	do{
	   printf("横向采样点数(数据类型:int>0):xn=");
	   scanf("%d",&xn);
	   if(xn<=0)printf("xn<=0输入错误,请重新输入!");
	   }while(xn<=0);
    printf("纵向起始坐标(数据类型:float):默认设置fz=0\n");
    fz = 0;
	do{
	    printf("纵向采样间隔(数据类型:float>0):dz=");
	    scanf("%f",&dz);
		if(dz<=0)printf("dz<=0输入错误,请重新输入!");
	}while(dz<=0);
	do{
	    printf("纵向采样点数(数据类型:int>0):zn=");
		scanf("%d",&zn);
		if(zn<=0)printf("zn<=0输入错误,请重新输入!");
	}while(zn<=0);
    
	xend = fx +(xn-1)*dx;
	zend = fz +(zn-1)*dz;
	printf("***输入炮参数***\n");
	printf("请输入第一炮的横坐标(数据类型float):fsx=");
	do{
	   scanf("%f",&fsx);
       if(fsx<fx || fsx >xend) printf("炮点不在剖面上,请重新输入!");
	   }while(fsx <fx || fsx >xend);
   do{
	    printf("炮点采样间隔(数据类型:float>0):dsx=");
	    scanf("%f",&dsx);
		if(dsx<=0)printf("dsx<=0输入错误,请重新输入!");
	}while(dsx<=0);
	do{
	    printf("炮点采样点数(数据类型:int>0):nsx=");
		scanf("%d",&nsx);
		if(nsx<=0)printf("nsx<=0输入错误,请重新输入!");
	}while(nsx<=0);
	printf("***角度参数***\n");
	do{
		printf("输入角度起始值(°):fangle=");
		scanf("%f",&fangle);
		printf("输入角度中止值(°)>=起始值:endangle=");
		scanf("%f",&endangle);
		if(fangle>endangle)printf("输入错误,请重新输入!");
	}while(fangle>endangle);
	do{
		 printf("输入角度增量(>=0):dangle=");
		 scanf("%f",&dangle);
		 if(dangle<0)printf("输入错误,请重新输入!");
	}while(dangle<0);
	printf("*******参数输入完毕*******\n");
	printf("进行射线追踪,请稍等...\n");


	outfpxz=fopen("xz.dat","w");
	outfpp=fopen("pshu.dat","w");

    
    v= (float*) malloc(xn*zn*sizeof(float));
 
   if(vtype == 1)
   {
    for (ii = 0 ; ii < zn; ii++)
	{

		for (ij = 0;ij < xn;ij++)
		{
			fscanf(infp,"%f",&v[ii*xn+ij]);
		
		}
       
	}
   }else
   {
	   fread(v,sizeof(float),zn*xn,infp);
   }
  
   for(is = 0;is< nsx ; is++)
   {
      sx = fsx + is*dsx;n=0;
	  
	  while ((fangle + n*dangle) <= endangle)
	  {
		  x = sx;z = 0;
		  alpha = (float)PAI*(fangle + n*dangle)/180;
		  printf("射线追踪:炮点sx=%f,入射角度alpha=%f,",sx,(fangle+n*dangle));
		  nx = -(float)sin(alpha);
	      nz = (float)cos(alpha)  ; 
	      t  = 0;                      
	      p[0].x = x;    
	      p[0].z = 0;
         
	    do
		{
          vflag = deltv(x,z,nx,nz,&dvxa,&dvza,&va,v,fx,dx,xn,fz,dz,zn);
		  if(vflag == 0) break;
          sign=raytrace(&x,&z,&nx,&nz,&t,va,dvxa,dvza,dx,dz,fx,fz,p,&k,xend,zend);
		  if(sign == 0 || sign == -1) break;
		}while(1);
	
        
		if(sign != 0 )
        {
          for (ii = 0;ii < k ;ii++)
		  {
		   fprintf(outfpxz,"%.8f  ",p[ii].x);
	       fprintf(outfpxz,"%.8f\n ",p[ii].z);
		  }
		  fprintf(outfpp,"%d\n",k);
		  printf("射线交点数k=%d\n",k);
		}else{ printf("追踪失败!\n");}
		 k = 1;
		 n = n + 1;
	  }
    printf("完成炮点sx=%f的射线追踪\n",sx);
   }


    printf("完成射线追踪!");
    fclose(infp);
	fclose(outfpxz);
	fclose(outfpp);

}
int deltv(float x,float z,float nx,float nz,float *DVX,float *DVZ,float *vp,float *v,float fx,float dx,int xn,
		  float fz ,float dz,int zn)
{
	float l,dvx,dvz;
	float v1,v2,v3,v4;
	float dv1,dv2,dv1x,dv1z,dv2x,dv2z;
	int i,j;

	
	j = (int)floor((x-fx)/dx);
	i = (int)floor((z-fz)/dz);



	/*求速度梯度*/
	if(j>=0 && j<= xn && i>=0 && i<=zn)
	{
	
          if(nx<0 &&nz<0)
		  {
			  if(i-1 <0 || j-1 <0) return 0;
			  v1 = v[(i-1)*xn+j-1];v2 = v[(i-1)*xn+j];
			  v3 = v[i*xn+j];      v4 = v[i*xn+j-1];
		  }
		  if(nx>0 && nz<0)
		  {
			  if(i-1 <0 || j+1 >xn) return 0;
			  v1 = v[(i-1)*xn + j] ; v2 = v[(i-1)*xn+j+1];
			  v3 = v[i*xn +j+1] ;    v4 = v[i*xn +j];
		  }
		  if(nx >0 && nz>0)
		  {
			  if(i+1 > zn || j+1 > xn) return 0;
			  v1 = v[i*xn+j]; v2 = v[i*xn +j+1];
			  v3 = v[(i+1)*xn+j+1]; v4 = v[(i+1)*xn +j];
		  }
          if(nx <0 && nz>0)
		  {
			  if(i+1 >zn || j-1<0) return 0;
			  v1 = v[i*xn +j-1]; v2 = v[i*xn +j];
			  v3 = v[(i+1)*xn+j];v4 = v[(i+1)*xn+j-1];
		  }
		  
	      l = (float)sqrt(dx*dx+dz*dz);
		  dv1 = (v3-v1)/l;dv1x = dv1*dx/l;dv1z = dv1*dz/l;
		  dv2 = (v4-v2)/l;dv2x =-dv2*dx/l;dv2z = dv2*dz/l;
		  *DVX = (float)0.5*(dv1x+dv2x);
		  *DVZ = (float)0.5*(dv1z+dv2z);
		 
	}else return 0;
    dvx = *DVX;dvz =*DVZ;
	if(j>= 0 && j<= xn && i >=0 && i <= zn)
	{
		if(fmod((x-fx),dx) == 0 && fmod((z-fz),dz) == 0)
			*vp = v[i*xn+j];
		else
			*vp = v[i*xn+j]+(float)fmod((x-fx),dx)*dvx+(float)fmod((z-fz),dz)*dvz;
        return 1;
	}else return 0;

}



float raytrace (float *X,float *Z,float *NX,float *NZ,float *T,float v,float dvx,float dvz,float dx,float dz,float fx,float fz,
			   struct dotinform*p,int *k,float xend,float zend)
{
	/*变量定义*/
   int i,j,flag;
   int  jj,ks;
   float x,z,nx,nz,t;
   jie so,s[8],ends[8];
   float deltx,zbefore,zafter;
   float xa,xb,xc1,xc2,delt,zs,za,zb,zc1,zc2,delt1,delt2,xs;
   float deltz,xbefore,xafter;
   float deltk;
  
   x = *X;
   z = *Z;
   nx = *NX;
   nz = *NZ;
   t  = *T;
  
   for(i=0;i<8;i++)
   {
	   s[i].ch= 'a';s[i].s = -1;s[i].val = 0;
	   ends[i].ch= 'a';ends[i].s= -1;ends[i].val=0;
   }
 
   so.ch = 'a' ; so.s = -1;so.val= 0;
  
  
   if(fmod(x,dx) == 0) {flag = 1;}   /*flag=1,射线从Z轴入射*/
   if(fmod(z,dz) == 0) {flag = 2;}
   if(flag != 1 && flag != 2) return 0; 
  
   if(v <= 0) return 0;
   i = 0;
   j = 0;
   ks= 0;   
   switch (flag){
   case 1:
	   if(nx >0)
	   {
		   deltx = dx;
	   }else{
		   deltx = -dx;
	   }
    
	   xa = (dvx*nx*nx+dvz*nx*nz-dvx)/(2*v);
	   xb = nx;
	   xc1= 0;
	   xc2= -deltx;
	   delt = xb*xb - 4*xa*xc2;
	   if(xa != 0)
	   {
	     s[i].s = -(xb/xa);s[i].ch = 'x';s[i].val = x;
	     i++;
	     if (delt >= 0)
		 {
		   s[i].s = (-xb+(float)sqrt(delt))/(2*xa);s[i].ch = 'x';s[i].val = (x+deltx);
		   i++;
           s[i].s = (-xb-(float)sqrt(delt))/(2*xa);s[i].ch = 'x';s[i].val = (x+deltx);
		   i++;
		 }
	   }else{
         s[i].s = -(xc2/xb);s[i].ch = 'x';s[i].val = (x+deltx); i++;
        
	   }
      
	   if(nz > 0)
	   {
		   zbefore = z - (float)fmod(z,dz);
	       zafter  = zbefore + dz;
	   }else{ 
		      if ( fmod(z,dz) == 0.0)
			  {
				  zafter = z ;
	              zbefore  = zafter - dz;
			  }else{
                 zbefore = z - (float)fmod(z,dz);
	             zafter  = zbefore + dz;
			  }
	   }
	   for(j = 0; j<i ;j++)
	   {
		   if (s[j].s >0) 
		   {
			   zs = s[j].s*s[j].s*(dvz*nz*nz+dvx*nx*nz-dvz)/(2*v)+nz*s[j].s +z;
		       if (zbefore <= zs && zs <= zafter) 
			   {
				   ends[ks].s = s[j].s;ends[ks].ch = s[j].ch;ends[ks].val = s[j].val;ks++;
			   }
		   }
	   }
	   

	   za = (dvz*nz*nz+dvx*nx*nz-dvz)/(2*v);
	   zb = nz;
	   zc1= z-zbefore;
	   zc2= z-zafter;
	   delt1 = zb*zb-4*za*zc1;                   
	   delt2 = zb*zb-4*za*zc2;
	   if(za != 0)
	   {
	     if (delt1 >= 0)
		 {
		   s[i].s = (-zb+(float)sqrt(delt1))/(2*za);s[i].ch = 'z';s[i].val = zbefore;i++;
           s[i].s = (-zb-(float)sqrt(delt1))/(2*za);s[i].ch = 'z';s[i].val = zbefore;i++;
		 }
	     if (delt2 >= 0)
		 {
           s[i].s = (-zb+(float)sqrt(delt2))/(2*za);s[i].ch = 'z';s[i].val = zafter;i++;
           s[i].s = (-zb-(float)sqrt(delt2))/(2*za);s[i].ch = 'z';s[i].val = zafter;i++;       
		 }
	   }else{
              s[i].s = -(zc1/nz);s[i].ch = 'z';s[i].val = zbefore;i++;
              s[i].s = -(zc2/nz);s[i].ch = 'z';s[i].val = zafter;i++;
	   }

	   for(jj = j ;jj <i ;jj++)
	   {
		   if (s[jj].s >0) 
		   {
			   xs = s[jj].s*s[jj].s*(dvx*nx*nx+dvz*nx*nz-dvx)/(2*v)+nx*s[jj].s+x;
		       if ((x<=xs && xs<=x+deltx)||(x+deltx <= xs && xs <= x)) 
			   {
				   ends[ks].s = s[jj].s;ends[ks].ch = s[jj].ch;ends[ks].val = s[jj].val;ks++;
			   }
		   }
	   }
	   so.s = 999999;
	   for(jj = 0 ;jj<ks ; jj++)
	   {
		   if(ends[jj].s<=so.s)
		   {
			   so.s = ends[jj].s;so.ch = ends[jj].ch;so.val = ends[jj].val;
		   }
	   }
	   break;

   case 2:
       if (nz >0) 
	   {
		   deltz = dz;
	   }else{
		   deltz = -dz;                       
	   }
	  
	   za = (dvz*nz*nz+dvx*nx*nz-dvz)/(2*v);
	   zb = nz;
	   zc1= 0;
	   zc2= -deltz;
	   delt= zb*zb - 4*za*zc2;
	   if(za != 0)
	   {
	     s[i].s=-(zb/za);s[i].ch = 'z';s[i].val = z;
	     i++;
	
	     if (delt >= 0)
		 {
		   s[i].s = (-zb+(float)sqrt(delt))/(2*za);s[i].ch = 'z';s[i].val = (z+deltz);i++;
           s[i].s = (-zb-(float)sqrt(delt))/(2*za);s[i].ch = 'z';s[i].val = (z+deltz);i++;
		 }
	   }else{
              s[i].s = -(zc2/zb);s[i].ch = 'z';s[i].val = (z+deltz);
	          i++;
	   }
	   if(x>0)
	   {
	     if(nx >=0)
		 {
	       xbefore = x - (float)fmod(x,dx);
	       xafter  = xbefore + dx;
		 }else{
		      if (fmod(x,dx) == 0.0)
			  { 
				  xafter = x;
				  xbefore = xafter -dx;
			  }else{ 
				   xbefore = x - (float)fmod(x,dx);
	               xafter  = xbefore + dx;
			  }
		 }
	   }else{
           if(nx <=0)
		   {
	         xafter = x - (float)fmod(x,dx);
	         xbefore  = xafter - dx;
		   }else{
		      if (fmod(x,dx) == 0.0)
			  { 
				  xbefore = x;
				  xafter = xbefore +dx;
			  }else{ 
				   xafter = x - (float)fmod(x,dx);
	               xbefore  = xafter - dx;
			  }
		   }
	   }

	   for (j=0;j<i;j++)
	   {
		   if(s[j].s>0) 
		   {
			   xs = s[j].s*s[j].s*(dvx*nx*nx+dvz*nx*nz-dvx)/(2*v)+nx*s[j].s+x;
		       if(xbefore<= xs&& xs<= xafter) 
			   {
			     ends[ks].s = s[j].s;ends[ks].ch = s[j].ch;ends[ks].val = s[j].val;ks++;
			   }
		   }
	   }
	  

	   xa = (dvx*nx*nx+dvz*nx*nz-dvx)/(2*v);
	   xb = nx;
	   xc1=x-xbefore;
	   xc2=x-xafter;
	   delt1 = xb*xb-4*xa*xc1;
	   delt2 = xb*xb-4*xa*xc2;
	   
	   if(xa != 0)
	   {
	     if(delt1>=0)
		 {
		   s[i].s = (-xb+(float)sqrt(delt1))/(2*xa);s[i].ch = 'x';s[i].val = xbefore;i++;
           s[i].s = (-xb-(float)sqrt(delt1))/(2*xa);s[i].ch = 'x';s[i].val = xbefore;i++;
		 }

         if(delt2>=0)
		 {
		   s[i].s = (-xb+(float)sqrt(delt2))/(2*xa);s[i].ch = 'x';s[i].val = xafter;i++;
           s[i].s = (-xb-(float)sqrt(delt2))/(2*xa);s[i].ch = 'x';s[i].val = xafter;i++;
		 }
	   }else{
           s[i].s = -(xc1/nx);s[i].ch = 'x';s[i].val = xbefore;i++;
           s[i].s = -(xc2/nx);s[i].ch = 'x';s[i].val = xafter;i++;
	   }
 
	   for(jj = j;jj<i;jj++)
	   {
         
		   if(s[jj].s>0) 
		   {
			   zs = s[jj].s*s[jj].s*(dvz*nz*nz+dvx*nx*nz-dvz)/(2*v)+nz*s[jj].s+z;
		       if((z<= zs &&zs <= z+deltz)||(z+deltz <= zs && zs<=z))
			   {
			     ends[ks].s = s[jj].s;ends[ks].ch = s[jj].ch;ends[ks].val = s[jj].val;ks++;
			   
			   }
		   }
	   }
      
	   
	   so.s=999999;
	   for(jj=0;jj<ks;jj++)
	   {
		   if(ends[jj].s<=so.s) 
		   {  
			   so.s = ends[jj].s;so.ch = ends[jj].ch;so.val = ends[jj].val;
		   }
	   }
	   break;
	}

	if (so.s != 999999)
	{
	   
		if(so.ch == 'x')
		{ 
			*X = so.val;
            *Z = so.s*so.s*(dvz*nz*nz+dvx*nx*nz-dvz)/(2*v)+nz*so.s+z;
		}
		if(so.ch == 'z')
		{
            *X = so.s*so.s*(dvx*nx*nx+dvz*nx*nz-dvx)/(2*v)+nx*so.s+x;
		    *Z = so.val;
		}
		*T = so.s*(1-(dvx*nx+dvz*nz)*so.s/(2*v))/v+t;
        *NX = nx+(dvx*nx*nx+dvz*nz*nx-dvx)*so.s/v;
        *NZ = nz+(dvx*nx*nz+dvz*nz*nz-dvz)*so.s/v;
     	deltk = ((*NX)*(*NX)+(*NZ)*(*NZ)-1)/2;
		*NX = (*NX)/(1+deltk);
		*NZ = (*NZ)/(1+deltk);
	
/*		if(fabs((*NX)*(*NX)) >=0.8 && fabs((*NX)*(*NX)) <1)
		{
            if(*Z >z) *NZ = (float)sqrt(1-(*NX)*(*NX));
			else *NZ = (float)-sqrt(1-(*NX)*(*NX));
		}
        if(fabs((*NZ)*(*NZ)) >=0.8 && fabs((*NZ)*(*NZ)) <1)
		{
           	if(*X >x) *NX = (float)sqrt(1-(*NZ)*(*NZ));
			else *NX = (float)-sqrt(1-(*NZ)*(*NZ));
		}
*/
	    if(fabs(*NX)>1)
		{
			if(*X >x) *NX = (float)sqrt(1-(*NZ)*(*NZ));
			*NX = (float)-sqrt(1-(*NZ)*(*NZ));
		}
		if(fabs(*NZ)>1)
		{
            if(*Z >z) *NZ = (float)sqrt(1-(*NX)*(*NX));
			*NZ = (float)-sqrt(1-(*NX)*(*NX));
		} 
	
		if(*X == x)  return 0;
		if ((fx<=*X)&&(*X<= xend)&&(fz<=*Z)&&(*Z<=zend))
		{
		   p[*k].x= *X;
		   p[*k].z= *Z;
		   p[*k].nx=*NX;
		   p[*k].nz=*NZ;
		   p[*k].tsum=*T;
		   (*k)++;
		}
	   if(*X <= fx || *X >= xend || *Z<= fz || *Z>= zend) return -1;
	   return 1 ;
	}
	else {
		
		return 0;
		
	}
   
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -