65.9K
CodeProject 正在变化。 阅读更多。
Home

通用多边形管理例程

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.25/5 (5投票s)

2001年10月25日

5分钟阅读

viewsIcon

86946

downloadIcon

1449

一个让处理多边形更简单的类。

引言

最近我发现自己画了很多简单的多边形,比如轮廓形状。问题是这些形状需要以各种不同的旋转方式显示。其中一种形状是一个漂亮的指南针箭头,我在我的配套文章中使用了它来制作自注册自定义控件。完整的控件在这里重现。这篇文章主要讲的是我如何制作一个漂亮的旋转箭头。

这里的想法是创建一个指南针,它指向一个物体前进的方向,使用地理坐标。绘图的许多细节将在配套文章中讨论。 

为了创建这些简单的单色形状,我花了几小时编写了一个简单的编辑器,允许我输入一组x,y坐标。不需要鼠标,没有什么特别复杂的东西,但所有我需要的是x,y坐标的列表,而不是图元文件或其他什么复杂的东西。我最复杂的一幅画有大约20个端点。我使用了我写的那个矢量编辑器程序,它也在一篇配套文章中进行了描述。

这是定义指南针针头的点集。名义坐标系是一个100单位的坐标系,范围是±50。

-14, 30
-5, 38
0, 46
5, 38
14, 30
4, 34
4, -36
14,-46
0, -40
-14, -46
-4,-36
-4, 34

Polygon.h

class CPolygon
   { 
    public:
       CPolygon() { heading = 0.0; scaling = 1.0; }
       BOOL Read(const CString & filename);
       BOOL Load(UINT resid);
       BOOL Load(LPCTSTR resource);
       CRect GetInputBB();
       CRgn * GetRgn();
       CRect Transform(double angle, double scale);
       void Draw(CDC & dc, CDoublePoint pt);
       bool IsDefined() { return points.GetSize() > 0; }
    protected:
       CArray<CDoublePoint, CDoublePoint> points;
       double heading; // current angle
       double scaling;
       CArray<CPoint, CPoint> transformed;
   };

CPolygon::CPolygon

CPolygon::CPolygon()

构造函数。初始化多边形。多边形不包含任何点。

CPolygon::Read

BOOL CPolygon::Read(const CString & filename)
const CString & filename 要读取的文件的名称。

从指定文件中读取一组点。如果发生错误,则返回FALSE。如果发生错误,points数组的内容未定义。输入时只进行最小的语法检查,因为假定输入来自程序。

CPolygon::Load

BOOL CPolygon::Load(UINT resid)
BOOL CPolygon::Load(LPCTSTR resourcename)
UINT resid POINTS资源的资源ID
LPCTSTR resourcename POINTS资源的名称

从资源段加载一组点。资源段类型必须是POINTS。两种形式决定名称是数字资源ID还是字符串名称。

要将一组点包含在资源段中,请将以下样式的声明添加到\res\projectname.rc2文件中

resource_name POINTS DISCARDABLE "\\res\\filename"

例如,为了添加箭头资源,我这样做了

IDP_ARROW POINTS DISCARDABLE "\\res\\arrow.pln"

因为我没有定义符号,比如

#define IDP_ARROW 1101

我使用了该方法的LPCTSTR版本。

将文件(在本例中是arrow.pln)复制到项目目录下的\\res子目录中。

CPolygon::GetInputBB

CRect CPolygon::GetInputBB( )

返回一个CRect,它表示多边形在读入时(在进行任何旋转变换之前)的边界框。边界框是完全包含对象所有点的最小矩形。

CPolygon::GetRgn

CRgn * CPolygon::GetRgn( )

返回变换后的(旋转和缩放后的)多边形的区域。这可以用来使对象占据的区域无效。

CPolygon::Transform

CRect Transform(double angle, double scale, BOOL force = FALSE)
double angle 旋转角度,以地理坐标表示
double scale 缩放因子。这被解释为相对于定义时读入的点。
BOOL force 强制重新计算,即使内部优化确定现有的变换后点集是有效的。

这将根据指定的角度(以地理坐标表示,0.0为北,90.0为东,180.0为南,270.0为西)和缩放来变换多边形点。结果是一个内部结构,包含变换后的点,适用于Draw方法。返回的CRect是变换后点的边界矩形,或者矩形(0,0,0,0)。作为一种优化,如果角度和缩放与上一次Transform调用相同,则不计算任何内容,并返回(0,0,0,0)。如果你需要强制重新计算以获得边界框返回值,请使用第三个参数force,并将其设置为TRUE,这将绕过优化。

请注意,CRect是以映射坐标表示的,y值向上增加,x值向右增加;假设点围绕一个逻辑对象中心的0,0轴居中。因此,IsRectEmpty将始终返回TRUE。如果你需要检查一个空矩形,你可能需要先创建一个副本,并在副本上调用NormalizeRect方法(如果你不需要保留CRect,你可以对结果调用NormalizeRect)。

必须在执行Draw方法之前调用此方法。Draw将始终根据Transform建立的当前变换来绘制多边形。如果自数据加载以来没有调用Transform,则变换后的点数组为空。

变换是根据下图中所示的变换矩阵进行的,围绕中心点0,0的经典旋转。给定两点x,y,x方向的缩放sx,y方向的缩放sy,新点x',y'根据以下矩阵乘法计算

             _                   _
            |  cos Ø    sin Ø  0  |
     [x y 0]|  -sin Ø   cos Ø  0  |=[sx*((cos Ø)*x-(sin Ø)*y)
            |_    0     0      0 _|  sy*((sin Ø)*x+(cos Ø)*y) 0]

(第三列是为了使矩阵乘法正确而添加的,然后被丢弃)。

在我的情况下,我只允许各向同性(sx == sy)缩放。

CPolygon::IsDefined

BOOL CPolygon::IsDefined( )

如果多边形由一组点定义,则返回TRUE。如果点数组为空,则返回FALSE。请注意,如果读取时出错,点数组通常是空的。

CPolygon::Draw

void CPolygon::Draw(CDC & dc, CDoublePoint pt)
CDC & dc 用于绘制对象的DC。 
CDoublePoint pt 在DC中绘制图像的点,以逻辑坐标表示。

在指定的DC中,在由点指定的_位置_绘制变换后的多边形。假定DC处于y值向上(而不是向下,如MM_TEXT模式)增加的映射模式。返回时DC不变。必须在调用Draw之前调用Transform方法来创建变换后的点集。未能调用Transform将意味着使用上一次变换;如果没有执行过任何变换,变换集将为空,并且不会出现任何绘图。

© . All rights reserved.