1. 程式人生 > >GIS程式設計(七)實現基本向量圖形系統的文件和檢視(3) 實現向量圖形系統的檢視

GIS程式設計(七)實現基本向量圖形系統的文件和檢視(3) 實現向量圖形系統的檢視

GIS程式設計(七)實現基本向量圖形系統的文件和檢視(3

實現向量圖形系統的檢視

本節將在上兩節的基礎之上,實現向量圖形系統的檢視,完成向量圖形系統的圖形元素繪製功能。

1、建立座標系

在組織一幅圖形時,採用哪一種映像方式組織向量圖形系統的座標系值得進行研究。在本向量圖形系統中,可以建立一個座標原點在左下角的座標系,然後建立這個座標系和Windows各個座標系映像方式之間的轉換關係。在此座標系中,取左下角為原點,給定這個點的實際座標為(m_xStart,m_yStart,並確定一個變數blc,作為邏輯座標和實際座標的比例關係。

為了實現實際座標和邏輯座標之間的轉換,在檢視類【CDrawView】中定義如下的兩個轉換函式:

public:

void DPtoVP(float x,float y,int *X,int *Y);

void VPtoDP(int x,int y,float *X,float *Y);

在實現檔案中實現此兩個函式

兩個轉換函式中用到的成員變數在檢視類中定義:

float m_xStart,m_yStart,blc; //繪製圖形時的起點座標和比例尺

int m_hScreen,m_wScreen; //當前檢視的高度和寬度

int m_MapMode; //映像模式

 

在檢視類的建構函式中完成初始化:

m_xStart=0;

m_yStart=0;

blc=1.0;

m_MapMode=1; //映像模式初始化

 

成員變數

m_hScreen,m_wScreen在訊息處理函式OnSize中初始化,當視窗建立或視窗大小發生變化時,OnSize訊息處理函式被呼叫。

為檢視類新增訊息處理函式OnSize();

 

//當檢視的大小變化時被呼叫,cx,cy為變化後螢幕頂長、寬(畫素)

 

為了在應用程式的其他類中能夠使用這兩個座標函式,可以定義兩個全域性函式來實現轉換操作功能。在實現檔案【Drawdoc.cpp】中定義兩個全域性函式如下:

//全域性函式,座標轉換,為了能在檢視類中使用

void DPtoVP(float x,float y,int *X,int *Y);

void VPtoDP(int x,int y,float *X,float *Y);

 

還是在實現檔案【Drawdoc.cpp】中加入這兩個函式的實現程式碼:

void DPtoVP(float x,float y,int *X,int *Y)

{

p_View->DPtoVP(x,y,X,Y);

}

void VPtoDP(int x,int y,float *X,float *Y)

{

p_View->VPtoDP(x,y,X,Y);

}

 

以上兩個全域性函式利用檢視類指標p_View呼叫檢視類的兩個座標轉換函式,來完成座標的轉換操作功能。如果要在某個實現檔案中使用這兩個全域性函式,只需在這個實現檔案的開始處加入全域性函式的外部引用

extern void DPtoVP(float x,float y,int *X,int *Y);

extern void VPtoDP(int x,int y,float *X,float *Y);

在以上的兩個全域性函式中,p_View指向當前啟用的檢視物件。p_View是一個在實現檔案【Drawview.cpp】中全域性定義的檢視類指標:

CDrawView *p_View;

 

在檢視類的過載虛擬函式【OnActiveView】中,對p_View指標進行初始化,以保證p_View指標時刻指向當前啟用的檢視物件:

void CDrawView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView)

{

// TODO: Add your specialized code here and/or call the base class

p_View = this;

CView::OnActivateView(bActivate, pActivateView, pDeactiveView);

}

 

2、實現各圖形元素類的繪製函式

利用虛擬函式來實現各種圖形元素的繪製功能。在圖形元素基類CDraw中,抽象定義一個進行繪製的虛擬函式。因為不需要用【CDraw】類直接來定義物件,所以可以將虛擬函式定義成純虛擬函式。

virtual void Draw(CDC *pDC,int m_DrawMode,int m_DrawMode1,short BackColor)=0;

 

引數說明:

pDC:指向當前繪圖物件的指標

m_DrawMode:繪製模式 1-R2_COPYPEN 2-R2_NOT

m_DrawMode1: 直線繪製方式。0-正常顯示 1-特殊顯示 2-用指定顏色繪製

在各種圖形元素類中,過載虛擬函式。

virtual void Draw(CDC *pDC,int m_DrawMode,int m_DrawMode1,short BackColor);

3.1直線的繪製

在直線類的實現程式碼中,加入過載函式的實現程式碼:

3.2 連續直線和多邊形區域的繪製



3.3 圓和填充圓的繪製



3.4 圓弧的繪製

3.5 標註文字的繪製

IMPLEMENT_SERIAL(CText,CObject,1)

void CText::Draw(CDC *pDC,int m_DrawMode,int m_DrawMode1,short BackColor)

{         

if(b_Delete) //如果已經處於刪除狀態

return;

short ColorPen=m_ColorPen;

if(m_DrawMode1==2) //指定顏色繪製

ColorPen=BackColor;

CFont cjcf;  //定義一個字模

int high,wide,cc1,cc2,cd,angg;

unsigned char c1,c2;

float x1,y1,ang1;

char bz[4];

const char *ls1;

if(m_DrawMode==0)

pDC->SetROP2(R2_COPYPEN);

else if(m_DrawMode==1)

pDC->SetROP2(R2_NOT);  

pDC->SetBkMode(TRANSPARENT);

high=DLtoVL(m_TextHeight); //得到字型的點陣高度

ang1=(float)(m_Angle1*pi/180);

if(high<3||high>200)

return;                 //字型太小或太大將不顯示

x1=m_StartX-m_TextHeight*(float)sin(ang1);

y1=m_StartY+m_TextHeight*(float)cos(ang1);

angg=(int)(m_Angle2*10);

wide=DLtoVL(m_TextWide);

//起始點的螢幕點陣座標

DPtoVP(x1,y1,&cc1,&cc2);

//建立字模

cjcf.CreateFont(high,wide,angg,0,50,0,0,0,255,OUT_TT_PRECIS,CLIP_CHARACTER_PRECIS,DEFAULT_QUALITY,FIXED_PITCH,"cjc");

//選中字模

CFont* cjcbakf=pDC->SelectObject(&cjcf);

pDC->SetBkMode(TRANSPARENT);          //設定顯示方式

pDC->SetTextColor(p_GraphPara->GetColor(ColorPen)); //設定文字顏色

ls1=(const char *)c_Text;                     //文字內容

cd=strlen(ls1);                       //文字字元長度

while(cd>0)  //繪出所有的字元

{

c1=*ls1;

c2=*(ls1+1);

if(c1>127&&c2>127)  //如果是一個漢字

{

strncpy(bz,ls1,2);//拷貝一個漢字到bz

bz[2]=0;

ls1=ls1+2;        //跳過漢字指向下一個字元位置

pDC->TextOut(cc1,cc2,bz); //在螢幕上寫這個漢字

cd=cd-2;                  //字元數減2

//下一個字元的顯示位置

x1=x1+(m_TextWide*2+m_OffWide)*(float)cos(ang1);

y1=y1+(m_TextWide*2+m_OffWide)*(float)sin(ang1);

//下一個字元顯示位置的螢幕座標

DPtoVP(x1,y1,&cc1,&cc2);

}

else //如果是一個西文字元

{

strncpy(bz,ls1,1);       //拷貝一個字元到bz

bz[1]=0;

ls1++;                   //跳過這一個字元到下一個字元

pDC->TextOut(cc1,cc2,bz);//在螢幕上寫字元

cd=cd-1;                 //字元數減1

//下一個字元的顯示位置的實際座標

x1=x1+(m_TextWide+m_OffWide/2)*(float)cos(ang1);

y1=y1+(m_TextWide+m_OffWide/2)*(float)sin(ang1);

//下一個字元顯示位置的螢幕座標

DPtoVP(x1,y1,&cc1,&cc2);

}

}

pDC->SelectObject(cjcbakf);//恢復字模

}

4、檢視類的OnDraw函式。實現檢視

為了實現應用程式的圖形繪製工作,在文件類【CDrawDoc】中定義一個函式如下:

void Draw(CDC *pDC,int m_DrawMode,int m_DrawMode1,short BackColor);

 

在實現函式中加入這個函式的實現程式碼:

void CDrawDoc::Draw(CDC *pDC,int m_DrawMode,int m_DrawMode1,short BackColor)

{

  for(int i=1; i<=5 ; i++)

  {

    int nn = GetGraphUpperBound(i)+1;

while(nn--)

      GetGraph(i,nn)->Draw(pDC,m_DrawMode, m_DrawMode1, BackColor);

  }

}

 

以上函式實現了對5中圖形元素的繪製工作。對於每一類圖形元素,繪製過程如下:

①呼叫GetGraphUpperBound()函式,得到儲存這類圖形元素物件指標的最大陣列下標、

②對所有的圖形元素迴圈,得到指向每一個圖形元素物件的指標。然後通過這個指標呼叫圖形元素類的Draw函式實現圖形元素的繪製操作。

1、為了實現圖形元素在檢視中的繪製,對檢視類的OnDraw函式進行修改,修改後的OnDraw函式實現程式碼如下:

void CDrawView::OnDraw(CDC* pDC)

{

CDrawDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

// TODO: add draw code for native data here

CBrush brush(p_GraphPara->GetColor(m_bColor));  //建立CBrush物件

    CBrush* pOldBrush = pDC->SelectObject(&brush);  //將畫刷選入繪圖物件

pDC->PatBlt(0,0,m_wScreen,m_hScreen,PATCOPY);   //用畫刷填充檢視區域

pDC->SelectObject(pOldBrush);   //恢復原來的畫刷

pDoc->Draw(pDC,0,0,m_bColor);

}

 

OnDraw函式中,呼叫了文件類的Draw函式來繪製所有的圖形元素。

CBrush brush(p_GraphPara->GetColor(m_bColor));  這個函式呼叫的文件類中CGraphPara類的成員函式,

所以需要在檢視類的實現檔案中新增外部引用。

 

參考資料:陳建春,Visual C++開發GIS系統--開發例項剖析。

地理資訊科學

Writed By NX

QQ:1051926720