显示线符号指将简单的线型或复杂的符号去绘制线物标或面物标的边界。S-52标准规定,线的标准宽度为0.32mm,当线宽度大于0.6mm时,应对线段结合点作平滑处理。
线符号显示在涉及到两个命令:LS
和LC
1. TS
简单线型,即用实线、虚线、点线描述的线型
参数说明:
-
PSTYLE 线型
'SOLD' 实线 (_________)
'DASH' 虚线 (- - - - - - - - ) 每画3.6mm间隔1.8mm
'DOTT' 点线 (..................) 每画0.6mm间隔1.2mm -
WIDTH 线宽
单位为0.32mm,'1' x 0.32 mm <= 线宽 <= '8' x 0.32 mm; -
COLOUR 颜色
用颜色标记指定的颜色
示例:LS(DASH,2,CHMGD)
含义:用颜色为CHMGD,宽度为0.64mm(2个单位)的虚线去绘制。
2. TC
复杂线型,即用复杂的符号去绘制线段
参数说明:
-
LINNAME 符号名
符号名由8位字母或数字组成,前6位字母代表符号类型,后2位数字代表序列号。符号的具体形状是由矢量符号描述语言定义的。
示例:LC(ACHARE51)
含义:用符号ACHARE51去绘制线段。
复杂线型是指线段由符号重复拼接而成。如同墙壁拼接瓷砖一样,需要根据线段的走向,动态计算每一块瓷砖的位置。拼接时还应注意符号的长度与宽度,还有转心,所以可能出现截断的情况。
编码实现
- 简单线型
对于简单线型中的虚线与点线,需要事先构造虚线规则。Skia中,线型可由public static SKPathEffect CreateDash(float[] intervals, float phase)
产生,如果intervals = new [] { 10, 20 }且phase = 25,表示隔25像素,然后绘制10像素,空20像素,再绘制10像素,空20像素,以此循环。
//虚线为 每画3.6mm间隔1.8mm
public static readonly SKPathEffect DASH = SKPathEffect.CreateDash(
new[] { (float)(3.6 * UPP), (float)(1.8 * UPP) }, 0);
//点线为 每画0.6mm间隔1.2mm
public static readonly SKPathEffect DOTT = SKPathEffect.CreateDash(
new[] { (float)(0.6 * UPP), (float)(3.6 * UPP) }, 0);
编写静态方法DrawSimpleLine
,传入所需绘制的路径:
public static void DrawSimpleLine(SKCanvas ca, SKPath path,
string pstyle, int penWidth, string color)
{
using (var paint = new SKPaint()
{
Color = S52Colors.Instance[color],
StrokeWidth = PicaPoint * penWidth,
IsAntialias = true,
Style = SKPaintStyle.Stroke,
})
{
switch (pstyle)
{
case "DASH": paint.PathEffect = DASH; break;
case "DOTT": paint.PathEffect = DOTT; break;
}
ca.DrawPath(path, paint);
}
}
- 复杂线型
对于某条线段,计算其长度,除以符号长度,得到所需绘制符号的个数及每个符号的起始位置。然后根据线段倾斜角度,旋转坐标系,依次将符号图片粘贴到指定位置。依次对路径中其他线段采取如上操作,即可完成复杂线型的绘制。
编写静态方法DrawComplexLine
,传入所需绘制的路径:
public static void DrawComplexLine(SKCanvas ca, SKPath path, string acroymn)
{
//线段 每段之间先分好段,然后将图片一个个贴上去
//输入的角度是指顺时针旋转的角度,0表示正东方向
var symbol = S52ComplexLines.Instance[acroymn];
var img = symbol.Image;
using (var iter = path.CreateIterator(false))
{
var points = new SKPoint[4];
var pathVerb = SKPathVerb.Move;
//遍历路径中的线段
while ((pathVerb = iter.Next(points)) != SKPathVerb.Done)
{
if (pathVerb == SKPathVerb.Line)
{
var p1 = points[0];
var p2 = points[1];
var distance = GeoTools.Distance(p1, p2);
if (distance <= img.Height) continue;
var angle = GeoTools.AngleBetweenTwoPoints(p2, p1) - 90;
var parts = distance / (img.Width - symbol.OffsetX);
var remain = (float)(distance - (int)parts * (img.Width - symbol.OffsetX));
ca.Save(); //保存坐标系
var tpX = p1.X - symbol.OffsetX;
var tpY = p1.Y - symbol.OffsetY;
ca.RotateDegrees((float)angle, p1.X, p1.Y); //旋转坐标系
for (int j = 1; j <= parts; j++)
{
ca.DrawBitmap(symbol.Image, tpX, tpY);
tpX += (img.Width - symbol.OffsetX);
}
if (remain > img.Height) //最后一张图片可能不全
{
ca.DrawBitmap(symbol.Image, new SKRect(0, 0, remain + symbol.OffsetX, img.Height),
new SKRect(tpX, tpY, tpX + remain + symbol.OffsetX, tpY + img.Height));
}
ca.Restore(); //还原坐标系
}
}
}
}