条件符号一般需要根据用户设置动态绘制,如非双色显示时,海洋会根据用户设备的等深线,被分成四部分,每部分有着不同的颜色。因此每一条件符号的流程都是独立的,其拥有唯一的流程名。
参数说明:
- PROCNAME 流程名
流程名由8位字母或数字组成,前6位字母代表流程所涉及的物标目录名,后2位数字代表版本号。
示例:CS(DEPARE02)
含义:执行名为DEPARE02的条件符号流程,该流程作用对象为深水区(DEPARE)。
现有的条件符号流程
S-52显示库中有如下流程,流程名后2位数字代表当前版本号。
流程名 | 适用对象 |
---|---|
CLRLIN01 | 安全导航线 |
DATCVR02 | 数据覆盖范围,比例尺边界,超比例尺显示 |
DEPARE02 | 水深区颜色填充和疏浚区图案填充 |
DEPCNT03 | 等深线,包括安全等深线 |
DEPVAL02 | 水深值 |
LEGLIN03 | 计划航线 |
LIGHTS05 | 灯标灯质、光弧及范围 |
LITDSN01 | 灯标的描述说明 |
OBSTRN06 | 障碍物和岩石 |
OWNSHP02 | 本船 |
PASTRK01 | 航迹 |
QUAPOS01 | 位置精度 |
QUALIN01 | 线物标的位置精度 |
QUAPNT02 | 点和面物标的位置精度 |
RESARE03 | 限制区域 |
RESTRN01 | 限制区域的入口程序 |
RESCSP02 | 限制区域–属性RESTRN |
SAFCON01 | 等深线标签 |
SLCONS03 | 海岸线,包括位置精度。 |
SEABED01 | 水深区的颜色填充 |
SNDFRM03 | 水深点符号化,包括安全水深 |
SOUNDG02 | 水深点绘制的入口程序 |
SYMINSnn | 绘制由IMO指定符号 |
TOPMAR01 | 灯标的项标 |
UDWHAZ04 | 孤立危险物 |
VESSEL02 | 本船以外的船只 |
VRMEBL02 | VRM和EBL |
WRECKS04 | 沉船 |
S-52标准中的条件流程可能包含子流程,子流程可以被共享。
流程名 | 物标 | 子流程名 |
---|---|---|
DATCVR | M_COVR(a), M_CSCL(a) | |
DEPARE | DEPARE(a), DRGARE(a) | RESCSP, SEABED, SAFCON |
DEPCNT | DEPARE(l), DEPCNT(l) | SAFCON |
LIGHTS | LIGHTS(p) | LITDSN |
OBSTRN | OBSTRN(pla), UWTROC(p) | DEPVAL, QUAPNT, SNDFRM, UDWHAZ |
QUAPOS | LNDARE(pl), COALNE(l) | QUAPNT, QUALIN |
RESARE | RESARE(a) | |
RESTRN | ACHARE(a), CBLARE(a), DMPGRD(a), DWRTPT(a), FAIRWY(a), ICNARE(a), ISTZNE(a), MARCUL(a), MIPARE(a), OSPARE(a), PIPARE(a), PRCARE(a), SPLARE(a), SUBTLN(a), TESARE(a), TSSCRS(a), TSSLPT(a), TSSRON(a) |
RESCSP |
SOUNDG | SOUNDG(p) | SNDFRM |
WRECKS | WRECKS(pa) | DEPVAL, QUAPNT, SNDFRM, UDWHAZ |
物标括号中的字母代表:p = 点物标;l = 线物标;a = 面物标。
如:绘制水深点针对的是点物标SOUNDG
,具体流程为条件符号流程SOUNDG
,其还使用到子流程SNDFRM
。
示例
需要针对每一条件符号流程单独编码,如水深点是以符号形式而非文本形式显示在电子海图中的。条件符号流程SOUNDG:
条件符号流程SOUNDG
的逻辑很简单:遍历本物标的水深点信息,将水深值传给子流程SNDFRM,将返回的符号数组显示在水深点处。
子流程SNDFRM
,根据水深值(是否大于安全水深)添加符号前缘,根据自身物标特点(水深点性质及精度),添加相应修饰符号。然后将水深值拆分,按照一定规则找到相应的符号。最后将符号号组成的数组返回给上层流程。
安全水深由用户设置,默认值为30米。
编码实现
添加全局设置,存在用户设定的安全水深:
public static class MySettings
{
// ...
internal static double SafetyDepth = 30; //用户设定的安全水深
}
对物标做预处理,将位置信息组装成路径,水深信息转化成浮点数组,并取出物标属性'TECSOU'(测深所使用的技术),‘STATUS’(位置状态),‘QUASOU’(测深质量),‘QUAPOS’(位置质量),将其传入函数。
TECSOU | STATUS | QUASOU | QUAPOS |
---|---|---|---|
1 : found by echo-sounder 2 : found by side scan sonar 3 : found by multi-beam 4 : found by diver 5 : found by lead-line 6 : swept by wire-drag 7 : found by laser 8 : swept by vertical acoustic system 9 : found by electromagnetic sensor 10 : photogrammetry 11 : satellite imagery 12 : found by levelling 13 : swept by side-scan sonar 14 : computer generated |
1 : permanent 2 : occasional 3 : recommended 4 : not in use 5 : periodic/intermittent 6 : reserved 7 : temporary 8 : private 9 : mandatory 10 : destroyed/ruined 11 : extinguished 12 : illuminated 13 : historic 14 : public 15 : synchronized 16 : watched 17 : un-watched 18 : existence doubtful |
1 : depth known 2 : depth unknown 3 : doubtful sounding 4 : unreliable sounding 5 : no bottom found at value shown 6 : least depth known 7 : least depth unknown, safe clearance at value shown 8 : value reported (not surveyed) 9 : value reported (not confirmed) 10 : maintained depth 11 : not regularly maintained |
1 : surveyed 2 : unsurveyed 3 : inadequately surveyed 4 : approximate 5 : position doubtful 6 : unreliable 7 : reported (not surveyed) 8 : reported (not confirmed) 9 : estimated 10 : precisely known 11 : calculated |
public static void DrawCS_SOUNDG(SKCanvas ca, SKPath path, double[] depths,
string tecsou, string status, string quasou, string quapos)
{
for (int i = 0; i < depths.Length; i++)
{
//转入水深点,返回符号数组
var symbols = DrawCS_SNDFRM(depths[i], tecsou, status, quasou, quapos);
//依次绘制
foreach (var sy in symbols)
{
DrawSymbolAtXY(ca, path.Points[i].X, path.Points[i].Y, sy);
}
}
}
public static List DrawCS_SNDFRM(double depth,
string tecsou, string status, string quasou, string quapos)
{
var symbols = new List();
var prefix = depth < MySettings.SafetyDepth ? "SOUNDS" : "SOUNDG"; //前缀
if (tecsou == "6") //扫海水深
{
symbols.Add(prefix + "B1");
}
if(status == "18") //疑存
{
symbols.Add(prefix + "C2");
}
else if (quasou == "3" || quasou == "4" || quasou == "5" || quasou == "8" || quasou == "9")
{
symbols.Add(prefix + "C2");
}
else if (quapos == "2" || quapos == "3" || quapos == "4" || quapos == "5" || quapos == "6"
|| quapos == "7" || quapos == "8" || quapos == "9")
{
symbols.Add(prefix + "C2");
}
if (depth < 0)
{
symbols.Add(prefix + "A1");
}
else if (depth < 10)
{
var f = (int)depth;
var s = (int)(depth * 10 % 10);
symbols.Add(prefix + (10 + f).ToString());
symbols.Add(prefix + (50 + s).ToString());
}
else if (depth < 31)
{
var f = (int)(depth / 10);
var s = (int)(depth % 10);
var t = (int)(depth * 10 % 10);
symbols.Add(prefix + (20 + f).ToString());
symbols.Add(prefix + (10 + s).ToString());
symbols.Add(prefix + (50 + t).ToString());
}
else if (depth < 100)
{
var f = (int)(depth / 10);
var s = (int)(depth % 10);
symbols.Add(prefix + (10 + f).ToString());
symbols.Add(prefix + s.ToString("00"));
}
else if (depth < 1000)
{
var f = (int)(depth / 100);
var s = (int)(depth % 100 / 10);
var t = (int)(depth % 10);
symbols.Add(prefix + (20 + f).ToString());
symbols.Add(prefix + (10 + s).ToString());
symbols.Add(prefix + t.ToString("00"));
}
else if (depth < 10000)
{
var f = (int)(depth / 1000);
var s = (int)(depth % 1000 / 100);
var t = (int)(depth % 100 / 10);
var l = (int)(depth % 10);
symbols.Add(prefix + (20 + f).ToString());
symbols.Add(prefix + (10 + s).ToString());
symbols.Add(prefix + t.ToString("00"));
symbols.Add(prefix + (40 + l).ToString());
}
else
{
var f = (int)(depth / 10000);
var s = (int)(depth % 10000 / 1000);
var t = (int)(depth % 1000 / 100);
var l = (int)(depth % 100 / 10);
var m = (int)(depth % 10);
symbols.Add(prefix + (30 + f).ToString());
symbols.Add(prefix + (20 + s).ToString());
symbols.Add(prefix + (10 + t).ToString());
symbols.Add(prefix + l.ToString("00"));
symbols.Add(prefix + (40 + m).ToString());
}
return symbols;
}