您当前的位置:首页 > 计算机 > 文件格式与编码

获取dwg中的标准号算法

时间:04-27来源:作者:点击数:

使用场景综述:需要校验dwg中的标准号(标号)是否为现行标准,并将正确标号回写到dwg中

使用场景简述理解:需要校验word中的标准号是否为现行标准,并回写

分析:

  • 1.读取dwg中的内容,沟通后定为以下图元:单行文本、多行文本、dwg表、图块
  • 2.将读取到的文字识别为标准号(下帖详述),并展现出来
  • 3.寻找标准号数据库,并放到服务器端,以供查询
  • 4.根据获取到的标准号,去服务器端匹配数据
  • 5.将匹配到的数据,回写到dwg中

综上,经过初步分析,本人认为该项目的难点在于如何识别某字段为标准号,及时间复杂度上。

本项目基于cad2021,c#,根据上述分析,预计循环层数不少于8层,也请大佬帮忙降重

预计循环情况:

  • 1、文件(dwg)
  • 2、循环文件中的图元(单行文本、多行文本、dwg表、图块)
  • 3.1、dwg表可理解为excel表,需要每个单元格进行循环,循环层数+2
  • 3.2、图块(不再圈套循环图块了),图块中有不同的属性,均获取到,循环层数+1
  • 4、上述3,循环+2,并将数据存储到DataTable中,记下文件路径、图块位置等

a、根据上述的DataTable按行匹配数据

b、将标号前缀(keys)作为循环条件,进行循环查找数据

c、在获取到的文本中依次查询标号前缀,看是否含有,含有的话,取固定长度25位

d、根据标号前缀key,再次循环标号排除前缀

e、根据不含有的字段,再次循环排除

f、根据25位长度,从后往前取,取最后一个数字截止

由此,取出标号

综上,10层循环齐活,刚刚取出数据

1.由于为公司项目,已有图签,故只取图签内的数据。涉及到合图、多dwg的情况,一并解决,无难点

2.从图元中取数据,分为dwg表、图块、单行文本,多行文本。其中多行文本取出的数据,较为麻烦,分为两种数据,一种是带格式的数据,一种是不带格式的数据,如下:

  1. 本配管的安装和试验应符合GB/T50783-2006<<冶金机械液压、润滑和气动设备工程安装验收规范>>的规定.
  2. 安装管道时,应严格遵循原理图(图号:MAG011402-GES02.1)所示走向配制.并在管端标明编号.
  3. 管子与管子,管子与焊接式管件采用氩弧焊焊接,或先用氩弧焊打底,再采用E4303焊条,进行电弧焊填充。
  4. 管夹与底板(钢板)等非管道的焊接采用E4303焊条进行连续焊缝焊接,焊缝高度等于相连件最薄厚度.并应符合JB/T5000.3-2007<<焊接件通用技术条件>>的有关规定.

若取不带格式的数据,更容易匹配到标号,但是不容易回写数据。正在尝试不带格式数据直接回写,暂测可行

this.dataGridView1.Columns["FLAG"].DataPropertyName = "flag";
this.dataGridView1.Columns["FilePathCurrent"].DataPropertyName = "FilePathCurrent";
this.dataGridView1.Columns["ObjectId"].DataPropertyName = "ObjectId";
this.dataGridView1.Columns["FileNameCurrent"].DataPropertyName = "FileNameCurrent";
this.dataGridView1.Columns["SourceData"].DataPropertyName = "SourceData";
this.dataGridView1.Columns["SourceSpecificationData"].DataPropertyName = "SourceSpecificationData";
this.dataGridView1.Columns["DealSourceSpecificationData"].DataPropertyName = "DealSourceSpecificationData";
this.dataGridView1.Columns["CheckSourceSpecificationData"].DataPropertyName = "CheckSourceSpecificationData";
this.dataGridView1.Columns["location"].DataPropertyName = "location";
this.dataGridView1.Columns["Remark"].DataPropertyName = "Remark";



System.Data.DataTable dtOut = dt.Clone();
string path = null;
try
{
//根据数据行循环
foreach (System.Data.DataRow dr in dt.Rows)
{
if (dr == null)
{
continue;
}
string sourceData = dr["SourceData"].ToString().Replace("\n", "").Replace("\r", "");
int sourceData_Num = sourceData.Length;
if (string.IsNullOrEmpty(sourceData))
{
continue;
}
//根据关键字前缀循环
foreach (var key in keys)
{
string key_Pre = key.Key;
List<string> key_Pre_Excludes = key.Value;
int index = 0;
//根据判断sourceData是否含有key,并排除sourceData中有key,但不为标准号的情况
for (int j = 0; ; j++)
{
int NS_Index = sourceData.IndexOf(key_Pre, index, StringComparison.OrdinalIgnoreCase);
//sourceData不含key_Pre,直接跳出
if (NS_Index < 0)
{
break;
}
//搜索key_Pre过程中,多次循环后NS_Index值未改变,说明含有前缀但不为标号的情况,sourceData.IndexOf搜索的起始位下标+1
if (j > NS_Index)
{
index = NS_Index + 1;
break;
}
int len = lengthMax;
if (sourceData.Length - NS_Index < lengthMax)
{
len = sourceData.Length - NS_Index;
}
string NS_vars = sourceData.Substring(NS_Index, len);
bool flag = false;
//去除对应 排除标号前缀的 标号前缀排除。例如:含GB,不含GBS
foreach (string key_Pre_Exclude in key_Pre_Excludes.CheckNull())
{
if (NS_vars.StartsWith(key_Pre_Exclude, StringComparison.OrdinalIgnoreCase))
{
flag = true;
index = NS_Index + 1;
j = NS_Index - 1;
break;
}
}
if (flag)
{
continue;
}
string NS_var = Regex.Split(NS_vars, @"\P", RegexOptions.IgnoreCase)[0];//去掉换行后的字符串
//根据不要的关键字,取关键字前面的部分
foreach (string key_Exclude in key_Excludes.CheckNull())
{
if (NS_vars.IndexOf(key_Exclude, StringComparison.OrdinalIgnoreCase) > -1)
{
int temp = NS_vars.IndexOf(key_Exclude, StringComparison.OrdinalIgnoreCase);
NS_vars = sourceData.Substring(NS_Index, temp);
NS_var = Regex.Split(NS_vars, @"\P", RegexOptions.IgnoreCase)[0];
}
}
if (NS_var.Length < lengthMin)
{
break;
}
for (int i = NS_var.Length - 1; i > 0; i--)
{
string tempWord = Regex.Replace(NS_var[i].ToString(), @"\d", "");//剔除数字
if (string.IsNullOrEmpty(tempWord) && !string.IsNullOrEmpty(NS_var[i].ToString()))
{
string DealSourceSpecificationData = sourceData.Substring(NS_Index, i + 1);
System.Data.DataRow drOut = dtOut.NewRow();
drOut = dr;
path = Path.GetDirectoryName(drOut["FilePathCurrent"].ToString());
drOut["SourceSpecificationData"] = NS_vars;
drOut["DealSourceSpecificationData"] = Regex.Split(DealSourceSpecificationData, @"\P", RegexOptions.IgnoreCase)[0];//去掉换行后的字符串
dtOut.Rows.Add(drOut.ItemArray);
//sourceData = sourceData.Replace(str, "");//剔除'str1'
index = NS_Index + 1;//剔除'DealSourceSpecificationData'
j = NS_Index - 1;
break;
}
}
}
}
}
}
catch (Exception ex)
{
LogTool.LogTest(ex.StackTrace);
}


private static string[] GetSpecificationPrefix()
{
string SpecificationPrefix = "GB";
try
{
SpecificationPrefix = IniTool.GetValue("cfg.ini", "Specification", "SpecificationPrefix");
}
catch
{ }
return SpecificationPrefix.Split(',');
}
private static string[] GetExcludeSpecificationPrefix()
{
string SpecificationPrefix = "GB2312";
try
{
SpecificationPrefix = IniTool.GetValue("cfg.ini", "Specification", "ExcludeSpecificationPrefix");
}
catch
{ }
return SpecificationPrefix.Split(',');
}
private static string[] GetExclude()
{
string Exclude = "。";
try
{
Exclude = IniTool.GetValue("cfg.ini", "Specification", "Exclude");
}
catch
{ }
return Exclude.Split('a');
}
private static Dictionary<string, List<string>> GetKeys()
{
string[] key_Pres = GetSpecificationPrefix();//获取标号前缀
string[] key_Pre_Excludes = GetExcludeSpecificationPrefix();//获取排除标号前缀
Dictionary<string, List<string>> keys = new Dictionary<string, List<string>>();
foreach (string key_Pre in key_Pres)
{
List<string> key_Pre_Exclude_List = new List<string>();
foreach (string key_Pre_Exclude in key_Pre_Excludes)
{
if (key_Pre_Exclude.IndexOf(key_Pre, StringComparison.OrdinalIgnoreCase) > -1)
{
key_Pre_Exclude_List.Add(key_Pre_Exclude);
}
}
keys.Add(key_Pre, key_Pre_Exclude_List);
}
return keys;
}

从dwg中取数据,暂无优化空间,已经从标号前缀、去除标号前缀的方向上,做出了优化:

1)根据填写的标号前缀、标号排除前缀、排除序列,将数据模拟成Dictionary<string, List<string>>格式

dic的string为标号前缀,对应的list为标号排除前缀,例如dic={AC,【AC220,AC110】}

SpecificationPrefix=AC,AQ

ExcludeSpecificationPrefix=GBS,GB2312,SHX,AC220,gbc

Exclude=.a,a、a。a,a和

已排除各种循环跑死的情况,例如:

GB6222-2005、GB50316-2000

GBS6222-2005、GBS50316-2000

GB2312、AC220、AC84156-2005

GB2312和AC220heAC84156-2005

例如 AC84156-2005为标准化,AC220、AC110不为标准号,GB50316-2000为标准号,GB2312不为标准号,即删除AC,又想到源字符串可能为AC220,AC84156-2005,此时,均去除,标号未取到

并由此,将循环图元的字符串,改为下标循环的方式,发现AC220时,IndexOf起始下标+1

链接为国家标号链接

http://std.samr.gov.cn/gb/gbQuery

查询时,思路为C端将取出的标准号进行拆分,以-为标准拆成两部分,前面为标号,后面为年份,并将标号中的\、空格等均去除,然后根据标号和年份一起去查询数据库的数据,数据库中的标号,也需要去除\、空格等,提高匹配命中率。去除\、空格的原因为:人工填数据,可能会漏\、空格,也可能会多,所以去除;去除年份的原因,即可能是年份写错,也可能是年份写的位数不对,可能是2位,可能是4位。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门