二:建立幾何元素對象類:
AutoCAD字體輪廓由圓弧和多義線(幾個點順次連接形成的一條曲線)的集合構成,圓弧和多義線具有一些相同的屬性和方法,比如繪制,如果進一步開發,還可能有相關的線型和顏色等等屬性,要把這些公共的屬性和方法抽象出來,形成基類。
首先形成三維點結構以及對它的封裝:
struct READSHX_API MYXYZ
{
double x;
double y;
double z;
};
class READSHX_API CMyXYZ:public MYXYZ
{
public:
CMyXYZ(){x=0;y=0;z=0;};
CMyXYZ(MYXYZ xyz){this->x=xyz.x;this->y=xyz.y;this->z=xyz.z;};
CMyXYZ(double x,double y,double z){ this->x=x;this->y=y;this->z=z;};
virtual ~CMyXYZ(){};
Operator MYXYZ() const{return MYXYZ(*this);};
const CMyXYZ& Operator =(MYXYZ &xyz){this->x=xyz.x;this->y=xyz.y;this->z=xyz.z;return *this;};
};
點數據用double數來表示並且使用三維點便於日後該結構體的重用性更廣泛,而從MYXYZ結構體派生出類CMyXYZ可以方便地對MYXYZ結構進行管理,比如所有參數中使用MYXYZ結構體的函數,都可以直接應用CMyXYZ類對象代替,CMyXYZ(MYXYZ xyz)聲明了該類的拷貝構造函數,使得兩個CMyXYZ類對象能夠互相直接賦值,比如:
MYXYZ xyz1;
xyz1.x=0;
xyz1.y=1;
xyz1.z=2;
CMyXYZ xyz2=xyz1;
最後一行的操作使用了CMyXYZ(MYXYZ xyz);函數,注意這個操作並沒有使用const CMyXYZ& operator =(MYXYZ &xyz)函數,這個函數在初始化以外的地方使用,比如xyz2已經聲明了,這時我在執行xyz2=xyz1;操作,就是使用重載等號操作符的定義了,當然,如果沒有重載等號操作符,則還會使用拷貝構造函數。CMyXYZ(double x,double y,double z);構造函數多用於臨時的點對象當作參數,比如Line(CMyXYZ(0,0,0),CMyXYZ(100,100,0));這樣就不必事先聲明兩個點了,Operator MYXYZ() const;操作將CMyXYZ對象直接轉化為MYXYZ對象,有了這個操作符轉化,就可以將CMyXYZ的對象直接賦值給MYXYZ對象了。
上面這些構造函數以及操作符重載的方式再C++中廣泛應用,希望讀者對其能夠深入了解。
下面聲明幾何元素基類
class READSHX_API CMyBase
{
protected:
CMyBase(){};
public:
virtual int GetType()=0;
virtual int Draw(long lDevice)=0;
virtual ~CMyBase(){};
};
CMyBase類的構造函數聲明成保護類型可以防止用戶直接創建CMyBase對象,使其只能用於派生其他類。
而純虛函數virtual int GetType()=0;和virtual int Draw(long lDevice)=0;保證了所有從CMyBase類派生的類必須重載這兩個成員函數,以得到一個幾何元素的類型(比如這個幾何元素是一個多義線還是一個圓弧)以及在指定的設備上進行繪制。注意virtual int Draw(long lDevice)=0中設備的描述使用了簡單的long型而不是HDC或者CDC等類型,這也是考慮到接口的擴充性,比如該程序在其他操作系統中可能找不到HDC的定義,因此只是使用了一個long型參數描述設備屬性,這在Windows操作系統中可以把HDC或者CDC指針強制轉化成long數傳入參數。
在多義線類中,要有一個多義線頂點指針的列表成員,列表采用標准C++模板庫(STL)中的list實現,這樣的話,可以方便地向列表中添加元素,以及遍歷該列表
使用起來list的方法一般是這樣子:
#pragma warning(disable:4786)
#pragma warning(disable:4251)
#pragma warning(disable:4273)
//上面這三行是為了去掉使用STL過程中容易出現的一些警告,注意要放在STL包括文件的前面才起作用
#include <list>
using namespace std;
typedef list<MYXYZ *> MYPOLYLN; //定義了一個點指針的列表,注意考慮效率問題,STL容器一般存放指針
至於具體用法參見接下來的源程序:
#define ISARC 1
#define ISPOLYLN 2
#define ISSHAPE 3
//聲明一個圓弧類
class READSHX_API CMyBase
{
protected:
CMyBase(){};
public:
virtual int GetType()=0;
virtual int Draw(long lDevice)=0;
virtual ~CMyBase(){};
};
class READSHX_API CMyArc:public CMyBase
{
public:
virtual int Draw(long lDevice);
CMyArc(MYXYZ i_pc,MYXYZ i_ps,MYXYZ i_pe);
virtual int GetType(){return ISARC;};
CMyArc(){};
virtual ~CMyArc(){};
MYXYZ m_pc;
MYXYZ m_ps;
MYXYZ m_pe;
};
typedef list<MYXYZ *> MYPOLYLN;
//聲明一個多義線類
class READSHX_API CMyPolyLn: public CMyBase
{
public:
virtual int Draw(long lDevice);
virtual int GetType(){return ISPOLYLN;};
virtual int AddPoint(MYXYZ* pxyz);
CMyPolyLn(){m_PolyLn.clear();};
virtual ~CMyPolyLn();
MYPOLYLN m_PolyLn;
};
//聲明一個字型類,其實就是一個幾何對象的集合
class READSHX_API CShape : public CMyBase
{
public:
virtual int Draw(long lDevice);
virtual int GetType(){return ISSHAPE;};
CShape(){m_List.clear();};
virtual ~CShape();
list<CMyBase*> m_List;
};