Commit 59890c98 authored by Scott Sun's avatar Scott Sun

scott

parent cae41a62
var plugin = require('topsin.gengui');
var gui = plugin.newGui();
var tmplayers = gui.selectLayer({
title: '请选择需拼片原稿层',
layermatrix: {
layer1: {
row: 1,
name: "layer1",
layer_type: "inner"
},
layer2: {
row: 2,
name: "layer2",
layer_type: "outer"
}
},
layertype: "_default",
layertypelist: [{
name: "_default",
display_name: "_default",
filter: function (x) {
return true
}
}, ],
selectmode: 'multiple',
filter: ".*", // regular expression
selectmode: "single", // single, multiple
context: "all", // all, board, misc
defaultsize: [600, 400], // window size
gen:null
});
console.log(tmplayers);
\ No newline at end of file
...@@ -229,7 +229,6 @@ r = gui.selectLayer({ ...@@ -229,7 +229,6 @@ r = gui.selectLayer({
filter: ".*", // regular expression filter: ".*", // regular expression
selectmode: "single", // single, multiple selectmode: "single", // single, multiple
context: "all", // all, board, misc context: "all", // all, board, misc
layertype: "inner", // default type of layertypelist
defaultsize: [600, 400], // window size defaultsize: [600, 400], // window size
layermatrix: { layermatrix: {
layer1: { layer1: {
...@@ -243,6 +242,7 @@ r = gui.selectLayer({ ...@@ -243,6 +242,7 @@ r = gui.selectLayer({
layer_type: "outer" layer_type: "outer"
} }
}, },
layertype: "inner", // default type of layertypelist
layertypelist: [ layertypelist: [
{name: "inner", display_name: "Inner", filter: function(x) { return x["layer_type"] === "inner"; }}, {name: "inner", display_name: "Inner", filter: function(x) { return x["layer_type"] === "inner"; }},
{name: "outer", display_name: "Outer", filter: function(x) { return x["layer_type"] === "outer"; }} {name: "outer", display_name: "Outer", filter: function(x) { return x["layer_type"] === "outer"; }}
......
...@@ -14,7 +14,7 @@ PARAMETER: ...@@ -14,7 +14,7 @@ PARAMETER:
] ]
VERSION_HISTORY: VERSION_HISTORY:
V1.00 2020-04-20 Scott Sun V1.01 2020-04-20 Scott Sun
1.新版本 1.新版本
HELP: HELP:
...@@ -73,11 +73,11 @@ var Status = 'ok'; ...@@ -73,11 +73,11 @@ var Status = 'ok';
var resultData = []; var resultData = [];
try { try {
console.log("=============================check in===================="); console.log("=============================check in====================");
GEN.COM("open_job,job="+Job+",open_win=no,disk_map=,job_map=") // GEN.COM("open_job,job="+Job+",open_win=no,disk_map=,job_map=")
GEN.AUX("set_group,group=99") // GEN.AUX("set_group,group=99")
GEN.COM("close_job,job="+Job+"") // GEN.COM("close_job,job="+Job+"")
GEN.COM("disp_on") // GEN.COM("disp_on")
GEN.COM("origin_on") // GEN.COM("origin_on")
GEN.COM("disp_on") GEN.COM("disp_on")
GEN.COM("origin_on") GEN.COM("origin_on")
GEN.COM("checkin_closed_job,job="+Job); GEN.COM("checkin_closed_job,job="+Job);
......
...@@ -108,7 +108,6 @@ var GUI = $.gui || {}; ...@@ -108,7 +108,6 @@ var GUI = $.gui || {};
var Job = $.job || $.job_name; var Job = $.job || $.job_name;
var JobId = $.job_id; var JobId = $.job_id;
var process = require('process'); var process = require('process');
var zip = require('topsin.zip');
var db = $.db || IKM.db var db = $.db || IKM.db
var PAR = {} var PAR = {}
if ($.par) { if ($.par) {
...@@ -168,10 +167,10 @@ if(mailUserList && mailUserList.length) { ...@@ -168,10 +167,10 @@ if(mailUserList && mailUserList.length) {
var cam_workflow_info = IKM.get_jobinfo({jobid:JobId, jobinfo:"cam_workflow_info"}); var cam_workflow_info = IKM.get_jobinfo({jobid:JobId, jobinfo:"cam_workflow_info"});
console.log("==========cam_workflow_info===========:" + cam_workflow_info); console.log("==========cam_workflow_info===========:" + cam_workflow_info);
try { try {
if(cam_workflow_info && cam_workflow_info != ""){ // if(cam_workflow_info == "err"){ // ! tmp
console.log("==========cam_workflow_info===========:" + cam_workflow_info); // console.log("==========cam_workflow_info===========:" + cam_workflow_info);
throw cam_workflow_info // throw cam_workflow_info
} // }
cam_workflow_info = "sendmail" cam_workflow_info = "sendmail"
console.log("=============================================>anaysis_start"); console.log("=============================================>anaysis_start");
var par = PAR; var par = PAR;
...@@ -187,7 +186,7 @@ try { ...@@ -187,7 +186,7 @@ try {
// 检查料号是否能够check out // 检查料号是否能够check out
if(GEN.checkInout({job:job,mode:"test"}) != 0 && mode == "aimdfm"){ throw "the job check" } if(GEN.checkInout({job:job,mode:"test"}) != 0 && mode == "aimdfm"){ throw "the job check" }
GEN.checkInout({job:job,mode:"out"}); GEN.checkInout({job:job,mode:"out"});
script_info({ msg: "开始分析客户料号" ,result_severity:"info"}) script_info({ msg: "Data Analysis" ,result_severity:"info"})
script_info({ progress: 65 }) script_info({ progress: 65 })
var pcs_step = par.pcs_step == "" ? "cad" : par.pcs_step; var pcs_step = par.pcs_step == "" ? "cad" : par.pcs_step;
var array_step = par.array_step == "" ? "stp" : par.array_step; var array_step = par.array_step == "" ? "stp" : par.array_step;
...@@ -199,7 +198,7 @@ try { ...@@ -199,7 +198,7 @@ try {
pcs_step = step_list[0] pcs_step = step_list[0]
} }
script_info({ msg: "分析上传matrix信息",result_severity:"info" }) script_info({ msg: "Error-Upload matrix",result_severity:"info" })
script_info({ progress: 65 }) script_info({ progress: 65 })
var matrix = UPLOAD_LAYER_MATRIX({job:job}) // 分析matrix 获得分析后的matrix信息 var matrix = UPLOAD_LAYER_MATRIX({job:job}) // 分析matrix 获得分析后的matrix信息
GEN.openStep({job:job, name:pcs_step}) GEN.openStep({job:job, name:pcs_step})
...@@ -255,7 +254,7 @@ try { ...@@ -255,7 +254,7 @@ try {
}) })
GEN.clearLayers() GEN.clearLayers()
script_info({ msg: "分析钻孔叠构" }) script_info({ msg: "Error-Drill Stackup analysis" })
script_info({ progress: 70 }) script_info({ progress: 70 })
// * new 钻孔叠构 // * new 钻孔叠构
var cam_drill_structure = [] var cam_drill_structure = []
...@@ -380,7 +379,7 @@ try { ...@@ -380,7 +379,7 @@ try {
var analysis_obj = analysis({job:job,jobId:JobId,pcs_step:pcs_step,array_step:array_step,matrix:matrix}) var analysis_obj = analysis({job:job,jobId:JobId,pcs_step:pcs_step,array_step:array_step,matrix:matrix})
// 创建profile // 创建profile
var tmp_matrix = GEN.getMatrix({job:job}) var tmp_matrix = GEN.getMatrix({job:job})
script_info({ msg: "分析profile" }) script_info({ msg: "Error-Profile analysis" })
script_info({ progress: 70 }) script_info({ progress: 70 })
// * profile 和 拼版 // * profile 和 拼版
var pandle_step = step_list.map(function(v){ var pandle_step = step_list.map(function(v){
...@@ -454,7 +453,7 @@ try { ...@@ -454,7 +453,7 @@ try {
} }
ALL.gold_fingers = gold_fingers ALL.gold_fingers = gold_fingers
GEN.closeStep() GEN.closeStep()
script_info({ msg: "分析料号信息" }) script_info({ msg: "Error-PN analysis" })
var config = { var config = {
jobInfo: { jobInfo: {
layer_count: ["signal","power_ground"], // Board属性的signal或者power_ground层 layer_count: ["signal","power_ground"], // Board属性的signal或者power_ground层
...@@ -534,7 +533,7 @@ try { ...@@ -534,7 +533,7 @@ try {
console.log("=================================> 5 save drill info") console.log("=================================> 5 save drill info")
script_info({ msg: "分析钻孔信息" }) script_info({ msg: "Error-Drill layer analysis" })
script_info({ progress: 75 }) script_info({ progress: 75 })
// * 获取pcs_step 和 array_step的钻孔信息 // * 获取pcs_step 和 array_step的钻孔信息
var drill_tool_info = {}; var drill_tool_info = {};
...@@ -659,7 +658,7 @@ try { ...@@ -659,7 +658,7 @@ try {
}) })
console.log("=============================> 6 set smd bga") console.log("=============================> 6 set smd bga")
script_info({ msg: "分析smd和bga" }) script_info({ msg: "Error-SMD&BGA analysis" })
script_info({ progress: 80 }); script_info({ progress: 80 });
step_list.forEach(function(step){ step_list.forEach(function(step){
GEN.openStep({job:job,name:step}) GEN.openStep({job:job,name:step})
...@@ -790,7 +789,7 @@ try { ...@@ -790,7 +789,7 @@ try {
}) })
var info = { var info = {
min_line_width: ["line","user_nor_line"], min_line_width: ["line","user_nor_line"],
min_line_spacing: ["l2l","user_nor_line2nor_line"], min_line_spacing: ["c2c","l2l","user_nor_line2nor_line"],
min_line2pad: ["p2line","user_010052nor_line","user_bga2nor_line-1","user_smd2nor_line","user_self_spacing_smd2l"], min_line2pad: ["p2line","user_010052nor_line","user_bga2nor_line-1","user_smd2nor_line","user_self_spacing_smd2l"],
min_pad2pad: ["p2p", "smd2smd", "smd2pad","via2via","bga2pad"], min_pad2pad: ["p2p", "smd2smd", "smd2pad","via2via","bga2pad"],
min_ar_laser:["laser_via_ar"], min_ar_laser:["laser_via_ar"],
...@@ -810,7 +809,7 @@ try { ...@@ -810,7 +809,7 @@ try {
// jobpath = "/home/local_db/server_db/jobs/"+job // jobpath = "/home/local_db/server_db/jobs/"+job
// } // }
mkPath(jobpath,["user","opcam","steps"]) mkPath(jobpath,["user","opcam","steps"])
script_info({ msg: "分析线路" }) script_info({ msg: "Error-Signal layer analysis" })
script_info({ progress: 85 }) script_info({ progress: 85 })
stepList.forEach(function(step){ stepList.forEach(function(step){
GEN.openStep({ job: job, name: step }) GEN.openStep({ job: job, name: step })
...@@ -925,6 +924,7 @@ try { ...@@ -925,6 +924,7 @@ try {
},[])[0] },[])[0]
return {layer:v,symbol:symbol,start:tmp_matrix[v]["drl_start"],end:tmp_matrix[v]["drl_end"]} return {layer:v,symbol:symbol,start:tmp_matrix[v]["drl_start"],end:tmp_matrix[v]["drl_end"]}
}) })
var drillRes = analysisDrill(drillToSignals,step) // 钻孔分析结果 var drillRes = analysisDrill(drillToSignals,step) // 钻孔分析结果
console.log("===============drillRes:" + _.toString(drillRes)); console.log("===============drillRes:" + _.toString(drillRes));
drillRes.forEach(function(item){ drillRes.forEach(function(item){
...@@ -963,7 +963,7 @@ try { ...@@ -963,7 +963,7 @@ try {
if(par.erf){ if(par.erf){
tmpitem.erf = par.erf tmpitem.erf = par.erf
} }
script_info({ msg: "运行线路分析checklist" }) script_info({ msg: "Error-Run Checklist",result_severity:"ok" })
createChklistAndRun({ // 创建checklist并运行 createChklistAndRun({ // 创建checklist并运行
layers: signalLayers, layers: signalLayers,
items: [tmpitem] items: [tmpitem]
...@@ -989,7 +989,6 @@ try { ...@@ -989,7 +989,6 @@ try {
GEN.closeStep() GEN.closeStep()
}) })
mvOutProfile({job:job, step:pcs_step}) mvOutProfile({job:job, step:pcs_step})
IKM.msg("end wait for save")
// 保存 // 保存
if(/yes/ig.test(par.auto_save)){ if(/yes/ig.test(par.auto_save)){
...@@ -1021,6 +1020,8 @@ try { ...@@ -1021,6 +1020,8 @@ try {
}); });
script_info({ progress: 95 }) script_info({ progress: 95 })
script_info({ msg: "analysis done" })
// 导出 // 导出
if(par.export_path != "" && par.export_mode != "" && par.export_submode != "" ){ if(par.export_path != "" && par.export_mode != "" && par.export_submode != "" ){
if(fs.exists(par.export_path)){ if(fs.exists(par.export_path)){
...@@ -1080,7 +1081,11 @@ catch (e) { ...@@ -1080,7 +1081,11 @@ catch (e) {
GEN.COM("origin_on") GEN.COM("origin_on")
GEN.COM("checkin_closed_job,job="+Job) GEN.COM("checkin_closed_job,job="+Job)
if( cam_workflow_info== "sendmail"){ if( cam_workflow_info== "sendmail"){
IKM.save_job_info({jobid:JobId, jobinfohash:{cam_workflow_info:_.toString(e)}}) IKM.crud("deleteRow", {
table: "pdm_job_jobattr",
where:{job_id:JobId, attr_name:"cam_workflow_info"},
})
IKM.save_job_info({jobid:JobId, jobinfohash:{cam_workflow_info:"err"}})
sendEmail({ sendEmail({
subject:db_customer + ' / '+Job+ " analysis error", subject:db_customer + ' / '+Job+ " analysis error",
content:_.toString(e) content:_.toString(e)
...@@ -2079,8 +2084,17 @@ function analysisChkAttr(par) { ...@@ -2079,8 +2084,17 @@ function analysisChkAttr(par) {
return hash return hash
} }
function analysisDrill(par, step){ function analysisDrill(par, step){
// {"layer":"d1-2","symbol":"r3.937","start":"top","end":"isl2"} // [{
// {"layer":"d1-2","symbol":"r35.0394","start":"top","end":"bottom"} // "layer": "ftdrill2-3l",
// "symbol": "r7.874",
// "start": "l2",
// "end": "l3"
// }, {
// "layer": "ftdrill",
// "symbol": "r7.874",
// "start": "top",
// "end": "bottom"
// }]
var job = Job.toLowerCase() var job = Job.toLowerCase()
GEN.affectedLayer({affected:'no',mode:'all'}) GEN.affectedLayer({affected:'no',mode:'all'})
var res = par.map(function(drill){ var res = par.map(function(drill){
...@@ -2097,21 +2111,31 @@ function analysisDrill(par, step){ ...@@ -2097,21 +2111,31 @@ function analysisDrill(par, step){
GEN.selClearFeature(); GEN.selClearFeature();
[drill.start,drill.end].forEach(function(item, i){ [drill.start,drill.end].forEach(function(item, i){
GEN.workLayer({name:item,display_number:1,clear_before:"yes"}) GEN.workLayer({name:item,display_number:1,clear_before:"yes"})
GEN.selClearFeature();
GEN.COM("filter_set,filter_name=popup,update_popup=no,feat_types=pad"); GEN.COM("filter_set,filter_name=popup,update_popup=no,feat_types=pad");
GEN.COM("sel_ref_feat",{layers:tmplayer,use:"filter",mode:"touch",pads_as:"shape",f_types:"pad",polarity:"positive\;negative",include_syms:drill.symbol}) GEN.COM("sel_ref_feat",{layers:tmplayer,use:"filter",mode:"touch",pads_as:"shape",f_types:"pad",polarity:"positive\;negative",include_syms:drill.symbol})
// GEN.selRefFeat({layers:tmplayer, use:"filter",mode:"touch"}) // GEN.selRefFeat({layers:tmplayer, use:"filter",mode:"touch"})
GEN.COM("filter_reset,filter_name=popup") GEN.COM("filter_reset,filter_name=popup")
if(GEN.getSelectCount()>0){ if(GEN.getSelectCount()>0){
var res = "" var res = "";
var pads = GEN.getFeatures({job:job,step:step,layer:item,options:"select"}) var pads = GEN.getFeatures({job:job,step:step,layer:item,options:"select"})
if(pads && pads.length) { if (pads && pads.length) {
pads = pads.filter(function(item){ pads = pads.map(function (item2) {
return /^r\d+/.test(item.symbol) if(!item2.size){
if(/^r\d+/.test(item2.symbol)){
item2.size = Number(item2.symbol.slice(1))
}else if(/^rect([^x]+)x([^x]+)/.test(item2.symbol)){
item2.size = Number(RegExp.$1 > RegExp.$2 ? RegExp.$1 :RegExp.$2)
}
} else {
item2.size = Number(item2.size)
}
return item2
}) })
pads = pads.sort(function(a,b){ pads = pads.sort(function (a, b) {
return parseInt(a.symbol.slice(1)) - parseInt(b.symbol.slice(1)) return a.size - b.size
}) })
res = pads[0].symbol.slice(1) res = pads[0].size
} }
if ( i == 0) { if ( i == 0) {
drill.drl_pad_top = res drill.drl_pad_top = res
......
...@@ -99,10 +99,10 @@ if(mailUserList && mailUserList.length) { ...@@ -99,10 +99,10 @@ if(mailUserList && mailUserList.length) {
} }
var cam_workflow_info = IKM.get_jobinfo({jobid:JobId, jobinfo:"cam_workflow_info"}); var cam_workflow_info = IKM.get_jobinfo({jobid:JobId, jobinfo:"cam_workflow_info"});
try { try {
if(cam_workflow_info && cam_workflow_info != ""){ // if(cam_workflow_info && cam_workflow_info != ""){ //! tmp
throw cam_workflow_info // throw cam_workflow_info
} // }
script_info({ msg: "料号标准化流程开始" ,result_severity:"info"}) script_info({ msg: "Data formatting" ,result_severity:"info"})
script_info({ progress: 35 }) script_info({ progress: 35 })
var par = PAR; var par = PAR;
if(!par.hasOwnProperty("config_path") || par.config_path==""){ if(!par.hasOwnProperty("config_path") || par.config_path==""){
...@@ -138,11 +138,11 @@ try { ...@@ -138,11 +138,11 @@ try {
if(!custCfg){throw "config error"} if(!custCfg){throw "config error"}
// 料号验证 // 料号验证
if(!GEN.isJobExists({job:job})){ if(!GEN.isJobExists({job:job})){
script_info({ msg: "料号"+job+"不存在" ,result_severity:"error"}) script_info({ msg: "No PN was found in system" ,result_severity:"error"})
throw "job "+ job+ " is not exist" } throw "job "+ job+ " is not exist" }
if(!GEN.isJobOpen({job:job})){GEN.openJob({job:job})} if(!GEN.isJobOpen({job:job})){GEN.openJob({job:job})}
if(GEN.checkInout({job:job,mode:"test"}) != 0 && mode == "aimdfm"){ if(GEN.checkInout({job:job,mode:"test"}) != 0 && mode == "aimdfm"){
script_info({ msg: "料号"+job+" check" ,result_severity:"error"}) script_info({ msg: "PN is not checkin" ,result_severity:"error"})
throw "the job check" } throw "the job check" }
console.log("Checkout====== ========================>") console.log("Checkout====== ========================>")
GEN.checkInout({job:job,mode:"out"}); GEN.checkInout({job:job,mode:"out"});
...@@ -264,7 +264,7 @@ try { ...@@ -264,7 +264,7 @@ try {
var after_sort_matrix = ret.sortNames var after_sort_matrix = ret.sortNames
// 改名 // 改名
script_info({ msg: "开始改名" ,result_severity:"info"}) script_info({ msg: "Failed to change name(Name clashes)" ,result_severity:"info"})
script_info({ progress: 50 }) script_info({ progress: 50 })
err = reName({job:job, matrix:after_sort_matrix, cfg:format_cfg}) err = reName({job:job, matrix:after_sort_matrix, cfg:format_cfg})
if(err){throw err} if(err){throw err}
...@@ -307,8 +307,8 @@ try { ...@@ -307,8 +307,8 @@ try {
var tmp = /(\d+)-(\d+)/.exec(v) var tmp = /(\d+)-(\d+)/.exec(v)
var num1 = Number(tmp[1]) var num1 = Number(tmp[1])
var num2 = Number(tmp[2]) var num2 = Number(tmp[2])
var chabie = num2 - num1 var chabie = Math.abs(num2 - num1)
if(num1 == 1 && num2 == layer_count && !hasMainDrill){ if(((num1 == 1 && num2 == layer_count) || num2 > layer_count) && !hasMainDrill){
GEN.renameLayer({job:job,layer:v,new_name:"ftdrill"}) GEN.renameLayer({job:job,layer:v,new_name:"ftdrill"})
if (ftdrill_layer[ftdrill_layer.length-1]!= v){ if (ftdrill_layer[ftdrill_layer.length-1]!= v){
GEN.matrixMoveRow({ job:job,layer:"ftdrill",after:ftdrill_layer[ftdrill_layer.length-1] }) GEN.matrixMoveRow({ job:job,layer:"ftdrill",after:ftdrill_layer[ftdrill_layer.length-1] })
...@@ -316,11 +316,15 @@ try { ...@@ -316,11 +316,15 @@ try {
hasMainDrill = !hasMainDrill hasMainDrill = !hasMainDrill
} else if(chabie>1 && chabie < layer_count - 1){ } else if(chabie>1 && chabie < layer_count - 1){
// 改名 // 改名
if(num1 > num2){
var tmpv = "ftdrill"+num2+"-"+num1+"l";
GEN.renameLayer({job:job,layer:v,new_name:tmpv.substr(0,v.length-1)})
} else{
GEN.renameLayer({job:job,layer:v,new_name:v.substr(0,v.length-1)}) GEN.renameLayer({job:job,layer:v,new_name:v.substr(0,v.length-1)})
} }
} }
}
}) })
// 设置钻孔 // 设置钻孔
err = setDrill({job:job}) err = setDrill({job:job})
if(err){throw err} if(err){throw err}
...@@ -387,7 +391,7 @@ try { ...@@ -387,7 +391,7 @@ try {
GEN.closeJob({job:job}); GEN.closeJob({job:job});
GEN.COM("open_job,job="+job); GEN.COM("open_job,job="+job);
script_info({ msg: "准备创建profile" ,result_severity:"info"}) script_info({ msg: "Creating Profile" ,result_severity:"info"})
script_info({ progress: 55 }) script_info({ progress: 55 })
var all_layer = Object.keys(tmp_matrix) var all_layer = Object.keys(tmp_matrix)
// 没有outline层 // 没有outline层
...@@ -418,7 +422,7 @@ try { ...@@ -418,7 +422,7 @@ try {
} }
var hasProfile = GEN.getProfile({job:job, step:tmp_step}) var hasProfile = GEN.getProfile({job:job, step:tmp_step})
if(hasProfile.match(/\n/ig).length == 1){ if(hasProfile.match(/\n/ig).length == 1){
script_info({ msg: "创建profile失败" ,result_severity:"warn"}) script_info({ msg: "Failed to create profile" ,result_severity:"warn"})
job_attrs.readin_result = "Failed to create profile" job_attrs.readin_result = "Failed to create profile"
db.query("",function(q){ db.query("",function(q){
return q.updateRow({ return q.updateRow({
...@@ -432,8 +436,7 @@ try { ...@@ -432,8 +436,7 @@ try {
} }
} }
} }
script_info({ msg: "Data format is done" ,result_severity:"warn"})
script_info({ msg: "料号标准化结束" ,result_severity:"warn"})
db.query("",function(q){ db.query("",function(q){
return q.updateRow({ return q.updateRow({
...@@ -481,7 +484,12 @@ catch (e) { ...@@ -481,7 +484,12 @@ catch (e) {
script_info({ result_severity: "error" }) script_info({ result_severity: "error" })
IKM.msg(_.join(GEN.STATUS, "\n")) IKM.msg(_.join(GEN.STATUS, "\n"))
IKM.msg(e) IKM.msg(e)
IKM.save_job_info({jobid:JobId, jobinfohash:{cam_workflow_info:_.toString(e)}}) console.log("=======save cam workflow info");
IKM.crud("deleteRow", {
table: "pdm_job_jobattr",
where:{job_id:JobId, attr_name:"cam_workflow_info"},
})
IKM.save_job_info({jobid:JobId, jobinfohash:{cam_workflow_info:"err"}})
checkIn() checkIn()
// 发送邮件 // 发送邮件
// sendEmail({ // sendEmail({
...@@ -938,16 +946,19 @@ function createOutline(props){ ...@@ -938,16 +946,19 @@ function createOutline(props){
if(GEN.isLayerExists({job:job,layer:"outline"})){GEN.deleteLayer({job:job,layer:"outline"})} if(GEN.isLayerExists({job:job,layer:"outline"})){GEN.deleteLayer({job:job,layer:"outline"})}
GEN.renameLayer({job:job, layer:l,new_name:'outline'}) GEN.renameLayer({job:job, layer:l,new_name:'outline'})
GEN.deleteLayer({job:job, layer:l}) GEN.deleteLayer({job:job, layer:l})
if(GEN.isLayerExists({job:job, layer:bk2})){ GEN.deleteLayer({job:job, layer:bk2}) }
if(GEN.isLayerExists({job:job, layer:tmp})){ GEN.deleteLayer({job:job, layer:tmp}) }
return true return true
} }
GEN.deleteLayer({job:job, layer:l}) GEN.deleteLayer({job:job, layer:l})
GEN.deleteLayer({job:job, layer:bk2}) if(GEN.isLayerExists({job:job, layer:bk2})){ GEN.deleteLayer({job:job, layer:bk2}) }
if(GEN.isLayerExists({job:job, layer:tmp})){ GEN.deleteLayer({job:job, layer:tmp}) }
GEN.deleteLayer({job:job, layer:[tmp_layer]}) GEN.deleteLayer({job:job, layer:[tmp_layer]})
GEN.deleteLayer({job:job, layer:[tmp_layer]}) GEN.deleteLayer({job:job, layer:[tmp_layer]})
return false return false
} }
GEN.deleteLayer({job:job, layer:[tmp]})
} }
function touch(layer) { function touch(layer) {
......
...@@ -91,10 +91,14 @@ var import_info = []; ...@@ -91,10 +91,14 @@ var import_info = [];
var inputState = []; var inputState = [];
var cam_workflow_info = IKM.get_jobinfo({jobid:JobId, jobinfo:"cam_workflow_info"}); var cam_workflow_info = IKM.get_jobinfo({jobid:JobId, jobinfo:"cam_workflow_info"});
if(cam_workflow_info){ if(cam_workflow_info){
IKM.crud("deleteRow", {
table: "pdm_job_jobattr",
where:{job_id:JobId, attr_name:"cam_workflow_info"},
})
IKM.save_job_info({jobid:JobId, jobinfohash:{cam_workflow_info:""}}) IKM.save_job_info({jobid:JobId, jobinfohash:{cam_workflow_info:""}})
} }
try { try {
script_info({ msg: "开始导入", result_severity:"info" }) script_info({ msg: "Failed to unzip the file", result_severity:"info" })
var par = PAR; var par = PAR;
// var db_path = db.query("",function(q){ // var db_path = db.query("",function(q){
// return q.selectValue({ // return q.selectValue({
...@@ -105,7 +109,7 @@ try { ...@@ -105,7 +109,7 @@ try {
// }); // });
// if(_.isEmpty(db_path)){throw "quote-data-upload error"} // if(_.isEmpty(db_path)){throw "quote-data-upload error"}
if(!par.path || par.path == "") { if(!par.path || par.path == "") {
script_info({ msg: "资料路径不存在", result_severity:"error" }); script_info({ msg: "The data path does not exist", result_severity:"error" });
throw "path error"} throw "path error"}
if(!par.hasOwnProperty("config_path") || par.config_path==""){ if(!par.hasOwnProperty("config_path") || par.config_path==""){
console.log("===================cfg"); console.log("===================cfg");
...@@ -123,7 +127,7 @@ try { ...@@ -123,7 +127,7 @@ try {
}) })
}); });
if(_.isEmpty(db_customer)){ if(_.isEmpty(db_customer)){
script_info({ msg: "该料号客户不存在", result_severity:"error" }); script_info({ msg: "No customer was found", result_severity:"error" });
throw "customer error"} throw "customer error"}
if(db_customer && !(/^done$/ig.test(db_customer)) && db_customer != "" ){ if(db_customer && !(/^done$/ig.test(db_customer)) && db_customer != "" ){
par.customer = db_customer par.customer = db_customer
...@@ -137,11 +141,11 @@ try { ...@@ -137,11 +141,11 @@ try {
}) })
}); });
if (!cfg || cfg == ""){ if (!cfg || cfg == ""){
script_info({ msg: "客户配置不存在", result_severity:"error" }); script_info({ msg: "No customer config was found", result_severity:"error" });
throw "cfg can not find"} throw "cfg can not find"}
var config = eval(cfg); var config = eval(cfg);
if(!config.hasOwnProperty("customer")){ if(!config.hasOwnProperty("customer")){
script_info({ msg: "客户配置不存在", result_severity:"error" }); script_info({ msg: "No customer config was found", result_severity:"error" });
throw "config error"} throw "config error"}
var job = Job; var job = Job;
if(_.isEmpty(job)) throw "没有传入料号名!"; if(_.isEmpty(job)) throw "没有传入料号名!";
...@@ -155,7 +159,7 @@ try { ...@@ -155,7 +159,7 @@ try {
// 获取路径下文件信息 // 获取路径下文件信息
var path = par.path var path = par.path
if(!fs.exists(path)){ if(!fs.exists(path)){
script_info({ msg: "资料路径不存在", result_severity:"error" }); script_info({ msg: "No PN file was found in folder", result_severity:"error" });
throw "path error"} throw "path error"}
var pathInfo = fs.listDir(path + "/" + db_customer.toLowerCase(), 1) var pathInfo = fs.listDir(path + "/" + db_customer.toLowerCase(), 1)
// 判断存不存在料号文件 // 判断存不存在料号文件
...@@ -172,7 +176,7 @@ try { ...@@ -172,7 +176,7 @@ try {
// } // }
var jobFile = pathInfo.filter(function(v){return v.baseName.toLowerCase() == job_file_baseName}) var jobFile = pathInfo.filter(function(v){return v.baseName.toLowerCase() == job_file_baseName})
if(jobFile.length == 0){ if(jobFile.length == 0){
script_info({ msg: "资料路径不存在", result_severity:"error" }); script_info({ msg: "No PN file was found in folder", result_severity:"error" });
throw "job file is not exist"} throw "job file is not exist"}
var jobFiles = [] // 记录要分析的文件 var jobFiles = [] // 记录要分析的文件
if (!jobFile[0].isDir) { if (!jobFile[0].isDir) {
...@@ -209,7 +213,7 @@ try { ...@@ -209,7 +213,7 @@ try {
// 分析料号文件 得到料号导入信息 导入类型 // 分析料号文件 得到料号导入信息 导入类型
var jobInfo = analyJobFiles({jobFiles:jobFiles.filter(function(v){return v.isFile}),custCfg:custCfg,config:config,job:job }) var jobInfo = analyJobFiles({jobFiles:jobFiles.filter(function(v){return v.isFile}),custCfg:custCfg,config:config,job:job })
if(jobInfo.data.length == 0){ if(jobInfo.data.length == 0){
script_info({ msg: "未找到料号文件", result_severity:"error" }); script_info({ msg: "No PN file was found in folder", result_severity:"error" });
throw "file error"} throw "file error"}
var importOk = false; // 是否成功导入 var importOk = false; // 是否成功导入
...@@ -300,8 +304,14 @@ try { ...@@ -300,8 +304,14 @@ try {
gerberCfg.step = step gerberCfg.step = step
return gerberCfg return gerberCfg
}) })
if(GEN.GEN_TYPE == "genesis"){
GEN.COM("input_manual_reset")
gerberInfo.forEach(function(v){
import_info.push({name:v.layer, type:"gerber274x", date:now(),user:$.user_name})
GEN.COM("input_manual_set",v)
GEN.COM("input_manual")
})
} else {
gerberInfo.forEach(function(v){ gerberInfo.forEach(function(v){
GEN.COM("input_result_reset,step=,category=warnings,close_tab=yes") GEN.COM("input_result_reset,step=,category=warnings,close_tab=yes")
GEN.COM("input_create,path="+v.path) GEN.COM("input_create,path="+v.path)
...@@ -314,9 +324,11 @@ try { ...@@ -314,9 +324,11 @@ try {
GEN.COM("input_manual_set",v) GEN.COM("input_manual_set",v)
GEN.COM("input_manual") GEN.COM("input_manual")
}) })
}
importOk = true importOk = true
} }
if(!importOk){ script_info({ msg: "导入错误",result_severity:"error" }); throw "import error"} if(!importOk){ throw "import error"}
script_info({ progress: 20 }) script_info({ progress: 20 })
reNameStep(job) reNameStep(job)
if(/2171/.test(par.customer)){ if(/2171/.test(par.customer)){
...@@ -331,12 +343,12 @@ try { ...@@ -331,12 +343,12 @@ try {
// GEN.closeStep() // GEN.closeStep()
// } // }
} else if ((/yucca/ig.test(par.customer))) { } else if ((/yucca/ig.test(par.customer))) {
var matrix = GEN.getMatrix({job:job,type:"array"}) // var matrix = GEN.getMatrix({job:job,type:"array"})
matrix.layer_type.forEach(function(v, i){ // matrix.layer_type.forEach(function(v, i){
if( v == "document") { // if( v == "document") {
GEN.COM("matrix_layer_type,job="+job+",matrix=matrix,layer="+matrix.name[i]+",type=signal") // GEN.COM("matrix_layer_type,job="+job+",matrix=matrix,layer="+matrix.name[i]+",type=signal")
} // }
}) // })
} }
var steplist = GEN.getStepList({job:job}) var steplist = GEN.getStepList({job:job})
GEN.openStep({job:job,name:steplist[0]}) GEN.openStep({job:job,name:steplist[0]})
...@@ -362,10 +374,10 @@ try { ...@@ -362,10 +374,10 @@ try {
var import_html = "<table border=1 align='center' cellpadding=5 cellspacing=0 style=\"text-align: center;\"><tr><th>导入状态/Import Status</th><th>文件/File</th><th>类型/Type</th><th>导入时间/Import Time</th><th>操作用户/User</th></tr>" var import_html = "<table border=1 align='center' cellpadding=5 cellspacing=0 style=\"text-align: center;\"><tr><th>导入状态/Import Status</th><th>文件/File</th><th>类型/Type</th><th>导入时间/Import Time</th><th>操作用户/User</th></tr>"
import_info.forEach(function(item){ import_info.forEach(function(item){
var name = item.name var name = item.name;
var type = item.type var type = item.type;
var date = item.date var date = item.date;
var user = item.user var user = item.user;
import_html += "<tr><td>Readin</td><td>"+name+"</td><td>"+type+"</td><td>"+date+"</td><td>"+user+"</td></tr>" import_html += "<tr><td>Readin</td><td>"+name+"</td><td>"+type+"</td><td>"+date+"</td><td>"+user+"</td></tr>"
}) })
import_html += "</table>" import_html += "</table>"
...@@ -401,7 +413,11 @@ try { ...@@ -401,7 +413,11 @@ try {
catch (e) { catch (e) {
script_info({ result_severity: "error" }) script_info({ result_severity: "error" })
IKM.save_job_info({jobid:JobId, jobinfohash:{cam_workflow_info:_.toString(e)}}) IKM.crud("deleteRow", {
table: "pdm_job_jobattr",
where:{job_id:JobId, attr_name:"cam_workflow_info"},
})
IKM.save_job_info({jobid:JobId, jobinfohash:{cam_workflow_info:"err"}})
IKM.msg(_.join(GEN.STATUS, "\n")) IKM.msg(_.join(GEN.STATUS, "\n"))
IKM.msg(e) IKM.msg(e)
...@@ -429,20 +445,19 @@ function analyJobFiles(props){ ...@@ -429,20 +445,19 @@ function analyJobFiles(props){
var job = props.job; var job = props.job;
var custCfg = props.custCfg; var custCfg = props.custCfg;
var rules = custCfg.rules; var rules = custCfg.rules;
var paramsFile = files.filter(function(file){return /param|ncdrill/ig.test(file.baseName)}) var paramsFile = files.filter(function(file){return /nc_param|ncdrill/ig.test(file.baseName)})
var tmp_hash = {} var tmp_hash = {}
paramsFile.forEach(function(file){ paramsFile.forEach(function(file){
tmp_hash[file.baseName] = (function(){ tmp_hash[file.baseName] = (function(){
var tmparr = fs.readFile(file.path).split("\n").filter(function(v){return /^\S+\s+\S/ig.test(v)}) var tmparr = fs.readFile(file.path).split("\n").filter(function(v){return /^\s?\S+\s+\S/ig.test(v)}).filter(function(v){return !/\(/.test(v)})
var tmp = {} var tmp = {}
tmparr.map(function(v){ tmparr.map(function(v){
var arr = v.split(/\b\s+\b/) var arr = v.split(/\b\s+\b/)
tmp[arr[0].replace(/-/ig,"_")] = arr[1] tmp[arr[0].replace(/-/ig,"_").trim()] = arr[1]
}) })
return tmp return tmp
})() })()
}) })
var fileInfo = files.reduce(function(a,file){ var fileInfo = files.reduce(function(a,file){
try { try {
rules.forEach(function(item){ rules.forEach(function(item){
...@@ -558,20 +573,21 @@ function decompression(path, zips) { ...@@ -558,20 +573,21 @@ function decompression(path, zips) {
var count = 0; var count = 0;
var zipfiles = files.filter(function(item){ var zipfiles = files.filter(function(item){
if (item.suffix == "zip" || item.suffix == "rar" || item.suffix == "7z") { if (item.suffix == "zip" || item.suffix == "rar" || item.suffix == "7z") {
inputState.push(item.suffix) inputState.push(item.suffix);
} console.log("--->path:" + item.path)
if(/zip|rar|7z/.test(item.suffix) && zips.indexOf(item.path) < 0){ if(zips.indexOf(item.path) < 0){
zips.push(item.path)
if(item.name.length >= 20) { if(item.name.length >= 20) {
var mvname = "custom" + count + "." + item.suffix; var mvname = "custom" + count + "." + item.suffix;
count++ count++
fs.rename(item.path, item.dir + "/" + mvname) fs.rename(item.path, item.dir + "/" + mvname)
item.path = item.dir + "/" + mvname item.path = item.dir + "/" + mvname
} }
zips.push(item.path)
var dir_name = item.path.replace(/\.(zip|7z|rar)$/, ""); var dir_name = item.path.replace(/\.(zip|7z|rar)$/, "");
autoUn(item.path, dir_name); autoUn(item.path, dir_name);
return true return true
} }
}
return false return false
}) })
if(zipfiles.length) {decompression(path, zips)} if(zipfiles.length) {decompression(path, zips)}
...@@ -598,3 +614,7 @@ function autoUn(path, dirname) { ...@@ -598,3 +614,7 @@ function autoUn(path, dirname) {
process.exec('7za', ['x' , path, "-o"+dirname, "-aoa"]) process.exec('7za', ['x' , path, "-o"+dirname, "-aoa"])
} }
} }
function exportInfo(info){
fs.writeFile("/home/toplinker/samba/scott_test/tmp", _.toString(info))
}
\ No newline at end of file
...@@ -507,7 +507,7 @@ ...@@ -507,7 +507,7 @@
{ {
"valid": function(props){ "valid": function(props){
var file = props.file; var file = props.file;
return /.+\.art$|\.l\d+$|\.r1$|\.sb$|\.st$|\.d\d+-\d+|\.[bt]sm$|\.drwg$|\.p\d+p$|\.gdo/ig.test(file.name) return /.+\.gbr$|.+\.art$|\.l\d+$|\.r1$|\.sb$|\.st$|\.d\d+-\d+|\.[bt]sm$|\.drwg$|\.p\d+p$|\.gdo/ig.test(file.name)
}, },
"type": "Gerber274x", "type": "Gerber274x",
"format": "Gerber274x_2", "format": "Gerber274x_2",
...@@ -599,16 +599,16 @@ ...@@ -599,16 +599,16 @@
"tl_name": [ "tl_name": [
{"orig_name" : ["^comp_+_top$"], "tl_name" : "comp_+_top" }, {"orig_name" : ["^comp_+_top$"], "tl_name" : "comp_+_top" },
{"orig_name" : ["^comp_+_bot$"], "tl_name" : "comp_+_bot" }, {"orig_name" : ["^comp_+_bot$"], "tl_name" : "comp_+_bot" },
{"orig_name" : ["^pm_top","paste.pri|pripaste|solderpaste_top","ppst\\.art|spt\\.art","assy[_-]?top\\.art","past_top","paste_top"], "tl_name" : "past_top" }, {"orig_name" : ["^pm_top","spcs\\.gbr$|paste.pri|pripaste|solderpaste_top","ppst\\.art|spt\\.art","assy[_-]?top\\.art","past_top","paste_top"], "tl_name" : "past_top" },
{"orig_name" : ["^pm_bot","paste.sec|secpaste|solderpaste_bottom","spst\\.art|spb\\.art","assy[_-]?bott?o?m?\\.art","past_bot","paste_bot"], "tl_name" : "past_botm" }, {"orig_name" : ["^pm_bot","spps\\.gbr$|paste.sec|secpaste|solderpaste_bottom","spst\\.art|spb\\.art","assy[_-]?bott?o?m?\\.art","past_bot","paste_bot"], "tl_name" : "past_botm" },
{"orig_name" : ["silk.pri","pleg\\.art|sst\\.art","^ss_top","silk_top"], "tl_name" : "silk_top" }, {"orig_name" : ["silk.pri","pleg\\.art|sst\\.art","^ss_top|sscs\\.gbr$","silk_top"], "tl_name" : "silk_top" },
{"orig_name" : ["silk.sec","sleg\\.art|ssb\\.art","^ss_bot","silk_bot"], "tl_name" : "silk_bot" }, {"orig_name" : ["silk.sec","sleg\\.art|ssb\\.art","^ss_bot|ssps\\.gbr$","silk_bot"], "tl_name" : "silk_bot" },
{"orig_name" : ["\\.st$|\\.tsm$|soldermask_top","mask.top\\.art|smt\\.art","mask.pri\\.art","psm\\.art","sm_top"], "tl_name" : "sm_top" }, {"orig_name" : ["\\.st$|\\.tsm$|soldermask_top","mask.top\\.art|smt\\.art","mask.pri\\.art|smcs\\.gbr$","psm\\.art","sm_top"], "tl_name" : "sm_top" },
{"orig_name" : ["\\.sb$|\\.bsm$|soldermask_bottom","mask.bot\\.art|smb\\.art","mask.sec\\.art","ssm\\.art","sm_bot"], "tl_name" : "sm_botm" }, {"orig_name" : ["\\.sb$|\\.bsm$|soldermask_bottom","mask.bot\\.art|smb\\.art","mask.sec\\.art|smps\\.gbr$","ssm\\.art","sm_bot"], "tl_name" : "sm_botm" },
{"orig_name" : ["^(?:(?!assy|enig|pm|past|ss|silk|sm|soldermask).)+_top\.art$","^top$","^top.art$"], "tl_name" : "top" }, {"orig_name" : ["^(?:(?!assy|enig|pm|past|ss|silk|sm|soldermask).)+_top\.art$","^top$","^top.art$"], "tl_name" : "top" },
{"orig_name" : ["^(?:(?!assy|enig|pm|past|ss|silk|sm|soldermask).)+_bottom\.art$","^bot\\.art$","^bottom$","^bottom\\.art$"], "tl_name" : "bottom" }, {"orig_name" : ["^(?:(?!assy|enig|pm|past|ss|silk|sm|soldermask).)+_bottom\.art$","^bot\\.art$","^bottom$","^bottom\\.art$"], "tl_name" : "bottom" },
{"orig_name" : ["int(\\d+)\\.art"], "tl_name" : "l_($1+1)"}, {"orig_name" : ["int(\\d+)\\.art"], "tl_name" : "l_($1+1)"},
{"orig_name" : ["^0?(\\d+)[\\D].*\\.art$","\\.p(\\d+)p?$","\\.l(\\d+)$","^l(\\d+).*\\.art$","^l(\\d+)\\.art$","^0(\\d+).*ccp_ms","^s(\\d+)\\.art","laye?r?(\\d+)","layer_(\\d+)"], "tl_name" : "l_($1)"}, {"orig_name" : ["l(\\d+).*\\.gbr$","^0?(\\d+)[\\D].*\\.art$","\\.p(\\d+)p?$","\\.l(\\d+)$","^l(\\d+).*\\.art$","^l(\\d+)\\.art$","^0(\\d+).*ccp_ms","^s(\\d+)\\.art","laye?r?(\\d+)","layer_(\\d+)"], "tl_name" : "l_($1)"},
{"orig_name" : ["(\\d+)-(\\d+)-((?:(?!laser)[a-zA-Z])+)\\.drl$","\\.d(\\d+)-(\\d+)((?:(?!laser)[a-zA-Z])+)$"], "tl_name" : "d($1)-($2)-($3)"}, {"orig_name" : ["(\\d+)-(\\d+)-((?:(?!laser)[a-zA-Z])+)\\.drl$","\\.d(\\d+)-(\\d+)((?:(?!laser)[a-zA-Z])+)$"], "tl_name" : "d($1)-($2)-($3)"},
{"orig_name" : ["\\.ncd(\\d)-(\\d)$","\\.d(\\d+)-(\\d+)$","-(\\d+)-(\\d+)\\.drl$","(\\d+)-(\\d+)-laser\\.drl$","d(\\d+)-(\\d+)"], "tl_name" : "d_($1)-($2)"}, {"orig_name" : ["\\.ncd(\\d)-(\\d)$","\\.d(\\d+)-(\\d+)$","-(\\d+)-(\\d+)\\.drl$","(\\d+)-(\\d+)-laser\\.drl$","d(\\d+)-(\\d+)"], "tl_name" : "d_($1)-($2)"},
{"orig_name" : ["\\.ncdthru$"], "tl_name" : "drill" }, {"orig_name" : ["\\.ncdthru$"], "tl_name" : "drill" },
...@@ -710,7 +710,7 @@ ...@@ -710,7 +710,7 @@
{ {
"valid": function(props){ "valid": function(props){
var file = props.file; var file = props.file;
return /.+\.ger$/ig.test(file.name) || /\.pho$|\.bol$|\.gdo$|\.pma$|\.pmb$|\.spa$|\.spb$\.sma$|\.smb$|\.ssa$|\.ssb$/ig.test(file.name) || return /.+\.ger$/ig.test(file.name) || /.+\.l\d+$|\.pho$|\.bol$|\.gdo$|\.pma$|\.pmb$|\.spa$|\.spb$\.sma$|\.smb$|\.ssa$|\.ssb$/ig.test(file.name) ||
/.+\.l\d+$/ig.test(file.name) /.+\.l\d+$/ig.test(file.name)
}, },
"type": "Gerber274x", "type": "Gerber274x",
...@@ -833,9 +833,9 @@ ...@@ -833,9 +833,9 @@
{"orig_name" : ["bsilk","^ssb\\.art$","\\.ssb$","silkscrnbot|silkscreenbot","silk.bot|silk-bot"], "tl_name" : "silk_bot" }, {"orig_name" : ["bsilk","^ssb\\.art$","\\.ssb$","silkscrnbot|silkscreenbot","silk.bot|silk-bot"], "tl_name" : "silk_bot" },
{"orig_name" : ["tmask","^smt\\.art$","\\.sma$","soldmask1top|soldermask.?top","sm.top|solder.top"], "tl_name" : "sm_top" }, {"orig_name" : ["tmask","^smt\\.art$","\\.sma$","soldmask1top|soldermask.?top","sm.top|solder.top"], "tl_name" : "sm_top" },
{"orig_name" : ["bmask","^smb\\.art$","\\.smb$","soldmask1bot|soldermask.?bot","sm.bot|solder.bot"], "tl_name" : "sm_botm" }, {"orig_name" : ["bmask","^smb\\.art$","\\.smb$","soldmask1bot|soldermask.?bot","sm.bot|solder.bot"], "tl_name" : "sm_botm" },
{"orig_name" : ["^(?:(?!assy|enig|pm|past|paste|silk|mask).)+top\\.(pho|art)$","^top$","^top\\.art$"], "tl_name" : "top" }, {"orig_name" : ["^(?:(?!assy|export|enig|pm|past|paste|silk|mask).)+top\\.(pho|art)$","^top$","^top\\.art$"], "tl_name" : "top" },
{"orig_name" : ["^(?:(?!ref).)+l(\\d)\\.art$","-(\\d+)l\\.pho$","^l(\\d+).*\\.art$","^v(\\d+)\\.art$","^g(\\d+)\\.art$","^s(\\d+)\\.art$","\\.l(\\d+)$","Copper(\\d+)\\.ger$","^laye?r?_(\\d+)"], "tl_name" : "l_($1)"}, {"orig_name" : ["^(?:(?!ref).)+l(\\d)\\.art$","-(\\d+)l\\.pho$","^l(\\d+).*\\.art$","^v(\\d+)\\.art$","^g(\\d+)\\.art$","^s(\\d+)\\.art$","\\.l(\\d+)$","Copper(\\d+)\\.ger$","^laye?r?_(\\d+)"], "tl_name" : "l_($1)"},
{"orig_name" : ["^(?:(?!assy|enig|pm|past|paste|silk|mask).)+bot\\.(pho|art)$","^bot\\.art$","^bottom$","^bottom.art$"], "tl_name" : "bottom" }, {"orig_name" : ["^(?:(?!assy|view|enig|pm|past|paste|silk|mask).)+bot\\.(pho|art)$","^bot\\.art$","^bottom$","^bottom.art$"], "tl_name" : "bottom" },
{"orig_name" : ["\\.d(\\d+)$"], "tl_name" : "d_($1)-($1+1)"}, {"orig_name" : ["\\.d(\\d+)$"], "tl_name" : "d_($1)-($1+1)"},
{"orig_name" : ["(\\d+)-(\\d+)plated\\.ncd","thruHolePlated_(\\d+)_(\\d+)\\.ncd","(\\d+)-(\\d+)\\.drl$","^drill(\\d+)-(\\d+)$","^d_(\\d+)-(\\d+)$"], "tl_name" : "d_($1)-($2)"}, {"orig_name" : ["(\\d+)-(\\d+)plated\\.ncd","thruHolePlated_(\\d+)_(\\d+)\\.ncd","(\\d+)-(\\d+)\\.drl$","^drill(\\d+)-(\\d+)$","^d_(\\d+)-(\\d+)$"], "tl_name" : "d_($1)-($2)"},
{"orig_name" : ["(\\d+)-(\\d+)-np\\.drl$","ThruHoleNonPlated\\.ncd$","^drill$"], "tl_name" : "drill" }, {"orig_name" : ["(\\d+)-(\\d+)-np\\.drl$","ThruHoleNonPlated\\.ncd$","^drill$"], "tl_name" : "drill" },
...@@ -982,7 +982,7 @@ ...@@ -982,7 +982,7 @@
{"orig_name" : ["soldtop.art","sm_top|mask_top"], "tl_name" : "sm_top" }, {"orig_name" : ["soldtop.art","sm_top|mask_top"], "tl_name" : "sm_top" },
{"orig_name" : ["soldbotm\\.art","sm_bot|mask_bot"], "tl_name" : "sm_botm" }, {"orig_name" : ["soldbotm\\.art","sm_bot|mask_bot"], "tl_name" : "sm_botm" },
{"orig_name" : ["^top$","^top.art$"], "tl_name" : "top" }, {"orig_name" : ["^top$","^top.art$"], "tl_name" : "top" },
{"orig_name" : ["^pgp(\\d+)\\.art$","^art(\\d+)\\.art$","^l_(\\d+)"], "tl_name" : "l_($1)"}, {"orig_name" : ["^gnd(\\d+)\\.art$","^in(\\d+)\\.art$","^pgp(\\d+)\\.art$","^art(\\d+)\\.art$","^l_(\\d+)"], "tl_name" : "l_($1)"},
{"orig_name" : ["^bot\\.art$","^bottom$","^bottom.art$"], "tl_name" : "bottom" }, {"orig_name" : ["^bot\\.art$","^bottom$","^bottom.art$"], "tl_name" : "bottom" },
{"orig_name" : ["\\.d(\\d+)$"], "tl_name" : "d_($1)-($1+1)"}, {"orig_name" : ["\\.d(\\d+)$"], "tl_name" : "d_($1)-($1+1)"},
{"orig_name" : ["(\\d+)-(\\d+)-((?:(?!laser)[a-zA-Z])+)\\.drl$","\\.d(\\d+)-(\\d+)((?:(?!laser)[a-zA-Z])+)$"], "tl_name" : "d($1)-($2)-($3)"}, {"orig_name" : ["(\\d+)-(\\d+)-((?:(?!laser)[a-zA-Z])+)\\.drl$","\\.d(\\d+)-(\\d+)((?:(?!laser)[a-zA-Z])+)$"], "tl_name" : "d($1)-($2)-($3)"},
......
...@@ -188,9 +188,9 @@ ...@@ -188,9 +188,9 @@
}, },
"Excellon2_4": { "Excellon2_4": {
"nf1": 2, "nf1": 2,
"nf2": 3, "nf2": 4,
"units": "mm", "units": "inch",
"zeroes": "leading", "zeroes": "trailing",
"decimal": "no", "decimal": "no",
"nf_comp": 0, "nf_comp": 0,
"break_sr": "yes", "break_sr": "yes",
...@@ -200,7 +200,7 @@ ...@@ -200,7 +200,7 @@
"drill_only": "no", "drill_only": "no",
"multiplier": 1, "multiplier": 1,
"resolution": 3, "resolution": 3,
"tool_units": "mm", "tool_units": "inch",
"coordinates": "absolute", "coordinates": "absolute",
"merge_by_rule": "no", "merge_by_rule": "no",
"signed_coords": "no", "signed_coords": "no",
...@@ -286,6 +286,26 @@ ...@@ -286,6 +286,26 @@
"signed_coords": "no", "signed_coords": "no",
"text_line_width": 0.0024 "text_line_width": 0.0024
}, },
"Excellon2_9": {
"nf1": 3,
"nf2": 6,
"units": "inch",
"zeroes": "leading",
"decimal": "no",
"nf_comp": 0,
"break_sr": "yes",
"data_type": "ascii",
"separator": "nl",
"threshold": 200,
"drill_only": "no",
"multiplier": 1,
"resolution": 3,
"tool_units": "inch",
"coordinates": "absolute",
"merge_by_rule": "no",
"signed_coords": "no",
"text_line_width": 0.0024
},
"IPC356_1": { "IPC356_1": {
"nf1": 2, "nf1": 2,
"nf2": 4, "nf2": 4,
...@@ -787,7 +807,7 @@ ...@@ -787,7 +807,7 @@
{ {
"valid": function(props){ "valid": function(props){
var file = props.file; var file = props.file;
return /.+\.ger$/ig.test(file.name) || /\.gdo$|\.bol$|\.gdo$|\.pma$|\.sma$|\.smb$|\.ssa$|\.ssb$/ig.test(file.name) || return /.+\.ger$/ig.test(file.name) || /\.pho$|\.gdo$|\.bol$|\.gdo$|\.pma$|\.sma$|\.smb$|\.ssa$|\.ssb$/ig.test(file.name) ||
/.+\.l\d+$/ig.test(file.name) /.+\.l\d+$/ig.test(file.name)
}, },
"type": "Gerber274x", "type": "Gerber274x",
...@@ -902,15 +922,15 @@ ...@@ -902,15 +922,15 @@
} }
], ],
"tl_name": [ "tl_name": [
{"orig_name" : ["^pmt\\.art$","\\.pma$","SoldPasteTop\\.ger","past_top"], "tl_name" : "past_top" }, {"orig_name" : ["pastmasktop\\.pho|^pmt\\.art$","\\.pma$","SoldPasteTop\\.ger","past_top"], "tl_name" : "past_top" },
{"orig_name" : ["^pmb\\.art$","\\.pmb$","SoldPasteBot\\.ger","past_botm"], "tl_name" : "past_botm" }, {"orig_name" : ["pastmaskbot\\.pho|^pmb\\.art$","\\.pmb$","SoldPasteBot\\.ger","past_botm"], "tl_name" : "past_botm" },
{"orig_name" : ["tsilk","^sst\\.art$","\\.ssa$","SilkScrnTop\\.ger","silk_top"], "tl_name" : "silk_top" }, {"orig_name" : ["silkscreentop\\.pho|tsilk","^sst\\.art$","\\.ssa$","SilkScrnTop\\.ger","silk_top"], "tl_name" : "silk_top" },
{"orig_name" : ["bsilk","^ssb\\.art$","\\.ssb$","SilkScrnBot\\.ger","silk_bot"], "tl_name" : "silk_bot" }, {"orig_name" : ["silkscreenbot\\.pho|bsilk","^ssb\\.art$","\\.ssb$","SilkScrnBot\\.ger","silk_bot"], "tl_name" : "silk_bot" },
{"orig_name" : ["tmask","^smt\\.art$","\\.sma$","SoldMask1Top\\.ger","sm_top"], "tl_name" : "sm_top" }, {"orig_name" : ["soldermasktop\\.pho|tmask","^smt\\.art$","\\.sma$","SoldMask1Top\\.ger","sm_top"], "tl_name" : "sm_top" },
{"orig_name" : ["bmask","^smb\\.art$","\\.smb$","SoldMask1Bot\\.ger","sm_bot"], "tl_name" : "sm_botm" }, {"orig_name" : ["soldermaskbot\\.pho|bmask","^smb\\.art$","\\.smb$","SoldMask1Bot\\.ger","sm_bot"], "tl_name" : "sm_botm" },
{"orig_name" : ["^top$","^top.art$"], "tl_name" : "top" }, {"orig_name" : ["-top\\.pho$|^top$","^top.art$"], "tl_name" : "top" },
{"orig_name" : ["^l(\\d+).*\\.art$","^v(\\d+)\\.art$","^g(\\d+)\\.art$","^s(\\d+)\\.art$","\\.l(\\d+)$","Copper(\\d+)\\.ger$","^layer_(\\d+)"], "tl_name" : "l_($1)"}, {"orig_name" : ["-(\\d+)l\\.pho$","^l(\\d+).*\\.art$","^v(\\d+)\\.art$","^g(\\d+)\\.art$","^s(\\d+)\\.art$","\\.l(\\d+)$","Copper(\\d+)\\.ger$","^layer_(\\d+)"], "tl_name" : "l_($1)"},
{"orig_name" : ["^bot\\.art$","^bottom$","^bottom.art$"], "tl_name" : "bottom" }, {"orig_name" : ["-bot\\.pho$|^bot\\.art$","^bottom$","^bottom.art$"], "tl_name" : "bottom" },
{"orig_name" : ["\\.d(\\d+)$"], "tl_name" : "d_($1)-($1+1)"}, {"orig_name" : ["\\.d(\\d+)$"], "tl_name" : "d_($1)-($1+1)"},
{"orig_name" : ["thruHolePlated_(\\d+)_(\\d+)\\.ncd","(\\d+)-(\\d+)\\.drl$","^drill(\\d+)-(\\d+)$","^d_(\\d+)-(\\d+)$"], "tl_name" : "d_($1)-($2)"}, {"orig_name" : ["thruHolePlated_(\\d+)_(\\d+)\\.ncd","(\\d+)-(\\d+)\\.drl$","^drill(\\d+)-(\\d+)$","^d_(\\d+)-(\\d+)$"], "tl_name" : "d_($1)-($2)"},
{"orig_name" : ["ThruHoleNonPlated\\.ncd$","^drill$"], "tl_name" : "drill" }, {"orig_name" : ["ThruHoleNonPlated\\.ncd$","^drill$"], "tl_name" : "drill" },
...@@ -918,9 +938,12 @@ ...@@ -918,9 +938,12 @@
{"orig_name" : "fab.art", "tl_name" : "fab.art" }, {"orig_name" : "fab.art", "tl_name" : "fab.art" },
{"orig_name" : ["multipack.art","^array$"], "tl_name" : "array" }, {"orig_name" : ["multipack.art","^array$"], "tl_name" : "array" },
{"orig_name" : ["outline\\.art$","\\.bol$","PnlContourNonPlated\\.ger","^outline"], "tl_name" : "outline" }, {"orig_name" : ["outline\\.art$","\\.bol$","PnlContourNonPlated\\.ger","^outline"], "tl_name" : "outline" },
{"orig_name" : ["top-enig","enig_top"], "tl_name" : "enig_top" }, {"orig_name" : ["^topside.golden\\.pho$","top-enig","enig_top"], "tl_name" : "enig_top" },
{"orig_name" : ["bot-enig","enig_bot"], "tl_name" : "enig_bot" }, {"orig_name" : ["^botside.golden\\.pho$","bot-enig","enig_bot"], "tl_name" : "enig_bot" },
] ],
"mergerule" : {
profile:["silk_top"]
}
}, },
"Vivo":{ "Vivo":{
"step": "cad", "step": "cad",
...@@ -957,6 +980,14 @@ ...@@ -957,6 +980,14 @@
"type": "Excellon2", "type": "Excellon2",
"format": "Excellon2_5" "format": "Excellon2_5"
}, },
{
"valid": function(props){
var file = props.file;
return /^ftdrill/ig.test(file.name)
},
"type": "Gerber274x",
"format": "Gerber274x_4"
},
{ {
"valid": function(props){ "valid": function(props){
var file = props.file; var file = props.file;
...@@ -971,8 +1002,8 @@ ...@@ -971,8 +1002,8 @@
{"orig_name" : ["osp-bottom\\.pho","solderpastebottom","past_botm"], "tl_name" : "past_botm" }, {"orig_name" : ["osp-bottom\\.pho","solderpastebottom","past_botm"], "tl_name" : "past_botm" },
{"orig_name" : ["pleg\\.art","^ss_top","silk_top"], "tl_name" : "silk_top" }, {"orig_name" : ["pleg\\.art","^ss_top","silk_top"], "tl_name" : "silk_top" },
{"orig_name" : ["sleg\\.art","^ss_bot","silk_bot"], "tl_name" : "silk_bot" }, {"orig_name" : ["sleg\\.art","^ss_bot","silk_bot"], "tl_name" : "silk_bot" },
{"orig_name" : ["soldermask-top","top-solder-mask\\.pho","soldermasktop","sm_top"], "tl_name" : "sm_top" }, {"orig_name" : ["soldermask1|soldermask-top","top-solder-mask\\.pho","soldermasktop","sm_top"], "tl_name" : "sm_top" },
{"orig_name" : ["soldermask-bottom","bottom-solder-mask\\.pho","soldermaskbottom","sm_bot"], "tl_name" : "sm_botm" }, {"orig_name" : ["soldermask2|soldermask-bottom","bottom-solder-mask\\.pho","soldermaskbottom","sm_bot"], "tl_name" : "sm_botm" },
{"orig_name" : ["top\\.pho","^top$","layertop"], "tl_name" : "top" }, {"orig_name" : ["top\\.pho","^top$","layertop"], "tl_name" : "top" },
{"orig_name" : ["^lay(\\d+)","layer(\\d+)\\.gdo","layer_(\\d+)"], "tl_name" : "l_($1)"}, {"orig_name" : ["^lay(\\d+)","layer(\\d+)\\.gdo","layer_(\\d+)"], "tl_name" : "l_($1)"},
{"orig_name" : ["^bottom\\.pho$","^bottom$","layerbottom"], "tl_name" : "bottom" }, {"orig_name" : ["^bottom\\.pho$","^bottom$","layerbottom"], "tl_name" : "bottom" },
......
=head
NAME:
DESCRIPTION: 钻孔输出
PARAMETER:
[
{
name : 'step_filter',
title : '工作step',
type : 'LineEdit',
property : {tool_tip : '过滤Step名称'},
},
{
name : 'out_dir',
title : '钻孔输出路径',
type : 'LineEdit',
property:{tool_tip:'例如: /output/drill'}
},
{
name : 'cool_spread',
title : '跳钻距离(um)',
type : 'LineEdit',
property:{tool_tip:'例如: 350'}
},
{
name : 'reread_layer',
type : 'RadioBox',
title : '回读钻孔程式',
property : {tool_tip:'未设定,则默认no',
size_policy:'Expanding,Fixed',item_list:[{name:'yes',text:'Yes'},{name:'no',text:'No'}]},
pack : {row:1,column:1},
},
{
name : 'is_select_lyr',
type : 'RadioBox',
title : '是否选择层别',
property : {tool_tip:'未设定,则默认no',
size_policy:'Expanding,Fixed',item_list:[{name:'yes',text:'Yes'},{name:'no',text:'No'}]},
pack : {row:1,column:1},
},
{
name : 'save_job',
title : '保存料号',
type : 'RadioBox',
property : {
size_policy:'Expanding,Fixed',
item_list:[
{name:'Yes',text:'Yes'},
{name:'No',text:'No'},
],
tool_tip:'脚本结束后自动保存料号,未设定,默认为No'
},
pack : {row:1,column:1},
}
]
VERSION_HISTORY:
V1.00 2019-10-22 Super Zhang
1.新版本
V1.1 2020-03-11 Super Zhang
1.不同尺寸板子增加输出参数
V1.2 2020-03-12 Super
1.修改钻孔输出方式代码
V1.3 2020-03-23 Super
1.增加0.549的M97批号孔
V1.4 2020-3-25 Super
1.增加web server数据传输
V1.5 2020-03-27 Super
1.钻孔输出格式调整为3:3不省零 modal_coords=no
V1.6 2020-3-30 Super
1.修改涨缩参数
V1.7 2020-04-01 Super
1.钻带表头增加料号和涨缩信息
2.涨缩中心点按原点移动后的数据从新计算
V1.8 2020-04-02 Super
1.涨缩中心按改变原点前的坐标计算
v1.9 2020-04-04 Super
1.angle = 270
v2.0 2020-04-15 Kurri
1.增加跳刀参数
V2.1 2020-04-21 Super
1.调整T99坐标位置
2.T02板框监视孔的数据放到T01前面
V2.2 2020-05-14 Kurri
1.vpg层也插入M97,${JOB} $S$I
V2.3 2020-05-15 Kurri
1.修复涨缩小于1的程序没有正常输出的问题
V2.31 2020-06-09 Super
1.扩孔时不再增加G84代码
2.扩孔钻咀用3.151
3.修复ncset同名时钻孔无法输出
V2.32 2020-06-11 Super
1.输出命名更新
V2.33 2020-08-18 Super
1.读取map_info参数2.修复检测孔不是第二把刀的时候检测孔坐标乱刀序,3.双面3.054排序
V2.34 2020-10-13 Kurri
1.输出层别选择取消board属性限定
V2.35 2020-10-16 Kurri
1.增加程序上传的类型
V2.36 2020-10-16 Kurri
1.输出alp和alr时bottom层做mirror
V2.37 2020-10-21 Kurri
1.取消测试版本T2.37
T2.38 2020-10-22 Super
1.增加短槽拉伸
2.调整*的M97/M98模式
T2.39 2020-10-29 Super
1.更新拉伸规则
2.706*603的M97/M98位置调整
V2.38 2020-11-03 Super
1.测试版本到正式版
2.取消槽孔角度旋转
3.输出参数增加single_sr
V2.39 2020-11-06 Super
1.输出参数break_sr设置成yes
HELP:
<html><body bgcolor="#DDECFE">
<font size="3" color="#003DB2"><p>功能简介</p></font>
<p> 钻孔输出 </p>
<br>
<font size="3" color="#003DB2"><p>参数配置</p></font>
<font color="#008000"><p> ● 无</p></font>
<font size="3" color="#003DB2"><p>注意事项</p></font>
<p> ● 无 </p>
<br>
</body></html>
=cut
use strict;
use Encode;
use utf8;
use Data::Dump 'dump';
use File::Copy;
use JSON;
my $json = new JSON;
# my $datum;#增加一个基准点数据
# my @drl_section_data;#监视孔范围数据
# my (@drl_section,$section_tool,$section_number);#监视孔坐标
use_module('TL_GenMath');
my ($Job,$Step)=($JOB,undef);
my $units = 'mm';
# my $url = "http://10.87.66.216:9008/api/TOPMES6_SEC_V6/sec/sec-import_drill_program";
# my $server_data;
# my $map_info = do($GEN->getJobPath(job=>$Job).'/user/PNL_map_info');
# my $new_name = get_new_layer_name("$Job");
##host name为cody电脑名称,本地测试用本地目录
use Sys::Hostname;
my $hostname = hostname;
#$GUI->debug(dump($hostname));
if( $hostname eq 'DESKTOP-010QP68' ){
$PAR->{out_dir} = 'D:/tmp';
}
if ($hostname eq 'g1kevnzhang'){
$PAR->{out_dir} = 'D:/tmp';
}
$PAR->{spread} = 2000 unless $PAR->{spread};
$PAR->{reread_layer} = 'no' unless $PAR->{reread_layer};
$PAR->{is_select_lyr} = 'no' unless $PAR->{is_select_lyr};
$PAR->{save_job} = 'No' unless $PAR->{save_job};
$PAR->{cool_spread} = 350 unless $PAR->{cool_spread};#跳孔间距
unless( $PAR->{out_dir} ){
$GUI->msgbox(-icon=>'warning',-text=>'请在脚本参数中设定钻孔输出路径');
return 'Cancel';
}
$PAR->{out_dir} = encode('gbk',$PAR->{out_dir});
##
unless( -d $PAR->{out_dir} ){
$GUI->msgbox(-icon=>'warning',-text=>"$PAR->{out_dir} 脚本参数设定的钻孔输出目录不存在,请确认!");
return 'Cancel';
}
$PAR->{out_dir} .= '/'.lc($new_name);
mkdir $PAR->{out_dir} unless ( -e $PAR->{out_dir});
my $info;
try {
show_loading("判断是否选择料号..",0,position=>'n');
unless( $Job){
$GUI->msgbox(-icon=>'error',-text=>"请先选择料号后再执行脚本!");
return 'Cancel';
}
##检查料号是否存在
update_loading("检查${Job}是否存在..",0,position=>'n');
unless ( $GEN->isJobExists(job=>$Job) ){
$GUI->msgbox(-icon=>'error',-text=>"料号 $Job 不存在,请确认。");
return 'Cancel';
}
##
update_loading("正在打开料号${Job}...",0,position=>'n');
$GEN->openJob(job=>$Job) unless ($GEN->isJobOpen(job=>$Job));
##
update_loading("过滤工作step...",0,position=>'n');
my $ans = get_work_step();
return $ans if $ans;
##选择工作层
update_loading("过滤层别...",0,position=>'n');
my @work_layers = select_work_layer();
return 'Cancel' if $work_layers[0] eq 'Cancel';
##确认涨缩信息
my $scale = get_scale_info(layers=>\@work_layers);#-----涨缩值信息确认
return $scale if $scale eq 'Cancel';
$PAR->{scale} = $scale;
##
update_loading("正在打开料号$Step STEP...",0,position=>'n');
$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=>$units );
$GEN->zoomHome();
$PAR->{profile_limits} = $GEN->getProfileLimits(job=>$Job,step=>$Step,units=>'mm');
$PAR->{profile_limits}{xc} = $PAR->{profile_limits}{xsize}/2-abs($PAR->{profile_limits}{xmin});
$PAR->{profile_limits}{yc} = $PAR->{profile_limits}{ysize}/2-abs($PAR->{profile_limits}{ymin});
$PAR->{sr} = $GEN->getSRLimits(job=>$Job,step=>$Step,units=>'mm');
my $orgDrillToolInfo ;
foreach my $layer (@work_layers) {
##钻孔输出
update_loading("$layer 层钻孔正在输出...",0,position=>'n');
my $output_layer = $Job.'-'.$layer.'-ori';#$Job.'-'.$layer.'-ori'
my $ans = drill_out(layer=>$layer,output_layer=>$output_layer,scale_x=>$PAR->{scale}{$layer}{x},scale_y=>$PAR->{scale}{$layer}{y});
return $ans if $ans;
####钻孔程式编辑
my $new_layer;
if($PAR->{scale}{$layer}{x} != 1 or $PAR->{scale}{$layer}{y} != 1){
$new_layer= $new_name.'.'.$layer.('X').($PAR->{scale}{$layer}{x}).('Y').($PAR->{scale}{$layer}{y});
}else{
$new_layer= $new_name.'.'.$layer;
}
my $new_file = $PAR->{out_dir}.'/'.$new_layer;
update_loading("$layer 层钻孔程式正在编辑...",0,position=>'n');
$ans = edit_nc_file(layer=>$layer,output_file=>$PAR->{out_dir}.'/'.$output_layer,new_file=>$new_file,x=>$PAR->{scale}{$layer}{x},y=>$PAR->{scale}{$layer}{y});#drl_type=>$drl_type
return $ans if $ans;
##删除钻孔输出的临时文件
unlink $PAR->{out_dir}.'/'.$output_layer;
##回读钻孔程式
if( $PAR->{reread_layer} =~ /yes/i){
update_loading("$layer 层钻孔程式回读中...",0,position=>'n');
my $new_layer_2 = $new_layer;
input_drill_program(layer=>$layer,file=>$PAR->{out_dir}.'/'.$new_layer_2,new_layer=>$new_layer);#drl_type=>$drl_type,drl_side=>$drl_side
}
#传入web server数据
#if($layer =~ /(cdr|vpg|alp|alr|psp)/){
# update_loading("$layer 层web server数据上传中...",0,position=>'n');
# open(TMP,$new_file) || die "cannot open $PAR->{out_dir}/$new_layer";
# my @data = <TMP>;
# close (TMP);
# chomp(@data);
# my $file_data;
# $file_data = join("\n",@data);
# $server_data->{data} = [{
# tooling_type=>"mech_drill",
# tooling_name=>$new_layer,
# partnumber=>$Job,
# tooling_text_data=>$file_data,
# }];
# #$GUI->debug(-text=>dump($server_data));
# my $result = sec_web_services($url,$server_data);
# if($result){
# $GUI->msgbox(-icon=>'error',-text=>"Web services数据传输错误!");
# return 'Cancel';
# }
#}
}
hide_loading();
##保存料号
if( $PAR->{save_job} =~ /yes/i ){
show_loading("$Job 正在保存料号,请稍候...",0,position=>'n');
$GEN->checkInout(job=>$Job,mode=>'out');
$GEN->saveJob(job=>$Job);
hide_loading();
}
###output and return status, if genesis error, it will output genesis error command
unless ($GEN->{STATUS}){
return 'done';
}
else{
$GUI->msgbox(-icon=>'error',-text=>join("\n",@{$GEN->{STATUS}}));
return 'Error';
}
}
catch Error::Simple with {
my $error = shift;
$GUI->msgbox(-icon=>'error',-text=>$error);
return 'Error';
}
finally{
$GEN->COM('disp_on');
};
sub get_work_step {
my @steps = $GEN->getStepList(job=>$Job);
if ( @steps == 0 ) {
$GUI->msgbox(-icon=>'error',-text=>'在料号中没有Step存在,请确认。');
return 'Cancel';
}
elsif (@steps != 0){
$PAR->{step_filter} = '.*' unless $PAR->{step_filter};
my @tmp_steps = grep(/$PAR->{step_filter}/,@steps);
if ( @tmp_steps == 0 ) {
$GUI->msgbox(-icon=>'warning',-text=>'根据脚本参数过滤出来的step不存在,请检查资料或者脚本参数配置!');
return 'Cancel';
}
elsif (@tmp_steps == 1) {
$Step = $tmp_steps[0];
}
else {
$Step = $GUI->select_step(-title=>'请选择工作 Step',
-steplist=>[@tmp_steps],
-default=>[$tmp_steps[0]],
-gen=>$GEN,
-selectmode=>'single');
return 'Cancel' unless ($Step);
}
}
return undef;
}
sub select_work_layer {
my %par = @_;
my @drill;
my %matrix = $GEN->getMatrix(job=>$Job,type=>'hash');
foreach my $layer (sort {$matrix{$a}{row} <=> $matrix{$b}{row}} keys %matrix) {
next if $layer =~ /ddr/;
if(defined($matrix{$layer}{layer_type}) and $matrix{$layer}{layer_type} eq 'drill'){
push @drill,$layer;
}
}
unless( @drill ){
$GUI->msgbox(-icon=>'warning',-text=>'资料中无钻孔层,请确认!');
return 'Cancel';
}
if ($PAR->{is_select_lyr} eq 'yes' and scalar @drill > 1) {
my (%tmp_matrix);
foreach my $layer (@drill) {
$tmp_matrix{$layer} = $matrix{$layer};
}
@drill = $GUI->select_layer(
-title=>'请选择输出层别',
-layermatrix=>\%tmp_matrix,
-default => ['drl','md','bk','lp'],
-selectmode => 'multiple');#single
return 'Cancel' unless(@drill);
}
return @drill;
}
sub get_scale_info{
my %par = @_;
my (%rows,$n);
foreach my $layer (@{$par{layers}}){
$n ++;
$rows{$layer}{sequence} = $n;
$rows{$layer}{layer} = $layer;
if($layer eq "md"){
$rows{$layer}{x} = 1.0004;
$rows{$layer}{y} = 1.0004;
}
else{
$rows{$layer}{x} = 1.0000;
$rows{$layer}{y} = 1.0000;
}
}
my $scale_factor = $GUI->show_tableform (
-defaultsize=>[380,400],-title => '请确认涨缩值',-rows => \%rows,
-showcheck => 1,-gen => $GEN,
-columns => [
{
column_name=>'layer',
label=>'层名称',
width=>70,
type=>'label',
},
{
column_name=>'x',
label=>'X涨缩值',
width=>130,
type=>'number',
},
{
column_name=>'y',
label=>'Y涨缩值',
width=>130,
type=>'number',
},
],
);
return 'Cancel' unless ($scale_factor);
##
return $scale_factor;
}
=head
drillmarge 输出
=cut
sub drill_out
{
my %par = @_;
my $nc_set = 'sec-jt';
my @ncsets = $GEN->getNcsetsList(job=>$Job,step=>$Step,layer=>$par{layer});
if( @ncsets ){
if (grep (/^($nc_set)$/,@ncsets)) {
$GEN->COM('ncset_delete',name=>$nc_set);
}
}
#钻带涨缩中心点
my $x_anchor = ($par{scale_x} != 1 or $par{scale_y} != 1) ? $PAR->{profile_limits}{xc} : 0;
my $y_anchor = ($par{scale_x} != 1 or $par{scale_y} != 1) ? $PAR->{profile_limits}{yc} : 0;
unlink if(-e $PAR->{out_dir}.'/'.$par{output_layer});
my ($org_x,$org_y,$angle);
if($PAR->{profile_limits}{ysize} == 603 and $PAR->{profile_limits}{xsize} == 706){
$org_x = $PAR->{profile_limits}{yc};#- 15
$org_y = 5;
$angle = 270;
$datum->{x} = $PAR->{profile_limits}{xmax} - 5;
$datum->{y} = $PAR->{profile_limits}{yc};
$datum->{angle} = 90;
$datum->{type} = 1;#拼版类型
}elsif($PAR->{profile_limits}{ysize} == 603 and $PAR->{profile_limits}{xsize} == 606){
$datum->{x} = $org_x = $PAR->{profile_limits}{xc};#- 5
$datum->{y} = $org_y = 5;
$datum->{angle} = $angle = 0;
$datum->{type} = 0;#拼版类型
}else{
$datum->{x} = $org_x = $PAR->{profile_limits}{xc};#- 24
$datum->{y} = $org_y = 5;
$datum->{angle} = $angle = 0;
$datum->{type} = 0;#拼版类型
}
# 铝片塞防焊和铝片塞树脂程序,bot面时需要mirror
my $xmirror = 'no';
my $ymirror = 'no';
if ($par{layer} =~ /al[pr](\d\d)(\d\d)/) {
my $start = $1 + 0;
my $end = $2 + 0;
if ($start > $end) {
$xmirror = 'yes';
}
}
#获取@drl_section_data数据
if($par{layer} =~ /(cdr)/ and $GEN->getLayerCount(job=>$Job) >= 4){
my @feat = $GEN->getFeatures(job=>$Job,step=>$Step,layer=>'pnl-map',units=>'mm');
my @data_tmp = grep($_->{attributes}->[0] =~ /(DRL_SECTION)/,@feat);#获取监视孔坐标
$section_tool = $map_info->{P}{min_drl} >= 1100 ? 1100 : $map_info->{P}{min_drl};
@drl_section_data = TL::GenMath->p_trans($datum,$datum->{angle},'no',-$datum->{x},-$datum->{y},@data_tmp);
# if($datum->{angle} == 90){
# my @data_tmp = TL::GenMath->p_trans($datum,$datum->{angle},'no',0,0,@data_tmp);#坐标选择
# foreach my $data (@data_tmp){
# my $coorder_txt;
# $coorder_txt = change_coode(data=>$data,datum=>$datum);
# $drl_section_data->{$coorder_txt} = 1;
# }
# }else{
# foreach my $data (@data_tmp){
# my $coorder_txt;
# $coorder_txt = change_coode(data=>{x=>$data->{x},y=>},datum=>$datum);
# $drl_section_data->{$coorder_txt} = 1;
# }
# }
}
my $id = $nc_set;
$GEN->COM('ncset_units',units=>'mm');
if($par{layer} =~ /(cdr)/){
$GEN->affectedLayer(affected=>'yes',layer=>$par{layer},clear_before=>'yes');
$GEN->COM("adv_filter_reset");
$GEN->COM("reset_filter_criteria,filter_name=,criteria=all");
$GEN->selectByFilter(attribute=>[{attribute=>'tl_string',text=>"*LDI_HOLE_Two*"}]);
$GEN->selectByFilter(attribute=>[{attribute=>'tl_string',text=>"*XRAY_HOLE*"}]);
$GEN->COM("adv_filter_reset");
$GEN->COM("reset_filter_criteria,filter_name=,criteria=all");
$GEN->selChangeSym(symbol=>'r1') if $GEN->getSelectCount();
$GEN->affectedLayer( mode=>'all',affected=>'no' );
}
#$GEN->COM('open_sets_manager',test_current=>'no');
$GEN->COM('nc_create',ncset=>$id,device=>'basic_excellon',lyrs=>$par{layer},thickness=>0);
$GEN->COM('nc_set_advanced_params',layer=>$par{layer},ncset=>$id);
$GEN->COM('nc_set_current',job=>$Job,step=>$Step,layer=>$par{layer},ncset=>$id);
$GEN->COM('nc_set_file_params',single_sr=>'no',output_path=>$PAR->{out_dir},output_name=>$par{output_layer},zeroes=>'none',units=>'mm',tool_units=>'mm',nf1=>3,nf2=>3,decimal=>'no',modal_coords=>'no');
$GEN->COM('nc_register',angle=>$angle,xoff=>0,yoff=>0,version=>1,xorigin=>$org_x,yorigin=>$org_y,xscale=>$par{scale_x},yscale=>$par{scale_y},xscale_o=>$x_anchor,yscale_o=>$y_anchor,xmirror=>$xmirror,ymirror=>$ymirror);
$GEN->COM('nc_set_optim',optimize=>'yes',iterations=>5,reduction_percent=>1,cool_spread=>$PAR->{cool_spread},break_sr=>'yes',xspeed=>2540,yspeed=>2540,diag_mode=>'45ort');
$GEN->COM('nc_cre_output',layer=>$par{layer},ncset=>$id);
my $profile = $GEN->getProfileLimits(job=>$Job,step=>$Step,units=>'mm');
$GEN->origin(x=>$profile->{xmin},y=>$profile->{ymin});
if($par{layer} =~ /(cdr)/){
$GEN->affectedLayer(affected=>'yes',layer=>$par{layer},clear_before=>'yes');
$GEN->COM("adv_filter_reset");
$GEN->COM("reset_filter_criteria,filter_name=,criteria=all");
$GEN->selectByFilter(attribute=>[{attribute=>'tl_string',text=>"*LDI_HOLE_Two*"}]);
$GEN->selectByFilter(attribute=>[{attribute=>'tl_string',text=>"*XRAY_HOLE*"}]);
$GEN->COM("adv_filter_reset");
$GEN->COM("reset_filter_criteria,filter_name=,criteria=all");
$GEN->selChangeSym(symbol=>'r3054') if $GEN->getSelectCount();
$GEN->affectedLayer( mode=>'all',affected=>'no');
}
@ncsets = $GEN->getNcsetsList(job=>$Job,step=>$Step,layer=>$par{layer});
if( @ncsets ){
if (grep (/^($nc_set)$/,@ncsets)) {
$GEN->COM('ncset_delete',name=>$nc_set);
}
}
return undef;
}
sub edit_nc_file{
my %par = @_;
open(TMP,"$par{output_file}") || die "cannot open $par{output_file}";
my @data = <TMP>;
close (TMP);
chomp @data;
#
my %data = split_program(data=>\@data);
my $ans = convert_new_program(layer=>$par{layer},new_file=>$par{new_file},data=>\%data,x=>$par{x},y=>$par{y});
return $ans if $ans;
return undef;
}
sub split_program{
my %par = @_;
my $ui_info = $par{info};
my (%info);
my ($flag,$router_flag) = ('start',undef);
foreach my $line(@{$par{data}}){
if( $flag eq 'start' ){
if( $line eq 'M48' ){
$flag = 'overhead';
}
}
elsif( $flag eq 'overhead' ){
if( $line =~ /^T01C/i ){
$flag = 'head';
}
}
elsif( $flag eq 'head' ){
if( $line !~ /^T\d+/i ){
$flag = 'neck';
}
}
elsif( $flag eq 'neck' ){
if( $line =~ /^T01/i ){
$flag = 'body';
}
}
elsif( $flag eq 'body' ){
if( $line =~ /^M30$/i ){
$flag = 'end';
}
}
##
if( $flag eq 'overhead' ){
push @{$info{overhead}},$line;
}
elsif( $flag eq 'head' ){
if($line =~ /^T(\d+)C(.*)/){
if($2 - $section_tool/1000 < 0.0001){
$section_number = $1;
}
}
push @{$info{head}},$line;
}
elsif( $flag eq 'neck' ){
push @{$info{neck}},$line;
}
elsif( $flag eq 'body' ){
if( $line =~ /^(T(\d+))$/i ){
$router_flag = $1;
}
if($router_flag){
my ($num) = $router_flag =~ /^T(\d+)$/;
$info{body}{$router_flag}{num} = $num;
#判断孔的范围 2020-04-21
# if($num - $section_number < 0.001 and $line !~ /^T/){
# my $point = change_coode_to_vale($line);
# my $are_check = 0;
# foreach my $symbol (@drl_section_data){
# my $dist = TL::GenMath->point2sym_dist($point,$symbol);
# if($dist == 0){
# $are_check = 1;
# last;
# }
# }
# if($are_check){
# push @drl_section,$line;
# }else{
# push @{$info{body}{$router_flag}{value}},$line;
# }
# }else{
push @{$info{body}{$router_flag}{value}},$line;
# }
}
}
elsif( $flag eq 'end' ){
push @{$info{end}},$line;
}
##
}
if( wantarray ){
return %info;
}
else{
return \%info;
}
}
sub convert_new_program{
my %par = @_;
##
open(NEWMYFILE,">$par{new_file}");
my %data = %{$par{data}};
##0.插入表头
# if($par{x} != 1 or $par{y} != 1){
# print NEWMYFILE 'M47,'.$Job.' '.'X:'.$par{x}.' '.'Y:'.$par{y},"\n";
# }
##1.头顶(刀径清单之前的)/overhead
foreach my $line(@{$data{overhead}}){
print NEWMYFILE $line,"\n";
}
##
##2.程序头(router清单)/head
my $tool_change = get_tool_change(layer=>$par{layer},data=>$par{data});
#$GUI->debug(dump($tool_change));
###人工排序一次
# $tool_change = manual_sort_tool(layer=>$par{layer},data=>$par{data},info=>$tool_change);
# return $tool_change if $tool_change eq 'Cancel';
##目前扩孔后没有其它类型的孔
my $nibble_suffix = 1;
my $check_nibble_tool = 0;
foreach my $line(@{$data{head}}){
my ($tool,$suffix) = $line =~ /^(T\d+)C.*$/;
next unless $tool;
##刀序顺序使用最新的
next unless $tool_change->{$tool}{new_tool};
foreach my $item(values %$tool_change){
if( $tool eq $item->{new_tool} ){
if($tool_change->{$item->{new_tool}}{size} > 6.35){
if(! $check_nibble_tool){
print NEWMYFILE $tool.'C'.(3.15 + $nibble_suffix/1000),"\n";
#$nibble_suffix++;
$check_nibble_tool = 1;
}
}else{
print NEWMYFILE $item->{new_header},"\n";
}
$PAR->{tool_num_count} = $item->{new_tool_num} unless ($PAR->{tool_num_count} and $PAR->{tool_num_count} > $item->{new_tool_num});
#$hole_exit = 1 if $item->{new_header} =~ /503$/;
}
}
}
# if($par{layer} =~ /(cdr|vpg|alp|alr|psp)/){
# print NEWMYFILE 'T99C0.549',"\n";
# }
##3.脖子(程序头和正式T序坐标之间)/neck
foreach my $line(@{$data{neck}}){
next if $line =~ /g93/i;
print NEWMYFILE $line,"\n";
}
# if(@drl_section_data){
# print NEWMYFILE 'T'.$section_number,"\n";
# foreach my $tmp (@drl_section){
# print NEWMYFILE $tmp,"\n";
# }
# }
##4.实际的每把T序/body
my $nibble_tool_check = 0;
foreach my $tool (sort{$data{body}{$a}{num}<=>$data{body}{$b}{num}} keys %{$data{body}}){
##获取对应的新刀径
my $new_tool;
my $check_drl_section = 0;
foreach my $old_tool(keys %$tool_change){
if( $tool eq $tool_change->{$old_tool}{new_tool} ){
$new_tool = $old_tool;
}
}
next unless $new_tool;
foreach my $line(@{$data{body}{$new_tool}{value}}){
#if( abs($tool_change->{$new_tool}{size} - 3.175) < 0.001 ){
# if( $line =~ /^(T\d+)/ ){
# print NEWMYFILE '/',$tool,"\n";
# }
# else{
# print NEWMYFILE '/',$line,"\n";
# }
#}
#else{
#if( $line =~ /^(T\d+)/ ){
# print NEWMYFILE $tool,"\n";
#}
#else{
# print NEWMYFILE $line,"\n";
#}
#}
if( $tool_change->{$new_tool}{size} > 6.35 ){
if( $line =~ /^(T\d+)/ ){
if( !$nibble_tool_check ){
print NEWMYFILE $tool,"\n";
$nibble_tool_check = 1;
}
}
else{
print NEWMYFILE $line,"\n";#'G84X'.$tool_change->{$new_tool}{size}
}
}
else{
if( $line =~ /^(T\d+)/ ){
print NEWMYFILE $tool,"\n";
}
else{
if( $line =~ /X.*Y.*G85X.*Y.*/ ){
my ($tmp1,$tmp2) = $line =~ /(X\-?\d*\.?\d*Y\-?\d*\.?\d*)G85(X\-?\d*\.?\d*Y\-?\d*\.?\d*)/;
my $slot_star = change_coode_to_vale($tmp1);
my $slot_end = change_coode_to_vale($tmp2);
my $slot_size = $tool_change->{$new_tool}{size};
my $slot_length = $slot_size + TL::GenMath->line_length({xs=>$slot_star->{x},xe=>$slot_end->{x},ys=>$slot_star->{y},ye=>$slot_end->{y}});
my $slot_info = ger_short_slot_vale(slot_size=>$slot_size,slot_length=>$slot_length);
#if($slot_info){
# my $angle = $slot_info->{angle};
# my $point = TL::GenMath->rotate_point($slot_star,$slot_end,$angle);
# my $tmp_data = change_coode(data=>{x=>$point->{x},y=>$point->{y}},datum=>{x=>0,y=>0});
# my $tmp_line = $tmp1.'G85'.$tmp_data;
# print NEWMYFILE $tmp_line,"\n";
#}else{
print NEWMYFILE $line,"\n";
#}
}else{
print NEWMYFILE $line,"\n";
}
}
}
}
}
#插入M97坐标 'X-214500Y000000'
if($par{layer} =~ /(cdr|vpg|alp|alr|psp)/){
my @feat = $GEN->getFeatures(job=>$Job,step=>$Step,layer=>'pnl-map',units=>'mm');
my @feat_M97 = grep($_->{attributes}->[0] =~ /(DRL_TXT_DRL)/,@feat);
my $coordinate_txt;
my $mode;#判断*的位置是横放还是竖放 1 代表横放 2代表竖放
if($feat_M97[0]->{x} >= $PAR->{sr}{xmin} and $feat_M97[0]->{x} <= $PAR->{sr}{xmax}){
$mode = 1;
}else{
$mode = 2;
}
if($datum->{angle} == 90){
my @M97_tmp = TL::GenMath->p_trans($datum,$datum->{angle},'no',0,0,({x=>$feat_M97[0]->{x},y=>$feat_M97[0]->{y}}));#返回的是一个数组
if($mode == 1){
$coordinate_txt = change_coode(data=>{x=>$M97_tmp[0]->{x} + 2.5 - 0.275,y=>$M97_tmp[0]->{y} - 25 + 0.275},datum=>$datum);
}else{
$coordinate_txt = change_coode(data=>{x=>$M97_tmp[0]->{x} - 25 + 0.275,y=>$M97_tmp[0]->{y} - 2.5 + 0.275},datum=>$datum);
}
}else{
if($mode == 1){
$coordinate_txt = change_coode(data=>{x=>$feat_M97[0]->{x} - 25 + 0.275,y=>$feat_M97[0]->{y} - 2.5 + 0.275},datum=>$datum);
}else{
$coordinate_txt = change_coode(data=>{x=>$feat_M97[0]->{x} + 2.5 - 0.275,y=>$feat_M97[0]->{y} - 25 + 0.275},datum=>$datum);
}
}
if($datum->{angle} == 90){
print NEWMYFILE 'T99',"\n";
if($mode == 1){
#$GEN->PAUSE('M98');
print NEWMYFILE 'M98,'.substr($Job,0,6).' $S$I',"\n";
}else{
#$GEN->PAUSE('M97');
print NEWMYFILE 'M97,'.substr($Job,0,6).' $S$I',"\n";
}
print NEWMYFILE $coordinate_txt,"\n";
}else{
print NEWMYFILE 'T99',"\n";
if($mode == 1){
print NEWMYFILE 'M97,'.substr($Job,0,6).' $S$I',"\n"
}else{
print NEWMYFILE 'M98,'.substr($Job,0,6).' $S$I',"\n";
}
print NEWMYFILE $coordinate_txt,"\n";
}
}
##5.结束/end
foreach my $line(@{$data{end}}){
print NEWMYFILE $line,"\n";
}
##
close (NEWMYFILE);
return undef;
}
sub get_tool_change{
my %par = @_;
my %info;
my %data = %{$par{data}};
my $is_laser = $par{is_laser};
my $row_num = 0;
##
my (%head,%special,$exist_2500);
##先判断有无3.054的刀径(排第1)
foreach my $line(@{$data{head}}){
my ($tool,$size,$data) = $line =~ /^(T\d+)C(\d*\.?\d{3})(S?.*)$/;
next unless $tool;
$head{$tool}{data} = 'C'.$2;
####
if( abs($size - 0.001) < 0.0001 ){
$head{$tool}{data} = 'C3.054';
$row_num++;
$info{$tool}{new_tool_num} = $row_num;
$info{$tool}{new_tool} = 'T'.sprintf("%02s",$row_num);
$info{$tool}{size} = 3.054;
$info{$tool}{new_header} = $info{$tool}{new_tool}.$head{$tool}{data};
}
}
foreach my $line(@{$data{head}}){
my ($tool,$size,$data) = $line =~ /^(T\d+)C(\d*\.?\d{3})(.*)$/;
next unless $tool;
next if(abs($size - 0.001) < 0.0001);
$row_num++;
$info{$tool}{size} = $size;
$info{$tool}{new_tool_num} = $row_num;
$info{$tool}{new_tool} = 'T'.sprintf("%02s",$row_num);
$info{$tool}{new_header} = $info{$tool}{new_tool}.$head{$tool}{data};
}
return \%info;
}
sub manual_sort_tool{
my %par = @_;
my $data = $par{data};
my $tool_info = $par{info};
my @items;
my ($slot_flag,@slot_size);
foreach my $num(1..scalar(keys %{$data->{body}})){
my $tool = 'T'.sprintf("%02s",$num);
next unless $tool_info->{$tool}{new_tool};
foreach my $old_tool(sort{$tool_info->{$a}{new_tool_num}<=>$tool_info->{$b}{new_tool_num}} keys %$tool_info){
if( $tool eq $tool_info->{$old_tool}{new_tool} ){
my $suffix;
my $size = $tool_info->{$old_tool}{size};
push @items,{tool=>$old_tool,size=>$tool_info->{$old_tool}{size} >= 1 ? $tool_info->{$old_tool}{size} : '0'.$tool_info->{$old_tool}{size},suffix=>$suffix};
last;
}
}
}
update_loading("$par{layer} 层请确认钻刀排列顺序...",0,position=>'n');
my %form = $GUI->show_form(
-title => "请确认钻孔刀径顺序",
-defaultsize => [400,500],
-columns => 2,
-items => [
{
name => 'table',
type => 'treeview',
label => '',
label_position => 'top',
expand=>1,
scrolledwindow=>{},
property => {
height_request=>200,
tl_model_type => 'list',
enable_grid_lines => 'none',
tl_mapping =>['tool' => 'Glib::String','size' => 'Glib::String','suffix'=>'Glib::String'],
tl_columns =>[
{title=>'原始刀序',visible=>1,resizable=>1,min_width=>80,expand=>1,renders=>[{class=>'Text',property=>{editable=>0,background=>'#FCFBB6',foreground=>'#000000'},text=>'tool'}]},
{title=>'刀径',visible=>1,resizable=>1,min_width=>80,expand=>1,renders=>[{class=>'Text',property=>{editable=>0,background=>'#FCFBB6',foreground=>'#000000'},text=>'size'}]},
{title=>'后缀(可编辑)',visible=>1,resizable=>1,min_width=>80,expand=>1,renders=>[{class=>'Text',property=>{editable=>1,background=>'#C5DBF2',foreground=>'#000000'},text=>'suffix'}]},
],
},
value => \@items,
get_value_func => sub{ my %par = @_;
my $tvdata = $par{widget}->tl_get_model_data();
return $tvdata;
},
set_value_func => sub{ my %par = @_;
my $v = $par{value};
$par{widget}->tl_set_data($v);
return 0;
},
button_position=>'top',
buttons => [
{ name=>'top',label=>'置顶',stock=>'gtk-goto-top',
command=>sub{ my %p = @_;
my $widget = $p{formpanel}->get_widget('table');
$widget->set_property(reorderable=>1);
$widget->tl_sel_moveto_top();
$widget->set_property(reorderable=>0);
}
},
{ name=>'up',label=>'上移',stock=>'gtk-go-up',
command=>sub{ my %p = @_;
my $widget = $p{formpanel}->get_widget('table');
$widget->set_property(reorderable=>1);
$widget->tl_sel_move_up();
$widget->set_property(reorderable=>0);
}
},
{ name=>'down',label=>'下移',stock=>'gtk-go-down',
command=>sub{ my %p = @_;
my $widget = $p{formpanel}->get_widget('table');
$widget->set_property(reorderable=>1);
$widget->tl_sel_move_down();
$widget->set_property(reorderable=>0);
}
},
{ name=>'bottom',label=>'置底',stock=>'gtk-goto-bottom',
command=>sub{ my %p = @_;
my $widget = $p{formpanel}->get_widget('table');
$widget->set_property(reorderable=>1);
$widget->tl_sel_moveto_bottom();
$widget->set_property(reorderable=>0);
}
},
],
},
]
);
return 'Cancel' unless %form;
##将界面确认的结果重新整理一遍
my %info;
my @data = @{$form{table}};
my $row_num;
foreach my $item(@data){
$row_num++;
if( $item->{suffix} =~ /^\(w(\d+)\)$/i || $item->{suffix} =~ /^\(w(\d+)s\d+\)$/i || $item->{suffix} =~ /^\(s(\d+)\)$/i){
$info{$item->{tool}}{suffix} = $item->{suffix};
$info{$item->{tool}}{size} = $item->{size};
}
elsif($item->{suffix} =~ /^(\d+)$/i ){
$info{$item->{tool}}{suffix} = $item->{suffix}+0;
$info{$item->{tool}}{size} = $item->{size};
}
else{
$info{$item->{tool}}{size} = $item->{size};
}
$info{$item->{tool}}{new_tool_num} = $row_num;
$info{$item->{tool}}{new_tool} = 'T'.sprintf("%02s",$row_num);
if( $item->{suffix} =~ /^\((w|s)(\d+)\)$/i || $item->{suffix} =~ /^\(w(\d+)s(\d+)\)$/i){
$info{$item->{tool}}{new_header} = $info{$item->{tool}}{new_tool}.'C'.sprintf("%.3f",$info{$item->{tool}}{size}).$item->{suffix};
}
else{
$info{$item->{tool}}{new_header} = $info{$item->{tool}}{new_tool}.'C'.sprintf("%.3f",$info{$item->{tool}}{size});
}
}
##
return \%info;
}
sub input_drill_program{
my %par = @_;
$GEN->COM( "input_manual_reset");
$GEN->COM( "input_manual_set,path=$par{file},job=$Job,step=$Step,format=Excellon2,data_type=ascii,
units=mm,coordinates=absolute,zeroes=none,nf1=3,nf2=3,decimal=no,separator=nl,tool_units=mm,layer=$par{new_layer},wheel=,
wheel_template=,nf_comp=0,multiplier=1,text_line_width=0.0024,signed_coords=no,break_sr=yes,drill_only=no,merge_by_rule=no,threshold=200,resolution=3");
$GEN->COM( "input_manual,script_path=");
$GEN->zoomHome();
return undef;
}
=head
web server数据传输
=cut
sub sec_web_services{
use LWP::UserAgent;
use LWP;
use HTTP::Headers;
use HTTP::Response;
use Encode;
use JSON;
use JSON qw(encode_json);
my $url = shift;
my $data = shift;
my $json = JSON->new->allow_nonref;
my $ua = LWP::UserAgent->new();
$ua->agent("Mozilla/5.0 (Windows NT 6.1; rv:30.0) Gecko/20100101 Firefox/30.0");
my $header = ['Content-Type' => 'application/json; charset=UTF-8'];
my $body = encode('utf8', $json->encode($data));
my $request = HTTP::Request->new('POST', $url, $header, $body);
my $res = $ua->request($request);
#$GUI->debug(-text=>dump($res,'-----------------------------------------------------------------',$res->is_success));
if ($res->is_success) {
return 0;
}else{
return 1;
}
}
=head
3:3 不省零
坐标转换 data=>{x=>,y=>} datum=>{x=>,y=>}
=cut
sub change_coode
{
my %par = @_;
my ($check_x,$check_y);
$par{data}->{x} = $par{data}->{x} - $par{datum}->{x};
$par{data}->{y} = $par{data}->{y} - $par{datum}->{y};
$check_x = $par{data}->{x} > 0 ? '': '-';
$check_y = $par{data}->{y} > 0 ? '': '-';
$par{data}->{x} = sprintf("%0.3f",$par{data}->{x});
$par{data}->{x} = sprintf("%06s",abs($par{data}->{x})*1000);
$par{data}->{y} = sprintf("%0.3f",$par{data}->{y});
$par{data}->{y} = sprintf("%06s",abs($par{data}->{y})*1000);
return 'X'.$check_x.($par{data}->{x}).'Y'.$check_y.($par{data}->{y});
}
=head
坐标转换成数值
=cut
sub change_coode_to_vale
{
my $string = shift;
$string =~ /X(-?\w+)Y(-?\w+)/;
my $x_data = sprintf("%0.3f",$1/1000);
my $y_data = sprintf("%0.3f",$2/1000);
return {x=>$x_data,y=>$y_data};
}
sub _deleteLayer{
my %par = @_;
foreach my $layer(@{$par{layer}}){
$GEN->deleteLayer(layer=>$layer) if ($GEN->isLayerExists(job=>$Job,layer=>$layer));
}
}
=head
输出层新命名
=cut
sub get_new_layer_name
{
my $job = shift;
my @tmp = split/\-/,$job;
splice(@tmp,2,1);
$tmp[2] =~ s/2//;
unless($tmp[2]){
splice(@tmp,2,1);
}
my $new = join('-',@tmp);
return $new;
}
=head
短槽拉伸值 slot_size=>,slot_length=>
=cut
sub ger_short_slot_vale
{
my %par = @_;
my $info = {
1.5 =>[
{size_min=>0.4,size_max=>0.55,length=>0,angle=>0},
{size_min=>0.6,size_max=>0.65,length=>0.07,angle=>5},
{size_min=>0.7,size_max=>0.75,length=>0.0625,angle=>4},
{size_min=>0.8,size_max=>0.95,length=>0.05,angle=>2.5},
{size_min=>1.0,size_max=>1.25,length=>0.045,angle=>2},
{size_min=>1.3,size_max=>1.6,length=>0.0375,angle=>1},
{size_min=>1.65,size_max=>2.5,length=>0.0375,angle=>1},
{size_min=>2.55,size_max=>999,length=>0.03,angle=>0.5},
],
1.75 =>[
{size_min=>0.4,size_max=>0.55,length=>0.055,angle=>4},
{size_min=>0.6,size_max=>0.65,length=>0.055,angle=>3},
{size_min=>0.7,size_max=>0.75,length=>0.05,angle=>2.5},
{size_min=>0.8,size_max=>0.95,length=>0.045,angle=>2},
{size_min=>1.0,size_max=>1.25,length=>0.0375,angle=>1},
{size_min=>1.3,size_max=>1.6,length=>0.03,angle=>0.5},
{size_min=>1.65,size_max=>2.5,length=>0.03,angle=>0.5},
{size_min=>2.55,size_max=>999,length=>0.025,angle=>0.5},
],
2.0 =>[
{size_min=>0.4,size_max=>0.55,length=>0.045,angle=>3},
{size_min=>0.6,size_max=>0.65,length=>0.0375,angle=>2},
{size_min=>0.7,size_max=>0.75,length=>0.0375,angle=>1.5},
{size_min=>0.8,size_max=>0.95,length=>0.03,angle=>1},
{size_min=>1.0,size_max=>1.25,length=>0.03,angle=>1},
{size_min=>1.3,size_max=>1.6,length=>0.025,angle=>0.5},
{size_min=>1.65,size_max=>2.5,length=>0.02,angle=>0.5},
{size_min=>2.55,size_max=>999,length=>0.02,angle=>0},
],
};
my $type;
if($par{slot_length}/$par{slot_size} <= 1.5){
$type = 1.5;
}elsif($par{slot_length}/$par{slot_size} > 1.5 and $par{slot_length}/$par{slot_size} <= 1.75){
$type = 1.75;
}elsif($par{slot_length}/$par{slot_size} > 1.75 and $par{slot_length}/$par{slot_size} <= 2){
$type = 2.0;
}elsif($par{slot_length}/$par{slot_size} > 2){
return 0;
}
my $result;
foreach my $tmp (@{$info->{$type}}){
if($par{slot_size} >= $tmp->{size_min} and $par{slot_size} <= $tmp->{size_max}){
$result = 1;
return $tmp;
}
}
unless ($result){
return 0;
}
}
__END__
\ No newline at end of file
/* /*
NAME: NAME:
DESCRIPTION: ; DESCRIPTION: 原稿拼底片;
PARAMETER: PARAMETER:
[ [
{
name : 'out_line',
title : '外形层',
type : 'LineEdit',
property : {tool_tip : '定原稿拼片的step,如未设定,默认为org'},
},
{ {
name : 'step', name : 'step',
title : 'step', title : 'Org step',
type : 'LineEdit', type : 'LineEdit',
property : {tool_tip : '目标step,默认是orig'}, property : {tool_tip : '定原稿拼片的step,如未设定,默认为org'},
}, },
{ {
name : 'outline', name : 'job_suffix',
title : '外形层', title : '料号后缀',
type : 'LineEdit', type : 'LineEdit',
property : {tool_tip : '支持正则匹配'}, property : {tool_tip : '定原稿拼片的料号后缀,如未设定,默认为-org'},
},
{
name : 'path',
title : '输出路径',
type : 'LineEdit',
property : {tool_tip : '定原稿拼片的路径'},
}, },
{ {
name : 'auto_save', name : 'auto_save',
...@@ -36,7 +48,7 @@ PARAMETER: ...@@ -36,7 +48,7 @@ PARAMETER:
HELP: HELP:
<html><body bgcolor="#DDECFE"> <html><body bgcolor="#DDECFE">
<font size="3" color="#003DB2"><p>功能简介</p></font> <font size="3" color="#003DB2"><p>功能简介</p></font>
<p> 铺铜 </p> <p> 原稿拼底片 </p>
<br> <br>
<font size="3" color="#003DB2"><p>参数配置</p></font> <font size="3" color="#003DB2"><p>参数配置</p></font>
<p> step信息 </p> <p> step信息 </p>
...@@ -60,209 +72,806 @@ var GEN = $.gen; ...@@ -60,209 +72,806 @@ var GEN = $.gen;
var GUI = $.gui || {}; var GUI = $.gui || {};
var Job = $.job || $.job_name; var Job = $.job || $.job_name;
var JobId = $.job_id; var JobId = $.job_id;
var db = $.db || IKM.db; var db = $.db || IKM.db
require("topsin.genmath");
var genMath = new GenMath();
var PAR = {} var PAR = {}
if ($.par) { if ($.par) { PAR = $.par } else if ($.hasOwnProperty('script_parameter')){ PAR = JSON.parse($.script_parameter); }
PAR = $.par
} else if ($.hasOwnProperty('script_parameter')){
PAR = JSON.parse($.script_parameter);
}
if (mode === "aimdfm") { if (mode === "aimdfm") {
var database = require("topsin.database"); var database = require("topsin.database");
database.addConnection($.conf.database_conf, "DFM"); database.addConnection($.conf.database_conf, "DFM");
var QDfm = database.query("DFM"); var QDfm = database.query("DFM");
$.QDfm = QDfm; $.QDfm = QDfm;
if ($.conf.product_type == "aimdfm") { if ($.conf.product_type == "aimdfm") {
QDfm.updateRow({ QDfm.updateRow({ table: "pdm_aimdfm_task", data: { current_process_title: $.process_title }, where: { id: $.task_id } });
table: "pdm_aimdfm_task",
data: {
current_process_title: $.process_title
},
where: { id: $.task_id }
});
} }
} }
require("topsin.genmath")
var genMath = new GenMath();
var gui = new NewGUI(GUI);
var Status = 'ok'; var Status = 'ok';
var resultData = []; var resultData = [];
var par = PAR;
try { var default_par = {
var par = PAR; out_line:"out",
var default_par = { step:"step",
step: "unit.+", job_suffix:"-org",
step2:"unit", path:"C:/Users/Administrator/Desktop/jobs/demo",
auto_save: "No", auto_save: "No",
outline:"ol",
units:"mm" units:"mm"
}
for(var key in default_par){ if (!par.hasOwnProperty(key) || par[key] == ""){ par[key] = default_par[key] }}
var job = Job;
var Step;
var film_size = ['20x24','22x26','24x28'];
var film_tol_number = 0; // 总的底片数量
var sold_mask_layer = []; // 阻焊层
var cust_code = "",serial="";
if(/^(?:[a-z0-9]{2})([a-z0-9]{2})(?:[a-z0-9])(?:[a-z0-9])(?:[a-z0-9])([a-z0-9]{3})(?:(?:[a-z0-9])(?:[a-z0-9])(?:[a-z0-9])|sys)(?:\-s)?/i.test(job)){
cust_code = RegExp.$1;
serial = RegExp.$2;
}
par.film_name = cust_code + serial + '-org';
try {
if(_.isEmpty(job)){throw "参数job不存在"} else { job = job.toLowerCase() }
if(!GEN.isJobExists({job:job})){throw "料号"+job+"不存在"}
var gotoFlag = false;
Job = job + par.job_suffix;
// 检查拼片料号是否存在
var films=[],tmp_matrix={};
if (GEN.isJobExists({job:Job}) ){
var matrix = GEN.getMatrix({job:Job});
// my $customer_code = $IKM->select_value(-sql =>"select c.name from job as j left join public_customer as c on j.customer_id = c.id where j.id = $JOB_ID");
Object.keys(matrix).forEach(function(layer){
var tmp_reg = new RegExp(par.film_name)
if( tmp_reg.test(layer) ){
films.push(layer);
tmp_matrix[layer] = matrix[layer];
} }
var jtg_inner_layer_avoid_copper = IKM.get_jobinfo({jobid:JobId, jobinfo:"jtg_inner_layer_avoid_copper"}) * 2000 - 200 })
for(var key in default_par){ // 设置默认属性
if (!par.hasOwnProperty(key) || par[key] == ""){ if( films.length ){
par[key] = default_par[key] if( GUI.confirm("料号"+Job+"在Genesis中已经存在,且已存在原稿拼片层,是否直接输出?",["yes", "no"], "question") == 'yes' ){
if( films.length > 1){
films = GUI.selectLayer({title:'请选择输出的原稿拼片层',
layermatrix:tmp_matrix,
layertype: "films", // default type of layertypelist
layertypelist: [
{name: "films", display_name: "films", filter: function(x) {
return films.indexOf(x["name"]) >= 0 ; }},
],
selectmode : 'multiple'}); // single
if(films.length == 0){throw "canel"}
} }
gotoFlag = true;
} }
if(_.isEmpty(Job)){throw "参数Job不存在"} }else{
var job = Job.toLowerCase() IKM.msg("料号"+Job+"在Genesis中已经存在, 请检查!");
if(!GEN.isJobExists({job:job})){throw "料号"+job+"不存在"} return 'Cancel';
if(!GEN.isJobOpen({job:job})){ GEN.openJob({job:job}) } }
if(mode == "aimdfm"){ }else{
if(GEN.checkInout({job:job,mode:"test"}) != 0){ throw "the job check" } GEN.copyJob({source_job:job,dest_job:Job,dest_database:GEN.getJobDbName({job:Job})});
GEN.checkInout({job:job,mode:"out"});
} }
var steplist = GEN.getStepList({job:job}) if(!gotoFlag){
steplist = steplist.filter(function(v){
var tmpreg = new RegExp(par.step,"ig") var stepList = GEN.getStepList({job:job})
return tmpreg.test(v) stepList = stepList.filter(function(step){
}) var reg = new RegExp(par.step,"ig")
if (steplist.length == 0 && par.step2) { return reg.test(step)
steplist = GEN.getStepList({job:job}).filter(function (v) {
var tmpreg = new RegExp(par.step2, "ig");
return tmpreg.test(v);
}) })
Step = stepList[0]
if ( !GEN.isStepExists({job:Job,step:Step}) ){
IKM.msg(Step + "不存在,无法拼原稿!");
throw 'Cancel';
} }
var rout = "ol-tz";
if(!GEN.isLayerExists({job:job, layer:rout})){ // 获取sold_mask_layer
rout = par.outline sold_mask_layer = getLayer({layer_type:"solder_mask", context: "board"})
var matrix = GEN.getMatrix({job:Job});
var _default=[],films=[],tmp_matrix={};
for (var layer in matrix) {
if ( GEN.isLayerEmpty( {job:Job,step:Step,layer:layer}) ){
delete matrix[layer];
continue;
} }
var tmp = rout + '_tmp' var tmp_reg = new RegExp(par.film_name)
if(!GEN.isLayerExists({job:job, layer:tmp})){ if( tmp_reg.test(layer) ){
GEN.deleteLayer({job:job, layer:[tmp]}) films.push(layer);
tmp_matrix[layer] = matrix[layer];
delete matrix[layer];
continue;
} }
var matrix = GEN.getMatrix({job:job}) if( matrix[layer].context == 'board' && matrix[layer].layer_type != 'drill' ){
var work_layers = Object.keys(matrix).filter(function(v) { _default.push(layer)
var layer_info = matrix[v]; }
return layer_info.context == "board" && layer_info.layer_type=="signal" && layer_info.side == "inner" else{
if(layer == "map" || /^m[12]\-/.test(layer)){
_default.push(layer);
}
}
}
//
if( films.length ){
if( GUI.confirm("已存在原稿拼片层,是否直接输出?" ["yes", "no"], "question") == 'yes' ){
if( films.length > 1){
films = GUI.selectLayer({title:'请选择输出的原稿拼片层',
layermatrix:tmp_matrix,
layertype: "films", // default type of layertypelist
layertypelist: [
{name: "films", display_name: "films", filter: function(x) {
return films.indexOf(x["name"]) >= 0 ; }},
],
selectmode : 'multiple'}); // single
if(films.length == 0){throw "canel"}
}
gotoFlag = true;
}
}
}
if(!gotoFlag){
var tmplayers = GUI.selectLayer({
title:'请选择需拼片原稿层',
layermatrix:matrix,
layertype:"_default",
layertypelist: [
{
name: "_default",
display_name: "_default",
filter: function (x) {
return _default.indexOf(x.name) >=0
}
},
{
name: "all",
display_name: "all",
filter: function (x) {
return true
}
}
],
selectmode:'multiple'});
if(tmplayers.length == 0){throw "cancel"}
tmplayers = tmplayers.map(function(v){return v.name})
// 创建拼片的辅助层
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:'inch'} );
GEN.zoomHome();
if(!GEN.isLayerExists({job:Job,layer:par.out_line})){
IKM.msg(par.out_line + "层不存在!!");
throw 'Cancel';
}
if(GEN.isLayerEmpty({job:Job,step:Step,layer:par.out_line})){
IKM.msg(par.out_line + "层为空无法创建profice!!");
throw 'Cancel';
}
// 删除板外物 除map层外 2020-07-14 Super
GEN.affectedLayer({affected:'yes',layer:par.out_line,clear_before:'yes'});
GEN.COM('sel_reverse');
if ( GEN.getSelectCount() > 1 ){
GEN.COM('sel_create_profile');
GEN.affectedLayer( {mode:'all',affected:'no'} );
}else{
GEN.COM('sel_reverse');
GEN.affectedLayer( {mode:'all',affected:'no'} );
IKM.msg(par.out_line + "层外形数量太少无法创建profice!!");
throw 'Cancel';
}
tmplayers.forEach(function(layer){
if(!/^map$/.test(layer)){
GEN.affectedLayer({affected:'yes',layer:layer,clear_before:'no'});
}
})
GEN.clipArea({layers_mode:'affected_layers',area:'profile',inout:'outside',margin:0,contour_cut:'yes'});
// 复制外形
GEN.workLayer({name:par.out_line,display_number:1,clear_before:'yes'});
tmplayers.forEach(function(layer){
if(!/^map$/.test(layer)){
GEN.affectedLayer({affected:'yes',layer:layer,clear_before:'no'});
}
})
GEN.selCopyOther({dest:'affected_layers',invert:'no'});
GEN.clearLayers();
GEN.affectedLayer( {mode:'all',affected:'no'} );
// 创建阻焊负片层
var sold_mask_negative = [];
if(sold_mask_layer.length > 0){
sold_mask_layer.forEach(function(layer){
var tmp_layer = layer+'+1';
sold_mask_negative.push(tmp_layer)
var layer_limits = GEN.getLayerLimits({job:Job,step:Step,layer:layer,units:'inch'});
GEN.createLayer({job:Job,layer:tmp_layer,context:'misc',type:'document',delete_exists:'yes'});
GEN.affectedLayer({affected:'yes',layer:tmp_layer,clear_before:'yes'});
GEN.addRectangle({x1:Number(layer_limits.xmin)-0.1,y1:Number(layer_limits.ymin)-0.1,x2:Number(layer_limits.xmax)+0.1,y2:Number(layer_limits.ymax)+0.1});
GEN.affectedLayer({affected:'yes',layer:layer,clear_before:'yes'});
GEN.selCopyOther({target_layer:tmp_layer,invert:'yes'});
GEN.selContourize();
GEN.affectedLayer({mode:'all',affected:'no'});
})
}
// 总的底片数量
film_tol_number = tmplayers.length*2 + sold_mask_layer.length;
// 创建辅助层,返回实际需拼片的层
var tmp_layers = tmplayers;
tmp_layers = tmp_layers.concat(sold_mask_negative)
tmplayers = tmplayers.concat(tmp_layers);
// my @tmp_layers2 = @tmplayers;
create_tmp_layer({step:Step,layer:tmplayers,matrix:matrix});
var film_scheme;
var index = 1;
film_size.forEach(function(filmsize){
var info = get_repeat_info({step:Step,layer:tmplayers,film_size:filmsize});
film_scheme[index].info = info;
film_scheme[index].film_count = Object.keys(info).length;
film_scheme[index].film_size = filmsize;
index++ ;
}) })
steplist.forEach(function(step) { IKM.msg(2)
GEN.openStep({job:job, name:step})
GEN.units({type:par.units}) // 选出最优方案
GEN.clearLayers() var best_scheme_index;
GEN.workLayer({name:rout,display_number:2,clear_before:'yes'}) Object.keys(film_scheme).sort().forEach(function(index){
GEN.selectByFilter({profile:"in"}) if(best_scheme_index){
if(GEN.getSelectCount() > 0) { if(film_scheme[index].film_count < film_scheme[best_scheme_index].film_count){
GEN.selMoveOther({target_layer:tmp,invert:'no',dx:0,dy:0,size:0}) best_scheme_index = index;
GEN.workLayer({name:tmp,display_number:2,clear_before:'yes'});
(function(){
GEN.selRefFeat({layers:rout,use:"filter",mode:"touch"});
if(GEN.getSelectCount() > 0) {
GEN.selMoveOther({target_layer:rout,invert:'no',dx:0,dy:0,size:0})
arguments.callee()
}
})();
// 过滤外形线
if(!GEN.isLayerExists({job:job, layer:tmp + "2"})){
GEN.deleteLayer({job:job, layer:[tmp + "2"]})
}
GEN.COM("profile_to_rout,layer="+tmp + "2"+",width=1")
GEN.selRefFeat({layers:tmp + "2",use:"filter",mode:"touch"});
(function(){
GEN.selRefFeat({layers:rout,use:"filter",mode:"touch"});
if(GEN.getSelectCount() > 0) {
GEN.selMoveOther({target_layer:rout,invert:'no',dx:0,dy:0,size:0})
arguments.callee()
}
})();
GEN.deleteLayer({job:job, layer:[tmp + "2"]})
GEN.selAllFeat()
if(GEN.getSelectCount() > 0) {
// 继续过滤
if(GEN.isLayerExists({job:job, layer:tmp+"_f"})){
GEN.deleteLayer({job:job, layer:[tmp + "_f"]})
}
GEN.selCopyOther({dest:'layer_name',target_layer:tmp + "_f",invert:'no',dx:0,dy:0,size:0})
GEN.workLayer({name:tmp + "_f",display_number:2,clear_before:'yes'})
GEN.COM("sel_cut_data,det_tol=25.4,con_tol=25.4,rad_tol=0,filter_overlaps=no,delete_doubles=no,use_order=yes,ignore_width=yes,ignore_holes=none,start_positive=yes,polarity_of_touching=same")
GEN.selRefFeat({layers:"drl",use:"filter",mode:"touch"})
if(GEN.getSelectCount() > 0) {GEN.selDelete()}
GEN.workLayer({name:tmp,display_number:2,clear_before:'yes'});
GEN.selRefFeat({layers:tmp + "_f",use:"filter",mode:"touch"})
GEN.selReverse()
if(GEN.getSelectCount() > 0) {
GEN.selMoveOther({target_layer:rout,invert:'no',dx:0,dy:0,size:0})
}
GEN.deleteLayer({job:job, layer:[tmp + "_f"]})
// 对单边>=20000um的闭合图形铺铜
// 将长度 >= 20000的线选出来 将跟此线xy坐标相同的线选出来拷贝到辅助层 cuttingdata 拷贝回去
if(GEN.isLayerExists({job:job, layer:tmp+"_2"})){
GEN.deleteLayer({job:job, layer:[tmp + "_2"]})
}
var feats = GEN.getFeatures({job:job,step:step,layer:tmp,units:"mm",options:"feat_index"})
feats.forEach(function(item){
if(item.type == "line") {
var len = Math.sqrt((item.xe-item.xs)*(item.xe-item.xs) + (item.ye-item.ys)*(item.ye-item.ys))
if(len >= 20) {
GEN.selLayerFeat({layer:tmp,index:item.index,operation:"select"})
if(GEN.getSelectCount() > 0) {GEN.selMoveOther({target_layer:tmp+"_2",invert:'no',dx:0,dy:0,size:0})}
}
} else if (item.type == "arc") {
var len = genMath.arcLength(item)
if(len >= 20) {
GEN.selLayerFeat({layer:tmp,index:item.index,operation:"select"})
if(GEN.getSelectCount() > 0) {GEN.selMoveOther({target_layer:tmp+"_2",invert:'no',dx:0,dy:0,size:0})}
} }
}else{
best_scheme_index = index;
} }
}) })
if(GEN.isLayerExists({job:job, layer:tmp+"_2"})){
(function(){ IKM.msg(3)
GEN.workLayer({name:tmp,display_number:2,clear_before:'yes'}); film_repeat({step:Step,layer:tmplayers,info:film_scheme[best_scheme_index].info,film_size:film_scheme[best_scheme_index].film_size});
GEN.selRefFeat({layers:tmp+"_2",use:"filter",mode:"touch"})
if(GEN.getSelectCount() > 0) { //画profile
GEN.selMoveOther({target_layer:tmp+"_2",invert:'no',dx:0,dy:0,size:0}) var tmp_fs = film_scheme[best_scheme_index].film_size.split("x")
arguments.callee() var film_width=tmp_fs[0],film_height = tmp_fs[1];
} GEN.COM( 'profile_rect',{x1:0,y1:0,x2:film_width-0.005,y2:film_height-0.005});
})() //更改文字序列号
GEN.workLayer({name:tmp+"_2",display_number:2,clear_before:'yes'}); var change_layers = Object.keys(film_scheme[best_scheme_index].info).sort(function(a,b){
GEN.selCopyOther({dest:'layer_name',target_layer:rout,invert:'no'}) return film_scheme[best_scheme_index].info[a].num - film_scheme[best_scheme_index].info[b].num
GEN.COM("sel_cut_data,det_tol=25.4,con_tol=25.4,rad_tol=0,filter_overlaps=no,delete_doubles=no,use_order=yes,ignore_width=yes,ignore_holes=none,start_positive=yes,polarity_of_touching=same") })
// 拷贝到负层 var number = 1;
work_layers.forEach(function(l){ change_layers.forEach(function(layer){
GEN.selCopyOther({dest:'layer_name',target_layer:l,invert:'no',dx:0,dy:0,size:-500}) GEN.affectedLayer({affected:'yes',mode:'single',layer:layer,clear_before:'yes'});
// GEN.selectByFilter(feat_types:'text',polarity:'positive',profile:'all');
var tmp_data = GEN.getFeature({job:Job,step:Step,layer:layer,surface:0,options:'feat_index'});
// var tmp_data = GEN.getFeatures(job:Job,step:Step,layer:layer,options:'select');
var txt_data = tmp_data.filter(function(v){return v.type=="text"})
// $GUI->debug(-text:dump(@txt_data,'---',layer,$Step,$Job));
txt_data.forEach(function(data){
GEN.COM('sel_layer_feat',{operation:'select',layer:layer,index:data.index});
var txt = data.text.split("/")
var new_text = number+'/'+txt[1];
GEN.COM( 'sel_change_txt',{
text:new_text,
x_size:data.x_size,
y_size:data.y_size,
w_factor:data.w_factor,
polarity:'no_change',
mirror:'no',
fontname:data.fontname
});
number++;
})
}) })
GEN.deleteLayer({job:job, layer:[tmp + "_2"]})
// 请检查拼片信息
var n = 1;
var lastflag = true
Object.keys(film_scheme[best_scheme_index].info).sort(function(a,b){
return film_scheme[best_scheme_index].info[a].num - film_scheme[best_scheme_index].info[b].num
}).forEach(function(film){
if(lastflag){
if( n == 1 ){
GEN.workLayer({name:film,display_number:1,clear_before:'yes'});
} }
else{
GEN.displayLayer({name:film,number:n});
} }
GEN.workLayer({name:tmp,display_number:2,clear_before:'yes'}) n++;
GEN.selMoveOther({target_layer:rout,invert:'no',dx:0,dy:0,size:0})
GEN.displayLayer({name:rout, number:1})
GEN.deleteLayer({job:job, layer:[tmp]})
// 删除+++
var matrix = GEN.getMatrix({job:job})
Object.keys(matrix).forEach(function(v) {
if(/\+\+\+$/.test(v)){
GEN.deleteLayer({job:job, layer:[v]})
} }
if (n > 4){lastflag = false};
}) })
GEN.PAUSE('Please Check Layer');
} }
//
if(films.length == 0){
films = Object.keys(film_scheme[best_scheme_index].info).sort(function(a,b){
return film_scheme[best_scheme_index].info[a].num - film_scheme[best_scheme_index].info[b].num
}) })
}
//my $film_size = $film_scheme->{$best_scheme_index}{film_size};
// 保存 //删除多余step和层别
if(/yes/ig.test(par.auto_save)){ var steps = GEN.getStepList({job:Job});
GEN.checkInout({job:job,mode:"out"}) // 结束保存料号 关闭料号 steps.forEach(function(step){
GEN.saveJob({ job: job }); if(step != Step){
GEN.checkInout({job:job,mode:"in"}) GEN.matrixDeleteStep({job:Job,step:step});
GEN.closeJob({job:job})
} else {
GEN.checkInout({job:job,mode:"in"})
} }
})
var matrix = GEN.getMatrix({job:Job});
Object.keys(matrix).forEach(function(layer){
var tmp_reg = new RegExp("^"+par.film_name)
if(!tmp_reg.test(layer)){
_deleteLayer({layer:[layer]});
}
})
GEN.checkInout({job:Job,mode:'out'});
// $GUI->debug(-text=>dump($PAR->{path}));
GEN.saveJob({job:Job});
GEN.COM('export_job',{job:Job,path:par.path,mode:'tar_gzip',submode:'full',overwrite:'yes'});
// 保存
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"})}
if (mode === "aimdfm") { if (mode === "aimdfm") {
$.QDfm.updateRow({table: "pdm_aimdfm_task",data: {progress: 33.33},where: { id: $.task_id }}); $.QDfm.updateRow({table: "pdm_aimdfm_task",data: {progress: 33.33},where: { id: $.task_id }});
if (GEN.hasError()) { if (GEN.hasError()) { Status = 'error';resultData.push({ type: "error", title: "GEN错误!", detail: [{ desc: _.join(GEN.STATUS, "\n") }] });
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}; return {status: Status,result_data: resultData};
} } else { resultData.push({ type: "info", title: "操作完成, 请注意检查!" }); return {status: Status,result_data: resultData}; }
}else { }else { return "Done" }
return "Done"
}
} catch (e) { } catch (e) {
IKM.msg(_.join(GEN.STATUS, "\n")) IKM.msg(_.join(GEN.STATUS, "\n"));IKM.msg(e);Status = 'error';
IKM.msg(e)
Status = 'error';
resultData.push({type: "error", title: "脚本执行出错!", detail: [{desc: _.toString(e)}]}); resultData.push({type: "error", title: "脚本执行出错!", detail: [{desc: _.toString(e)}]});
return (mode === "aimdfm") ? {status: Status, result_data: resultData} : "Error"; return (mode === "aimdfm") ? {status: Status, result_data: resultData} : "Error";
} }
function NewGUI (gui) {
this.msgBox = function(props){ // title type content button
props = props || {}
return gui.msgBox(props.title || "title",props.type || "info",props.content || "content",props.button || ["ok", "cancel"]);
}
this.selectFromTreeview = gui.selectFromTreeview
this.selectFile = function(props){ // "choose something", "*", true, "file", "/home/abby/fast_io"
props = props || {}
return gui.selectFile(props.title || "choose something",props.filter || "*",props.multiple || false, "file","");
}
this.selectSingle = function(props) {
props = props || {}
return gui.selectSingle({
"title": props.title || "select",
"list": props.list || [],
"default": props["default"] || "",
"columns": props.columns || 2,
"gen":props.gen || GEN
});
}
this.selectMultiple = function(props) {
props = props || {}
return gui.selectMultiple({
"title": props.title || "select",
"list": props.list || [],
"defaultvalue": props["defaultvalue"] || [""],
"defaultsize": props["defaultsize"] || [200, 100],
"columns": props.columns || 2,
"gen":props.gen || GEN
});
}
this.selectFromTable = gui.selectFromTable
this.snapScreen = gui.snapScreen
this.imageViewer = gui.imageViewer
this.inputBox = gui.inputBox
this.showForm = gui.showForm
this.lockUnlockLayer = function(props){
props = props || {}
var tmp = {}
if (props.matrix) {
for (var key in props.matrix) {
var item = props.matrix[key]
tmp[key] = {
row : item.row,
name : item.name
}
}
}
return gui.lockUnlockLayer({
title: props.title || "lockUnlockLayer",
layermatrix:props.layermatrix || tmp
})
}
this.passwordBox = function(props){
props = props || {}
return gui.passwordBox({title:props.title || "password", password:props.password || "1212"})
}
this.selectJobLayer = function (props) {
props = props || {}
return gui.selectJobLayer({
layertypelist: props.layertypelist || [
{name: "all", display_name: "all", filter: function(x) { return x }},
{name: "signal", display_name: "signal", filter: function(x) { return x["layer_type"] === "signal"; }},
{name: "power_ground", display_name: "power_ground", filter: function(x) { return x["layer_type"] === "power_ground"; }},
{name: "mixed", display_name: "mixed", filter: function(x) { return x["layer_type"] === "mixed"; }},
{name: "solder_mask", display_name: "solder_mask", filter: function(x) { return x["layer_type"] === "solder_mask"; }},
{name: "silk_screen", display_name: "silk_screen", filter: function(x) { return x["layer_type"] === "silk_screen"; }},
{name: "solder_paste", display_name: "solder_paste", filter: function(x) { return x["layer_type"] === "solder_paste"; }},
{name: "drill", display_name: "drill", filter: function(x) { return x["layer_type"] === "drill"; }},
{name: "rout", display_name: "rout", filter: function(x) { return x["layer_type"] === "rout"; }},
{name: "document", display_name: "document", filter: function(x) { return x["layer_type"] === "document"; }}
],
//defaultlayertype: "ha",
joblist: props.joblist || [],
defaultJob: props.defaultJob || [], // select by default
steplist: props.steplist || [],
// defaultstep: "step3",
showstep: props.showstep || true,
selectmode: props.selectmode || "multiple", // single/multiple
layermatrix: props.layermatrix || { },
defaultlayer: props.defaultlayer || []
})
}
}
function getLayer(props){
if(!props){return}
if(!props.context){props.context = "board"}
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(!Array.isArray(props[key])){props[key] = [props[key]]}
if(info[key] && props[key].indexOf(info[key]) < 0){ ret = false } }
if(ret){ a.push(props.res == "info"? info : b) } return a
},[])
}
function _deleteLayer(layers){
layers = Array.isArray(layers.layer) ? layers.layer : [layers.layer];
layers.forEach(function(layer){
if(GEN.isLayerExists({job:Job,layer:layer})){
GEN.deleteLayer({job:Job,layer:[layer]})
}
})
}
function create_tmp_layer(par){
var matrix = par.matrix;
// 先清除原先存在的辅助层
Object.keys(matrix).forEach(function(layer){
if(/_$|_tl_angle$/ig.test(layer)){
GEN.deleteLayer({job:Job,layer:[layer],step:par.step})
}
})
par.layer.forEach(function(layer){
var tmp_layer = layer+'_';
var tmp_layer_angle = layer+'_tl_angle';
GEN.copyLayer({source_job:Job,source_step:par.step,source_layer:layer,dest_layer:tmp_layer,invert:'no',mode:'replace'});
// 打散层上字串
GEN.affectedLayer({affected:'yes',layer:[tmp_layer],clear_before:'yes'});
GEN.selectByFilter({feat_types:'text',profile:'all'});
if ( GEN.getSelectCount() > 0 ){GEN.COM("sel_break")};
if(matrix[layer] && matrix[layer].tl_type == 'inner' && matrix[layer].polarity != 'negative' ){
var layer_limits = GEN.getLayerLimits({job:Job,step:par.step,layer:layer,units:'inch'});
var tmp = 'pos_to_neg_tl';
GEN.createLayer({job:Job,layer:tmp,context:'board',type:'document',delete_exists:'yes'});
GEN.affectedLayer({affected:'yes',layer:[tmp],clear_before:'yes'});
GEN.addRectangle({x1:Number(layer_limits.xmin)-0.1,y1:Number(layer_limits.ymin)-0.1,x2:Number(layer_limits.xmax)+0.1,y2:Number(layer_limits.ymax)+0.1});
GEN.affectedLayer({affected:'yes',layer:[tmp_layer],clear_before:'yes'});
GEN.selCopyOther({target_layer:tmp,invert:'yes'});
GEN.copyLayer({source_job:Job,source_step:par.step,source_layer:tmp,dest_layer:tmp_layer,invert:'no',mode:'replace'});
GEN.deleteLayer({job:Job,layer:[tmp],step:par.step});
}
// $GUI->debug(dump(matrix[layer].tl_type));
GEN.copyLayer({source_job:Job,source_step:par.step,source_layer:tmp_layer,dest_layer:tmp_layer_angle,invert:'no',mode:'replace'});
//
GEN.affectedLayer({affected:'yes',layer:[tmp_layer],clear_before:'yes'});
var layer_limits = GEN.getLayerLimits({job:Job,step:par.step,layer:tmp_layer,units:'inch'});
GEN.selMove({dx:0-layer_limits.xmin+0.1,dy:0-layer_limits.ymin+0.1});
// 制作旋转辅助层
GEN.affectedLayer({affected:'yes',layer:[tmp_layer_angle],clear_before:'yes'});
GEN.selTransform({mode:'anchor',oper:'rotate',x_anchor:0,y_anchor:0,angle:90});
layer_limits = GEN.getLayerLimits({job:Job,step:par.step,layer:tmp_layer_angle,units:'inch'});
GEN.selMove({dx:0-layer_limits.xmin+0.1,dy:0-layer_limits.ymin+0.1});
// 添加文字标识
[tmp_layer,tmp_layer_angle].forEach(function(txt_data){
GEN.affectedLayer({affected:'yes',layer:txt_data,clear_before:'yes'});
var txt = '1/'+film_tol_number+' '+Job.toUpperCase()+' '+layer.toUpperCase();
var lay_limt = GEN.getLayerLimits({job:Job,step:par.step,layer:txt_data,units:'inch'});
Add_Text({x:lay_limt.xmin-0,y:lay_limt.ymin - 0.18,txt:txt,angle:0});
// GEN.createLayer(job:Job,layer:$txt_data.'+bak',context:'misc',type:'document',delete_exists:'yes');
// GEN.selCopyOther(target_layer:$txt_data.'+bak',invert:'no');
})
})
}
function get_repeat_info(par){
// 判断不旋转
var info1 = {};
var film_size = par.film_size;
var tmp_film_size = film_size.split("x")
var film_width = tmp_film_size[0],film_height = tmp_film_size[1];
var film_org = PAR.film_name+'-'+film_size;
var film_name=film_org,film_num=0,film_status="old";
var first_area,last_area={},xstart={},ystart;//第一张底片的范围/上一张底片的范围
par.layer.forEach(function(layer){
var tmp_layer = layer+'_';
film_status = last_area.xmin ? 'old' : 'new' ;
var layer_limits = GEN.getLayerLimits({job:Job,step:par.step,layer:tmp_layer,units:'inch'});
layer_limits.xsize = layer_limits.xsize - 0;
layer_limits.ysize = layer_limits.ysize - 0;
layer_limits.xmin = layer_limits.xmin - 0;
layer_limits.ymin = layer_limits.ymin - 0;
layer_limits.xmax = layer_limits.xmax - 0;
layer_limits.ymax = layer_limits.ymax - 0;
var tol_x = (layer_limits.xsize > layer_limits.ysize) ? 0.3 : 0.3;
var tol_y = (layer_limits.xsize > layer_limits.ysize) ? 0.3 : 0.3;
// 判断拼入后是否会超出范围
if( layer_limits.xsize > film_width && layer_limits.ysize > film_height ){
// xy都超出范围,一片一拼
film_status = 'new';
}
else if( layer_limits.xsize > film_width ){
film_status = 'new' ;//if ( ($last_area->{ymax}+ layer_limits.ysize) > $film_height );
}
else if( layer_limits.ysize > film_height ){
film_status = 'new' ;//if ( ($last_area->{xmax}+ layer_limits.xsize) > film_width );
}
else{
if ( (last_area.ymax+ layer_limits.ysize) > film_height && (last_area.xmax+ layer_limits.xsize) > film_width ){
film_status = 'new'
};
}
// 新底片的准备工作
if( film_status == 'new' ){
film_name = film_org+'-'+film_num;
if(!info1[film_name]){info1[film_name] = {}}
if(!info1[film_name].layers){info1[film_name].layers = []}
if(!info1[film_name][layer]){info1[film_name][layer] ={shift:{}}}
info1[film_name].layers.push(layer)
info1[film_name].num = film_num;
info1[film_name].type = 'no_angle';
info1[film_name][layer].shift.x = 0;
info1[film_name][layer].shift.y = 0;
xstart.status = 1;
xstart.shifty = info1[film_name][layer].shift.y;
first_area = {
xmin: layer_limits.xmin,
ymin: layer_limits.ymin,
xmax: layer_limits.xmax + tol_x,
ymax: layer_limits.ymax + tol_y,
xsize: layer_limits.xsize + tol_x,
ysize: layer_limits.ysize + tol_y
};
last_area = first_area;
film_num++;
}else{
// Y方向添加
if ( (last_area.xsize+ layer_limits.xsize+tol_x) > film_width ){
//print dump($last_area->{xsize},'--',layer_limits.xsize,'--',film_width),"\n";
//print dump(@{$info{$film_name}{layers}}),"\n";
//GEN.PAUSE('tttt++'.$layer);
if(!info1[film_name]){info1[film_name] = {}}
if(!info1[film_name].layers){info1[film_name].layers = []}
if(!info1[film_name][layer]){info1[film_name][layer] ={shift:{}}}
info1[film_name].layers.push(layer);
info1[film_name][layer].shift.x = 0;
info1[film_name][layer].shift.y = last_area.ymax-layer_limits.ymin;
xstart.status = 1;
xstart.shifty = info1[film_name][layer].shift.y;
//$ystart->{status} = 0;$xstart->{shiftx} = undef;
last_area = {
xmin: layer_limits.xmin,
ymin: layer_limits.ymin + info1[film_name][layer].shift.y,
xmax: layer_limits.xmax + tol_x,
ymax: info1[film_name][layer].shift.y + layer_limits.ymax + tol_y,
xsize: layer_limits.xsize + tol_x,
ysize: layer_limits.ysize + last_area.ysize + tol_y
};
}
// X方向添加
else{
if(!info1[film_name]){info1[film_name] = {}}
if(!info1[film_name].layers){info1[film_name].layers = []}
if(!info1[film_name][layer]){info1[film_name][layer] ={shift:{}}}
info1[film_name].layers.push(layer);
info1[film_name][layer].shift.x = last_area.xmax-layer_limits.xmin;
info1[film_name][layer].shift.y = xstart.status ? xstart.shifty : last_area.ymax-last_area.xmin;
//print dump($info{$film_name}{$layer}{shift}{x},'-----',$info{$film_name}{$layer}{shift}{y}),"\n";
//GEN.PAUSE('ttt++'.$layer);
xstart.status = 1;
xstart.shifty = info1[film_name][layer].shift.y;
var high = (layer_limits.ymax+info1[film_name][layer].shift.y-0+tol_y) > last_area.ymax ? layer_limits.ymax+info1[film_name][layer].shift.y-0+tol_y : last_area.ymax;
//$ystart->{status} = 1;$ystart->{shiftx} = undef;
last_area = {
xmin: layer_limits.xmin + info1[film_name][layer].shift.x,
ymin: layer_limits.ymin + info1[film_name][layer].shift.y,
xmax: layer_limits.xmax + info1[film_name][layer].shift.x + tol_x,
ymax: high,
xsize: layer_limits.xsize + last_area.xsize + tol_x,
ysize: layer_limits.ysize + tol_y
};
}
}
})
// 判断旋转90度
var info2 = {};
film_org = PAR.film_name+'-'+film_size;
film_name = film_org,film_num=0,film_status="old";
first_area={},last_area={},xstart={},ystart={};//第一张底片的范围/上一张底片的范围
par.layer.forEach(function(layer){
var tmp_layer = layer+'_tl_angle';
film_status = last_area.xmin ? 'old' : 'new' ;
var layer_limits = GEN.getLayerLimits({job:Job,step:par.step,layer:tmp_layer,units:'inch'});
layer_limits.xsize = layer_limits.xsize - 0;
layer_limits.ysize = layer_limits.ysize - 0;
layer_limits.xmin = layer_limits.xmin - 0;
layer_limits.ymin = layer_limits.ymin - 0;
layer_limits.xmax = layer_limits.xmax - 0;
layer_limits.ymax = layer_limits.ymax - 0;
var tol_x = (layer_limits.xsize > layer_limits.ysize) ? 0.3 : 0.3;
var tol_y = (layer_limits.xsize > layer_limits.ysize) ? 0.3 : 0.3;
//判断拼入后是否会超出范围
if( layer_limits.xsize > film_width && layer_limits.ysize > film_height ){
//xy都超出范围,一片一拼
film_status = 'new';
}
else if( layer_limits.xsize > film_width ){
film_status = 'new' ;//if ( ($last_area->{ymax}+ layer_limits.ysize) > $film_height );
}
else if( layer_limits.ysize > $film_height ){
film_status = 'new' ;//if ( ($last_area->{xmax}+ layer_limits.xsize) > film_width );
}
else{
if ( (last_area.ymax+ layer_limits.ysize) > film_height && (last_area.xmax+ layer_limits.xsize) > film_width ){
film_status = 'new'
};
}
//新底片的准备工作
if( film_status == 'new' ){
film_name = film_org+'-'+film_num;
if(!info2[film_name]){info2[film_name] = {}}
if(!info2[film_name].layers){info2[film_name].layers = []}
if(!info2[film_name][layer]){info2[film_name][layer] ={shift:{}}}
info2[film_name].layers.push(layer)
info2[film_name].num = film_num;
info2[film_name].type = 'angle';
info2[film_name][layer].shift.x = 0;
info2[film_name][layer].shift.y = 0;
xstart.status = 1;
xstart.shifty = info2[film_name][layer].shift.y;
first_area = {
xmin: layer_limits.xmin,
ymin: layer_limits.ymin,
xmax: layer_limits.xmax + tol_x,
ymax: layer_limits.ymax + tol_y,
xsize: layer_limits.xsize + tol_x,
ysize: layer_limits.ysize + tol_y
};
last_area = first_area;
film_num++;
}else{
//Y方向添加
if ( (last_area.xsize+ layer_limits.xsize+tol_x) > film_width ){
//print dump($last_area->{xsize},'--',layer_limits.xsize,'--',film_width),"\n";
//print dump(@{$info{$film_name}{layers}}),"\n";
//GEN.PAUSE('tttt++'.$layer);
if(!info2[film_name]){info2[film_name] = {}}
if(!info2[film_name].layers){info2[film_name].layers = []}
if(!info2[film_name][layer]){info2[film_name][layer] ={shift:{}}}
info2[film_name].layers.push(layer);
info2[film_name][layer].shift.x = 0;
info2[film_name][layer].shift.y = last_area.ymax-layer_limits.ymin;
xstart.status = 1;
xstart.shifty = info2[film_name][layer].shift.y;
//$ystart->{status} = 0;$xstart->{shiftx} = undef;
last_area = {
xmin: layer_limits.xmin,
ymin: layer_limits.ymin + info2[film_name][layer].shift.y,
xmax: layer_limits.xmax + tol_x,
ymax: info2[film_name][layer].shift.y + layer_limits.ymax + tol_y,
xsize: layer_limits.xsize + tol_x,
ysize: layer_limits.ysize + last_area.ysize + tol_y
};
}
//#X方向添加
else{
if(!info2[film_name]){info2[film_name] = {}}
if(!info2[film_name].layers){info2[film_name].layers = []}
if(!info2[film_name][layer]){info2[film_name][layer] ={shift:{}}}
info2[film_name].layers.push(layer);
info2[film_name][layer].shift.x = last_area.xmax-layer_limits.xmin;
info2[film_name][layer].shift.y = xstart.status ? xstart.shifty : last_area.ymax-last_area.xmin;
//print dump($info{$film_name}{$layer}{shift}{x},'-----',$info{$film_name}{$layer}{shift}{y}),"\n";
//GEN.PAUSE('ttt++'.$layer);
xstart.status = 1;
xstart.shifty = info2[film_name][layer].shift.y;
var high = (layer_limits.ymax+info2[film_name][layer].shift.y-0+tol_y) > last_area.ymax ? layer_limits.ymax+info2[film_name][layer].shift.y-0+tol_y : last_area.ymax;
//$ystart->{status} = 1;$ystart->{shiftx} = undef;
last_area = {
xmin: layer_limits.xmin + info2[film_name][layer].shift.x,
ymin: layer_limits.ymin + info2[film_name][layer].shift.y,
xmax: layer_limits.xmax + info2[film_name][layer].shift.x + tol_x,
ymax: high,
xsize: layer_limits.xsize + last_area.xsize + tol_x,
ysize: layer_limits.ysize + tol_y
};
}
}
})
//
if( Object.keys(info2).length < Object.keys(info1).length){
return info2;
}
else{
return info1;
}
}
function film_repeat(par){
var film_size = par.film_size;
var tmp_film_size = film_size.split("x")
var film_width = tmp_film_size[0];
var film_height = tmp_film_size[1];
var info = par.info;
Object.keys(info).sort(function(a,b){return info[a].num - info[b].num}).forEach(function(film){
if(info[film].layers){
GEN.createLayer({job:Job,layer:film,conext:'misc',type:'document',delete_exists:'yes'});
GEN.affectedLayer({affected:'yes',layer:[film],clear_before:'yes'});
// my $all = scalar(@{$info{$film}{layers}});
// $GUI->debug(dump($film, $info{$film}{layers}));
var n = 1;
info[film].layers.forEach(function(layer){
var tmp_layer = info[film].type == 'no_angle' ? layer+'_' : layer+'_tl_angle';
GEN.affectedLayer({affected:'yes',layer:[tmp_layer],clear_before:'yes'});
GEN.selMove({dx:info[film][layer].shift.x,dy:info[film][layer].shift.y});
GEN.copyLayer({source_job:Job,source_step:par.step,source_layer:tmp_layer,dest_layer:film,invert:'no',mode:'append'});
GEN.selMove({dx:-info[film][layer].shift.x,dy:-info[film][layer].shift.y});
// GEN.deleteLayer(job:Job,layer:[$layer.'_',$layer.'_tl_angle'],step:par.step);
n++;
})
GEN.affectedLayer({affected:'yes',layer:[film],clear_before:'yes'});
// 移动居中
var layer_limits = GEN.getLayerLimits({job:Job,step:Step,layer:film,units:'inch'});
layer_limits.xc = layer_limits.xsize/2-Math.abs(layer_limits.xmin);
layer_limits.yc = layer_limits.ysize/2-Math.abs(layer_limits.ymin);
GEN.selMove({dx:film_width/2-layer_limits.xc,dy:film_height/2-layer_limits.yc});
//
GEN.addRectangle({x1:0,y1:0,x2:film_width-0.005,y2:film_height-0.005,type:'line',symbol:'r5'});
}
})
}
// =head
// 增加文字 Add_Text(x=>,y=>,txt=>,angle=>)
// =cut
function Add_Text(par){
GEN.COM('add_text',{
attributes:'no',
type:'string',
x:par.x,
y:par.y,
text:par.txt,
x_size:0.15,
y_size:0.15,
w_factor:1.6666666269,
polarity:'positive',
angle:par.angle,
mirror:'no',
fontname:'simple',
ver:1
})
}
\ No newline at end of file
/* /*
NAME: NAME:
DESCRIPTION: ; DESCRIPTION: ;
PARAMETER: PARAMETER:
[ [
{ {
name : 'step_fliter', name : 'step',
title : 'Step过滤', title : 'step',
type : 'LineEdit',
property : {tool_tip : 'unit'},
},
{
name : 'erf',
title : 'erf name',
type : 'LineEdit', type : 'LineEdit',
property : {tool_tip : 'erf'}, property : {tool_tip : '目标step,默认是orig'},
},
{
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', name : 'auto_save',
...@@ -58,16 +24,16 @@ PARAMETER: ...@@ -58,16 +24,16 @@ PARAMETER:
] ]
VERSION_HISTORY: VERSION_HISTORY:
V1.00 2020-04-28 Scott Sun V1.00 2020-09-01 Scott Sun
1.新版本 1.新版本
HELP: HELP:
<html><body bgcolor="#DDECFE"> <html><body bgcolor="#DDECFE">
<font size="3" color="#003DB2"><p>功能简介</p></font> <font size="3" color="#003DB2"><p>功能简介</p></font>
<p> 补铜桥 </p> <p> 标题 </p>
<br> <br>
<font size="3" color="#003DB2"><p>参数配置</p></font> <font size="3" color="#003DB2"><p>参数配置</p></font>
<p> 配置 </p> <p> step信息 </p>
<br> <br>
<font size="3" color="#003DB2"><p>注意事项</p></font> <font size="3" color="#003DB2"><p>注意事项</p></font>
<p> 无 </p> <p> 无 </p>
...@@ -76,8 +42,7 @@ PARAMETER: ...@@ -76,8 +42,7 @@ PARAMETER:
*/ */
////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////
console.log("==============================>JTG_PUB_pos_add_copper_bridge_aim"); console.log("==============================>template");
// 引入模块 包 // 引入模块 包
var $ = require('topcam.scriptfunc').argv(); var $ = require('topcam.scriptfunc').argv();
var fs = require('fs'); var fs = require('fs');
...@@ -89,411 +54,165 @@ var GEN = $.gen; ...@@ -89,411 +54,165 @@ var GEN = $.gen;
var GUI = $.gui || {}; var GUI = $.gui || {};
var Job = $.job || $.job_name; var Job = $.job || $.job_name;
var JobId = $.job_id; var JobId = $.job_id;
var db = $.db || IKM.db; var db = $.db || IKM.db
var GenMath = require("topsin.genmath")
var PAR = {} var PAR = {}
if ($.par) { if ($.par) { PAR = $.par } else if ($.hasOwnProperty('script_parameter')){ PAR = JSON.parse($.script_parameter); }
PAR = $.par
} else if ($.hasOwnProperty('script_parameter')){
PAR = JSON.parse($.script_parameter);
}
if (mode === "aimdfm") { if (mode === "aimdfm") {
var database = require("topsin.database"); var database = require("topsin.database");
database.addConnection($.conf.database_conf, "DFM"); database.addConnection($.conf.database_conf, "DFM");
var QDfm = database.query("DFM"); var QDfm = database.query("DFM");
$.QDfm = QDfm; $.QDfm = QDfm;
if ($.conf.product_type == "aimdfm") { if ($.conf.product_type == "aimdfm") {
QDfm.updateRow({ QDfm.updateRow({ table: "pdm_aimdfm_task", data: { current_process_title: $.process_title }, where: { id: $.task_id } });
table: "pdm_aimdfm_task",
data: {
current_process_title: $.process_title
},
where: { id: $.task_id }
});
} }
} }
var Status = 'ok'; var Status = 'ok';
var resultData = []; var resultData = [];
var par = PAR;
var default_par = {
step: "unit",
auto_save: "No",
units:"mm"
}
for(var key in default_par){ if (!par.hasOwnProperty(key) || par[key] == ""){ par[key] = default_par[key] }}
var job = Job;
try { try {
var par = PAR; if(_.isEmpty(job)){throw "参数job不存在"} else { job = job.toLowerCase() }
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.isJobExists({job:job})){throw "料号"+job+"不存在"}
if(!GEN.isJobOpen({job:job})){ GEN.openJob({job:job}) } if(!GEN.isJobOpen({job:job})){ GEN.openJob({job:job}) }
if(mode == "aimdfm"){ if(mode == "aimdfm"){ if(GEN.checkInout({job:job,mode:"test"}) != 0){ throw "the job check" } else { GEN.checkInout({job:job,mode:"out"}) } }
if(GEN.checkInout({job:job,mode:"test"}) != 0){ throw "the job check" }
GEN.checkInout({job:job,mode:"out"});
}
// 脚本开始
var stepList = GEN.getStepList({job:job}) var stepList = GEN.getStepList({job:job})
if(par.step_fliter != ""){ stepList = stepList.filter(function(step){
stepList = stepList.filter(function(v){ var reg = new RegExp(par.step,"ig")
var step_reg = new RegExp(par.step_fliter) return reg.test(step)
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 worklayer = [{},{}];
var matrix = GEN.getMatrix({job:job})
var tmp_e = {
top:0,
bot:1,
bottom:1
} }
var layer_config = { for (var key in matrix) {
outer: {layer_type:"signal", side:"top|bottom", context:"board", polarity:"positive"}, var info = matrix[key];
inner: {layer_type:"signal", side:"inner", context:"board", polarity:"positive"}, if(info.context == "board"){
all: {layer_type:"signal", context:"board", polarity:"positive"}, if(info.layer_type == "solder_mask" && /top|bot/.test(info.side)){
power_ground: {layer_type:"power_ground", side:"inner", context:"board", polarity:"negative"}, worklayer[tmp_e[info.side]].sm = key;
} }
var layer_cfg if(info.layer_type == "signal" && /top|bot/.test(info.side)){
if(par.layer_type != ""){ worklayer[tmp_e[info.side]].sig = key;
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){ stepList.forEach(function(step){
GEN.openStep({job:job, name:step}) GEN.openStep({job:job, name:step})
GEN.units({type:par.units}) GEN.units({type:par.units})
GEN.affectedLayer({affected:'no',mode:'all'})
GEN.clearLayers() GEN.clearLayers()
var profile_limits = GEN.getProfileLimits({job:job,step:step,units:par.units}); worklayer.forEach(function(item){
var ans_chk = create_checklist_and_run_analysis({layers:n_layers,aux:1, job:job, step:step}, par); if(item.sig && item.sm){
GEN.COM("disp_off"); var sig = item.sig;
n_layers.forEach(function(layer){ var sm = item.sm;
var tmp = [] // 选择全包围类型
tmp.push(layer + '_tl+++tmp') GEN.workLayer({name:sm,display_number:2,clear_before:'yes'})
GEN.copyLayer({source_job:job,source_step:step,source_layer:layer,dest_layer:layer+'_tl+++',mode:'replace',invert:'no'}); GEN.COM("filter_atr_set,filter_name=ref_select,condition=yes,attribute=.smd")
var length = par["length"]; GEN.COM("sel_ref_feat,layers="+sig+",use=filter,mode=touch,pads_as=shape,f_types=line\;pad\;surface\;arc\;text,polarity=positive,include_syms=,exclude_syms=")
var width = par["width"]; GEN.COM("filter_atr_reset,filter_name=ref_select")
var line_chk = "tl_line_chk",line_ok="tl_line_ok", add_pad="tl_add_pad",touch_lyr="tl_touch_lyr" if(GEN.getSelectCount() > 0) {
var tmp_layers = [line_chk,line_ok,add_pad,touch_lyr] delLayer(sm+"_tmp1");
//GEN.deleteLayer(job:job,layer:[line_chk,line_ok,add_pad,touch_lyr],step:step); GEN.selCopyOther({dest:'layer_name',target_layer:sm+"_tmp1",invert:'no',dx:0,dy:0,size:0})
tmp_layers.forEach(function(v){ GEN.workLayer({name:sm+"_tmp1",display_number:2,clear_before:'yes'})
if(GEN.isLayerExists({job:job, layer:v})){GEN.deleteLayer({job:job, layer:v})} GEN.COM("sel_ref_feat,layers="+sig+",use=filter,mode=multi_cover,pads_as=shape,f_types=line\;pad\;surface\;arc\;text,polarity=positive\;negative,include_syms=,exclude_syms=")
GEN.createLayer({job:job,layer:v,conext:'misc',type:'document'}) if(GEN.getSelectCount() > 0) {
}) delLayer([sm+"_tmp2",sm+"_tmp3"]);
var ms_layer = 'ms_1_'+layer GEN.selMoveOther({target_layer:sm+"_tmp2",invert:'no',dx:0,dy:0,size:0})
var mk_layer='mk_1_'+layer // 制作 负性环
if(GEN.isLayerExists({job:job,layer:ms_layer})){ GEN.workLayer({name:sm+"_tmp2",display_number:2,clear_before:'yes'})
var feature = GEN.getFeatures({job:job,step:step,layer:ms_layer,units:par["units"]}); // break_sr GEN.selCopyOther({dest:'layer_name',target_layer:sm+"_tmp3",invert:'no',dx:0,dy:0,size:0})
GEN.affectedLayer({affected:'yes',mode:'single',layer:line_chk,clear_before:'yes'}); GEN.selResize({size:-50})
if(feature && feature.length){ GEN.selMoveOther({target_layer:sm+"_tmp3",invert:'yes',dx:0,dy:0,size:0})
feature.forEach(function(feat){ delLayer([sm+"_tmp2"]);
if(feat.type == "line"){ GEN.workLayer({name:sm+"_tmp3",display_number:2,clear_before:'yes'})
var line = {xs:feat["xs"]-0,xe:feat["xe"]-0,ys:feat["ys"]-0,ye:feat["ye"]-0}; GEN.selContourize()
var tmpline = getLineParallel(line, length/ 2000) GEN.selMoveOther({target_layer:sm,invert:'yes',dx:0,dy:0,size:0})
var line1 = tmpline.line1 delLayer([sm+"_tmp3"]);
var line2 = tmpline.line2 }
var point1 = get_line_center(line1); GEN.workLayer({name:sm+"_tmp1",display_number:2,clear_before:'yes'})
var point2 = get_line_center(line2); GEN.COM("sel_ref_feat,layers="+sig+",use=filter,mode=touch,pads_as=shape,f_types=line\;arc,polarity=positive,include_syms=,exclude_syms=")
var line_new = {xs:point1["x"],ys:point1["y"],xe:point2["x"],ye:point2["y"]}; GEN.selReverse()
GEN.addLine({xs:line_new["xs"],ys:line_new["ys"],xe:line_new["xe"],ye:line_new["ye"],symbol:'r'+width}); if(GEN.getSelectCount() > 0) {GEN.selDelete()}
} // 制作反层
}) delLayer([sm+"_tmp4"]);
} GEN.createLayer({job:job,layer:sm+"_tmp4",type:'document'})
} GEN.workLayer({name:sm+"_tmp4",display_number:2,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,\
// var feature = GEN.getFeatures({job:job,step:step,layer:ms_layer,units:par["units"]}); //// break_sr nest_sr=yes,stop_at_steps=,consider_feat=no,consider_drill=no,consider_rout=no,\
// GEN.affectedLayer({affected:'yes',mode:'single',layer:line_chk,clear_before:'yes'}); dest=affected_layers,attributes=no");
// if(feature && feature.length){ GEN.workLayer({name:sm+"_tmp1",display_number:2,clear_before:'yes'})
// 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() GEN.selAllFeat()
if (GEN.getSelectCount()>0){ if(GEN.getSelectCount() > 0) {
GEN.selCopyOther({dest:'layer_name',target_layer:touch_lyr,invert:'yes',dx:0,dy:0,size:width+0.5}) delLayer([sm+"_tmp5"]);
}; GEN.selCopyOther({dest:'layer_name',target_layer:sm+"_tmp4",invert:'yes',dx:0,dy:0,size:0})
GEN.affectedLayer({affected:'yes',mode:'single',layer:touch_lyr,clear_before:'yes'}); GEN.workLayer({name:sig,display_number:2,clear_before:'yes'})
GEN.selContourize(); GEN.COM("filter_set,filter_name=popup,update_popup=no,feat_types=line\;arc")
GEN.COM("sel_ref_feat,layers="+sm+"_tmp1"+",use=filter,mode=touch,pads_as=shape,f_types=line\;pad\;surface\;arc\;text,polarity=positive\;negative,include_syms=,exclude_syms=")
GEN.affectedLayer({affected:'yes',mode:'single',layer:line_chk,clear_before:'yes'}); GEN.COM("filter_reset,filter_name=popup")
GEN.selRefFeat({layers:touch_lyr,use:'filter',mode:'touch'}); if(GEN.getSelectCount() > 0) {
if ( GEN.getSelectCount() > 0 ){GEN.selDelete()}; GEN.selCopyOther({dest:'layer_name',target_layer:sm+"_tmp5",invert:'no',dx:0,dy:0,size:0})
GEN.affectedLayer({affected:'yes',mode:'single',layer:add_pad,clear_before:'yes'}); }
GEN.selRefFeat({layers:layer,use:'filter',mode:'cover'}); GEN.COM("filter_reset,filter_name=popup")
GEN.selReverse(); GEN.COM("filter_set,filter_name=popup,update_popup=no,feat_types=pad")
if ( GEN.getSelectCount() > 0 ){GEN.selDelete()}; GEN.COM("sel_ref_feat,layers="+sm+"_tmp1"+",use=filter,mode=touch,pads_as=shape,f_types=line\;pad\;surface\;arc\;text,polarity=positive\;negative,include_syms=,exclude_syms=")
//// if(GEN.getSelectCount() > 0) {
GEN.affectedLayer({affected:'yes',mode:'single',layer:[line_chk,add_pad],clear_before:'yes'}); GEN.selCopyOther({dest:'layer_name',target_layer:sm+"_tmp5",invert:'yes',dx:0,dy:0,size:30})
GEN.selAllFeat() }
GEN.selChangeSym({symbol:'r0.1'}); GEN.workLayer({name:sm+"_tmp4",display_number:2,clear_before:'yes'})
GEN.workLayer({name:line_chk,display_number:1,clear_before:'yes'}); GEN.selContourize()
GEN.selRefFeat({layers:add_pad,use:'filter',mode:'touch'}); GEN.selCopyOther({dest:'layer_name',target_layer:sm+"_tmp5",invert:'yes',dx:0,dy:0,size:0})
GEN.selAddAttr({attribute:[{attribute:'.string',text:'bridge'}]}); GEN.workLayer({name:sm+"_tmp5",display_number:2,clear_before:'yes'})
GEN.selAllFeat() GEN.PAUSE(0)
GEN.selChangeSym({symbol:'r'+width}); GEN.selContourize()
GEN.selectByFilter({attribute:[{attribute:'.string',text:'bridge'}]}); GEN.selResize({size: 100})
if( GEN.getSelectCount()>0){GEN.selMoveOther({target_layer:line_ok,invert:'no',dx:0,dy:0,size:0}) }; GEN.workLayer({name:sig,display_number:2,clear_before:'yes'})
GEN.selAddAttr({attribute:[{attribute:'.string',text:'bridge'}]}); GEN.COM("filter_reset,filter_name=popup")
GEN.COM("filter_set,filter_name=popup,update_popup=no,feat_types=pad")
GEN.affectedLayer({affected:'yes',mode:'single',layer:[line_ok,line_chk],clear_before:'yes'}); GEN.COM("sel_ref_feat,layers="+sm+"_tmp1"+",use=filter,mode=touch,pads_as=shape,f_types=line\;pad\;surface\;arc\;text,polarity=positive\;negative,include_syms=,exclude_syms=")
GEN.selRefFeat({layers:layer,use:'filter',mode:'touch',f_types:'line\;arc'}); if(GEN.getSelectCount() > 0) {
if( GEN.getSelectCount()>0){GEN.selDelete() }; GEN.selCopyOther({dest:'layer_name',target_layer:sm+"_tmp5",invert:'yes',dx:0,dy:0,size:30})
GEN.affectedLayer({ mode:'all',affected:'no' }); }
GEN.workLayer({name:sm+"_tmp5",display_number:2,clear_before:'yes'})
GEN.displayLayer({name:layer,number:2}); GEN.selContourize()
GEN.displayLayer({name:line_ok,number:3}); GEN.PAUSE(1)
GEN.selCopyOther({dest:'layer_name',target_layer:sm,invert:'yes',dx:0,dy:0,size:0})
GEN.COM("disp_on"); delLayer([sm+"_tmp5",sm+"_tmp1"]);
GEN.COM("disp_off"); }
delLayer([sm+"_tmp4"]);
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)){ 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"})}
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") { if (mode === "aimdfm") {
$.QDfm.updateRow({ $.QDfm.updateRow({table: "pdm_aimdfm_task",data: {progress: 33.33},where: { id: $.task_id }});
table: "pdm_aimdfm_task", if (GEN.hasError()) { Status = 'error';resultData.push({ type: "error", title: "GEN错误!", detail: [{ desc: _.join(GEN.STATUS, "\n") }] });
data: { return {status: Status,result_data: resultData};
progress: 33.33 } else { resultData.push({ type: "info", title: "操作完成, 请注意检查!" }); return {status: Status,result_data: resultData}; }
}, }else { return "Done" }
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) { } catch (e) {
IKM.msg(_.join(GEN.STATUS, "\n")) IKM.msg(_.join(GEN.STATUS, "\n"));IKM.msg(e);Status = 'error';
IKM.msg(e)
Status = 'error';
resultData.push({type: "error", title: "脚本执行出错!", detail: [{desc: _.toString(e)}]}); resultData.push({type: "error", title: "脚本执行出错!", detail: [{desc: _.toString(e)}]});
return (mode === "aimdfm") ? {status: Status, result_data: resultData} : "Error"; 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; function delLayer(layers){
// meas.forEach(function(item){ // 结果存在 [""] 的情况,会继续导致下面的命令报错 if(!Array.isArray(layers)){ layers = [layers] };
// if(item.trim() == ''){ layers.forEach(function(v){
// cflag = false; if(GEN.isLayerExists({job:Job, layer:v})){GEN.deleteLayer({job:Job, layer:[v]})}
// } })
// })
// 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}
} }
\ No newline at end of file
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,
}
}
}
};
=head
NAME: // 获取涨缩值
DESCRIPTION: 层别对齐 function get_scale_info(par){
PARAMETER: var rows={},n=0;
[ par.layers.forEach(function(layer){
n ++;
rows[layer].sequence = n;
rows[layer].layer = layer;
if(layer == "md"){
rows[layer].x = 1.0004;
rows[layer].y = 1.0004;
}
else{
rows[layer].x = 1.0000;
rows[layer].y = 1.0000;
}
})
var scale_factor = GUI.show_tableform({
defaultsize:[380,400],title : '请确认涨缩值',rows : rows,
showcheck : 1,gen : $GEN,
columns : [
{ {
name : 'step_filter', column_name:'layer',
type : 'LineEdit', label:'层名称',
title : 'step过滤', width:70,
pack : {row:0,column:1}, type:'label',
property:{tool_tip:'step过滤,未设置则手动选择'},
}, },
{ {
name : 'base_layer', column_name:'x',
type : 'LineEdit', label:'X涨缩值',
title : '初始参考层', width:130,
pack : {row:0,column:1}, type:'number',
property:{tool_tip:'选择参考基准的参考层,未设定则手动选择'},
}, },
{ {
name : 'register_layers', column_name:'y',
title : '需对齐的层别', label:'Y涨缩值',
type : 'ComboBox', width:130,
property : { type:'number',
size_policy:'Expanding,Fixed',
item_list:[
{name:'all',text:'所有层'},
{name:'board',text:'board层'},
{name:'select',text:'选择层'},
],
tool_tip:'如果未设置,默认为选择层'
},
pack : {row:1,column:1},
}, },
{
name : 'save_job',
title : '保存料号',
type : 'RadioBox',
property : {
size_policy:'Expanding,Fixed',
item_list:[
{name:'Yes',text:'Yes'},
{name:'No',text:'No'},
], ],
tool_tip:'脚本结束后自动保存料号,未设定,默认为No' });
}, return scale_factor || "Cancel";
pack : {row:1,column:1}, }
}
]
VERSION_HISTORY:
V1.00 2018-01-15 Cody Yu
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>
<font color="#008000"><p> </p></font>
<font size="3" color="#003DB2"><p>注意事项</p></font>
<p> </p>
<br>
</body></html>
=cut
use strict; // drillmarge 输出
use Encode; function drill_out(par){
use utf8; var nc_set = 'sec-jt';
use Data::Dump 'dump'; var ncsets = GEN.getNcsetsList({job:job,step:step,layer:par.layer});
my ($Job,$Step)=($JOB,undef); if( ncsets.length > 0 ){
my $Return = 'done'; if (ncsets.filter(function(v){return /^($nc_set)$/.test(v)}).length > 0) {
$PAR->{step_filter} = '.*' unless $PAR->{step_filter}; GEN.COM('ncset_delete',{name:nc_set});
$PAR->{units} = 'inch' unless $PAR->{units};
$PAR->{cmp_tol} = 0.003 unless $PAR->{cmp_tol};
$PAR->{register_layers} = 'select' unless $PAR->{register_layers};
$PAR->{save_job} = 'No' unless $PAR->{save_job};
my $Matrix = $GEN->getMatrix(job=>$Job);
my $Replace_symbol = 'moire1x1x1x1x1x1';
# 设定参考层
$PAR->{base_layer} = 'out' unless $PAR->{base_layer};
try {
##
show_loading("判断是否选择料号..",0,position=>'n');
unless( $Job){
$GUI->msgbox(-icon=>'error',-text=>"请先选择料号后再执行脚本!");
return 'Cancel';
}
update_loading("检查${Job}是否存在..",0,position=>'n');
##检查料号是否存在
unless ( $GEN->isJobExists(job=>$Job) ){
$GUI->msgbox(-icon=>'error',-text=>"料号 $Job 不存在,请确认。");
return 'Cancel';
}
update_loading("正在打开料号$Job...",0,position=>'n');
$GEN->openJob(job=>$Job) unless ($GEN->isJobOpen(job=>$Job));
# 获取工作step
update_loading("正在过滤工作step ,请稍候..",0,position=>'n');
my @steps = $GEN->getStepList(job=>$Job);
if ( @steps == 0 ) {
$GUI->msgbox(-icon=>'error',-text=>'在料号中没有Step存在,你将退出!');
return 0;
} }
elsif (@steps != 1){
my @tmp_steps = grep(/$PAR->{step_filter}/,@steps);
if ( @tmp_steps == 0 ) {
$GUI->msgbox(-icon=>'warning',-text=>'根据脚本参数过滤出来的step不存在,请检查资料或者脚本参数配置!');
return 'Cancel';
} }
elsif ( @tmp_steps == 1 ) {
$Step = $tmp_steps[0]; // 钻带涨缩中心点
var x_anchor = (par.scale_x != 1 || par.scale_y != 1) ? PAR.profile_limits.xc : 0;
var y_anchor = (par.scale_x != 1 || par.scale_y != 1) ? PAR.profile_limits.yc : 0;
if(fstat.exist(PAR.out_dir+'/'+par.output_layer)){
//? unlink
};
var org_x,org_y,angle;
if(PAR.profile_limits.ysize == 603 && PAR.profile_limits.xsize == 706){
org_x = PAR.profile_limits.yc; // - 15
org_y = 5;
angle = 270;
datum.x = PAR.profile_limits.xmax - 5;
datum.y = PAR.profile_limits.yc;
datum.angle = 90;
datum.type = 1; // 拼版类型
}else if(PAR.profile_limits.ysize == 603 && PAR.profile_limits.xsize == 606){
datum.x = org_x = PAR.profile_limits.xc;//- 5
datum.y = org_y = 5;
datum.angle = angle = 0;
datum.type = 0; // 拼版类型
}else{
datum.x = org_x = PAR.profile_limits.xc;//- 24
datum.y = org_y = 5;
datum.angle = angle = 0;
datum.type = 0; // 拼版类型
} }
else {
$Step = $GUI->select_step(-title=>'请选择工作Step', // 铝片塞防焊和铝片塞树脂程序,bot面时需要mirror
-steplist=>[@tmp_steps], var xmirror = 'no';
-selectmode=>'single'); var ymirror = 'no';
return 'Cancel' unless ($Step); if (/al[pr](\d\d)(\d\d)/.test(par.layer)) {
var start = RegExp.$1 + 0;
var end = RegExp.$2 + 0;
if (start > end) {
xmirror = 'yes';
} }
} }
else {
$Step = $steps[0]; // 获取@drl_section_data数据
if( /(cdr)/.test(par.layer) && GEN.getLayerCount({job:job}) >= 4){
var feat = GEN.getFeatures({job:job,step:step,layer:'pnl-map',units:'mm'});
var data_tmp = feat.filter(function(v){return /(DRL_SECTION)/.test(v.attributes[0])});//获取监视孔坐标
section_tool = map_info.P.min_drl >= 1100 ? 1100 : map_info.P.min_drl;
drl_section_data = genMath.p_trans(datum,datum.angle,'no',-datum.x,-datum.y,data_tmp);
// if($datum->{angle} == 90){
// my @data_tmp = TL::GenMath->p_trans($datum,$datum->{angle},'no',0,0,@data_tmp);#坐标选择
// foreach my $data (@data_tmp){
// my $coorder_txt;
// $coorder_txt = change_coode(data=>$data,datum=>$datum);
// $drl_section_data->{$coorder_txt} = 1;
// }
// }else{
// foreach my $data (@data_tmp){
// my $coorder_txt;
// $coorder_txt = change_coode(data=>{x=>$data->{x},y=>},datum=>$datum);
// $drl_section_data->{$coorder_txt} = 1;
// }
// }
} }
$GEN->openStep(job=>$Job,name=>$Step); var id = nc_set;
$GEN->clearLayers(); GEN.COM('ncset_units',{units:'mm'});
$GEN->affectedLayer( mode=>'all',affected=>'no' ); if(/(cdr)/.test(par.layer)){
$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.affectedLayer({affected:'yes',layer:par.layer,clear_before:'yes'});
$GEN->units( type=>$PAR->{units} ); GEN.COM("adv_filter_reset");
$GEN->zoomHome(); GEN.COM("reset_filter_criteria,filter_name=,criteria=all");
GEN.selectByFilter({attribute:[{attribute:'tl_string',text:"*LDI_HOLE_Two*"}]});
GEN.selectByFilter({attribute:[{attribute:'tl_string',text:"*XRAY_HOLE*"}]});
GEN.COM("adv_filter_reset");
GEN.COM("reset_filter_criteria,filter_name=,criteria=all");
if( GEN.getSelectCount()>0){
GEN.selChangeSym({symbol:'r1'})
};
GEN.affectedLayer( {mode:'all',affected:'no'} );
}
# 开始层对齐 // GEN.COM('open_sets_manager',test_current=>'no');
#create tmp layer GEN.COM('nc_create',{ncset:id,device:'basic_excellon',lyrs:par.layer,thickness:0});
my ($base_lyr) = ('base_lyr_tl'); GEN.COM('nc_set_advanced_params',{layer:par.layer,ncset:id});
$GEN->createLayer(job=>$Job,layer=>$base_lyr,delete_exists=>'yes'); GEN.COM('nc_set_current',{job:job,step:step,layer:par.layer,ncset:id});
GEN.COM('nc_set_file_params',{single_sr:'no',output_path:PAR.out_dir,output_name:par.output_layer,zeroes:'none',units:'mm',tool_units:'mm',nf1:3,nf2:3,decimal:'no',modal_coords:'no'});
GEN.COM('nc_register',{angle:angle,xoff:0,yoff:0,version:1,xorigin:org_x,yorigin:org_y,xscale:par.scale_x,yscale:par.scale_y,xscale_o:x_anchor,yscale_o:y_anchor,xmirror:xmirror,ymirror:ymirror});
GEN.COM('nc_set_optim',{optimize:'yes',iterations:5,reduction_percent:1,cool_spread:PAR.cool_spread,break_sr:'yes',xspeed:2540,yspeed:2540,diag_mode:'45ort'});
GEN.COM('nc_cre_output',{layer:par.layer,ncset:id});
var profile = GEN.getProfileLimits({job:job,step:step,units:'mm'});
GEN.origin({x:profile.xmin,y:profile.ymin});
if(/(cdr)/.test(par.layer)){
GEN.affectedLayer({affected:'yes',layer:par.layer,clear_before:'yes'});
GEN.COM("adv_filter_reset");
GEN.COM("reset_filter_criteria,filter_name=,criteria=all");
GEN.selectByFilter({attribute:[{attribute:'tl_string',text:"*LDI_HOLE_Two*"}]});
GEN.selectByFilter({attribute:[{attribute:'tl_string',text:"*XRAY_HOLE*"}]});
GEN.COM("adv_filter_reset");
GEN.COM("reset_filter_criteria,filter_name=,criteria=all");
if( GEN.getSelectCount()>0){
GEN.selChangeSym({symbol:'r3054'})
};
GEN.affectedLayer({ mode:'all',affected:'no'});
}
my %step_limits = $GEN->getStepLimits(job=>$Job,step=>$Step,units=>$PAR->{units}); ncsets = GEN.getNcsetsList({job:job,step:step,layer:par.layer});
##select register features and create base layer if( ncsets.length > 0 ){
update_loading("选择对齐基准..",0,position=>'n'); if (ncsets.filter(function(v){ return /^($nc_set)$/.test(v)}).length > 0) {
my $ans = select_register_basic(step=>$Step,base_lyr=>$base_lyr,step_limits=>\%step_limits); GEN.COM('ncset_delete',{name:nc_set});
return $ans if($ans eq 'Cancel'); }
## }
my %register_info = %{$ans}; }
update_loading("选择需对齐的层别..",0,position=>'n'); // function edit_nc_file(par){
my $layers = select_work_layer(); // open(TMP,par.output_file) || die "cannot open "+par.output_file;
return $layers if $layers eq 'Cancel'; // my @data = <TMP>;
// close (TMP);
// chomp @data;
// #
// my %data = split_program(data=>\@data);
// my $ans = convert_new_program(layer=>$par{layer},new_file=>$par{new_file},data=>\%data,x=>$par{x},y=>$par{y});
// return $ans if $ans;
// return undef;
// }
function split_program(par){
var ui_info = par.info;
var info={};
var flag="start",router_flag = undefined;
par.data.forEach(function(line){
if( flag == 'start' ){
if( line == 'M48' ){
flag = 'overhead';
}
}
else if( flag == 'overhead' ){
if( /^T01C/i.test(line) ){
flag = 'head';
}
}
else if( flag == 'head' ){
if( !/^T\d+/i.test(line) ){
flag = 'neck';
}
}
else if( flag == 'neck' ){
if( /^T01/i.test(line) ){
flag = 'body';
}
}
else if( flag == 'body' ){
if( /^M30$/i.test(line) ){
flag = 'end';
}
}
my $report = register_layers(step=>$Step,layers=>$layers,register_info=>\%register_info,step_limits=>\%step_limits,base_lyr=>$base_lyr); if( flag == 'overhead' ){
##储存比对报告 info.overhead.push(line)
if( $report ){
$IKM->update_flow_report(-report=>$report,-job_id=>$ARGS{job_id},-process_id=>$ARGS{process_id});
} }
else{ else if( flag == 'head' ){
$IKM->update_flow_report(-report=>'',-job_id=>$ARGS{job_id},-process_id=>$ARGS{process_id}); if(/^T(\d+)C(.*)/.test(line)){
if(2 - section_tool/1000 < 0.0001){
section_number = RegExp.$1;
}
}
info.head.push(line)
}
else if( flag == 'neck' ){
info.neck.push(line)
}
else if( flag == 'body' ){
if( /^(T(\d+))$/i.test(line) ){
router_flag = RegExp.$1;
}
if(router_flag){
var num = router_flag.slice(1) - 0;
info.body[router_flag].num = num;
// 判断孔的范围 2020-04-21
if(num - section_number < 0.001 && /^T/.test(line)){
var point = change_coode_to_vale(line);
var are_check = 0;
drl_section_data.forEach(function(symbol){
var dist = genMath.point2sym_dist(point,symbol);
if(dist == 0){
are_check = 1;
} }
})
if(are_check){
drl_section.push(line)
}else{
info.body[router_flag].value.push(line)
}
}else{
info.body[router_flag].value.push(line)
}
}
}
else if( flag == 'end' ){
info.end.push(line)
}
})
return info;
}
$GEN->deleteLayer(job=>$Job,layer=>['base_lyr_tl']); function convert_new_program(par){
$GEN->affectedLayer(mode=>'all',affected=>'no'); open(NEWMYFILE,">$par{new_file}");
update_loading("【 层对齐 】完成,..",1,position=>'n'); var data = par.data;
hide_loading();
##保存料号
if( $PAR->{save_job} =~ /yes/i ){ ##0.插入表头
show_loading("$Job 正在保存料号,请稍候...",0,position=>'n'); if($par{x} != 1 or $par{y} != 1){
$GEN->checkInout(job=>$Job,mode=>'out'); print NEWMYFILE 'M47,'.job.' '.'X:'.$par{x}.' '.'Y:'.$par{y},"\n";
$GEN->saveJob(job=>$Job);
hide_loading();
} }
unless ($GEN->{STATUS}){ ##1.头顶(刀径清单之前的)/overhead
return $Return; foreach my $line(@{$data{overhead}}){
print NEWMYFILE $line,"\n";
}
##
##2.程序头(router清单)/head
my $tool_change = get_tool_change(layer=>$par{layer},data=>$par{data});
#$GUI->debug(dump($tool_change));
###人工排序一次
$tool_change = manual_sort_tool(layer=>$par{layer},data=>$par{data},info=>$tool_change);
return $tool_change if $tool_change eq 'Cancel';
##目前扩孔后没有其它类型的孔
my $nibble_suffix = 1;
my $check_nibble_tool = 0;
foreach my $line(@{$data{head}}){
my ($tool,$suffix) = $line =~ /^(T\d+)C.*$/;
next unless $tool;
##刀序顺序使用最新的
next unless $tool_change->{$tool}{new_tool};
foreach my $item(values %$tool_change){
if( $tool eq $item->{new_tool} ){
if($tool_change->{$item->{new_tool}}{size} > 6.35){
if(! $check_nibble_tool){
print NEWMYFILE $tool.'C'.(3.15 + $nibble_suffix/1000),"\n";
#$nibble_suffix++;
$check_nibble_tool = 1;
}
}else{
print NEWMYFILE $item->{new_header},"\n";
}
$PAR->{tool_num_count} = $item->{new_tool_num} unless ($PAR->{tool_num_count} and $PAR->{tool_num_count} > $item->{new_tool_num});
#$hole_exit = 1 if $item->{new_header} =~ /503$/;
} }
else{
$GUI->msgbox(-icon=>'error',-text=>join("\n",@{$GEN->{STATUS}}));
addFlowNotes(-notes=>" Genesis Error:\n ".join("\n ",@{$GEN->{STATUS}}));
return 'Error';
} }
}
catch Error::Simple with {
my $error = shift;
$GUI->msgbox(-icon=>'error',-text=>$error);
return 'Error';
}
finally{
}; }
if($par{layer} =~ /(cdr|vpg|alp|alr|psp)/){
print NEWMYFILE 'T99C0.549',"\n";
}
sub select_register_basic{ ##3.脖子(程序头和正式T序坐标之间)/neck
my %par = @_; foreach my $line(@{$data{neck}}){
my $step = $par{step}; next if $line =~ /g93/i;
my $base_lyr = $par{base_lyr}; print NEWMYFILE $line,"\n";
my %step_limits = %{$par{step_limits}}; }
my %info ;
update_loading("请选择层别对齐的参照物(一般选择外形或钻孔,最少选择3个)",0,position=>'n'); if(@drl_section_data){
while(1){ print NEWMYFILE 'T'.$section_number,"\n";
$GEN->openStep(job=>$Job,name=>$step); foreach my $tmp (@drl_section){
#如果存在默认基准层,则打开它; print NEWMYFILE $tmp,"\n";
if (defined $PAR->{base_layer} and $PAR->{base_layer} !~ /^\s*$/){ }
$GEN->workLayer(name=>$PAR->{base_layer},display_number=>2,clear_before=>'yes') if ($GEN->isLayerExists(job=>$Job,layer=>$PAR->{base_layer}));
} }
my $ok = $GEN->PAUSE('Please Select Register Features');
return 'Cancel' unless $ok;
$info{sel_count} = $GEN->getSelectCount(); ##4.实际的每把T/body
unless ($info{sel_count}){ my $nibble_tool_check = 0;
$GUI->msgbox(-icon=>'error',-text=>'请选择参考对象'); foreach my $tool (sort{$data{body}{$a}{num}<=>$data{body}{$b}{num}} keys %{$data{body}}){
##获取对应的新刀径
my $new_tool;
my $check_drl_section = 0;
foreach my $old_tool(keys %$tool_change){
if( $tool eq $tool_change->{$old_tool}{new_tool} ){
$new_tool = $old_tool;
}
}
next unless $new_tool;
foreach my $line(@{$data{body}{$new_tool}{value}}){
#if( abs($tool_change->{$new_tool}{size} - 3.175) < 0.001 ){
# if( $line =~ /^(T\d+)/ ){
# print NEWMYFILE '/',$tool,"\n";
# }
# else{
# print NEWMYFILE '/',$line,"\n";
# }
#}
#else{
#if( $line =~ /^(T\d+)/ ){
# print NEWMYFILE $tool,"\n";
#}
#else{
# print NEWMYFILE $line,"\n";
#}
#}
if( $tool_change->{$new_tool}{size} > 6.35 ){
if( $line =~ /^(T\d+)/ ){
if( !$nibble_tool_check ){
print NEWMYFILE $tool,"\n";
$nibble_tool_check = 1;
}
} }
else{ else{
last; print NEWMYFILE $line,"\n";#'G84X'.$tool_change->{$new_tool}{size}
}
}
else{
if( $line =~ /^(T\d+)/ ){
print NEWMYFILE $tool,"\n";
}
else{
if( $line =~ /X.*Y.*G85X.*Y.*/ ){
my ($tmp1,$tmp2) = $line =~ /(X\-?\d*\.?\d*Y\-?\d*\.?\d*)G85(X\-?\d*\.?\d*Y\-?\d*\.?\d*)/;
my $slot_star = change_coode_to_vale($tmp1);
my $slot_end = change_coode_to_vale($tmp2);
my $slot_size = $tool_change->{$new_tool}{size};
my $slot_length = $slot_size + TL::GenMath->line_length({xs=>$slot_star->{x},xe=>$slot_end->{x},ys=>$slot_star->{y},ye=>$slot_end->{y}});
my $slot_info = ger_short_slot_vale(slot_size=>$slot_size,slot_length=>$slot_length);
#if($slot_info){
# my $angle = $slot_info->{angle};
# my $point = TL::GenMath->rotate_point($slot_star,$slot_end,$angle);
# my $tmp_data = change_coode(data=>{x=>$point->{x},y=>$point->{y}},datum=>{x=>0,y=>0});
# my $tmp_line = $tmp1.'G85'.$tmp_data;
# print NEWMYFILE $tmp_line,"\n";
#}else{
print NEWMYFILE $line,"\n";
#}
}else{
print NEWMYFILE $line,"\n";
}
}
}
} }
} }
#生成基准层
$GEN->selCopyOther(dest=>'layer_name',target_layer=>$base_lyr,invert=>'no',);
$GEN->clearLayers();
$GEN->affectedLayer(mode=>'all',affected=>'no');
my %layer_limits = $GEN->getLayerLimits(job=>$Job,step=>$step,layer=>$base_lyr,units=>$PAR->{units},);
$info{shift_x} = abs($layer_limits{xmax}-$step_limits{xmin}) + 1;
$GEN->workLayer(name=>$base_lyr,display_number=>1);
$GEN->selMove(dx=>-$info{shift_x},dy=>0);
return \%info;
}
#插入M97坐标 'X-214500Y000000'
if($par{layer} =~ /(cdr|vpg|alp|alr|psp)/){
my @feat = GEN.getFeatures(job=>job,step=>step,layer=>'pnl-map',units=>'mm');
my @feat_M97 = grep($_->{attributes}->[0] =~ /(DRL_TXT_DRL)/,@feat);
my $coordinate_txt;
my $mode;#判断*的位置是横放还是竖放 1 代表横放 2代表竖放
if($feat_M97[0]->{x} >= $PAR->{sr}{xmin} and $feat_M97[0]->{x} <= $PAR->{sr}{xmax}){
$mode = 1;
}else{
$mode = 2;
}
sub select_work_layer{
my @layers; if($datum->{angle} == 90){
#选择层 my @M97_tmp = TL::GenMath->p_trans($datum,$datum->{angle},'no',0,0,({x=>$feat_M97[0]->{x},y=>$feat_M97[0]->{y}}));#返回的是一个数组
if ($PAR->{register_layers} eq 'all'){ if($mode == 1){
@layers = sort {$Matrix->{$a}{row} <=> $Matrix->{$b}{row}} keys %$Matrix; $coordinate_txt = change_coode(data=>{x=>$M97_tmp[0]->{x} + 2.5 - 0.275,y=>$M97_tmp[0]->{y} - 25 + 0.275},datum=>$datum);
}else{
$coordinate_txt = change_coode(data=>{x=>$M97_tmp[0]->{x} - 25 + 0.275,y=>$M97_tmp[0]->{y} - 2.5 + 0.275},datum=>$datum);
}
}else{
if($mode == 1){
$coordinate_txt = change_coode(data=>{x=>$feat_M97[0]->{x} - 25 + 0.275,y=>$feat_M97[0]->{y} - 2.5 + 0.275},datum=>$datum);
}else{
$coordinate_txt = change_coode(data=>{x=>$feat_M97[0]->{x} + 2.5 - 0.275,y=>$feat_M97[0]->{y} - 25 + 0.275},datum=>$datum);
} }
elsif ($PAR->{register_layers} eq 'board'){
@layers = grep({$Matrix->{$_}{context} eq 'board'}keys %$Matrix);
@layers = sort {$Matrix->{$a}{row} <=> $Matrix->{$b}{row}} @layers;
} }
elsif($PAR->{register_layers} eq 'select'){ if($datum->{angle} == 90){
@layers = $GUI->select_layer(-title=>'请选择需对齐的层',-layermatrix=>$Matrix,-selectmode=>'multiple'); print NEWMYFILE 'T99',"\n";
return 'Cancel' unless @layers; if($mode == 1){
#GEN.PAUSE('M98');
print NEWMYFILE 'M98,'.substr(job,0,6).' $S$I',"\n";
}else{
#GEN.PAUSE('M97');
print NEWMYFILE 'M97,'.substr(job,0,6).' $S$I',"\n";
}
print NEWMYFILE $coordinate_txt,"\n";
}else{
print NEWMYFILE 'T99',"\n";
if($mode == 1){
print NEWMYFILE 'M97,'.substr(job,0,6).' $S$I',"\n"
}else{
print NEWMYFILE 'M98,'.substr(job,0,6).' $S$I',"\n";
}
print NEWMYFILE $coordinate_txt,"\n";
}
}
##5.结束/end
foreach my $line(@{$data{end}}){
print NEWMYFILE $line,"\n";
} }
return \@layers; ##
close (NEWMYFILE);
return undef;
} }
sub register_layers{ sub get_tool_change{
my %par = @_; my %par = @_;
my $step = $par{step}; my %info;
my @layers = @{$par{layers}}; my %data = %{$par{data}};
my %register_info = %{$par{register_info}}; my $is_laser = $par{is_laser};
my %step_limits = %{$par{step_limits}}; my $row_num = 0;
my $base_lyr = $par{base_lyr};
#my $report;
my $report = '<html><body bgcolor="#DDECFE"><font size="3" color="#003DB2"><p>层间对齐报告</p></font>';
$report .= '<font size="3" color="#003DB2">Step:'.$step.'&nbsp;&nbsp;&nbsp;&nbsp;运行时间:'.now().'</font>';
$report .= '<table border="1"><tr bg_color><th>层别</th><th>是否对位</th><th>是否镜像</th></tr>';
my $n_progress = 0;
my $tmp_lyr = 'tmp_lyr_tl';
foreach my $layer (@layers){
update_loading("正在对齐${layer}..",(++$n_progress/scalar(@layers)));
$GEN->clearLayers();
$GEN->affectedLayer(mode=>'all',affected=>'no');
$GEN->affectedLayer(affected=>'yes',layer=>[$layer],mode=>'single');
$GEN->selReverse();
next if ($register_info{sel_count} >$GEN->getSelectCount());
my ($moved,$mirror) = ('No','No');
foreach my $n (0..4){
$GEN->deleteLayer(layer=>$tmp_lyr) if ($GEN->isLayerExists(job=>$Job,layer=>$tmp_lyr));
$GEN->clearLayers();
$GEN->affectedLayer(mode=>'all',affected=>'no');
if ($n ==1 or $n == 2){
$GEN->affectedLayer(affected=>'yes',layer=>[$layer],mode=>'single');
$GEN->selTransform(
oper=>'mirror',
x_anchor=>$step_limits{xmin} + $step_limits{xsize}/2,
y_anchor=>$step_limits{ymin} + $step_limits{ysize}/2,
mode=>'anchor',
);
$GEN->affectedLayer(mode=>'all',affected=>'no');
$mirror = ($n%2)?'Yes':'No';
}
if ($n ==3 or $n == 4){
$GEN->affectedLayer(affected=>'yes',layer=>[$layer],mode=>'single');
$GEN->selTransform(
oper=>'mirror',
x_anchor=>$step_limits{xmin} + $step_limits{xsize}/2,
y_anchor=>$step_limits{ymin} + $step_limits{ysize}/2,
mode=>'anchor',
);
$GEN->selTransform(
oper=>'rotate',
x_anchor=>$step_limits{xmin} + $step_limits{xsize}/2,
y_anchor=>$step_limits{ymin} + $step_limits{ysize}/2,
mode=>'anchor',
angle=>180,
);
$GEN->affectedLayer(mode=>'all',affected=>'no');
$mirror = ($n%2)?'Yes':'No';
##
my (%head,%special,$exist_2500);
##先判断有无3.054的刀径(排第1)
foreach my $line(@{$data{head}}){
my ($tool,$size,$data) = $line =~ /^(T\d+)C(\d*\.?\d{3})(S?.*)$/;
next unless $tool;
$head{$tool}{data} = 'C'.$2;
####
if( abs($size - 0.001) < 0.0001 ){
$head{$tool}{data} = 'C3.054';
$row_num++;
$info{$tool}{new_tool_num} = $row_num;
$info{$tool}{new_tool} = 'T'.sprintf("%02s",$row_num);
$info{$tool}{size} = 3.054;
$info{$tool}{new_header} = $info{$tool}{new_tool}.$head{$tool}{data};
} }
if ($n == 0 or $n == 1 or $n == 3){
$GEN->affectedLayer(affected=>'yes',layer=>[$base_lyr,$layer],mode=>'single');
$GEN->selCopyOther(
dest=>'layer_name',
target_layer=>$tmp_lyr,
);
$GEN->clearLayers();
$GEN->affectedLayer(mode=>'all',affected=>'no');
$GEN->workLayer(name=>$tmp_lyr,display_number=>1);
$GEN->selectByFilter(feat_types=>'pad\;line\;arc',);
$GEN->selChangeSym(symbol=>'r1') if ($GEN->getSelectCount());
$GEN->selRefFeat(
use=>'filter',
layers=>$base_lyr,
mode=>'touch',
f_types=>'line\;pad\;surface\;arc\;text',
polarity=>'positive\;negative',
filter=>{
feat_types=>'pad\;line\;surface\;arc\;text',
polarity=>'positive\;negative',
} }
);
$GEN->selSubstitute( foreach my $line(@{$data{head}}){
mode=>'substitute', my ($tool,$size,$data) = $line =~ /^(T\d+)C(\d*\.?\d{3})(.*)$/;
symbol=>$Replace_symbol, next unless $tool;
x_datum=>0, next if(abs($size - 0.001) < 0.0001);
y_datum=>0, $row_num++;
tol=>$PAR->{cmp_tol}*1000, $info{$tool}{size} = $size;
); $info{$tool}{new_tool_num} = $row_num;
$GEN->selectByFilter( $info{$tool}{new_tool} = 'T'.sprintf("%02s",$row_num);
feat_types=>'pad', $info{$tool}{new_header} = $info{$tool}{new_tool}.$head{$tool}{data};
include_syms=>$Replace_symbol, }
polarity=>'positive\;negative', return \%info;
); }
my $count = $GEN->getSelectCount();
if ($GEN->getSelectCount() > 1.5){
my @features = $GEN->getFeatures(
job=>$Job,
step=>$step,
layer=>$tmp_lyr,
options=>'select',
units=>$PAR->{units},
);
foreach my $feat (@features){ sub manual_sort_tool{
if (abs($feat->{x}) > 0.0001 or abs($feat->{y}) > 0.0001){ my %par = @_;
$GEN->workLayer(name=>$layer,display_number=>1); my $data = $par{data};
$GEN->selMove(dx=>$register_info{shift_x}-$feat->{x},dy=>-$feat->{y}) if (abs($register_info{shift_x}-$feat->{x}) > 0.0001); my $tool_info = $par{info};
$moved = 'Yes'; my @items;
my ($slot_flag,@slot_size);
foreach my $num(1..scalar(keys %{$data->{body}})){
my $tool = 'T'.sprintf("%02s",$num);
next unless $tool_info->{$tool}{new_tool};
foreach my $old_tool(sort{$tool_info->{$a}{new_tool_num}<=>$tool_info->{$b}{new_tool_num}} keys %$tool_info){
if( $tool eq $tool_info->{$old_tool}{new_tool} ){
my $suffix;
my $size = $tool_info->{$old_tool}{size};
push @items,{tool=>$old_tool,size=>$tool_info->{$old_tool}{size} >= 1 ? $tool_info->{$old_tool}{size} : '0'.$tool_info->{$old_tool}{size},suffix=>$suffix};
last; last;
} }
} }
last;
} }
update_loading("$par{layer} 层请确认钻刀排列顺序...",0,position=>'n');
my %form = $GUI->show_form(
-title => "请确认钻孔刀径顺序",
-defaultsize => [400,500],
-columns => 2,
-items => [
{
name => 'table',
type => 'treeview',
label => '',
label_position => 'top',
expand=>1,
scrolledwindow=>{},
property => {
height_request=>200,
tl_model_type => 'list',
enable_grid_lines => 'none',
tl_mapping =>['tool' => 'Glib::String','size' => 'Glib::String','suffix'=>'Glib::String'],
tl_columns =>[
{title=>'原始刀序',visible=>1,resizable=>1,min_width=>80,expand=>1,renders=>[{class=>'Text',property=>{editable=>0,background=>'#FCFBB6',foreground=>'#000000'},text=>'tool'}]},
{title=>'刀径',visible=>1,resizable=>1,min_width=>80,expand=>1,renders=>[{class=>'Text',property=>{editable=>0,background=>'#FCFBB6',foreground=>'#000000'},text=>'size'}]},
{title=>'后缀(可编辑)',visible=>1,resizable=>1,min_width=>80,expand=>1,renders=>[{class=>'Text',property=>{editable=>1,background=>'#C5DBF2',foreground=>'#000000'},text=>'suffix'}]},
],
},
value => \@items,
get_value_func => sub{ my %par = @_;
my $tvdata = $par{widget}->tl_get_model_data();
return $tvdata;
},
set_value_func => sub{ my %par = @_;
my $v = $par{value};
$par{widget}->tl_set_data($v);
return 0;
},
button_position=>'top',
buttons => [
{ name=>'top',label=>'置顶',stock=>'gtk-goto-top',
command=>sub{ my %p = @_;
my $widget = $p{formpanel}->get_widget('table');
$widget->set_property(reorderable=>1);
$widget->tl_sel_moveto_top();
$widget->set_property(reorderable=>0);
}
},
{ name=>'up',label=>'上移',stock=>'gtk-go-up',
command=>sub{ my %p = @_;
my $widget = $p{formpanel}->get_widget('table');
$widget->set_property(reorderable=>1);
$widget->tl_sel_move_up();
$widget->set_property(reorderable=>0);
}
},
{ name=>'down',label=>'下移',stock=>'gtk-go-down',
command=>sub{ my %p = @_;
my $widget = $p{formpanel}->get_widget('table');
$widget->set_property(reorderable=>1);
$widget->tl_sel_move_down();
$widget->set_property(reorderable=>0);
}
},
{ name=>'bottom',label=>'置底',stock=>'gtk-goto-bottom',
command=>sub{ my %p = @_;
my $widget = $p{formpanel}->get_widget('table');
$widget->set_property(reorderable=>1);
$widget->tl_sel_moveto_bottom();
$widget->set_property(reorderable=>0);
}
},
],
},
]
);
return 'Cancel' unless %form;
##将界面确认的结果重新整理一遍
my %info;
my @data = @{$form{table}};
my $row_num;
foreach my $item(@data){
$row_num++;
if( $item->{suffix} =~ /^\(w(\d+)\)$/i || $item->{suffix} =~ /^\(w(\d+)s\d+\)$/i || $item->{suffix} =~ /^\(s(\d+)\)$/i){
$info{$item->{tool}}{suffix} = $item->{suffix};
$info{$item->{tool}}{size} = $item->{size};
}
elsif($item->{suffix} =~ /^(\d+)$/i ){
$info{$item->{tool}}{suffix} = $item->{suffix}+0;
$info{$item->{tool}}{size} = $item->{size};
}
else{
$info{$item->{tool}}{size} = $item->{size};
}
$info{$item->{tool}}{new_tool_num} = $row_num;
$info{$item->{tool}}{new_tool} = 'T'.sprintf("%02s",$row_num);
if( $item->{suffix} =~ /^\((w|s)(\d+)\)$/i || $item->{suffix} =~ /^\(w(\d+)s(\d+)\)$/i){
$info{$item->{tool}}{new_header} = $info{$item->{tool}}{new_tool}.'C'.sprintf("%.3f",$info{$item->{tool}}{size}).$item->{suffix};
} }
else{ else{
$mirror = 'No'; $info{$item->{tool}}{new_header} = $info{$item->{tool}}{new_tool}.'C'.sprintf("%.3f",$info{$item->{tool}}{size});
$moved = 'No'; }
} }
##
return \%info;
}
sub input_drill_program{
my %par = @_;
GEN.COM( "input_manual_reset");
GEN.COM( "input_manual_set,path=$par{file},job=job,step=step,format=Excellon2,data_type=ascii,
units=mm,coordinates=absolute,zeroes=none,nf1=3,nf2=3,decimal=no,separator=nl,tool_units=mm,layer=$par{new_layer},wheel=,
wheel_template=,nf_comp=0,multiplier=1,text_line_width=0.0024,signed_coords=no,break_sr=yes,drill_only=no,merge_by_rule=no,threshold=200,resolution=3");
GEN.COM( "input_manual,script_path=");
GEN.zoomHome();
return undef;
}
=head
web server数据传输
=cut
sub sec_web_services{
use LWP::UserAgent;
use LWP;
use HTTP::Headers;
use HTTP::Response;
use Encode;
use JSON;
use JSON qw(encode_json);
my $url = shift;
my $data = shift;
my $json = JSON->new->allow_nonref;
my $ua = LWP::UserAgent->new();
$ua->agent("Mozilla/5.0 (Windows NT 6.1; rv:30.0) Gecko/20100101 Firefox/30.0");
my $header = ['Content-Type' => 'application/json; charset=UTF-8'];
my $body = encode('utf8', $json->encode($data));
my $request = HTTP::Request->new('POST', $url, $header, $body);
my $res = $ua->request($request);
#$GUI->debug(-text=>dump($res,'-----------------------------------------------------------------',$res->is_success));
if ($res->is_success) {
return 0;
}else{
return 1;
} }
$report .= '<tr><th>'.$layer.'</th>'.(($moved eq 'Yes')?'<th bgcolor="green">Yes':'<th>No').'</th>'.(($mirror eq 'Yes')?'<th bgcolor="yellow">Yes':'<th>No').'</th></tr>'."\n"; }
=head
3:3 不省零
坐标转换 data=>{x=>,y=>} datum=>{x=>,y=>}
=cut
sub change_coode
{
my %par = @_;
my ($check_x,$check_y);
$par{data}->{x} = $par{data}->{x} - $par{datum}->{x};
$par{data}->{y} = $par{data}->{y} - $par{datum}->{y};
$check_x = $par{data}->{x} > 0 ? '': '-';
$check_y = $par{data}->{y} > 0 ? '': '-';
$par{data}->{x} = sprintf("%0.3f",$par{data}->{x});
$par{data}->{x} = sprintf("%06s",abs($par{data}->{x})*1000);
$par{data}->{y} = sprintf("%0.3f",$par{data}->{y});
$par{data}->{y} = sprintf("%06s",abs($par{data}->{y})*1000);
return 'X'.$check_x.($par{data}->{x}).'Y'.$check_y.($par{data}->{y});
}
=head
坐标转换成数值
=cut
sub change_coode_to_vale
{
my $string = shift;
$string =~ /X(-?\w+)Y(-?\w+)/;
my $x_data = sprintf("%0.3f",$1/1000);
my $y_data = sprintf("%0.3f",$2/1000);
return {x=>$x_data,y=>$y_data};
}
sub _deleteLayer{
my %par = @_;
foreach my $layer(@{$par{layer}}){
GEN.deleteLayer(layer=>$layer) if (GEN.isLayerExists(job=>job,layer=>$layer));
} }
$GEN->deleteLayer(job=>$Job,layer=>[$tmp_lyr],step=>$step);
$GEN->affectedLayer(mode=>'all',affected=>'no');
$GEN->units( type=>$PAR->{units});
$report .='</table></body></html>';
return $report;
} }
=head
输出层新命名
=cut
sub get_new_layer_name
{
my job = shift;
my @tmp = split/\-/,job;
splice(@tmp,2,1);
$tmp[2] =~ s/2//;
unless($tmp[2]){
splice(@tmp,2,1);
}
my $new = join('-',@tmp);
return $new;
}
__END__ =head
\ No newline at end of file 短槽拉伸值 slot_size=>,slot_length=>
=cut
sub ger_short_slot_vale
{
my %par = @_;
my $info = {
1.5 =>[
{size_min=>0.4,size_max=>0.55,length=>0,angle=>0},
{size_min=>0.6,size_max=>0.65,length=>0.07,angle=>5},
{size_min=>0.7,size_max=>0.75,length=>0.0625,angle=>4},
{size_min=>0.8,size_max=>0.95,length=>0.05,angle=>2.5},
{size_min=>1.0,size_max=>1.25,length=>0.045,angle=>2},
{size_min=>1.3,size_max=>1.6,length=>0.0375,angle=>1},
{size_min=>1.65,size_max=>2.5,length=>0.0375,angle=>1},
{size_min=>2.55,size_max=>999,length=>0.03,angle=>0.5},
],
1.75 =>[
{size_min=>0.4,size_max=>0.55,length=>0.055,angle=>4},
{size_min=>0.6,size_max=>0.65,length=>0.055,angle=>3},
{size_min=>0.7,size_max=>0.75,length=>0.05,angle=>2.5},
{size_min=>0.8,size_max=>0.95,length=>0.045,angle=>2},
{size_min=>1.0,size_max=>1.25,length=>0.0375,angle=>1},
{size_min=>1.3,size_max=>1.6,length=>0.03,angle=>0.5},
{size_min=>1.65,size_max=>2.5,length=>0.03,angle=>0.5},
{size_min=>2.55,size_max=>999,length=>0.025,angle=>0.5},
],
2.0 =>[
{size_min=>0.4,size_max=>0.55,length=>0.045,angle=>3},
{size_min=>0.6,size_max=>0.65,length=>0.0375,angle=>2},
{size_min=>0.7,size_max=>0.75,length=>0.0375,angle=>1.5},
{size_min=>0.8,size_max=>0.95,length=>0.03,angle=>1},
{size_min=>1.0,size_max=>1.25,length=>0.03,angle=>1},
{size_min=>1.3,size_max=>1.6,length=>0.025,angle=>0.5},
{size_min=>1.65,size_max=>2.5,length=>0.02,angle=>0.5},
{size_min=>2.55,size_max=>999,length=>0.02,angle=>0},
],
};
my $type;
if($par{slot_length}/$par{slot_size} <= 1.5){
$type = 1.5;
}elsif($par{slot_length}/$par{slot_size} > 1.5 and $par{slot_length}/$par{slot_size} <= 1.75){
$type = 1.75;
}elsif($par{slot_length}/$par{slot_size} > 1.75 and $par{slot_length}/$par{slot_size} <= 2){
$type = 2.0;
}elsif($par{slot_length}/$par{slot_size} > 2){
return 0;
}
my $result;
foreach my $tmp (@{$info->{$type}}){
if($par{slot_size} >= $tmp->{size_min} and $par{slot_size} <= $tmp->{size_max}){
$result = 1;
return $tmp;
}
}
unless ($result){
return 0;
}
}
\ No newline at end of file
=head =head
NAME: NAME:
DESCRIPTION: 层别对齐 DESCRIPTION: 钻孔输出
PARAMETER: PARAMETER:
[ [
{ {
name : 'step_filter', name : 'step_filter',
title : '工作step',
type : 'LineEdit', type : 'LineEdit',
title : 'step过滤', property : {tool_tip : '过滤Step名称'},
pack : {row:0,column:1},
property:{tool_tip:'step过滤,未设置则手动选择'},
}, },
{ {
name : 'base_layer', name : 'out_dir',
title : '钻孔输出路径',
type : 'LineEdit', type : 'LineEdit',
title : '初始参考层', property:{tool_tip:'例如: /output/drill'}
pack : {row:0,column:1},
property:{tool_tip:'选择参考基准的参考层,未设定则手动选择'},
}, },
{ {
name : 'register_layers', name : 'cool_spread',
title : '需对齐的层别', title : '跳钻距离(um)',
type : 'ComboBox', type : 'LineEdit',
property : { property:{tool_tip:'例如: 350'}
size_policy:'Expanding,Fixed', },
item_list:[ {
{name:'all',text:'所有层'}, name : 'reread_layer',
{name:'board',text:'board层'}, type : 'RadioBox',
{name:'select',text:'选择层'}, title : '回读钻孔程式',
], property : {tool_tip:'未设定,则默认no',
tool_tip:'如果未设置,默认为选择层' size_policy:'Expanding,Fixed',item_list:[{name:'yes',text:'Yes'},{name:'no',text:'No'}]},
pack : {row:1,column:1},
}, },
{
name : 'is_select_lyr',
type : 'RadioBox',
title : '是否选择层别',
property : {tool_tip:'未设定,则默认no',
size_policy:'Expanding,Fixed',item_list:[{name:'yes',text:'Yes'},{name:'no',text:'No'}]},
pack : {row:1,column:1}, pack : {row:1,column:1},
}, },
{ {
...@@ -49,13 +54,68 @@ ...@@ -49,13 +54,68 @@
] ]
VERSION_HISTORY: VERSION_HISTORY:
V1.00 2018-01-15 Cody Yu V1.00 2019-10-22 Super Zhang
1.新版本 1.新版本
V1.1 2020-03-11 Super Zhang
1.不同尺寸板子增加输出参数
V1.2 2020-03-12 Super
1.修改钻孔输出方式代码
V1.3 2020-03-23 Super
1.增加0.549的M97批号孔
V1.4 2020-3-25 Super
1.增加web server数据传输
V1.5 2020-03-27 Super
1.钻孔输出格式调整为3:3不省零 modal_coords=no
V1.6 2020-3-30 Super
1.修改涨缩参数
V1.7 2020-04-01 Super
1.钻带表头增加料号和涨缩信息
2.涨缩中心点按原点移动后的数据从新计算
V1.8 2020-04-02 Super
1.涨缩中心按改变原点前的坐标计算
v1.9 2020-04-04 Super
1.angle = 270
v2.0 2020-04-15 Kurri
1.增加跳刀参数
V2.1 2020-04-21 Super
1.调整T99坐标位置
2.T02板框监视孔的数据放到T01前面
V2.2 2020-05-14 Kurri
1.vpg层也插入M97,${JOB} $S$I
V2.3 2020-05-15 Kurri
1.修复涨缩小于1的程序没有正常输出的问题
V2.31 2020-06-09 Super
1.扩孔时不再增加G84代码
2.扩孔钻咀用3.151
3.修复ncset同名时钻孔无法输出
V2.32 2020-06-11 Super
1.输出命名更新
V2.33 2020-08-18 Super
1.读取map_info参数2.修复检测孔不是第二把刀的时候检测孔坐标乱刀序,3.双面3.054排序
V2.34 2020-10-13 Kurri
1.输出层别选择取消board属性限定
V2.35 2020-10-16 Kurri
1.增加程序上传的类型
V2.36 2020-10-16 Kurri
1.输出alp和alr时bottom层做mirror
V2.37 2020-10-21 Kurri
1.取消测试版本T2.37
T2.38 2020-10-22 Super
1.增加短槽拉伸
2.调整*的M97/M98模式
T2.39 2020-10-29 Super
1.更新拉伸规则
2.706*603的M97/M98位置调整
V2.38 2020-11-03 Super
1.测试版本到正式版
2.取消槽孔角度旋转
3.输出参数增加single_sr
V2.39 2020-11-06 Super
1.输出参数break_sr设置成yes
HELP: HELP:
<html><body bgcolor="#DDECFE"> <html><body bgcolor="#DDECFE">
<font size="3" color="#003DB2"><p>功能简介</p></font> <font size="3" color="#003DB2"><p>功能简介</p></font>
<p> 层别对齐 </p> <p> 钻孔输出 </p>
<br> <br>
<font size="3" color="#003DB2"><p>参数配置</p></font> <font size="3" color="#003DB2"><p>参数配置</p></font>
<font color="#008000"><p> ● 无</p></font> <font color="#008000"><p> ● 无</p></font>
...@@ -70,100 +130,154 @@ use strict; ...@@ -70,100 +130,154 @@ use strict;
use Encode; use Encode;
use utf8; use utf8;
use Data::Dump 'dump'; use Data::Dump 'dump';
use File::Copy;
use JSON;
my $json = new JSON;
# my $datum;#增加一个基准点数据
# my @drl_section_data;#监视孔范围数据
# my (@drl_section,$section_tool,$section_number);#监视孔坐标
use_module('TL_GenMath');
my ($Job,$Step)=($JOB,undef); my ($Job,$Step)=($JOB,undef);
my $Return = 'done'; my $units = 'mm';
$PAR->{step_filter} = '.*' unless $PAR->{step_filter}; # my $url = "http://10.87.66.216:9008/api/TOPMES6_SEC_V6/sec/sec-import_drill_program";
$PAR->{units} = 'inch' unless $PAR->{units}; # my $server_data;
$PAR->{cmp_tol} = 0.003 unless $PAR->{cmp_tol};
$PAR->{register_layers} = 'select' unless $PAR->{register_layers}; # my $map_info = do($GEN->getJobPath(job=>$Job).'/user/PNL_map_info');
# my $new_name = get_new_layer_name("$Job");
##host name为cody电脑名称,本地测试用本地目录
use Sys::Hostname;
my $hostname = hostname;
#$GUI->debug(dump($hostname));
if( $hostname eq 'DESKTOP-010QP68' ){
$PAR->{out_dir} = 'D:/tmp';
}
if ($hostname eq 'g1kevnzhang'){
$PAR->{out_dir} = 'D:/tmp';
}
$PAR->{spread} = 2000 unless $PAR->{spread};
$PAR->{reread_layer} = 'no' unless $PAR->{reread_layer};
$PAR->{is_select_lyr} = 'no' unless $PAR->{is_select_lyr};
$PAR->{save_job} = 'No' unless $PAR->{save_job}; $PAR->{save_job} = 'No' unless $PAR->{save_job};
$PAR->{cool_spread} = 350 unless $PAR->{cool_spread};#跳孔间距
unless( $PAR->{out_dir} ){
$GUI->msgbox(-icon=>'warning',-text=>'请在脚本参数中设定钻孔输出路径');
return 'Cancel';
}
$PAR->{out_dir} = encode('gbk',$PAR->{out_dir});
##
unless( -d $PAR->{out_dir} ){
$GUI->msgbox(-icon=>'warning',-text=>"$PAR->{out_dir} 脚本参数设定的钻孔输出目录不存在,请确认!");
return 'Cancel';
}
my $Matrix = $GEN->getMatrix(job=>$Job);
my $Replace_symbol = 'moire1x1x1x1x1x1';
# 设定参考层 $PAR->{out_dir} .= '/'.lc($new_name);
$PAR->{base_layer} = 'out' unless $PAR->{base_layer}; mkdir $PAR->{out_dir} unless ( -e $PAR->{out_dir});
my $info;
try { try {
##
show_loading("判断是否选择料号..",0,position=>'n'); show_loading("判断是否选择料号..",0,position=>'n');
unless( $Job){ unless( $Job){
$GUI->msgbox(-icon=>'error',-text=>"请先选择料号后再执行脚本!"); $GUI->msgbox(-icon=>'error',-text=>"请先选择料号后再执行脚本!");
return 'Cancel'; return 'Cancel';
} }
update_loading("检查${Job}是否存在..",0,position=>'n');
##检查料号是否存在 ##检查料号是否存在
update_loading("检查${Job}是否存在..",0,position=>'n');
unless ( $GEN->isJobExists(job=>$Job) ){ unless ( $GEN->isJobExists(job=>$Job) ){
$GUI->msgbox(-icon=>'error',-text=>"料号 $Job 不存在,请确认。"); $GUI->msgbox(-icon=>'error',-text=>"料号 $Job 不存在,请确认。");
return 'Cancel'; return 'Cancel';
} }
update_loading("正在打开料号$Job...",0,position=>'n'); ##
update_loading("正在打开料号${Job}...",0,position=>'n');
$GEN->openJob(job=>$Job) unless ($GEN->isJobOpen(job=>$Job)); $GEN->openJob(job=>$Job) unless ($GEN->isJobOpen(job=>$Job));
##
update_loading("过滤工作step...",0,position=>'n');
my $ans = get_work_step();
return $ans if $ans;
# 获取工作step ##选择工作层
update_loading("正在过滤工作step ,请稍候..",0,position=>'n'); update_loading("过滤层别...",0,position=>'n');
my @steps = $GEN->getStepList(job=>$Job); my @work_layers = select_work_layer();
if ( @steps == 0 ) { return 'Cancel' if $work_layers[0] eq 'Cancel';
$GUI->msgbox(-icon=>'error',-text=>'在料号中没有Step存在,你将退出!');
return 0; ##确认涨缩信息
} my $scale = get_scale_info(layers=>\@work_layers);#-----涨缩值信息确认
elsif (@steps != 1){ return $scale if $scale eq 'Cancel';
my @tmp_steps = grep(/$PAR->{step_filter}/,@steps); $PAR->{scale} = $scale;
if ( @tmp_steps == 0 ) {
$GUI->msgbox(-icon=>'warning',-text=>'根据脚本参数过滤出来的step不存在,请检查资料或者脚本参数配置!');
return 'Cancel';
}
elsif ( @tmp_steps == 1 ) {
$Step = $tmp_steps[0];
}
else {
$Step = $GUI->select_step(-title=>'请选择工作Step',
-steplist=>[@tmp_steps],
-selectmode=>'single');
return 'Cancel' unless ($Step);
}
}
else {
$Step = $steps[0];
}
##
update_loading("正在打开料号$Step STEP...",0,position=>'n');
$GEN->openStep(job=>$Job,name=>$Step); $GEN->openStep(job=>$Job,name=>$Step);
$GEN->clearLayers(); $GEN->clearLayers();
$GEN->affectedLayer( mode=>'all',affected=>'no' ); $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->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->units( type=>$units );
$GEN->zoomHome(); $GEN->zoomHome();
# 开始层对齐
#create tmp layer
my ($base_lyr) = ('base_lyr_tl');
$GEN->createLayer(job=>$Job,layer=>$base_lyr,delete_exists=>'yes');
my %step_limits = $GEN->getStepLimits(job=>$Job,step=>$Step,units=>$PAR->{units}); $PAR->{profile_limits} = $GEN->getProfileLimits(job=>$Job,step=>$Step,units=>'mm');
##select register features and create base layer $PAR->{profile_limits}{xc} = $PAR->{profile_limits}{xsize}/2-abs($PAR->{profile_limits}{xmin});
update_loading("选择对齐基准..",0,position=>'n'); $PAR->{profile_limits}{yc} = $PAR->{profile_limits}{ysize}/2-abs($PAR->{profile_limits}{ymin});
my $ans = select_register_basic(step=>$Step,base_lyr=>$base_lyr,step_limits=>\%step_limits); $PAR->{sr} = $GEN->getSRLimits(job=>$Job,step=>$Step,units=>'mm');
return $ans if($ans eq 'Cancel');
##
my %register_info = %{$ans};
update_loading("选择需对齐的层别..",0,position=>'n'); my $orgDrillToolInfo ;
my $layers = select_work_layer();
return $layers if $layers eq 'Cancel';
my $report = register_layers(step=>$Step,layers=>$layers,register_info=>\%register_info,step_limits=>\%step_limits,base_lyr=>$base_lyr); foreach my $layer (@work_layers) {
##储存比对报告 ##钻孔输出
if( $report ){ update_loading("$layer 层钻孔正在输出...",0,position=>'n');
$IKM->update_flow_report(-report=>$report,-job_id=>$ARGS{job_id},-process_id=>$ARGS{process_id}); my $output_layer = $Job.'-'.$layer.'-ori';#$Job.'-'.$layer.'-ori'
my $ans = drill_out(layer=>$layer,output_layer=>$output_layer,scale_x=>$PAR->{scale}{$layer}{x},scale_y=>$PAR->{scale}{$layer}{y});
return $ans if $ans;
####钻孔程式编辑
my $new_layer;
if($PAR->{scale}{$layer}{x} != 1 or $PAR->{scale}{$layer}{y} != 1){
$new_layer= $new_name.'.'.$layer.('X').($PAR->{scale}{$layer}{x}).('Y').($PAR->{scale}{$layer}{y});
}else{
$new_layer= $new_name.'.'.$layer;
} }
else{
$IKM->update_flow_report(-report=>'',-job_id=>$ARGS{job_id},-process_id=>$ARGS{process_id}); my $new_file = $PAR->{out_dir}.'/'.$new_layer;
update_loading("$layer 层钻孔程式正在编辑...",0,position=>'n');
$ans = edit_nc_file(layer=>$layer,output_file=>$PAR->{out_dir}.'/'.$output_layer,new_file=>$new_file,x=>$PAR->{scale}{$layer}{x},y=>$PAR->{scale}{$layer}{y});#drl_type=>$drl_type
return $ans if $ans;
##删除钻孔输出的临时文件
unlink $PAR->{out_dir}.'/'.$output_layer;
##回读钻孔程式
if( $PAR->{reread_layer} =~ /yes/i){
update_loading("$layer 层钻孔程式回读中...",0,position=>'n');
my $new_layer_2 = $new_layer;
input_drill_program(layer=>$layer,file=>$PAR->{out_dir}.'/'.$new_layer_2,new_layer=>$new_layer);#drl_type=>$drl_type,drl_side=>$drl_side
}
#传入web server数据
#if($layer =~ /(cdr|vpg|alp|alr|psp)/){
# update_loading("$layer 层web server数据上传中...",0,position=>'n');
# open(TMP,$new_file) || die "cannot open $PAR->{out_dir}/$new_layer";
# my @data = <TMP>;
# close (TMP);
# chomp(@data);
# my $file_data;
# $file_data = join("\n",@data);
# $server_data->{data} = [{
# tooling_type=>"mech_drill",
# tooling_name=>$new_layer,
# partnumber=>$Job,
# tooling_text_data=>$file_data,
# }];
# #$GUI->debug(-text=>dump($server_data));
# my $result = sec_web_services($url,$server_data);
# if($result){
# $GUI->msgbox(-icon=>'error',-text=>"Web services数据传输错误!");
# return 'Cancel';
# }
#}
} }
$GEN->deleteLayer(job=>$Job,layer=>['base_lyr_tl']);
$GEN->affectedLayer(mode=>'all',affected=>'no');
update_loading("【 层对齐 】完成,..",1,position=>'n');
hide_loading(); hide_loading();
##保存料号 ##保存料号
...@@ -174,12 +288,12 @@ try { ...@@ -174,12 +288,12 @@ try {
hide_loading(); hide_loading();
} }
###output and return status, if genesis error, it will output genesis error command
unless ($GEN->{STATUS}){ unless ($GEN->{STATUS}){
return $Return; return 'done';
} }
else{ else{
$GUI->msgbox(-icon=>'error',-text=>join("\n",@{$GEN->{STATUS}})); $GUI->msgbox(-icon=>'error',-text=>join("\n",@{$GEN->{STATUS}}));
addFlowNotes(-notes=>" Genesis Error:\n ".join("\n ",@{$GEN->{STATUS}}));
return 'Error'; return 'Error';
} }
} }
...@@ -190,192 +304,848 @@ catch Error::Simple with { ...@@ -190,192 +304,848 @@ catch Error::Simple with {
return 'Error'; return 'Error';
} }
finally{ finally{
$GEN->COM('disp_on');
}; };
sub select_register_basic{ sub get_work_step {
my %par = @_; my @steps = $GEN->getStepList(job=>$Job);
my $step = $par{step}; if ( @steps == 0 ) {
my $base_lyr = $par{base_lyr}; $GUI->msgbox(-icon=>'error',-text=>'在料号中没有Step存在,请确认。');
my %step_limits = %{$par{step_limits}}; return 'Cancel';
my %info ; }
elsif (@steps != 0){
$PAR->{step_filter} = '.*' unless $PAR->{step_filter};
my @tmp_steps = grep(/$PAR->{step_filter}/,@steps);
if ( @tmp_steps == 0 ) {
$GUI->msgbox(-icon=>'warning',-text=>'根据脚本参数过滤出来的step不存在,请检查资料或者脚本参数配置!');
return 'Cancel';
}
elsif (@tmp_steps == 1) {
$Step = $tmp_steps[0];
}
else {
$Step = $GUI->select_step(-title=>'请选择工作 Step',
-steplist=>[@tmp_steps],
-default=>[$tmp_steps[0]],
-gen=>$GEN,
-selectmode=>'single');
return 'Cancel' unless ($Step);
}
}
return undef;
}
update_loading("请选择层别对齐的参照物(一般选择外形或钻孔,最少选择3个)",0,position=>'n'); sub select_work_layer {
while(1){ my %par = @_;
$GEN->openStep(job=>$Job,name=>$step); my @drill;
#如果存在默认基准层,则打开它; my %matrix = $GEN->getMatrix(job=>$Job,type=>'hash');
if (defined $PAR->{base_layer} and $PAR->{base_layer} !~ /^\s*$/){ foreach my $layer (sort {$matrix{$a}{row} <=> $matrix{$b}{row}} keys %matrix) {
$GEN->workLayer(name=>$PAR->{base_layer},display_number=>2,clear_before=>'yes') if ($GEN->isLayerExists(job=>$Job,layer=>$PAR->{base_layer})); next if $layer =~ /ddr/;
if(defined($matrix{$layer}{layer_type}) and $matrix{$layer}{layer_type} eq 'drill'){
push @drill,$layer;
} }
my $ok = $GEN->PAUSE('Please Select Register Features'); }
return 'Cancel' unless $ok; unless( @drill ){
$GUI->msgbox(-icon=>'warning',-text=>'资料中无钻孔层,请确认!');
return 'Cancel';
}
if ($PAR->{is_select_lyr} eq 'yes' and scalar @drill > 1) {
my (%tmp_matrix);
foreach my $layer (@drill) {
$tmp_matrix{$layer} = $matrix{$layer};
}
@drill = $GUI->select_layer(
-title=>'请选择输出层别',
-layermatrix=>\%tmp_matrix,
-default => ['drl','md','bk','lp'],
-selectmode => 'multiple');#single
return 'Cancel' unless(@drill);
}
return @drill;
}
$info{sel_count} = $GEN->getSelectCount(); sub get_scale_info{
unless ($info{sel_count}){ my %par = @_;
$GUI->msgbox(-icon=>'error',-text=>'请选择参考对象'); my (%rows,$n);
foreach my $layer (@{$par{layers}}){
$n ++;
$rows{$layer}{sequence} = $n;
$rows{$layer}{layer} = $layer;
if($layer eq "md"){
$rows{$layer}{x} = 1.0004;
$rows{$layer}{y} = 1.0004;
} }
else{ else{
last; $rows{$layer}{x} = 1.0000;
$rows{$layer}{y} = 1.0000;
} }
} }
#生成基准层 my $scale_factor = $GUI->show_tableform (
$GEN->selCopyOther(dest=>'layer_name',target_layer=>$base_lyr,invert=>'no',); -defaultsize=>[380,400],-title => '请确认涨缩值',-rows => \%rows,
$GEN->clearLayers(); -showcheck => 1,-gen => $GEN,
$GEN->affectedLayer(mode=>'all',affected=>'no'); -columns => [
my %layer_limits = $GEN->getLayerLimits(job=>$Job,step=>$step,layer=>$base_lyr,units=>$PAR->{units},); {
$info{shift_x} = abs($layer_limits{xmax}-$step_limits{xmin}) + 1; column_name=>'layer',
$GEN->workLayer(name=>$base_lyr,display_number=>1); label=>'层名称',
$GEN->selMove(dx=>-$info{shift_x},dy=>0); width=>70,
return \%info; type=>'label',
},
{
column_name=>'x',
label=>'X涨缩值',
width=>130,
type=>'number',
},
{
column_name=>'y',
label=>'Y涨缩值',
width=>130,
type=>'number',
},
],
);
return 'Cancel' unless ($scale_factor);
##
return $scale_factor;
} }
=head
drillmarge 输出
=cut
sub drill_out
{
my %par = @_;
my $nc_set = 'sec-jt';
my @ncsets = $GEN->getNcsetsList(job=>$Job,step=>$Step,layer=>$par{layer});
if( @ncsets ){
if (grep (/^($nc_set)$/,@ncsets)) {
$GEN->COM('ncset_delete',name=>$nc_set);
}
}
#钻带涨缩中心点
my $x_anchor = ($par{scale_x} != 1 or $par{scale_y} != 1) ? $PAR->{profile_limits}{xc} : 0;
my $y_anchor = ($par{scale_x} != 1 or $par{scale_y} != 1) ? $PAR->{profile_limits}{yc} : 0;
unlink if(-e $PAR->{out_dir}.'/'.$par{output_layer});
my ($org_x,$org_y,$angle);
if($PAR->{profile_limits}{ysize} == 603 and $PAR->{profile_limits}{xsize} == 706){
$org_x = $PAR->{profile_limits}{yc};#- 15
$org_y = 5;
$angle = 270;
$datum->{x} = $PAR->{profile_limits}{xmax} - 5;
$datum->{y} = $PAR->{profile_limits}{yc};
$datum->{angle} = 90;
$datum->{type} = 1;#拼版类型
}elsif($PAR->{profile_limits}{ysize} == 603 and $PAR->{profile_limits}{xsize} == 606){
$datum->{x} = $org_x = $PAR->{profile_limits}{xc};#- 5
$datum->{y} = $org_y = 5;
$datum->{angle} = $angle = 0;
$datum->{type} = 0;#拼版类型
}else{
$datum->{x} = $org_x = $PAR->{profile_limits}{xc};#- 24
$datum->{y} = $org_y = 5;
$datum->{angle} = $angle = 0;
$datum->{type} = 0;#拼版类型
}
# 铝片塞防焊和铝片塞树脂程序,bot面时需要mirror
my $xmirror = 'no';
my $ymirror = 'no';
if ($par{layer} =~ /al[pr](\d\d)(\d\d)/) {
my $start = $1 + 0;
my $end = $2 + 0;
if ($start > $end) {
$xmirror = 'yes';
}
}
#获取@drl_section_data数据
if($par{layer} =~ /(cdr)/ and $GEN->getLayerCount(job=>$Job) >= 4){
my @feat = $GEN->getFeatures(job=>$Job,step=>$Step,layer=>'pnl-map',units=>'mm');
my @data_tmp = grep($_->{attributes}->[0] =~ /(DRL_SECTION)/,@feat);#获取监视孔坐标
$section_tool = $map_info->{P}{min_drl} >= 1100 ? 1100 : $map_info->{P}{min_drl};
@drl_section_data = TL::GenMath->p_trans($datum,$datum->{angle},'no',-$datum->{x},-$datum->{y},@data_tmp);
# if($datum->{angle} == 90){
# my @data_tmp = TL::GenMath->p_trans($datum,$datum->{angle},'no',0,0,@data_tmp);#坐标选择
# foreach my $data (@data_tmp){
# my $coorder_txt;
# $coorder_txt = change_coode(data=>$data,datum=>$datum);
# $drl_section_data->{$coorder_txt} = 1;
# }
# }else{
# foreach my $data (@data_tmp){
# my $coorder_txt;
# $coorder_txt = change_coode(data=>{x=>$data->{x},y=>},datum=>$datum);
# $drl_section_data->{$coorder_txt} = 1;
# }
# }
}
sub select_work_layer{ my $id = $nc_set;
my @layers; $GEN->COM('ncset_units',units=>'mm');
#选择层 if($par{layer} =~ /(cdr)/){
if ($PAR->{register_layers} eq 'all'){ $GEN->affectedLayer(affected=>'yes',layer=>$par{layer},clear_before=>'yes');
@layers = sort {$Matrix->{$a}{row} <=> $Matrix->{$b}{row}} keys %$Matrix; $GEN->COM("adv_filter_reset");
$GEN->COM("reset_filter_criteria,filter_name=,criteria=all");
$GEN->selectByFilter(attribute=>[{attribute=>'tl_string',text=>"*LDI_HOLE_Two*"}]);
$GEN->selectByFilter(attribute=>[{attribute=>'tl_string',text=>"*XRAY_HOLE*"}]);
$GEN->COM("adv_filter_reset");
$GEN->COM("reset_filter_criteria,filter_name=,criteria=all");
$GEN->selChangeSym(symbol=>'r1') if $GEN->getSelectCount();
$GEN->affectedLayer( mode=>'all',affected=>'no' );
} }
elsif ($PAR->{register_layers} eq 'board'){
@layers = grep({$Matrix->{$_}{context} eq 'board'}keys %$Matrix); #$GEN->COM('open_sets_manager',test_current=>'no');
@layers = sort {$Matrix->{$a}{row} <=> $Matrix->{$b}{row}} @layers; $GEN->COM('nc_create',ncset=>$id,device=>'basic_excellon',lyrs=>$par{layer},thickness=>0);
$GEN->COM('nc_set_advanced_params',layer=>$par{layer},ncset=>$id);
$GEN->COM('nc_set_current',job=>$Job,step=>$Step,layer=>$par{layer},ncset=>$id);
$GEN->COM('nc_set_file_params',single_sr=>'no',output_path=>$PAR->{out_dir},output_name=>$par{output_layer},zeroes=>'none',units=>'mm',tool_units=>'mm',nf1=>3,nf2=>3,decimal=>'no',modal_coords=>'no');
$GEN->COM('nc_register',angle=>$angle,xoff=>0,yoff=>0,version=>1,xorigin=>$org_x,yorigin=>$org_y,xscale=>$par{scale_x},yscale=>$par{scale_y},xscale_o=>$x_anchor,yscale_o=>$y_anchor,xmirror=>$xmirror,ymirror=>$ymirror);
$GEN->COM('nc_set_optim',optimize=>'yes',iterations=>5,reduction_percent=>1,cool_spread=>$PAR->{cool_spread},break_sr=>'yes',xspeed=>2540,yspeed=>2540,diag_mode=>'45ort');
$GEN->COM('nc_cre_output',layer=>$par{layer},ncset=>$id);
my $profile = $GEN->getProfileLimits(job=>$Job,step=>$Step,units=>'mm');
$GEN->origin(x=>$profile->{xmin},y=>$profile->{ymin});
if($par{layer} =~ /(cdr)/){
$GEN->affectedLayer(affected=>'yes',layer=>$par{layer},clear_before=>'yes');
$GEN->COM("adv_filter_reset");
$GEN->COM("reset_filter_criteria,filter_name=,criteria=all");
$GEN->selectByFilter(attribute=>[{attribute=>'tl_string',text=>"*LDI_HOLE_Two*"}]);
$GEN->selectByFilter(attribute=>[{attribute=>'tl_string',text=>"*XRAY_HOLE*"}]);
$GEN->COM("adv_filter_reset");
$GEN->COM("reset_filter_criteria,filter_name=,criteria=all");
$GEN->selChangeSym(symbol=>'r3054') if $GEN->getSelectCount();
$GEN->affectedLayer( mode=>'all',affected=>'no');
}
@ncsets = $GEN->getNcsetsList(job=>$Job,step=>$Step,layer=>$par{layer});
if( @ncsets ){
if (grep (/^($nc_set)$/,@ncsets)) {
$GEN->COM('ncset_delete',name=>$nc_set);
} }
elsif($PAR->{register_layers} eq 'select'){
@layers = $GUI->select_layer(-title=>'请选择需对齐的层',-layermatrix=>$Matrix,-selectmode=>'multiple');
return 'Cancel' unless @layers;
} }
return \@layers;
return undef;
} }
sub register_layers{ sub edit_nc_file{
my %par = @_; my %par = @_;
my $step = $par{step}; open(TMP,"$par{output_file}") || die "cannot open $par{output_file}";
my @layers = @{$par{layers}}; my @data = <TMP>;
my %register_info = %{$par{register_info}}; close (TMP);
my %step_limits = %{$par{step_limits}}; chomp @data;
#
my $base_lyr = $par{base_lyr}; my %data = split_program(data=>\@data);
#my $report; my $ans = convert_new_program(layer=>$par{layer},new_file=>$par{new_file},data=>\%data,x=>$par{x},y=>$par{y});
my $report = '<html><body bgcolor="#DDECFE"><font size="3" color="#003DB2"><p>层间对齐报告</p></font>'; return $ans if $ans;
$report .= '<font size="3" color="#003DB2">Step:'.$step.'&nbsp;&nbsp;&nbsp;&nbsp;运行时间:'.now().'</font>';
$report .= '<table border="1"><tr bg_color><th>层别</th><th>是否对位</th><th>是否镜像</th></tr>';
my $n_progress = 0;
my $tmp_lyr = 'tmp_lyr_tl';
foreach my $layer (@layers){
update_loading("正在对齐${layer}..",(++$n_progress/scalar(@layers)));
$GEN->clearLayers(); return undef;
$GEN->affectedLayer(mode=>'all',affected=>'no'); }
$GEN->affectedLayer(affected=>'yes',layer=>[$layer],mode=>'single');
$GEN->selReverse();
next if ($register_info{sel_count} >$GEN->getSelectCount());
my ($moved,$mirror) = ('No','No');
foreach my $n (0..4){
$GEN->deleteLayer(layer=>$tmp_lyr) if ($GEN->isLayerExists(job=>$Job,layer=>$tmp_lyr));
$GEN->clearLayers();
$GEN->affectedLayer(mode=>'all',affected=>'no');
if ($n ==1 or $n == 2){
$GEN->affectedLayer(affected=>'yes',layer=>[$layer],mode=>'single');
$GEN->selTransform(
oper=>'mirror',
x_anchor=>$step_limits{xmin} + $step_limits{xsize}/2,
y_anchor=>$step_limits{ymin} + $step_limits{ysize}/2,
mode=>'anchor',
);
$GEN->affectedLayer(mode=>'all',affected=>'no');
$mirror = ($n%2)?'Yes':'No';
}
if ($n ==3 or $n == 4){
$GEN->affectedLayer(affected=>'yes',layer=>[$layer],mode=>'single');
$GEN->selTransform(
oper=>'mirror',
x_anchor=>$step_limits{xmin} + $step_limits{xsize}/2,
y_anchor=>$step_limits{ymin} + $step_limits{ysize}/2,
mode=>'anchor',
);
$GEN->selTransform(
oper=>'rotate',
x_anchor=>$step_limits{xmin} + $step_limits{xsize}/2,
y_anchor=>$step_limits{ymin} + $step_limits{ysize}/2,
mode=>'anchor',
angle=>180,
);
$GEN->affectedLayer(mode=>'all',affected=>'no');
$mirror = ($n%2)?'Yes':'No';
sub split_program{
my %par = @_;
my $ui_info = $par{info};
my (%info);
my ($flag,$router_flag) = ('start',undef);
foreach my $line(@{$par{data}}){
if( $flag eq 'start' ){
if( $line eq 'M48' ){
$flag = 'overhead';
} }
if ($n == 0 or $n == 1 or $n == 3){
$GEN->affectedLayer(affected=>'yes',layer=>[$base_lyr,$layer],mode=>'single');
$GEN->selCopyOther(
dest=>'layer_name',
target_layer=>$tmp_lyr,
);
$GEN->clearLayers();
$GEN->affectedLayer(mode=>'all',affected=>'no');
$GEN->workLayer(name=>$tmp_lyr,display_number=>1);
$GEN->selectByFilter(feat_types=>'pad\;line\;arc',);
$GEN->selChangeSym(symbol=>'r1') if ($GEN->getSelectCount());
$GEN->selRefFeat(
use=>'filter',
layers=>$base_lyr,
mode=>'touch',
f_types=>'line\;pad\;surface\;arc\;text',
polarity=>'positive\;negative',
filter=>{
feat_types=>'pad\;line\;surface\;arc\;text',
polarity=>'positive\;negative',
} }
); elsif( $flag eq 'overhead' ){
if( $line =~ /^T01C/i ){
$flag = 'head';
}
}
elsif( $flag eq 'head' ){
if( $line !~ /^T\d+/i ){
$flag = 'neck';
}
}
elsif( $flag eq 'neck' ){
if( $line =~ /^T01/i ){
$flag = 'body';
}
}
elsif( $flag eq 'body' ){
if( $line =~ /^M30$/i ){
$flag = 'end';
}
}
##
if( $flag eq 'overhead' ){
push @{$info{overhead}},$line;
}
elsif( $flag eq 'head' ){
if($line =~ /^T(\d+)C(.*)/){
if($2 - $section_tool/1000 < 0.0001){
$section_number = $1;
}
}
push @{$info{head}},$line;
}
elsif( $flag eq 'neck' ){
push @{$info{neck}},$line;
}
elsif( $flag eq 'body' ){
if( $line =~ /^(T(\d+))$/i ){
$router_flag = $1;
}
if($router_flag){
my ($num) = $router_flag =~ /^T(\d+)$/;
$info{body}{$router_flag}{num} = $num;
#判断孔的范围 2020-04-21
# if($num - $section_number < 0.001 and $line !~ /^T/){
# my $point = change_coode_to_vale($line);
# my $are_check = 0;
# foreach my $symbol (@drl_section_data){
# my $dist = TL::GenMath->point2sym_dist($point,$symbol);
# if($dist == 0){
# $are_check = 1;
# last;
# }
# }
# if($are_check){
# push @drl_section,$line;
# }else{
# push @{$info{body}{$router_flag}{value}},$line;
# }
# }else{
push @{$info{body}{$router_flag}{value}},$line;
# }
}
}
elsif( $flag eq 'end' ){
push @{$info{end}},$line;
}
##
}
if( wantarray ){
return %info;
}
else{
return \%info;
}
}
$GEN->selSubstitute( sub convert_new_program{
mode=>'substitute', my %par = @_;
symbol=>$Replace_symbol, ##
x_datum=>0, open(NEWMYFILE,">$par{new_file}");
y_datum=>0, my %data = %{$par{data}};
tol=>$PAR->{cmp_tol}*1000,
);
$GEN->selectByFilter(
feat_types=>'pad',
include_syms=>$Replace_symbol,
polarity=>'positive\;negative',
);
my $count = $GEN->getSelectCount();
if ($GEN->getSelectCount() > 1.5){
my @features = $GEN->getFeatures(
job=>$Job,
step=>$step,
layer=>$tmp_lyr,
options=>'select',
units=>$PAR->{units},
);
foreach my $feat (@features){ ##0.插入表头
if (abs($feat->{x}) > 0.0001 or abs($feat->{y}) > 0.0001){ # if($par{x} != 1 or $par{y} != 1){
$GEN->workLayer(name=>$layer,display_number=>1); # print NEWMYFILE 'M47,'.$Job.' '.'X:'.$par{x}.' '.'Y:'.$par{y},"\n";
$GEN->selMove(dx=>$register_info{shift_x}-$feat->{x},dy=>-$feat->{y}) if (abs($register_info{shift_x}-$feat->{x}) > 0.0001); # }
$moved = 'Yes';
last; ##1.头顶(刀径清单之前的)/overhead
foreach my $line(@{$data{overhead}}){
print NEWMYFILE $line,"\n";
}
##
##2.程序头(router清单)/head
my $tool_change = get_tool_change(layer=>$par{layer},data=>$par{data});
#$GUI->debug(dump($tool_change));
###人工排序一次
# $tool_change = manual_sort_tool(layer=>$par{layer},data=>$par{data},info=>$tool_change);
# return $tool_change if $tool_change eq 'Cancel';
##目前扩孔后没有其它类型的孔
my $nibble_suffix = 1;
my $check_nibble_tool = 0;
foreach my $line(@{$data{head}}){
my ($tool,$suffix) = $line =~ /^(T\d+)C.*$/;
next unless $tool;
##刀序顺序使用最新的
next unless $tool_change->{$tool}{new_tool};
foreach my $item(values %$tool_change){
if( $tool eq $item->{new_tool} ){
if($tool_change->{$item->{new_tool}}{size} > 6.35){
if(! $check_nibble_tool){
print NEWMYFILE $tool.'C'.(3.15 + $nibble_suffix/1000),"\n";
#$nibble_suffix++;
$check_nibble_tool = 1;
}
}else{
print NEWMYFILE $item->{new_header},"\n";
}
$PAR->{tool_num_count} = $item->{new_tool_num} unless ($PAR->{tool_num_count} and $PAR->{tool_num_count} > $item->{new_tool_num});
#$hole_exit = 1 if $item->{new_header} =~ /503$/;
}
}
}
# if($par{layer} =~ /(cdr|vpg|alp|alr|psp)/){
# print NEWMYFILE 'T99C0.549',"\n";
# }
##3.脖子(程序头和正式T序坐标之间)/neck
foreach my $line(@{$data{neck}}){
next if $line =~ /g93/i;
print NEWMYFILE $line,"\n";
}
# if(@drl_section_data){
# print NEWMYFILE 'T'.$section_number,"\n";
# foreach my $tmp (@drl_section){
# print NEWMYFILE $tmp,"\n";
# }
# }
##4.实际的每把T序/body
my $nibble_tool_check = 0;
foreach my $tool (sort{$data{body}{$a}{num}<=>$data{body}{$b}{num}} keys %{$data{body}}){
##获取对应的新刀径
my $new_tool;
my $check_drl_section = 0;
foreach my $old_tool(keys %$tool_change){
if( $tool eq $tool_change->{$old_tool}{new_tool} ){
$new_tool = $old_tool;
}
}
next unless $new_tool;
foreach my $line(@{$data{body}{$new_tool}{value}}){
#if( abs($tool_change->{$new_tool}{size} - 3.175) < 0.001 ){
# if( $line =~ /^(T\d+)/ ){
# print NEWMYFILE '/',$tool,"\n";
# }
# else{
# print NEWMYFILE '/',$line,"\n";
# }
#}
#else{
#if( $line =~ /^(T\d+)/ ){
# print NEWMYFILE $tool,"\n";
#}
#else{
# print NEWMYFILE $line,"\n";
#}
#}
if( $tool_change->{$new_tool}{size} > 6.35 ){
if( $line =~ /^(T\d+)/ ){
if( !$nibble_tool_check ){
print NEWMYFILE $tool,"\n";
$nibble_tool_check = 1;
}
}
else{
print NEWMYFILE $line,"\n";#'G84X'.$tool_change->{$new_tool}{size}
}
}
else{
if( $line =~ /^(T\d+)/ ){
print NEWMYFILE $tool,"\n";
}
else{
if( $line =~ /X.*Y.*G85X.*Y.*/ ){
my ($tmp1,$tmp2) = $line =~ /(X\-?\d*\.?\d*Y\-?\d*\.?\d*)G85(X\-?\d*\.?\d*Y\-?\d*\.?\d*)/;
my $slot_star = change_coode_to_vale($tmp1);
my $slot_end = change_coode_to_vale($tmp2);
my $slot_size = $tool_change->{$new_tool}{size};
my $slot_length = $slot_size + TL::GenMath->line_length({xs=>$slot_star->{x},xe=>$slot_end->{x},ys=>$slot_star->{y},ye=>$slot_end->{y}});
my $slot_info = ger_short_slot_vale(slot_size=>$slot_size,slot_length=>$slot_length);
#if($slot_info){
# my $angle = $slot_info->{angle};
# my $point = TL::GenMath->rotate_point($slot_star,$slot_end,$angle);
# my $tmp_data = change_coode(data=>{x=>$point->{x},y=>$point->{y}},datum=>{x=>0,y=>0});
# my $tmp_line = $tmp1.'G85'.$tmp_data;
# print NEWMYFILE $tmp_line,"\n";
#}else{
print NEWMYFILE $line,"\n";
#}
}else{
print NEWMYFILE $line,"\n";
}
}
}
}
}
#插入M97坐标 'X-214500Y000000'
if($par{layer} =~ /(cdr|vpg|alp|alr|psp)/){
my @feat = $GEN->getFeatures(job=>$Job,step=>$Step,layer=>'pnl-map',units=>'mm');
my @feat_M97 = grep($_->{attributes}->[0] =~ /(DRL_TXT_DRL)/,@feat);
my $coordinate_txt;
my $mode;#判断*的位置是横放还是竖放 1 代表横放 2代表竖放
if($feat_M97[0]->{x} >= $PAR->{sr}{xmin} and $feat_M97[0]->{x} <= $PAR->{sr}{xmax}){
$mode = 1;
}else{
$mode = 2;
}
if($datum->{angle} == 90){
my @M97_tmp = TL::GenMath->p_trans($datum,$datum->{angle},'no',0,0,({x=>$feat_M97[0]->{x},y=>$feat_M97[0]->{y}}));#返回的是一个数组
if($mode == 1){
$coordinate_txt = change_coode(data=>{x=>$M97_tmp[0]->{x} + 2.5 - 0.275,y=>$M97_tmp[0]->{y} - 25 + 0.275},datum=>$datum);
}else{
$coordinate_txt = change_coode(data=>{x=>$M97_tmp[0]->{x} - 25 + 0.275,y=>$M97_tmp[0]->{y} - 2.5 + 0.275},datum=>$datum);
}
}else{
if($mode == 1){
$coordinate_txt = change_coode(data=>{x=>$feat_M97[0]->{x} - 25 + 0.275,y=>$feat_M97[0]->{y} - 2.5 + 0.275},datum=>$datum);
}else{
$coordinate_txt = change_coode(data=>{x=>$feat_M97[0]->{x} + 2.5 - 0.275,y=>$feat_M97[0]->{y} - 25 + 0.275},datum=>$datum);
}
}
if($datum->{angle} == 90){
print NEWMYFILE 'T99',"\n";
if($mode == 1){
#$GEN->PAUSE('M98');
print NEWMYFILE 'M98,'.substr($Job,0,6).' $S$I',"\n";
}else{
#$GEN->PAUSE('M97');
print NEWMYFILE 'M97,'.substr($Job,0,6).' $S$I',"\n";
}
print NEWMYFILE $coordinate_txt,"\n";
}else{
print NEWMYFILE 'T99',"\n";
if($mode == 1){
print NEWMYFILE 'M97,'.substr($Job,0,6).' $S$I',"\n"
}else{
print NEWMYFILE 'M98,'.substr($Job,0,6).' $S$I',"\n";
}
print NEWMYFILE $coordinate_txt,"\n";
} }
} }
##5.结束/end
foreach my $line(@{$data{end}}){
print NEWMYFILE $line,"\n";
}
##
close (NEWMYFILE);
return undef;
}
sub get_tool_change{
my %par = @_;
my %info;
my %data = %{$par{data}};
my $is_laser = $par{is_laser};
my $row_num = 0;
##
my (%head,%special,$exist_2500);
##先判断有无3.054的刀径(排第1)
foreach my $line(@{$data{head}}){
my ($tool,$size,$data) = $line =~ /^(T\d+)C(\d*\.?\d{3})(S?.*)$/;
next unless $tool;
$head{$tool}{data} = 'C'.$2;
####
if( abs($size - 0.001) < 0.0001 ){
$head{$tool}{data} = 'C3.054';
$row_num++;
$info{$tool}{new_tool_num} = $row_num;
$info{$tool}{new_tool} = 'T'.sprintf("%02s",$row_num);
$info{$tool}{size} = 3.054;
$info{$tool}{new_header} = $info{$tool}{new_tool}.$head{$tool}{data};
}
}
foreach my $line(@{$data{head}}){
my ($tool,$size,$data) = $line =~ /^(T\d+)C(\d*\.?\d{3})(.*)$/;
next unless $tool;
next if(abs($size - 0.001) < 0.0001);
$row_num++;
$info{$tool}{size} = $size;
$info{$tool}{new_tool_num} = $row_num;
$info{$tool}{new_tool} = 'T'.sprintf("%02s",$row_num);
$info{$tool}{new_header} = $info{$tool}{new_tool}.$head{$tool}{data};
}
return \%info;
}
sub manual_sort_tool{
my %par = @_;
my $data = $par{data};
my $tool_info = $par{info};
my @items;
my ($slot_flag,@slot_size);
foreach my $num(1..scalar(keys %{$data->{body}})){
my $tool = 'T'.sprintf("%02s",$num);
next unless $tool_info->{$tool}{new_tool};
foreach my $old_tool(sort{$tool_info->{$a}{new_tool_num}<=>$tool_info->{$b}{new_tool_num}} keys %$tool_info){
if( $tool eq $tool_info->{$old_tool}{new_tool} ){
my $suffix;
my $size = $tool_info->{$old_tool}{size};
push @items,{tool=>$old_tool,size=>$tool_info->{$old_tool}{size} >= 1 ? $tool_info->{$old_tool}{size} : '0'.$tool_info->{$old_tool}{size},suffix=>$suffix};
last; last;
} }
} }
}
update_loading("$par{layer} 层请确认钻刀排列顺序...",0,position=>'n');
my %form = $GUI->show_form(
-title => "请确认钻孔刀径顺序",
-defaultsize => [400,500],
-columns => 2,
-items => [
{
name => 'table',
type => 'treeview',
label => '',
label_position => 'top',
expand=>1,
scrolledwindow=>{},
property => {
height_request=>200,
tl_model_type => 'list',
enable_grid_lines => 'none',
tl_mapping =>['tool' => 'Glib::String','size' => 'Glib::String','suffix'=>'Glib::String'],
tl_columns =>[
{title=>'原始刀序',visible=>1,resizable=>1,min_width=>80,expand=>1,renders=>[{class=>'Text',property=>{editable=>0,background=>'#FCFBB6',foreground=>'#000000'},text=>'tool'}]},
{title=>'刀径',visible=>1,resizable=>1,min_width=>80,expand=>1,renders=>[{class=>'Text',property=>{editable=>0,background=>'#FCFBB6',foreground=>'#000000'},text=>'size'}]},
{title=>'后缀(可编辑)',visible=>1,resizable=>1,min_width=>80,expand=>1,renders=>[{class=>'Text',property=>{editable=>1,background=>'#C5DBF2',foreground=>'#000000'},text=>'suffix'}]},
],
},
value => \@items,
get_value_func => sub{ my %par = @_;
my $tvdata = $par{widget}->tl_get_model_data();
return $tvdata;
},
set_value_func => sub{ my %par = @_;
my $v = $par{value};
$par{widget}->tl_set_data($v);
return 0;
},
button_position=>'top',
buttons => [
{ name=>'top',label=>'置顶',stock=>'gtk-goto-top',
command=>sub{ my %p = @_;
my $widget = $p{formpanel}->get_widget('table');
$widget->set_property(reorderable=>1);
$widget->tl_sel_moveto_top();
$widget->set_property(reorderable=>0);
}
},
{ name=>'up',label=>'上移',stock=>'gtk-go-up',
command=>sub{ my %p = @_;
my $widget = $p{formpanel}->get_widget('table');
$widget->set_property(reorderable=>1);
$widget->tl_sel_move_up();
$widget->set_property(reorderable=>0);
}
},
{ name=>'down',label=>'下移',stock=>'gtk-go-down',
command=>sub{ my %p = @_;
my $widget = $p{formpanel}->get_widget('table');
$widget->set_property(reorderable=>1);
$widget->tl_sel_move_down();
$widget->set_property(reorderable=>0);
}
},
{ name=>'bottom',label=>'置底',stock=>'gtk-goto-bottom',
command=>sub{ my %p = @_;
my $widget = $p{formpanel}->get_widget('table');
$widget->set_property(reorderable=>1);
$widget->tl_sel_moveto_bottom();
$widget->set_property(reorderable=>0);
}
},
],
},
]
);
return 'Cancel' unless %form;
##将界面确认的结果重新整理一遍
my %info;
my @data = @{$form{table}};
my $row_num;
foreach my $item(@data){
$row_num++;
if( $item->{suffix} =~ /^\(w(\d+)\)$/i || $item->{suffix} =~ /^\(w(\d+)s\d+\)$/i || $item->{suffix} =~ /^\(s(\d+)\)$/i){
$info{$item->{tool}}{suffix} = $item->{suffix};
$info{$item->{tool}}{size} = $item->{size};
}
elsif($item->{suffix} =~ /^(\d+)$/i ){
$info{$item->{tool}}{suffix} = $item->{suffix}+0;
$info{$item->{tool}}{size} = $item->{size};
}
else{
$info{$item->{tool}}{size} = $item->{size};
}
$info{$item->{tool}}{new_tool_num} = $row_num;
$info{$item->{tool}}{new_tool} = 'T'.sprintf("%02s",$row_num);
if( $item->{suffix} =~ /^\((w|s)(\d+)\)$/i || $item->{suffix} =~ /^\(w(\d+)s(\d+)\)$/i){
$info{$item->{tool}}{new_header} = $info{$item->{tool}}{new_tool}.'C'.sprintf("%.3f",$info{$item->{tool}}{size}).$item->{suffix};
}
else{ else{
$mirror = 'No'; $info{$item->{tool}}{new_header} = $info{$item->{tool}}{new_tool}.'C'.sprintf("%.3f",$info{$item->{tool}}{size});
$moved = 'No';
} }
}
##
return \%info;
}
sub input_drill_program{
my %par = @_;
$GEN->COM( "input_manual_reset");
$GEN->COM( "input_manual_set,path=$par{file},job=$Job,step=$Step,format=Excellon2,data_type=ascii,
units=mm,coordinates=absolute,zeroes=none,nf1=3,nf2=3,decimal=no,separator=nl,tool_units=mm,layer=$par{new_layer},wheel=,
wheel_template=,nf_comp=0,multiplier=1,text_line_width=0.0024,signed_coords=no,break_sr=yes,drill_only=no,merge_by_rule=no,threshold=200,resolution=3");
$GEN->COM( "input_manual,script_path=");
$GEN->zoomHome();
return undef;
}
=head
web server数据传输
=cut
sub sec_web_services{
use LWP::UserAgent;
use LWP;
use HTTP::Headers;
use HTTP::Response;
use Encode;
use JSON;
use JSON qw(encode_json);
my $url = shift;
my $data = shift;
my $json = JSON->new->allow_nonref;
my $ua = LWP::UserAgent->new();
$ua->agent("Mozilla/5.0 (Windows NT 6.1; rv:30.0) Gecko/20100101 Firefox/30.0");
my $header = ['Content-Type' => 'application/json; charset=UTF-8'];
my $body = encode('utf8', $json->encode($data));
my $request = HTTP::Request->new('POST', $url, $header, $body);
my $res = $ua->request($request);
#$GUI->debug(-text=>dump($res,'-----------------------------------------------------------------',$res->is_success));
if ($res->is_success) {
return 0;
}else{
return 1;
} }
$report .= '<tr><th>'.$layer.'</th>'.(($moved eq 'Yes')?'<th bgcolor="green">Yes':'<th>No').'</th>'.(($mirror eq 'Yes')?'<th bgcolor="yellow">Yes':'<th>No').'</th></tr>'."\n"; }
=head
3:3 不省零
坐标转换 data=>{x=>,y=>} datum=>{x=>,y=>}
=cut
sub change_coode
{
my %par = @_;
my ($check_x,$check_y);
$par{data}->{x} = $par{data}->{x} - $par{datum}->{x};
$par{data}->{y} = $par{data}->{y} - $par{datum}->{y};
$check_x = $par{data}->{x} > 0 ? '': '-';
$check_y = $par{data}->{y} > 0 ? '': '-';
$par{data}->{x} = sprintf("%0.3f",$par{data}->{x});
$par{data}->{x} = sprintf("%06s",abs($par{data}->{x})*1000);
$par{data}->{y} = sprintf("%0.3f",$par{data}->{y});
$par{data}->{y} = sprintf("%06s",abs($par{data}->{y})*1000);
return 'X'.$check_x.($par{data}->{x}).'Y'.$check_y.($par{data}->{y});
}
=head
坐标转换成数值
=cut
sub change_coode_to_vale
{
my $string = shift;
$string =~ /X(-?\w+)Y(-?\w+)/;
my $x_data = sprintf("%0.3f",$1/1000);
my $y_data = sprintf("%0.3f",$2/1000);
return {x=>$x_data,y=>$y_data};
}
sub _deleteLayer{
my %par = @_;
foreach my $layer(@{$par{layer}}){
$GEN->deleteLayer(layer=>$layer) if ($GEN->isLayerExists(job=>$Job,layer=>$layer));
} }
$GEN->deleteLayer(job=>$Job,layer=>[$tmp_lyr],step=>$step);
$GEN->affectedLayer(mode=>'all',affected=>'no');
$GEN->units( type=>$PAR->{units});
$report .='</table></body></html>';
return $report;
} }
=head
输出层新命名
=cut
sub get_new_layer_name
{
my $job = shift;
my @tmp = split/\-/,$job;
splice(@tmp,2,1);
$tmp[2] =~ s/2//;
unless($tmp[2]){
splice(@tmp,2,1);
}
my $new = join('-',@tmp);
return $new;
}
=head
短槽拉伸值 slot_size=>,slot_length=>
=cut
sub ger_short_slot_vale
{
my %par = @_;
my $info = {
1.5 =>[
{size_min=>0.4,size_max=>0.55,length=>0,angle=>0},
{size_min=>0.6,size_max=>0.65,length=>0.07,angle=>5},
{size_min=>0.7,size_max=>0.75,length=>0.0625,angle=>4},
{size_min=>0.8,size_max=>0.95,length=>0.05,angle=>2.5},
{size_min=>1.0,size_max=>1.25,length=>0.045,angle=>2},
{size_min=>1.3,size_max=>1.6,length=>0.0375,angle=>1},
{size_min=>1.65,size_max=>2.5,length=>0.0375,angle=>1},
{size_min=>2.55,size_max=>999,length=>0.03,angle=>0.5},
],
1.75 =>[
{size_min=>0.4,size_max=>0.55,length=>0.055,angle=>4},
{size_min=>0.6,size_max=>0.65,length=>0.055,angle=>3},
{size_min=>0.7,size_max=>0.75,length=>0.05,angle=>2.5},
{size_min=>0.8,size_max=>0.95,length=>0.045,angle=>2},
{size_min=>1.0,size_max=>1.25,length=>0.0375,angle=>1},
{size_min=>1.3,size_max=>1.6,length=>0.03,angle=>0.5},
{size_min=>1.65,size_max=>2.5,length=>0.03,angle=>0.5},
{size_min=>2.55,size_max=>999,length=>0.025,angle=>0.5},
],
2.0 =>[
{size_min=>0.4,size_max=>0.55,length=>0.045,angle=>3},
{size_min=>0.6,size_max=>0.65,length=>0.0375,angle=>2},
{size_min=>0.7,size_max=>0.75,length=>0.0375,angle=>1.5},
{size_min=>0.8,size_max=>0.95,length=>0.03,angle=>1},
{size_min=>1.0,size_max=>1.25,length=>0.03,angle=>1},
{size_min=>1.3,size_max=>1.6,length=>0.025,angle=>0.5},
{size_min=>1.65,size_max=>2.5,length=>0.02,angle=>0.5},
{size_min=>2.55,size_max=>999,length=>0.02,angle=>0},
],
};
my $type;
if($par{slot_length}/$par{slot_size} <= 1.5){
$type = 1.5;
}elsif($par{slot_length}/$par{slot_size} > 1.5 and $par{slot_length}/$par{slot_size} <= 1.75){
$type = 1.75;
}elsif($par{slot_length}/$par{slot_size} > 1.75 and $par{slot_length}/$par{slot_size} <= 2){
$type = 2.0;
}elsif($par{slot_length}/$par{slot_size} > 2){
return 0;
}
my $result;
foreach my $tmp (@{$info->{$type}}){
if($par{slot_size} >= $tmp->{size_min} and $par{slot_size} <= $tmp->{size_max}){
$result = 1;
return $tmp;
}
}
unless ($result){
return 0;
}
}
__END__ __END__
\ No newline at end of file
=head
NAME: TL_PUB_update_sm_defined_opening
DESCRIPTION: Update soldermask opening which covered by copper or heavy line
PARAMETER:
[
{
name : 'step_filter',
type : 'LineEdit',
title : 'step过滤',
pack : {row:0,column:1},
property:{tool_tip:'选择step时候的过滤器'},
},
{
name : 'drill_layer',
type : 'LineEdit',
title : '外层机械钻孔层',
pack : {row:0,column:1},
property:{tool_tip:''},
},
{
name : 'smd',
title : '处理SMD盘',
type : 'RadioBox',
property : {
size_policy:'Expanding,Fixed',
item_list:[
{name:'Yes',text:'Yes'},
{name:'No',text:'No'},
],
tool_tip:'是否处理SMD盘'
},
pack : {row:1,column:1},
value : 'Yes'
},
{
name : 'bga',
title : '处理BGA盘',
type : 'RadioBox',
property : {
size_policy:'Expanding,Fixed',
item_list:[
{name:'Yes',text:'Yes'},
{name:'No',text:'No'},
],
tool_tip:'是否处理BGA盘'
},
pack : {row:1,column:1},
value : 'Yes'
},
{
name : 'pth',
title : '处理非Via孔的pth孔盘',
type : 'RadioBox',
property : {
size_policy:'Expanding,Fixed',
item_list:[
{name:'Yes',text:'Yes'},
{name:'No',text:'No'},
],
tool_tip:'是否处理PTH所对应的盘'
},
pack : {row:1,column:1},
value : 'No'
},
{
name : 'via',
title : '处理Via孔盘',
type : 'RadioBox',
property : {
size_policy:'Expanding,Fixed',
item_list:[
{name:'Yes',text:'Yes'},
{name:'No',text:'No'},
],
tool_tip:'是否处理Via孔所对应的盘'
},
pack : {row:1,column:1},
value : 'No'
},
{
name : 'pad',
title : '处理其它盘',
type : 'RadioBox',
property : {
size_policy:'Expanding,Fixed',
item_list:[
{name:'Yes',text:'Yes'},
{name:'No',text:'No'},
],
tool_tip:'是否处理除SMD,BGA,和PTH孔对应盘以外的所有pad'
},
pack : {row:1,column:1},
value : 'No'
},
{
name : 'include_pad',
title : '附近无开窗pad当大铜面',
type : 'RadioBox',
property : {
size_policy:'Expanding,Fixed',
item_list:[
{name:'Yes',text:'Yes'},
{name:'No',text:'No'},
],
tool_tip:'附近无开窗pad当大铜面'
},
pack : {row:1,column:1},
value : 'No'
},
{
name : 'ignore_bgasmd',
title : '允许smdbga上的盘制作',
type : 'RadioBox',
property : {
size_policy:'Expanding,Fixed',
item_list:[
{name:'Yes',text:'Yes'},
{name:'No',text:'No'},
],
tool_tip:'除SMD,BGA外的盘在做完bga和smd后任运行制作'
},
pack : {row:1,column:1},
value : 'No'
},
{
name : 'make_sm_less_pad',
title : '自动优化防焊ON PAD',
type : 'RadioBox',
property : {
size_policy:'Expanding,Fixed',
item_list:[
{name:'Yes',text:'Yes'},
{name:'No',text:'No'},
],
tool_tip:'默认参数为铜面上单边开窗(mil)大小'
},
pack : {row:1,column:1},
value : 'No'
},
{
name : 'delete_samll_area',
title : '允许删除小面积开窗',
type : 'RadioBox',
property : {
size_policy:'Expanding,Fixed',
item_list:[
{name:'Yes',text:'Yes'},
{name:'No',text:'No'},
],
tool_tip:'允许删除小面积开窗'
},
pack : {row:1,column:1},
value : 'No'
},
{
name : 'small_area_open',
type : 'LineEdit',
title : '认为是小面积开窗的面积',
pack : {row:0,column:1},
units:'mil',
property:{tool_tip:'认为是小面积开窗的面积大小,默认0.01'},
value : 10
},
{
name : 'smd_line',
type : 'LineEdit',
title : 'SMD认为是铜面的最小线',
pack : {row:0,column:1},
units:'mil',
property:{tool_tip:'SMD认为是铜面的最小线'},
value : 10
},
{
name : 'bga_line',
type : 'LineEdit',
title : 'BGA认为是铜面的最小线',
pack : {row:0,column:1},
units:'mil',
property:{tool_tip:'BGA认为是铜面的最小线'},
value : 5
},
{
name : 'coverage',
type : 'LineEdit',
title : '最小Coverage(去除Coverage Tol)',
pack : {row:0,column:1},
units:'mil',
property:{tool_tip:'最小Coverage'},
value : 2
},
{
name : 'coverage_tol',
type : 'LineEdit',
title : 'Coverage Tol',
pack : {row:0,column:1},
units:'mil',
property:{tool_tip:'主要用于铜面比线路pad稍微大一点时,忽略宽度的值,会纳入最小Coverage计算'},
value : 2
},
{
name : 'bga_copperopen',
type : 'LineEdit',
title : 'BGA铜面上单边开窗',
pack : {row:0,column:1},
units:'mil',
property:{tool_tip:'BGA铜面上单边开窗'},
value : 0.5
},
{
name : 'spec_bga_copperopen',
type : 'LineEdit',
title : '特殊BGA铜面上单边开窗',
pack : {row:0,column:1},
units:'mil',
property:{tool_tip:'特殊BGA铜面上单边开窗'},
value : 0.5
},
{
name : 'smd_copperopen',
type : 'LineEdit',
title : 'SMD铜面上单边开窗',
pack : {row:0,column:1},
units:'mil',
property:{tool_tip:'SMD铜面上单边开窗'},
value : 0.5
},
{
name : 'pth_copperopen',
type : 'LineEdit',
title : 'PTH孔盘铜面上单边开窗',
pack : {row:0,column:1},
units:'mil',
property:{tool_tip:'PTH孔盘铜面上单边开窗'},
value : 0.5
},
{
name : 'via_copperopen',
type : 'LineEdit',
title : 'VIA孔盘铜面上单边开窗',
pack : {row:0,column:1},
units:'mil',
property:{tool_tip:'VIA孔盘铜面上单边开窗'},
value : 0.5
},
{
name : 'pad_copperopen',
type : 'LineEdit',
title : '其他PAD铜面上单边开窗',
pack : {row:0,column:1},
units:'mil',
property:{tool_tip:'其他PAD铜面上单边开窗'},
value : 0.5
},
{
name : 'opt_open',
type : 'LineEdit',
title : '正常最优单边开窗',
pack : {row:0,column:1},
units:'mil',
property:{tool_tip:'正常最优单边开窗'},
value : 1.5
},
{
name : 'update_max_opening',
type : 'LineEdit',
title : '允许优化的单边最大开窗',
pack : {row:0,column:1},
units:'mil',
property:{tool_tip:'pad单边放大这个值后,开窗在里面的才优化'},
value : 3
},
{
name : 'keep_gasket',
type : 'RadioBox',
title : '是否保证Gasket',
property : {
tool_tip:'是否保证开窗下面的垫圈',
size_policy:'Expanding,Fixed',
item_list:[
{name:'Yes',text:'Yes'},
{name:'No',text:'No'}
]
},
pack : {row:0,column:2},
value:'No'
},
{
name : 'gasket_size',
type : 'LineEdit',
title : '开窗gasket最小',
pack : {row:0,column:1},
units:'mil',
property:{tool_tip:'为了保证完全落于铜面的开窗大小,对于靠在边上的下面加垫圈'},
value:1.5
},
{
name : 'bga_attr',
type : 'LineEdit',
title : '定义为BGA Pad的属性名字',
pack : {row:0,column:1},
units:'mil',
property:{tool_tip:'定义BGA的属性名字'},
value:'.bga'
},
{
name : 'smd_attr',
type : 'LineEdit',
title : '定义为SMD Pad的属性名字',
pack : {row:0,column:1},
units:'mil',
property:{tool_tip:'定义SMD的属性名字'},
value:'.smd'
},
{
name : 'ignore_attr',
type : 'LineEdit',
title : 'SM忽略处理开窗的属性名字',
pack : {row:0,column:1},
units:'mil',
property:{tool_tip:'定义需要被忽略处理的开窗所加属性名字'},
value:'.ignore_action'
},
{
name : 'include_teardrop',
type : 'RadioBox',
title : '大铜面包含.tear_drop',
property : {
tool_tip:'碰到大铜面或者粗线的.tear_drop是否也当成大铜面处理',
size_policy:'Expanding,Fixed',
item_list:[
{name:'Yes',text:'Yes'},
{name:'No',text:'No'},
{name:'Manual',text:'Manual'},
]
},
pack : {row:0,column:2},
value:'No'
},
{
name : 'laser_pad_attr',
type : 'LineEdit',
title : '镭射Pad属性',
pack : {row:0,column:1},
units:'mil',
property:{tool_tip:'定义Laser Pad的属性名字'},
value:''
},
{
name : 'ignore_attr_comp',
type : 'RadioBox',
title : '补偿有属性的忽略开窗',
property : {
tool_tip:'对定义属性的开窗,是否进行铜面补偿',
size_policy:'Expanding,Fixed',
item_list:[
{name:'Yes',text:'Yes'},
{name:'No',text:'No'}
]
},
pack : {row:0,column:2},
value:'No'
},
{
name : 'specifical_opening_suffix',
type : 'LineEdit',
title : '特殊情况报警层后缀',
pack : {row:0,column:1},
units:'mil',
property:{tool_tip:'定义特殊的开窗不能处理,报警层后缀名'},
value:''
},
{
name : 'backup_suffix',
type : 'LineEdit',
title : '备份层后缀',
pack : {row:0,column:1},
units:'mil',
property:{tool_tip:'定义备份层后缀名'},
value:'._tl+++'
},
{
name : 'is_select_lyr',
title : '选择层别',
type : 'RadioBox',
property : {
size_policy:'Expanding,Fixed',
item_list:[
{name:'Yes',text:'Yes'},
{name:'No',text:'No'},
],
tool_tip:'未设定,默认为yes'
},
pack : {row:1,column:1},
value : 'Yes'
},
]
VERSION_HISTORY:
V1.00 2011-03-28 Jacket Wu
Release first version according to request
V1.10 2011-06-01 Jacket Wu
增加了补偿值对忽略的属性,并有参数可以定义
V1.20 2011-06-03 Jacket Wu
修正bug,对于特殊属性补偿,系统运行根据需要做的情况有好几次,目前改为一次
V1.30 2012-01-10 Jacket Wu
最优窗口支持不同pad size有不同的值,可以定义为如下的一个结构或者一个值
[{min=>0,max=>10,cmp=>2.5},{min=>10,max=>10000,cmp=>2},{type=>'others',cmp=>2}]
V1.40 2012-01-17 Jacket Wu
调整料号选择,可以支持几个料号名字优先排列
V1.50 2012-01-19 Jacket Wu
添加备份层后缀名参数
V1.51 2012-02-02 Jacket Wu
更改开窗大小的时候pad从大到小改
V1.52 2012-02-16 Jacket Wu
对于需要shave的地方,如果在sm层碰到surface就去掉
V1.60 2013-07-09 Jacket Wu
分开不同类型pad可以设定不同的铜面开窗大小
V1.70 2015-04-16 Jacket Wu
1. 修正整个负数据覆盖pad及部分pad 不应该处理也处理的情况
2. 增加允许对单边开窗用负的数据,就是开窗比pad小
V1.71 2015-04-21 Jacket Wu
1.分开标准pth孔与via孔可以设定不同的铜面开窗大小
2.优化执行效率
V1.72 2015-04-24 Sting Chen
1.优化转换铜面参数
V1.73 2016-11-21 Cody Yu
1.脚本参数转换为c++格式
V1.74 2016-12-09 Cody Yu
1.铜面上的开窗,在参数确认界面上自动缩小补偿值
V1.75 2018-05-02 Shyer Wang
1.去除2018-3-23更改逻辑
2.修复铜面重复pad不做优化的问题
V1.76 2018-05-11 Shyer Wang
1.更改界面默认参数
2.取消pad碰到钻孔不做sm_defined的逻辑
3.增加附近无开窗pad当大铜面参数设置
4.增加允许smdbga上的盘再次制作sm_defined的参数设置
V1.77 2018-05-15 Shyer Wang
1.去除普通pad碰到pth孔
V1.78 2018-05-16 Shyer Wang
1.开窗层过滤掉负性物件制作
2.via负性和sm_defined合并
V1.79 2018-05-17 Shyer Wang
1.增加脚本参数控制是否清除小面积开窗
2.增加脚本参数设置清除小面积开窗的面积
V1.80 2018-05-19 Shyer Wang
1.优化尖角
2.优化负属性物件制作逻辑
V1.81 2018-05-29 Shyer Wang
1.on pad制作增加脚本参数控制
2.修复负片层确实问题
V1.82 2018-06-04 Shyer Wang
1.优化负片逻辑
2.大铜面碰到的pad选择逻辑变更
V1.83 2018-06-04 Shyer Wang
1.优化增加泪滴逻辑
2.增加特殊bga参数‘tl_spec_bga’
V1.84 2018-08-07 Shyer Wang
1.增加coverage 公差,用于支持线与smd等等大情况的
V1.85 2018-08-15 Shyer Wang
1.前台界面增加是否忽略泪滴的脚本参数
V1.86 2018-09-25 Alan
1.修复via盘参数选择no,还处理的bug
HELP:
<html><body bgcolor="#DDECFE">
<font size="3" color="#003DB2"><p>功能简介</p><br></font>
<p>分开处理在铜面上的Pad开窗和正常没有铜面开窗</p><br>
<br>
<font size="3" color="#003DB2"><p>参数配置</p><br></font>
<font color="#008000"><p> ● 料号名</p><br></font>
<p> 设置genesis中料号的名字,${JOB}表示跟TopCAM中的料号名字一样,TL_genesis_work_jobname表示用这个料号属性定义的名字</p><br>
<font color="#008000"><p> ● step过滤</p><br></font>
<p> 选择step时候的过滤器</p><br>
<font color="#008000"><p> ● 外层机械钻孔层</p><br></font>
<p> 定义外层机械钻孔层得固定名字</p><br>
<font color="#008000"><p> ● 处理SMD盘</p><br></font>
<p> 定义缺省的是否处理SMD pad</p><br>
<font color="#008000"><p> ● 处理BGA盘</p><br></font>
<p> 定义缺省的是否处理BGA pad</p><br>
<font color="#008000"><p> ● 处理pth 孔盘</p><br></font>
<p> 定义缺省的是否处理非via孔的PTH孔所对应的盘</p><br>
<font color="#008000"><p> ● 处理via 孔盘</p><br></font>
<p> 定义缺省的是否处理via孔所对应的盘</p><br>
<font color="#008000"><p> ● 处理其它盘</p><br></font>
<p> 定义缺省的是否处理除SMD,BGA,PTH和Via孔对应盘以外的所有pad</p><br>
<font color="#008000"><p> ● SMD认为是铜面的最小线</p><br></font>
<p> 对于非BGA盘对应的线,需要当作铜面处理的最小线宽。也就是大于等于这个线宽的线并且跟盘相连,将当铜面处理</p><br>
<font color="#008000"><p> ● BGA认为是铜面的最小线</p><br></font>
<p> 对于BGA盘对应的线,需要当作铜面处理的最小线宽。也就是大于等于这个线宽的线并且是跟BGA相连,将当铜面处理</p><br>
<font color="#008000"><p> ● 最小Coverage</p><br></font>
<p> 定义缺省开窗到线或需要用绿油盖起来的元素的最小安全距离</p><br>
<font color="#008000"><p> ● 铜面上单边开窗</p><br></font>
<p> pad落于大铜面上的开窗的大小要求,指的是单面的</p><br>
<font color="#008000"><p> ● 正常最优单边开窗</p><br></font>
<p> 没有落于大铜面的最优开窗大小,指的是单边的</p><br>
<font color="#008000"><p> ● 允许优化的单边最大开窗</p><br></font>
<p> 定义允许进行优化操作的最大单边开窗,如果开窗超过这个值,将不进行优化</p><br>
<font color="#008000"><p> ● 是否保证Gasket</p><br></font>
<p> 定义对开窗正好在大铜面边上,并且都落于大铜面上,是否要在外层加个垫圈,以防治开窗制作公差引起铜面变小</p><br>
<font color="#008000"><p> ● 开窗gasket最小</p><br></font>
<p> 在需要保证gastet的情况下,铜面必须比开窗单边大的尺寸要求</p><br>
<font color="#008000"><p> ● 定义为BGA Pad的属性名字</p><br></font>
<p> BGA pad所加的属性名字</p><br>
<font color="#008000"><p> ● 定义为SMD Pad的属性名字</p><br></font>
<p> SMD pad所加的属性名字</p><br>
<font color="#008000"><p> ● SM忽略处理开窗的属性名字</p><br></font>
<p> 定义需要被忽略处理的属性名字,这个属性名字是加在 solder mask层上的</p><br>
<font color="#008000"><p> ● 大铜面包含.tear_drop</p><br></font>
<p> 定义碰到大铜面或者粗线的.tear_drop是否也当成大铜面处理</p><br>
<font color="#008000"><p> ● 镭射Pad属性</p><br></font>
<p> 定义laser pad属性名字,如果定义了laser pad,系统将把laser pad过滤掉来处理</p><br>
<font color="#008000"><p> ● 补偿有属性的忽略开窗</p><br></font>
<p> 对于定义需要被忽略处理的开窗,是否需要做大铜面补偿值</p><br>
<font size="3" color="#003DB2"><p>注意事项</p><br></font>
<p> ● 在solder mask层上面是surface的将不被优化</p><br>
<p> ● 如果一个开窗下面对应有超过并等于2个盘得情况也将不做处理</p><br>
<p> ● 对于开窗形状和pad形状不是相同的情况下也将过滤不处理</p><br>
<br>
</body></html>
=cut
use strict;
#my ($JOB,$GEN,$GUI,$DB,$JOB_ID,$PAR);
#####使用时间控制
#my $year = (localtime())[5] + 1900;
#my $mon = (localtime())[4];
#if ( $year > 2012 or ($year == 2012 and $mon > 12) ) {
# $GUI->msgbox(-text=>"License is out of date! Please check with TopLinker!");
# return;
#}
use utf8;
use Encode;
use Data::Dump qw/dump/;
my $Return = 'Done';
my ($Job,$Step) = ($JOB,undef);
###处理step过滤
$PAR->{step_filter} = $PAR->{step_filter} ? $PAR->{step_filter} : '.*';
$PAR->{is_select_lyr} = 'yes' unless $PAR->{is_select_lyr};
my $DrillLayer = $PAR->{drill_layer};
my $MinSMDCopperLine = $PAR->{smd_line};
my $MinBGACopperLine = $PAR->{bga_line};
my $Coverage = $PAR->{coverage};
my $CoverageTol = $PAR->{coverage_tol};
my $BGACopperOpening = $PAR->{bga_copperopen};
my $SpecBGACopperOpening = $PAR->{spec_bga_copperopen};
my $SMDCopperOpening = $PAR->{smd_copperopen};
my $PTHCopperOpening = $PAR->{pth_copperopen};
my $VIACopperOpening = $PAR->{via_copperopen};
my $PADCopperOpening = $PAR->{pad_copperopen};
my $CopperOpening;
my $OptOpening = $PAR->{opt_open};
my $UpdateMaxOpening = $PAR->{update_max_opening};
my $GasketSize = $PAR->{gasket_size};
my $DoSMD = $PAR->{smd};
my $DoPTH = $PAR->{pth};
my $DoVIA = $PAR->{via};
my $DoBGA = $PAR->{bga};
my $DoPAD = $PAR->{pad};
my $KeepGasket = $PAR->{keep_gasket};
my $IgnoreAttr = $PAR->{ignore_attr} || '';
my $IncludeTearDrop = $PAR->{include_teardrop};
my $IncludePad = $PAR->{include_pad}|| 'No';
my $InIgnoreSmdBga = $PAR->{ignore_bgasmd}|| 'No';
my $DeleteSamllArea = $PAR->{delete_samll_area}||'No';
my $SmallAreaOpen = $PAR->{small_area_open}||'0.01';
my $AttrHash = {bga=>$PAR->{bga_attr},smd=>$PAR->{smd_attr}};
my $LaserPadAttr = $PAR->{laser_pad_attr} || '';
my $SpecificalWarningSuffix = $PAR->{specifical_opening_suffix} || '';
my $BakSuffix = $PAR->{backup_suffix} || '+++';
$PAR->{is_select_lyr} = 'Yes' unless $PAR->{is_select_lyr};
my %TmpLayer = (
tmp_layer => 'tl_script_tmp_layer', ###临时中间使用的层
big_copper_layer => 'tl_script_tmp_layer1', ###铜面和粗线
pad_touch_copper => 'tl_script_tmp_layer2', ###碰到 big_copper_layer 的所有盘
pad_opening => 'tl_script_tmp_layer3', ###pad_touch_copper 盘所对应的开窗
sm_opening => 'tl_script_tmp_layer31', ###solder mask 层所有东西复制到这里并做contourize
org_pad_opening => 'tl_script_tmp_layer4', ###pad_touch_copper 盘所对应的原稿开窗
opt_big_copper => 'tl_script_tmp_layer5', ####优化铜面和粗线,来制作缺口和coverage
correct_sm_opening => 'tl_script_tmp_layer6', ####制作准确的开窗
sm_opening_free => 'tl_script_tmp_layer7', ####制作开窗要的负片层
npth_layer=> 'tl_script_tmp_layer8', ####npth drill layer
sm_less_pad => 'tl_script_tmp_layer9', ####开窗比盘小 (有一边小就算)
pad_on_copper_gasket => 'tl_script_tmp_layer10', ####开窗比盘小 (有一边小就算)
remove_specifical_sm => 'tl_script_tmp_layer11', ####特殊开窗不处理
all_pad_with_attr => 'tl_script_tmp_layer12', ####符合条件的所有pad
sliver_layer => 'tl_script_tmp_layer13', ####需要优化掉的小细丝层
smd_bga_pad => 'tl_script_tmp_layer15', ####smd bga attribute pad
via_drill_layer => 'tl_script_tmp_layer16', ####via drill layer
samll_area_layer=>'tl_script_tmp_layer17', #####制作去除小面积开窗层
sm_defined_tmp_layer=>'tl_script_tmp_layer18', #####临时sm defined层
);
try{
###Check genesis job name exist or not
unless ( $Job and $GEN->isJobExists(job=>$Job) ){
$Job = $GUI->select_job(
-title=>'请选择料号',
-joblist=>[$GEN->getJobList()]
);
return 'Cancel' if (! defined $Job or (defined $Job and $Job eq ''));
}
###open Job
$GEN->openJob(job=>$Job) unless ($GEN->isJobOpen(job=>$Job));
###check and get work Step name
my @steps = $GEN->getStepList(job=>$Job);
if ( @steps == 0 ) {
$GUI->msgbox(-icon=>'error',-text=>'在料号中没有Step存在,你将退出!');
return 'Cancel';
}
elsif (@steps != 1){
my @tmp_steps = grep(/$PAR->{step_filter}/,@steps);
if ( @tmp_steps == 0 ) {
$GUI->msgbox(-icon=>'warning',-text=>'根据脚本参数过滤出来的step不存在,请检查资料或者脚本参数配置!');
return 'Cancel';
}
elsif ( @tmp_steps == 1 ) {
$Step = $tmp_steps[0];
}
else {
$Step = $GUI->select_step(-title=>'请选择工作Step',
-steplist=>[@tmp_steps],
-selectmode=>'single');
return 'Cancel' unless ($Step);
}
}
else {
$Step = $steps[0];
}
###Open step and clear layer
$GEN->openStep(job=>$Job,name=>$Step);
$GEN->COM("disp_off");
$GEN->clearLayers();
$GEN->affectedLayer(mode=>'all',affected=>'no');
$GEN->units(type=>'inch');
####选择SM层,并寻找对应的外层
my %matrix=$GEN->getMatrix(job=>$Job,type=>'hash');
#my @smlayer = $GUI->select_layer(-title=>'Please select solder mask layer to opt Defined pad',
# -layermatrix=>\%matrix);
#return 'Cancel' unless ( @smlayer );
my $layers = select_work_layer();
return $layers if $layers eq 'Cancel';
my @smlayer = @{$layers};
my %smout;
foreach my $item ( @smlayer ) {
if ( $matrix{$item}{side} eq 'top' ) {
foreach my $layer (keys %matrix) {
if ( $matrix{$layer}{tl_name} eq 'top' ) {
$smout{$item} = $layer;
last;
}
}
}
elsif ( $matrix{$item}{side} eq 'bottom' ) {
foreach my $layer (keys %matrix) {
if ( $matrix{$layer}{tl_name} eq 'bottom' ) {
$smout{$item} = $layer;
last;
}
}
}
}
#####确认外层名字
my $tmp;
my $tmplayerhash;
foreach my $item (keys %matrix) {
push(@$tmplayerhash,{name=>$item});
}
foreach my $item (@smlayer) {
push(@$tmp,
{
name=>$item,
label=>$item,
type=>'enum',
property=>{
tl_field=>[name=>'text'],
tl_value_field=>'name',
tl_data=>$tmplayerhash
},
must_field=>1,
value => $smout{$item} || ''
}
);
}
if ( ! $GEN->isLayerExists(job=>$Job,layer=>$DrillLayer) ) {
push(@$tmp,
{
name=>'drill',
label=>'Drill Layer',
type=>'enum',
property=>{
tl_field=>[name=>'text'],
tl_value_field=>'name',
tl_data=>$tmplayerhash
},
must_field=>1,
value => $DrillLayer
}
);
}
my %tmp = $GUI->show_form(
-title => 'Set Outer Layer of defined SM Layer',
-items => $tmp
);
return 'Cancel' unless %tmp;
if ( $tmp{drill} ) {
$DrillLayer = delete $tmp{drill};
}
###获取补偿值
#my $out_comp = $IKM->get_jobinfo(-jobid=>$JOB_ID,-jobcategory=>'work',-jobinfo=>'outer_comp_value');
#my $bga_comp = $out_comp;
#if( $out_comp ){
# my $customer_code = $IKM->select_value(-table=>'pdm_job',-field=>'customer_code',-where=>{id=>$JOB_ID});
# if( $customer_code =~ /(1812|1861)/ ){
# $bga_comp += 1;
# }
# else{
# $bga_comp += 0.5;
# }
#}
#$out_comp = $out_comp/2 - 0.5;
#$bga_comp = $bga_comp/2 - 0.5;
#####confirm parameter
my $info = [
{
name=>'smd',
label=>'处理SMD',
type=>'enum',
property=>{
tl_field=>[name=>'scalar',display_name=>'text'],
tl_value_field=>'name',
tl_data=>[
{name=>'Yes',display_name=>'Yes'},
{name=>'No',display_name=>'No'}
]
},
must_field=>1,
remark=>'是否处理SMD',
value => $PAR->{smd},
},
{
name=>'bga',
label=>'处理BGA',
type=>'enum',
property=>{
tl_field=>[name=>'scalar',display_name=>'text'],
tl_value_field=>'name',
tl_data=>[
{name=>'Yes',display_name=>'Yes'},
{name=>'No',display_name=>'No'}
]
},
must_field=>1,
remark=>'是否处理BGA',
value => $PAR->{bga},
},
{
name=>'pth',
label=>'处理pth 孔盘',
type=>'enum',
property=>{
tl_field=>[name=>'scalar',display_name=>'text'],
tl_value_field=>'name',
tl_data=>[
{name=>'Yes',display_name=>'Yes'},
{name=>'No',display_name=>'No'}
]
},
must_field=>1,
remark=>'是否处理PTH所对应的盘',
value => $PAR->{pth},
},
{
name=>'via',
label=>'处理via 孔盘',
type=>'enum',
property=>{
tl_field=>[name=>'scalar',display_name=>'text'],
tl_value_field=>'name',
tl_data=>[
{name=>'Yes',display_name=>'Yes'},
{name=>'No',display_name=>'No'}
]
},
must_field=>1,
remark=>'是否处理VIA所对应的盘',
value => $PAR->{via},
},
{
name=>'pad',
label=>'处理其它盘',
type=>'enum',
property=>{
tl_field=>[name=>'scalar',display_name=>'text'],
tl_value_field=>'name',
tl_data=>[
{name=>'Yes',display_name=>'Yes'},
{name=>'No',display_name=>'No'}
]
},
must_field=>1,
remark=>'是否处理除SMD,BGA,PTH孔对应盘以外的所有pad',
value => $PAR->{pad},
},
{
name=>'smd_line',
label=>'SMD认为是铜面的最小线(mil)',
type=>'string',
must_field=>1,
remark=>'',
value => $PAR->{smd_line},
},
{
name=>'bga_line',
label=>'BGA认为是铜面的最小线(mil)',
type=>'string',
must_field=>1,
remark=>'',
value => $PAR->{bga_line},
},
{
name=>'coverage',
label=>'最小Coverage(mil)',
type=>'string',
must_field=>1,
remark=>'需去除Coverage Tol',
value => $PAR->{coverage},
},
{
name=>'coverage_tol',
label=>'Coverage Tol(mil)',
type=>'string',
must_field=>1,
remark=>'主要用于铜面比线路pad稍微大一点时,忽略宽度的值,会纳入最小Coverage计算',
value => $PAR->{coverage_tol},
},
{
name=>'bga_copperopen',
label=>'BGA铜面上单边开窗(mil)',
type=>'string',
must_field=>1,
remark=>'',
value => $PAR->{bga_copperopen},
},
{
name=>'spec_bga_copperopen',
label=>'特殊BGA铜面上单边开窗(mil)',
type=>'string',
must_field=>1,
remark=>'',
value => $PAR->{spec_bga_copperopen},
},
{
name=>'smd_copperopen',
label=>'SMD铜面上单边开窗(mil)',
type=>'string',
must_field=>1,
remark=>'',
value => $PAR->{smd_copperopen},
},
{
name=>'pth_copperopen',
label=>'PTH盘铜面上单边开窗(mil)',
type=>'string',
must_field=>1,
remark=>'',
value => $PAR->{pth_copperopen},
},
{
name=>'via_copperopen',
label=>'VIA盘铜面上单边开窗(mil)',
type=>'string',
must_field=>1,
remark=>'',
value => $PAR->{via_copperopen},
},
{
name=>'pad_copperopen',
label=>'其他盘铜面上单边开窗(mil)',
type=>'string',
must_field=>1,
remark=>'',
value => $PAR->{pad_copperopen},
},
{
name=>'opt_open',
label=>'正常最优单边开窗(mil)',
type=>'string',
must_field=>1,
remark=>'',
value => $PAR->{opt_open},
},
{
name=>'update_max_opening',
label=>'允许优化的单边最大开窗(mil)',
type=>'string',
must_field=>1,
remark=>'pad单边放大这个值后,开窗在里面的才优化',
value => $PAR->{update_max_opening},
},
{
name=>'include_teardrop',
label=>'大铜面包含.tear_drop',
type=>'enum',
property=>{
tl_field=>[name=>'scalar',display_name=>'text'],
tl_value_field=>'name',
tl_data=>[
{name=>'Yes',display_name=>'Yes'},
{name=>'No',display_name=>'No'}
]
},
must_field=>1,
remark=>'碰到大铜面或者粗线的.tear_drop是否也当成大铜面处理',
value => $PAR->{include_teardrop},
},
{
name=>'keep_gasket',
label=>'是否保证Gasket',
type=>'enum',
property=>{
tl_field=>[name=>'scalar',display_name=>'text'],
tl_value_field=>'name',
tl_data=>[
{name=>'Yes',display_name=>'Yes'},
{name=>'No',display_name=>'No'}
]
},
must_field=>1,
remark=>'是否保证开窗下面的垫圈',
value => $PAR->{keep_gasket},
},
{
name=>'gasket_size',
label=>'开窗gasket最小(mil)',
type=>'string',
must_field=>1,
remark=>'为了保证完全落于铜面的开窗大小,对于靠在边上的下面加垫圈',
value => $PAR->{gasket_size},
},
];
my %info = $GUI->show_form(
-title=>'请设置缩铜面Pad参数',
-items=>$info);
return 'Cancel' unless %info;
$MinSMDCopperLine = $info{smd_line};
$MinBGACopperLine = $info{bga_line};
$Coverage = $info{coverage};
$CoverageTol = $info{coverage_tol};
$BGACopperOpening = $info{bga_copperopen};
$SMDCopperOpening = $info{smd_copperopen};
$PTHCopperOpening = $info{pth_copperopen};
$VIACopperOpening = $info{via_copperopen};
$PADCopperOpening = $info{pad_copperopen};
$OptOpening = eval($info{opt_open});
$GasketSize = $info{gasket_size};
$DoSMD = $info{smd};
$DoBGA = $info{bga};
$DoPTH = $info{pth};
$DoVIA = $info{via};
$DoPAD = $info{pad};
$IncludeTearDrop = $info{include_teardrop};
$KeepGasket = $info{keep_gasket};
$UpdateMaxOpening = $info{update_max_opening};
%tmp = reverse %tmp;
foreach my $layer (keys %tmp) {
my $ref_layer = $tmp{$layer}.'_ref';
if ( $GEN->isLayerExists(job=>$Job,layer=>$ref_layer) ) {
$GEN->workLayer(name=>$ref_layer,number=>1);
$GEN->selDelete();
}
else {
$GEN->createLayer(job=>$Job,layer=>$ref_layer);
}
$GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$tmp{$layer},dest_layer=>$tmp{$layer}.$BakSuffix);
$GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$layer,dest_layer=>$layer.$BakSuffix);
$GEN->workLayer(name=>$tmp{$layer},number=>1);
$GEN->selectByFilter(attribute=>[{attribute=>'.string',text=>'sm_defined_pad_shave'}]);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
##移除via
$GEN->selectByFilter(attribute=>[{attribute=>'.drill',option=>'via'}],polarity=>'positive');
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
my $sm_tmp_bk = $tmp{$layer}.'_tl_script_bk';
$GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$tmp{$layer},dest_layer=>$sm_tmp_bk);
#$GEN->selectByFilter(attribute=>[{attribute=>'.shave'}]);
$GEN->selectByFilter(polarity=>'negative');
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
$GEN->workLayer(name=>$layer,number=>1);
$GEN->selectByFilter(attribute=>[{attribute=>'.string',text=>'smdef_gasket'}]);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
_deleteLayer(layer=>[$tmp{$layer}.$SpecificalWarningSuffix]);
foreach my $item ('smd','bga','pth','via','pad') {#'smd','bga','pth','via','pad'
next unless ( defined $info{$item} and $info{$item} eq 'Yes' );
my $Coverage_tmp = $Coverage;
my $CoverageTol_tmp = $CoverageTol;
if ( $item eq 'smd' or $item eq 'bga' ) {
next unless ( $AttrHash->{$item} );
}
_deleteLayer(layer=>[values %TmpLayer]);
if ( $item eq 'smd' ) {
$CopperOpening = $SMDCopperOpening;
}
elsif ( $item eq 'bga' ) {
$CopperOpening = $BGACopperOpening;
}
elsif ( $item eq 'pth' ) {
$CopperOpening = $PTHCopperOpening;
}
elsif ( $item eq 'via' ) {
$CopperOpening = $VIACopperOpening;
}
elsif ( $item eq 'pad' ) {
$CopperOpening = $PADCopperOpening;
}
####制作npth and via drill layer
$GEN->createLayer(job=>$Job,layer=>$TmpLayer{npth_layer});
$GEN->workLayer(name=>$DrillLayer,number=>1);
$GEN->selectByFilter(attribute=>[{attribute=>'.drill',option=>'non_plated'}]);
if ( $GEN->getSelectCount() > 0 ) {
$GEN->selCopyOther(target_layer=>$TmpLayer{npth_layer});
}
$GEN->selectByFilter(attribute=>[{attribute=>'.drill',option=>'via'}]);
if ( $GEN->getSelectCount() > 0 ) {
$GEN->selCopyOther(target_layer=>$TmpLayer{via_drill_layer});
}
####制作铜面和粗线层(有碰到的.tear_drop也包括) 到辅助层 big_copper_layer
$GEN->workLayer(name=>$layer,number=>1);
$GEN->selectByFilter(feat_types=>'surface');
$GEN->selectByFilter(polarity=>'negative');
my $tmp_line = $MinSMDCopperLine;
if ( $item eq 'bga' ) {
$tmp_line = $MinBGACopperLine;
}
my %symhist = $GEN->getLayerSymsHist(job=>$Job,step=>$Step,layer=>$layer);
foreach my $sym (keys %symhist) {
if ( $sym =~ /^(r|s)[0-9]+\.?[0-9]*$/ and $symhist{$sym}{size} >= $tmp_line ) {
$GEN->selectByFilter(include_syms=>$sym,
feat_types=>'line\;arc',
polarity=>'positive');
}
}
if ( $IncludeTearDrop eq 'No' ) {
$GEN->selectByFilter(
attribute=>'.tear_drop',
operation=>'unselect'
);
}
if ( $GEN->getSelectCount() > 0 ) {
$GEN->selCopyOther(target_layer=>$TmpLayer{big_copper_layer});
}
else {
next;
}
if ( $IncludeTearDrop eq 'Yes' ) {
$GEN->selRefFeat(
layers=>$TmpLayer{big_copper_layer},
use=>'filter',
mode=>'touch',
f_types=>'line\;arc',
polarity=>'positive',
filter=>{
filter_name => 'popup',
attribute=>[{attribute=>'.tear_drop'}],
}
);
if ( $GEN->getSelectCount() > 0 ) {
$GEN->selCopyOther(target_layer=>$TmpLayer{big_copper_layer});
}
}
if( $IncludePad eq 'Yes' ){
$GEN->attributeReset();
$GEN->COM('filter_reset',filter_name=>'popup');
$GEN->selRefFeat(
layers=>$TmpLayer{big_copper_layer},
use=>'filter',
mode=>'touch',
f_types=>'line\;arc',
polarity=>'positive',
filter=>{
filter_name => 'popup',
feat_types=>'pad',
polarity=>'positive',
}
);
if ( $GEN->getSelectCount() > 0 ) {
my $include_pad_lyr = '__include_pad_lyr__tl_script__';
$GEN->createLayer(job=>$Job,layer=>$include_pad_lyr,conext=>'misc',type=>'document',delete_exists =>'yes');
$GEN->selCopyOther(target_layer=>$include_pad_lyr);
$GEN->workLayer(name=>$include_pad_lyr,number=>1);
$GEN->attributeReset();
$GEN->COM('filter_reset',filter_name=>'popup');
$GEN->selRefFeat(
layers=>$tmp{$layer},
use=>'filter',
mode=>'disjoint'
);
$GEN->selRefFeat(
layers=>$tmp{$layer},
use=>'filter',
mode=>'cover'
);
$GEN->selRefFeat(
layers=>$tmp{$layer},
use=>'filter',
mode=>'include'
);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
$GEN->workLayer(name=>$include_pad_lyr,number=>1);
$GEN->COM("sel_all_feat");
if ( $GEN->getSelectCount() > 0 ){
$GEN->selCopyOther(target_layer=>$TmpLayer{big_copper_layer});
$GEN->workLayer(name=>$layer,number=>1);
$GEN->selectByFilter(polarity=>'negative');
$GEN->selCopyOther(target_layer=>$TmpLayer{big_copper_layer}) if ( $GEN->getSelectCount() > 0 );
}
_deleteLayer(layer=>[$include_pad_lyr]);
}
}
$GEN->workLayer(name=>$TmpLayer{big_copper_layer},number=>1);
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
$GEN->selectByFilter();
if ( $GEN->getSelectCount() == 1 ) {
$GEN->COM('sel_decompose',overlap=>'yes');
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
}
else {
$GEN->selClearFeature();
}
#####选择有碰到大铜面的盘到临时层 pad_touch_copper
#####如果是pth会去除smd和bga
#####如果是smd会去除bga
my $tmp_work_layer = $layer.'_tmp_script__';
$GEN->copyLayer(source_job=>$Job,
source_step=>$Step,
source_layer=>$layer,
dest_layer=>$tmp_work_layer,
mode=>'replace', #append/replace
invert=>'no') ;#|'yes'
$GEN->workLayer(name=>$tmp_work_layer,number=>1);
$GEN->attributeReset();
$GEN->COM('filter_reset',filter_name=>'popup');
$GEN->selectByFilter(
attribute=>[{attribute=>'tl_string',text=>'pad_touch_copper_tmp_attr'}],
);
if ($GEN->getSelectCount() > 0) {
#$GEN->COM( "sel_delete_atr,attributes=tl_string,text=pad_touch_copper_tmp_attr" );
$GEN->COM( "sel_delete_atr,attributes=tl_string" );
}
if ($item eq 'pad') {
#if ( $GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{via_drill_layer}) ) {
$GEN->COM("filter_reset,filter_name=popup");
$GEN->COM("filter_set,filter_name=popup,update_popup=no,feat_types=pad,polarity=positive");
$GEN->COM("sel_ref_feat,layers=$TmpLayer{via_drill_layer},use=filter,mode=touch,pads_as=shape,f_types=pad,polarity=positive,include_syms=,exclude_syms=");
$GEN->COM("filter_reset,filter_name=popup");
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
#}
}
$GEN->selectByFilter(attribute=>$AttrHash->{bga});
$GEN->selCopyOther(target_layer=>$TmpLayer{smd_bga_pad}) if ( $GEN->getSelectCount() > 0 );
$GEN->selectByFilter(attribute=>$AttrHash->{smd});
$GEN->selCopyOther(target_layer=>$TmpLayer{smd_bga_pad}) if ( $GEN->getSelectCount() > 0 );
if ( $item eq 'pth' or $item eq 'pad' or $item eq 'via' ) {
$GEN->selRefFeat(
layers=>$TmpLayer{big_copper_layer},
use=>'filter',
mode=>'touch',
filter=>{
filter_name => 'popup',
feat_types=>'pad',
polarity=>'positive',
}
);
}
else {
$GEN->selRefFeat(
layers=>$TmpLayer{big_copper_layer},
use=>'filter',
mode=>'touch',
filter=>{
filter_name => 'popup',
attribute=> $AttrHash->{$item}
}
);
}
if ( $item eq 'smd' ) {
$GEN->selectByFilter(
attribute=>$AttrHash->{bga},
operation=>'unselect'
);
}
elsif ( $item eq 'pth' or $item eq 'pad' or $item eq 'via' ) {
$GEN->selectByFilter(
attribute=>$AttrHash->{bga},
operation=>'unselect'
);
$GEN->selectByFilter(
attribute=>$AttrHash->{smd},
operation=>'unselect'
);
}
if ( $GEN->getSelectCount() > 0 ) {
$GEN->selAddAttr(attribute=>[{attribute=>'tl_string',text=>'pad_touch_copper_tmp_attr'}]);
$GEN->selectByFilter(
attribute=>[{attribute=>'tl_string',text=>'pad_touch_copper_tmp_attr'}],
);
if ( $item eq 'pth' or $item eq 'pad' or $item eq 'via' ) {
$GEN->selRefFeat(
use=>'select',
mode=>'touch',
filter=>{
filter_name => 'popup',
feat_types=>'pad',
polarity=>'positive',
}
);
$GEN->selectByFilter(
attribute=>$AttrHash->{bga},
operation=>'unselect'
);
$GEN->selectByFilter(
attribute=>$AttrHash->{smd},
operation=>'unselect'
);
}else{
$GEN->selRefFeat(
use=>'select',
mode=>'touch',
filter=>{
polarity=>'positive',
attribute=>$AttrHash->{$item},
}
);
$GEN->selectByFilter(
attribute=>$AttrHash->{bga},
operation=>'unselect'
);
}
$GEN->selAddAttr(attribute=>[{attribute=>'tl_string',text=>'pad_touch_copper_tmp_attr'}])if ( $GEN->getSelectCount() > 0 );
$GEN->selectByFilter(
attribute=>[{attribute=>'tl_string',text=>'pad_touch_copper_tmp_attr'}],
);
$GEN->selCopyOther(target_layer=>$TmpLayer{pad_touch_copper});
$GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1);
if ( $item eq 'pth' or $item eq 'via' ) {
$GEN->selRefFeat(
layers=>$DrillLayer,
use=>'filter',
mode=>'disjoint'
);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
if ( $GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{via_drill_layer}) ) {
if ( $item eq 'pth' ) {
$GEN->selRefFeat(
layers=>$TmpLayer{via_drill_layer},
use=>'filter',
mode=>'touch'
);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
}
elsif ( $item eq 'via' ) {
$GEN->selRefFeat(
layers=>$TmpLayer{via_drill_layer},
use=>'filter',
mode=>'disjoint'
);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
}
}
}
elsif ( $item eq 'pad' ) {
#$GEN->selRefFeat(
# layers=>$DrillLayer,
# use=>'filter',
# mode=>'touch'
#);
#$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
$GEN->COM("filter_atr_set,filter_name=ref_select,condition=yes,attribute=.drill,option=plated");
$GEN->selRefFeat(
layers=>$DrillLayer,
use=>'filter',
mode=>'touch'
);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
$GEN->COM("filter_atr_reset,filter_name=ref_select");
}
if ( ($item eq 'pth' or $item eq 'pad' or $item eq 'via') and ( $GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{smd_bga_pad}) ) and $InIgnoreSmdBga eq 'No') {
$GEN->selRefFeat(
layers=>$TmpLayer{smd_bga_pad},
use=>'filter',
mode=>'touch'
);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
}
$GEN->selRefFeat(
layers=>$TmpLayer{npth_layer},
use=>'filter',
mode=>'touch'
);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
}
else {
next;
}
###去除laser Pad
$GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1);
if ( $LaserPadAttr ) {
$GEN->selectByFilter(
feat_types=>'pad',
polarity=>'positive',
attribute=>$LaserPadAttr
);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
}
####制作符合条件的所有pad 到辅助层 all_pad_with_attr
$GEN->workLayer(name=>$layer,number=>1);
$GEN->attributeReset();
$GEN->COM('filter_reset',filter_name=>'popup');
if ( $item eq 'pth' or $item eq 'via' ) {
$GEN->selRefFeat(
layers=>$DrillLayer,
use=>'filter',
mode=>'touch',
filter=>{
filter_name => 'popup',
feat_types=>'pad'
}
);
}
elsif ( $item eq 'pad' ) {
#$GEN->selRefFeat(
# layers=>$DrillLayer,
# use=>'filter',
# mode=>'touch',
# filter=>{
# filter_name => 'popup',
# feat_types=>'pad'
# }
#);
$GEN->COM("filter_atr_set,filter_name=ref_select,condition=yes,attribute=.drill,option=plated");
$GEN->selRefFeat(
layers=>$DrillLayer,
use=>'filter',
mode=>'disjoint',
filter=>{
filter_name => 'popup',
feat_types=>'pad'
}
);
$GEN->COM("filter_atr_reset,filter_name=ref_select");
}
else {
$GEN->selectByFilter(
feat_types=>'pad',
polarity=>'positive',
attribute=>$AttrHash->{$item}
);
}
if ( $item eq 'smd' ) {
$GEN->selectByFilter(
attribute=>$AttrHash->{bga},
operation=>'unselect'
);
}
elsif ( $item eq 'pth' or $item eq 'pad' ) {
$GEN->selectByFilter(
attribute=>$AttrHash->{bga},
operation=>'unselect'
);
$GEN->selectByFilter(
attribute=>$AttrHash->{smd},
operation=>'unselect'
);
}
if ( $GEN->getSelectCount() > 0 ) {
$GEN->selCopyOther(target_layer=>$TmpLayer{all_pad_with_attr});
$GEN->workLayer(name=>$TmpLayer{all_pad_with_attr},number=>1);
$GEN->selRefFeat(
layers=>$TmpLayer{npth_layer},
use=>'filter',
mode=>'touch'
);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
if ( $GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{via_drill_layer}) ) {
if ( $item eq 'pth' ) {
$GEN->selRefFeat(
layers=>$TmpLayer{via_drill_layer},
use=>'filter',
mode=>'touch'
);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
}
elsif ( $item eq 'via' ) {
$GEN->selRefFeat(
layers=>$TmpLayer{via_drill_layer},
use=>'filter',
mode=>'disjoint'
);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
}
}
if ( $GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{smd_bga_pad}) and ( $item eq 'pth' or $item eq 'via' or $item eq 'pad' ) and $InIgnoreSmdBga eq 'No') {
$GEN->selRefFeat(
layers=>$TmpLayer{smd_bga_pad},
use=>'filter',
mode=>'touch'
);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
}
}
else {
next;
}
###去除laser Pad
$GEN->workLayer(name=>$TmpLayer{all_pad_with_attr},number=>1);
if ( $LaserPadAttr ) {
$GEN->selectByFilter(
feat_types=>'pad',
polarity=>'positive',
attribute=>$LaserPadAttr
);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
}
####制作碰到大铜面的pad所对应的开窗到临时层pad_opening
$GEN->workLayer(name=>$tmp{$layer},number=>1);
$GEN->selCopyOther(target_layer=>$TmpLayer{pad_opening});
$GEN->workLayer(name=>$TmpLayer{pad_opening},number=>1);
$GEN->selectByFilter(feat_types=>'surface');
$GEN->selectByFilter(polarity=>'negative');##删除所有负片
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
#remove npth opening
$GEN->selRefFeat(
layers=>$TmpLayer{npth_layer},
use=>'filter',
mode=>'touch'
);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
$GEN->selRefFeat(
layers=>$TmpLayer{pad_touch_copper},
use=>'filter',
mode=>'disjoint'
);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
####去除客户定义不需要处理的开窗
if ( $IgnoreAttr ) {
$GEN->selectByFilter(attribute=>$IgnoreAttr);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
}
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
$GEN->selectByFilter();
if ( $GEN->getSelectCount() == 1 ) {
$GEN->COM('sel_decompose',overlap=>'yes');
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
}
else {
$GEN->selClearFeature();
}
###去除特殊开窗
$GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1);
$GEN->selCopyOther(target_layer=>$TmpLayer{tmp_layer});
$GEN->workLayer(name=>$TmpLayer{tmp_layer},number=>1);
$GEN->COM('sel_resize',size=>$UpdateMaxOpening*3,corner_ctl=>'no');
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
$GEN->selectByFilter();
if ( $GEN->getSelectCount() == 1 ) {
$GEN->COM('sel_decompose',overlap=>'yes');
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
}
else {
$GEN->selClearFeature();
}
$GEN->workLayer(name=>$TmpLayer{pad_opening},number=>1);
$GEN->selRefFeat(
layers=>$TmpLayer{tmp_layer},
use=>'filter',
mode=>'cover'
);
#$GEN->COM('disp_on');
$GEN->selReverse();
if ( $GEN->getSelectCount() > 0 ) {
$GEN->selCopyOther(target_layer=>$TmpLayer{remove_specifical_sm});
##2018-3-23修复如果防焊开窗ring本来满足要求,就会放到报警层而不制作smdefined的问题 -- start
#$GEN->workLayer(name=>$TmpLayer{remove_specifical_sm},number=>1);
#$GEN->selRefFeat(
# layers=>$TmpLayer{tmp_layer},
# use=>'filter',
# mode=>'include'
#);
#$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
##2018-3-23 -- end
##
$GEN->workLayer(name=>$TmpLayer{pad_opening},number=>1);
$GEN->selRefFeat(
layers=>$TmpLayer{remove_specifical_sm},
use=>'filter',
mode=>'touch'
);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
if ( $SpecificalWarningSuffix ) {
$GEN->workLayer(name=>$TmpLayer{remove_specifical_sm},number=>1);
$GEN->selCopyOther(target_layer=>$tmp{$layer}.$SpecificalWarningSuffix);
}
}
#$GEN->PAUSE('tttt');
_deleteLayer(layer=>[$TmpLayer{tmp_layer}]);
####去除没有被覆盖在开窗里面的pad
$GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1);
$GEN->selRefFeat(
layers=>$TmpLayer{pad_opening},
use=>'filter',
mode=>'cover'
);
$GEN->selReverse();
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
####所有SM开窗到临时层sm_opening
$GEN->workLayer(name=>$tmp{$layer},number=>1);
$GEN->selCopyOther(target_layer=>$TmpLayer{sm_opening});
$GEN->workLayer(name=>$TmpLayer{sm_opening},number=>1);
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
$GEN->selectByFilter();
if ( $GEN->getSelectCount() == 1 ) {
$GEN->COM('sel_decompose',overlap=>'yes');
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
}
else {
$GEN->selClearFeature();
}
###制作开窗比pad小的到临时层 sm_less_pad
$GEN->workLayer(name=>$TmpLayer{all_pad_with_attr},number=>1);
$GEN->selCopyOther(target_layer=>$TmpLayer{tmp_layer});
$GEN->workLayer(name=>$TmpLayer{tmp_layer},number=>1);
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
$GEN->selectByFilter();
if ( $GEN->getSelectCount() == 1 ) {
$GEN->COM('sel_decompose',overlap=>'yes');
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
}
else {
$GEN->selClearFeature();
}
$GEN->workLayer(name=>$tmp{$layer},number=>1);
$GEN->selRefFeat(
layers=>$TmpLayer{tmp_layer},
use=>'filter',
mode=>'include'
);
$GEN->selReverse();
if ( $GEN->getSelectCount() > 0 ) {
$GEN->selCopyOther(target_layer=>$TmpLayer{sm_less_pad});
$GEN->workLayer(name=>$TmpLayer{sm_less_pad},number=>1);
$GEN->selRefFeat(
layers=>$TmpLayer{tmp_layer},
use=>'filter',
mode=>'cover'
);
$GEN->selReverse();
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
}
_deleteLayer(layer=>[$TmpLayer{tmp_layer}]);
###制作正式层上开窗比pad小的情况
if ( $GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{sm_less_pad}) and $PAR->{make_sm_less_pad} eq 'Yes') {
$GEN->workLayer(name=>$tmp{$layer},number=>1);
$GEN->selRefFeat(
layers=>$TmpLayer{sm_less_pad},
use=>'filter',
mode=>'cover'
);
$GEN->selectByFilter(
attribute=>[{attribute=>'.string',text=>'smdefpad_sm'}],
operation=>'unselect'
);
####去除客户定义不需要处理的开窗
if ( $IgnoreAttr ) {
$GEN->selectByFilter(attribute=>$IgnoreAttr,
operation=>'unselect');
}
if ( $GEN->getSelectCount() > 0 ) {
$GEN->selCopyOther(target_layer=>$TmpLayer{tmp_layer});
$GEN->selRefFeat(
layers=>$TmpLayer{tmp_layer},
use=>'filter',
mode=>'cover'
);
$GEN->selAddAttr(attribute=>[{attribute=>'.string',text=>'smdefpad_sm_'.$item},'smdefpad_sm']) if ( $GEN->getSelectCount() > 0 );
$GEN->selectByFilter(attribute=>[{attribute=>'.string',text=>'smdefpad_sm_'.$item}]);
if ( $GEN->getSelectCount() > 0 ) {
$GEN->selCopyOther(target_layer=>$ref_layer);
}
$GEN->selectByFilter(attribute=>[{attribute=>'.string',text=>'smdefpad_sm_'.$item}]);
$GEN->COM('sel_resize',size=>$CopperOpening*2,corner_ctl=>'no') if ( $GEN->getSelectCount() > 0 );
$GEN->workLayer(name=>$TmpLayer{pad_opening},number=>1);
$GEN->selRefFeat(
layers=>$TmpLayer{tmp_layer},
use=>'filter',
mode=>'touch'
);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
$GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1);
$GEN->selRefFeat(
layers=>$TmpLayer{tmp_layer},
use=>'filter',
mode=>'touch'
);
$GEN->workLayer(name=>$TmpLayer{all_pad_with_attr},number=>1);
$GEN->selRefFeat(
layers=>$TmpLayer{tmp_layer},
use=>'filter',
mode=>'touch'
);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
_deleteLayer(layer=>[$TmpLayer{tmp_layer}]);
}
}
####gaster 制作(copy 外层pad加大(gasketsize+$CopperOpening)*2 到当前层为surface)
$GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1);
$GEN->selRefFeat(
layers=>$TmpLayer{big_copper_layer},
use=>'filter',
mode=>'cover'
);
if ( $GEN->getSelectCount() > 0 ) {
$GEN->selCopyOther(target_layer=>$TmpLayer{tmp_layer});
$GEN->workLayer(name=>$TmpLayer{tmp_layer},number=>1);
$GEN->selRefFeat(
layers=>$TmpLayer{pad_opening},
use=>'filter',
mode=>'cover'
);
if ( $GEN->getSelectCount() > 0 ) {
$GEN->selCopyOther(target_layer=>$TmpLayer{pad_on_copper_gasket});
}
}
_deleteLayer(layer=>[$TmpLayer{tmp_layer}]);
if ( $KeepGasket eq 'Yes' and $GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{pad_on_copper_gasket}) ) {
$GEN->workLayer(name=>$TmpLayer{pad_on_copper_gasket},number=>1);
$GEN->COM('sel_resize',size=>($GasketSize+$CopperOpening)*2,corner_ctl=>'no');
$GEN->selAddAttr(attribute=>['gasket',{attribute=>'.string',text=>'smdef_gasket'}]);
$GEN->selCopyOther(target_layer=>$layer);
$GEN->selCopyOther(target_layer=>$TmpLayer{big_copper_layer});
$GEN->workLayer(name=>$TmpLayer{big_copper_layer},number=>1);
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
$GEN->selectByFilter();
if ( $GEN->getSelectCount() == 1 ) {
$GEN->COM('sel_decompose',overlap=>'yes');
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
}
else {
$GEN->selClearFeature();
}
}
####开窗不足最优的情况下最优化开窗
$GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1);
$GEN->selCopyOther(target_layer=>$TmpLayer{tmp_layer});
$GEN->workLayer(name=>$TmpLayer{tmp_layer},number=>1);
if ( ref $OptOpening eq 'ARRAY' ) {
my %symhist = $GEN->getLayerSymsHist(job=>$Job,step=>$Step,layer=>$TmpLayer{tmp_layer});
foreach my $item (sort { $symhist{$b}{size} <=> $symhist{a}{size} } keys %symhist) {
my $size = $symhist{$item}{size};
if ( ! $size ) {
$size = ($symhist{$item}{width} < $symhist{$item}{length}) ? $symhist{$item}{width} : $symhist{$item}{length};
}
my $cmp;
foreach my $v (@$OptOpening) {
if ( $size ) {
next if ( $v->{type} eq 'others' );
if ( $size > $v->{min} and $size <= $v->{max} ) {
$cmp = $v->{cmp};
last;
}
}
else {
if ( $v->{type} eq 'others' ) {
$cmp = $v->{cmp};
last;
}
}
}
if ( $cmp ) {
$GEN->selectByFilter(include_syms=>$item);
$GEN->COM('sel_resize',size=>$cmp*2,corner_ctl=>'no') if ( $GEN->getSelectCount() > 0 );
}
else {
$GUI->msgbox(-icon=>'error',-text=>"symbol $item 找不到最优开窗大小!");
return 'Error';
}
}
}
else {
$GEN->COM('sel_resize',size=>$OptOpening*2,corner_ctl=>'no');
}
$GEN->selRefFeat(
layers=>$TmpLayer{pad_opening},
use=>'filter',
mode=>'include'
);
$GEN->selReverse();
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
$GEN->workLayer(name=>$tmp{$layer},number=>1);
$GEN->selRefFeat(
layers=>$TmpLayer{tmp_layer},
use=>'filter',
mode=>'cover'
);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
$GEN->workLayer(name=>$TmpLayer{tmp_layer},number=>1);
$GEN->selCopyOther(target_layer=>$tmp{$layer});
$GEN->selCopyOther(target_layer=>$TmpLayer{pad_opening});
$GEN->selCopyOther(target_layer=>$TmpLayer{sm_opening});
$GEN->workLayer(name=>$TmpLayer{pad_opening},number=>1);
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
$GEN->selectByFilter();
if ( $GEN->getSelectCount() == 1 ) {
$GEN->COM('sel_decompose',overlap=>'yes');
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
}
else {
$GEN->selClearFeature();
}
$GEN->workLayer(name=>$TmpLayer{sm_opening},number=>1);
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
$GEN->selectByFilter();
if ( $GEN->getSelectCount() == 1 ) {
$GEN->COM('sel_decompose',overlap=>'yes');
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
}
else {
$GEN->selClearFeature();
}
_deleteLayer(layer=>[$TmpLayer{tmp_layer}]);
####制作优化的大铜面到临时层 opt_big_copper
#my $CoverageTol = 1;
if ($item ne 'smd') {
$Coverage_tmp = $Coverage_tmp + $CoverageTol_tmp/2;
$CoverageTol_tmp = 0;
}
#$Coverage = $CopperOpening < 0 ? -$Coverage : $Coverage;
$GEN->workLayer(name=>$TmpLayer{big_copper_layer},number=>1);
$GEN->selCopyOther(target_layer=>$TmpLayer{opt_big_copper},size=>$Coverage_tmp);
$GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1);
$GEN->selRefFeat(
layers=>$TmpLayer{pad_opening},
use=>'filter',
mode=>'include'
);
if ($item eq 'bga') {
$GEN->selectByFilter(attribute=>[{attribute=>'tl_spec_bga'}],operation=>'unselect');#non_plated,plated,via
}
$GEN->selCopyOther(target_layer=>$TmpLayer{opt_big_copper},size=>2*$CopperOpening+$Coverage_tmp+$CoverageTol_tmp,invert=>'yes') if ( $GEN->getSelectCount() > 0 );
$GEN->selRefFeat(
layers=>$TmpLayer{pad_opening},
use=>'filter',
mode=>'cover'
);
if ($item eq 'bga') {
$GEN->selectByFilter(attribute=>[{attribute=>'tl_spec_bga'}],operation=>'unselect');#non_plated,plated,via
}
$GEN->selCopyOther(target_layer=>$TmpLayer{opt_big_copper},size=>2*$CopperOpening+$Coverage_tmp+$CoverageTol_tmp,invert=>'yes') if ( $GEN->getSelectCount() > 0 );
if ($item eq 'bga') {
$GEN->selectByFilter(attribute=>[{attribute=>'tl_spec_bga'}]);#non_plated,plated,via
$GEN->selCopyOther(target_layer=>$TmpLayer{opt_big_copper},size=>2*$SpecBGACopperOpening+$Coverage_tmp+$CoverageTol_tmp,invert=>'yes') if ( $GEN->getSelectCount() > 0 );
}
$GEN->workLayer(name=>$TmpLayer{opt_big_copper},number=>1);
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
$GEN->selectByFilter();
if ( $GEN->getSelectCount() == 1 ) {
$GEN->COM('sel_decompose',overlap=>'yes');
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
}
else {
$GEN->selClearFeature();
}
$GEN->COM('sel_resize',size=>$Coverage_tmp+$CoverageTol_tmp,corner_ctl=>'no');
####制作准确的大铜面pad开窗到临时层 correct_sm_opening
$GEN->workLayer(name=>$TmpLayer{pad_opening},number=>1);
$GEN->selCopyOther(target_layer=>$TmpLayer{correct_sm_opening},size=>2);
$GEN->workLayer(name=>$TmpLayer{opt_big_copper},number=>1);
$GEN->selCopyOther(target_layer=>$TmpLayer{correct_sm_opening},invert=>'yes');
$GEN->workLayer(name=>$TmpLayer{correct_sm_opening},number=>1);
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
$GEN->selectByFilter();
if ( $GEN->getSelectCount() == 1 ) {
$GEN->COM('sel_decompose',overlap=>'yes');
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
}
else {
$GEN->selClearFeature();
}
$GEN->selRefFeat(
layers=>$TmpLayer{pad_touch_copper},
use=>'filter',
mode=>'disjoint'
);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
####制作需要刮开的开窗部分
$GEN->workLayer(name=>$TmpLayer{pad_opening},number=>1);
$GEN->selCopyOther(target_layer=>$TmpLayer{sm_opening_free},size=>1);
$GEN->workLayer(name=>$TmpLayer{correct_sm_opening},number=>1);
$GEN->selCopyOther(target_layer=>$TmpLayer{sm_opening_free},invert=>'yes');
$GEN->workLayer(name=>$tmp{$layer}.$BakSuffix,number=>1);
$GEN->attributeReset();
$GEN->COM('filter_reset',filter_name=>'popup');
$GEN->selectByFilter(attribute=>[{attribute=>'.drill',option=>'via'}],polarity=>'negative');
if ( $GEN->getSelectCount() > 0 ){
$GEN->selCopyOther(target_layer=>$TmpLayer{sm_opening_free});
}
$GEN->workLayer(name=>$TmpLayer{sm_opening_free},number=>1);
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
$GEN->selectByFilter();
if ( $GEN->getSelectCount() == 1 ) {
$GEN->COM('sel_decompose',overlap=>'yes');
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
}
else {
$GEN->selClearFeature();
}
$GEN->COM('sel_resize',size=>-0.05,corner_ctl=>'no');
$GEN->selRefFeat(
layers=>$TmpLayer{sm_opening},
use=>'filter',
mode=>'cover'
);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
$GEN->selRefFeat(
layers=>$TmpLayer{sm_opening},
use=>'filter',
mode=>'disjoint'
);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
$GEN->selRefFeat(
layers=>$TmpLayer{sm_opening},
use=>'filter',
mode=>'include'
);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
if ( $CopperOpening > 0 ) {
$GEN->selRefFeat(
layers=>$TmpLayer{pad_touch_copper},
use=>'filter',
mode=>'touch'
);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
}
$GEN->COM('sel_resize',size=>0.05,corner_ctl=>'no');
#####去除小细丝
$GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$tmp{$layer},dest_layer=>$TmpLayer{tmp_layer});
$GEN->workLayer(name=>$TmpLayer{sm_opening_free},number=>1);
$GEN->selCopyOther(target_layer=>$TmpLayer{tmp_layer},invert=>'yes');
$GEN->workLayer(name=>$TmpLayer{tmp_layer},number=>1);
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
$GEN->selectByFilter();
if ( $GEN->getSelectCount() == 1 ) {
$GEN->COM('sel_decompose',overlap=>'yes');
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
}
else {
$GEN->selClearFeature();
}
$GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$TmpLayer{tmp_layer},dest_layer=>$TmpLayer{sliver_layer});
#$GEN->COM('sel_resize',size=>-1,corner_ctl=>'no');
#$GEN->COM('sel_resize',size=>1,corner_ctl=>'no');
$GEN->selFill(min_brush=>2);
$GEN->selContourize();
$GEN->selCopyOther(target_layer=>$TmpLayer{sliver_layer},invert=>'yes',size=>0.05);
$GEN->workLayer(name=>$TmpLayer{sliver_layer},number=>1);
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
$GEN->COM('sel_resize',size=>-0.05,corner_ctl=>'no');
$GEN->COM('sel_resize',size=>0.05,corner_ctl=>'no');
$GEN->selectByFilter();
if ( $GEN->getSelectCount() == 1 ) {
$GEN->COM('sel_decompose',overlap=>'yes');
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
}
else {
$GEN->selClearFeature();
}
$GEN->selectByFilter(polarity=>'positive');
if ( $GEN->getSelectCount() > 0 ) {
$GEN->selCopyOther(target_layer=>$TmpLayer{sm_opening_free},size=>0.05);
$GEN->workLayer(name=>$TmpLayer{sm_opening_free},number=>1);
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
$GEN->selectByFilter();
if ( $GEN->getSelectCount() == 1 ) {
$GEN->COM('sel_decompose',overlap=>'yes');
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
}
else {
$GEN->selClearFeature();
}
}
$GEN->selClearFeature();
##去除小面积物件
if ($DeleteSamllArea eq 'Yes') {
$GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$tmp{$layer},dest_layer=>$TmpLayer{tmp_layer});
$GEN->workLayer(name=>$TmpLayer{sm_opening_free},number=>1);
$GEN->selCopyOther(target_layer=>$TmpLayer{tmp_layer},invert=>'yes');
$GEN->workLayer(name=>$TmpLayer{tmp_layer},number=>1);
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
$GEN->selectByFilter();
if ( $GEN->getSelectCount() == 1 ) {
$GEN->COM('sel_decompose',overlap=>'yes');
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
}
else {
$GEN->selClearFeature();
}
$GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$TmpLayer{tmp_layer},dest_layer=>$TmpLayer{samll_area_layer});
$GEN->workLayer(name=>$TmpLayer{tmp_layer},number=>1);
$GEN->selectByFilter(polarity=>'positive');
$GEN->COM("sel_clean_surface,accuracy=0,clean_size=$SmallAreaOpen,clean_mode=area,max_fold_len=0");
$GEN->workLayer(name=>$TmpLayer{samll_area_layer},number=>1);
$GEN->selRefFeat(
layers=>$TmpLayer{tmp_layer},
use=>'filter',
mode=>'touch'
);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
$GEN->selectByFilter(polarity=>'positive');
if ( $GEN->getSelectCount() > 0 ) {
$GEN->selCopyOther(target_layer=>$TmpLayer{sm_opening_free},size=>0.05);
$GEN->workLayer(name=>$TmpLayer{sm_opening_free},number=>1);
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
$GEN->selectByFilter();
if ( $GEN->getSelectCount() == 1 ) {
$GEN->COM('sel_decompose',overlap=>'yes');
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
}
else {
$GEN->selClearFeature();
}
}
$GEN->selClearFeature();
}
###add smdefpad_sm_totally and smdefpad_sm_partly
_deleteLayer(layer=>[$TmpLayer{tmp_layer}]);
if ( $GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{pad_on_copper_gasket}) ) {
$GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1);
$GEN->selRefFeat(
layers=>$TmpLayer{pad_on_copper_gasket},
use=>'filter',
mode=>'touch'
);
if ( $GEN->getSelectCount() > 0 ) {
$GEN->selCopyOther(target_layer=>$TmpLayer{tmp_layer});
$GEN->workLayer(name=>$tmp{$layer},number=>1);
$GEN->selRefFeat(
layers=>$TmpLayer{tmp_layer},
use=>'filter',
mode=>'include'
);
if ( $GEN->getSelectCount() > 0 ) {
$GEN->selAddAttr(attribute=>'smdefpad_sm_totally');
}
}
}
$GEN->workLayer(name=>$tmp{$layer},number=>1);
$GEN->selRefFeat(
layers=>$TmpLayer{sm_opening_free},
use=>'filter',
mode=>'touch'
);
$GEN->selectByFilter(
attribute=>'smdefpad_sm',
operation=>'unselect'
);
$GEN->selectByFilter(
attribute=>'smdefpad_sm_totally',
operation=>'unselect'
);
if ( $GEN->getSelectCount() > 0 ) {
$GEN->selAddAttr(attribute=>'smdefpad_sm_partly');
}
_deleteLayer(layer=>[$TmpLayer{tmp_layer}]);
###copy to sm layer
$GEN->workLayer(name=>$TmpLayer{sm_opening_free},number=>1);
$GEN->COM('sel_delete_atr',attributes=>'smdefpad_sm');
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
$GEN->selectByFilter();
if ( $GEN->getSelectCount() == 1 ) {
$GEN->COM('sel_decompose',overlap=>'yes');
#$GEN->selContourize();
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
}
else {
$GEN->selClearFeature();
}
$GEN->selAddAttr(attribute=>[{attribute=>'.string',text=>'sm_defined_pad_shave'}]);
###去掉有shave碰到开窗上是surface的部分
$GEN->workLayer(name=>$TmpLayer{sm_opening_free},number=>1);
$GEN->selRefFeat(
layers=>$tmp{$layer},
use=>'filter',
mode=>'touch',
f_types=>'surface'
);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
$GEN->selCopyOther(target_layer=>$TmpLayer{sm_defined_tmp_layer},invert=>'yes');
$GEN->selCopyOther(target_layer=>$sm_tmp_bk,invert=>'yes');
$GEN->selCopyOther(target_layer=>$ref_layer);
}
if($GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{sm_defined_tmp_layer})){
$GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$TmpLayer{sm_defined_tmp_layer},dest_layer=>$tmp{$layer},mode=>'append',invert=>'no');
}
$GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$sm_tmp_bk,dest_layer=>$tmp{$layer});
$GEN->COM("disp_on");
_deleteLayer(layer=>[$sm_tmp_bk,$TmpLayer{sm_defined_tmp_layer}]);
###补偿用户定义的属性将忽略处理的开窗
$GEN->workLayer(name=>$tmp{$layer},number=>1);
if ( $PAR->{ignore_attr_comp} and $PAR->{ignore_attr_comp} eq 'Yes' and $IgnoreAttr ) {
$GEN->workLayer(name=>$tmp{$layer},number=>1);
$GEN->selectByFilter(attribute=>$IgnoreAttr);
if ( $GEN->getSelectCount() > 0 ) {
$GEN->COM('sel_resize',size=>$CopperOpening*2,corner_ctl=>'no');
}
}
##恢复via
$GEN->workLayer(name=>$tmp{$layer}.$BakSuffix,number=>1);
$GEN->attributeReset();
$GEN->COM('filter_reset',filter_name=>'popup');
$GEN->selectByFilter(attribute=>[{attribute=>'.drill',option=>'via'}],polarity=>'positive');
if ( $GEN->getSelectCount() > 0 ){
$GEN->selCopyOther(target_layer=>$tmp{$layer});
$GEN->selCopyOther(target_layer=>$sm_tmp_bk);
}
# # 恢复负片层
# my $negative_open_lyr = $tmp{$layer}.'_negative_open_lyr_tl_script';
# $GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$tmp{$layer}.$BakSuffix,dest_layer=>$negative_open_lyr);
# $GEN->workLayer(name=>$negative_open_lyr,number=>1);
# $GEN->attributeReset();
# $GEN->COM('filter_reset',filter_name=>'popup');
# $GEN->selectByFilter(polarity=>'positive');
# if ( $GEN->getSelectCount() > 0 ){
# $GEN->selectByFilter(polarity=>'positive');
# $GEN->COM('sel_resize',size=>'-1',corner_ctl=>'no');
# }
# $GEN->attributeReset();
# $GEN->COM('filter_reset',filter_name=>'popup');
# $GEN->selectByFilter(polarity=>'negative');
# $GEN->COM('sel_resize',size=>1,corner_ctl=>'no') if ( $GEN->getSelectCount() > 0 );
# $GEN->selContourize();
#
# $GEN->workLayer(name=>$tmp{$layer}.$BakSuffix,number=>1);
# $GEN->selRefFeat(
# layers=>$negative_open_lyr,
# use=>'filter',
# mode=>'disjoint',
# filter=>{
# filter_name => 'popup',
# polarity=>'negative',
# }
# );
# if ( $GEN->getSelectCount() > 0 ){
# $GEN->selCopyOther(target_layer=>$tmp{$layer},size=>0);
# }
#_deleteLayer(layer=>[$negative_open_lyr]);
$GEN->workLayer(name=>$tmp{$layer},number=>1);
}
###output and return status, if genesis error, it will output genesis error command
unless ($GEN->{STATUS}){
$GEN->COM("disp_on");
return $Return;
}
else{
$GEN->COM("disp_on");
$GUI->msgbox(-icon=>'error',-text=>join("\n",@{$GEN->{STATUS}}));
#addFlowNotes(-notes=>" Genesis Error:\n ".join("\n ",@{$GEN->{STATUS}}));
return 'Error';
}
}
catch Error::Simple with {
$GEN->COM("disp_on");
my $error = encode("utf8",shift);
$GUI->msgbox(-icon=>'error',-text=>$error);
return 'Error';
}
finally{
$GEN->COM("disp_on");
_deleteLayer(layer=>[values %TmpLayer]);
};
sub _deleteLayer{
my %par = @_;
foreach my $layer(@{$par{layer}}){
$GEN->deleteLayer(layer=>$layer) if ($GEN->isLayerExists(job=>$Job,layer=>$layer));
}
}
sub select_work_layer{
my %par = @_;
##获取工作层
my @sm;
my %matrix = $GEN->getMatrix(job=>$Job,type=>'hash');
foreach my $layer (sort {$matrix{$a}{row} <=> $matrix{$b}{row}} keys %matrix) {
if(defined($matrix{$layer}{context}) and $matrix{$layer}{context} eq 'board' ){
if (defined($matrix{$layer}{tl_type}) and $matrix{$layer}{tl_type} eq 'solder_mask') {
push @sm,$layer;
}
}
}
##
unless( @sm ){
$GUI->msgbox(-icon=>'warning',-text=>'资料中无防焊层,请确认');
return 'Cancel';
}
##
if ($PAR->{is_select_lyr} eq 'Yes' and scalar(@sm) > 1) {
my (%tmp_matrix);
foreach my $layer (@sm) {
$tmp_matrix{$layer} = $matrix{$layer};
}
@sm = $GUI->select_layer(
-title=>'请选择工作层别',
-layermatrix=>\%tmp_matrix,
-default => [keys %tmp_matrix],
-selectmode => 'multiple');#single
return 'Cancel' unless(@sm);
}
return \@sm;
}
...@@ -638,7 +638,6 @@ try{ ...@@ -638,7 +638,6 @@ try{
###Open step and clear layer ###Open step and clear layer
$GEN->openStep(job=>$Job,name=>$Step); $GEN->openStep(job=>$Job,name=>$Step);
$GEN->COM("disp_off");
$GEN->clearLayers(); $GEN->clearLayers();
$GEN->affectedLayer(mode=>'all',affected=>'no'); $GEN->affectedLayer(mode=>'all',affected=>'no');
$GEN->units(type=>'inch'); $GEN->units(type=>'inch');
...@@ -979,6 +978,8 @@ try{ ...@@ -979,6 +978,8 @@ try{
$KeepGasket = $info{keep_gasket}; $KeepGasket = $info{keep_gasket};
$UpdateMaxOpening = $info{update_max_opening}; $UpdateMaxOpening = $info{update_max_opening};
$GUI->msgbox(-text=>"start"); #? tmp
%tmp = reverse %tmp; %tmp = reverse %tmp;
foreach my $layer (keys %tmp) { foreach my $layer (keys %tmp) {
my $ref_layer = $tmp{$layer}.'_ref'; my $ref_layer = $tmp{$layer}.'_ref';
...@@ -992,8 +993,8 @@ try{ ...@@ -992,8 +993,8 @@ try{
$GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$tmp{$layer},dest_layer=>$tmp{$layer}.$BakSuffix); $GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$tmp{$layer},dest_layer=>$tmp{$layer}.$BakSuffix);
$GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$layer,dest_layer=>$layer.$BakSuffix); $GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$layer,dest_layer=>$layer.$BakSuffix);
$GEN->workLayer(name=>$tmp{$layer},number=>1); $GEN->workLayer(name=>$tmp{$layer},number=>1);
$GEN->PAUSE($layer); #? tmp
$GEN->selectByFilter(attribute=>[{attribute=>'.string',text=>'sm_defined_pad_shave'}]); $GEN->selectByFilter(attribute=>[{attribute=>'.string',text=>'sm_defined_pad_shave'}]);
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
##移除via ##移除via
...@@ -1013,7 +1014,7 @@ try{ ...@@ -1013,7 +1014,7 @@ try{
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
_deleteLayer(layer=>[$tmp{$layer}.$SpecificalWarningSuffix]); _deleteLayer(layer=>[$tmp{$layer}.$SpecificalWarningSuffix]);
$GEN->PAUSE(1); #? tmp
foreach my $item ('smd','bga','pth','via','pad') {#'smd','bga','pth','via','pad' foreach my $item ('smd','bga','pth','via','pad') {#'smd','bga','pth','via','pad'
next unless ( defined $info{$item} and $info{$item} eq 'Yes' ); next unless ( defined $info{$item} and $info{$item} eq 'Yes' );
my $Coverage_tmp = $Coverage; my $Coverage_tmp = $Coverage;
...@@ -1153,7 +1154,6 @@ try{ ...@@ -1153,7 +1154,6 @@ try{
_deleteLayer(layer=>[$include_pad_lyr]); _deleteLayer(layer=>[$include_pad_lyr]);
} }
} }
$GEN->workLayer(name=>$TmpLayer{big_copper_layer},number=>1); $GEN->workLayer(name=>$TmpLayer{big_copper_layer},number=>1);
$GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no");
$GEN->selectByFilter(); $GEN->selectByFilter();
...@@ -1469,6 +1469,7 @@ try{ ...@@ -1469,6 +1469,7 @@ try{
); );
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
} }
$GEN->PAUSE(3); #? tmp
####制作碰到大铜面的pad所对应的开窗到临时层pad_opening ####制作碰到大铜面的pad所对应的开窗到临时层pad_opening
...@@ -1684,7 +1685,6 @@ try{ ...@@ -1684,7 +1685,6 @@ try{
_deleteLayer(layer=>[$TmpLayer{tmp_layer}]); _deleteLayer(layer=>[$TmpLayer{tmp_layer}]);
} }
} }
####gaster 制作(copy 外层pad加大(gasketsize+$CopperOpening)*2 到当前层为surface) ####gaster 制作(copy 外层pad加大(gasketsize+$CopperOpening)*2 到当前层为surface)
$GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1); $GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1);
$GEN->selRefFeat( $GEN->selRefFeat(
...@@ -1707,7 +1707,7 @@ try{ ...@@ -1707,7 +1707,7 @@ try{
_deleteLayer(layer=>[$TmpLayer{tmp_layer}]); _deleteLayer(layer=>[$TmpLayer{tmp_layer}]);
if ( $KeepGasket eq 'Yes' and $GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{pad_on_copper_gasket}) ) { if ( $KeepGasket eq 'Yes' and $GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{pad_on_copper_gasket}) ) {
$GEN->workLayer(name=>$TmpLayer{pad_on_copper_gasket},number=>1); $GEN->workLayer(name=>$TmpLayer{pad_on_copper_gasket},number=>1);
$GEN->COM('sel_resize',size=>($GasketSize+$CopperOpening)*2,corner_ctl=>'no'); $GEN->COM('sel_resize',size=>($GasketSize+$CopperOpening)*3,corner_ctl=>'no');
$GEN->selAddAttr(attribute=>['gasket',{attribute=>'.string',text=>'smdef_gasket'}]); $GEN->selAddAttr(attribute=>['gasket',{attribute=>'.string',text=>'smdef_gasket'}]);
$GEN->selCopyOther(target_layer=>$layer); $GEN->selCopyOther(target_layer=>$layer);
$GEN->selCopyOther(target_layer=>$TmpLayer{big_copper_layer}); $GEN->selCopyOther(target_layer=>$TmpLayer{big_copper_layer});
...@@ -1857,7 +1857,6 @@ try{ ...@@ -1857,7 +1857,6 @@ try{
} }
$GEN->COM('sel_resize',size=>$Coverage_tmp+$CoverageTol_tmp,corner_ctl=>'no'); $GEN->COM('sel_resize',size=>$Coverage_tmp+$CoverageTol_tmp,corner_ctl=>'no');
####制作准确的大铜面pad开窗到临时层 correct_sm_opening ####制作准确的大铜面pad开窗到临时层 correct_sm_opening
$GEN->workLayer(name=>$TmpLayer{pad_opening},number=>1); $GEN->workLayer(name=>$TmpLayer{pad_opening},number=>1);
$GEN->selCopyOther(target_layer=>$TmpLayer{correct_sm_opening},size=>2); $GEN->selCopyOther(target_layer=>$TmpLayer{correct_sm_opening},size=>2);
...@@ -1881,7 +1880,6 @@ try{ ...@@ -1881,7 +1880,6 @@ try{
mode=>'disjoint' mode=>'disjoint'
); );
$GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 );
####制作需要刮开的开窗部分 ####制作需要刮开的开窗部分
$GEN->workLayer(name=>$TmpLayer{pad_opening},number=>1); $GEN->workLayer(name=>$TmpLayer{pad_opening},number=>1);
$GEN->selCopyOther(target_layer=>$TmpLayer{sm_opening_free},size=>1); $GEN->selCopyOther(target_layer=>$TmpLayer{sm_opening_free},size=>1);
...@@ -2118,8 +2116,6 @@ try{ ...@@ -2118,8 +2116,6 @@ try{
$GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$sm_tmp_bk,dest_layer=>$tmp{$layer}); $GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$sm_tmp_bk,dest_layer=>$tmp{$layer});
$GEN->COM("disp_on");
_deleteLayer(layer=>[$sm_tmp_bk,$TmpLayer{sm_defined_tmp_layer}]); _deleteLayer(layer=>[$sm_tmp_bk,$TmpLayer{sm_defined_tmp_layer}]);
...@@ -2181,24 +2177,20 @@ try{ ...@@ -2181,24 +2177,20 @@ try{
###output and return status, if genesis error, it will output genesis error command ###output and return status, if genesis error, it will output genesis error command
unless ($GEN->{STATUS}){ unless ($GEN->{STATUS}){
$GEN->COM("disp_on");
return $Return; return $Return;
} }
else{ else{
$GEN->COM("disp_on");
$GUI->msgbox(-icon=>'error',-text=>join("\n",@{$GEN->{STATUS}})); $GUI->msgbox(-icon=>'error',-text=>join("\n",@{$GEN->{STATUS}}));
#addFlowNotes(-notes=>" Genesis Error:\n ".join("\n ",@{$GEN->{STATUS}})); #addFlowNotes(-notes=>" Genesis Error:\n ".join("\n ",@{$GEN->{STATUS}}));
return 'Error'; return 'Error';
} }
} }
catch Error::Simple with { catch Error::Simple with {
$GEN->COM("disp_on");
my $error = encode("utf8",shift); my $error = encode("utf8",shift);
$GUI->msgbox(-icon=>'error',-text=>$error); $GUI->msgbox(-icon=>'error',-text=>$error);
return 'Error'; return 'Error';
} }
finally{ finally{
$GEN->COM("disp_on");
_deleteLayer(layer=>[values %TmpLayer]); _deleteLayer(layer=>[values %TmpLayer]);
}; };
......
/*
NAME:
DESCRIPTION: ;
PARAMETER:
[
{
name : 'step',
title : 'step',
type : 'LineEdit',
property : {tool_tip : '目标step,默认是orig'},
},
{
name : 'export_path',
title : 'export_path',
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 2020-09-01 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> step信息 </p>
<br>
<font size="3" color="#003DB2"><p>注意事项</p></font>
<p> 无 </p>
<br>
</body></html>
*/
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
console.log("==============================>template");
// 引入模块 包
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 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 = [];
var par = PAR;
var default_par = {
step: "edit",
export_path:"C:/Users/ADMINI~1/Desktop/jobs/demo",
auto_save: "No",
units:"mm"
}
for(var key in default_par){ if (!par.hasOwnProperty(key) || par[key] == ""){ par[key] = default_par[key] }}
var job = Job;
try {
if(_.isEmpty(job)){throw "参数job不存在"} else { 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" } else { GEN.checkInout({job:job,mode:"out"}) } }
var stepList = GEN.getStepList({job:job})
stepList = stepList.filter(function(step){
var reg = new RegExp(par.step,"ig")
return reg.test(step)
})
var matrix = GEN.getMatrix({job:job});
stepList.forEach(function(step){
var excellon = [];
var gerber = [];
fs.mkdir(par.export_path + "/" + step)
for (var key in matrix) {
var info = matrix[key];
if(!GEN.isLayerEmpty({job:job,step:step,layer:key})){
if(info.layer_type == "drill"){
excellon.push(key)
} else {
gerber.push(key)
}
}
}
if(gerber.length){
GEN.COM("output_layer_reset")
gerber.forEach(function(v){
GEN.COM("output_layer_set,layer="+v+",angle=0,mirror=no,x_scale=1,y_scale=1,comp=0,polarity=positive,setupfile=,setupfiletmp=,line_units=inch,gscl_file=,step_scale=no")
})
GEN.COM("output,job="+job+",step="+step+",format=Gerber274x,dir_path="+par.export_path + "/" + step+",prefix=,suffix=.art,break_sr=yes,break_symbols=no,break_arc=no,scale_mode=all,surface_mode=fill,min_brush=1,units=inch,coordinates=absolute,zeroes=none,nf1=2,nf2=4,x_anchor=0,y_anchor=0,wheel=,x_offset=0,y_offset=0,line_units=inch,override_online=yes,film_size_cross_scan=0,film_size_along_scan=0,ds_model=RG6500")
}
if(excellon.length){
GEN.COM("output_layer_reset")
excellon.forEach(function(v){
GEN.COM("output_layer_set,layer="+v+",angle=0,mirror=no,x_scale=1,y_scale=1,comp=0,polarity=positive,setupfile=,setupfiletmp=,line_units=inch,gscl_file=,step_scale=no")
})
GEN.COM("output,job="+job+",step="+step+",format=Excellon2,dir_path="+par.export_path + "/" + step+",prefix=,suffix=.drill,break_sr=yes,break_symbols=yes,break_arc=no,scale_mode=all,surface_mode=fill,min_brush=1,units=inch,coordinates=absolute,decimal=no,zeroes=none,nf1=2,nf2=4,modal=yes,tool_units=inch,optimize=no,iterations=5,reduction_percent=1,cool_spread=0,x_anchor=0,y_anchor=0,x_offset=0,y_offset=0,line_units=inch,override_online=yes,canned_text_mode=break")
excellon.forEach(function(v){
GEN.COM("ncset_create,name=_1_tmp__+++_")
GEN.COM("ncset_cur,job="+job+",step="+step+",layer="+v+",ncset=")
})
}
})
// 保存
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"})}
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";
}
\ No newline at end of file
/*
NAME:
DESCRIPTION: ;
PARAMETER:
[
{
name : 'step',
title : 'step',
type : 'LineEdit',
property : {tool_tip : '目标step,默认是orig'},
},
{
name : 'export_path',
title : 'export_path',
type : 'LineEdit',
property : {tool_tip : '导出路径'},
},
{
name : 'export_layers',
title : 'export_layers',
type : 'LineEdit',
property : {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-09-01 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> step信息 </p>
<br>
<font size="3" color="#003DB2"><p>注意事项</p></font>
<p> 无 </p>
<br>
</body></html>
*/
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
console.log("==============================>template");
// 引入模块 包
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 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 = [];
var par = PAR;
var default_par = {
step: "step",
export_path:"C:/Users/ADMINI~1/Desktop/jobs/demo",
export_layers: "",
auto_save: "No",
units:"mm"
}
for(var key in default_par){ if (!par.hasOwnProperty(key) || par[key] == ""){ par[key] = default_par[key] }}
var gui = new NewGUI(GUI);
var job = Job;
try {
if(_.isEmpty(job)){throw "参数job不存在"} else { 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" } else { GEN.checkInout({job:job,mode:"out"}) } }
var stepList = getWorkStep()
if(!fs.exists(par.export_path)){
throw "导出路径不存在"
}
var export_layers = par.export_layers;
var matrix = GEN.getMatrix({job:job})
var work_layer;
if(export_layers == "") {
work_layer = Object.keys(matrix)
}
var matrix = GEN.getMatrix({job:job});
var layers = Object.keys(matrix).map(function(key){
var tmp ={};
tmp[key] = key;
return tmp
})
work_layer = gui.selectMultiple({title: "请先择工作层",list: layers,defaultvalue: work_layer,columns: 4,gen: GEN})
if(work_layer.length == 0 ) {return "没有先择layer"}
if(stepList.length == 0){throw "没有找到step"}
GEN.COM("export_job",{
job : job,
path : par.export_path,
mode : 'tar_gzip',
submode : 'partial',
del_elements : '',
steps_mode : 'include',
steps : stepList.join("\\;"),
lyrs_mode : 'include',
lyrs : work_layer.join("\\;"),
overwrite : 'yes'
});
// 保存
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"})}
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 NewGUI (gui) {
this.msgBox = function(props){ // title type content button
props = props || {}
return gui.msgBox(props.title || "title",props.type || "info",props.content || "content",props.button || ["ok", "cancel"]);
}
this.selectFromTreeview = gui.selectFromTreeview
this.confirm = function(props) {
props = props || {}
return gui.confirm(props.content || "content",props.button || ["yes", "no"], props.type || "question");
}
this.selectFile = function(props){ // "choose something", "*", true, "file", "/home/abby/fast_io"
props = props || {}
return gui.selectFile(props.title || "choose something",props.filter || "*",props.multiple || false, "file","");
}
this.selectSingle = function(props) {
props = props || {}
return gui.selectSingle({
"title": props.title || "select",
"list": props.list || [],
"default": props["default"] || "",
"columns": props.columns || 2,
"gen":props.gen || GEN
});
}
this.selectMultiple = function(props) {
props = props || {}
return gui.selectMultiple({
"title": props.title || "select",
"list": props.list || [],
"defaultvalue": props["defaultvalue"] || [""],
"defaultsize": props["defaultsize"] || [200, 100],
"columns": props.columns || 2,
"gen":props.gen || GEN
});
}
this.selectFromTable = gui.selectFromTable
this.snapScreen = gui.snapScreen
this.imageViewer = gui.imageViewer
this.inputBox = gui.inputBox
this.showForm = gui.showForm
this.selectLayer = function(props){
props = props || {}
return gui.selectLayer({
title: props.title || "请选择层",
filter: props.filter || ".*", // regular expression
selectmode: props.selectmode || "multiple", // single, multiple
context: props.context || "all", // all, board, misc
layertype: props.layertype || "signal", // default type of layertypelist
defaultsize: props.defaultsize || [600, 400], // window size
layermatrix: props.layermatrix || props.matrix,
layertypelist: props.layertypelist || [
{name: "all", display_name: "all", filter: function(x) { return x }},
{name: "signal", display_name: "signal", filter: function(x) { return x["layer_type"] === "signal"; }},
{name: "power_ground", display_name: "power_ground", filter: function(x) { return x["layer_type"] === "power_ground"; }},
{name: "mixed", display_name: "mixed", filter: function(x) { return x["layer_type"] === "mixed"; }},
{name: "solder_mask", display_name: "solder_mask", filter: function(x) { return x["layer_type"] === "solder_mask"; }},
{name: "silk_screen", display_name: "silk_screen", filter: function(x) { return x["layer_type"] === "silk_screen"; }},
{name: "solder_paste", display_name: "solder_paste", filter: function(x) { return x["layer_type"] === "solder_paste"; }},
{name: "drill", display_name: "drill", filter: function(x) { return x["layer_type"] === "drill"; }},
{name: "rout", display_name: "rout", filter: function(x) { return x["layer_type"] === "rout"; }},
{name: "document", display_name: "document", filter: function(x) { return x["layer_type"] === "document"; }}
],
gen: props.GEN || GEN
})
}
this.lockUnlockLayer = function(props){
props = props || {}
var tmp = {}
if (props.matrix) {
for (var key in props.matrix) {
var item = props.matrix[key]
tmp[key] = {
row : item.row,
name : item.name
}
}
}
return gui.lockUnlockLayer({
title: props.title || "lockUnlockLayer",
layermatrix:props.layermatrix || tmp
})
}
this.passwordBox = function(props){
props = props || {}
return gui.passwordBox({title:props.title || "password", password:props.password || "1212"})
}
this.selectJobLayer = function (props) {
props = props || {}
return gui.selectJobLayer({
layertypelist: props.layertypelist || [
{name: "all", display_name: "all", filter: function(x) { return x }},
{name: "signal", display_name: "signal", filter: function(x) { return x["layer_type"] === "signal"; }},
{name: "power_ground", display_name: "power_ground", filter: function(x) { return x["layer_type"] === "power_ground"; }},
{name: "mixed", display_name: "mixed", filter: function(x) { return x["layer_type"] === "mixed"; }},
{name: "solder_mask", display_name: "solder_mask", filter: function(x) { return x["layer_type"] === "solder_mask"; }},
{name: "silk_screen", display_name: "silk_screen", filter: function(x) { return x["layer_type"] === "silk_screen"; }},
{name: "solder_paste", display_name: "solder_paste", filter: function(x) { return x["layer_type"] === "solder_paste"; }},
{name: "drill", display_name: "drill", filter: function(x) { return x["layer_type"] === "drill"; }},
{name: "rout", display_name: "rout", filter: function(x) { return x["layer_type"] === "rout"; }},
{name: "document", display_name: "document", filter: function(x) { return x["layer_type"] === "document"; }}
],
//defaultlayertype: "ha",
joblist: props.joblist || [],
defaultJob: props.defaultJob || [], // select by default
steplist: props.steplist || [],
// defaultstep: "step3",
showstep: props.showstep || true,
selectmode: props.selectmode || "multiple", // single/multiple
layermatrix: props.layermatrix || { },
defaultlayer: props.defaultlayer || []
})
}
}
function getWorkStep(props){
var steplists = GEN.getStepList({job:job});
if(steplists.length == 0){return "该料号没有step"}
var steps_tmp = steplists.filter(function(name){
var reg = new RegExp(par.step, "ig")
return reg.test(name)
})
if(steplists.length == 0){return "根据脚本参数过滤出来的step不存在,请检查资料或者脚本参数配置!"}
var workstep = gui.selectMultiple({
title: "请先择工作step",
size:[200,100],
defaultsize:[200,100],
list: steplists.map(function(v){ var tmp = {}; tmp[v] = v ;return tmp}),
defaultvalue: steps_tmp,
columns: 1,
gen: GEN
})
if(workstep.length == 0 ) {return "没有先择step"}
return workstep
}
\ No newline at end of file
/*
NAME:
DESCRIPTION: 原稿拼底片;
PARAMETER:
[
{
name : 'out_line',
title : '外形层',
type : 'LineEdit',
property : {tool_tip : '定原稿拼片的step,如未设定,默认为org'},
},
{
name : 'step',
title : 'Org step',
type : 'LineEdit',
property : {tool_tip : '定原稿拼片的step,如未设定,默认为org'},
},
{
name : 'job_suffix',
title : '料号后缀',
type : 'LineEdit',
property : {tool_tip : '定原稿拼片的料号后缀,如未设定,默认为-org'},
},
{
name : 'path',
title : '输出路径',
type : 'LineEdit',
property : {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-09-01 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> step信息 </p>
<br>
<font size="3" color="#003DB2"><p>注意事项</p></font>
<p> 无 </p>
<br>
</body></html>
*/
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
console.log("==============================>template");
// 引入模块 包
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 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 } });
}
}
require("topsin.genmath")
var genMath = new GenMath();
var gui = new NewGUI(GUI);
var Status = 'ok';
var resultData = [];
var par = PAR;
var default_par = {
out_line:"out",
step:"step",
job_suffix:"-org",
path:"C:/Users/Administrator/Desktop/jobs/demo",
auto_save: "No",
units:"mm"
}
for(var key in default_par){ if (!par.hasOwnProperty(key) || par[key] == ""){ par[key] = default_par[key] }}
var job = Job;
var Step;
var film_size = ['20x24','22x26','24x28'];
var film_tol_number = 0; // 总的底片数量
var sold_mask_layer = []; // 阻焊层
var cust_code = "",serial="";
if(/^(?:[a-z0-9]{2})([a-z0-9]{2})(?:[a-z0-9])(?:[a-z0-9])(?:[a-z0-9])([a-z0-9]{3})(?:(?:[a-z0-9])(?:[a-z0-9])(?:[a-z0-9])|sys)(?:\-s)?/i.test(job)){
cust_code = RegExp.$1;
serial = RegExp.$2;
}
par.film_name = cust_code + serial + '-org';
try {
if(_.isEmpty(job)){throw "参数job不存在"} else { job = job.toLowerCase() }
if(!GEN.isJobExists({job:job})){throw "料号"+job+"不存在"}
var gotoFlag = false;
Job = job + par.job_suffix;
// 检查拼片料号是否存在
var films=[],tmp_matrix={};
if (GEN.isJobExists({job:Job}) ){
var matrix = GEN.getMatrix({job:Job});
// my $customer_code = $IKM->select_value(-sql =>"select c.name from job as j left join public_customer as c on j.customer_id = c.id where j.id = $JOB_ID");
Object.keys(matrix).forEach(function(layer){
var tmp_reg = new RegExp(par.film_name)
if( tmp_reg.test(layer) ){
films.push(layer);
tmp_matrix[layer] = matrix[layer];
}
})
if( films.length ){
if( GUI.confirm("料号"+Job+"在Genesis中已经存在,且已存在原稿拼片层,是否直接输出?",["yes", "no"], "question") == 'yes' ){
if( films.length > 1){
films = GUI.selectLayer({title:'请选择输出的原稿拼片层',
layermatrix:tmp_matrix,
layertype: "films", // default type of layertypelist
layertypelist: [
{name: "films", display_name: "films", filter: function(x) {
return films.indexOf(x["name"]) >= 0 ; }},
],
selectmode : 'multiple'}); // single
if(films.length == 0){throw "canel"}
}
gotoFlag = true;
}
}else{
IKM.msg("料号"+Job+"在Genesis中已经存在, 请检查!");
return 'Cancel';
}
}else{
GEN.copyJob({source_job:job,dest_job:Job,dest_database:GEN.getJobDbName({job:Job})});
}
if(!gotoFlag){
var stepList = GEN.getStepList({job:job})
stepList = stepList.filter(function(step){
var reg = new RegExp(par.step,"ig")
return reg.test(step)
})
Step = stepList[0]
if ( !GEN.isStepExists({job:Job,step:Step}) ){
IKM.msg(Step + "不存在,无法拼原稿!");
throw 'Cancel';
}
// 获取sold_mask_layer
sold_mask_layer = getLayer({layer_type:"solder_mask", context: "board"})
var matrix = GEN.getMatrix({job:Job});
var _default=[],films=[],tmp_matrix={};
for (var layer in matrix) {
if ( GEN.isLayerEmpty( {job:Job,step:Step,layer:layer}) ){
delete matrix[layer];
continue;
}
var tmp_reg = new RegExp(par.film_name)
if( tmp_reg.test(layer) ){
films.push(layer);
tmp_matrix[layer] = matrix[layer];
delete matrix[layer];
continue;
}
if( matrix[layer].context == 'board' && matrix[layer].layer_type != 'drill' ){
_default.push(layer)
}
else{
if(layer == "map" || /^m[12]\-/.test(layer)){
_default.push(layer);
}
}
}
//
if( films.length ){
if( GUI.confirm("已存在原稿拼片层,是否直接输出?" ["yes", "no"], "question") == 'yes' ){
if( films.length > 1){
films = GUI.selectLayer({title:'请选择输出的原稿拼片层',
layermatrix:tmp_matrix,
layertype: "films", // default type of layertypelist
layertypelist: [
{name: "films", display_name: "films", filter: function(x) {
return films.indexOf(x["name"]) >= 0 ; }},
],
selectmode : 'multiple'}); // single
if(films.length == 0){throw "canel"}
}
gotoFlag = true;
}
}
}
if(!gotoFlag){
var tmplayers = GUI.selectLayer({
title:'请选择需拼片原稿层',
layermatrix:matrix,
layertype:"_default",
layertypelist: [
{
name: "_default",
display_name: "_default",
filter: function (x) {
return _default.indexOf(x.name) >=0
}
},
{
name: "all",
display_name: "all",
filter: function (x) {
return true
}
}
],
selectmode:'multiple'});
if(tmplayers.length == 0){throw "cancel"}
tmplayers = tmplayers.map(function(v){return v.name})
IKM.msg(tmplayers)
// 创建拼片的辅助层
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:'inch'} );
GEN.zoomHome();
if(!GEN.isLayerExists({job:Job,layer:par.out_line})){
IKM.msg(par.out_line + "层不存在!!");
throw 'Cancel';
}
if(GEN.isLayerEmpty({job:Job,step:Step,layer:par.out_line})){
IKM.msg(par.out_line + "层为空无法创建profice!!");
throw 'Cancel';
}
// 删除板外物 除map层外 2020-07-14 Super
GEN.affectedLayer({affected:'yes',layer:par.out_line,clear_before:'yes'});
GEN.COM('sel_reverse');
if ( GEN.getSelectCount() > 1 ){
GEN.COM('sel_create_profile');
GEN.affectedLayer( {mode:'all',affected:'no'} );
}else{
GEN.COM('sel_reverse');
GEN.affectedLayer( {mode:'all',affected:'no'} );
IKM.msg(par.out_line + "层外形数量太少无法创建profice!!");
throw 'Cancel';
}
tmplayers.forEach(function(layer){
if(!/^map$/.test(layer)){
GEN.affectedLayer({affected:'yes',layer:layer,clear_before:'no'});
}
})
GEN.clipArea({layers_mode:'affected_layers',area:'profile',inout:'outside',margin:0,contour_cut:'yes'});
// 复制外形
GEN.workLayer({name:par.out_line,display_number:1,clear_before:'yes'});
tmplayers.forEach(function(layer){
if(!/^map$/.test(layer)){
GEN.affectedLayer({affected:'yes',layer:layer,clear_before:'no'});
}
})
GEN.selCopyOther({dest:'affected_layers',invert:'no'});
GEN.clearLayers();
GEN.affectedLayer( {mode:'all',affected:'no'} );
// 创建阻焊负片层
var sold_mask_negative = [];
if(sold_mask_layer.length > 0){
sold_mask_layer.forEach(function(layer){
var tmp_layer = layer+'+1';
sold_mask_negative.push(tmp_layer)
var layer_limits = GEN.getLayerLimits({job:Job,step:Step,layer:layer,units:'inch'});
GEN.createLayer({job:Job,layer:tmp_layer,context:'misc',type:'document',delete_exists:'yes'});
GEN.affectedLayer({affected:'yes',layer:tmp_layer,clear_before:'yes'});
GEN.addRectangle({x1:Number(layer_limits.xmin)-0.1,y1:Number(layer_limits.ymin)-0.1,x2:Number(layer_limits.xmax)+0.1,y2:Number(layer_limits.ymax)+0.1});
GEN.affectedLayer({affected:'yes',layer:layer,clear_before:'yes'});
GEN.selCopyOther({target_layer:tmp_layer,invert:'yes'});
GEN.selContourize();
GEN.affectedLayer({mode:'all',affected:'no'});
})
}
// 总的底片数量
film_tol_number = tmplayers.length*2 + sold_mask_layer.length;
// 创建辅助层,返回实际需拼片的层
var tmp_layers = tmplayers;
tmp_layers = tmp_layers.concat(sold_mask_negative)
// my @tmp_layers2 = @tmplayers;
create_tmp_layer({step:Step,layer:tmplayers,matrix:matrix});
var film_scheme;
var index = 1;
tmplayers = tmplayers.concat(tmp_layers)
film_size.forEach(function(filmsize){
var info = get_repeat_info({step:Step,layer:tmplayers,film_size:filmsize});
film_scheme[index].info = info;
film_scheme[index].film_count = Object.keys(info).length;
film_scheme[index].film_size = filmsize;
index++ ;
})
// 选出最优方案
var best_scheme_index;
Object.keys(film_scheme).sort().forEach(function(index){
if(best_scheme_index){
if(film_scheme[index].film_count < film_scheme[best_scheme_index].film_count){
best_scheme_index = index;
}
}else{
best_scheme_index = index;
}
})
film_repeat({step:Step,layer:tmplayers,info:film_scheme[best_scheme_index].info,film_size:film_scheme[best_scheme_index].film_size});
//画profile
var tmp_fs = film_scheme[best_scheme_index].film_size.split("x")
var film_width=tmp_fs[0],film_height = tmp_fs[1];
GEN.COM( 'profile_rect',{x1:0,y1:0,x2:film_width-0.005,y2:film_height-0.005});
//更改文字序列号
var change_layers = Object.keys(film_scheme[best_scheme_index].info).sort(function(a,b){
return film_scheme[best_scheme_index].info[a].num - film_scheme[best_scheme_index].info[b].num
})
var number = 1;
change_layers.forEach(function(layer){
GEN.affectedLayer({affected:'yes',mode:'single',layer:layer,clear_before:'yes'});
// GEN.selectByFilter(feat_types:'text',polarity:'positive',profile:'all');
var tmp_data = GEN.getFeature({job:Job,step:Step,layer:layer,surface:0,options:'feat_index'});
// var tmp_data = GEN.getFeatures(job:Job,step:Step,layer:layer,options:'select');
var txt_data = tmp_data.filter(function(v){return v.type=="text"})
// $GUI->debug(-text:dump(@txt_data,'---',layer,$Step,$Job));
txt_data.forEach(function(data){
GEN.COM('sel_layer_feat',{operation:'select',layer:layer,index:data.index});
var txt = data.text.split("/")
var new_text = number+'/'+txt[1];
GEN.COM( 'sel_change_txt',{
text:new_text,
x_size:data.x_size,
y_size:data.y_size,
w_factor:data.w_factor,
polarity:'no_change',
mirror:'no',
fontname:data.fontname
});
number++;
})
})
// 请检查拼片信息
var n = 1;
var lastflag = true
Object.keys(film_scheme[best_scheme_index].info).sort(function(a,b){
return film_scheme[best_scheme_index].info[a].num - film_scheme[best_scheme_index].info[b].num
}).forEach(function(film){
if(lastflag){
if( n == 1 ){
GEN.workLayer({name:film,display_number:1,clear_before:'yes'});
}
else{
GEN.displayLayer({name:film,number:n});
}
n++;
}
if (n > 4){lastflag = false};
})
GEN.PAUSE('Please Check Layer');
}
//
if(films.length == 0){
films = Object.keys(film_scheme[best_scheme_index].info).sort(function(a,b){
return film_scheme[best_scheme_index].info[a].num - film_scheme[best_scheme_index].info[b].num
})
}
//my $film_size = $film_scheme->{$best_scheme_index}{film_size};
//删除多余step和层别
var steps = GEN.getStepList({job:Job});
steps.forEach(function(step){
if(step != Step){
GEN.matrixDeleteStep({job:Job,step:step});
}
})
var matrix = GEN.getMatrix({job:Job});
Object.keys(matrix).forEach(function(layer){
var tmp_reg = new RegExp("^"+par.film_name)
if(!tmp_reg.test(layer)){
_deleteLayer({layer:[layer]});
}
})
GEN.checkInout({job:Job,mode:'out'});
// $GUI->debug(-text=>dump($PAR->{path}));
GEN.saveJob({job:Job});
GEN.COM('export_job',{job:Job,path:par.path,mode:'tar_gzip',submode:'full',overwrite:'yes'});
// 保存
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"})}
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 NewGUI (gui) {
this.msgBox = function(props){ // title type content button
props = props || {}
return gui.msgBox(props.title || "title",props.type || "info",props.content || "content",props.button || ["ok", "cancel"]);
}
this.selectFromTreeview = gui.selectFromTreeview
this.selectFile = function(props){ // "choose something", "*", true, "file", "/home/abby/fast_io"
props = props || {}
return gui.selectFile(props.title || "choose something",props.filter || "*",props.multiple || false, "file","");
}
this.selectSingle = function(props) {
props = props || {}
return gui.selectSingle({
"title": props.title || "select",
"list": props.list || [],
"default": props["default"] || "",
"columns": props.columns || 2,
"gen":props.gen || GEN
});
}
this.selectMultiple = function(props) {
props = props || {}
return gui.selectMultiple({
"title": props.title || "select",
"list": props.list || [],
"defaultvalue": props["defaultvalue"] || [""],
"defaultsize": props["defaultsize"] || [200, 100],
"columns": props.columns || 2,
"gen":props.gen || GEN
});
}
this.selectFromTable = gui.selectFromTable
this.snapScreen = gui.snapScreen
this.imageViewer = gui.imageViewer
this.inputBox = gui.inputBox
this.showForm = gui.showForm
this.lockUnlockLayer = function(props){
props = props || {}
var tmp = {}
if (props.matrix) {
for (var key in props.matrix) {
var item = props.matrix[key]
tmp[key] = {
row : item.row,
name : item.name
}
}
}
return gui.lockUnlockLayer({
title: props.title || "lockUnlockLayer",
layermatrix:props.layermatrix || tmp
})
}
this.passwordBox = function(props){
props = props || {}
return gui.passwordBox({title:props.title || "password", password:props.password || "1212"})
}
this.selectJobLayer = function (props) {
props = props || {}
return gui.selectJobLayer({
layertypelist: props.layertypelist || [
{name: "all", display_name: "all", filter: function(x) { return x }},
{name: "signal", display_name: "signal", filter: function(x) { return x["layer_type"] === "signal"; }},
{name: "power_ground", display_name: "power_ground", filter: function(x) { return x["layer_type"] === "power_ground"; }},
{name: "mixed", display_name: "mixed", filter: function(x) { return x["layer_type"] === "mixed"; }},
{name: "solder_mask", display_name: "solder_mask", filter: function(x) { return x["layer_type"] === "solder_mask"; }},
{name: "silk_screen", display_name: "silk_screen", filter: function(x) { return x["layer_type"] === "silk_screen"; }},
{name: "solder_paste", display_name: "solder_paste", filter: function(x) { return x["layer_type"] === "solder_paste"; }},
{name: "drill", display_name: "drill", filter: function(x) { return x["layer_type"] === "drill"; }},
{name: "rout", display_name: "rout", filter: function(x) { return x["layer_type"] === "rout"; }},
{name: "document", display_name: "document", filter: function(x) { return x["layer_type"] === "document"; }}
],
//defaultlayertype: "ha",
joblist: props.joblist || [],
defaultJob: props.defaultJob || [], // select by default
steplist: props.steplist || [],
// defaultstep: "step3",
showstep: props.showstep || true,
selectmode: props.selectmode || "multiple", // single/multiple
layermatrix: props.layermatrix || { },
defaultlayer: props.defaultlayer || []
})
}
}
function getLayer(props){
if(!props){return}
if(!props.context){props.context = "board"}
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(!Array.isArray(props[key])){props[key] = [props[key]]}
if(info[key] && props[key].indexOf(info[key]) < 0){ ret = false } }
if(ret){ a.push(props.res == "info"? info : b) } return a
},[])
}
function _deleteLayer(layers){
layers = Array.isArray(layers.layer) ? layers.layer : [layers.layer];
layers.forEach(function(layer){
if(GEN.isLayerExists({job:Job,layer:layer})){
GEN.deleteLayer({job:Job,layer:[layer]})
}
})
}
function create_tmp_layer(par){
var matrix = par.matrix;
// 先清除原先存在的辅助层
GEN.deleteLayer({job:Job,layer:['~_$'],step:par.step});
GEN.deleteLayer({job:Job,layer:['~_tl_angle$'],step:par.step});
par.layer.forEach(function(layer){
var tmp_layer = layer+'_';
var tmp_layer_angle = layer+'_tl_angle';
GEN.copyLayer({source_job:Job,source_step:par.step,source_layer:layer,dest_layer:tmp_layer,invert:'no',mode:'replace'});
// 打散层上字串
GEN.affectedLayer({affected:'yes',layer:[tmp_layer],clear_before:'yes'});
GEN.selectByFilter({feat_types:'text',profile:'all'});
if ( GEN.getSelectCount() > 0 ){GEN.COM("sel_break")};
if( matrix[layer].tl_type == 'inner' && matrix[layer].polarity != 'negative' ){
var layer_limits = GEN.getLayerLimits({job:Job,step:par.step,layer:layer,units:'inch'});
var tmp = 'pos_to_neg_tl';
GEN.createLayer({job:Job,layer:tmp,context:'board',type:'document',delete_exists:'yes'});
GEN.affectedLayer({affected:'yes',layer:[tmp],clear_before:'yes'});
GEN.addRectangle({x1:Number(layer_limits.xmin)-0.1,y1:Number(layer_limits.ymin)-0.1,x2:Number(layer_limits.xmax)+0.1,y2:Number(layer_limits.ymax)+0.1});
GEN.affectedLayer({affected:'yes',layer:[tmp_layer],clear_before:'yes'});
GEN.selCopyOther({target_layer:tmp,invert:'yes'});
GEN.copyLayer({source_job:Job,source_step:par.step,source_layer:tmp,dest_layer:tmp_layer,invert:'no',mode:'replace'});
GEN.deleteLayer({job:Job,layer:[tmp],step:par.step});
}
// $GUI->debug(dump(matrix[layer].tl_type));
GEN.copyLayer({source_job:Job,source_step:par.step,source_layer:tmp_layer,dest_layer:tmp_layer_angle,invert:'no',mode:'replace'});
//
GEN.affectedLayer({affected:'yes',layer:[tmp_layer],clear_before:'yes'});
var layer_limits = GEN.getLayerLimits({job:Job,step:par.step,layer:tmp_layer,units:'inch'});
GEN.selMove({dx:0-layer_limits.xmin+0.1,dy:0-layer_limits.ymin+0.1});
// 制作旋转辅助层
GEN.affectedLayer({affected:'yes',layer:[tmp_layer_angle],clear_before:'yes'});
GEN.selTransform({mode:'anchor',oper:'rotate',x_anchor:0,y_anchor:0,angle:90});
layer_limits = GEN.getLayerLimits({job:Job,step:par.step,layer:tmp_layer_angle,units:'inch'});
GEN.selMove({dx:0-layer_limits.xmin+0.1,dy:0-layer_limits.ymin+0.1});
// 添加文字标识
[tmp_layer,tmp_layer_angle].forEach(function(txt_data){
GEN.affectedLayer({affected:'yes',layer:txt_data,clear_before:'yes'});
var txt = '1/'+film_tol_number+' '+Job.toUpperCase()+' '+layer.toUpperCase();
var lay_limt = GEN.getLayerLimits({job:Job,step:par.step,layer:txt_data,units:'inch'});
Add_Text({x:lay_limt.xmin-0,y:lay_limt.ymin - 0.18,txt:txt,angle:0});
// GEN.createLayer(job:Job,layer:$txt_data.'+bak',context:'misc',type:'document',delete_exists:'yes');
// GEN.selCopyOther(target_layer:$txt_data.'+bak',invert:'no');
})
})
}
function get_repeat_info(par){
// 判断不旋转
var info1 = {};
var film_size = par.film_size;
var tmp_film_size = film_size.split("x")
var film_width = tmp_film_size[0],film_height = tmp_film_size[1];
var film_org = PAR.film_name+'-'+film_size;
var film_name=film_org,film_num=0,film_status="old";
var first_area,last_area,xstart,ystart;//第一张底片的范围/上一张底片的范围
par.layer.forEach(function(layer){
var tmp_layer = layer+'_';
film_status = last_area.xmin ? 'old' : 'new' ;
var layer_limits = GEN.getLayerLimits({job:Job,step:par.step,layer:tmp_layer,units:'inch'});
layer_limits.xsize = layer_limits.xsize - 0;
layer_limits.ysize = layer_limits.ysize - 0;
layer_limits.xmin = layer_limits.xmin - 0;
layer_limits.ymin = layer_limits.ymin - 0;
layer_limits.xmax = layer_limits.xmax - 0;
layer_limits.ymax = layer_limits.ymax - 0;
var tol_x = (layer_limits.xsize > layer_limits.ysize) ? 0.3 : 0.3;
var tol_y = (layer_limits.xsize > layer_limits.ysize) ? 0.3 : 0.3;
// 判断拼入后是否会超出范围
if( layer_limits.xsize > film_width && layer_limits.ysize > film_height ){
// xy都超出范围,一片一拼
film_status = 'new';
}
else if( layer_limits.xsize > film_width ){
film_status = 'new' ;//if ( ($last_area->{ymax}+ layer_limits.ysize) > $film_height );
}
else if( layer_limits.ysize > film_height ){
film_status = 'new' ;//if ( ($last_area->{xmax}+ layer_limits.xsize) > film_width );
}
else{
if ( (last_area.ymax+ layer_limits.ysize) > film_height && (last_area.xmax+ layer_limits.xsize) > film_width ){
film_status = 'new'
};
}
// 新底片的准备工作
if( film_status == 'new' ){
film_name = film_org+'-'+film_num;
info1[film_name].layers.push(layer)
info1[film_name].num = film_num;
info1[film_name].type = 'no_angle';
info1[film_name][layer].shift.x = 0;
info1[film_name][layer].shift.y = 0;
xstart.status = 1;
xstart.shifty = info1[film_name][layer].shift.y;
first_area = {
xmin: layer_limits.xmin,
ymin: layer_limits.ymin,
xmax: layer_limits.xmax + tol_x,
ymax: layer_limits.ymax + tol_y,
xsize: layer_limits.xsize + tol_x,
ysize: layer_limits.ysize + tol_y
};
last_area = first_area;
film_num++;
}else{
// Y方向添加
if ( (last_area.xsize+ layer_limits.xsize+tol_x) > film_width ){
//print dump($last_area->{xsize},'--',layer_limits.xsize,'--',film_width),"\n";
//print dump(@{$info{$film_name}{layers}}),"\n";
//GEN.PAUSE('tttt++'.$layer);
info1[film_name].layers.push(layer);
info1[film_name][layer].shift.x = 0;
info1[film_name][layer].shift.y = last_area.ymax-layer_limits.ymin;
xstart.status = 1;
xstart.shifty = info1[film_name][layer].shift.y;
//$ystart->{status} = 0;$xstart->{shiftx} = undef;
last_area = {
xmin: layer_limits.xmin,
ymin: layer_limits.ymin + info1[film_name][layer].shift.y,
xmax: layer_limits.xmax + tol_x,
ymax: info1[film_name][layer].shift.y + layer_limits.ymax + tol_y,
xsize: layer_limits.xsize + tol_x,
ysize: layer_limits.ysize + last_area.ysize + tol_y
};
}
// X方向添加
else{
info1[film_name].layers.push(layer);
info1[film_name][layer].shift.x = last_area.xmax-layer_limits.xmin;
info1[film_name][layer].shift.y = xstart.status ? xstart.shifty : last_area.ymax-last_area.xmin;
//print dump($info{$film_name}{$layer}{shift}{x},'-----',$info{$film_name}{$layer}{shift}{y}),"\n";
//GEN.PAUSE('ttt++'.$layer);
xstart.status = 1;
xstart.shifty = info1[film_name][layer].shift.y;
var high = (layer_limits.ymax+info1[film_name][layer].shift.y-0+tol_y) > last_area.ymax ? layer_limits.ymax+info1[film_name][layer].shift.y-0+tol_y : last_area.ymax;
//$ystart->{status} = 1;$ystart->{shiftx} = undef;
last_area = {
xmin: layer_limits.xmin + info1[film_name][layer].shift.x,
ymin: layer_limits.ymin + info1[film_name][layer].shift.y,
xmax: layer_limits.xmax + info1[film_name][layer].shift.x + tol_x,
ymax: high,
xsize: layer_limits.xsize + last_area.xsize + tol_x,
ysize: layer_limits.ysize + tol_y
};
}
}
})
// 判断旋转90度
var info2 = {};
film_org = PAR.film_name+'-'+film_size;
film_name = film_org,film_num=0,film_status="old";
first_area=undefined,last_area=undefined,xstart=undefined,ystart=undefined;//第一张底片的范围/上一张底片的范围
par.layer.forEach(function(layer){
var tmp_layer = layer+'_tl_angle';
film_status = last_area.xmin ? 'old' : 'new' ;
var layer_limits = GEN.getLayerLimits({job:Job,step:par.step,layer:tmp_layer,units:'inch'});
layer_limits.xsize = layer_limits.xsize - 0;
layer_limits.ysize = layer_limits.ysize - 0;
layer_limits.xmin = layer_limits.xmin - 0;
layer_limits.ymin = layer_limits.ymin - 0;
layer_limits.xmax = layer_limits.xmax - 0;
layer_limits.ymax = layer_limits.ymax - 0;
var tol_x = (layer_limits.xsize > layer_limits.ysize) ? 0.3 : 0.3;
var tol_y = (layer_limits.xsize > layer_limits.ysize) ? 0.3 : 0.3;
//判断拼入后是否会超出范围
if( layer_limits.xsize > film_width && layer_limits.ysize > film_height ){
//xy都超出范围,一片一拼
film_status = 'new';
}
else if( layer_limits.xsize > film_width ){
film_status = 'new' ;//if ( ($last_area->{ymax}+ layer_limits.ysize) > $film_height );
}
else if( layer_limits.ysize > $film_height ){
film_status = 'new' ;//if ( ($last_area->{xmax}+ layer_limits.xsize) > film_width );
}
else{
if ( (last_area.ymax+ layer_limits.ysize) > film_height && (last_area.xmax+ layer_limits.xsize) > film_width ){
film_status = 'new'
};
}
//新底片的准备工作
if( film_status == 'new' ){
film_name = film_org+'-'+film_num;
info2[film_name].layers.push(layer)
info2[film_name].num = film_num;
info2[film_name].type = 'angle';
info2[film_name][layer].shift.x = 0;
info2[film_name][layer].shift.y = 0;
xstart.status = 1;
xstart.shifty = info2[film_name][layer].shift.y;
first_area = {
xmin: layer_limits.xmin,
ymin: layer_limits.ymin,
xmax: layer_limits.xmax + tol_x,
ymax: layer_limits.ymax + tol_y,
xsize: layer_limits.xsize + tol_x,
ysize: layer_limits.ysize + tol_y
};
last_area = first_area;
film_num++;
}else{
//Y方向添加
if ( (last_area.xsize+ layer_limits.xsize+tol_x) > film_width ){
//print dump($last_area->{xsize},'--',layer_limits.xsize,'--',film_width),"\n";
//print dump(@{$info{$film_name}{layers}}),"\n";
//GEN.PAUSE('tttt++'.$layer);
info2[film_name].layers.push(layer);
info2[film_name][layer].shift.x = 0;
info2[film_name][layer].shift.y = last_area.ymax-layer_limits.ymin;
xstart.status = 1;
xstart.shifty = info2[film_name][layer].shift.y;
//$ystart->{status} = 0;$xstart->{shiftx} = undef;
last_area = {
xmin: layer_limits.xmin,
ymin: layer_limits.ymin + info2[film_name][layer].shift.y,
xmax: layer_limits.xmax + tol_x,
ymax: info2[film_name][layer].shift.y + layer_limits.ymax + tol_y,
xsize: layer_limits.xsize + tol_x,
ysize: layer_limits.ysize + last_area.ysize + tol_y
};
}
//#X方向添加
else{
info2[film_name].layers.push(layer);
info2[film_name][layer].shift.x = last_area.xmax-layer_limits.xmin;
info2[film_name][layer].shift.y = xstart.status ? xstart.shifty : last_area.ymax-last_area.xmin;
//print dump($info{$film_name}{$layer}{shift}{x},'-----',$info{$film_name}{$layer}{shift}{y}),"\n";
//GEN.PAUSE('ttt++'.$layer);
xstart.status = 1;
xstart.shifty = info2[film_name][layer].shift.y;
var high = (layer_limits.ymax+info2[film_name][layer].shift.y-0+tol_y) > last_area.ymax ? layer_limits.ymax+info2[film_name][layer].shift.y-0+tol_y : last_area.ymax;
//$ystart->{status} = 1;$ystart->{shiftx} = undef;
last_area = {
xmin: layer_limits.xmin + info2[film_name][layer].shift.x,
ymin: layer_limits.ymin + info2[film_name][layer].shift.y,
xmax: layer_limits.xmax + info2[film_name][layer].shift.x + tol_x,
ymax: high,
xsize: layer_limits.xsize + last_area.xsize + tol_x,
ysize: layer_limits.ysize + tol_y
};
}
}
})
//
if( Object.keys(info2).length < Object.keys(info1).length){
return info2;
}
else{
return info1;
}
}
function film_repeat(par){
var film_size = par.film_size;
var tmp_film_size = film_size.split("x")
var film_width = tmp_film_size[0];
var film_height = tmp_film_size[1];
var info = par.info;
Object.keys(info).sort(function(a,b){return info[a].num - info[b].num}).forEach(function(film){
if(info[film].layers){
GEN.createLayer({job:Job,layer:film,conext:'misc',type:'document',delete_exists:'yes'});
GEN.affectedLayer({affected:'yes',layer:[film],clear_before:'yes'});
// my $all = scalar(@{$info{$film}{layers}});
// $GUI->debug(dump($film, $info{$film}{layers}));
var n = 1;
info[film].layers.forEach(function(layer){
var tmp_layer = info[film].type == 'no_angle' ? layer+'_' : layer+'_tl_angle';
GEN.affectedLayer({affected:'yes',layer:[tmp_layer],clear_before:'yes'});
GEN.selMove({dx:info[film][layer].shift.x,dy:info[film][layer].shift.y});
GEN.copyLayer({source_job:Job,source_step:par.step,source_layer:tmp_layer,dest_layer:film,invert:'no',mode:'append'});
GEN.selMove({dx:-info[film][layer].shift.x,dy:-info[film][layer].shift.y});
// GEN.deleteLayer(job:Job,layer:[$layer.'_',$layer.'_tl_angle'],step:par.step);
n++;
})
GEN.affectedLayer({affected:'yes',layer:[film],clear_before:'yes'});
// 移动居中
var layer_limits = GEN.getLayerLimits({job:Job,step:Step,layer:film,units:'inch'});
layer_limits.xc = layer_limits.xsize/2-Math.abs(layer_limits.xmin);
layer_limits.yc = layer_limits.ysize/2-Math.abs(layer_limits.ymin);
GEN.selMove({dx:film_width/2-layer_limits.xc,dy:film_height/2-layer_limits.yc});
//
GEN.addRectangle({x1:0,y1:0,x2:film_width-0.005,y2:film_height-0.005,type:'line',symbol:'r5'});
}
})
}
// =head
// 增加文字 Add_Text(x=>,y=>,txt=>,angle=>)
// =cut
function Add_Text(par){
GEN.COM('add_text',{
attributes:'no',
type:'string',
x:par.x,
y:par.y,
text:par.txt,
x_size:0.15,
y_size:0.15,
w_factor:1.6666666269,
polarity:'positive',
angle:par.angle,
mirror:'no',
fontname:'simple',
ver:1
})
}
\ No newline at end of file
/*
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 2020-09-01 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> step信息 </p>
<br>
<font size="3" color="#003DB2"><p>注意事项</p></font>
<p> 无 </p>
<br>
</body></html>
*/
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
console.log("==============================>template");
// 引入模块 包
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 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 = [];
var par = PAR;
var default_par = {
step: "orig",
auto_save: "No",
units:"mm"
}
for(var key in default_par){ if (!par.hasOwnProperty(key) || par[key] == ""){ par[key] = default_par[key] }}
var job = Job;
try {
if(_.isEmpty(job)){throw "参数job不存在"} else { 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" } else { GEN.checkInout({job:job,mode:"out"}) } }
var stepList = GEN.getStepList({job:job})
stepList = stepList.filter(function(step){
var reg = new RegExp(par.step,"ig")
return reg.test(step)
})
GEN.PAUSE("Ok")
IKM.msg("Ok")
// 保存
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"})}
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";
}
\ No newline at end of file
/*
NAME:
DESCRIPTION: ;
PARAMETER:
[
{
name : 'pcs',
title : 'pcs名称',
type : 'LineEdit',
property : {tool_tip : 'pcs名称'},
},
{
name : 'set',
title : 'set名称',
type : 'LineEdit',
property : {tool_tip : 'set名称'},
},
{
name : 'panel',
title : 'panel名称',
type : 'LineEdit',
property : {tool_tip : 'panel名称'},
},
{
name : 'outline',
title : 'outline层名称',
type : 'LineEdit',
property : {tool_tip : 'outline层名称'},
},
{
name : 'drill',
title : 'drill层名称',
type : 'LineEdit',
property : {tool_tip : 'drill层名称'},
},
{
name : 'dc',
title : '钉床层名称',
type : 'LineEdit',
property : {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-09-01 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> step信息 </p>
<br>
<font size="3" color="#003DB2"><p>注意事项</p></font>
<p> 无 </p>
<br>
</body></html>
*/
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
console.log("==============================>template");
// 引入模块 包
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 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 } });
}
}
require("topsin.genmath")
var genMath = new GenMath();
addApi(genMath);
var gui = new NewGUI(GUI);
var Status = 'ok';
var resultData = [];
var par = PAR;
var default_par = {
pcs:"edit",
set:"step",
panel:"panel",
outline:"out",
drill:"drl",
dc:"dc",
auto_save: "No",
units:"mm"
}
for(var key in default_par){ if (!par.hasOwnProperty(key) || par[key] == ""){ par[key] = default_par[key] }}
var job = Job;
try {
if(_.isEmpty(job)){throw "参数job不存在"} else { 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" } else { GEN.checkInout({job:job,mode:"out"}) } }
var stepList = GEN.getStepList({job:job})
stepList = stepList.filter(function(step){
var reg = new RegExp(par.step,"ig")
return reg.test(step)
})
var edit = par.pcs;
var step = par.set;
var panel = par.panel;
var out_layer = par.outline;
var drill_layer = par.drill;
var dc_layer = par.dc;
var auto_save = par.auto_save;
var units = par.units;
GEN.openStep({job:job,name:panel});
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:units });
GEN.zoomHome();
GEN.createLayer({job:job,layer:dc_layer,context:'misc',type:'drill',delete_exists:'yes'});
// 添加板边孔
// copy钻孔层所有r3148的孔和r490的孔
GEN.workLayer({name:drill_layer, clear_before:'yes'});
GEN.selectByFilter({feat_type:'pad', polarity:'positive', include_syms:'r3148\;r490', profile:'in'});
if (GEN.getSelectCount()>0){GEN.selCopyOther({dest:'layer_name', target_layer:dc_layer}) };
// 距离板内0.2mm添加一圈2.6mm的孔,间隔距离30~50mm
GEN.workLayer({name:dc_layer, clear_before:'yes'});
var dist_edge = 0.2; // 孔边距离板内的距离
var size = 2600;
var dist_center = dist_edge + size / 2000;
var symbol = 'r' + size;
var sr_limit = GEN.getSRLimits({job:job,step:panel,units:units});
sr_limit.xmin = Number(sr_limit.xmin) - dist_center;
sr_limit.xmax = Number(sr_limit.xmax) + dist_center;
sr_limit.ymin = Number(sr_limit.ymin) - dist_center;
sr_limit.ymax = Number(sr_limit.ymax) + dist_center;
sr_limit.xsize = sr_limit.xmax - sr_limit.xmin;
sr_limit.ysize = sr_limit.ymax - sr_limit.ymin;
var nx = parseInt(sr_limit.xsize / 30) + 1;
var dx = sr_limit.xsize / (nx - 1);
var ny = parseInt(sr_limit.ysize / 30) - 1;
var dy = sr_limit.ysize / (ny + 1);
GEN.addPad({x:sr_limit.xmin,y:sr_limit.ymin,nx:nx,dx:dx * 1000,symbol:symbol});
GEN.addPad({x:sr_limit.xmin,y:sr_limit.ymax,nx:nx,dx:dx * 1000,symbol:symbol});
GEN.addPad({x:sr_limit.xmin,y:sr_limit.ymin + dy,ny:ny,dy:dy * 1000,symbol:symbol});
GEN.addPad({x:sr_limit.xmax,y:sr_limit.ymin + dy,ny:ny,dy:dy * 1000,symbol:symbol});
// 去除与dir层料号孔重叠的孔
GEN.selRefFeat({layers:drill_layer,mode:'touch',include_syms:'r490',filter:{include_syms:symbol}});
if (GEN.getSelectCount() > 0){GEN.selDelete() };
// 添加拼版间距孔
var repeat = GEN.getRepeat({job:job,step:panel,units:units});
var gap_lines = get_gap_lines({repeat:repeat});
var gap_pin_syms = get_gap_pin_syms({gap_lines:gap_lines, step : 30, size_list : [2600, 1600]});
gap_pin_syms.forEach(function(sym){
GEN.addPad(sym);
})
// 添加板内捞槽孔
var work_step = GEN.isStepExists({job:job,step:step}) ? step : edit;
if (!GEN.isStepExists({job:job,step:work_step})) {
throw "不存在edit或step:" + work_step
}
GEN.createLayer({job:job,layer:'tl_script_surface',delete_exists:'yes'});
if (work_step == step) {
GEN.openStep({job:job,name:edit});
GEN.srFill({layer:'tl_script_surface'});
GEN.closeStep();
}
GEN.openStep({job:job,name:work_step});
GEN.units({type:units} );
GEN.srFill({layer:'tl_script_surface'});
GEN.flattenLayer({source_layer:'tl_script_surface',target_layer:'tl_script_surface_flatten'});
GEN.workLayer({name:'tl_script_surface_flatten', clear_before:'yes'});
GEN.selContourize();
GEN.workLayer({name:out_layer, clear_before:'yes'});
GEN.selCopyOther({target_layer:'tl_script_surface_flatten',invert:'yes'});
GEN.workLayer({name:'tl_script_surface_flatten', clear_before:'yes'});
GEN.selContourize();
var features = GEN.getFeatures({job:job,step:work_step,layer:'tl_script_surface_flatten',options:'feat_index',surface:1,units:units});
//$GUI->debug(dump(@features));
var indexes = [];
var polygons = [];
features.forEach(function(feature){
if(feature.type == "surface"){
if(feature.feats.filter(function(v){return /^#OB \S+ \S+ H$/.test(v)}).length == 0){
var polygon = profile2Polygon(feature.feats);
var area = polygonArea(JSON.parse(JSON.stringify(polygon)));
if(area && area > 30){
indexes.push(feature.index)
polygons.push(polygon)
}
}
}
})
if(GEN.isLayerExists({job:job,layer:"tl_script_inner_rout"})){GEN.deleteLayer({job:job,layer:"tl_script_inner_rout"})}
GEN.createLayer({job:job,layer:'tl_script_inner_rout'});
indexes.forEach(function(index){
GEN.COM("sel_layer_feat,operation=select,layer=tl_script_surface_flatten,index="+index);
})
if(GEN.getSelectCount()>0){
GEN.selCopyOther({target_layer:'tl_script_inner_rout'})
};
if(GEN.isLayerExists({job:job,layer:"tl_script_inner_dc"})){GEN.deleteLayer({job:job,layer:"tl_script_inner_dc"})}
GEN.createLayer({job:job,layer:'tl_script_inner_dc',delete_exists:'yes'});
GEN.workLayer({name:'tl_script_inner_dc', clear_before:'yes'});
var rout_pin_syms = get_rout_pin_syms({polygons:polygons, step:30, size_list:[2600, 1600]});
rout_pin_syms.forEach(function(sym){
GEN.addPad(sym);
})
// 添加防焊开窗孔
var matrix = GEN.getMatrix({job:job});
var tmp_matrix = {};
// 获取防焊层
for (var layer in matrix) {
if(matrix[layer].context == "board" && matrix[layer].layer_type=="solder_mask"){
tmp_matrix[layer] = matrix[layer];
}
}
var sm_layer = gui.selectSingle({title:"请选择防焊层别",list: Object.keys(tmp_matrix).map(function(key){
var tmp = {};
tmp[key] = key
return tmp
}),"default": Object.keys(tmp_matrix)[0]})
var outer_layer = sm_layer == /smb/ ? 'bot' : 'top';
GEN.flattenLayer({source_layer:outer_layer,target_layer:outer_layer+'_flatten'});
GEN.flattenLayer({source_layer:drill_layer,target_layer:drill_layer+'_flatten'});
GEN.flattenLayer({source_layer:sm_layer,target_layer:sm_layer+'_flatten'});
GEN.workLayer({name:sm_layer+'_flatten', clear_before:'yes'});
GEN.selContourize();
GEN.selRefFeat({layers:'tl_script_inner_rout'});
if( GEN.getSelectCount()>0){GEN.selDelete()};
GEN.selRefFeat({layers:drill_layer+'_flatten'});
if( GEN.getSelectCount()>0){GEN.selDelete()};
var out_symbols_sys = GEN.getLayerSymsHist({job:job,step:work_step,layer:outer_layer+'_flatten',units:'mm'});
var out_symbols = Object.keys(out_symbols_sys).filter(function(symbol){
if(/^[rs]([0-9.]+)/.test(symbol)){
return RegExp.$1 < 1600
} else if (/^(rect|oval)([0-9.]+)x([0-9.]+)/.test(symbol)) {
return RegExp.$2 < 1600 || RegExp.$3 < 1600
} else {
return false
}
})
GEN.selRefFeat({layers:outer_layer+'_flatten', include_syms:out_symbols.join('\;')});
//$GUI->debug(dump(@out_symbols));
GEN.closeStep();
GEN.openStep({job:job,name:panel});
GEN.units( {type:units} );
GEN.flattenLayer({source_layer:'tl_script_inner_dc',target_layer:'tl_script_inner_dc_flatten'});
GEN.workLayer({name:'tl_script_inner_dc_flatten', clear_before:'yes'});
GEN.selCopyOther({target_layer:dc_layer});
GEN.workLayer({name:dc_layer, clear_before:'yes'});
GEN.selCopyOther({target_layer:dc_layer+'_tmp'});
GEN.workLayer({name:dc_layer+'_tmp', clear_before:'yes'});
GEN.COM("sel_resize,size=60000,corner_ctl=no");
GEN.flattenLayer({source_layer:sm_layer+'_flatten',target_layer:sm_layer+'_flatten_panel'});
GEN.createLayer({job:job,layer:'tl_script_sm_dc',delete_exists:'yes'});
GEN.workLayer({name:'tl_script_sm_dc', clear_before:'yes'});
var sm_features = GEN.getFeatures({job:job,step:panel,layer:sm_layer+'_flatten_panel',options:'feat_index',surface:1,units:units});
sm_features.forEach(function(feature){
if(feature.type == "surface"){
if(feature.feats.filter(function(v){return /^#OB \S+ \S+ H$/.test(v)}).length == 0){
var polygon = profile2Polygon(feature.feats);
var limits = polygonLimits(polygon);
if(limits.xsize >= 1.6 && limits.ysize >= 1.6){
var x = (Number(limits.xmin) + Number(limits.xmax)) / 2;
var y = (Number(limits.ymin) + Number(limits.ymax)) / 2;
GEN.addPad({x:x, y:y, symbol:'r1600'});
}
}
}
})
GEN.selRefFeat({layers:sm_layer+'_flatten_panel', mode:'cover'});
GEN.selReverse();
if( GEN.getSelectCount() > 0){GEN.selDelete() };
GEN.selRefFeat({layers:dc_layer+'_tmp'});
if( GEN.getSelectCount() > 0){GEN.selDelete() };
GEN.selCopyOther({target_layer:dc_layer});
// 清理辅助层
matrix = GEN.getMatrix({job:job,type:'hash'});
var tmp_layers = Object.keys(matrix).filter(function(v){return /^tl_script/.test(v)});
GEN.deleteLayer({job:job,layer:tmp_layers});
GEN.deleteLayer({job:job,layer:outer_layer+'_flatten'});
GEN.deleteLayer({job:job,layer:drill_layer+'_flatten'});
GEN.deleteLayer({job:job,layer:sm_layer+'_flatten'});
GEN.deleteLayer({job:job,layer:sm_layer+'_flatten_panel'});
GEN.deleteLayer({job:job,layer:dc_layer+'_tmp'});
// 保存
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"})}
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 get_rout_pin_syms(par) {
var polygons = par.polygons;
var step = par.step;
var size_list = par.size_list.sort(function(a,b){return b-a})
var symbols = [];
polygons.forEach(function(polygon){
var limits = polygonLimits(polygon);
var sym_size;
size_list.forEach(function(size){
if (limits.xsize >= (size / 1000) && limits.ysize >= (size / 1000) && !sym_size) {
sym_size = size;
}
})
if (sym_size) {
var box = genMath.resizeBox(limits, -(2 + sym_size / 2000));
resizeBox(box)
var direct = limits.xsize > limits.ysize ? 'w' : 'n';
var points = genMath.gpListArea(box, step, direct, '', 'normal');
points = points.map(function (v) {
v.symbol = "r" + sym_size;
return v
});
points.forEach(function (point) {
var point_size = point.symbol.slice(1) - 0;
var size_idx = size_list.reduce(function(a,b){if(b == point_size){a=b} ;return a}, 0)
size_list.forEach(function(v,i){if(v==size_idx){size_idx = i}})
var dist = point2polygon_dist(point, polygon);
if (dist <= (point_size / 2000)) {
size_idx++;
while (size_idx < size_list.length) {
var size = size_list[size_idx];
if (dist > (size / 2000)) {
point.symbol = "r" + size;
symbols.push(point);
break;
}
size_idx++;
}
} else {
symbols.push(point)
}
})
}
})
return symbols
}
function polygonLimits(par) {
var tmpx = par.map(function(v){return v.x}).sort(function(a,b){return a-b})
var xmin = tmpx[0]
var xmax = tmpx[tmpx.length - 1]
var tmpy = par.map(function(v){return v.y}).sort(function(a,b){return a-b})
var ymin = tmpy[0]
var ymax = tmpy[tmpy.length - 1]
var xsize = xmax - xmin;
var ysize = ymax - ymin;
return {xmin:xmin, xmax:xmax, ymin:ymin, ymax:ymax, xsize:xsize, ysize:ysize};
}
function polygonArea(points) {
if (points.length < 3) {
return;
}
if(points[0].x != points[points.length - 1].x || points[0].y != points[points.length - 1].y){
points.push(points[0])
}
var area = 0;
while(points.length >= 2){
area += points[0].x*points[1].y - points[1].x*points[0].y;
points.shift();
}
return area > 0 ? (area/2.0) : -(area/2.0);
}
function get_gap_pin_syms(par) {
var gap_lines = par.gap_lines;
var step = par.step;
var size_list = par.size_list.sort(function(b,a){return a-b});
var symbols = [];
gap_lines.forEach(function(line){
Object.keys(line).forEach(function(key){
line[key] = Number(line[key])
})
var sym_size;
size_list.forEach(function(size){
if (line.width >= size / 1000 && !sym_size) {
sym_size = size;
}
})
if(sym_size){
var symbol = "r"+sym_size;
if (line.xs == line.xe) {
for (var y = line.ys + 5; y <= line.ye - 5; y += 30) {
var pin = {x:line.xs,y:y,symbol:symbol};
var found_nearly = 0;
symbols.forEach(function(other){
var dist = genMath.point2PointDis(pin,other);
if (dist < 29 && !found_nearly) {
found_nearly = 1;
}
})
if(found_nearly==0){
symbols.push(pin)
}
}
} else if (line.ys == line.ye) {
for (var x = line.xs + 5; x <= line.xe - 5; x += 30) {
var pin = {x:x,y:line.ys,symbol:symbol};
var found_nearly = 0;
symbols.forEach(function(other){
var dist = genMath.point2PointDis(pin,other);
if (dist < 29 && !found_nearly) {
found_nearly = 1;
}
})
if(found_nearly==0){
symbols.push(pin)
}
}
}
}
})
return symbols
}
function get_gap_lines(par) {
var repeat = par.repeat;
var lines = [];
for (var i = 0; i < repeat.length; i++) {
var step1 = repeat[i];
for (var j = i+1; j < repeat.length; j++) {
var step2 = repeat[j];
// 判断x和y方向坐标范围是否有重合,有部分重合且相邻的才需要处理
if ((step1.xmax < step2.xmin || step1.xmin > step2.xmax) && (step1.ymax < step2.ymin || step1.ymin > step2.ymax)) {
continue;
}
if (step1.xmax < step2.xmin || step1.xmin > step2.xmax) {
var gap_x = genMath.minInArray(Math.abs(step1.xmax - step2.xmin),Math.abs(step1.xmin - step2.xmax));
if (gap_x > 0 && gap_x < 20) {
var x_sites = [step1.xmin, step1.xmax, step2.xmin, step2.xmax].sort(function(a,b){return a-b});
var y_sites = [step1.ymin, step1.ymax, step2.ymin, step2.ymax].sort(function(a,b){return a-b});
var xs = (Number(x_sites[1]) + Number(x_sites[2])) / 2;
var xe = xs;
var ys = y_sites[1];
var ye = y_sites[2];
var line = {xs:xs,xe:xe,ys:ys,ye:ye,width:gap_x};
lines.push(line)
}
}
else {
var gap_y = genMath.minInArray(Math.abs(step1.ymax - step2.ymin),Math.abs(step1.ymin - step2.ymax));
if (gap_y > 0 && gap_y < 20) {
var x_sites = [step1.xmin, step1.xmax, step2.xmin, step2.xmax].sort(function(a,b){return a-b});
var y_sites = [step1.ymin, step1.ymax, step2.ymin, step2.ymax].sort(function(a,b){return a-b});
var xs = x_sites[1];
var xe = x_sites[2];
var ys = (Number(y_sites[1]) + Number(y_sites[2])) / 2;
var ye = ys;
var line = {xs:xs,xe:xe,ys:ys,ye:ye,width:gap_y};
lines.push(line)
}
}
}
}
// 截断与step相交的线
for (var i = lines.length; i >= 0; i--) {
var line = lines[i];
repeat.forEach(function(step){
var rect = {x1:step.xmin,x2:step.xmax,y1:step.ymin,y2:step.ymax};
var points = get_line_rect_intersect(line, rect);
// var dist = genMath.line2RectDis(line,rect); // js genmath无此api
if (points.length > 0) {
var new_lines = [];
if (points.length == 1) {
if (line.xs == line.xe) {
if (line.ys > rect.y1 && line.ys < rect.y2) {
new_lines.push({xs : line.xe, ys : line.ye, xe : points[0].x, ye : points[0].y, width:line.width});
}
else {
new_lines.push({xs : line.xs, ys : line.ys, xe : points[0].x, ye : points[0].y, width:line.width});
}
}
else if (line.ys == line.ye) {
if (line.xs > rect.x1 && line.xs < rect.x2) {
new_lines.push({xs : line.xe, ys : line.ye, xe : points[0].x, ye : points[0].y, width:line.width});
}
else {
new_lines.push({xs : line.xs, ys : line.ys, xe : points[0].x, ye : points[0].y, width:line.width});
}
}
}
else if (points.length == 2) {
if (line.xs == line.xe) {
var sites = [{x:line.xs,y:line.ys},{x:line.xe,y:line.ye},points[0],points[1]].sort(function(a,b){return a.y-b.y});
new_lines.push({xs : sites[0].x, ys : sites[1].y, xe : sites[1].x, ye : sites[1].y, width:line.width});
new_lines.push({xs : sites[2].x, ys : sites[2].y, xe : sites[3].x, ye : sites[3].y, width:line.width});
}
else if (line.ys == line.ye) {
var sites = [{x:line.xs,y:line.ys},{x:line.xe,y:line.ye},points[0],points[1]].sort(function(a,b){return a.x-b.x});
new_lines.push({xs : sites[0].x, ys : sites[1].y, xe : sites[1].x, ye : sites[1].y, width:line.width});
new_lines.push({xs : sites[2].x, ys : sites[2].y, xe : sites[3].x, ye : sites[3].y, width:line.width});
}
}
lines.splice(i, 1);
lines.push(new_lines)
}
})
}
// 将连续线连接
var pair_array = [];
for (var i = 0; i < lines.length; i++) {
var line1 = lines[i];
for (var j = i+1; j < lines.length; j++) {
var line2 = lines[j];
var is_continue = 0;
if (line1.xs == line1.xe && line2.xs == line2.xe && line1.xs == line2.xs) {
var y_sites =[line1.ys, line1.ye, line2.ys, line2.ye].sort(function(a,b){return a-b});
if (y_sites[2] - y_sites[1] < 20) {
var new_line = {xs:line1.xs, xe:line1.xe, ys:y_sites[0], ye:y_sites[3]};
is_continue = 1;
}
}
else if (line1.ys == line1.ye && line2.ys == line2.ye && line1.ys == line2.ys) {
var x_sites = [line1.xs, line1.xe, line2.xs, line2.xe].sort(function(a,b){return a-b});
if (x_sites[2] - x_sites[1] < 20) {
var new_line = {xs:x_sites[0], xe:x_sites[3], ys:line1.ys, ye:line1.ye};
is_continue = 1;
}
}
if (is_continue) {
var found = 0;
pair_array.forEach(function(pair,index){
if (pair.filter(function(v){return v==i||v==j}).length > 0) { //? todo
var tmp = pair.concat([i, j]);
// tmp 去重
tmp = tmp.reduce(function(a,b){
if(a.indexOf(b) < 0) {
a.push(b)
}
return a
}, [])
pair_array[index] = tmp;
found = 1;
}
})
if (found == 0) {
pair_array.push([i,j])
}
}
}
var found_in_pair = 0;
pair_array.forEach(function(pair){
if(pair.filter(function(v){return v==i}).length > 0){
found_in_pair = 1;
}
})
if (found_in_pair == 0) {
pair_array.push([i])
}
}
var new_lines = [];
pair_array.forEach(function(pair){
if (pair.length == 1) {
new_lines.push(lines[pair[0]])
} else {
var x_sites = pair.reduce(function(a,b){a.push(lines[b].xs);a.push(lines[b].xe);return a},[]).sort();
var y_sites = pair.reduce(function(a,b){a.push(lines[b].ys);a.push(lines[b].ye);return a},[]).sort();
new_lines.push({xs:x_sites[0],ys:y_sites[0],xe:x_sites[x_sites.length-1],ye:y_sites[y_sites.length-1],width:lines[pair[0]].width})
}
})
return new_lines;
}
function point2polygon_dist(point,polygon ) {
var min_dist = 9999999;
for (var i = 0; i < polygon.length - 1; i++) {
var line = {xs:polygon[i].x, ys:polygon[i].y, xe:polygon[i+1].x, ye:polygon[i+1].y};
var dist = genMath.point2LineDis(point,line);
if(dist < min_dist){
min_dist = dist
}
}
return min_dist;
}
// 获取线跟矩形交点
function get_line_rect_intersect(line,rect) {
var intersects = [];
var edges = [
{xs:rect.x1,ys:rect.y1,xe:rect.x1,ye:rect.y2},
{xs:rect.x1,ys:rect.y2,xe:rect.x2,ye:rect.y2},
{xs:rect.x2,ys:rect.y2,xe:rect.x2,ye:rect.y1},
{xs:rect.x2,ys:rect.y1,xe:rect.x1,ye:rect.y1}
];
edges.forEach(function(edge){
var point = genMath.getLineIntersect(line,edge,0);
if(point){
intersects.push(point)
}
})
return intersects
}
function addApi(api){
api.minInArray = function(){
var arr = [];
[].forEach.call(arguments,function(v){
if(Array.isArray(v)){
arr = arr.concat(v)
} else {
arr.push(v)
}
})
return arr.reduce(function(a,b){return a<b? a:b})
}
}
function NewGUI (gui) {
this.msgBox = function(props){ // title type content button
props = props || {}
return gui.msgBox(props.title || "title",props.type || "info",props.content || "content",props.button || ["ok", "cancel"]);
}
this.selectFromTreeview = gui.selectFromTreeview
this.confirm = function(props) {
props = props || {}
return gui.confirm(props.content || "content",props.button || ["yes", "no"], props.type || "question");
}
this.selectFile = function(props){ // "choose something", "*", true, "file", "/home/abby/fast_io"
props = props || {}
return gui.selectFile(props.title || "choose something",props.filter || "*",props.multiple || false, "file","");
}
this.selectSingle = function(props) {
props = props || {}
return gui.selectSingle({
"title": props.title || "select",
"list": props.list || [],
"default": props["default"] || "",
"columns": props.columns || 2,
"gen":props.gen || GEN
});
}
this.selectMultiple = function(props) {
props = props || {}
return gui.selectMultiple({
"title": props.title || "select",
"list": props.list || [],
"defaultvalue": props["defaultvalue"] || [""],
"defaultsize": props["defaultsize"] || [200, 100],
"columns": props.columns || 2,
"gen":props.gen || GEN
});
}
this.selectFromTable = gui.selectFromTable
this.snapScreen = gui.snapScreen
this.imageViewer = gui.imageViewer
this.inputBox = gui.inputBox
this.showForm = gui.showForm
this.selectLayer = function(props){
props = props || {}
return gui.selectLayer({
title: props.title || "请选择层",
filter: props.filter || ".*", // regular expression
selectmode: props.selectmode || "multiple", // single, multiple
context: props.context || "all", // all, board, misc
layertype: props.layertype || "signal", // default type of layertypelist
defaultsize: props.defaultsize || [600, 400], // window size
layermatrix: props.layermatrix || props.matrix,
layertypelist: props.layertypelist || [
{name: "all", display_name: "all", filter: function(x) { return x }},
{name: "signal", display_name: "signal", filter: function(x) { return x["layer_type"] === "signal"; }},
{name: "power_ground", display_name: "power_ground", filter: function(x) { return x["layer_type"] === "power_ground"; }},
{name: "mixed", display_name: "mixed", filter: function(x) { return x["layer_type"] === "mixed"; }},
{name: "solder_mask", display_name: "solder_mask", filter: function(x) { return x["layer_type"] === "solder_mask"; }},
{name: "silk_screen", display_name: "silk_screen", filter: function(x) { return x["layer_type"] === "silk_screen"; }},
{name: "solder_paste", display_name: "solder_paste", filter: function(x) { return x["layer_type"] === "solder_paste"; }},
{name: "drill", display_name: "drill", filter: function(x) { return x["layer_type"] === "drill"; }},
{name: "rout", display_name: "rout", filter: function(x) { return x["layer_type"] === "rout"; }},
{name: "document", display_name: "document", filter: function(x) { return x["layer_type"] === "document"; }}
],
gen: props.GEN || GEN
})
}
this.lockUnlockLayer = function(props){
props = props || {}
var tmp = {}
if (props.matrix) {
for (var key in props.matrix) {
var item = props.matrix[key]
tmp[key] = {
row : item.row,
name : item.name
}
}
}
return gui.lockUnlockLayer({
title: props.title || "lockUnlockLayer",
layermatrix:props.layermatrix || tmp
})
}
this.passwordBox = function(props){
props = props || {}
return gui.passwordBox({title:props.title || "password", password:props.password || "1212"})
}
this.selectJobLayer = function (props) {
props = props || {}
return gui.selectJobLayer({
layertypelist: props.layertypelist || [
{name: "all", display_name: "all", filter: function(x) { return x }},
{name: "signal", display_name: "signal", filter: function(x) { return x["layer_type"] === "signal"; }},
{name: "power_ground", display_name: "power_ground", filter: function(x) { return x["layer_type"] === "power_ground"; }},
{name: "mixed", display_name: "mixed", filter: function(x) { return x["layer_type"] === "mixed"; }},
{name: "solder_mask", display_name: "solder_mask", filter: function(x) { return x["layer_type"] === "solder_mask"; }},
{name: "silk_screen", display_name: "silk_screen", filter: function(x) { return x["layer_type"] === "silk_screen"; }},
{name: "solder_paste", display_name: "solder_paste", filter: function(x) { return x["layer_type"] === "solder_paste"; }},
{name: "drill", display_name: "drill", filter: function(x) { return x["layer_type"] === "drill"; }},
{name: "rout", display_name: "rout", filter: function(x) { return x["layer_type"] === "rout"; }},
{name: "document", display_name: "document", filter: function(x) { return x["layer_type"] === "document"; }}
],
//defaultlayertype: "ha",
joblist: props.joblist || [],
defaultJob: props.defaultJob || [], // select by default
steplist: props.steplist || [],
// defaultstep: "step3",
showstep: props.showstep || true,
selectmode: props.selectmode || "multiple", // single/multiple
layermatrix: props.layermatrix || { },
defaultlayer: props.defaultlayer || []
})
}
}
function resizeBox(box){
box.xmin = Number(box.xmin);
box.xmax = Number(box.xmax);
box.ymin = Number(box.ymin);
box.ymax = Number(box.ymax);
box.xsize = Math.abs(box.xmin-box.xmax)
box.ysize = Math.abs(box.ymin-box.ymax)
box.ld = { "x" : box.xmin, "y" : box.ymin }
box.lu = { "x" : box.xmin, "y" : box.ymax }
box.rd = { "x" : box.xmax, "y" : box.ymin }
box.ru = { "x" : box.xmax, "y" : box.ymax }
}
function profile2Polygon(feat) {
var info = [];
feat.forEach(function(v){
if (/^#O. ([\S]+) ([\S]+)/.test(v)) {
info.push({
x: RegExp.$1 - 0,
y: RegExp.$2 - 0
})
}
})
return info
}
\ No newline at end of file
/*
NAME:
DESCRIPTION: ;
PARAMETER:
[
{
name : 'step',
title : 'step',
type : 'LineEdit',
property : {tool_tip : '目标step,默认是orig'},
},
{
name : 'orig_step',
title : 'orig_step',
type : 'LineEdit',
property : {tool_tip : '原稿step名称'},
},
{
name : 'export_path',
title : 'export_path',
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 2020-09-01 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> step信息 </p>
<br>
<font size="3" color="#003DB2"><p>注意事项</p></font>
<p> 无 </p>
<br>
</body></html>
*/
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
console.log("==============================>template");
// 引入模块 包
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 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 = [];
var par = PAR;
var default_par = {
orig_step:"orig",
step: "step",
export_path:"C:/Users/ADMINI~1/Desktop/jobs/demo",
auto_save: "No",
units:"mm"
}
for(var key in default_par){ if (!par.hasOwnProperty(key) || par[key] == ""){ par[key] = default_par[key] }}
var job = Job;
try {
if(_.isEmpty(job)){throw "参数job不存在"} else { 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" } else { GEN.checkInout({job:job,mode:"out"}) } }
var stepList = GEN.getStepList({job:job})
stepList = stepList.filter(function(step){
var reg = new RegExp(par.step,"ig")
return reg.test(step)
})
if(!GEN.isStepExists({job:job, step:par.orig_step})){
throw "原稿step:" + par.orig_step + "不存在";
}
var matrix = GEN.getMatrix({job:job})
var layers = [];
for (var key in matrix) {
var info = matrix[key];
if(info.context == "board" && /silk_screen|solder_mask|solder_past|signal/.test(info.layer_type)){
layers.push(key)
}
}
stepList.forEach(function(step){
if(GEN.isStepExists({job:job, step:step})){
var substeps = GEN.getSubSteps({job:job,step:step});
substeps.forEach(function(substep){
if(substep){
// 将原稿的board 文字防旱锡膏线路 层拷贝到这些substep里
GEN.openStep({job:job, name:substep})
layers.forEach(function(v){
GEN.copyLayer({source_job:job,source_step:par.orig_step,source_layer:v,dest_layer:v,mode:"replace"})
})
GEN.closeStep()
}
})
// 导出step
fs.mkdir(par.export_path + "/" + step)
if(layers.length){
GEN.COM("output_layer_reset")
layers.forEach(function(v){
GEN.COM("output_layer_set,layer="+v+",angle=0,mirror=no,x_scale=1,y_scale=1,comp=0,polarity=positive,setupfile=,setupfiletmp=,line_units=inch,gscl_file=,step_scale=no")
})
GEN.COM("output,job="+job+",step="+step+",format=Gerber274x,dir_path="+par.export_path + "/" + step+",prefix=,suffix=.art,break_sr=yes,break_symbols=no,break_arc=no,scale_mode=all,surface_mode=fill,min_brush=1,units=inch,coordinates=absolute,zeroes=none,nf1=2,nf2=4,x_anchor=0,y_anchor=0,wheel=,x_offset=0,y_offset=0,line_units=inch,override_online=yes,film_size_cross_scan=0,film_size_along_scan=0,ds_model=RG6500")
}
}
})
// 保存
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"})}
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";
}
\ No newline at end of file
/*
NAME:
DESCRIPTION: 钻孔输出;
PARAMETER:
[
{
name : 'step_filter',
title : '工作step',
type : 'LineEdit',
property : {tool_tip : '过滤Step名称'},
},
{
name : 'out_dir',
title : '钻孔输出路径',
type : 'LineEdit',
property : {tool_tip : '例如: /output/drill'},
},
{
name : 'cool_spread',
title : '跳钻距离(um)',
type : 'LineEdit',
property : {tool_tip : '例如: 350'},
},
{
name : 'reread_layer',
type : 'RadioBox',
title : '回读钻孔程式',
property : {tool_tip:'未设定,则默认no',
size_policy:'Expanding,Fixed',item_list:[{name:'yes',text:'Yes'},{name:'no',text:'No'}]},
pack : {row:1,column:1},
},
{
name : 'is_select_lyr',
type : 'RadioBox',
title : '是否选择层别',
property : {tool_tip:'未设定,则默认no',
size_policy:'Expanding,Fixed',item_list:[{name:'yes',text:'Yes'},{name:'no',text:'No'}]},
pack : {row:1,column:1},
},
{
name : 'auto_save',
title : '自动保存',
type : 'RadioBox',
property : {
item_list:[
{name:'yes',text:'YES'},
{name:'no',text:'NO'},
],
tool_tip:'是否自动保存料号开关'
}
}
]
VERSION_HISTORY:
V1.00 2020-09-01 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> step信息 </p>
<br>
<font size="3" color="#003DB2"><p>注意事项</p></font>
<p> 无 </p>
<br>
</body></html>
*/
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
console.log("==============================>template");
// 引入模块 包
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 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 } });
}
}
require("topsin.genmath")
var genMath = new GenMath();
var gui = new NewGUI(GUI);
var Status = 'ok';
var resultData = [];
var par = PAR;
var default_par = {
spread: 2000,
step_filter:"step",
out_dir:"C:/Users/Administrator/Desktop/jobs/demo",
cool_spread:350,
reread_layer:"no",
is_select_lyr:"no",
auto_save: "No",
units:"mm"
}
for(var key in default_par){ if (!par.hasOwnProperty(key) || par[key] == ""){ par[key] = default_par[key] }}
var job = Job;
var info = {};
var new_name = "new_test";
if(!fs.exists(par.out_dir)){
IKM.msg("导出路径不存在");
return "Canel"
}
par.out_dir += '/' + new_name;
fs.mkdir(par.out_dir);
var Step;
try {
if(_.isEmpty(job)){throw "参数job不存在"} else { job = job.toLowerCase() }
if(!GEN.isJobExists({job:job})){throw "料号"+job+"不存在"}
// 选择工作step
var workstep = getWorkStep()
if(workstep.length == 0){throw "未找到工作step"}
// 选择工作层
var work_layers = select_work_layer();
if(work_layers.length == 0){throw "未找到工作层"}
// 确认涨缩信息
var scale = get_scale_info({layers:work_layers}); // -----涨缩值信息确认
par.scale = scale;
workstep.forEach(function(step){
Step = 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();
PAR.profile_limits = GEN.getProfileLimits({job:job,step:step,units:'mm'});
PAR.profile_limits.xsize = Number(PAR.profile_limits.xsize);
PAR.profile_limits.ysize = Number(PAR.profile_limits.ysize);
PAR.profile_limits.xmin = Number(PAR.profile_limits.xmin);
PAR.profile_limits.ymin = Number(PAR.profile_limits.ymin);
PAR.profile_limits.xmax = Number(PAR.profile_limits.xmax);
PAR.profile_limits.ymax = Number(PAR.profile_limits.ymax);
PAR.profile_limits.xc = PAR.profile_limits.xsize/2-Math.abs(PAR.profile_limits.xmin);
PAR.profile_limits.yc = PAR.profile_limits.ysize/2-Math.abs(PAR.profile_limits.ymin);
PAR.sr = GEN.getSRLimits({job:job,step:step,units:'mm'});
work_layers.forEach(function(layer){
//钻孔输出
var output_layer = job+'-'+layer+'-ori'; // Job.'-'.$layer.'-ori'
drill_out({layer:layer,output_layer:output_layer,scale_x:PAR.scale[layer].x,scale_y:PAR.scale[layer].y});
//钻孔程式编辑
var new_layer='';
if(PAR.scale[layer].x != 1 || PAR.scale[layer].y != 1){
new_layer= new_name+'.'+layer+'X'+PAR.scale[layer]+'Y'+PAR.scale[layer].y
}else{
new_layer= new_name+'.'+layer;
}
var new_file = PAR.out_dir+'/'+new_layer;
// 分割文件内容
edit_nc_file({layer:layer,output_file:PAR.out_dir+'/'+output_layer,new_file:new_file,x:PAR.scale[layer].x,y:PAR.scale[layer].y});//drl_type:$drl_type
//删除钻孔输出的临时文件
// fs.unlink(PAR.out_dir+'/'+output_layer);
//回读钻孔程式
if( PAR.reread_layer =~ /yes/i){
var new_layer_2 = new_layer;
input_drill_program({layer:layer,file:PAR.out_dir+'/'+new_layer_2,new_layer:new_layer});//drl_type:drl_type,drl_side=>$drl_side
}
})
})
// 保存
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"})}
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 NewGUI (gui) {
this.msgBox = function(props){ // title type content button
props = props || {}
return gui.msgBox(props.title || "title",props.type || "info",props.content || "content",props.button || ["ok", "cancel"]);
}
this.selectFromTreeview = gui.selectFromTreeview
this.selectFile = function(props){ // "choose something", "*", true, "file", "/home/abby/fast_io"
props = props || {}
return gui.selectFile(props.title || "choose something",props.filter || "*",props.multiple || false, "file","");
}
this.selectSingle = function(props) {
props = props || {}
return gui.selectSingle({
"title": props.title || "select",
"list": props.list || [],
"default": props["default"] || "",
"columns": props.columns || 2,
"gen":props.gen || GEN
});
}
this.selectMultiple = function(props) {
props = props || {}
return gui.selectMultiple({
"title": props.title || "select",
"list": props.list || [],
"defaultvalue": props["defaultvalue"] || [""],
"defaultsize": props["defaultsize"] || [200, 100],
"columns": props.columns || 2,
"gen":props.gen || GEN
});
}
this.selectFromTable = gui.selectFromTable
this.snapScreen = gui.snapScreen
this.imageViewer = gui.imageViewer
this.inputBox = gui.inputBox
this.showForm = gui.showForm
this.lockUnlockLayer = function(props){
props = props || {}
var tmp = {}
if (props.matrix) {
for (var key in props.matrix) {
var item = props.matrix[key]
tmp[key] = {
row : item.row,
name : item.name
}
}
}
return gui.lockUnlockLayer({
title: props.title || "lockUnlockLayer",
layermatrix:props.layermatrix || tmp
})
}
this.passwordBox = function(props){
props = props || {}
return gui.passwordBox({title:props.title || "password", password:props.password || "1212"})
}
this.selectJobLayer = function (props) {
props = props || {}
return gui.selectJobLayer({
layertypelist: props.layertypelist || [
{name: "all", display_name: "all", filter: function(x) { return x }},
{name: "signal", display_name: "signal", filter: function(x) { return x["layer_type"] === "signal"; }},
{name: "power_ground", display_name: "power_ground", filter: function(x) { return x["layer_type"] === "power_ground"; }},
{name: "mixed", display_name: "mixed", filter: function(x) { return x["layer_type"] === "mixed"; }},
{name: "solder_mask", display_name: "solder_mask", filter: function(x) { return x["layer_type"] === "solder_mask"; }},
{name: "silk_screen", display_name: "silk_screen", filter: function(x) { return x["layer_type"] === "silk_screen"; }},
{name: "solder_paste", display_name: "solder_paste", filter: function(x) { return x["layer_type"] === "solder_paste"; }},
{name: "drill", display_name: "drill", filter: function(x) { return x["layer_type"] === "drill"; }},
{name: "rout", display_name: "rout", filter: function(x) { return x["layer_type"] === "rout"; }},
{name: "document", display_name: "document", filter: function(x) { return x["layer_type"] === "document"; }}
],
//defaultlayertype: "ha",
joblist: props.joblist || [],
defaultJob: props.defaultJob || [], // select by default
steplist: props.steplist || [],
// defaultstep: "step3",
showstep: props.showstep || true,
selectmode: props.selectmode || "multiple", // single/multiple
layermatrix: props.layermatrix || { },
defaultlayer: props.defaultlayer || []
})
}
}
function getLayer(props){
if(!props){return}
if(!props.context){props.context = "board"}
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(!Array.isArray(props[key])){props[key] = [props[key]]}
if(info[key] && props[key].indexOf(info[key]) < 0){ ret = false } }
if(ret){ a.push(props.res == "info"? info : b) } return a
},[])
}
function _deleteLayer(layers){
layers = Array.isArray(layers.layer) ? layers.layer : [layers.layer];
layers.forEach(function(layer){
if(GEN.isLayerExists({job:Job,layer:layer})){
GEN.deleteLayer({job:Job,layer:[layer]})
}
})
}
function getWorkStep(props){
var steplists = GEN.getStepList({job:job});
if(steplists.length == 0){return "该料号没有step"}
var steps_tmp = steplists.filter(function(name){
var reg = new RegExp(par.step_filter, "ig")
return reg.test(name)
})
if(steplists.length == 0){return "根据脚本参数过滤出来的step不存在,请检查资料或者脚本参数配置!"}
var workstep = gui.selectMultiple({
title: "请先择工作step",
size:[200,100],
defaultsize:[200,100],
list: steplists.map(function(v){ var tmp = {}; tmp[v] = v ;return tmp}),
defaultvalue: steps_tmp,
columns: 1,
gen: GEN
})
if(workstep.length == 0 ) {return "没有先择step"}
return workstep
}
function select_work_layer(par) {
var drill = [];
var matrix = GEN.getMatrix({job:Job});
Object.keys(matrix).forEach(function(layer){
if (!/ddr/.test(layer)){
if(matrix[layer].layer_type == "drill"){
drill.push(layer)
}
}
})
if(drill.length == 0){
IKM.msg("资料中未找到钻孔层")
}
if (PAR.is_select_lyr == 'yes' && drill.length > 1) {
var tmp_matrix={};
drill.forEach(function(v){
tmp_matrix[v] = matrix[v]
})
drill = GUI.selectLayer({
title:'请选择输出层别',
layermatrix:tmp_matrix,
selectmode : 'multiple'}); // single
}
return drill;
}
function get_scale_info(par){
var rows={},n=0;
par.layers.forEach(function(layer){
n++;
if(!rows[layer]){rows[layer] = {}}
rows[layer].sequence = n;
rows[layer].layer = layer;
if(layer == "md"){
rows[layer].x = 1.0004;
rows[layer].y = 1.0004;
}
else{
rows[layer].x = 1.0000;
rows[layer].y = 1.0000;
}
})
return rows;
}
function drill_out(par){
var nc_set = par.layer;
var ncsets = GEN.getNcsetsList({job:Job,step:Step,layer:par.layer});
if( ncsets.length ){
if (ncsets.filter(function(v){return /^($nc_set)$/.test(v)}).length > 0) {
GEN.COM('ncset_delete',{name:nc_set});
}
}
//钻带涨缩中心点
var anchor_x = (par.scale_x != 1 || par.scale_y != 1) ? PAR.profile_limits.xc : 0;
var anchor_y = (par.scale_x != 1 || par.scale_y != 1) ? PAR.profile_limits.yc : 0;
if(fs.exists(PAR.out_dir+"/"+par.output_layer)){
fs.unlink(PAR.out_dir+"/"+par.output_layer)
}
var org_x=0,org_y=0,angle;
// if(PAR.profile_limits.ysize == 603 && PAR.profile_limits.xsize == 706){
// org_x = PAR.profile_limits.yc;//- 15
// org_y = 5;
// angle = 270;
// }else if(PAR.profile_limits.ysize == 603 && PAR.profile_limits.xsize == 606){
// org_x = PAR.profile_limits.xc;//- 5
// org_y = 5;
// angle = 0;
// }else{
// org_x = PAR.profile_limits.xc;//- 24
// org_y = 5;
// angle = 0;
// }
// 导出
GEN.COM("ncset_cur,job="+Job+",step="+Step+",layer="+par.layer+",ncset="+nc_set);
GEN.COM("ncd_set_machine,machine=excellon2,thickness=0");//excellon2 cpc_pn basic_excellon
GEN.COM("ncd_register,angle=0,mirror=no,xoff=0,yoff=0,version=1,xorigin="+org_x+
",yorigin="+org_y+",xscale="+par.scale_x+",yscale="+par.scale_y+
",xscale_o="+anchor_x+",yscale_o="+anchor_y);
GEN.COM("ncd_cre_drill");
GEN.COM("ncd_ncf_export,stage=1,split=1,dir="+PAR.out_dir+",name="+par.output_layer);
GEN.COM("ncset_delete,name="+par.layer);
}
// 整理输出文件数据
function edit_nc_file(par){
// {
// "layer": "drl",
// "output_file": "C:/Users/Administrator/Desktop/jobs/demo/new_test/demo-drl-ori",
// "new_file": "C:/Users/Administrator/Desktop/jobs/demo/new_test/new_test.drl",
// "x": 1,
// "y": 1
// }
// 读取文件内容
var fileCtx = fs.readFile(par.output_file)
// 分割文件内容
var data = split_program(fileCtx);
// 排序
convert_new_program(data);
// 重写
write_new_file({new_file:par.new_file, data:data})
}
// 分割文件内容
function split_program(string){
var data = string.split("\n");
var info = {overhead:[],head:[],neck:[],body:[],end:[]};
var flag="start",router_flag;
data.forEach(function(line){
if( flag == 'start' ){
if( line == 'M48' ){
flag = 'overhead';
}
}
else if( flag == 'overhead' ){
if( /^T01C/i.test(line) ){
flag = 'head';
}
}
else if( flag == 'head' ){
if( !/^T\d+/i.test(line) ){
flag = 'neck';
}
}
else if( flag == 'neck' ){
if( /^T01/i.test(line) ){
flag = 'body';
}
}
else if( flag == 'body' ){
if( /^M30$/i.test(line) ){
flag = 'end';
}
}
if( flag == 'overhead' ){
info.overhead.push(line)
}
else if( flag == 'head' ){
info.head.push(line)
}
else if( flag == 'neck' ){
info.neck.push(line)
}
else if( flag == 'body' ){
if(/^(T(\d+))$/i.test(line) ){
router_flag = RegExp.$1;
}
if(router_flag){
if(!/^T\d/.test(line)){
var tmpT = info.body.filter(function(v){
return v.name == router_flag
})
if(tmpT.length > 0){
tmpT[0].value.push(line)
} else {
info.body.push({
name: router_flag,
value: [line]
})
}
}
//判断孔的范围 2020-04-21
// if($num - $section_number < 0.001 and line !~ /^T/){
// my $point = change_coode_to_vale(line);
// my $are_check = 0;
// foreach my $symbol (@drl_section_data){
// my $dist = TL::GenMath->point2sym_dist($point,$symbol);
// if($dist == 0){
// $are_check = 1;
// last;
// }
// }
// if($are_check){
// push @drl_section,line;
// }else{
// push @{$info{body}{$router_flag}{value}},line;
// }
// }else{
// info.body[router_flag].value.push(line)
// }
}
}
else if( flag == 'end' ){
info.end.push(line)
}
})
return info
}
function convert_new_program(info){
// 这里只对head和body排序
var head = info.head;
var body = info.body;
// 做一个临时排序基准数组
var head_tmp = head.map(function(v) {
var tmp = v.split(/c/ig)
return {
name:tmp[0],
value : parseFloat(tmp[1])
}
})
head_tmp.sort(function(a,b){
var a_tmp_value = (a.value==2.1 || a.value==0.7) ? -a.value : a.value;
var b_tmp_value = (b.value==2.1 || b.value==0.7) ? -b.value : b.value;
if(/\.\d\d1$/.test(a_tmp_value)){
a_tmp_value = a_tmp_value + 10000;
}
if(/\.\d\d1$/.test(b_tmp_value)){
b_tmp_value = b_tmp_value + 10000;
}
if(/\.\d\d2$/.test(a_tmp_value)){
a_tmp_value = a_tmp_value + 20000;
}
if(/\.\d\d2$/.test(b_tmp_value)){
b_tmp_value = b_tmp_value + 20000;
}
return a_tmp_value - b_tmp_value;
})
head_tmp = head_tmp.map(function(v){return v.name})
// head body 根据基准排序
head.sort(function(a,b){
var aT = /^(T\d+)C/.exec(a)[1];
var bT = /^(T\d+)C/.exec(b)[1];
return head_tmp.indexOf(aT) - head_tmp.indexOf(bT)
})
body.sort(function(a,b){
var aT = a.name;
var bT = b.name;
return head_tmp.indexOf(aT) - head_tmp.indexOf(bT)
})
// 重写head与body
head = head.map(function(v, i){
var Tnum = /^T(\d+)C/.exec(v)[1] - 0;
if(Tnum != (i+1)){
var newT = "T" + ((i+1)>9? (i+1) : "0"+(i+1))
v = v.replace(/^T\d+/, newT)
}
return v
})
body = body.map(function(v, i){
var Tnum = /^T(\d+)/.exec(v.name)[1] - 0;
if(Tnum != (i+1)){
var newT = "T" + ((i+1)>9? (i+1) : "0"+(i+1))
v.name = newT
}
return v
})
info.head = head;
info.body = body;
}
function write_new_file(par){
// {new_file:new_file, data:data}
var data = par.data
var newstr = "";
var overhead = data.overhead.join("\n");
var neck = data.neck.join("\n");
var head = data.head.join("\n");
newstr += overhead + "\n" + head + "\n" + neck + "\n";
var body = "";
data.body.forEach(function(v){
body += v.name + "\n";
body += v.value.join("\n") + "\n"
})
newstr += body;
var end = data.end.join("\n");
newstr += end;
fs.writeFile(par.new_file, newstr)
}
function input_drill_program(par){
GEN.COM( "input_manual_reset");
GEN.COM( "input_manual_set,path="+par.file+",job="+Job+",step="+Step
+",format=Excellon2,data_type=ascii,units=mm,coordinates=absolute,"
+"zeroes=none,nf1=3,nf2=3,decimal=no,separator=nl,tool_units=mm,layer="+par.new_layer
+",wheel=,wheel_template=,nf_comp=0,multiplier=1,text_line_width=0.0024,"
+"signed_coords=no,break_sr=yes,drill_only=no,merge_by_rule=no,threshold=200,resolution=3");
GEN.COM( "input_manual,script_path=");
GEN.zoomHome();
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment