/*
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 p>
参数配置
去除重复线
注意事项
无
*/
// 引入模块 包 外部参数
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
});
}