通用多边形管理例程






4.25/5 (5投票s)
2001年10月25日
5分钟阅读

86946

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
将意味着使用上一次变换;如果没有执行过任何变换,变换集将为空,并且不会出现任何绘图。