// Hidden Line
#include "stdafx.h"

#include "math.h"

#define PI 3.14159265358979

 

FILE *fstream;

double Hidden_dlx;      // 表示刻み幅(dl)

double Hidden_alpha;    // x軸と水平軸との角度(α)

double Hidden_beta;     // y軸と水平軸との角度(β) 

double Hidden_dx;       // x軸方向の単位メッシュの長さ(dx)

double Hidden_dy;       // y軸方向の単位メッシュの長さ(dy)

double HeighZ[51][51]; // 高さ(z)

double YMax[2000];  // Y座標値の最大値(上の浮動水平線)

double YMin[2000];  // Y座標値の最小値(下の浮動水平線)

double Hidden_Xlen;// 表示上のX方向長さ=(numX-1)*dx*cos(α)

double Hidden_Ylen;// 表示上のX方向長さ=(numY-1)*dx*cos(β)

int Hidden_NR;                 // 浮動水平線用配列の長さ

double beforX;                   // 現在ペン位置X

double beforY;                   // 現在ペン位置Y

int numX=51;                    // x方向メッシュ数

int numY=51;                    // y方向メッシュ数

double Hidden_dxCosA;   // dx*cos(α)

double Hidden_dyCosB;   // dy*cos(β)

double Hidden_dxSinA;    // dx*sin(α)

double Hidden_dySinB;    // dy*sin(β)

double Hidden_dlxTanA;  // dl*tan(α)

double Hidden_dlxTanB;  // dl*tan(β)

 

bool Hidden_Draw(double px,double py,int p, bool Visible, bool Update)

{             // 陰線かどうかを判断し,陰線でない場合,線を描く。

              // 関数値  : 表示後の可視フラグ

              // e       : 描画用引数

              // pen     : ペン属性

              // px      : 補間されたX座標値(平面座標系)

              // py      : 補間されたY座標値(平面座標系)

              // p       : 比較する浮動水平線の位置

              // Visible : 現ペン位置が見えているかどうかを示すフラグ(可視フラグ)

              // Update  : 陰線でないとき,浮動水平線を更新するかどうかを示すフラグ

              if((py>=YMax[p])||(py<=YMin[p])){

              if(Update && py >=YMax[p])YMax[p]=py;

              if(Update && py <=YMin[p])YMin[p]=py;

              if(Visible){

                            float fx1=(float)beforX; float fy1=(float)beforY;

                            float fx2=(float)px    ; float fy2=(float)py;

                            fprintf(fstream,"\"Line\", %f,%f,%f,%f,0,\"\"\n",fx1,fy1,fx2,fy2);

              }

                            beforX=px;beforY=py; return true;                  

              }

              else{

                            beforX=px;beforY=py; return false;

              }

}

double Hidden_GroundX(int j, int k) // X0=Y0=0のときのX座標

{ return (double)j * Hidden_dxCosA - (double) k * Hidden_dyCosB;}

double Hidden_GroundY(int j, int k) // X0=Y0=0のときのY座標

{ return (double)j * Hidden_dxSinA + (double) k * Hidden_dySinB;}

void window(double X1, double Y1, double X2, double Y2)

{

  fprintf(fstream,"\"window\", %f, %f, %f,%f\n",X1,Y1,X2,Y2);

}

// 関数値設定部分を次のように変更してみよう
//    X=0.3*((double)j-DNX2);
//    for(int k=0; k<numY; k++){

//     Y=0.3*((double)k-DNY2);
//
      fxy=(X-Y)*exp(-(X*X+Y*Y));
//      HeighZ[j][k]=40.0*fxy;
// }

int main(int argc, char* argv[])

{

              double DNX2= ((double)numX)/2;double DNY2= ((double)numY)/2; // 高さデータの設定

              double X,Y,R,fxy;int j;

              fstream=fopen("c:\\data2.txt","w");

              for( j=0; j<numX; j++){

                            X=0.3*((double)j-DNX2);//***

                            for(int k=0; k<numY; k++){//**

                                          Y=0.3*((double)k-DNY2); R=sqrt(X*X+Y*Y);/**

                                          if(R==0.0) fxy=1.0; else fxy=sin(R)/R;/**

                                          HeighZ[j][k]=40.0*fxy;/**

                            }

              }

              Hidden_dlx= 0.1; Hidden_alpha = PI/12; // 表示用パラメータの設定

              Hidden_beta= PI/8;           Hidden_dx = 2;   Hidden_dy  = 1.4;

  Hidden_dxCosA=Hidden_dx*cos(Hidden_alpha); // 計算に用いる値の設定

  Hidden_dyCosB=Hidden_dx*cos(Hidden_beta);

  Hidden_dxSinA=Hidden_dx*sin(Hidden_alpha);

  Hidden_dySinB=Hidden_dx*sin(Hidden_beta);

  Hidden_Xlen=(numX-1)*Hidden_dxCosA;

  Hidden_Ylen=(numY-1)*Hidden_dyCosB;

  Hidden_dlxTanA=Hidden_dlx*tan(Hidden_alpha);

  Hidden_dlxTanB=Hidden_dlx*tan(Hidden_beta);

  Hidden_NR=(int)((Hidden_Xlen+Hidden_Ylen)/Hidden_dlx)+1;

  // 表示座標マトリックスの設定

  window(-10,200,200,60);       // 表示座標マトリックスの設定

              bool VisibleFlag=true;

              for (j=0;j<Hidden_NR;j++){ YMax[j]=-1E20; YMin[j]=1E20;} // 浮動水平線の初期化

              double X0=80;                                                // 表示始点位置 

              double Y0=100;

              for(int k=0;k<numY;k++)  {

                            VisibleFlag=false;

                            for(int j=0;j<numX-1;j++){                               // X軸方向描画

                                          int p1=(int)((0.5+(Hidden_Ylen+Hidden_GroundX(j,k))  /Hidden_dlx));

                                          int p2=(int)((0.5+(Hidden_Ylen+Hidden_GroundX(j+1,k))/Hidden_dlx));

                                          for(int p=p1; p<=p2;p++){                                                                                     // 補間

                                                        double PH=(double)(p-p1);

                                                        double fp = HeighZ[j][k]+(HeighZ[j+1][k]-HeighZ[j][k]) * PH * Hidden_dlx / Hidden_dxCosA;

                    double px = PH*Hidden_dlx + Hidden_GroundX(j,k)+ X0;

                   double py = PH*Hidden_dlxTanA + Hidden_GroundY(j,k) + fp + Y0;

                    if((j<numX-2 && p<p2) || (j == numX-2))

                     VisibleFlag=Hidden_Draw(px, py, p,VisibleFlag, true);

           }

              }

              for(j=0;j<numX && k<numY-1;j++)              {                     // Y軸方向描画

            VisibleFlag=false;

                            int p1=(int)((0.5+(Hidden_Ylen+Hidden_GroundX(j,k))  /Hidden_dlx));

                            int p2=(int)((0.5+(Hidden_Ylen+Hidden_GroundX(j,k+1))/Hidden_dlx));

                            for(int p=p1; p>=p2;p--){                  // 補間

                                          double PH=(double)(p-p1);

                                          double fp=HeighZ[j][k]-(HeighZ[j][k+1]-HeighZ[j][k])*PH*Hidden_dlx/Hidden_dyCosB;

                                          double px = PH*Hidden_dlx + Hidden_GroundX(j,k) + X0;

                                          double py =-PH*Hidden_dlxTanB + Hidden_GroundY(j,k) + fp + Y0;

                                          VisibleFlag=Hidden_Draw(px, py, p,VisibleFlag, p!=p2);

                            }

              }

              }

  fclose(fstream);

  return 0;

}