/*
NAME:
DESCRIPTION: ;
PARAMETER:
[
{
name : 'step_fliter',
title : 'Step过滤',
type : 'LineEdit',
property : {tool_tip : 'unit'},
},
{
name : 'erf',
title : 'erf name',
type : 'LineEdit',
property : {tool_tip : 'erf'},
},
{
name : 'layer_type',
title : '工作层',
type : 'ComboBox',
property : {
size_policy:'Expanding,Fixed',
item_list:[
{name:'outer',text:'outer'},
{name:'inner',text:'inner'},
{name:'all',text:'all'}
],
tool_tip:'分析模式必须设置,未设定则退出'
},
pack : {row:1,column:1},
},
{
name : 'del_backup',
title : '删除TL备份层',
type : 'RadioBox',
property : {
item_list:[
{name:'yes',text:'YES'},
{name:'no',text:'NO'},
],
tool_tip:'是否自动保存料号开关'
}
},
{
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-28 Scott Sun
1.新版本
HELP:
功能简介
补铜桥
参数配置
配置
注意事项
无
*/
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
console.log("==============================>JTG_PUB_pos_add_copper_bridge_aim");
// 引入模块 包
var $ = require('topcam.scriptfunc').argv();
var fs = require('fs');
var _ = require('lodash');
var mode = $.ikm ? "topcam" : "aimdfm";
var IKM = $.ikm;
if (IKM==undefined ) { IKM = require('topcam.ikm6')($) }
var GEN = $.gen;
var GUI = $.gui || {};
var Job = $.job || $.job_name;
var JobId = $.job_id;
var db = $.db || IKM.db;
var GenMath = require("topsin.genmath")
var PAR = {}
if ($.par) {
PAR = $.par
} else if ($.hasOwnProperty('script_parameter')){
PAR = JSON.parse($.script_parameter);
}
if (mode === "aimdfm") {
var database = require("topsin.database");
database.addConnection($.conf.database_conf, "DFM");
var QDfm = database.query("DFM");
$.QDfm = QDfm;
if ($.conf.product_type == "aimdfm") {
QDfm.updateRow({
table: "pdm_aimdfm_task",
data: {
current_process_title: $.process_title
},
where: { id: $.task_id }
});
}
}
var Status = 'ok';
var resultData = [];
try {
var par = PAR;
PAR.width = 10
PAR.length = 10
var default_par = { // par默认参数?
step_fliter:"unit.+",
step2:"unit",
units: "inch",
auto_save: "no"
}
for(var key in default_par){ // 设置默认属性
if (!par.hasOwnProperty(key) || par[key] == ""){
par[key] = default_par[key]
}
}
// var par_props = ["ring_size","line_size"] // par的必填参数
// par_props.forEach(function(v){
// if(par[v] == ""){throw "par props "+v+" err"}
// })
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}) }
if(mode == "aimdfm"){
if(GEN.checkInout({job:job,mode:"test"}) != 0){ throw "the job check" }
GEN.checkInout({job:job,mode:"out"});
}
// 脚本开始
var stepList = GEN.getStepList({job:job})
if(par.step_fliter != ""){
stepList = stepList.filter(function(v){
var step_reg = new RegExp(par.step_fliter)
return step_reg.test(v)})
}
if (stepList.length == 0 && par.step2) {
stepList = GEN.getStepList({job: job}).filter(function (v) {
var step_reg = new RegExp(par.step2)
return step_reg.test(v)
})
}
var layer_config = {
outer: {layer_type:"signal", side:"top|bottom", context:"board", polarity:"positive"},
inner: {layer_type:"signal", side:"inner", context:"board", polarity:"positive"},
all: {layer_type:"signal", context:"board", polarity:"positive"},
power_ground: {layer_type:"power_ground", side:"inner", context:"board", polarity:"negative"},
}
var layer_cfg
if(par.layer_type != ""){
layer_cfg = layer_config[par.layer_type]
}
var matrix = GEN.getMatrix({job:job})
var n_layers = Object.keys(matrix).sort(function(a,b){return matrix[a].row - matrix[b].row})
.filter(function(key){
var val = matrix[key]
var flag = true
if(!layer_cfg){ return false}
for(var k in layer_cfg){
var tmp_reg = new RegExp(layer_cfg[k], "ig")
if(!tmp_reg.test(val[k])){
flag = false
}
}
return flag
})
if(n_layers.length == 0){throw "can not find layer"}
stepList.forEach(function(step){
GEN.openStep({job:job, name:step})
GEN.units({type:par.units})
GEN.affectedLayer({affected:'no',mode:'all'})
GEN.clearLayers()
var profile_limits = GEN.getProfileLimits({job:job,step:step,units:par.units});
var ans_chk = create_checklist_and_run_analysis({layers:n_layers,aux:1, job:job, step:step}, par);
GEN.COM("disp_off");
n_layers.forEach(function(layer){
var tmp = []
tmp.push(layer + '_tl+++tmp')
GEN.copyLayer({source_job:job,source_step:step,source_layer:layer,dest_layer:layer+'_tl+++',mode:'replace',invert:'no'});
var length = par["length"];
var width = par["width"];
var line_chk = "tl_line_chk",line_ok="tl_line_ok", add_pad="tl_add_pad",touch_lyr="tl_touch_lyr"
var tmp_layers = [line_chk,line_ok,add_pad,touch_lyr]
//GEN.deleteLayer(job:job,layer:[line_chk,line_ok,add_pad,touch_lyr],step:step);
tmp_layers.forEach(function(v){
if(GEN.isLayerExists({job:job, layer:v})){GEN.deleteLayer({job:job, layer:v})}
GEN.createLayer({job:job,layer:v,conext:'misc',type:'document'})
})
var ms_layer = 'ms_1_'+layer
var mk_layer='mk_1_'+layer
if(GEN.isLayerExists({job:job,layer:ms_layer})){
var feature = GEN.getFeatures({job:job,step:step,layer:ms_layer,units:par["units"]}); // break_sr
GEN.affectedLayer({affected:'yes',mode:'single',layer:line_chk,clear_before:'yes'});
if(feature && feature.length){
feature.forEach(function(feat){
if(feat.type == "line"){
var line = {xs:feat["xs"]-0,xe:feat["xe"]-0,ys:feat["ys"]-0,ye:feat["ye"]-0};
var tmpline = getLineParallel(line, length/ 2000)
var line1 = tmpline.line1
var line2 = tmpline.line2
var point1 = get_line_center(line1);
var point2 = get_line_center(line2);
var line_new = {xs:point1["x"],ys:point1["y"],xe:point2["x"],ye:point2["y"]};
GEN.addLine({xs:line_new["xs"],ys:line_new["ys"],xe:line_new["xe"],ye:line_new["ye"],symbol:'r'+width});
}
})
}
}
// 此处报错 ??
// var feature = GEN.getFeatures({job:job,step:step,layer:ms_layer,units:par["units"]}); //// break_sr
// GEN.affectedLayer({affected:'yes',mode:'single',layer:line_chk,clear_before:'yes'});
// if(feature && feature.length){
// feature.forEach(function(feat){
// if(feat.type != "line"){
// var line = {xs:feat["xs"],xe:feat["xe"],ys:feat["ys"],ye:feat["ye"]};
// var line1 = GenMath.get_line_parallel(line,length/2000);
// var line2 = GenMath.get_line_parallel(line,-length/2000);
// var point1 = GenMath.get_line_center(line1);
// var point2 = GenMath.get_line_center(line2);
// var line_new = {xs:point1["x"],ys:point1["y"],xe:point2["x"],ye:point2["y"]};
// GEN.addLine({xs:line_new["xs"],ys:line_new["ys"],xe:line_new["xe"],ye:line_new["ye"],symbol:'r'+width});
// }
// })
// }
GEN.selClearFeature();
var feature_line = GEN.getFeatures({job:job,step:step,layer:line_chk,units:par["units"]}); // break_sr
GEN.affectedLayer({affected:'yes',mode:'single',layer:add_pad,clear_before:'yes'});
if(feature_line && feature_line.length){
feature_line.forEach(function(feat){
if(feat.type != "line"){
GEN.addLine({xs:feat["xs"],ys:feat["ys"],xe:feat["xs"],ye:feat["ys"],symbol:'r'+width});
GEN.addLine({xs:feat["xe"],ys:feat["ye"],xe:feat["xe"],ye:feat["ye"],symbol:'r'+width});
}
})
}
GEN.affectedLayer({affected:'yes',mode:'single',layer:touch_lyr,clear_before:'yes'});
GEN.addRectangle({x1:profile_limits["xmin"],y1:profile_limits["ymin"],x2:profile_limits["xmax"],y2:profile_limits["ymax"]});
GEN.workLayer({name:layer,display_number:2,clear_before:'yes'})
GEN.selAllFeat()
if (GEN.getSelectCount()>0){
GEN.selCopyOther({dest:'layer_name',target_layer:touch_lyr,invert:'yes',dx:0,dy:0,size:width+0.5})
};
GEN.affectedLayer({affected:'yes',mode:'single',layer:touch_lyr,clear_before:'yes'});
GEN.selContourize();
GEN.affectedLayer({affected:'yes',mode:'single',layer:line_chk,clear_before:'yes'});
GEN.selRefFeat({layers:touch_lyr,use:'filter',mode:'touch'});
if ( GEN.getSelectCount() > 0 ){GEN.selDelete()};
GEN.affectedLayer({affected:'yes',mode:'single',layer:add_pad,clear_before:'yes'});
GEN.selRefFeat({layers:layer,use:'filter',mode:'cover'});
GEN.selReverse();
if ( GEN.getSelectCount() > 0 ){GEN.selDelete()};
////
GEN.affectedLayer({affected:'yes',mode:'single',layer:[line_chk,add_pad],clear_before:'yes'});
GEN.selAllFeat()
GEN.selChangeSym({symbol:'r0.1'});
GEN.workLayer({name:line_chk,display_number:1,clear_before:'yes'});
GEN.selRefFeat({layers:add_pad,use:'filter',mode:'touch'});
GEN.selAddAttr({attribute:[{attribute:'.string',text:'bridge'}]});
GEN.selAllFeat()
GEN.selChangeSym({symbol:'r'+width});
GEN.selectByFilter({attribute:[{attribute:'.string',text:'bridge'}]});
if( GEN.getSelectCount()>0){GEN.selMoveOther({target_layer:line_ok,invert:'no',dx:0,dy:0,size:0}) };
GEN.selAddAttr({attribute:[{attribute:'.string',text:'bridge'}]});
GEN.affectedLayer({affected:'yes',mode:'single',layer:[line_ok,line_chk],clear_before:'yes'});
GEN.selRefFeat({layers:layer,use:'filter',mode:'touch',f_types:'line\;arc'});
if( GEN.getSelectCount()>0){GEN.selDelete() };
GEN.affectedLayer({ mode:'all',affected:'no' });
GEN.displayLayer({name:layer,number:2});
GEN.displayLayer({name:line_ok,number:3});
GEN.COM("disp_on");
GEN.COM("disp_off");
GEN.copyLayer({source_job:job,source_step:step,source_layer:line_ok,dest_layer:layer,mode:'append',invert:'no'});
GEN.copyLayer({source_job:job,source_step:step,source_layer:line_chk,dest_layer:layer,mode:'append',invert:'no'});
if(GEN.isLayerExists({job:job,layer:ms_layer})){
GEN.deleteLayer({job:job,layer:[ms_layer]})
}
if(GEN.isLayerExists({job:job,layer:mk_layer})){
GEN.deleteLayer({job:job,layer:[mk_layer]})
}
GEN.deleteLayer({job:job,layer:[line_chk,line_ok,add_pad,touch_lyr],step:step});
if (/yes/ig.test(par["del_backup"])){GEN.deleteLayer({job:job,layer:[layer+'_tl+++'],step:step})};
})
GEN.COM("disp_on");
var ans_chk_new = create_checklist_and_run_analysis({layers:n_layers,aux:0,job:job, step:step}, par);
GEN.affectedLayer({mode:'all',affected:'no'});
GEN.clearLayers();
GEN.zoomHome();
})
// 保存
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"})
}
console.log("======================== JTG_OUT_delete_individual_pad_aim end");
if (mode === "aimdfm") {
$.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
};
}
}else {
return "Done"
}
} catch (e) {
IKM.msg(_.join(GEN.STATUS, "\n"))
IKM.msg(e)
Status = 'error';
resultData.push({type: "error", title: "脚本执行出错!", detail: [{desc: _.toString(e)}]});
return (mode === "aimdfm") ? {status: Status, result_data: resultData} : "Error";
}
function create_checklist_and_run_analysis(obj, par){
var job = obj.job;
var step = obj.step;
var layers = obj.layers;
var num = par["width"];
var nact = 1;
var checklist = 'tmp_signal_analysis';
var params = {}, items = []
params["pp_layer"] = '.affected';
params["pp_tests"] = 'Bottleneck';
params["pp_selected"] = 'All';
// params["pp_selected"] = 'Selected';
items.push({
name:'tmp_signal_check',
nact:nact,
action:'valor_analysis_signal',
erf:par.erf,
mode:'regular',
params:params,
})
if(GEN.isChklistExists({job:job,step:step,chklist:checklist})){
GEN.COM("chklist_delete,chklist="+checklist)
}
GEN.createChklist({chklist:checklist,items:items});
GEN.affectedLayer({affected:'yes',layer:layers,clear_before:'yes'});
if (obj["aux"] == 1){
GEN.COM('filter_reset',{filter_name:'popup'});
GEN.selectByFilter({feat_types:'surface',polarity:'positive',profile:'all'});
GEN.COM('filter_reset',{filter_name:'popup'});
}
GEN.COM('chklist_run',{chklist:checklist,nact:nact,area:'profile'});
GEN.chklistErfRange({
job:job,step:step,chklist:checklist,nact:nact,erf:par.erf,default_range:[0,0,0.1],
range:{
conductor_width : [num,num+1,num+2],
}
});
if (obj["aux"] == 1) {
// var meas = GEN.getCheckMeas({
// job: job,
// step:step,
// chklist:checklist,
// nact:nact,
// })
// var cflag = true;
// meas.forEach(function(item){ // 结果存在 [""] 的情况,会继续导致下面的命令报错
// if(item.trim() == ''){
// cflag = false;
// }
// })
// if(meas.length > 0 && cflag){
// GEN.COM("chklist_create_lyrs,chklist="+checklist+",severity=0,suffix=");
// }
}
else {
GEN.chklistShow({chklist:checklist});
GEN.COM("chklist_res_show,chklist="+checklist+",nact="+nact+",x=0,y=0,w=0,h=0");
}
}
function get_line_center(line){
var xs = line.xs
var ys = line.ys
var xe = line.xe
var ye = line.ye
return {x:(xs+xe)/2,y:(ys+ye)/2}
}
function getLineParallel(line,length){
var xs = line.xs
var ys = line.ys
var xe = line.xe
var ye = line.ye
var linelength = Math.sqrt((xe-xs)*(xe-xs) + (ye-ys)*(ye-ys))
var ylengthq = Math.abs(xe - xs) / linelength * length
var xlengthq = Math.abs(ye - ys) / linelength * length
if((xe-xs)*(ye-ys) > 0){
return {
line1: {
xs: xs + xlengthq,
xe: xe + xlengthq,
ys: ys - ylengthq,
ye: ye - ylengthq,
},
line2: {
xs: xs - xlengthq,
xe: xe - xlengthq,
ys: ys + ylengthq,
ye: ye + ylengthq,
}
}
} else if (ye == ys) {
return {
line1: {
xs: xs,
xe: xe,
ys: ys - length,
ye: ye - length,
},
line2: {
xs: xs,
xe: xe,
ys: ys + length,
ye: ye + length,
}
}
} else if (xe == xs) {
return {
line1: {
xs: xs- length,
xe: xe- length,
ys: ys ,
ye: ye ,
},
line2: {
xs: xs +length,
xe: xe +length,
ys: ys,
ye: ye,
}
}
} else {
return {
line1: {
xs: xs + xlengthq,
xe: xe + xlengthq,
ys: ys + ylengthq,
ye: ye + ylengthq,
},
line2: {
xs: xs - xlengthq,
xe: xe - xlengthq,
ys: ys - ylengthq,
ye: ye - ylengthq,
}
}
}
};