/* NAME: DESCRIPTION: 去除重复线; PARAMETER: [ { name : 'step', title : 'step', type : 'LineEdit', property : {tool_tip : '目标step,默认是orig'} }, { name : 'auto_save', title : '自动保存', type : 'RadioBox', property : { item_list:[ {name:'yes',text:'YES'}, {name:'no',text:'NO'}, ], tool_tip:'是否自动保存料号开关' } } ] VERSION_HISTORY: V1.00 2021-04-08 template 1.新版本 HELP:

功能简介

template

参数配置

去除重复线


注意事项


*/ // 引入模块 包 外部参数 var $ = require('topcam.scriptfunc').argv(); var fs = require('fs'); var _ = require('lodash'); var mode = $.ikm ? "topcam" : "aimdfm"; var IKM = $.ikm ? $.ikm : require('topcam.ikm6')($); var GEN = $.gen; var Job = $.job || $.job_name; var JobId = $.job_id; var db = $.db || IKM.db; var plugin = require('topsin.gengui'); var GUI = plugin.newGui(plugin.__dirname); var PAR = {}; if ($.par) { PAR = $.par; } else if ($.hasOwnProperty('script_parameter')) { PAR = JSON.parse($.script_parameter); } if (mode === "aimdfm") { IKM.crud("updateRow", { table: "pdm_aimdfm_task", data: { current_process_title: $.process_title }, where: { id: $.task_id } }); } var Status = 'ok'; var resultData = []; var par = PAR; // 接收参数 var default_par = { // 设置默认参数 step: "cad", auto_save: "No", workLayers:"rout", units: "mm" }; for (var key in default_par) { if (!par.hasOwnProperty(key) || par[key] == "") { par[key] = default_par[key]; } } // 定义变量 var job = Job.toLowerCase(); require("topsin.genmath"); var genMath = new GenMath(); try { // 常规验证 准备工作 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 }); stepList = stepList.filter(function (v) { var tmpreg = new RegExp(par.step, "ig"); return tmpreg.test(v); }); if (stepList.length == 0) { throw "未找到" + par.step } // var workLayers = par.workLayers.split(";") // workLayers = workLayers.filter(function(l){return GEN.isLayerExists({job:job, layer:l})}) // if(workLayers.length == 0) { // throw "没有找到工作层" // } var workLayers = getWorkLayer() if (workLayers && workLayers.length > 0) {} else { throw "没有找到工作层"} var func = 'function(props){return GUI.showForm({\ title: "去除重复线",\ size: "400x220",\ use_core_engine: true,\ include_hidden_items: true,\ items: {\ type: "ScrollArea",\ property: {\ widget_resizable: true,\ frame_shape: "NoFrame"\ },\ child: [{\ type: "FormGridLayout",\ property: {\ },\ child: [{\ name : "min_line",\ title: "min_line",\ type : "LineEdit",\ property : {tool_tip : "min_line"}\ },{\ name : "max_line",\ title: "max_line",\ type : "LineEdit",\ property : {tool_tip : "max_line"}\ },{\ name : "margin",\ title: "margin",\ type : "LineEdit",\ property : {tool_tip : "margin"}\ }]\ }]\ },\ values: { min_line: 0, max_line: 508,margin:-10 },\ }) }'; workLayers = workLayers.map(function (item) { return item.name }); var data = IKM.command(func, {}, 1).data; if(data.hasOwnProperty("margin") && data.hasOwnProperty("max_line") && data.hasOwnProperty("min_line")) { stepList.forEach(function (step) { GEN.openStep({ job: job, name: step }); GEN.clearLayers(); //清除层显示 GEN.affectedLayer({ mode: 'all', affected: 'no' }); //设置影响层全部不影响 GEN.COM("sel_options,clear_mode=clear_after,display_mode=all_layers,area_inout=inside,area_select=select,select_mode=standard,area_touching_mode=exclude"); GEN.units({ type: par.units }); //单位初始化 GEN.zoomHome(); //窗口显示回到原始位置 GEN.selClearFeature() GEN.affectedLayer({affected:"yes", layer:workLayers}) GEN.COM("chklist_single,action=valor_dfm_nflr,show=yes") GEN.COM("chklist_cupd,chklist=valor_dfm_nflr,nact=1,params=((pp_layer=.affected)(pp_min_line="+data.min_line+")(pp_max_line="+data.max_line+")(pp_margin="+data.margin+")(pp_remove_item=Line\;Arc)(pp_delete=Covered)(pp_work=Features)(pp_remove_mark=Remove)),mode=regular") GEN.COM("chklist_run,chklist=valor_dfm_nflr,nact=1,area=global") GEN.COM("chklist_single,action=valor_dfm_nflr,show=yes") GEN.COM("chklist_cupd,chklist=valor_dfm_nflr,nact=1,params=((pp_layer=.affected)(pp_min_line="+data.min_line+")(pp_max_line="+data.max_line+")(pp_margin="+data.margin+")(pp_remove_item=Line\;Arc)(pp_delete=Duplicated)(pp_work=Features)(pp_remove_mark=Remove)),mode=regular") GEN.COM("chklist_run,chklist=valor_dfm_nflr,nact=1,area=global") GEN.COM("chklist_close,chklist=valor_dfm_nflr,mode=hide") // workLayers.forEach(function (layer) { // check_connect_line_and_connnect({layer:layer,step:step}) // }) GEN.affectedLayer({ mode: 'all', affected: 'no' }); //设置影响层全部不影响 GEN.clearLayers(); //清除层显示 }); } // 保存料号 if (/yes/ig.test(par.auto_save)) { GEN.checkInout({ job: job, mode: "out" }); GEN.saveJob({ job: job }); GEN.checkInout({ job: job, mode: "in" }); } // 结尾返回 固定写法 var Return = "Done"; if (mode === "aimdfm") { IKM.crud("updateRow", { table: "pdm_aimdfm_task", data: { progress: 100 }, where: { id: $.task_id } }); var tmperr = { type: "info", title: "操作完成, 请注意检查!" }; if (GEN.hasError()) { Status = 'error'; tmperr = { type: "error", title: "GEN错误!", detail: [{ desc: GEN.STATUS.join("\n") }] }; } resultData.push(tmperr); Return = { status: Status, result_data: resultData }; } return Return; } catch (e) { var showGUI = true; if (GEN.STATUS.length > 0) { if (GEN.STATUS.indexOf("Pause Exit:0") >= 0) { showGUI = false; } e = _.toString(e) + "\n" + GEN.STATUS.join("\n"); } if (showGUI) { IKM.msg(e); } Status = 'error'; resultData.push({ type: "error", title: "脚本执行出错!", detail: [{ desc: _.toString(e) }] }); return mode === "aimdfm" ? { status: Status, result_data: resultData } : "Error"; } /** * 获取层别 * @param {Object} 过滤选项 * @returns {Array} */ function getLayer(props) { if (!props) { props = {}; } var matrix = GEN.getMatrix({ job: job }); return Object.keys(matrix).reduce(function (a, b) { var info = matrix[b]; var ret = true; for (var _key in props) { if (info[_key]) { if (/object string|object number/ig.test({}.toString.call(props[_key]))) { if (props[_key] != info[_key]) { ret = false; } } if (/object RegExp/ig.test({}.toString.call(props[_key]))) { if (!props[_key].test(info[_key])) { ret = false; } } if (/object function/ig.test({}.toString.call(props[_key]))) { if (!props[_key](info[_key])) { ret = false; } } } } if (ret) { a.push(props.res == "info" ? info : b); } return a; }, []); } function check_connect_line_and_connnect(props){ var step = props.step GEN.COM("disp_off"); GEN.affectedLayer({affected:'yes',layer:props.layer,clear_before:'yes'}); GEN.flattenLayer({source_layer:props.layer,target_layer:props.layer+'++tl++tmp++'}); // GEN.selCopyOther(target_layer:props.layer.'++tl++tmp++',invert:'no'); GEN.affectedLayer({affected:'yes',layer:props.layer+'++tl++tmp++',clear_before:'yes'});//当前工作层 //1.去重复和cover var check_list = 'topcam_tl_nflr_cover'; if (GEN.isChklistExists({ job: job, step: step, chklist: check_list })) { GEN.COM("chklist_delete", { chklist: check_list }); } var params={} var items=[]; params.pp_layer = '.affected'; params.pp_min_line = 0; params.pp_max_line = 2540; params.pp_margin = 25.4; params.pp_remove_item = 'Line\;Arc'; params.pp_delete = 'Covered'; params.pp_work = 'Features'; params.pp_remove_mark = 'Remove'; items.push({ name:'tl_nflr_cover', nact:1, action:'valor_dfm_nflr', erf:'Report All (Mils)', params:params, }) GEN.createChklist({chklist:check_list,items:items}); GEN.COM('chklist_run',{chklist:check_list,nact:1,area:'profile'}); var check_list_ = 'topcam_tl_nflr_duplicated'; if ( GEN.isChklistExists({job:Job,step:step,chklist:check_list_}) ){ GEN.COM("chklist_delete",{chklist:check_list_}); } var params_={} var items_=[]; params_.pp_layer = '.affected'; params_.pp_min_line = 0; params_.pp_max_line = 2540; params_.pp_margin = 25.4; params_.pp_remove_item = 'Line\;Arc'; params_.pp_delete = 'Duplicated'; params_.pp_work = 'Features'; params_.pp_remove_mark = 'Remove'; items_.push({ name:'tl_nflr_duplicated', nact:1, action:'valor_dfm_nflr', erf:'Report All (Mils)', params:params_, }) GEN.createChklist({chklist:check_list_,items:items_}); GEN.COM('chklist_run',{chklist:check_list_,nact:1,area:'profile'}); GEN.selBreak(); GEN.COM( "sel_design2rout,det_tol=10,con_tol=10,rad_tol=1" );//先修复一次 10mil内 var feat = GEN.getFeatures({job:Job,step:step,layer:props.layer+'++tl++tmp++'});//抽取特殊槽 if (GEN.isLayerExists({job:Job,layer:'tl++other++tmp++'})){ GEN.deleteLayer({job:Job,layer:'tl++other++tmp++',step:step}) }; feat.forEach(function (tmp) { var size = tmp.symbol.slice(1) - 0; if (size >= 31.496) { GEN.COM('filter_reset',{filter_name:'popup'}); GEN.selectByFilter({include_syms:tmp.symbol,profile:'all'}); GEN.COM('filter_reset',{filter_name:'popup'}); if ( GEN.getSelectCount() > 0 ){ GEN.selMoveOther({target_layer:'tl++other++tmp++',invert:'no',dx:0,dy:0,size:0}); } } }) GEN.selChangeSym({symbol:'r1'}); GEN.COM('profile_to_rout',{layer:'tl+wai++',width:0}); GEN.affectedLayer({affected:'yes',layer:'tl+wai++',clear_before:'yes'}); GEN.COM( "sel_cut_data,det_tol=1,con_tol=1,rad_tol=0.1,filter_overlaps=no,delete_doubles=no,use_order=yes,ignore_width=yes,ignore_holes=all,start_positive=yes,polarity_of_touching=same"); GEN.affectedLayer({affected:'yes',layer:'tl+wai+++++',clear_before:'yes'}); GEN.COM('sr_fill',{ polarity : 'positive', step_margin_x : 0, step_margin_y : 0, step_max_dist_x : 100, step_max_dist_y : 100, sr_margin_x : 0, sr_margin_y : 0, sr_max_dist_x : 0, sr_max_dist_y : 0, nest_sr : 'yes', stop_at_steps : '', consider_feat : 'no', consider_drill : 'no', consider_rout : 'no', dest : 'affected_layers', attributes : 'no'}); GEN.COM('fill_params',{ type : 'solid', origin_type : 'datum', solid_type : 'fill', std_type : 'line', min_brush : 1, use_arcs : 'yes', symbol : '', dx : '0.1', dy : '0.1', x_off : 0, y_off : 0, std_angle : 45, std_line_width : 10, std_step_dist : 50, std_indent : 'odd', break_partial : 'yes', cut_prims : 'no', outline_draw : 'no', outline_width : 0, outline_invert : 'no'}); GEN.COM('sel_fill'); GEN.selContourize(); GEN.selCopyOther({target_layer:'tl+wai++',invert:'yes'});//单只的suface GEN.affectedLayer({affected:'yes',layer:'tl+wai++',clear_before:'yes'}); GEN.selContourize(); GEN.COM('sel_resize', {size : -10, corner_ctl : 'no'}); GEN.COM('sel_resize', {size : 20, corner_ctl : 'no'}); GEN.COM('fill_params', {type : 'solid', origin_type : 'datum', solid_type : 'fill', std_type : 'line', min_brush : 1, use_arcs : 'yes', symbol : '', dx : '0.1', dy : '0.1', x_off : 0, y_off : 0, std_angle : 45, std_line_width : 10, std_step_dist : 50, std_indent : 'odd', break_partial : 'yes', cut_prims : 'no', outline_draw : 'no', outline_width : 0, outline_invert : 'no'}); GEN.COM('sel_fill'); GEN.selContourize(); GEN.createLayer({job:Job,layer:'++profice++tmp++',context:'misc',type:'document',delete_exists:'yes'}); GEN.affectedLayer({affected:'yes',layer:'++profice++tmp++',clear_before:'yes'}); var profile = GEN.getProfileLimits({job:Job,step:step}); GEN.addRectangle({x1:profile.xmin,y1:profile.ymin,x2:profile.xmax,y2:profile.ymax,type:'line',symbol:'r1'}); GEN.affectedLayer({affected:'yes',layer:props.layer+'++tl++tmp++',clear_before:'yes'});//工作层 GEN.selCopyOther({target_layer:'tl+wai+++++',invert:'yes'}); GEN.affectedLayer({affected:'yes',layer:'tl+wai+++++',clear_before:'yes'});//工作层 GEN.selContourize(); GEN.COM('fill_params', {type : 'solid', origin_type : 'datum', solid_type : 'fill', std_type : 'line', min_brush : 1, use_arcs : 'yes', symbol : '', dx : '0.1', dy : '0.1', x_off : 0, y_off : 0, std_angle : 45, std_line_width : 10, std_step_dist : 50, std_indent : 'odd', break_partial : 'yes', cut_prims : 'no', outline_draw : 'no', outline_width : 0, outline_invert : 'no'}); GEN.COM('sel_fill'); GEN.selContourize(); GEN.selRefFeat({layers:'++profice++tmp++',use:'filter',mode:'disjoint'}); if ( GEN.getSelectCount() > 0 ){GEN.selDelete() }; GEN.selRefFeat({layers:'tl+wai++',use:'filter',mode:'touch'}); if ( GEN.getSelectCount() > 0 ){GEN.selDelete() }; GEN.COM('sel_resize', {size : 10, corner_ctl : 'no'}); GEN.selMoveOther({target_layer:'tl+wai++',invert:'no',dx:0,dy:0,size:1}); GEN.affectedLayer({affected:'yes',layer:props.layer+'++tl++tmp++',clear_before:'yes'}); GEN.selRefFeat({layers:'tl+wai++',use:'filter',mode:'cover'}); if (GEN.getSelectCount() > 0){ GEN.selRefFeat({layers:'tl+wai++',use:'select',mode:'touch'}); if (GEN.getSelectCount() > 0){ GEN.createLayer({job:Job,layer:'++tl+connect+line+',context:'misc',type:'document',delete_exists:'yes'}); GEN.selMoveOther({target_layer:'++tl+connect+line+',invert:'no',dx:0,dy:0,size:0}); //2.检测连接点及重绘 var feat1 = GEN.getFeatures({job:Job,step:step,layer:'++tl+connect+line+'});//连接层数据 var feat2 = GEN.getFeatures({job:Job,step:step,layer:props.layer+'++tl++tmp++'});//被连接层数据 //GEN.createLayer(job=>$Job,layer=>'+tmp++',context=>'misc',type=>'document',delete_exists=>'yes');//测试数据层 feat1.forEach(function (tmp1) { var line_tmp = []; if (tmp1.type == 'line') { var line1 = genMath.extend_line({xs:tmp1.xs,ys:tmp1.ys,xe:tmp1.xe,ye:tmp1.ye},0.3937);// var line2 = genMath.extend_line({xs:line1.xe,ys:line1.ye,xe:line1.xs,ye:line1.ys},0.3937); var line = {xs:line2.xe,ys:line2.ye,xe:line2.xs,ye:line2.ys}; //GEN.workLayer(name=>'+tmp++',display_number=>1,clear_before=>'yes'); //GEN.addLine(xs=>$line->{xs},ys=>$line->{ys},xe=>$line->{xe},ye=>$line->{ye},symbol=>'r2'); feat2.forEach(function (tmp2) { var line_x1 = line.xs < line.xe ? line.xs : line.xe; var line_x2 = line.xs < line.xe ? line.xe : line.xs; var line_y1 = line.ys < line.ye ? line.ys : line.ye; var line_y2 = line.ys < line.ye ? line.ye : line.ys; var line2_x1 = tmp2.xs < tmp2.xe ? tmp2.xs : tmp2.xe; var line2_x2 = tmp2.xs < tmp2.xe ? tmp2.xe : tmp2.xs; var line2_y1 = tmp2.ys < tmp2.ye ? tmp2.ys : tmp2.ye; var line2_y2 = tmp2.ys < tmp2.ye ? tmp2.ye : tmp2.ys; if((line2_x1 >= line_x1 && line2_x2 <= line_x2 && line2_y1 <= line_y1 && line2_y2 >= line_y2) || (line2_x1 <= line_x1 && line2_x2 >= line_x2 && line2_y1 >= line_y1 && line2_y2 <= line_y2)){ var dis = genMath.line2line_dist({xs:tmp1.xs,ys:tmp1.ys,xe:tmp1.xe,ye:tmp1.ye}, {xs:tmp2.xs,ys:tmp2.ys,xe:tmp2.xe,ye:tmp2.ye}); tmp2.distance = dis; line_tmp.push(tmp2) } }) } //计算交点坐标 先冒泡排序一次 var add_line = []; if (line_tmp.length > 1) { for(var i = 0;i < line_tmp.length;i++){ for(var k = i + 1;k < line_tmp.length; k++){ if (line_tmp[k].distance < line_tmp[i].distance) { var tmp; tmp = line_tmp[i]; line_tmp[i] = line_tmp[k]; line_tmp[k] = tmp; } } } var i = 1; for(var i=0;i < 2;i++){ add_line.push( genMath.get_line_intersect({xs:tmp1.xs,ys:tmp1.ys,xe:tmp1.xe,ye:tmp1.ye}, {xs:line_tmp[i].xs,ys:line_tmp[i].ys,xe:line_tmp[i].xe,ye:line_tmp[i].ye},1) ) } } //GEN.workLayer(name=>$par{layer}.'++tl++tmp++',display_number=>1,clear_before=>'yes'); GEN.affectedLayer({affected:'yes',layer:props.layer+'++tl++tmp++',clear_before:'no'}); GEN.addLine({xs:add_line[0].x,ys:add_line[0].y,xe:add_line[1].x,ye:add_line[1].y,symbol:'r2',attributes:[{attribute:'.string',text:'tl_rou_line'}]}); }); } } GEN.affectedLayer({affected:'yes',layer:props.layer+'++tl++tmp++',clear_before:'yes'}); GEN.selChangeSym({symbol:'r10'}); if (GEN.isLayerExists({job:Job,layer:'tl++other++tmp++'})){ GEN.affectedLayer({affected:'yes',layer:'tl++other++tmp++',clear_before:'yes'}); GEN.selMoveOther({target_layer:props.layer+'++tl++tmp++',invert:'no',dx:0,dy:0,size:0}); GEN.deleteLayer({job:Job,layer:'tl++other++tmp++',step:step}); } if (GEN.isLayerExists({job:Job,layer:'tl+wai++'})){ GEN.deleteLayer({job:Job,layer:['tl+wai+++++','tl+wai++','++profice++tmp++','++tl+connect+line+'],step:step}) };//删除临时层 GEN.COM("disp_on"); IKM.msg(props.layer+"层连接位修复完成请仔细检查!") GEN.PAUSE('Please Check!'); } function getWorkLayer() { var matrix = GEN.getMatrix({ job: job }); return GUI.selectLayer({ title: "请选择层", //filter: ".*", // regular expression selectmode: "multiple", // single, multiple context: "all", // all, board, misc layertype: par.workLayers, // default type of layertypelist defaultsize: [600, 400], // window size layermatrix: matrix, layertypelist: [{ name: "all", display_name: "All", filter: function filter(x) { return true; } }, { name: "outer", display_name: "Outer", filter: function filter(x) { return x.layer_type == "signal" && /top|bot/.test(x.side); } }, { name: "inner", display_name: "Inner", filter: function filter(x) { return (/signal|power_ground/.test(x.layer_type) && /inner/.test(x.side) ); } }, { name: "solder_mask", display_name: "Solder Mask", filter: function filter(x) { return (/solder_mask/.test(x.layer_type) ); } }, { name: "silk_screen", display_name: "Silk Screen", filter: function filter(x) { return (/silk_screen/.test(x.layer_type) ); } }, { name: "rout", display_name: "Rout", filter: function filter(x) { return (/rout/.test(x.layer_type) || /outline/.test(x.name)); } }], gen: GEN }); }