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

生成美观的线条样式

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.40/5 (6投票s)

2008 年 4 月 6 日

CPOL

4分钟阅读

viewsIcon

47101

downloadIcon

1122

一种创建复杂线条图案的新颖方法

引言

这项技术是一种创新的生成美观线型的方式。它主要用于 CAD/GIS 及相关应用,这些应用需要自定义线型。它完全使用 MFC 编写,并且非常易于使用。

背景

我一直在研究如何创建自定义线型。我生成此类线型的努力包括:

  • 使用矢量图形沿给定线布置。这涉及到复杂的矩阵数学。但它效率低下,无法应用于填充的几何实体。
  • 使用分形几何,这也证明是不明智的,因为它需要为我感兴趣的每种线条图案发明一个新公式。
  • 我偶然发现了一个使用 LineDDA 的文章来生成复杂的线型,该文章涉及使用回调函数来绘制复杂的线型。此技术是 Win32 解决方案,目前不直接受 MFC 支持。尽管它是一个出色的解决方案,但它并非万无一失,我得到了不理想的输出。例如,当我选择字符“X”作为线条图案的输入时,输出如下:(图 1 & 2)
LineDDARight.JPG LineDDAWrong.JPG
图 1. 理想的输出
图 2. 错误的输出

这促使我致力于开发一种更简单、更优雅、不会给普通程序员增加智力负担的 MFC 解决方案。我使用了 TrueType(.ttf)字体来生成线型。字体中的每个 字形 都可以用作线条的图案。

技巧

CaracterMap.JPG
图 3:Windows 中的字符映射

使用 Microsoft 的字符映射应用程序(开始 > 所有程序 > 附件 > 系统工具 > 字符映射)并从所需的字体中选择一个字符或符号(代表您的线型的图案)。每个符号都有一个唯一的十六进制数字与之关联。我们在逻辑中使用这个十六进制数字。上面图像中突出显示的符号的十六进制数字是 0x5C。请参见图 3

注意:我计划通过使用此网站上Hans Dietrich撰写的文章《XCharMap - 用于显示字符映射的对话框》中的代码来扩展此应用程序。

您可以使用 CorelDraw、Font Creator 或 Fontlab 等字体创建工具,设计自己的 TrueType 字体符号图案。将您创建的字体复制到 Windows 目录的Fonts文件夹中。这可以通过进入控制面板中的Fonts文件夹来完成。

理解代码

我采用了 Jeff Prosise 的《Programming Windows with MFC》第三章中绘制橡皮筋线的代码,此处不再赘述。核心逻辑在视图类的OnLButtonUp中。

要沿着绘制的线布置所需的图案,首先,计算线的斜率以及线相对于水平线的夹角。

//calculate the slope of this line
if(point.x-m_ptFrom.x==0) return;//Avoid crashes due to infinity

float slope= -(point.y -m_ptFrom.y)/(point.x-m_ptFrom.x);
//Negative sign is used as the slope from math.h is in clockwise direction, while the 
//LOGFONT expects angle in counter-clockwise direction.

//find the inclination w.r.t horizontal 
float ang=atan2(m_ptFrom.y-point.y,point.x-m_ptFrom.x)*180.0f/3.1415927f;

将角度分配给LOGFONT变量的 Orientation 和 Escapement 属性。选择感兴趣的字体,并将字符/符号的十六进制值赋给CString变量。

LOGFONT lf;
lf.lfCharSet=SYMBOL_CHARSET;//For Symbol Fonts like "Wingdings" 
lf.lfHeight=20;
lf.lfEscapement=(long)ang*10;//Angle of the text
lf.lfOrientation=(long)ang*10;//Angle of the text
lf.lfItalic=false;
lf.lfStrikeOut=false;
lf.lfUnderline=false;
lf.lfQuality=ANTIALIASED_QUALITY;
lf.lfWeight=FW_BOLD;
strcpy(lf.lfFaceName,_T("Wingdings"));//Select the desired font

--
--
--        
CString str;
str=0x5c;//Hexadecimal value of the desired //character/symbol from Character Map

找到线段的长度,并重复地将字符/符号的十六进制值添加到CString变量中,直到string的宽度小于线的长度。绘制文本,我们就得到了惊人的线条图案。

//Calculate Length of line segment in pixels 
float dist= sqrt((point.y - m_ptFrom.y  )*(point.y-m_ptFrom.y  )+
			(point.x-m_ptFrom.x)*(point.x-m_ptFrom.x)) ;
    
//Add Symbol to the text until the width of string is less than length of  line
while(textwidth < dist )
{
    str+=0x5c;
    textwidth=dc.GetTextExtent(str).cx;
}

运行应用程序

在 VS6 中编译源代码并生成它(或)使用AestheticLines_Demo.zip中的可执行文件。单击并拖动以绘制橡皮筋线。请注意,通过简单地颠倒绘制顺序,我们可以获得反转的符号。请参见下面的图 4

AestheticLines.JPG
图 4:生成的线条图案

进一步改进

  • 从应用程序中调用的字符映射对话框中选择所需的符号。(我将就此与Hans Dietrich联系。)
  • 扩展绘图逻辑,使用户能够绘制折线图和多边形。
  • 提供一个对话框,用于选择字体大小、颜色、对齐方式等。

参考文献

致谢

  • Pravin Ramdas Raijade

历史

  • 2008年4月6日:首次发布

我希望这篇文章有用。请随意扩展、修复错误和改进它。如果您能在您的程序或文档中注明我,那将是很好的。

© . All rights reserved.