在学校没事,所以开发一个具有基本功能的二维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;
}
所有的一切鼠标在屏幕上的操作,必需用这两个函数转换成实际坐标,而所有的实际坐标屏幕上显示的时候,都必需转换为
屏幕坐标