1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
/*
NAME:
DESCRIPTION: ;
PARAMETER:
[
{
name : 'max_via_size',
title : '最大via孔径',
type : 'LineEdit',
property : {tool_tip : '最大via孔径,默认是0.9mm'},
},
{
name : 'min_via_num',
title : '最少via孔数',
type : 'LineEdit',
property : {tool_tip : '最少via孔数,默认是100'},
},
{
name : 'equidistant_tolerance',
title : '等间距公差',
type : 'LineEdit',
property : {tool_tip : '等间距公差,默认是0.005mm'},
},
{
name : 'auto_save',
title : '自动保存',
type : 'RadioBox',
property : {
item_list:[
{name:'yes',text:'YES'},
{name:'no',text:'NO'},
],
tool_tip:'是否自动保存料号开关'
}
}
]
VERSION_HISTORY:
V1.00 2020-04-20 Scott Sun
1.新版本
HELP:
<html><body bgcolor="#DDECFE">
<font size="3" color="#003DB2"><p>功能简介</p></font>
<p> 设置孔属性 </p>
<br>
<font size="3" color="#003DB2"><p>参数配置</p></font>
<p> </p>
<br>
<font size="3" color="#003DB2"><p>注意事项</p></font>
<p> 无 </p>
<br>
</body></html>
*/
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
console.log("==============================>set drill");
// 引入模块 包
var $ = require('topcam.scriptfunc').argv();
var fs = require('fs');
var _ = require('lodash');
var database = require("topsin.database");
database.addConnection($.conf.database_conf, "DFM");
var QDfm = database.query("DFM");
if ($.conf.product_type == "aimdfm") {
QDfm.updateRow({
table: "pdm_aimdfm_task",
data: {
current_process_title: $.process_title
},
where: { id: $.task_id }
});
}
var GEN = $.gen;
var Job = $.job_name;
var db = $.db
var Status = 'ok';
var resultData = [];
var PAR = {};
if ($.hasOwnProperty('script_parameter')){
PAR = JSON.parse($.script_parameter);
}
try {
var par = PAR;
var default_par = {
max_via_size: "0.9mm",
min_via_num: "100",
equidistant_tolerance: "0.005mm",
auto_save: "No"
}
for(var key in default_par){ // 设置默认属性
if (!par.hasOwnProperty(key) || par[key] == ""){
par[key] = default_par[key]
}
}
var max_via_size = parseFloat(par.max_via_size);
var equidistant_tolerance = parseFloat(par.equidistant_tolerance);
if(_.isEmpty(Job)){throw "参数Job不存在"}
var job = Job.toLowerCase()
// 检查料号是否存在
if(!GEN.isJobExists({job:job})){throw "料号已经:"+job+"不存在"}
// 检查料号是否被打开
if(!GEN.isJobOpen({job:job})){ GEN.openJob({job:job}) }
// 检查料号是否能够check out
if(GEN.checkInout({job:job,mode:"test"}) != 0){ throw "the job check" }
GEN.checkInout({job:job,mode:"out"});
// 通过matrix获取board属性的钻孔层
var matrix = GEN.getMatrix({job:job})
var dirll_layer = Object.keys(matrix).reduce(function(a,b){
if(matrix[b].context == "board" && matrix[b].layer_type == "drill"){
a.push(b)
}
return a
},[])
var stepList = GEN.getStepList({job:job})
stepList.forEach(function(step){
GEN.openStep({job:job,name:step})
dirll_layer.forEach(function(layer){
// 逐层设置钻孔工作层
GEN.workLayer({name:layer,display_number:2,clear_before:'yes'})
// 分析via孔:排除超过max_via_size的孔径的孔,排除数量少于min_via_num数量的钻孔,排除存在等间距equidistant_tolerance的钻孔
// 排除超过max_via_size的孔径的孔
var layerSymsHist = GEN.getLayerSymsHist({job:job,step:step,layer:layer});
var via_symbol = Object.keys(layerSymsHist).map(function(v){return layerSymsHist[v]})
via_symbol = via_symbol.filter(function(item){
if(!item.size && item.width){
var max_tmp = item.width > item.height ? item.width : item.height
item.size = max_tmp
}
if(!item.size){item.size = 0}
return Number(item.size) <= max_via_size
})
// 排除少于min_via_num数量的钻孔
via_symbol = via_symbol.filter(function(item){
if(item.pad == 0){return false}
return item.pad >= Number(par.min_via_num)
})
console.log("via_symbols================================:"+_.toString(via_symbol))
if(via_symbol.length){
// 如果via_symbol存在
GEN.selClearFeature()
GEN.selectByFilter({
feat_types:"pad",
include_syms: via_symbol.map(function(v){return v.symbol}).join(",")
})
// 将选中的复制到辅助层
var layer_tmp = layer + "_tmp"
if(GEN.isLayerExists({job:job,layer:layer_tmp})){GEN.deleteLayer({job:job,step:step,layer:layer_tmp})}
GEN.selCopyOther({dest:"layer_name",target_layer:layer_tmp,invert:'no'})
GEN.selClearFeature();
GEN.workLayer({name:layer_tmp,display_number:2,clear_before:'yes'})
var ck = "tmp_chk"
if(GEN.isChklistExists({job:job,step:step,chklist:ck})){
GEN.COM("chklist_delete", { chklist: ck })
}
// 创建并运行
GEN.createChklist({ // 创建checklist
chklist: ck,
items: [{
name: "viaPitch",
nact: 1,
action: "valor_analysis_signal",
erf: "S2_conductor_Check",
params: {
pp_layer: ".affected",
pp_spacing: 20,
pp_selected: "All",
pp_r2c: 10,
pp_d2c: 15,
pp_sliver: 8,
pp_min_pad_overlap: 5,
pp_check_missing_pads_for_drills: "Yes",
pp_use_compensated_rout: "Skeleton",
pp_sm_spacing: "Yes",
pp_tests: "Spacing",
pp_check_missing_pads_for_drills:"Yes"
}
}]
})
GEN.chklistShow({ chklist: ck })
GEN.affectedLayer({ affected: "yes", layer: layer, clear_before: "yes" })
GEN.chklistRun({
chklist: ck,
nact: 1,
area: "profile"
})
var tmp_layer1 = "mk_1_"+layer_tmp+"_pitch"
var tmp_layer2 = "ms_1_"+layer_tmp+"_pitch"
if(GEN.isLayerExists({job:job,layer:tmp_layer1})){
GEN.deleteLayer({job:job,layer:tmp_layer1})
}
if(GEN.isLayerExists({job:job,layer:tmp_layer2})){
GEN.deleteLayer({job:job,layer:tmp_layer2})
}
GEN.COM("chklist_create_lyrs,chklist="+ck+",severity=3,suffix=pitch");
GEN.workLayer({name:tmp_layer2,display_number:1,clear_before:'yes'});
GEN.selectByFilter({attribute:[{attribute:".string",text:"via_pitch"}]})
var tmp_layer2_tmp = tmp_layer2 + "_tmp"
if(GEN.isLayerExists({job:job,layer:tmp_layer2})){
GEN.deleteLayer({job:job,layer:tmp_layer2_tmp})
}
GEN.selCopyOther({dest:"layer_name",target_layer:tmp_layer2_tmp,invert:'no'})
GEN.selClearFeature();
GEN.workLayer({name:tmp_layer2_tmp,display_number:1,clear_before:'yes'});
var symbols_tmp = GEN.getLayerSymsHist({job:job,layer:tmp_layer2_tmp,step:step})
// 找出间距 equidistant_tolerance 的
var equidistant_tolerance_symbol = _.values(symbols_tmp).filter(function(item){
return Math.abs(Number(item.size) - equidistant_tolerance) < 0.000001
})
// 如果有 根据上面找到的 参考选择 删掉 layer_tmp 层里的钻孔
if(equidistant_tolerance_symbol.length){
GEN.selectByFilter({
exclude_syms:equidistant_tolerance_symbol.map(function(v){return v.symbol}).join(",")
})
GEN.selDelete()
GEN.workLayer({name:layer_tmp,display_number:2,clear_before:'yes'})
GEN.selRefFeat({layers:tmp_layer2_tmp,use:'filter',mode:'touch'})
GEN.selDelete()
}
// 根据layer_tmp层的钻孔参考选择出 层里面的镭射层
GEN.selClearFeature()
GEN.workLayer({name:layer,display_number:2,clear_before:'yes'})
GEN.selRefFeat({layers:layer_tmp,use:'filter',mode:'touch'})
// 设置选中的via孔属性
if(GEN.getSelectCount() > 0){
GEN.COM("cur_atr_set,attribute=.drill,option=via")
GEN.COM("sel_change_atr,mode=add")
GEN.selClearFeature()
}
// 删除辅助层
var deleLayers = [tmp_layer1, tmp_layer2, tmp_layer2_tmp, layer_tmp]
deleLayers.forEach(function(v){
GEN.deleteLayer({job:job,layer:v})
})
}
})
GEN.closeStep()
})
// 保存
if(/yes/ig.test(par.auto_save)){
GEN.checkInout({job:job,mode:"out"}) // 结束保存料号 关闭料号
GEN.saveJob({ job: job });
GEN.checkInout({job:job,mode:"in"})
GEN.closeJob({job:job})
} else {
GEN.checkInout({job:job,mode:"in"})
}
QDfm.updateRow({
table: "pdm_aimdfm_task",
data: {
progress: 33.33
},
where: { id: $.task_id }
});
if (GEN.hasError()) {
Status = 'error';
resultData.push({ type: "error", title: "GEN错误!", detail: [{ desc: _.join(GEN.STATUS, "\n") }] });
return {
status: Status,
result_data: resultData
};
} else {
resultData.push({ type: "info", title: "操作完成, 请注意检查!" });
return {
status: Status,
result_data: resultData
};
}
} catch (e) {
Status = 'error';
resultData.push({type: "error", title: "脚本执行出错!", detail: [{desc: _.toString(e)}]});
return {status: Status, result_data: resultData};
}