您的位置:首页 > 其它

(1)一步一步开发一个简单二维CAD之基本框架

2008-09-11 14:55 513 查看
在学校没事,所以开发一个具有基本功能的二维CAD,具有画线,画矩形,画圆,有捡选,平移,旋转,镜像,删除,实时放大,缩小,串行化的功能

首先谈架构,架构采用流行的MVC架构,也就是模型,视图,控制器的架购,模型包括数据和对数据的操作,而视图则是对模型的显示,控制器则是根据界面的操作.

(1)为了开发方便,首先开发了两个数学工具类,以便于使用

点类和包围盒类

class CBox2D;

class CPosition

{

public:

CPosition();

CPosition(float x, float y);

virtual ~CPosition();

public:

float verdistance(CPosition &begin, CPosition &end);

float Distance(const CPosition pos);

BOOL IsBox(const CBox2D &pox);

CPosition Rotate(const CPosition &base, float angle);

CPosition Explan(const CPosition &base, float scale);

CPosition Mirror(CPosition &first, CPosition &second);

CPosition Move(CPosition &first, CPosition &second);

float AagleTox();

void Get2Point(double circel[2]);

CPosition operator-(CPosition pos);

CPosition operator+(CPosition pos);

void operator-=(CPosition pos);

void operator+=(CPosition pos);

CPosition operator*(float scale);

private:

float m_x;

float m_y;

};

class CBox2D

{

public:

CBox2D();

CBox2D(CPosition min, CPosition max);

virtual ~CBox2D();

public:

void GetExBox2D(float distance);//扩张包围

private:

CPosition m_min;

CPosition m_max;

};

两个类的实现如下

#define IP 3.1415926

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

// Construction/Destruction

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

CBox2D::CBox2D()

{

}

CBox2D::~CBox2D()

{

}

CBox2D::CBox2D(CPosition min, CPosition max)

{

m_min = min;

m_max = max;

}

void CBox2D::GetExBox2D(float distance)//扩张包围盒,当直线是水平或者垂直的时候,不存在包围盒,所以要包围对角点平移,以适应这种情况

{

m_min.m_x -= distance;

m_min.m_y -= distance;

m_max.m_x += distance;

m_max.m_y += distance;

}

CPosition::CPosition()

{

}

CPosition::CPosition(float x, float y)

{

m_x = x;

m_y = y;

}

CPosition::~CPosition()

{

}

float CPosition::verdistance(CPosition &begin, CPosition &end)//利用三维叉集计算二维距离,Z坐标为0

{

float a = fabsf( (m_x - begin.m_x) * (end.m_y - begin.m_y) - (m_y - begin.m_y) * (end.m_x - begin.m_x) );

float b = sqrt( (end.m_x - begin.m_x) * (end.m_x - begin.m_x) + (end.m_y - begin.m_y) * (end.m_y - begin.m_y) );

return a/b;

}

BOOL CPosition::IsBox(const CBox2D &pox)

{

if (m_x >= pox.m_min.m_x && m_y >= pox.m_min.m_y && m_x <= pox.m_max.m_x && m_y <= pox.m_max.m_y)

return TRUE;

else

return FALSE;

}

CPosition CPosition::Rotate(const CPosition &base, float angle)//沿一点旋转angle度,逆时针为正

{

float x = (m_x - base.m_x) * cos(angle) - (m_y - base.m_y) * sin(angle) + base.m_x;

float y = (m_x - base.m_x) * sin(angle) + (m_y - base.m_y) * cos(angle) + base.m_y;

return CPosition(x, y);

}

CPosition CPosition::Explan(const CPosition &base, float scale)

{

*this = (*this - base) * scale + base;

return *this;

}

CPosition CPosition::Move(CPosition &first, CPosition &second)//沿两点方向平移

{

CPosition pos;

pos = second - first;

*this += pos;

return *this;

}

CPosition CPosition::operator-(CPosition pos)

{

return CPosition(m_x - pos.m_x, m_y - pos.m_y);

}

CPosition CPosition::operator+(CPosition pos)

{

return CPosition(m_x + pos.m_x, m_y + pos.m_y);

}

void CPosition::operator-=(CPosition pos)

{

m_x -= pos.m_x;

m_y -= pos.m_y;

}

void CPosition::operator+=(CPosition pos)

{

m_x += pos.m_x;

m_y += pos.m_y;

}

float CPosition::Distance(const CPosition pos)

{

return sqrt( (m_x - pos.m_x) * (m_x - pos.m_x) + (m_y - pos.m_y) * (m_y - pos.m_y) );

}

float CPosition::AagleTox()//

{

float cosv = m_x/sqrt(m_x * m_x + m_y * m_y);

float sinv = m_y/sqrt(m_x * m_x + m_y * m_y) ;

if(sinv >= 0)

return acos(cosv) ;

else if(sinv < 0)

return 2.*IP-acos(cosv) ;

return FALSE ;

}

CPosition CPosition::operator*(float scale)

{

return CPosition(m_x * scale, m_y * scale);

}

CPosition CPosition::Mirror(CPosition &first, CPosition &second)

{

CPosition pos = (second - first) * ( 1 / second.Distance(first) );//镜像线单位化

CPosition pos1 = *this - first;//第一起点和镜像点之间的矢量

float pos2 = pos1.m_x * pos.m_x + pos1.m_y * pos.m_y;

return (first + pos * pos2 ) * 2 - *this;

}

世界坐标,也就是我们在现实中实际看到的物体的坐标

客户坐标,也就是我们屏幕客户区的坐标

我们一切点的坐标,必需在这两个坐标之间转换

这两个函数可以放在CView的派生类里面



void CMcadView::DPTOWP(CPoint &point, CPosition &pos)//m_base_x, m_base_y观察坐标系的基点坐标,m_scale是观察坐标和客户转换的系数

{

CRect rect;

GetClientRect(&rect);

pos.m_x = point.x * m_scale + m_base_x;

pos.m_y = (rect.Height() - point.y) * m_scale + m_base_y;

}

void CMcadView::WPTODP(CPosition &pos, CPoint &point)

{

CRect rect;

GetClientRect(&rect);

point.x = (int)(pos.m_x - m_base_x)/m_scale;

point.y = rect.Height() - (int)(pos.m_y - m_base_y)/m_scale;

}

所有的一切鼠标在屏幕上的操作,必需用这两个函数转换成实际坐标,而所有的实际坐标屏幕上显示的时候,都必需转换为

屏幕坐标
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: