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

📄 消隐view.cpp

📁 计算机图形学原理及算法教程(VC++版)程序代码
💻 CPP
字号:
// 消隐View.cpp : implementation of the CMyView class
//

#include "stdafx.h"
#include "消隐.h"

#include "消隐Doc.h"
#include "消隐View.h"
#include "math.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CMyView

IMPLEMENT_DYNCREATE(CMyView, CView)

BEGIN_MESSAGE_MAP(CMyView, CView)
	//{{AFX_MSG_MAP(CMyView)
	ON_WM_KEYDOWN()
	ON_COMMAND(ID_TUMIANTI, OnTumianti)
	ON_COMMAND(ID_YUANJIN, OnYuanjin)
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMyView construction/destruction

CMyView::CMyView()
{
 
}

CMyView::~CMyView()
{
}

BOOL CMyView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CMyView drawing

void CMyView::OnDraw(CDC* pDC)
{
	CMyDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	// TODO: add draw code for native data here
}

/////////////////////////////////////////////////////////////////////////////
// CMyView printing

BOOL CMyView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CMyView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CMyView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CMyView diagnostics

#ifdef _DEBUG
void CMyView::AssertValid() const
{
	CView::AssertValid();
}

void CMyView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CMyDoc* CMyView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMyDoc)));
	return (CMyDoc*)m_pDocument;
}
#endif //_DEBUG

void  CMyView::Project(float X, float Y, float Z)// 此函数求点的平行投影和透视投影坐标值
{
       XObs = -X * Aux1 + Y * Aux3;
       YObs = -X * Aux5 - Y * Aux6 + Z * Aux4;
       // 求透视投影坐标值
	     ZObs = -X * Aux7 - Y * Aux8 - Z * Aux2 + Rol;
	     XProj = DE * XObs / ZObs;
	     YProj = DE * YObs / ZObs;
}

void  CMyView::WLineTo(float X, float Y, float Z,CDC*pDC)// 用三维点坐标直接从当前点画线到一点的函数
{ 
	  Project(X, Y, Z); // 将三维点作投影
	  XScreen = floor(0.5 + XProj * Scale +150); // 圆整
	  YScreen = floor(0.5 + 100 - YProj); // 圆整
	  pDC->LineTo(XScreen, YScreen); // 画线到一点
}

void  CMyView::WMoveTo(float X, float Y, float Z,CDC*pDC)// 三维坐标下直接将当前点移动到某点的函数
{ 
	  Project (X, Y, Z); // 将三维点作投影
	  XScreen = floor(0.5 + XProj * Scale + 150); // 圆整
	  YScreen = floor(0.5 + 100 - YProj); // 圆整
	  pDC->MoveTo(XScreen, YScreen); //移动到某点
}

void  CMyView::ReadVertics()// 此函数用来给数组St的元素赋顶点坐标值
{
      St[1][1]  = 40;    St[1][2]  = 154;    St[1][3]  =-20;
      St[2][1]  = 40;    St[2][2]  = 154;    St[2][3]  = 0;
      St[3][1]  = 40;    St[3][2]  =46;    St[3][3]  = 0;
      St[4][1]  = 40;    St[4][2]  =46;    St[4][3]  =-20;
      St[5][1]  =-40;    St[5][2]  =46;    St[5][3]  =-20;
      St[6][1]  =-40;    St[6][2]  = 154;    St[6][3]  =-20;
      St[7][1]  =-40;    St[7][2]  = 154;    St[7][3]  = 0;
      St[8][1]  = 0;     St[8][2]  = 134;    St[8][3]  = 40;
      St[9][1]  = 0;     St[9][2]  =66;    St[9][3]  = 40;
      St[10][1] =-40;    St[10][2] =46;    St[10][3] = 0;
}

void  CMyView::ReadFaces()// 此函数给数组Fc的元素赋表面有关的数据值
{
      NF= 9;
      Fc[1][0]=4;  Fc[1][1]=1;  Fc[1][2]=2;  Fc[1][3]=3;  Fc[1][4]=4;
      Fc[2][0]=4;  Fc[2][1]=1;  Fc[2][2]=6;  Fc[2][3]=7;  Fc[2][4]=2;
      Fc[3][0]=3;  Fc[3][1]=2;  Fc[3][2]=7;  Fc[3][3]=8;
      Fc[4][0]=4;  Fc[4][1]=2;  Fc[4][2]=8;  Fc[4][3]=9;  Fc[4][4]=3;
      Fc[5][0]=4;  Fc[5][1]=1;  Fc[5][2]=4;  Fc[5][3]=5;  Fc[5][4]=6;
      Fc[6][0]=4;  Fc[6][1]=7;  Fc[6][2]=10; Fc[6][3]=9;  Fc[6][4]=8;
      Fc[7][0]=3;  Fc[7][1]=3;  Fc[7][2]=9;  Fc[7][3]=10;
      Fc[8][0]=4;  Fc[8][1]=10; Fc[8][2]=5;  Fc[8][3]=4;  Fc[8][4]=3;
      Fc[9][0]=4;  Fc[9][1]=5;  Fc[9][2]=10; Fc[9][3]=7;  Fc[9][4]=6;
}

void  CMyView::VisionVector(int St1)  /* 该函数用于求观察方向矢量 St1 is the first point of a face.  */
{
       v1=O1-St[St1][1];
       v2=O2-St[St1][2];
       v3=O3-St[St1][3];
}

void  CMyView::NormalVector(int St1, int St2, int St3)// 此函数用表面三个顶点调用求该表面的法矢
  // St_i is the i_th point of a face. 
{
float   P1, P2, P3, Q1, Q2, Q3;
        // 求一个向量
	P1 = St[St2][1] - St[St1][1];
	P2 = St[St2][2] - St[St1][2];
	P3 = St[St2][3] - St[St1][3];
        // 求另一个向量
	Q1 = St[St3][1] - St[St1][1];
	Q2 = St[St3][2] - St[St1][2];
	Q3 = St[St3][3] - St[St1][3];
        //用向量积求法向量
	n1 = P2 * Q3 - Q2 * P3;
	n2 = P3 * Q1 - Q3 * P1;
	n3 = P1 * Q2 - Q1 * P2;
}

float  CMyView::ScaleProduct(float v1, float v2, float v3,
		    float n1, float n2, float n3)// 此函数用于求观察方向矢量与表面法矢的数量积
{
float   SProduct;
	SProduct = v1 * n1 + v2 * n2 + v3 * n3;
	return(SProduct);
}

void  CMyView::DrawFace(CDC*pDC)// 画出立体上的平面
{
int     S, NS, No;
float   X, Y, Z, X0, Y0, Z0;
	NS = Fc[F][0];
	for ( S = 1;  S<= NS;  S++ )
	{	    
	    No = Fc[F][S];
	    X = St[No][1];
	    Y = St[No][2];
	    Z = St[No][3];
		if ( S == 1 ) {
			  WMoveTo(X, Y, Z,pDC);
			  X0 = X;
			  Y0 = Y;
			  Z0 = Z;
		}
	    else  WLineTo(X, Y, Z,pDC);
	}
	WLineTo (X0, Y0, Z0,pDC);
}

void  CMyView::DrawObject()// 此函数用于绘出消隐立体图
   
{ int St1, St2, St3;
CDC*pDC=GetDC();
CPen pen1(PS_SOLID,1,(COLORREF)1),pen2(PS_DOT,1,(COLORREF)1);
CPen *pOldPen=pDC->SelectObject(&pen1);
	for ( F = 1;  F<= NF;  F++ )
	{	    
	    St1 = Fc[F][1];    St2 = Fc[F][2];    St3 = Fc[F][3];
	    VisionVector(St1); // 求观察方向矢量
	    NormalVector(St1, St2, St3); // 求表面法矢
	    if ( ScaleProduct( v1,v2,v3,n1,n2,n3 ) > 0 ) // 判断数量积正否
		{      
	       pDC->SelectObject(&pen1);
	       DrawFace(pDC); // 数量积大于零,表面可见,画出此表面
		}  
	    else;
	   }
	pDC->SelectObject(pOldPen);
	ReleaseDC(pDC);
}

void  CMyView::VisionPoint()// 此函数用于给出视点位置
{
  // 投影时初始值即正弦值和余弦值及其乘积的计算、赋值
	float  Th, Ph;
       Th   = 3.1415926 * Theta / 180;
       Ph   = 3.1415926 * Phi / 180;
       Aux1 = sin(Th);
       Aux2 = sin(Ph);
       Aux3 = cos(Th);
       Aux4 = cos(Ph);
       Aux5 = Aux3 * Aux2;
       Aux6 = Aux1 * Aux2;
       Aux7 = Aux3 * Aux4;
       Aux8 = Aux1 * Aux4;
      //给出视点位置
      O1 = Rol * Aux7;
      O2 = Rol * Aux8;
      O3 = Rol * Aux2;
}

void CMyView::Mydraw()
{
	RedrawWindow();
	ReadVertics();
	ReadFaces();
	// 绘出透视投影下的凸多面体图形
	VisionPoint(); // 给出视点位置
       DrawObject(); // 画出立体的图形
}

/////////////////////////////////////////////////////////////////////////////

void CMyView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{//此函数用来利用上下左右键移动视点角度位置,C键切换投影类型.
 //读者可以自己定义其他键值以及其他参数.
	switch(nChar){			
	case VK_UP:					//上下左右键选择		
		Phi=Phi-IncAng;
		Mydraw();
		break;
	case VK_DOWN:
		Phi=Phi+IncAng;
		Mydraw();
		break;
	case VK_RIGHT:
		Theta=Theta+IncAng;
		Mydraw();
		break;
	case VK_LEFT:
		Theta=Theta-IncAng;
		Mydraw();	
		break;
	default:
		break;
	}
}




void CMyView::OnTumianti() 
{//透视投影赋初值
	  Rol = 600.0;
 	  S=1;
 	  Theta = 60;
 	  Phi = 135;
 	  DE  = 1000;
 	   Mydraw();
 	   CDC*pDC=GetDC();
 	   pDC->TextOut(10,10,"按下键盘上的“上”、“下”、“左”、“右”箭头可从各方位观看图形");
 	   ReleaseDC(pDC);
}

void CMyView::OnYuanjin() 
{
	CClientDC *pdc=new CClientDC(this);
	CPen *pen1=new CPen(PS_SOLID,1,RGB(0,0XFF,0));
	CPen *pen2=new CPen(PS_SOLID,1,RGB(255,0,0));
	CPen *OldPen=pdc->SelectObject(pen1);

	CBrush brush;
    brush.CreateSolidBrush(RGB(0,0,0));
    CBrush *oldbrush=(CBrush*)pdc->SelectObject(&brush);
	int flag,k1,k2,r1,r2,n,d,m,p;
	int xs1,xs2,xs3,xs4,ys1,ys2,ys3,ys4,i,j,lastp;
	double x,y,z,thx,th1,th3,yw,zw,xw,thy,th2;
	double PI,ed,od,eh,zzw,ppw;
	double xs[50][17],zs[50][17],ys[50][17],zc[50][17],x1,y1;
	int zz[850],pp[850];

	r1=100;r2=40;k1=20;k2=16;ed=1500; eh=0;od=0;
	n=0;PI=3.14159;th3=1;thx=0.9;

	//计算顶点坐标值
for(d=-1;d<=1;d+=2){ 
	for(th1=0; th1<=2*PI+0.1;th1+=2*PI/k1){
        n=n+1; m=0;
       for(th2=0;th2<=2*PI+0.1;th2+=2*PI/k2){
            m=m+1;

		x=r1+r2*cos(th2);
		y=r2*sin(th2);
		z=0;
		thy=th1;

		//Call rot_y
		zw=z; xw=x;
		x=zw*cos(thy)-xw*sin(thy);
		z=zw*sin(thy)+xw*cos(thy);
		//
		x=x+r1/2*d;
   if(d==1)
   {
		yw=y;
		zw=z;
		y=yw*cos(PI/2)-zw*sin(PI/2);
		z=yw*sin(PI/2)+zw*cos(PI/2);
   }
			thy=th3;

			//Call rot_y 
			zw=z; xw=x;
			x=zw*cos(thy)-xw*sin(thy);
			z=zw*sin(thy)+xw*cos(thy);
			// Call rot_x:
			yw=y; zw=z;
			y=yw*cos(thx)-zw*sin(thx);
			z=yw*sin(thx)+zw*cos(thx);
			//Call pers
			x=x*ed/(ed-od-z);
			y=(y*ed-eh*(od+z))/(ed-od-z);

			xs[n][m]=x;
			ys[n][m]=y;
			zs[n][m]=z;
	   }
		//next th2
			
		flag=0;
		//Next th1
			}
		flag=0;	
		//Next d
	}
//计算center值
p=0;
  for(n=1;n<=k1;n+=1){
	  for(m=1;m<=k2;m+=1){
		zc[n][m]=int((zs[n][m]+zs[n+1][m+1])/2);
        zz[p]=zc[n][m];
        pp[p]=p;
        p=p+1;
    //Next m
    //Next n
	}
	}
 lastp=p-1;
 //排序
 for(i=2;i<=lastp;i+=1){
	   for(j=i-1;j>=0;j+=-1){
		 if(zz[j]>zz[j+1]) {
   zzw=zz[j];
   zz[j]=zz[j+1];
   zz[j+1]=zzw;
   ppw=pp[j];
   pp[j]=pp[j+1];
   pp[j+1]=ppw;
		 }
	 }
 }
  //绘图
	 for(p=0;p<=lastp;p+=1){
	  n=int(pp[p]/k2)+1;
	  m=pp[p]%k2+1;
	  if(n!=(k1+1)){
   
	  xs1=int(xs[n][m]);      ys1=int(ys[n][m]);
	  xs2=int(xs[n+1][m]);    ys2=int(ys[n+1][m]);
	  xs3=int(xs[n+1][m+1]);  ys3=int(ys[n+1][m+1]);
	  xs4=int(xs[n][m+1]);    ys4=int(ys[n][m+1]);
	  //}
  
	  if (abs(ys1*(xs2-xs3)+ys2*(xs3-xs1)+ys3*(xs1-xs2))>80){
		  pdc->MoveTo(xs1+320,ys1+200);
	pdc->SelectObject(pen1);
	  pdc->LineTo(xs2+320,ys2+200);
      pdc->LineTo(xs3+320,ys3+200);
      pdc->LineTo(xs4+320,ys4+200);
      pdc->LineTo(xs1+320,ys1+200);
  
  
	  //paint
  x=(xs[n][m]+xs[n+1][m+1])/2;
  y=(ys[n][m]+ys[n+1][m+1])/2;
  x1=int(x+320);
  y1=int(y+200);

  pdc->ExtFloodFill(x1,y1,RGB(0,255,0),0);
  //endif
  }

  pdc->MoveTo(xs1+320,ys1+200);
pdc->SelectObject(pen2);
	  pdc->LineTo(xs2+320,ys2+200);
      pdc->LineTo(xs3+320,ys3+200);
      pdc->LineTo(xs4+320,ys4+200);
      pdc->LineTo(xs1+320,ys1+200);
 }
 }
pdc->SelectObject(OldPen);
 delete pen1;
 delete pen2;
 pdc->DeleteDC();	
}

⌨️ 快捷键说明

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