VC++绘制坐标图.docx
- 文档编号:10461822
- 上传时间:2023-02-13
- 格式:DOCX
- 页数:34
- 大小:402.53KB
VC++绘制坐标图.docx
《VC++绘制坐标图.docx》由会员分享,可在线阅读,更多相关《VC++绘制坐标图.docx(34页珍藏版)》请在冰豆网上搜索。
VC++绘制坐标图
图五、代码效果图
需要注意的是,你也可以相对于客户区域来指定坐标原点
void CExoDraw1View:
:
OnPaint()
{
CPaintDC dc(this); //绘图的设备上下文;
CRect Recto;
//获取客户区尺寸;
GetClientRect(&Recto);
dc.SetViewportOrg(Recto.Width() / 2, Recto.Height() / 2);
// A circle whose center is at the origin (0, 0)
dc.Ellipse(-50, -50, 50, 50);
// A line that starts at (0, 0) and ends at (100, 100)
dc.MoveTo(0, 0);
dc.LineTo(100, 100);
}
图六、代码效果图
现在你已了解了如何设置坐标原点,让我们来将(380,220)点作为坐标原点,并绘制出笛卡尔的坐标轴:
void CExoDraw1View:
:
OnPaint()
{
CPaintDC dc(this); // device context for painting
CRect Recto;
dc.SetViewportOrg(380, 220);
// Use a red pen
CPen PenRed(PS_SOLID, 1, RGB(255, 0, 0));
dc.SelectObject(PenRed);
// A circle whose center is at the origin (0, 0)
dc.Ellipse(-100, -100, 100, 100);
// Use a blue pen
CPen PenBlue(PS_SOLID, 1, RGB(0, 0, 255));
dc.SelectObject(PenBlue);
// Horizontal axis
dc.MoveTo(-380, 0);
dc.LineTo(380, 0);
// Vertical axis
dc.MoveTo(0, -220);
dc.LineTo(0, 220);
}
图七、代码效果图
正如已经看到的,SetViewportOrg()函数可以更改设备上下文的坐标原点,同时,它也用来规定坐标轴的正方向,即水平轴向右,垂直轴向下:
图八、坐标轴示意图
为了说明这一点,下面来绘制一条黄色的45度角的直线:
void CExoDraw1View:
:
OnPaint()
{
CPaintDC dc(this); // device context for painting
dc.SetViewportOrg(380, 220);
// Use a red pen
CPen PenRed(PS_SOLID, 1, RGB(255, 0, 0));
dc.SelectObject(PenRed);
// A circle whose center is at the origin (0, 0)
dc.Ellipse(-100, -100, 100, 100);
// Use a blue pen
CPen PenBlue(PS_SOLID, 1, RGB(0, 0, 255));
dc.SelectObject(PenBlue);
// Horizontal axis
dc.MoveTo(-380, 0);
dc.LineTo(380, 0);
// Vertical axis
dc.MoveTo(0, -220);
dc.LineTo(0, 220);
// An orange pen
CPen PenOrange(PS_SOLID, 1, RGB(255, 128, 0));
dc.SelectObject(PenOrange);
// A diagonal line at 45 degrees
dc.MoveTo(0, 0);
dc.LineTo(120, 120);
}
图九、代码效果图
正如你所看到的,我们的直线没有在45度位置,而是位于坐标系统的第四象限,造成这种情况的原因是默认的坐标系统。
三、固定映射模式
为了控制设备上下文中的坐标轴的方向,可以使用CDC类的SetMapMode()函数,它的语法如下:
int SetMapMode(int nMapMode);
这个函数将根据参数的设置的不同做两件事,一是控制坐标轴的方向;二是坐标系统的单位长度。
这个函数的参数是用来定义映射模式的整型常量。
它可能的值是:
MM_TEXT, MM_LOENGLISH、MM_HIENGLISH、MM_ANISOTROPIC、MM_HIMETRIC, MM_ISOTROPIC、 MM_LOMETRIC, MM_TWIPS。
默认情况下使用MM_TEXT映射模式。
换句话说,如果你没有具体的规定某一映射模式,你的应用程序就将使用MM_TEXT映射模式。
在这种映射模式下,设备上下文中的度量尺寸将使用默认的像素单位,水平坐标轴正方向向右,垂直坐标轴正方向向下。
例如,上面的OnPaint事件可以用下面的代码重写,它将产生同样的效果,仿佛没有使用映射模式。
void CExoDraw1View:
:
OnPaint()
{
CPaintDC dc(this); // device context for painting
dc.SetMapMode(MM_TEXT);
dc.SetViewportOrg(380, 220);
// Use a red pen
CPen PenRed(PS_SOLID, 1, RGB(255, 0, 0));
dc.SelectObject(PenRed);
// A circle whose center is at the origin (0, 0)
dc.Ellipse(-100, -100, 100, 100);
// Use a blue pen
CPen PenBlue(PS_SOLID, 1, RGB(0, 0, 255));
dc.SelectObject(PenBlue);
// Horizontal axis
dc.MoveTo(-380, 0);
dc.LineTo(380, 0);
// Vertical axis
dc.MoveTo(0, -220);
dc.LineTo(0, 220);
// An orange pen
CPen PenOrange(PS_SOLID, 1, RGB(255, 128, 0));
dc.SelectObject(PenOrange);
// A diagonal line at 45 degrees
dc.MoveTo(0, 0);
dc.LineTo(120, 120);
}
图十、代码效果图
MM_LOENGLISH模式,与其他一些映射模式(不包括MM_TEXT模式)一样,执行两个动作,它改变坐标轴的方向,垂直坐标轴的正方向向上;
图十一、MM_LOENGLISH映射模式下的坐标系
此外,度量单位改为0.01英寸,这意味着你提供的坐标将除以100,观察上述代码的MM_LOENGLISH映射效果
void CExoDraw1View:
:
OnPaint()
{
CPaintDC dc(this); // device context for painting
dc.SetMapMode(MM_LOENGLISH);
dc.SetViewportOrg(380, 220);
. . .
}
图十二、代码效果图
正如你所看到的,直线现在位于坐标系的第一象限,同时,直线比以前缩短,圆也比以前的要小。
与MM_LOENGLISH映射模式相似,MM_HIENGLISH映射模式也是垂直坐标轴正向向上,只是它以0.001英寸为坐标单位,下面是它的效果:
void CExoDraw1View:
:
OnPaint()
{
CPaintDC dc(this); // device context for painting
dc.SetMapMode(MM_HIENGLISH);
dc.SetViewportOrg(380, 220);
. . . Same as previous
}
图十三、代码效果图
MM_LOMETRIC映射模式使用与上两种映射模式相同的坐标轴,不同的是MM_LOMETRIC使用0.1毫米为单位,下面是一个例子:
void CExoDraw1View:
:
OnPaint()
{
CPaintDC dc(this); // device context for painting
dc.SetMapMode(MM_LOMETRIC);
dc.SetViewportOrg(380, 220);
. . .
}
图十四、代码效果图
MM_HIMETRIC使用与上述三种映射模式相同的坐标系,但它的坐标单位是0.01毫米,下面例子代码如下:
void CExoDraw1View:
:
OnPaint()
{
CPaintDC dc(this); // device context for painting
dc.SetMapMode(MM_HIMETRIC);
dc.SetViewportOrg(380, 220);
. . . Same as previous
}
图十五、代码效果图
MM_TWIPS映射模式将每个逻辑单位(像素)除以20,实际上一twip等于1/1440 英寸,坐标系统仍然与上面几种映射方式相同。
void CExoDraw1View:
:
OnPaint()
{
CPaintDC dc(this); // device context for painting
CRect Recto;
dc.SetMapMode(MM_TWIPS);
dc.SetViewportOrg(380, 220);
. . .
}
图十六、代码效果图
四、自定义坐标系统
目前为止,我们使用的映射模式可以允许我们选择坐标轴的方向,但仅仅是Y轴的方向。
而且,我们不能更改坐标系统的单位,这是因为各种映射模式(MM_TEXT, MM_HIENGLISH, MM_LOENGLISH, MM_HIMETRIC, MM_LOMETRIC, and MM_TWIPS)有固定的属性集,例如坐标轴的方向和坐标单位等。
在CAD应用程序中,如果你需要灵活设置坐标轴方向及坐标单位的话,应该怎么做呢?
仔细研究下面的OnPaint()事件代码,它绘制了一个200X200像素大小的红边、浅绿色背景的正方形,这个正方形的顶点在(-100,-100)处,右底端位于(100,100)处。
同时,从坐标原点处绘制一个45度的直线。
void CExoDraw1View:
:
OnPaint()
{
CPaintDC dc(this); // device context for painting
CPen PenRed(PS_SOLID, 1, RGB(255, 0, 0));
CBrush BrushAqua(RGB(0, 255, 255));
dc.SelectObject(PenRed);
dc.SelectObject(BrushAqua);
// Draw a square with a red border and an aqua background
dc.Rectangle(-100, -100, 100, 100);
CPen BluePen(PS_SOLID, 1, RGB(0, 0, 255));
dc.SelectObject(BluePen);
// Diagonal line at 45 degrees starting at the origin (0, 0)
dc.MoveTo(0, 0);
dc.LineTo(200, 200);
}
图十七、代码效果图
正如你所看到的,我们只得到了正方形的右下部分,同时直线指向时钟的三点到六点之间的方向。
假定你想将坐标原点设置与窗口中央位置,或者是更精确一点,设置于点(340, 220)处,我们已经知道可以使用CDC:
:
SetViewportOrg()(记住,这个函数只用来更改坐标原点,它并不影响坐标轴的方向及坐标单位。
同时,需要注意的是,它使用的坐标单位是像素)函数,下面是一个例子(我们没有规定映射模式,所以程序使用的是默认的MM_TEXT映射模式)。
void CExoDraw1View:
:
OnPaint()
{
CPaintDC dc(this); // device context for painting
dc.SetViewportOrg(340, 220);
CPen PenRed(PS_SOLID, 1, RGB(255, 0, 0));
CBrush BrushAqua(RGB(0, 255, 255));
dc.SelectObject(PenRed);
dc.SelectObject(BrushAqua);
// Draw a square with a red border and an aqua background
dc.Rectangle(-100, -100, 100, 100);
CPen BluePen(PS_SOLID, 1, RGB(0, 0, 255));
dc.SelectObject(BluePen);
// Diagonal line at 45 degrees starting at the origin (0, 0)
dc.MoveTo(0, 0);
dc.LineTo(200, 200);
}
图十八、代码效果图
为了控制你自己应用程序中的坐标系统单位,坐标轴的方向,可以使用MM_ISOTROPIC 或MM_ANISOTROPIC映射模式。
第一件事是调用CDC:
:
SetMapMode()函数,并在两个常量中选择一个(MM_ISOTROPIC或 MM_ANISOTROPIC)。
下面是例子代码:
void CExoDraw1View:
:
OnPaint()
{
CPaintDC dc(this); // device context for painting
dc.SetMapMode(MM_ISOTROPIC);
dc.SetViewportOrg(340, 220);
CPen PenRed(PS_SOLID, 1, RGB(255, 0, 0));
CBrush BrushAqua(RGB(0, 255, 255));
dc.SelectObject(PenRed);
dc.SelectObject(BrushAqua);
// Draw a square with a red border and an aqua background
dc.Rectangle(-100, -100, 100, 100);
CPen BluePen(PS_SOLID, 1, RGB(0, 0, 255));
dc.SelectObject(BluePen);
// Diagonal line at 45 degrees starting at the origin (0, 0)
dc.MoveTo(0, 0);
dc.LineTo(200, 200);
}
图十九、代码效果图
先抛开上面的图片。
当调用CDC:
:
SetMapMode(),并使用MM_ISOTROPIC或 MM_ANISOTROPIC作为参数后,并没有结束,这两种映射方式允许我们改变坐标轴的正方向及坐标单位。
这两种映射方式的区别在于:
MM_ISOTROPIC映射方式中水平、垂直坐标轴的单位相等,MM_ANISOTROPIC映射方式可以随意控制水平及垂直方向的坐标单位长度。
所以,在调用SetMapMode()函数并规定了MM_ISOTROPIC或MM_ANISOTROPIC映射模式后,你必须调用CDC:
SetWindowExt()函数,这个函数用来计算老的或默认的坐标系中一个单位的长度。
这个函数有两个版本:
CSize SetWindowExt(int cx, int cy);
CSize SetWindowExt(SIZE size);
如果使用第一版本,第一个参数CX说明了水平坐标轴上按照新的逻辑单位代表的长度,CY代表了垂直坐标轴上按照新的逻辑单位代表的长度。
如果你知道按照新的坐标单位计算需要的逻辑尺寸的话,可以使用第二个版本的函数,例子代码如下:
void CExoDraw1View:
:
OnPaint()
{
CPaintDC dc(this); // device context for painting
dc.SetMapMode(MM_ISOTROPIC);
dc.SetViewportOrg(340, 220);
dc.SetWindowExt(480, 480);
CPen PenRed(PS_SOLID, 1, RGB(255, 0, 0));
CBrush BrushAqua(RGB(0, 255, 255));
dc.SelectObject(PenRed);
dc.SelectObject(BrushAqua);
// Draw a square with a red border and an aqua background
dc.Rectangle(-100, -100, 100, 100);
CPen BluePen(PS_SOLID, 1, RGB(0, 0, 255));
dc.SelectObject(BluePen);
// Diagonal line at 45 degrees starting at the origin (0, 0)
dc.MoveTo(0, 0);
dc.LineTo(200, 200);
}
图二十、代码效果图
调用SetWindowExt()函数后,紧接着应调用SetViewportExt()函数,它的任务是规定水平及垂直坐标轴的单位。
我们可以这样认为,SetWindowExt()函数对应着“窗口”,SetViewportExt()函数对应着“视口”。
SetViewportExt()函数有两个版本:
CSize SetViewportExt(int cx, int cy);
CSize SetViewportExt(SIZE size);
上述两个函数中的参数与“窗口”中的尺寸是相互对应的,它的单位是像素。
为了进一步说明这两个函数的使用,我对这两个函数进行了重新说明:
SetWindowExt(int Lwidth, int Lheight) //参数的单位为逻辑单位(Logical);
SetViewportExt(int Pwidth, int Pheight) //参数的单位为像素(Pixel);
以x轴为例(y轴类似),逻辑坐标系中的x轴的单位刻度=| Pwidth | / | Lwidth |。
这表示x轴上一个逻辑单位等于多少个像素。
比如我们先通过GetDeviceCap(LOGPIXELSX)获得在我们的显示器上每英寸等于多少个像素,设为p,然后我们将它赋给Pwidth,将Lwidth赋成2,即Pwidth / Lwidth=p / 2。
那么,此时逻辑坐标系x轴上的单位刻度就是p / 2个像素;又由于p个像素是代表一个英寸的,所以此时的逻辑坐标系x轴上的单位刻度同时也是半个英寸。
还有一点要注意的是,如果Lwidth与Pwidth同号,逻辑坐标的x轴方向与设备坐标系中的x轴方向相同,否则相反。
此外,当使用MM_ISOTROPIC模式时,如果通过计算window与viewport范围的比值得到两个方向的单位刻度值不同,那么将会以较小的那个为准。
下面是一个例子:
void CExoDraw1View:
:
OnPaint()
{
CPaintDC dc(this); // device context for painting
dc.SetMapMode(MM_ISOTROPIC);
dc.SetViewportOrg(340, 220);
dc.SetWindowExt(480, 480);
dc.SetViewportExt(440, -680);
CPen PenRed(PS_SOLID, 1, RGB(255, 0, 0));
CBrush BrushAqua(RGB(0, 255, 255));
dc.SelectObject(PenRed);
dc.SelectObject(BrushAqua);
// Draw a square with a red border and an aqua background
dc.Rectangle(-100, -100, 100, 100);
CPen BluePen(PS_SOLID, 1, RGB(0, 0, 255));
dc.SelectObject(BluePen);
// Diagonal line at 45 degrees starting at the origin (0, 0)
dc.MoveTo(0, 0);
dc.LineTo(200, 200);
}
图二十一、代码效果图
五、实例代码
为了灵活使用逻辑坐标系,下面给出了几个例子代码:
例1:
绘制带箭头的坐标轴
void CExoDraw1View:
:
OnPaint()
{
CPaintDC dc(this); // device context for painting
CBrush bgBrush(BLACK_BRUSH);
dc.SelectObject(bgBrush);
dc.Rectangle(Recto);
dc.SetMapMode(MM_ISOTROPIC);
dc.SetViewportOrg(
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- VC 绘制 标图