Commit 48be72f8 authored by Scott Sun's avatar Scott Sun

scott

parent 55212463
......@@ -430,9 +430,6 @@ try{
$GEN->closeStep();
}
_deleteLayer(step=>$Step,layer=>['qec_goldfr+++','qec_goldba+++','qec_ospfr+++','qec_ospba+++',
'rel_qec_goldfr+qec_ospfr+++','rel_qec_goldba+qec_ospba+++']);
......@@ -443,9 +440,6 @@ try{
}
my $info_step=$layerinfo->{sel};
$GEN->openStep(job=>$Job,name=>$Step);
$GEN->units(type=>'mm');
if ($PLAN_STATE eq 'SHA') {
......@@ -497,17 +491,11 @@ try{
}
}
if ($GEN->isLayerExists(job=>$Job,layer=>$ref_layer_c)){
my $ff = exposed_pad_size($Job,$Step,$layerinfo->{$ll},$ref_layer_c,$info_step);
foreach my $num (keys %$ff){
$guard_warning{$ll}{$num}=$ff->{$num};
}
#push @guard_warning , "On $ll side, ".join("<br>",@$ff) if (@$ff);
}
else{
$guard_warning{1} ="On $ll side, All layer exposed";
......@@ -555,90 +543,6 @@ try{
}
}
#if ($PLAN_STATE eq 'SHA') {
# my @guard_warning;
# foreach my $ref_layer_c('ref_layer_c_fr','ref_layer_c_ba'){
# my $ll='top';
# my @refs= ('qec_goldfr','qec_ospfr');
# if ($ref_layer_c eq 'ref_layer_c_ba'){
# @refs= ('qec_goldba','qec_ospba') ;
# $ll='bottom';
# }
#
# if (!$GEN->isLayerExists(job=>$Job,layer=>$ref_layer_c)){
# foreach my $ggg (@refs){
# if ($GEN->isLayerExists(job=>$Job,layer=>$ggg)){
# my @steps11 = $GEN->getSubSteps(job=>$Job,step=>$Step);
# if (@steps11) {
# foreach my $f (@steps11){
# $GEN->openStep(job=>$Job,name=>$f);
# $GEN->units(type=>'mm');
# $GEN->copyLayer(source_job=>$Job,
# source_step=>$Step,
# source_layer=>$ggg,
# dest_layer=>$ref_layer_c.'_tmp',
# mode=>'append', #append
# invert=>'yes');#|'yes'
# }
#
# $GEN->openStep(job=>$Job,name=>$Step);
# $GEN->units(type=>'mm');
# $GEN->flattenLayer(source_layer=>$ref_layer_c.'_tmp',target_layer=>$ref_layer_c.'_tmp1');
# $GEN->copyLayer(source_job=>$Job,
# source_step=>$Step,
# source_layer=>$ref_layer_c.'_tmp1',
# dest_layer=>$ref_layer_c,
# #mode=>'append', #append
# invert=>'no');#|'yes'
# }
# else{
# $GEN->copyLayer(source_job=>$Job,
# source_step=>$Step,
# source_layer=>$ggg,
# dest_layer=>$ref_layer_c,
# mode=>'append', #append
# invert=>'no');#|'yes'
# }
# }
#
# }
# }
#
#
# if ($GEN->isLayerExists(job=>$Job,layer=>$ref_layer_c)){
# my $ff = exposed_pad_size($Job,$Step,$ll,$ref_layer_c,$info_step);
# push @guard_warning , "On $ll side, ".join("<br>",@$ff) if (@$ff);
# }
# else{
# push @guard_warning , "On $ll side, All layer exposed";
# }
# }
#
# if (@guard_warning) {
# my $subject = "AUTO MAIL:GE01 risk PN[$JOB]";
# my $sent_mail = "Base on [$info_step]<br>".join("<br>",@guard_warning);
# mail_sand_task(jobname=>$JOB,
# title=>'exposed_pad_Area_GE01',
# subject=>$subject,
# body=>$sent_mail,
# #sand_mode=>'always',
# );
# ##### 生产拷贝文件
# #my $output_path = "/winshare/Z_customerdrawing/$Job";
# #my $tmp_path = "/winshare/Z_customerdrawing/".uc $Job;
# #if (-d $tmp_path){
# # `mv $tmp_path $output_path`;
# #}else{
# # mkdir $output_path ;
# #}
# #open(my $fh , ">$output_path/GE01 risk PN [$JOB].html");
# #print $fh "GE01 risk PN[$JOB]<br>";
# #print $fh "$sent_mail";
# #close($fh);
# }
#}
my %surface;
$surface{'gold_fr'}=0;
$surface{'gold_ba'}=0;
......@@ -660,7 +564,6 @@ try{
$surface{'ref_fr'}=$layerinfo->{Reffr};
$surface{'ref_ba'}=$layerinfo->{Refba};
#$GEN->PAUSE("11111111111111 $drill $layerinfo->{Goldfr} and $layerinfo->{Reffr}");
$surface{'gold_fr'}=exposedArea($Job,$Step,$thick,$layerinfo->{Front},'qec_goldfr',$layerinfo->{Back},'ats_empty',$layerinfo->{Drill}) if ($layerinfo->{Goldfr} and $layerinfo->{Reffr});
......@@ -694,14 +597,6 @@ try{
$surface{'carbon'}=sprintf('%.4f',$surface{'carbon'});
}
#= $GUI->select_single(
# -title=>'All the surface calculation is based on:',
# -list=>['Card'=>'Card','Array'=>'Array'],
# -defaultvalue=>'all_left'
#);
$surface{'baseon'} = $info_step;
# $GEN->PAUSE("$surface{baseon} g $surface{ref_fr} h $surface{ref_ba} ");
my %InfoHash;
......@@ -755,7 +650,7 @@ try{
-jobcategory=>'org',
-jobinfohash=>\%InfoHash);
# $GUI->debug(dump(\%InfoHash));
my $Check_gold_size= sprintf('%-15s',' ').sprintf('%-15s','Exposed').sprintf('%-15s','Gold').sprintf('%-15s','Sel.Ref (sqin)')."\n";
my $Check_gold_state = 0;
my($step_size_x,$step_size_y);
......@@ -782,97 +677,6 @@ try{
$Check_gold_size.= sprintf('%-15s',$tmpmm)."\n";
}
# if ($Check_gold_state==1 and $Job =~/^coc/i){
# my $profile_limits = $GEN->getProfileLimits(job=>$Job,step=>$Step,units=>'mm');
# my $Card_sizex=sprintf "%.2f",$profile_limits->{xsize};
# my $Card_sizey=sprintf "%.2f",$profile_limits->{ysize};
# my $Card_size="Card size: X $Card_sizex,Y $Card_sizey (mm)";
# my $subject = "Please be informed P/N $Job gold area > 2.5sqin per single card per side";
# my $content = "Dear All\n Pls be informed gold area > 2.5sqin \nIf any feedback Please contact PE!\n\n\n$Check_gold_size${Card_size}";
# my $title="Pls be informed gold area > 2.5sqin";
# my $mails = $DB->select_arrayhash(
# -table => 'ats_auto_mail_record',
# -where => {job_id => $JOB_ID}
# );
# my $n=0;
# foreach my $item (@$mails) {
# if ( $item->{mail_subject} eq $subject) {
# $n=1;
# last;
# }
# }
# if ($PAR->{send_mail} eq 'yes' and $n==0){
# my $username =$GEN->getUserName();
# Top::MailSender->send_mail(
# subject => $subject,#标题不能为中文
# group => $PAR->{mail_group},
# to => $PAR->{internal_mail_group},
# cc_user=>[$username],
# body=>$content,
# );
# $DB->insert(
# -table => 'ats_auto_mail_record',
# -data => {
# job_id => $JOB_ID,
# mail_from => $username,
# mail_to => join(',',Top::MailSender->get_mail_list($PAR->{$PAR->{mail_group}},'to')),
# mail_cc => $username,
# mail_subject => $subject,
# mail_title => $title,
# mail_content => $content,
# mail_version => 1
# }
# )
# }
#$sql="select mail_title from auto_mail_record where job_id=$processInfo{job_id} and mail_title='Pls be informed gold area > 2.5sqin'";
#my $db1 = DB::ACAMMysql->new();
#$db1->run($sql);
#my $mail_title=$db1->next();
#my $n=0;
#if ($mail_title){
# $n=1;
# return 1;
#}
#
#if ($n==0){
# # my @mailto1=('m.pei@cn.ats.net');
# my @mailto1 = $CAM->getMailListByTypeAndCategory(-type=>'gold area > 2.5sqin',-category=>'to');
# my $mailfrom1 = $CAM->getGenesisUserMail(-username=>$USERNAME);
# my @mailcc1=('SHA_PE','m.pei@cn.ats.net',$mailfrom1);
# my $subject1 = "Pls be informed P/N ${JOB_NAME} gold area > 2.5sqin per single card per side";
# my $content1 = "Dear All\n Pls be informed gold area > 2.5sqin \nIf any feedback Please contact PE!\n\n\n$Check_gold_size${Card_size}";
#
# Lib::MailMix->sendmail_ATSMail( -mailfrom =>$mailfrom1,
# -mailto =>\@mailto1,
# -mailcc =>\@mailcc1,
# -subject =>$subject1,
# -content =>$content1
# );
#
# my $nowtime=$Genesis->localtimemysql();
# &RecordMail(-jobname=>$JOB_NAME,
# -mail_from=>$mailfrom1,
# -mail_to=>join(',',@mailto1),
# -mail_cc=>join(',',@mailcc1),
# -mail_subject=>$subject1,
# -mail_title=>"Pls be informed gold area > 2.5sqin",
# -mail_content=>$content1,
# -mail_send_time=>$nowtime,
# -mail_attachment=>''
# );
#}
# }
###output and return status, if genesis error, it will output genesis error command
unless ($GEN->{STATUS}){
return $Return;
}
......@@ -983,6 +787,9 @@ sub expcopperArea {
}
sub exposedArea {
# ($thick,$layerinfo->{Front},'qec_goldfr',$layerinfo->{Back},'ats_empty',$layerinfo->{Drill}) if ($layerinfo->{Goldfr} and $layerinfo->{Reffr});
# ($thick,$layerinfo->{Front},'ats_empty',$layerinfo->{Back},'qec_goldba',$layerinfo->{Drill}) if ($layerinfo->{Goldba} and $layerinfo->{Refba});
my ($job,$step,$thick,$layer1,$mask1,$layer2,$mask2,$drill) = @_;
$GEN->openStep(job=>$Job,name=>$Step);
$GEN->units(type=>'mm');
......@@ -1009,7 +816,7 @@ sub exposedArea {
$reprot = sprintf "%0.4f",$reprot->{area}/10000;
return $reprot;
}
#exposed_pad_size($Job,$Step,$layer,$ref_layer);
sub exposed_pad_size{
my $Job=shift;
my $Step= shift;
......@@ -1155,7 +962,7 @@ sub exposed_pad_size1{
}
}
#$GUI->debug("@guard_warning");
return \@guard_warning;
}
......
......@@ -165,10 +165,8 @@ if(mailUserList && mailUserList.length) {
})
}
var cam_workflow_info = IKM.get_jobinfo({jobid:JobId, jobinfo:"cam_workflow_info"});
console.log("==========cam_workflow_info===========:" + cam_workflow_info);
try {
if(cam_workflow_info == "err" && global._STATUS == "err"){
console.log("==========cam_workflow_info===========:" + cam_workflow_info);
throw cam_workflow_info
}
if(global._STATUS != "err") {
......@@ -393,7 +391,6 @@ try {
jobinfohash: {cam_drill_structure: JSON.stringify(cam_drill_structure)}
})
GEN.closeStep()
console.log("===================>steplist:"+_.toString(step_list))
if(step_list.indexOf(pcs_step)<0){throw "can not find pcsstep"}
if(step_list.indexOf(array_step)<0){array_step = false}
console.log("=============== ====================> 1matrix")
......@@ -518,7 +515,6 @@ try {
var jobInfo = {}
Object.keys(config.jobInfo).forEach(function(key){
var props = config.jobInfo[key];
console.log("===================================> 2analysis_obj:key:"+key)
if(props){
try {
if(props.hasOwnProperty("api") && props.hasOwnProperty("props")){
......@@ -530,7 +526,6 @@ try {
}
} catch (e) {
console.log("========================================error:");
console.log(e);
jobInfo[key] = "_error"
}
}
......@@ -691,26 +686,27 @@ try {
GEN.COM("chklist_run,chklist=valor_cleanup_set_smd,nact=1,area=profile")
GEN.COM("chklist_close,chklist=valor_cleanup_set_smd,mode=hide")
}else{
// GEN.chklistRun({
// chklist: "quotation_check",
// nact: 4,
// area: 'profile'
// })
GEN.COM("chklist_single,show=yes,action=valor_cleanup_set_smd")
GEN.COM("chklist_cupd,chklist=valor_cleanup_set_smd,nact=1,params=((pp_layer=.type=signal|mixed&side=top|bottom)(pp_work_on=SMD\;BGA)(pp_delete=No)(pp_types=Square\;Rect\;Oval)(pp_other_smd=)(pp_sm=No)(pp_drill=)(pp_rotate=No)(pp_ignore_covered=Yes)(pp_bga_types=Round)(pp_other_bga=)(pp_sm_bga=No)(pp_bga_max_pitch=70)(pp_bga_actions=Set attribute)(pp_bga_suffix=_bga)(pp_identify_gf=)),mode=regular")
GEN.COM("get_user_name")
GEN.COM("get_job_path,job="+job)
GEN.COM("disp_on")
GEN.COM("origin_on")
GEN.COM("chklist_cnf_act,chklist=valor_cleanup_set_smd,nact=1,cnf=no")
GEN.COM("chklist_run,chklist=valor_cleanup_set_smd,nact=1,area=profile")
GEN.COM("skip_next_pre_hook")
GEN.COM("chklist_run,chklist=valor_cleanup_set_smd,nact=1,area=profile")
GEN.COM("get_user_name")
GEN.COM("skip_current_command")
GEN.COM("disp_on")
GEN.COM("origin_on")
GEN.COM("show_tab,tab=Checklists,show=no")
GEN.COM("chklist_from_lib,chklist=quotation_check,profile=none,customer=");
GEN.chklistRun({
chklist: "quotation_check",
nact: 4,
area: 'profile'
})
// GEN.COM("chklist_single,show=yes,action=valor_cleanup_set_smd")
// GEN.COM("chklist_cupd,chklist=valor_cleanup_set_smd,nact=1,params=((pp_layer=.type=signal|mixed&side=top|bottom)(pp_work_on=SMD\;BGA)(pp_delete=No)(pp_types=Square\;Rect\;Oval)(pp_other_smd=)(pp_sm=No)(pp_drill=)(pp_rotate=No)(pp_ignore_covered=Yes)(pp_bga_types=Round)(pp_other_bga=)(pp_sm_bga=No)(pp_bga_max_pitch=70)(pp_bga_actions=Set attribute)(pp_bga_suffix=_bga)(pp_identify_gf=)),mode=regular")
// GEN.COM("get_user_name")
// GEN.COM("get_job_path,job="+job)
// GEN.COM("disp_on")
// GEN.COM("origin_on")
// GEN.COM("chklist_cnf_act,chklist=valor_cleanup_set_smd,nact=1,cnf=no")
// GEN.COM("chklist_run,chklist=valor_cleanup_set_smd,nact=1,area=profile")
// GEN.COM("skip_next_pre_hook")
// GEN.COM("chklist_run,chklist=valor_cleanup_set_smd,nact=1,area=profile")
// GEN.COM("get_user_name")
// GEN.COM("skip_current_command")
// GEN.COM("disp_on")
// GEN.COM("origin_on")
// GEN.COM("show_tab,tab=Checklists,show=no")
}
// top bottom 层smd排除掉 r\d开头的圆形smd // 与开窗touch 碰不到的删除属性
analysis_obj.matrixInfo.mOuters.forEach(function(item){
......@@ -757,7 +753,6 @@ try {
console.log("===================================> 7 bga info")
var bgaInfo;
bgaInfo = bgaAnalysis({job:job,steplist:[pcs_step],layers:analysis_obj.matrixInfo.mOuters,attr:".bga"})
console.log("========================bgaInfo:" + _.toString(bgaInfo));
// 保存
console.log("============== =====================> 8 save bga smd info")
var save_info = [smdInfo, analysis_obj.jobInfo.laser_info,bgaInfo]; // 保存 smd 和 bga数据
......@@ -792,8 +787,6 @@ try {
tmp.copper_percent = GEN.copperArea({layer1:v}).percent + "%"
return tmp
})
console.log("================ ==signalLayers============"+_.toString(signalLayers));
console.log(_.toString(copper_percent_tmp));
copper_percent_tmp.forEach(function(item){
var save_info = {
jobid: JobId,
......@@ -825,7 +818,7 @@ try {
// }
var info = {
min_line_width: ["line","user_nor_line"],
min_line_spacing: ["c2c","l2l","user_nor_line2nor_line"],
min_line_spacing: ["c2c","l2l","user_nor_line2nor_line","user_nor_line2surface"],
min_line2pad: ["p2line","p2c"],
min_pad2pad: ["p2p", "smd2smd", "smd2pad","via2via","bga2pad"],
min_ar_laser:["laser_via_ar"],
......@@ -865,8 +858,9 @@ try {
GEN.copyLayer({source_job:job,source_step:step,source_layer:tmp_gold_info[layer_gold_type],dest_layer:tmp_area_layer,mode:'replace',invert:'no'});
GEN.COM("clip_area_strt")
GEN.COM("clip_area_end,layers_mode=layer_name,layer="+tmp_area_layer+",area=profile,area_type=rectangle,inout=outside,contour_cut=yes,margin=0,feat_types=line\;pad\;surface\;arc\;text")
// var tmp_info = GEN.copperArea({layer1:tmp_gold_info[layer_gold_type],resolution_value:25.4})
var tmp_info = GEN.exposedArea({layer1:item.signalL,mask1:tmp_gold_info[layer_gold_type],resolution_value:1})
var tmp_info = GEN.copperArea({layer1:tmp_gold_info[layer_gold_type],resolution_value:1})
// var tmp_info = GEN.exposedArea({layer1:item.signalL,mask1:tmp_gold_info[layer_gold_type],resolution_value:1})
// var tmp_info = GEN.exposedArea({mask1:item.signalL,layer1:tmp_gold_info[layer_gold_type],resolution_value:1})
var tmp_data = {}
if(layer_gold_type == "top") {
tmp_data.sf_area_ref_layer_front = tmp_gold_info[layer_gold_type]
......@@ -885,14 +879,15 @@ try {
layer: item.signalL,
layerinfohash: {
sf_area_ref_layer: tmp_gold_info[layer_gold_type],
sf_area_gold_area: (tmp_info.area * 645.16 / 10000).toFixed(3)
sf_area_gold_area: (tmp_info.area *1.1* 645.16 / 10000).toFixed(4)
}
})
}
}
if(item.solderL){
// var tmp_info = GEN.copperArea({layer1:item.solderL,resolution_value:1})
var tmp_info = GEN.exposedArea({layer1:item.signalL,mask1:item.solderL,resolution_value:1})
var tmp_info = GEN.exposedArea({mask1:item.signalL,layer1:item.solderL,resolution_value:1})
// var tmp_info = GEN.exposedArea({layer1:item.signalL,mask1:item.solderL,resolution_value:1})
// {"area":"0.73817","percent":"8.986"}
var tmp_area = tmp_info.area
var tmp_percent = tmp_info.percent;
......@@ -906,7 +901,7 @@ try {
layer: item.signalL,
layerinfohash: {
ref_layer: item.solderL,
exposed_area: (tmp_area* 645.16/ 10000).toFixed(3)
exposed_area: (tmp_area * 1.1 * 645.16 / 10000).toFixed(4)
}
})
}
......@@ -962,7 +957,6 @@ try {
})
var drillRes = analysisDrill(drillToSignals,step) // 钻孔分析结果
console.log("===============drillRes:" + _.toString(drillRes));
drillRes.forEach(function(item){
save_layerinfo({
jobid: JobId,
......@@ -1005,17 +999,27 @@ try {
// if (GEN.isChklistExists({ job: job, step: step, chklist: oChecklistName })) {
// GEN.COM("chklist_delete", { chklist: oChecklistName })
// }
GEN.COM("chklist_from_lib,chklist=quotation_check,profile=none,customer=")
GEN.COM("chklist_from_lib,chklist=quotation_check,profile=none,customer=");
GEN.chklistRun({
chklist: "quotation_check",
nact: 1,
area: 'profile'
})
});
GEN.chklistRun({
chklist: "quotation_check",
nact: 2,
area: 'profile'
})
});
GEN.chklistRun({
chklist: "quotation_check",
nact: 3,
area: 'profile'
});
GEN.chklistRun({
chklist: "quotation_check",
nact: 5,
area: 'profile'
});
// signal层分析结果
script_info({ msg: "Error-get ChkRes",result_severity:"ok" })
var res = analysisChkAttr({layers:signalLayers, info:info, step:step, job:job, oChecklistName:"quotation_check",jobpath:jobpath})
......@@ -1088,10 +1092,10 @@ try {
// }
// 邮件触发
sendEmail({
subject:db_customer + ' / '+job+' reading is ready!',
content: db_customer + ' / '+job+' reading is ready!'
})
// sendEmail({
// subject:db_customer + ' / '+job+' reading is ready!',
// content: db_customer + ' / '+job+' reading is ready!'
// })
if (mode === "aimdfm") {
$.QDfm.updateRow({
......@@ -1373,7 +1377,6 @@ function save_job_info(props){ // 保存料号信息
})
});
} else if (value != val) {
console.log("jobid:"+jobid+"==========update jobvalue:"+value+"->" + val)
db.query("",function(q){
return q.updateRow({
table:'pdm_job_jobattr',
......@@ -1408,10 +1411,8 @@ function save_layerinfo(props){ // 保存层信息
where:{job_id:jobid, attr_name: key, layer:layer}
})
});
console.log("+==========dblayervalue:" + value)
if(/done/ig.test(value) || !value){
db.query("",function(q){
console.log("+==========insertRowlayervalue:layer:"+layer+";attrname:"+key+";value:"+ val)
return q.insertRow({
table:'pdm_job_layerattr', // todo
data:{job_id:jobid, attr_name:key, value:val, layer:layer}, // todo
......@@ -1420,7 +1421,6 @@ function save_layerinfo(props){ // 保存层信息
});
} else if (value !== val) {
db.query("",function(q){
console.log("+==========updateRowlayer:layer:"+layer+";attrname:"+key+";value:"+ val)
return q.updateRow({
table:'pdm_job_layerattr',
where:{job_id:jobid, attr_name: key, layer:layer},
......@@ -1442,7 +1442,6 @@ function save_stack_info(props){
where:{job_id:JobId, drl_name: drl_name}
})
});
console.log(_.toString(info))
var Re = db.query("",function(q){
return q.insertRow({
table:table,
......@@ -1495,7 +1494,6 @@ function analysis(props){
init_checking.forEach(function(v){ if(!t[v]){t.e(v+" is undefined")} })
}
T_m_p.prototype.e = function(e){ // 处理error
console.log(e)
throw e
}
T_m_p.prototype.analysis_layer_count = function(props){ // 分析board属性的层数量 []string
......@@ -1563,7 +1561,7 @@ function analysis(props){
var cover_layer = laser_layers[i+1].odb_name
GEN.workLayer({name:start_layer,display_number:2,clear_before:'yes'})
GEN.selClearFeature()
GEN.selRefFeat({layers:cover_layer,use:'filter',mode:'cover'})
GEN.selRefFeat({layers:cover_layer,use:'filter',mode:'touch'})
var count = GEN.getSelectCount()
if(count>0){
if(!laser_info[start_layer]){
......@@ -1688,7 +1686,6 @@ function analysis(props){
var res = 0
var that = this;
console.log("============analysis_milling_length_card=============");
console.log("========step========:"+_.toString(allStep));
allStep.forEach(function(step){
if(GEN.isStepExists({job:that.job,step:step})){
GEN.openStep({job:that.job,name:step})
......@@ -1708,9 +1705,7 @@ function analysis(props){
}
return a
}, 0)
console.log("========milling:"+milling);
res += milling
console.log("========res:"+res);
GEN.deleteLayer({job:that.job,layer:[tmp]})
}
})
......@@ -1770,7 +1765,7 @@ function analysis(props){
mOuters.forEach(function(outer_layer){
if(outer_layer.solderL){
GEN.workLayer({name:outer_layer.solderL,display_number:2,clear_before:'yes'})
GEN.selectByFilter({include_syms:"rect180x150*"})
GEN.selectByFilter({include_syms:"rect213x250xr50\;rect250x213xr50"})
if(GEN.getSelectCount() > 0) {
GEN.selCopyOther({dest:'layer_name',target_layer:outer_layer.solderL+'temp',invert:'no',dx:0,dy:0,size:0})
GEN.workLayer({name:outer_layer.signalL,display_number:2,clear_before:'yes'})
......@@ -1919,6 +1914,13 @@ function smdAnalysis(props){
res[layer.solderL] = {}
}
if(GEN.getProfile({job:job, step:step}).match(/\n/ig).length > 1){
var tmp_solder = layer.solderL + "_tmp";
if(GEN.isLayerExists({job:job,layer:tmp_solder})){GEN.deleteLayer({job:job,layer:[tmp_solder]})}
// 拷贝到辅助层
GEN.selCopyOther({dest:'layer_name',target_layer:tmp_solder,invert:'no',dx:0,dy:0,size:0})
// 转铜皮
GEN.workLayer({name:tmp_solder,display_number:2,clear_before:'yes'})
GEN.selContourize()
GEN.selectByFilter({profile:'in'})
} else {
GEN.selAllFeat()
......@@ -2116,7 +2118,6 @@ function analysisChkAttr(par) {
nact: nact,
attr: v + "_min_" + type
})
console.log("===================== " + v + "_min_" + type + " -> " + tmp);
if (a === "N/A" && /^\d+\.?\d*$/.test(tmp)) {
tmp = Number(tmp)
a = tmp.toFixed(2)
......@@ -2133,7 +2134,6 @@ function analysisChkAttr(par) {
})
})
exportInfo(hash)
return hash
}
function analysisDrill(par, step){
......@@ -2148,12 +2148,12 @@ function analysisDrill(par, step){
// "start": "top",
// "end": "bottom"
// }]
var job = Job.toLowerCase()
var job = Job.toLowerCase();
GEN.affectedLayer({affected:'no',mode:'all'})
var res = par.map(function(drill){
GEN.workLayer({name:drill.layer,display_number:2,clear_before:'yes'})
GEN.selClearFeature()
GEN.selectByFilter({feat_types:'pad', include_syms:drill.symbol})
GEN.selectByFilter({feat_types:'pad'})
if(GEN.getSelectCount()>0){
console.log("==========================>jinru 111111111")
// 拷贝到_tmp
......@@ -2166,29 +2166,72 @@ function analysisDrill(par, step){
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("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.COM("sel_ref_feat,layers="+tmplayer+",use=filter,mode=touch,pads_as=shape,f_types=pad,polarity=positive\;negative,include_syms=,exclude_syms=")
// GEN.selRefFeat({layers:tmplayer, use:"filter",mode:"touch"})
GEN.COM("filter_reset,filter_name=popup")
if(GEN.getSelectCount()>0){
var res = "";
var pads = GEN.getFeatures({job:job,step:step,layer:item,options:"select"})
if (pads && pads.length) {
pads = pads.map(function (item2) {
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)
var res = 999;
if(GEN.isLayerExists({job:job,layer:"temp"})){GEN.deleteLayer({job:job,layer:["temp"]})}
if(GEN.isLayerExists({job:job,layer:"temp+++"})){GEN.deleteLayer({job:job,layer:["temp+++"]})}
GEN.selCopyOther({dest:'layer_name',target_layer:'temp',invert:'no',dx:0,dy:0,size:0})
GEN.workLayer({name:"temp",display_number:1,clear_before:"yes"})
GEN.COM("sel_ref_feat,layers="+item+",use=filter,mode=touch,pads_as=shape,f_types=surface,polarity=positive\;negative,include_syms=,exclude_syms=")
if(GEN.getSelectCount()>0){GEN.selDelete()}
GEN.COM("chklist_single,action=valor_dfm_nfpr,show=yes")
GEN.COM("chklist_cupd,chklist=valor_dfm_nfpr,nact=1,params=((pp_layer=temp)(pp_delete=Duplicate)(pp_work=Features)(pp_drill=PTH\;NPTH\;Via)(pp_non_drilled=Yes)(pp_in_selected=All)(pp_remove_mark=Remove)),mode=regular")
GEN.COM("chklist_run,chklist=valor_dfm_nfpr,nact=1,area=profile")
var layer = "temp";
var drl_layer = layer + "_drl"
if(GEN.isLayerExists({job:job, layer:drl_layer})){GEN.deleteLayer({job:job, layer:drl_layer})}
GEN.createLayer({job:job,layer:drl_layer,type:'drill'})
GEN.selCopyOther({dest:'layer_name',target_layer:drl_layer,invert:'no',dx:0,dy:0,size:0})
if(GEN.isChklistExists({job:job,step:step,chklist:'tmp_chk'})){
GEN.COM("chklist_delete,chklist=tmp_chk")
}
GEN.COM("chklist_create,chklist=tmp_chk")
GEN.COM("chklist_show,chklist=tmp_chk")
GEN.COM("chklist_single,action=valor_analysis_drill,show=yes")
GEN.COM("chklist_pclear")
GEN.COM("chklist_cupd,chklist=valor_analysis_drill,nact=1,params=((pp_drill_layer="+drl_layer+
")(pp_rout_distance=200)(pp_tests=Hole Separation)(pp_extra_hole_type=Pth\;Via)(pp_use_compensated_rout=Skeleton)),mode=regular")
GEN.COM("chklist_pcopy,chklist=valor_analysis_drill,nact=1")
GEN.COM("chklist_ppaste,chklist=tmp_chk,row=0")
GEN.COM("chklist_run,chklist=tmp_chk,nact=1,area=profile")
GEN.COM("chklist_close,chklist=valor_analysis_drill,mode=hide")
GEN.COM("chklist_close,chklist=tmp_chk,mode=hide")
GEN.deleteLayer({job:job, layer:drl_layer})
GEN.deleteLayer({job:job, layer:[layer, layer+"+++"]})
var meas = GEN.getCheckMeas({job:job,step:step,chklist:'tmp_chk',nact:1})
meas = meas.filter(function(v){return /^touch/.test(v)})
if(meas.length){
meas.forEach(function(v){
var tmparr = v.split(" ")
GEN.COM("sel_net_feat,operation=select,x="+tmparr[7]+",y="+tmparr[8]+",use_ffilter=no")
if(GEN.getSelectCount() > 0){GEN.selDelete()}
})
}
} else {
item2.size = Number(item2.size)
var pads = GEN.getFeatures({job:job,step:step,layer:"temp"})
pads = pads.filter(function(v){v.size=v.symbol.slice(1)-0 ;return /^r\d/.test(v.symbol)})
if (pads && pads.length) {
var tmphash = {};
pads.forEach(function(item2){
var key = item2.x+"x"+item2.y
if(!tmphash[key]){tmphash[key] = item2}else {
tmphash[key] = tmphash[key].size > item2.size? tmphash[key]:item2
}
return item2
})
pads = pads.sort(function (a, b) {
return a.size - b.size
})
res = pads[0].size
for (var key in tmphash) {
var size = tmphash[key].size;
res = size < res? size: res;
}
if(res == 999) {res = ""}
}
if ( i == 0) {
drill.drl_pad_top = res
......@@ -2627,12 +2670,10 @@ function unSelect(){
GEN.selectByFilter({attribute:[{attribute:'.drill',option:'non_plated'}],profile:'all',operation:"unselect"})
}
function mkPath(path,list) {
console.log("--path:" + path);
if(list.length){
var newPath = path + '/' + list.shift()
if(!fs.dirExists(newPath)){
fs.mkdir(newPath)
console.log("--mkdir:" + newPath);
}
return mkPath(newPath,list)
} else {return path}
......
......@@ -438,6 +438,7 @@ function delSameJob(props){
}
}
}
function analyJobFiles(props){
var files = props.jobFiles;
var config = props.config;
......
......@@ -3,18 +3,6 @@ NAME:
DESCRIPTION: 锣带输出;
PARAMETER:
[
{
name : 'Outpath',
title : '导出路径',
type : 'LineEdit',
property : {tool_tip : '导出路径'},
},
{
name : 'step',
title : '工作step',
type : 'LineEdit',
property : {tool_tip : '工作step'},
},
{
name : 'auto_save',
title : '自动保存',
......@@ -79,9 +67,8 @@ var Status = 'ok';
var resultData = [];
var par = PAR;
var default_par = {
Outpath:"C:/Users/Administrator/Desktop/jobs/demo",
auto_save: "No",
step:"step",
step:"orig",
units:"mm"
}
for(var key in default_par){ if (!par.hasOwnProperty(key) || par[key] == ""){ par[key] = default_par[key] }}
......@@ -103,24 +90,54 @@ try {
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:'mm'} );
GEN.zoomHome();
var matrix = GEN.getMatrix({job:Job});
Object.keys(matrix).forEach(function(layer){
if(matrix[layer].context && matrix[layer].context == 'board' ){
if(matrix[layer].layer_type == 'rout'){
rou_layer.push(layer)
}
}
})
var layer = "gtl";
if(rou_layer.length) {
var info = confirm_gui({layers:rou_layer});
GEN.workLayer({name:layer,display_number:2,clear_before:'yes'})
var drl_layer = layer + "_drl"
if(GEN.isLayerExists({job:job, layer:drl_layer})){GEN.deleteLayer({job:job, layer:drl_layer})}
GEN.createLayer({job:job,layer:drl_layer,type:'drill'})
GEN.selCopyOther({dest:'layer_name',target_layer:drl_layer,invert:'no',dx:0,dy:0,size:0})
output_rou({job:Job,step:step,info:info});
input_layers({job:Job,step:step,info:info});
if(GEN.isChklistExists({job:job,step:step,chklist:'tmp_chk'})){
GEN.COM("chklist_delete,chklist=tmp_chk")
}
GEN.COM("chklist_create,chklist=tmp_chk")
GEN.COM("chklist_show,chklist=tmp_chk")
GEN.COM("chklist_single,action=valor_analysis_drill,show=yes")
GEN.COM("chklist_pclear")
GEN.COM("chklist_cupd,chklist=valor_analysis_drill,nact=1,params=((pp_drill_layer="+drl_layer+
")(pp_rout_distance=200)(pp_tests=Hole Separation)(pp_extra_hole_type=Pth\;Via)(pp_use_compensated_rout=Skeleton)),mode=regular")
GEN.COM("chklist_pcopy,chklist=valor_analysis_drill,nact=1")
GEN.COM("chklist_ppaste,chklist=tmp_chk,row=0")
GEN.COM("chklist_run,chklist=tmp_chk,nact=1,area=profile")
GEN.COM("chklist_close,chklist=valor_analysis_drill,mode=hide")
GEN.COM("chklist_close,chklist=tmp_chk,mode=hide")
GEN.deleteLayer({job:job, layer:drl_layer})
var meas = GEN.getCheckMeas({job:job,step:step,chklist:'tmp_chk',nact:1})
meas = ["touchh gtl_drl 1.302 mil r5.315 r5.512 SG 2.0707502 6.2600882 2.0695853 6.2595058 1 R",
"touchh gtl_drl 3.222 mil r5.315 r5.512 SG 2.0915237 6.2635829 2.0883541 6.2641619 1 R",
"closeh gtl_drl 11.209 mil r5.512 r5.512 SG 2.0849209 6.2506255 2.0876766 6.2614906 1 R",
"closeh gtl_drl 11.828 mil r5.315 r5.512 SG 2.0904016 6.2611739 2.085407 6.2504523 1 R",
"closeh gtl_drl 12.656 mil r5.315 r5.512 SG 2.0733393 6.2606873 2.0856692 6.2635406 1 Y",
"closeh gtl_drl 12.733 mil r5.315 r5.512 SG 2.0727262 6.2583112 2.0821941 6.2497969 1 Y",
"closeh gtl_drl 13.151 mil r5.512 r5.512 SG 2.0820787 6.2496599 2.0717499 6.2578 1 Y",
"closeh gtl_drl 13.826 mil r5.512 r5.512 SG 2.0722601 6.2601694 2.0856793 6.2634983 1 Y",
"closeh gtl_drl 15.75 mil r5.315 r5.315 SG 2.0733709 6.260529 2.0889031 6.263142 1 G",
"closeh gtl_drl 16.901 mil r5.315 r5.512 SG 2.088911 6.2630973 2.0722949 6.2600094 1 G",
"overlap_width gtl_drl 2.191 mil r5.315 r5.512 SG 2.0889095 6.2640604 2.0910652 6.2636666 1 R",
"overlap_width gtl_drl 4.111 mil r5.315 r5.512 SG 2.0683732 6.2588998 2.0720503 6.2607382 1 R"
]
meas = meas.filter(function(v){return /^touch/.test(v)})
if(meas.length){
meas.forEach(function(v){
var tmparr = v.split(" ")
GEN.COM("sel_net_feat,operation=select,x="+tmparr[7]+",y="+tmparr[8]+",use_ffilter=no")
if(GEN.getSelectCount() > 0){GEN.selDelete()}
})
}
})
......
=head
NAME:
DESCRIPTION: Run Map
PARAMETER:
[
{
name : 'step',
title : 'Panel Step',
type : 'LineEdit',
value : 'E:/',
pack : {row:0,column:1},
property : {
tool_tip:'panel step名称,如未设置,默认为panel'
}
},
{
name : 'units',
title : 'Units',
type : 'ComboBox',
property : {
size_policy:'Expanding,Fixed',
item_list:[
{name:'mm',text:'mm'},
{name:'inch',text:'inch'},
],
tool_tip:'脚本运行genesis的工作单位,如未设置,默认为inch'
},
pack : {row:1,column:1},
},
{
name : 'panel_category',
title : '板框类型',
type : 'TextEdit',
property:{tool_tip:'未定义则默认为标准的category:overlay'},
setter:function(obj,value,self){
obj.setPlainText(value);
},
getter:function(obj,self){
return obj.plainText
}
},
{
name : 'version',
title : 'Version',
type : 'ComboBox',
property : {
size_policy:'Expanding,Fixed',
item_list:[
{name:'release',text:'正式版'},
{name:'test',text:'测试版'},
{name:'select',text:'选择版本'},
],
tool_tip:'板框版本:正式版为1,测试版为0,如未设置,默认为选择版本'
},
pack : {row:1,column:1},
},
{
name : 'change_standard_symbol',
title : '转为自定义Symbol',
type : 'ComboBox',
property : {
size_policy:'Expanding,Fixed',
item_list:[
{name:'Yes',text:'Yes'},
{name:'No',text:'No'},
],
tool_tip:'因标准symbol在旋转后会失去角度信息,所以需转为自定义symbol,默认为yes'
},
pack : {row:1,column:1},
},
{
name : 'condition',
title : '全部添加',
type : 'ComboBox',
property : {
size_policy:'Expanding,Fixed',
item_list:[
{name:'Yes',text:'Yes'},
{name:'No',text:'No'},
],
tool_tip:'全部添加如果是YES 所有SYMBOL添加出来(仅调试使用,将忽略symbol的添加条件的判断),默认为No'
},
pack : {row:1,column:1},
},
{
name : 'debug_priority',
title : '调试等级',
type : 'SpinBox',
pack : {row:1,column:1},
property : {
tool_tip:'symbol的优先级小于设定调试等级的,将不会添加出来,默认为0'
}
},
{
name : 'debug_add_size_symbol',
title : '调试-添加大小Symbol',
type : 'ComboBox',
property : {
size_policy:'Expanding,Fixed',
item_list:[
{name:'Yes',text:'Yes'},
{name:'No',text:'No'},
],
tool_tip:'设定为yes,将按图形symbol->孔symbol->map symbol的优先级顺序添加,否则直接添加map symbol,默认为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-05-17 Alan Fu
1.新版本.
HELP:
<html><body bgcolor="#DDECFE">
<font size="3" color="#003DB2"><p>功能简介</p></font>
<p> Overlay Run map </p>
</body></html>
=cut
#################################################################################################################
#################################################################################################################
use strict;
use utf8;
use JSON;
use Encode;
use Data::Dump 'dump';
use Number::Format 'round';
use_module('TL_GenMath');
#
my $Json = new JSON;
my $Math = TL::GenMath->new();
my ($Job,$Step,$Return) = ($JOB,undef,'finish');
my (@Report,$M,$S,$P,$L,$D);
my ($SIZE_DATA,$MAP_DATA);#SYMBOL、计算模块、计算模型
my $CALC_COUNT;
my (%SymbolExists,@MapOkPads,@MapFailPads,$isSymbolExitsFilter);
#
$PAR->{step} = 'panel' if(!defined($PAR->{step}));
$PAR->{units} = 'inch' if(!defined($PAR->{units}));
$PAR->{panel_category} = eval($PAR->{panel_category}) if $PAR->{panel_category};
$PAR->{version} = 'select' if(!defined($PAR->{version}));
$PAR->{change_standard_symbol} = 'Yes' if(!defined($PAR->{change_standard_symbol}));
$PAR->{condition} = 'No' if(!defined($PAR->{condition}));
$PAR->{debug_priority} = 0 if(!defined($PAR->{debug_priority}));
$PAR->{debug_add_size_symbol} = "No" if(!defined($PAR->{debug_add_size_symbol}));
$PAR->{save_job} = 'No' unless $PAR->{save_job};
$PAR->{safe_dist} = 0.05 if(!defined($PAR->{safe_dist}));
$PAR->{map_layer} = 'pnl-map' unless $PAR->{map_layer};
$PAR->{map_layer_error} = 'pnl-map-error' unless $PAR->{map_layer_error};
#
my $JOB_PATH = $GEN->getJobPath(job=>$Job);
#################################################################################################################
#################################################################################################################
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_step = get_work_step();
return $ans_step if $ans_step;
##
my $panel_category = $PAR->{panel_category} || 'overlay';
unless(defined($panel_category)){
$GUI->msgbox(-icon=>'error',-text=>"未定义板框运行类型!");
return "error";
}
##
update_loading("获取并选择板框执行版本..",0,position=>'n');
my $version;
my $version_list = $IKM->select_arrayhash(-table=>"pdm_panelmap",-field=>"version",-order=>"version ASC",-where => {category=>$panel_category});
my @tmp_version;
foreach my $ver(sort{$a->{version} <=> $b->{version} } @$version_list){
push @tmp_version,$ver->{version} unless grep {$_ eq $ver->{version}} @tmp_version;
}
$version_list = \@tmp_version;
if( scalar(@$version_list) == 1 ){
$version = $version_list->[0];
}
elsif($PAR->{version} eq "release" and grep( {$_ eq '1'} @$version_list) ){
$version = "1";
}
elsif($PAR->{version} eq "test" and grep( {$_ eq '0'} @$version_list) ){
$version = "0";
}
else{
my @version = $GUI->select_from_treeview(
-headstock=>'tl-question',
-defaultsize=>[200,300],
-selectmode=>'single',
-title=>__('Please Select Version'),
-treemapping=>[version=>'Glib::String'],
-treecolumns=>[
{title=>__('Version'),renders=>[{class=>'Text',text=>'version'}]},
],
-treedata=>[map {{version=>$_}} @$version_list],
-valuefield=>'version',
-selectvalue=>$version_list->[0],
-searchfield=>['version'],
);
return 'Cancel' unless(@version);
$version = $version[0];
}
##
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->zoomHome();
$GEN->units(type=>$PAR->{units});
##
update_loading("解析板框代码并确认配置信息,请稍候..",0,position=>'n');
my $tmp_db_map_data = $IKM->select_arrayhash(
-table=>"pdm_panelmap",
-field=>["id", "parent_id", "version", "category", "flow_order", "symbol_name", "row_name", "map_symbol" , "hole_symbol" , "pattern_symbol", "condition", "content", "status",
"active", "map_class", "avoid_hole_class" , "avoid_pattern_class" , "row_type" , "layer_type", "priority"],
-order=>"version ASC,parent_id ASC,flow_order ASC",
-where => {version=>$version,active=>1,category=>$panel_category,row_type=>['Category','Public','Map Header','Map Symbol','Map Footer']},
);
foreach my $item (@$tmp_db_map_data){
$item->{avoid_hole_class} = eval($item->{avoid_hole_class});
$item->{avoid_pattern_class} = eval($item->{avoid_pattern_class});
$item->{map_class} = eval($item->{map_class});
my %map_class;
if ($item->{map_class}){
foreach my $cls (@{$item->{map_class}}){
$map_class{$cls} = 1;
}
}
$item->{map_class} = \%map_class;
}
my @map_rows;
my @map_footer_rows;
my $row_num = 0;
my $sub_execute_db_map_data;
$sub_execute_db_map_data = sub{
my $db_data = shift;
foreach my $row (@$db_data){
$row->{_row_num} = ++$row_num;
if ($row->{row_type} eq 'Public'){
$row->{priority} = 9999;
}
elsif($row->{row_type} eq 'Map Header'){
$row->{priority} = 8888;
}
elsif($row->{row_type} eq 'Map Footer'){
$row->{priority} = -8888;
}
if ($row->{row_type} eq 'Map Footer'){
push @map_footer_rows,$row;
}
elsif ($row->{row_type} ne 'Category'){
push @map_rows,$row;
}
$sub_execute_db_map_data->([grep{$_->{parent_id} eq $row->{id}} @$tmp_db_map_data]);
}
};
$sub_execute_db_map_data->([grep{!($_->{parent_id})} @$tmp_db_map_data]);
my $row_count = scalar(@map_rows) + 2;
my $row_n = 0;
foreach my $row (sort{$b->{priority} <=> $a->{priority} || $a->{_row_num} <=> $b->{_row_num}} @map_rows){
#条件
next if ($PAR->{debug_priority} and $row->{priority} < $PAR->{debug_priority});
my $disp_name = $row->{row_name}; $disp_name =~ s/\n/ /g;
update_loading('正在计算['.$disp_name.']...',($row_n++)/$row_count);
my $condition = eval($row->{condition});
if ($@) {
$GUI->msgbox(-icon=>'error',-text=>"载入[$disp_name]条件失败! \n $@");
return "Error";
}
$condition = $condition->(%$row) if($condition and ref($condition) eq "CODE");
next unless((!defined($condition) or $condition == 1) or $PAR->{condition} eq "Yes");
#计算
my $calculate_pads;
$calculate_pads = eval($row->{content});
if ($@) {
$GUI->msgbox(-icon=>'error',-text=>"载入[$disp_name]坐标失败! \n $@");
return "Error";
}
if (ref($calculate_pads) eq 'CODE'){
eval{
$calculate_pads = $calculate_pads->(%$row);
};
if ($@) {
$GUI->msgbox(-icon=>'error',-text=>"载入[$disp_name]坐标失败! \n $@");
return "error";
}
}
PUSH_MAP_DATA($calculate_pads,$row);
}
$GEN->openStep(job=>$Job,name=>$Step);
$GEN->units(type=>$PAR->{units});
$PAR->{map_layer} = 'pnl-map' unless $PAR->{map_layer};
$PAR->{map_layer_error} = 'pnl-map-error' unless $PAR->{map_layer_error};
$GEN->deleteLayer(job=>$Job,layer=>[$PAR->{map_layer_error}]);
$GEN->createLayer(job=>$Job,layer=>$PAR->{map_layer},context=>'misc',type=>'signal') unless ($GEN->isLayerExists(job=>$Job,layer=>$PAR->{map_layer}));;
$GEN->clearLayers();
$GEN->affectedLayer(mode=>'all',affected=>'no');
$GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>[$PAR->{map_layer}],clear_before=>'yes');
$GEN->COM('sel_all_feat');
$GEN->selDelete() if $GEN->getSelectCount();
show_loading('正在pnl-map层添加Symbol...',0,position=>'n');
my $pad_count = scalar(@MapOkPads) + scalar(@MapFailPads) + 2;
my $pad_n = 1;
foreach my $pad (@MapOkPads){
update_loading('正在'.$PAR->{map_layer}.'层添加Symbol['.$pad->{symbol}.']'." $pad_n/$pad_count",$pad_n/$pad_count);
$GEN->addPad(%$pad);
$pad_n++;
}
$GEN->workLayer(name=>$PAR->{map_layer},display_number=>1,clear_before=>'yes');
if (@MapFailPads){
$GEN->createLayer(job=>$Job,layer=>$PAR->{map_layer_error},context=>'misc',type=>'signal') unless ($GEN->isLayerExists(job=>$Job,layer=>$PAR->{map_layer_error}));;
$GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>[$PAR->{map_layer_error}],clear_before=>'yes');
$GEN->COM('sel_all_feat');
$GEN->selDelete() if $GEN->getSelectCount();
foreach my $pad (@MapFailPads){
update_loading('正在'.$PAR->{map_layer_error}.'层添加Symbol['.$pad->{symbol}.']'." $pad_n/$pad_count",$pad_n/$pad_count);
$GEN->addPad(%$pad);
$pad_n++;
}
$GEN->workLayer(name=>$PAR->{map_layer_error},display_number=>1,clear_before=>'yes');
$GEN->displayLayer(name=>$PAR->{map_layer},number=>2);
}
update_loading("pnL-map层创建完成,脚本即将结束..",0,position=>'n');
foreach my $row (sort{$b->{priority} <=> $a->{priority} || $a->{_row_num} <=> $b->{_row_num}} @map_footer_rows){
my $disp_name = $row->{row_name}; $disp_name =~ s/\n/ /g;
my $condition = eval($row->{condition});
if ($@) {
$GUI->msgbox(-icon=>'error',-text=>"载入[$disp_name]条件失败! \n $@");
return "Error";
}
$condition = $condition->(%$row) if($condition and ref($condition) eq "CODE");
next unless((!defined($condition) or $condition == 1) or $PAR->{condition} eq "Yes");
#计算
my $calculate_pads;
$calculate_pads = eval($row->{content});
if ($@) {
$GUI->msgbox(-icon=>'error',-text=>"载入[$disp_name]坐标失败! \n $@");
return "Error";
}
if (ref($calculate_pads) eq 'CODE'){
eval{
$calculate_pads->(%$row);
};
if ($@) {
$GUI->msgbox(-icon=>'error',-text=>"载入[$disp_name]坐标失败! \n $@");
return "error";
}
}
}
##
unless( @MapFailPads or $PAR->{map_error} ){
$GEN->deleteLayer(job=>$Job,step=>$Step,layer=>$PAR->{map_layer_error});
}
hide_loading();
$GUI->msgbox(-text=>"请确认 $PAR->{map_layer} 层中的Symbol位置,并手动在 $PAR->{map_layer_error} 修正好!") if ( @MapFailPads or $PAR->{map_error} );
my $info_file = $JOB_PATH.'/user/PNL_map_info';
open(my $fh,'>',$info_file);
print $fh dump({P=>$P,L=>$L,D=>$D,S=>$S});
close($fh);
##报告
if (@Report){
#push @Report,"\n\n".$GEN->getUserName().":".$DB->get_now();
my $Report = join("\n",@Report);
$Report =~ s/\n/<br>/g;
$Report =~ s/\s/\<p\>\&NBSP\;\<\/p\>/g;
my $report_save = '<html><body text="#000022">';
$report_save .= "$Report";
$report_save .= '</body></html>';
$IKM->update_flow_report(-report=>$report_save);
}
else{
$IKM->update_flow_report(-report=>'');
}
##保存料号
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 $Return;
}
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{
#$GEN->workLayer(name=>,number=>1,clear_before=>'yes');
};
#################################################################################################################
#################################################################################################################
sub get_work_step {
my @steps = $GEN->getStepList(job=>$Job);
if ( @steps == 0 ) {
$GUI->msgbox(-icon=>'error',-text=>'在料号中没有Step存在,你将退出!');
return 'Cancel';
}
elsif (@steps != 0){
my @tmp_steps = grep(/^$PAR->{step}$/,@steps);
if ( @tmp_steps == 0 ) {
$GUI->msgbox(-icon=>'warning',-text=>'根据脚本参数过滤出来的step不存在,请检查资料或者脚本参数配置!');
return 'Cancel';
}
elsif (@tmp_steps == 1) {
$Step = $tmp_steps[0];
}
else {
update_loading("选择工作step...",0,position=>'n');
$Step = $GUI->select_step(
-title=>'请选择工作 Step',
-steplist=>[@tmp_steps],
-default=>[$tmp_steps[0]],
-gen=>$GEN,
-selectmode=>'single'
);
return 'Cancel' unless ($Step);
}
}
return undef;
}
sub PUSH_MAP_DATA{
my ($calculate_pads,$item) = @_;
return unless ref($calculate_pads) eq 'ARRAY';
#return unless defined $item->{name};
my @size_pads;
foreach my $pad (@$calculate_pads){
$pad->{name} = $item->{symbol_name} unless $pad->{name};
$pad->{class} = $item->{map_class} unless $pad->{class};
if ($pad->{class} and $pad->{class}{'Pattern'}){
$pad->{pattern_symbol} = $item->{pattern_symbol} || $pad->{hole_symbol} || $item->{hole_symbol} unless $pad->{pattern_symbol};
}
else{
delete $pad->{pattern_symbol};
}
if ($pad->{class} and $pad->{class}{'Hole'}){
$pad->{hole_symbol} = $item->{hole_symbol} || $pad->{pattern_symbol} || $item->{pattern_symbol} unless $pad->{hole_symbol};
}
else{
delete $pad->{hole_symbol};
}
$pad->{map_symbol} = $item->{map_symbol} || $pad->{pattern_symbol} || $pad->{hole_symbol} unless $pad->{map_symbol};
unless (defined $pad->{cannot_move}){
if ($item->{priority} >= 99){
$pad->{cannot_move} = 1;
}
}
$pad->{stack} = '1-'.$P->{layer_count} unless $pad->{stack};
unless($pad->{map_symbol}){
print dump($pad),"\n";
}
if( (! $SymbolExists{$pad->{map_symbol}}) and $pad->{map_symbol} ne 'NO' and
($pad->{map_symbol} !~ /^(rect|oval|r|s|rc_ths)\d+/) and
(! _isSymbolExists($pad->{map_symbol})))
{
$pad->{map_symbol} = $pad->{pattern_symbol} || $pad->{hole_symbol};
}
if ($PAR->{change_standard_symbol} eq 'Yes'){
if ($pad->{map_symbol} =~ /^(rect|oval|r|s)\d+/){
my $pnl_sym = 'pnl_' . $pad->{map_symbol};
unless ($SymbolExists{$pnl_sym} or _isSymbolExists($pnl_sym)){
_create_symbol($pnl_sym,$pad->{map_symbol});
}
$pad->{map_symbol} = $pnl_sym;
}
}
$SymbolExists{$pad->{map_symbol}} = 1;
my @pad_tag = ('S'.($pad->{stack}) , $pad->{name});
if ($pad->{tag}){
if (ref($pad->{tag}) eq 'ARRAY'){
foreach my $k (@{$pad->{tag}}){
push @pad_tag,$k;
}
}
elsif(ref($pad->{tag}) eq 'HASH'){
foreach my $k (sort keys %{$pad->{tag}}){
my $v = $pad->{tag}{$k};
if (defined $v){
push @pad_tag,$k.'='.$v;
}
else{
push @pad_tag,$k;
}
}
}
else{
push @pad_tag,$pad->{tag};
}
}
if ($pad->{size_shiftx}){
push @pad_tag , 'sx='.$pad->{size_shiftx};
}
if ($pad->{size_shifty}){
push @pad_tag , 'sy='.$pad->{size_shifty};
}
push @pad_tag , 'hs=' . $pad->{hole_symbol} if $pad->{hole_symbol};
push @pad_tag , 'ps=' . $pad->{pattern_symbol} if $pad->{pattern_symbol};
my $pad_attr = [{attribute=>'tl_string',text=>join(':',@pad_tag)}];
#push @$pad_attr,$PAR->{can_not_move_attr} if $pad->{cannot_move};
my $map_symbol = $pad->{map_symbol};
if ($PAR->{debug_add_size_symbol} eq 'Yes'){
$map_symbol = $pad->{pattern_symbol} || $pad->{hole_symbol} || $pad->{map_symbol};
}
my $map_pad = {
attributes=>$pad_attr,
x => $pad->{x},
y => $pad->{y},
angle=> $pad->{angle} || 0,
symbol=> $map_symbol ,
mirror => $pad->{mirror}
};
my $size_pad = {
x => $pad->{x},
y => $pad->{y},
stack => $pad->{stack},
hole_symbol => $pad->{hole_symbol},
pattern_symbol => $pad->{pattern_symbol} ,
angle => $pad->{angle},
class => $pad->{class},
name => $pad->{name},
};
push @{$MAP_DATA->{$pad->{name}}{$pad->{stack}}} , $pad;
$size_pad = _shift_size_pad(pad=>$size_pad,shiftx=>$pad->{size_shiftx},shifty=>$pad->{size_shifty});
$size_pad->{angle} = $pad->{angle};
if ($pad->{failed}){
push @MapFailPads,$map_pad unless $map_pad->{symbol} eq 'NO';
}
else{
push @MapOkPads,$map_pad unless $map_pad->{symbol} eq 'NO';
push @{$SIZE_DATA->{$pad->{name}}},$size_pad;
}
}
}
=h
如果以前检查过了那就不检查第二次
=cut
sub _isSymbolExists{
my $symbol = shift;
if(!defined($isSymbolExitsFilter->{$symbol})){
$isSymbolExitsFilter->{$symbol} = 0;
if($GEN->isSymbolExists(job=>'genesislib',symbol=>$symbol) or $GEN->isSymbolExists(job=>$Job,symbol=>$symbol)){
$isSymbolExitsFilter->{$symbol} = 1;
}
}
return $isSymbolExitsFilter->{$symbol};
}
sub GET_AVOID_FEATS {
my %par = @_; #(stack=>'1-8',class=>['S*:*','S-:grp'],name=>[],size_type =>'pattern'|'hole',range=>{x1=>,x2=>,y1=>,y2=>})
$par{size_type} = 'pattern' unless $par{size_type};
if (ref($par{class}) eq 'HASH'){
my @class;
foreach my $k (sort keys %{$par{class}}){
push @class,$k;
}
$par{class} = \@class;
}
my @avoid_feats;
if ($par{class}){
foreach my $name (keys %$SIZE_DATA){
foreach my $class (@{$par{class}}){
my ($stk_flag,@cls) = split(':',$class);
my $ivt = 0; my $all = 0;
if ($cls[0] =~ /^\!/){
$ivt = 1;
$cls[0] =~ s/^\!//;
}
$all = 1 if (! $cls[0] or $cls[0] eq '*');
my $stks = _parse_stack_flag($par{stack},$stk_flag) if $stk_flag;
foreach my $pad (@{$SIZE_DATA->{$name}}){
next unless $pad->{$par{size_type}.'_symbol'};
if (!$stks or ($stks and $stks->{$pad->{stack}})){
if ($all){
push @avoid_feats,{
x => $pad->{x},
y => $pad->{y},
symbol => $pad->{$par{size_type}.'_symbol'},
angle => $pad->{angle},
name => $name,
stack => $pad->{stack},
} if $pad->{$par{size_type}.'_symbol'};
}
else{
if ($ivt){
my $ok = 1;
foreach my $_cls (@cls){
if ($pad->{class}{$_cls}){
$ok = 0; last;
}
}
push @avoid_feats,{
x => $pad->{x},
y => $pad->{y},
symbol => $pad->{$par{size_type}.'_symbol'},
angle => $pad->{angle},
name => $name,
stack => $pad->{stack},
} if ($ok and $pad->{$par{size_type}.'_symbol'});
}
else{
my $ok = 0;
foreach my $_cls (@cls){
if ($pad->{class}{$_cls}){
$ok = 1; last;
}
}
push @avoid_feats,{
x => $pad->{x},
y => $pad->{y},
symbol => $pad->{$par{size_type}.'_symbol'},
angle => $pad->{angle},
name => $name,
stack => $pad->{stack},
} if ($ok and $pad->{$par{size_type}.'_symbol'});
}
}
}
}
}
}
}
if ($par{name}){
foreach my $name (keys %$SIZE_DATA){
foreach my $nam (@{$par{name}}){
my ($stk_flag,$nm) = split(':',$nam);
next unless $nm eq $name;
if ($stk_flag){
my $stks = _parse_stack_flag($par{stack},$stk_flag);
foreach my $pad (@{$SIZE_DATA->{$name}}){
if ($stks->{$pad->{stack}}){
push @avoid_feats,{
x => $pad->{x},
y => $pad->{y},
symbol => $pad->{$par{size_type}.'_symbol'},
angle => $pad->{angle},
name => $name,
stack => $pad->{stack},
} if ($pad->{$par{size_type}.'_symbol'});
}
}
}
else{
foreach my $pad (@{$SIZE_DATA->{$name}}){
push @avoid_feats,{
x => $pad->{x},
y => $pad->{y},
symbol => $pad->{$par{size_type}.'_symbol'},
angle => $pad->{angle},
name => $name,
stack => $pad->{stack},
} if ($pad->{$par{size_type}.'_symbol'});
}
}
}
}
}
if ($par{exclude_name}){
my @tmp;
my %flg;
foreach my $nam (@{$par{exclude_name}}) {
my ($stk_flag,$nm) = split(':',$nam);
unless($stk_flag){
$stk_flag = 'S*';
$nm = $nam;
}
if ($stk_flag){
my $stks = _parse_stack_flag($par{stack},$stk_flag);
foreach my $s (keys %$stks){
$flg{$s.':'.$nm} = 1;
}
}
}
foreach my $p (@avoid_feats) {
my $k = $p->{stack}.':'.$p->{name};
push @tmp , $p unless $flg{$k};
}
@avoid_feats = @tmp;
}
if ($par{range}){
$par{range} = [$par{range}] unless ref($par{range}) eq 'ARRAY';
my @tmp;
foreach my $area (@{$par{range}}){
my $xmin = (exists $area->{x1}) ? $area->{x1} : $area->{xmin};
my $xmax = (exists $area->{x2}) ? $area->{x2} : $area->{xmax};
my $ymin = (exists $area->{y1}) ? $area->{y1} : $area->{ymin};
my $ymax = (exists $area->{y2}) ? $area->{y2} : $area->{ymax};
($xmin,$xmax) = sort{$a <=> $b} sort ($xmin,$xmax);
($ymin,$ymax) = sort{$a <=> $b} sort ($ymin,$ymax);
foreach my $feat (@avoid_feats) {
my ($l,$s) = $feat->{symbol} =~ /(\d+\.?\d*)/g;
my $sum = ($l + $s)/1000;
if (TL::GenMath->is_range_intersect({min=>$xmin,max=>$xmax},{min=>$feat->{x} - $sum,max=>$feat->{x} + $sum}) or
TL::GenMath->is_range_intersect({min=>$ymin,max=>$ymax},{min=>$feat->{y} - $sum,max=>$feat->{y} + $sum}))
{
push @tmp,$feat;
}
}
}
return \@tmp;
}
else{
return \@avoid_feats;
}
}
sub _parse_stack_flag{
my ($stk,$stk_flag) = @_;
my %stks;
my $invert;
$stk_flag = 'S*' unless $stk_flag;
if ($stk =~ /^\!/){
$stk_flag =~ s/^\!//;
$invert = 1;
}
if ($stk_flag eq 'S'){
$stks{$stk} = 1;
}
elsif($stk_flag eq 'SO' or $stk_flag eq 'SE'){
$stks{1 . '-' . $P->{layer_count}} = 1;
}
elsif($stk_flag eq 'S-'){
foreach my $s (@{$S->{$stk}{all_sub_stacks}}){
$stks{$s} = 1;
}
}
elsif($stk_flag eq 'S+'){
foreach my $s (@{$S->{$stk}{all_parent_stacks}}){
$stks{$s} = 1;
}
}
elsif($stk_flag eq 'S-1'){
foreach my $s (@{$S->{$stk}{sub_stacks}}){
$stks{$s} = 1;
}
}
elsif($stk_flag eq 'S+1'){
if ($S->{$stk}{parent_stack}){
$stks{$S->{$stk}{parent_stack}} = 1;
}
}
elsif($stk_flag eq 'S-T'){
if (@{$S->{$stk}{sub_stacks}}){
$stks{$S->{$stk}{sub_stacks}[0]} = 1;
}
}
elsif($stk_flag eq 'S-B'){
if (@{$S->{$stk}{sub_stacks}}){
$stks{$S->{$stk}{sub_stacks}[-1]} = 1;
}
}
elsif($stk_flag eq 'S*'){
foreach my $s (keys %$S){
$stks{$s} = 1;
}
}
elsif($stk_flag =~ /^S(\d+\-\d+)$/){
$stks{$1} = 1;
}
if ($invert){
my %tmp;
foreach my $s (keys %$S){
$tmp{$s} = 1 unless $stks{$s};
}
return \%tmp;
}
else{
return \%stks;
}
}
sub GET_MAP_FEATS2{
my @pars = @_;
my @return;
foreach my $p (@pars){
push @return , (GET_MAP_FEATS(%$p));
}
if (wantarray){
return @return;
}
else{
return \@return;
}
}
sub GET_MAP_FEATS{
my %par = @_; #(map_flag => , layer_stack => ,deep_copy=>)
#name,stack,tag
$par{layer_stack} = '1-'.$P->{layer_count} unless $par{layer_stack};
$par{deep_copy} = 1 if (!defined $par{deep_copy});
my ($m_name,$m_stack,$m_tag);
if ($par{map_flag}){
$par{map_flag} =~ s/\s+//g;
($m_stack,$m_name,$m_tag) = split(':',$par{map_flag});
if ($m_tag){
my @tgs = split(/\s*(\(|\)|\&+|and|or|\|+)\s*/,$m_tag);
foreach my $t (@tgs){
if ($t =~ /^\&+$/){
$t = 'and';
}
elsif ($t =~ /^\|+$/){
$t = 'or';
}
elsif ($t =~ /^\s*([^ ]+)\s*\=\s*([^ ]+)\s*/){
my ($n,$v) = ($1,$2);
if ($v =~ /^\[(.*)\]$/){
my $tvv = $1;
my @vv = split(/\s*\,\s*/,$tvv);
foreach my $tv (@vv){
$tv = '$TAG->{'.$n.'} eq \'' . $tv . '\'';
}
$t = '('.join(' or ', @vv ).')';
}
else{
$t = '$TAG->{' . $1 . '} eq \'' . $2 .'\'';
}
}
else{
$t = '$TAG->{' . $t . '}';
}
}
$m_tag = join(' ',@tgs);
}
}
if ($par{map_stack}){
$m_stack = $par{map_stack};
}
if ($par{map_name}){
$m_name = $par{map_name};
}
if ($par{map_tag}){
$m_tag = $par{map_tag};
}
if ($m_stack){
if (ref($m_stack) eq 'CODE'){
$m_stack->(%par);
}
}
else{
$m_stack = 'S*';
}
my $stks;
if (ref($m_stack) eq 'ARRAY'){
foreach my $stk_flag (@$m_stack){
my $t_stks = _parse_stack_flag($par{layer_stack},$stk_flag);
foreach my $k (keys %$t_stks){
$stks->{$k} = $t_stks->{$k};
}
}
}
elsif(ref($m_stack) eq 'HASH'){
$stks = $m_stack;
}
else{
$stks = _parse_stack_flag($par{layer_stack},$m_stack);
}
return () unless $MAP_DATA->{$m_name};
my @map_feats;
foreach my $map_stk (keys %{$MAP_DATA->{$m_name}}){
next unless $stks->{$map_stk};
foreach my $map_pad (@{$MAP_DATA->{$m_name}{$map_stk}}){
my $TAG = $map_pad->{tag};
if ($m_tag){
if (ref($m_tag) eq 'CODE'){
my $ret = $m_tag->(tag=>$TAG);
next unless $ret;
}
else{
my $ret = eval($m_tag);
next unless $ret;
}
}
push @map_feats,$map_pad;
}
}
if ($par{deep_copy} and @map_feats){
my $dc = $IKM->deep_copy(\@map_feats);
@map_feats = @$dc;
}
foreach my $item (@map_feats){
$item->{TYPE} = 'MAP_FEAT';
}
if (wantarray){
return @map_feats;
}
else{
return \@map_feats;
}
}
sub _create_symbol{
my ($symbol,$pad_sym) = @_;
$GEN->createSymbol(job=>$Job,name=>$symbol);
$GEN->openSymbol(job=>$Job,name=>$symbol);
$GEN->units(type=>$PAR->{units} || 'inch');
$GEN->addPad(x=>0, y=>0, symbol=>$pad_sym);
$GEN->closeSymbol();
$GEN->openStep(job=>$Job,name=>$Step);
}
sub _shift_size_pad{
my %par = @_; #pad=>,shiftx=>,shift=>
my $pad = $par{pad};
my ($point) = TL::GenMath->p_trans({x=>$pad->{x},y=>$pad->{y}},0,'no',$par{shiftx},$par{shifty},$pad);
return $point;
}
sub MAX{
my @sizes = @_;
my $size;
foreach my $s (@sizes){
$size = $s if (!defined $size or $size < $s);
}
return $size;
}
sub MIN{
my @sizes = @_;
my $size;
foreach my $s (@sizes){
$size = $s if (!defined $size or $size > $s);
}
return $size;
}
sub mm2mil{
my $mm = shift;
return $mm*100/2.54;
}
sub mm2inch{
my $mm = shift;
return $mm*100/2.54/1000;
}
sub mil2inch{
my $mil = shift;
return $mil/1000;
}
sub inch2mil{
my $mil = shift;
return $mil*1000;
}
sub inch2mm{
my $inch = shift;
return 25.4*$inch;
}
=head
NAME:
DESCRIPTION: Run Overlay
PARAMETER:
[
{
name : 'step',
title : 'Panel Step',
type : 'LineEdit',
value : 'E:/',
pack : {row:0,column:1},
property : {
tool_tip:'panel step名称,如未设置,默认为panel'
}
},
{
name : 'units',
title : 'Units',
type : 'ComboBox',
property : {
size_policy:'Expanding,Fixed',
item_list:[
{name:'mm',text:'mm'},
{name:'inch',text:'inch'},
],
tool_tip:'脚本运行genesis的工作单位,如未设置,默认为inch'
},
pack : {row:1,column:1},
},
{
name : 'panel_category',
title : '板框类型',
type : 'TextEdit',
property:{tool_tip:'未定义则默认为标准的category:overlay'},
setter:function(obj,value,self){
obj.setPlainText(value);
},
getter:function(obj,self){
return obj.plainText
}
},
{
name : 'version',
title : 'Version',
type : 'ComboBox',
property : {
size_policy:'Expanding,Fixed',
item_list:[
{name:'release',text:'正式版'},
{name:'test',text:'测试版'},
{name:'select',text:'选择版本'},
],
tool_tip:'板框版本:正式版为1,测试版为0,如未设置,默认为选择版本'
},
pack : {row:1,column:1},
},
{
name : 'font',
title : 'Font',
type : 'LineEdit',
pack : {row:0,column:1},
property : {
tool_tip:'genesis中添加文字字体,默认为standard_new'
}
},
{
name : 'default_layer',
title : '默认层别',
type : 'TextEdit',
pack : {row:0,column:1},
property : {
tool_tip:'默认层别'
},
setter:function(obj,value,self){
obj.setPlainText(value);
},
getter:function(obj,self){
return obj.plainText
}
},
{
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-05-17 Alan Fu
1.新版本.
HELP:
<html><body bgcolor="#DDECFE">
<font size="3" color="#003DB2"><p>功能简介</p></font>
<p> Run Overlay </p>
</body></html>
=cut
#################################################################################################################
#################################################################################################################
use strict;
use utf8;
use JSON;
use Encode;
use Data::Dump 'dump';
use Number::Format 'round';
use_module('TL_GenMath');
use_module("PubFunction");
my $Func = PubFunction->new();
my $Math = TL::GenMath->new();
#
my (@Report,$M,$S,$P,$L,$D,$MAP_DATA,@LAYERS,$JOB_PATH,$LAYER_TYPE_LIST,@LAYER_ROWS,$_TMP_LAYER_STK);
my ($Job,$Step,$Return) = ($JOB,undef,'finish');
my ($_FEAT_NUM);
#
$PAR->{step} = 'panel' if(!defined($PAR->{step}));
$PAR->{units} = 'inch' if(!defined($PAR->{units}));
$PAR->{panel_category} = eval($PAR->{panel_category}) if $PAR->{panel_category};
$PAR->{version} = 'select' if(!defined($PAR->{version}));
$PAR->{font} = 'standard_new' if(!defined($PAR->{font}));
$PAR->{save_job} = 'No' unless $PAR->{save_job};
$PAR->{map_layer} = 'pnl-map' unless $PAR->{map_layer};
$PAR->{map_layer_error} = 'pnl-map-error' unless $PAR->{map_layer_error};
#################################################################################################################
#################################################################################################################
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_step = get_work_step();
return $ans_step if $ans_step;
##
if (! $GEN->isLayerExists(job=>$Job,layer=>$PAR->{map_layer} ) ) {
$GUI->msgbox(-type=>'error',-text=>"$PAR->{map_layer} 不存在, 请检查!");
return 'Error';
}
##
my $panel_category = $PAR->{panel_category} || 'overlay';
unless(defined($panel_category)){
$GUI->msgbox(-icon=>'error',-text=>"未定义板框运行类型!");
return "error";
}
##
update_loading("获取并选择板框执行版本..",0,position=>'n');
my $version;
my $version_list = $IKM->select_arrayhash(-table=>"pdm_panelmap",-field=>"version",-order=>"version ASC",-where => {category=>$panel_category});
my @tmp_version;
foreach my $ver(sort{$a->{version} <=> $b->{version} } @$version_list){
push @tmp_version,$ver->{version} unless grep {$_ eq $ver->{version}} @tmp_version;
}
$version_list = \@tmp_version;
##
if( scalar(@$version_list) == 1 ){
$version = $version_list->[0];
}
elsif($PAR->{version} eq "release" and grep( {$_ eq '1'} @$version_list) ){
$version = "1";
}
elsif($PAR->{version} eq "test" and grep( {$_ eq '0'} @$version_list) ){
$version = "0";
}
else{
$version = $GUI->select_from_treeview(
-headstock=>'tl-question',
-defaultsize=>[200,300],
-selectmode=>'single',
-title=>__('请选择板框版本'),
-treemapping=>[version=>'Glib::String'],
-treecolumns=>[
{title=>__('Version'),renders=>[{class=>'Text',text=>'version'}]},
],
-treedata=>[map {{version=>$_}} @$version_list],
-valuefield=>'version',
-selectvalue=>$version_list->[0],
-searchfield=>['version'],
);
return 'Cancel' unless($version);
}
##
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->zoomHome();
$GEN->units(type=>$PAR->{units});
$GEN->COM('display_sr',display=>'no');
$GEN->COM('disp_off');
#1.读取map 信息
update_loading("正在读取pnl-map层信息 ,请稍候..",0,position=>'n');
$MAP_DATA = PANEL_MAP_TO_DATA(job=>$Job,step=>$Step,layers=>[$PAR->{map_layer},$PAR->{map_layer_error}],units=>$PAR->{units});
#2.读取MAP传来的值
update_loading("正在读取pnl-map产生的信息文件 ,请稍候..",0,position=>'n');
$JOB_PATH = $GEN->getJobPath(job=>$Job);
unless (-f $JOB_PATH.'/user/PNL_map_info'){
$GUI->msgbox('Map信息文件'.$JOB_PATH.'/user/PNL_map_info不存在!');
return 'Error';
}
my $map_info = do($JOB_PATH.'/user/PNL_map_info');
$S = $map_info->{S};
$P = $map_info->{P};
$L = $map_info->{L};
$D = $map_info->{D};
$M = $GEN->getMatrix(job=>$Job);
delete $M->{$PAR->{map_layer}};
delete $M->{$PAR->{map_layer_error}};
#3.用户选择层
update_loading("选择板框添加层别..",0,position=>'n');
my $default_layer;
if (lc($PAR->{default_layer}) eq 'all'){
$default_layer = [keys %$M];
}
else{
$default_layer = eval($PAR->{default_layer});
}
@LAYERS = $GUI->select_layer(
-title=>__('Run Panel Overlay'),
-layermatrix=>$M,
-selectmode => 'multiple',
-default => $default_layer,
);
return 'Cancel' unless(@LAYERS);
update_loading("开始板框准备工作..",0,position=>'n');
my $db_data = $IKM->select_arrayhash(
-table=>"pdm_panelmap",
-field=>["id", "parent_id", "version", "category", "flow_order", "symbol_name", "row_name", "map_symbol" , "hole_symbol" , "pattern_symbol", "condition", "content", "status",
"active", "map_class", "avoid_hole_class" , "avoid_pattern_class" , "row_type" , "layer_type", "priority"],
-where=>{version=>$version,category=>$panel_category,active=>1},
#-order=>'flow_order asc',
-order=>"version ASC,parent_id ASC,flow_order ASC",
);
foreach my $row (@$db_data){
if ($row->{row_type} eq 'Map Header' or $row->{row_type} eq 'Map Footer' or $row->{row_type} eq 'Map Symbol'){
$row->{row_type} = 'Category';
}
push @LAYER_ROWS,$row;
}
foreach my $stack (values %$S){
my $stk = $stack->{key};
$L->{$stack->{top_layer_num}}{stack} = $stk;
$L->{$stack->{top_layer_num}}{layer_side} = 'Top';
$L->{$stack->{bot_layer_num}}{stack} = $stk;
$L->{$stack->{bot_layer_num}}{layer_side} = 'Bot';
foreach my $drl (keys %$D){
my $drill = $D->{$drl};
if ($drill->{drl_type} eq 'Laser'){
if ($drill->{drl_start_num} == $stack->{start_num}){
$drill->{stack} = $stk;
$drill->{drl_side} = 'Top';
}
elsif($drill->{drl_end_num} == $stack->{end_num}){
$drill->{stack} = $stk;
$drill->{drl_side} = 'Bot';
}
}
else{
if ($drill->{drl_start_num} == $stack->{start_num} and
$drill->{drl_end_num} == $stack->{end_num})
{
$drill->{stack} = $stk;
}
}
}
}
_EXEC_ROWS(['Public','Overlay Header']);
##
foreach my $key(keys %$LAYER_TYPE_LIST){
$LAYER_TYPE_LIST->{$key} = eval($LAYER_TYPE_LIST->{$key});
}
##
my $_layer_n = 1;my $_layer_count = scalar(@LAYERS) + 2;
foreach my $LAYER (@LAYERS){
my ($LAYER_SIDE,$LAYER_NUM,$LAYER_STACK);
$LAYER_NUM = $M->{$LAYER}{layer_num} || $M->{$LAYER}{tl_num};
if ($M->{$LAYER}{drl_start_num} and $M->{$LAYER}{drl_end_num}){
##core上打镭射增加
if( $P->{laser_on_core} ){
foreach my $stack (sort{$b->{stack_level} <=> $a->{stack_level} || $a->{start_num} <=> $b->{start_num}} values %$S){
if ($M->{$LAYER}{drl_start_num} == $stack->{start_num} and $M->{$LAYER}{drl_end_num} == $stack->{end_num}){
$LAYER_STACK = $stack->{key}; last;
}
}
}
##
unless($LAYER_STACK){
foreach my $stack (sort{$b->{stack_level} <=> $a->{stack_level} || $a->{start_num} <=> $b->{start_num}} values %$S){
if ($M->{$LAYER}{drl_start_num} == $stack->{start_num} or $M->{$LAYER}{drl_end_num} == $stack->{end_num}){
$LAYER_STACK = $stack->{key}; last;
}
}
}
if (exists $D->{$LAYER_STACK}){
if ($M->{$LAYER}{layer_side}){
$LAYER_SIDE = $M->{$LAYER}{layer_side} eq 'top' ? 'Top' : ($M->{$LAYER}{layer_side} eq 'bottom' ? 'Bot' : '');
}
else{
$LAYER_SIDE = $D->{$LAYER_STACK}{drl_side};
}
}
}
elsif(exists $L->{$LAYER_NUM}){
$LAYER_STACK = $L->{$LAYER_NUM}{stack};
$LAYER_SIDE = $L->{$LAYER_NUM}{layer_side};
}
else{
$LAYER_STACK = '1-'.$P->{layer_count};
$LAYER_SIDE = $M->{$LAYER}{layer_side} eq 'top' ? 'Top' : ($M->{$LAYER}{layer_side} eq 'bottom' ? 'Bot' : '');
}
if(!defined($LAYER_SIDE) and defined($M->{$LAYER}{layer_side})){
$LAYER_SIDE = $M->{$LAYER}{layer_side} eq 'top' ? 'Top' : ($M->{$LAYER}{layer_side} eq 'bottom' ? 'Bot' : '');
}
$_TMP_LAYER_STK = $LAYER_STACK;
_EXEC_ROWS(['Layer Header'],$LAYER);
show_loading("正在创建[${LAYER}]层板框图形...",$_layer_n/$_layer_count,position=>'n');
CREATE_LAYER_OVERLAY(layer=>$LAYER,layer_stack=>$LAYER_STACK,layer_num=>$LAYER_NUM,layer_side=>$LAYER_SIDE);
_EXEC_ROWS(['Layer Footer'],$LAYER);
$_layer_n++;
}
$GEN->COM('disp_on');
_EXEC_ROWS(['Overlay Footer']);
##
$GEN->clearLayers();
$GEN->affectedLayer( mode=>'all',affected=>'no' );
hide_loading();
#报告
if (@Report){
#push @Report,"\n\n".$GEN->getUserName().":".$DB->get_now();
my $Report = join("\n",@Report);
$Report =~ s/\n/<br>/g;
$Report =~ s/\s/\<p\>\&NBSP\;\<\/p\>/g;
my $report_save = '<html><body text="#000022">';
$report_save .= "$Report";
$report_save .= '</body></html>';
$IKM->update_flow_report(-report=>$report_save);
}
else{
$IKM->update_flow_report(-report=>'');
}
##保存料号
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 $Return;
}
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{
$GEN->COM('filter_reset',filter_name=>'popup');
$GEN->clearHighlight();
$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){
my @tmp_steps = grep(/^$PAR->{step}$/,@steps);
if ( @tmp_steps == 0 ) {
$GUI->msgbox(-icon=>'warning',-text=>'根据脚本参数过滤出来的step不存在,请检查资料或者脚本参数配置!');
return 'Cancel';
}
elsif (@tmp_steps == 1) {
$Step = $tmp_steps[0];
}
else {
update_loading("选择工作step...",0,position=>'n');
$Step = $GUI->select_step(
-title=>'请选择工作 Step',
-steplist=>[@tmp_steps],
-default=>[$tmp_steps[0]],
-gen=>$GEN,
-selectmode=>'single'
);
return 'Cancel' unless ($Step);
}
}
return undef;
}
sub _parse_layer_types{
my $LAYER = shift;
my $type_str = shift;
my $layer_types = eval($type_str);
$layer_types = [keys %$LAYER_TYPE_LIST] unless $layer_types;
my $LAYER_TYPES;
foreach my $type (@$layer_types){
next unless $LAYER_TYPE_LIST->{$type};
if (ref($LAYER_TYPE_LIST->{$type}) eq 'Regexp'){
$LAYER_TYPES->{$type} = 1 if $LAYER =~ $LAYER_TYPE_LIST->{$type};
}
elsif(ref($LAYER_TYPE_LIST->{$type}) eq 'ARRAY'){
foreach my $t (@{$LAYER_TYPE_LIST->{$type}}){
if (lc($t) eq lc($type)){
$LAYER_TYPES->{$type} = 1;
last;
}
}
}
elsif(ref($LAYER_TYPE_LIST->{$type}) eq 'CODE'){
$LAYER_TYPES->{$type} = 1 if $LAYER_TYPE_LIST->{$type}->(LAYER=>$LAYER,M=>$M,D=>$D,L=>$L,P=>$P);
}
else{
$LAYER_TYPES->{$type} = 1 if lc($LAYER) eq lc($LAYER_TYPE_LIST->{$type});
}
}
return $LAYER_TYPES;
}
sub MAP_TO_LAYER_FEATS {
my %par = @_; #(layer=>'',draw_layer=>,parent_id=>)
my $LAYER = $par{layer};
my $LAYER_STACK = $par{layer_stack};
my $LAYER_NUM = $par{layer_num};
my $LAYER_SIDE = $par{layer_side};
my $DRAW_LAYER = $par{draw_layer};
$DRAW_LAYER= $par{layer} unless $DRAW_LAYER;
my @feats;
##
$par{parent_id} = 0 unless $par{parent_id};
##
foreach my $row (@LAYER_ROWS){
#条件
next if $par{parent_id} != $row->{parent_id};
#$GUI->debug(dump($par{parent_id}, $row->{parent_id}));
if ($row->{row_type} eq 'Layer'){
#my $ans = $GUI->debug(dump(1111,'---',$LAYER,'---',$row->{layer_type}));
#exit unless $ans eq 'ok';
my $LAYER_TYPES = _parse_layer_types($LAYER,$row->{layer_type});
#my $ans = $GUI->debug(dump($LAYER,'---',$LAYER_TYPES,'---',$row->{layer_type}));
#exit unless $ans eq 'ok';
next unless $LAYER_TYPES;
#$GUI->debug(dump($row->{layer_type}, $LAYER_TYPES));
my $content = eval($row->{content});
if ($@) {
print dump($row),"\n";
print dump($@),"\n";
print dump(ref($content)),"\n";
print dump($content),"\n";
$GEN->PAUSE('error');
$GUI->msgbox(-icon=>'error',-text=>"[$row->{row_name}]在${LAYER}上执行错误!\n $@");
exit;
}
if (ref($content) eq 'CODE'){
$content = $content->(layer=>$LAYER,layer_stack=>$LAYER_STACK,layer_num=>$LAYER_NUM,layer_side=>$LAYER_SIDE,draw_layer=>$DRAW_LAYER);
}
if (ref($content) eq 'ARRAY' or ref($content) eq 'HASH'){
$content = [$content] unless ref($content) eq 'ARRAY';
foreach my $item (@$content){
if ($item->{feat_type} ){
push @feats,$item;
next;
}
my $map_pads;
$item->{layer_stack} = $LAYER_STACK unless defined $item->{layer_stack};
#$item->{layer_flag} = 'S,E' unless $item->{layer_flag};
$item->{layer_num} = $LAYER_NUM unless $item->{layer_num};
if ($item->{side_flag}){
if (uc($item->{side_flag}) eq 'T' or uc($item->{side_flag}) eq 'TOP'){
next unless (uc($LAYER_SIDE) eq 'T' or uc($LAYER_SIDE) eq 'TOP');
}
else{
next if (uc($LAYER_SIDE) eq 'T' or uc($LAYER_SIDE) eq 'TOP');
}
}
if($item->{map_pads}){
$map_pads = delete $item->{map_pads};
}
else{
if (ref($item->{condition}) eq 'CODE'){
$item->{condition} = $item->{condition}->(layer=>$LAYER,layer_stack=>$LAYER_STACK,layer_num=>$LAYER_NUM,layer_side=>$LAYER_SIDE,draw_layer=>$DRAW_LAYER);
next if (defined $item->{condition} and $item->{condition} == 0);
}
$map_pads = GET_MAP_FEATS(%$item,deep_copy=>0);
}
next unless $map_pads;
foreach my $map_pad (@$map_pads){
my $tmp = $Func->deep_copy($item);
foreach my $k (keys %$tmp){
$tmp->{$k} = $tmp->{$k}->(layer=>$LAYER,layer_stack=>$LAYER_STACK,layer_num=>$LAYER_NUM,layer_side=>$LAYER_SIDE,draw_layer=>$DRAW_LAYER,map_pad_stk=>$map_pad->{stack},map_pad=>$map_pad) if ref($tmp->{$k}) eq 'CODE';
}
if ($tmp->{layer_flag}){
next unless _parse_layer_flag($map_pad->{stack},$tmp->{layer_flag},$tmp->{layer_num});
}
if (defined $item->{text}){
push @feats,map_feat_to_text(%$tmp,map_pad=>$map_pad);
}
elsif(defined $item->{xs}){
push @feats,map_feat_to_line(%$tmp,map_pad=>$map_pad);
}
else{
push @feats,map_feat_to_pad(%$tmp,map_pad=>$map_pad);
}
}
}
}
}
push @feats,MAP_TO_LAYER_FEATS(%par,parent_id=>$row->{id});
}
return @feats;
};
sub GET_MAP_FEATS{
my %par = @_; #(map_flag => , layer_stack => ,deep_copy=>)
#name,stack,tag
$par{layer_stack} = $_TMP_LAYER_STK unless $par{layer_stack};
$par{deep_copy} = 1 if (!defined $par{deep_copy});
my ($m_name,$m_stack,$m_tag);
if ($par{map_flag}){
$par{map_flag} =~ s/\s+//g;
($m_stack,$m_name,$m_tag) = split(':',$par{map_flag});
if ($m_tag){
my @tgs = split(/\s*(\(|\)|\&+|and|or|\|+)\s*/,$m_tag);
foreach my $t (@tgs){
if ($t =~ /^\&+$/){
$t = 'and';
}
elsif ($t =~ /^\|+$/){
$t = 'or';
}
elsif ($t =~ /^\s*([^ ]+)\s*\=\s*([^ ]+)\s*/){
my ($n,$v) = ($1,$2);
if ($v =~ /^\[(.*)\]$/){
my $tvv = $1;
my @vv = split(/\s*\,\s*/,$tvv);
foreach my $tv (@vv){
$tv = '$TAG->{'.$n.'} eq \'' . $tv . '\'';
}
$t = '('.join(' or ', @vv ).')';
}
else{
$t = '$TAG->{' . $1 . '} eq \'' . $2 .'\'';
}
}
else{
$t = '$TAG->{' . $t . '}';
}
}
$m_tag = join(' ',@tgs);
}
}
if ($par{map_stack}){
$m_stack = $par{map_stack};
}
if ($par{map_name}){
$m_name = $par{map_name};
}
if ($par{map_tag}){
$m_tag = $par{map_tag};
}
if ($m_stack){
if (ref($m_stack) eq 'CODE'){
$m_stack->(%par);
}
}
else{
$m_stack = 'S*';
}
my $stks;
if (ref($m_stack) eq 'ARRAY'){
foreach my $stk_flag (@$m_stack){
my $t_stks = _parse_stack_flag($par{layer_stack},$stk_flag);
foreach my $k (keys %$t_stks){
$stks->{$k} = $t_stks->{$k};
}
}
}
elsif(ref($m_stack) eq 'HASH'){
$stks = $m_stack;
}
else{
$stks = _parse_stack_flag($par{layer_stack},$m_stack);
}
return () unless $MAP_DATA->{$m_name};
my @map_feats;
foreach my $map_stk (keys %{$MAP_DATA->{$m_name}}){
next unless $stks->{$map_stk};
foreach my $map_pad (@{$MAP_DATA->{$m_name}{$map_stk}}){
my $TAG = $map_pad->{tag};
if ($m_tag){
if (ref($m_tag) eq 'CODE'){
my $ret = $m_tag->(tag=>$TAG);
next unless $ret;
}
else{
my $ret = eval($m_tag);
next unless $ret;
}
}
push @map_feats,$map_pad;
}
}
if ($par{deep_copy} and @map_feats){
my $dc = $Func->deep_copy(\@map_feats);
@map_feats = @$dc;
}
foreach my $item (@map_feats){
$item->{TYPE} = 'MAP_FEAT';
}
if (wantarray){
return @map_feats;
}
else{
return \@map_feats;
}
}
sub _EXEC_ROWS {
my $row_type = shift;
my $LAYER = shift;
my $parent_id = shift || 0;
my %row_types;
foreach my $t (@$row_type,'Category'){
$row_types{$t} = 1;
}
foreach my $row (@LAYER_ROWS){
next if $row->{parent_id} ne $parent_id;
if ($row->{row_type} ne 'Category' and $row_types{$row->{row_type}}){
if (defined $LAYER){
my $LAYER_TYPES = _parse_layer_types($LAYER,$row->{layer_type});
next unless $LAYER_TYPES;
}
my $content = eval($row->{content});
if ($@) {
$GUI->msgbox(-icon=>'error',-text=>"[$row->{row_name}]在${LAYER}上执行错误!\n $@");
return;
}
if (ref($content) eq 'CODE'){
$content->(layer=>$LAYER);
}
}
_EXEC_ROWS($row_type,$LAYER,$row->{id});
}
return ;
};
sub map_feat_to_pad {
my %par = @_;#(map_pad=>{x=>,y=>,angle=>,mirror=>})
$par{nx} = 1 unless $par{nx};
$par{ny} = 1 unless $par{ny};
$par{dx} = 0 unless $par{dx};
$par{dy} = 0 unless $par{dy};
$par{sx} = 0 unless $par{sx};
$par{sy} = 0 unless $par{sy};
my @pads;
foreach my $num_nx (1..$par{nx}){
foreach my $num_ny (1..$par{ny}){
#偏移
my $pad;
my ($dx_shift,$dy_shift) = (($num_nx-1)*$par{dx},($num_ny-1)*$par{dy});
$pad->{feat_type} = 'pad';
$pad->{x} = $par{map_pad}{x} + $par{sx} + $dx_shift;
$pad->{y} = $par{map_pad}{y} + $par{sy} + $dy_shift;
$pad->{angle} = $par{angle} || 0;
$pad->{mirror} = $par{mirror} || 'no';
$pad->{polarity} = $par{polarity} || 'positive';
$pad->{symbol} = $par{symbol};
$pad->{priority} = $par{priority};
$pad->{num} = $_FEAT_NUM++;
if ($par{attributes}){
if (ref($par{attributes}) eq 'ARRAY'){
push @{$pad->{attributes}},@{$par{attributes}};
}
else{
push @{$pad->{attributes}},$par{attributes};
}
}
push @{$pad->{attributes}},@{$par{map_pad}{attributes}};
push @pads,$pad;
}
}
return TL::GenMath->p_trans({x=>$par{map_pad}{x},y=>$par{map_pad}{y}},$par{map_pad}{angle},$par{map_pad}{mirror},0,0,@pads);
}
sub map_feat_to_line {
my %par = @_;#(map_pad=>{x=>,y=>,angle=>,mirror=>})
$par{nx} = 1 unless $par{nx};
$par{ny} = 1 unless $par{ny};
$par{dx} = 0 unless $par{dx};
$par{dy} = 0 unless $par{dy};
$par{xs} = 0 unless $par{xs};
$par{ys} = 0 unless $par{ys};
$par{xe} = 0 unless $par{xe};
$par{ye} = 0 unless $par{ye};
my @lines;
foreach my $num_nx (1..$par{nx}){
foreach my $num_ny (1..$par{ny}){
#偏移
my $line;
my ($dx_shift,$dy_shift) = (($num_nx-1)*$par{dx},($num_ny-1)*$par{dy});
$line->{feat_type} = 'line';
$line->{xs} = $par{map_pad}{x} + $par{xs} + $dx_shift;
$line->{ys} = $par{map_pad}{y} + $par{ys} + $dy_shift;
$line->{xe} = $par{map_pad}{x} + $par{xe} + $dx_shift;
$line->{ye} = $par{map_pad}{y} + $par{ye} + $dy_shift;
$line->{polarity} = $par{polarity} || 'positive';
$line->{symbol} = $par{symbol};
$line->{priority} = $par{priority};
$line->{num} = $_FEAT_NUM++;
if ($par{attributes}){
if (ref($par{attributes}) eq 'ARRAY'){
push @{$line->{attributes}},@{$par{attributes}};
}
else{
push @{$line->{attributes}},$par{attributes};
}
}
push @{$line->{attributes}},@{$par{map_pad}{attributes}};
push @lines,$line;
}
}
foreach my $line (@lines){
my ($ps,$pe) = TL::GenMath->p_trans({x=>$par{map_pad}{x},y=>$par{map_pad}{y}},$par{map_pad}{angle},$par{map_pad}{mirror},0,0,{x=>$line->{xs},y=>$line->{ys}},{x=>$line->{xe},y=>$line->{ye}});
($line->{xs},$line->{ys}) = ($ps->{x},$ps->{y});
($line->{xe},$line->{ye}) = ($pe->{x},$pe->{y});
}
return @lines;
}
sub map_feat_to_text{
my %par = @_;
$par{sx} = 0 unless $par{sx};
$par{sy} = 0 unless $par{sy};
my $text;
$text->{feat_type} = 'text';
$text->{x} = $par{map_pad}{x} + $par{sx};
$text->{y} = $par{map_pad}{y} + $par{sy};
$text->{angle} = $par{angle} || 0;
$text->{mirror} = $par{mirror} || 'no';
$text->{polarity} = $par{polarity} || 'positive';
$text->{text} = $par{text};
$text->{x_size} = $par{x_size} || 0.15;
$text->{y_size} = $par{y_size} || 0.15;
$text->{line_width} = $par{line_width} || 10;
$text->{anchor} = $par{anchor} || 'center';
$text->{trans_anchor} = $par{trans_anchor} ;
$text->{fontname} = $par{fontname} || $PAR->{font};
$text->{type} = $par{type};
$text->{text_length} = $par{text_length};
$text->{priority} = $par{priority};
$text->{num} = $_FEAT_NUM++;
if ($par{attributes}){
if (ref($par{attributes}) eq 'ARRAY'){
push @{$text->{attributes}},@{$par{attributes}};
}
else{
push @{$text->{attributes}},$par{attributes};
}
}
push @{$text->{attributes}},@{$par{map_pad}{attributes}};
my ($tmp) = TL::GenMath->p_trans({x=>$par{map_pad}{x},y=>$par{map_pad}{y}},$par{map_pad}{angle},'no',0,0,$text);
my $mirror;
if ($par{map_pad}{mirror} eq 'yes'){
if ($tmp->{mirror} eq 'no'){
$mirror = 'yes';
}
else{
$mirror= 'no';
}
}
else{
$mirror = $tmp->{mirror};
}
if ($mirror eq 'yes' or $mirror eq 'x') {
if ($tmp->{angle} == 90 or $tmp->{angle} == 270){
$tmp->{angle} += 180;
}
}
elsif($mirror eq 'y'){
if ($tmp->{angle} == 0 or $tmp->{angle} == 180){
$tmp->{angle} += 180;
}
}
$tmp->{angle} = $tmp->{angle} % 360;
$tmp->{mirror} = (!$mirror or $mirror eq 'no')? 'no' : 'yes';
return ($tmp);
}
sub GET_FLAG_STACK{
my ($stk,$stk_flag) = @_;
my $stks = _parse_stack_flag($stk,$stk_flag);
my @retstks = sort {$S->{$b}{stack_level} <=> $S->{$a}{stack_level} ||$S->{$a}{start_num} <=> $S->{$a}{end_num}} keys %$stks;
if (wantarray){
return @retstks;
}
else{
return $retstks[0];
}
}
sub _parse_layer_flag{
my ($stk,$layer_flag,$layer_number) = @_;
$layer_flag =~ s/\s+//g;
$layer_flag = 'S,E' if $layer_flag eq 'SE';
my $stack = $S->{$stk};
my $stk_start_num = $stack->{top_layer_num} || 1;
my $stk_end_num = $stack->{bot_layer_num} || $P->{layer_count};
my @list = split(/\,+/,$layer_flag);
foreach my $item (@list){
my ($from,$to);
if ($item =~ /^([^.]*)\.+([^.]*)$/){
($from,$to) = ($1,$2);
}
else{
$from = $to = $item;
}
$from = 1 unless $from;
$to = $P->{layer_count} unless $to;
foreach my $flag ($from,$to){
if ($flag =~ /^(S|E)([+-]?\d+)?/){
my ($se,$n) = ($1,$2);
$n = 0 unless $n;
if ($se eq 'S'){
$flag = $stk_start_num - $n;
}
else{
$flag = $stk_end_num + $n;
}
}
}
return 1 if ($layer_number >= $from and $layer_number <= $to);
}
return 0;
}
#获取Stack中第几层的层号
sub GET_STK_NUM_LAYER{
my ($stk,$num) = @_;
return unless $S->{$stk};
my $stack = $S->{$stk};
if ($num == 1){
return $stack->{start_num};
}
elsif($num == -1){
return $stack->{end_num};
}
elsif($num > 1){
my $layer_num = int($stack->{start_num}) + $num - 1;
return if $layer_num > $stack->{end_num};
return $layer_num;
}
elsif($num < 0){
my $layer_num = int($stack->{end_num}) - $num + 1;
return if $layer_num < $stack->{start_num};
return $layer_num;
}
}
#获取层位于压合中的第几层
sub GET_LAYER_STK_NUM {
my ($layer_num,$stk) = @_;
return unless $S->{$stk};
my $stack = $S->{$stk};
my $lyr_num = int($layer_num);
return if ($lyr_num < int($stack->{start_num}) or $lyr_num > int($stack->{end_num}));
my $na = $lyr_num - int($stack->{start_num}) + 1;
my $nb = $lyr_num - int($stack->{end_num}) - 1;
if (wantarray){
return ($na,$nb);
}
else{
return $na;
}
}
sub _parse_stack_flag{
my ($stk,$stk_flag) = @_;
my %stks;
my $invert;
$stk_flag = 'S*' unless $stk_flag;
if ($stk_flag =~ /^\!/){
$stk_flag =~ s/^\!//;
$invert = 1;
}
if ($stk_flag eq 'S'){
$stks{$stk} = 1;
}
elsif($stk_flag eq 'SO' or $stk_flag eq 'SE'){
$stks{1 . '-' . $P->{layer_count}} = 1;
}
elsif($stk_flag eq 'S-'){
foreach my $s (@{$S->{$stk}{all_sub_stacks}}){
$stks{$s} = 1;
}
}
elsif($stk_flag eq 'S+'){
foreach my $s (@{$S->{$stk}{all_parent_stacks}}){
$stks{$s} = 1;
}
}
elsif($stk_flag eq 'S-1'){
foreach my $s (@{$S->{$stk}{sub_stacks}}){
$stks{$s} = 1;
}
}
elsif($stk_flag eq 'S+1'){
if ($S->{$stk}{parent_stack}){
$stks{$S->{$stk}{parent_stack}} = 1;
}
}
elsif($stk_flag eq 'S-T'){
if (@{$S->{$stk}{sub_stacks}}){
$stks{$S->{$stk}{sub_stacks}[0]} = 1;
}
}
elsif($stk_flag eq 'S-B'){
if (@{$S->{$stk}{sub_stacks}}){
$stks{$S->{$stk}{sub_stacks}[-1]} = 1;
}
}
elsif($stk_flag eq 'S*'){
foreach my $s (keys %$S){
$stks{$s} = 1;
}
}
elsif($stk_flag =~ /^S(\d+\-\d+)$/){
$stks{$1} = 1;
}
if ($invert){
my %tmp;
foreach my $s (keys %$S){
$tmp{$s} = 1 unless $stks{$s};
}
return \%tmp;
}
else{
return \%stks;
}
}
sub CREATE_LAYER_OVERLAY{
my %par = @_; #(layer=>'',draw_layer=>,invert=>)
my $LAYER = $par{layer};
my $LAYER_STACK = $par{layer_stack};
my $LAYER_NUM = $par{layer_num};
my $LAYER_SIDE = $par{layer_side};
my $DRAW_LAYER = $par{draw_layer};
$DRAW_LAYER= $par{layer} unless $DRAW_LAYER;
#$GEN->openStep(job=>$Job,name=>$Step);
$GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>[$DRAW_LAYER],clear_before=>'yes');
$GEN->COM('sel_all_feat');
$GEN->selDelete();
my @feats = MAP_TO_LAYER_FEATS(%par);
#$GEN->PAUSE("feats === \n ".dump(\@feats));
ADD_FEATS_ON_LAYER($DRAW_LAYER,\@feats,invert=>$par{invert});
}
sub ADD_FEATS_ON_LAYER{
my ($DRAW_LAYER,$FEATS,%par) = @_;
#$GEN->openStep(job=>$Job,name=>$Step);
$GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>[$DRAW_LAYER],clear_before=>'yes');
$GEN->selDelete() if $GEN->getSelectCount();
my $polarity_invert = {'positive'=>'negative','negative'=>'positive'};
foreach my $feat (sort{$b->{priority} <=> $a->{priority} || $a->{num} <=> $b->{num}} @$FEATS){
my %tmp = %$feat;
my $type = delete $tmp{feat_type};
delete $tmp{priority}; delete $tmp{num};
$tmp{polarity} = 'positive' unless $tmp{polarity};
if ($par{invert}){
$tmp{polarity} = $polarity_invert->{$tmp{polarity}};
}
if ($type eq 'pad'){
$GEN->addPad(%tmp);
}
elsif($type eq 'text'){
$GEN->addText(%tmp);
}
elsif($type eq 'line'){
$GEN->addLine(%tmp)
}
elsif($type eq 'rect'){
$GEN->addRectangle(%tmp);
}
elsif($type eq 'poly'){
$GEN->addPolygon(%tmp);
}
}
$GEN->clearLayers();
$GEN->affectedLayer(mode=>'all',affected=>'no');
}
sub PANEL_MAP_TO_DATA{
my %par = @_;
$par{units} = 'inch' if(!defined($par{units}));
my $MapData;
foreach my $layer (@{$par{layers}}){
next unless ($GEN->isLayerExists(job=>$par{job},layer=>$layer));
my @feats = $GEN->getFeatures(job=>$par{job},step=>$par{step},layer=>$layer,units=>$par{units});
foreach my $item (@feats){
next if $item->{type} ne 'pad';
foreach my $attr (@{$item->{attributes}}){
next if($attr !~ /^tl_string\=(.*)/);
$attr = $1;
next if($attr !~ /^S/);
my @attrs = split(':',$attr);
my $stack = shift @attrs;
$stack =~ s/^S//;
my $name = shift @attrs;
my %tags;
foreach my $tag (@attrs){
if ($tag =~ /^(.*)\=(.*)$/){
$tags{$1} = $2;
}
else{
$tags{$tag} = 1;
}
}
push @{$MapData->{$name}{$stack}},{
attributes => [{attribute=>'tl_string',text=>$attr}],
x => $item->{x},
y => $item->{y},
symbol => $item->{symbol},
angle => $item->{angle},
mirror => $item->{mirror},
stack => $stack,
name => $name,
tag => \%tags
}
}
}
}
return $MapData;
}
sub mm2mil{
my $mm = shift;
return $mm*100/2.54;
}
sub mm2inch{
my $mm = shift;
return $mm*100/2.54/1000;
}
sub mil2inch{
my $mil = shift;
return $mil/1000;
}
sub inch2mil{
my $mil = shift;
return $mil*1000;
}
sub inch2mm{
my $inch = shift;
return 25.4*$inch;
}
sub MAX{
my @sizes = @_;
my $size;
foreach my $s (@sizes){
$size = $s if (!defined $size or $size < $s);
}
return $size;
}
sub MIN{
my @sizes = @_;
my $size;
foreach my $s (@sizes){
$size = $s if (!defined $size or $size > $s);
}
return $size;
}
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