=head
NAME:
DESCRIPTION: Signal线路掏铜
PARAMETER:
[
{
name : 'step_filter',
type : 'LineEdit',
title : 'step过滤',
pack : {row:0,column:1},
property:{tool_tip:'选择step时候的过滤器'},
},
{
name : 'opt_item',
title : '优化类型',
type : 'ComboBox',
property : {
size_policy:'Expanding,Fixed',
item_list:[
{name:'inner',text:'内层'},
{name:'outer',text:'外层'},
]
},
},
{
name : 'drl_layer',
type : 'LineEdit',
title : '钻孔层',
pack : {row:0,column:1},
property:{tool_tip:'钻孔层'},
},
{
name : 'outline_layer',
type : 'LineEdit',
title : '外形层',
pack : {row:0,column:1},
property:{tool_tip:'外形层'},
},
{
name : 'ignore_attributes',
type : 'LineEdit',
title : '忽略的铜皮属性',
pack : {row:0,column:1},
property:{tool_tip:'忽略的铜皮属性'},
},
{
name : 'fill_data',
type : 'LineEdit',
title : '去铜丝参数',
pack : {row:0,column:1},
property:{tool_tip:'去铜丝参数'},
},
{
name : 'shave_cu_rule',
title : '削铜参数规则',
type : 'CodeEdit',
property : {min_row_count: 5, tool_tip : ''},
},
{
name : 'bak_layer_suf',
type : 'LineEdit',
title : '备份层后缀',
pack : {row:0,column:1},
property:{tool_tip:'去铜丝参数'},
}
]
VERSION_HISTORY:
V1.00 2020-10-30 Super
1.新版
V1.01 2020-11-5 Super
1.分内外层优化
HELP:
功能简介
DFM优化
参数配置
● 无
注意事项
● 无
=cut
use strict;
use utf8;
use Data::Dump 'dump';
my ($Job,$Step)=($JOB,undef);
my $Report = 'done';
my @work_layers;
$PAR->{fill_data} = $PAR->{fill_data} ? $PAR->{fill_data} : 1;
$PAR->{bak_layer_suf} = $PAR->{bak_layer_suf} ? $PAR->{bak_layer_suf} : '++--bak++';
try {
unless($PAR->{drl_layer}){
$GUI->msgbox(-icon=>'error',-text=>"请先设置钻孔层参数!");
return 'Error';
}
unless($PAR->{outline_layer}){
$GUI->msgbox(-icon=>'error',-text=>"请先设置外形层参数!");
return 'Error';
}
unless($PAR->{opt_item}){
$GUI->msgbox(-icon=>'error',-text=>"请先设置优化类型!");
return 'Error';
}
###检查Genesis料号是否存在并打开
show_loading("检查${Job}是否存在..",0,position=>'n');
if (! $GEN->isJobExists(job=>$Job) ){
$GUI->msgbox(-icon=>'error',-text=>"料号 $Job 在Genesis中不存在, 请检查!");
return 'Error';
}
update_loading("正在打开料号 ${Job} ...",0,position=>'n');
$GEN->openJob(job=>$Job) unless ($GEN->isJobOpen(job=>$Job));
my %matrix=$GEN->getMatrix(job=>$Job,type=>'hash');
my @steps = $GEN->getStepList(job=>$Job);
if ( @steps == 0 ) {
$GUI->msgbox(-icon=>'error',-text=>'在料号中没有Step存在,你将退出!');
return 'Error';
}
elsif (@steps != 1){
my $srep_filter = $PAR->{step_filter} ? $PAR->{step_filter} : '.*';
my @tmp_steps = grep(/$srep_filter/,@steps);
if ( @tmp_steps == 0 ) {
$GUI->msgbox(-icon=>'error',-text=>'在料号中没有过滤器中的step存在,你将退出!');
return 'Error';
}
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("过滤层别...",0,position=>'n');
@work_layers = get_work_layer();
return 'Cancel' if grep /^Cancel$/,@work_layers;
###打开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=>'inch');
$GEN->zoomHome();
update_loading("确认削铜参数...",0,position=>'n');
my $file = $GEN->getJobPath(job=>$Job).'/user/'.'shave_cu_info';
my (%rows,$n);
foreach my $layer (@work_layers){
$n++;
$rows{$layer}{sequence} = $n;
$rows{$layer}{layer} = $layer;
$rows{$layer}{cu} = '';
$rows{$layer}{pad_cu} = 0;
$rows{$layer}{line_cu} = 0;
$rows{$layer}{smd_cu} = 0;
$rows{$layer}{bga_cu} = 0;
$rows{$layer}{np_cu} = 0;
$rows{$layer}{drl_cu} = 0;
$rows{$layer}{cu_cu} = 0;
$rows{$layer}{outline_cu} = 0;
}
my $ShowForm = $GUI->show_tableform (
-title=>'请确认参数',
-defaultsize=>[900,500],
-rows => \%rows,
-showcheck => 1,-gen => $GEN,
-buttons=>[
{
response=>'help',
stock=>'载入上次填入值',
command=>sub{
my %par = @_;
$par{formpanel}->load_data(do($file)) if -f $file;
}
},
{response=>'ok',stock=>'gtk-ok'},
{response=>'cancel',stock=>'gtk-cancel'},
],
-columns => [
{
column_name=>'layer',
label=>'层名称',
width=>70,
type=>'label',
},
{
column_name=>'cu',
label=>'铜箔厚度',
type=>'enum',
width=>70,
must_field=>1,
property=>{
tl_field=>[name=>'scalar',display_name=>'text'],
tl_value_field=>'name',
tl_data=>[
{name=>'1/4',display_name=>'1/4oz'},
{name=>'1/3',display_name=>'1/3oz'},
{name=>'1/2',display_name=>'1/2oz'},
{name=>'1',display_name=>'1oz'},
{name=>'1.5',display_name=>'1.5oz'},
{name=>'2',display_name=>'2oz'},
]
},
validate_func=>sub{
my %par = @_;
my $cu = $par{formpanel}->get_value($par{row},'cu');
my ($pad_cu,$line_cu,$smd_cu,$bga_cu,$drl_cu,$np_cu,$cu_cu,$outline_cu);
unless($PAR->{shave_cu_rule}){
($pad_cu,$line_cu,$smd_cu,$bga_cu,$drl_cu,$np_cu,$cu_cu,$outline_cu) = (0,0,0,0,0,0,0,0);
}else{
($pad_cu,$line_cu,$smd_cu,$bga_cu,$drl_cu,$np_cu,$cu_cu,$outline_cu) = eval($PAR->{shave_cu_rule})->($cu);
}
$par{formpanel}->set_value($par{row},'pad_cu',$pad_cu) if ( $par{mode} eq 'keyin' );
$par{formpanel}->set_value($par{row},'line_cu',$line_cu) if ( $par{mode} eq 'keyin' );
$par{formpanel}->set_value($par{row},'smd_cu',$smd_cu) if ( $par{mode} eq 'keyin' );
$par{formpanel}->set_value($par{row},'bga_cu',$bga_cu) if ( $par{mode} eq 'keyin' );
$par{formpanel}->set_value($par{row},'drl_cu',$drl_cu) if ( $par{mode} eq 'keyin' );
$par{formpanel}->set_value($par{row},'np_cu',$np_cu) if ( $par{mode} eq 'keyin' );
$par{formpanel}->set_value($par{row},'cu_cu',$cu_cu) if ( $par{mode} eq 'keyin' );
$par{formpanel}->set_value($par{row},'outline_cu',$outline_cu) if ( $par{mode} eq 'keyin' );
return {};
}
},
{
column_name=>'pad_cu',
label=>'PAD到铜',
width=>80,
type=>'number',
units=>'mil',
},
{
column_name=>'line_cu',
label=>'线到铜',
width=>80,
type=>'number',
units=>'mil',
},
{
column_name=>'smd_cu',
label=>'SMD到铜',
width=>80,
type=>'number',
units=>'mil',
validate_func=>sub{
my %par = @_;
my $layer = $par{formpanel}->get_value($par{row},'layer');
if($matrix{$layer}{tl_type} eq 'inner'){
$par{formpanel}->set_value($par{row},'smd_cu',0)unless( $par{mode} eq 'save' );
$par{formpanel}->get_widget($par{row},'smd_cu')->set_sensitive(0);
}
return {};
}
},
{
column_name=>'bga_cu',
label=>'BGA到铜',
width=>80,
type=>'number',
units=>'mil',
validate_func=>sub{
my %par = @_;
my $layer = $par{formpanel}->get_value($par{row},'layer');
if($matrix{$layer}{tl_type} eq 'inner'){
$par{formpanel}->set_value($par{row},'bga_cu',0)unless( $par{mode} eq 'save' );
$par{formpanel}->get_widget($par{row},'bga_cu')->set_sensitive(0);
}
return {};
}
},
{
column_name=>'drl_cu',
label=>'孔到铜',
width=>80,
type=>'number',
units=>'mil',
validate_func=>sub{
my %par = @_;
my $layer = $par{formpanel}->get_value($par{row},'layer');
if($matrix{$layer}{tl_type} eq 'outer'){
$par{formpanel}->set_value($par{row},'drl_cu',0)unless( $par{mode} eq 'save' );
$par{formpanel}->get_widget($par{row},'drl_cu')->set_sensitive(0);
}
return {};
}
},
{
column_name=>'np_cu',
label=>'NP孔到铜',
width=>80,
type=>'number',
units=>'mil',
},
{
column_name=>'cu_cu',
label=>'铜到铜',
width=>80,
type=>'number',
units=>'mil',
},
{
column_name=>'outline_cu',
label=>'外形到铜',
width=>90,
type=>'number',
units=>'mil',
},
]
);
return 'Cancel' unless $ShowForm;
open(my $fh,'>',$file); print $fh dump($ShowForm); close $fh;
$GEN->COM("disp_off");
foreach my $layer (@work_layers){
my @del_layers;
$GEN->affectedLayer(affected=>'yes',layer=>$layer,clear_before=>'yes');
$GEN->selectByFilter(polarity=>'negative',profile=>'all');
if ( $GEN->getSelectCount() > 0 ){
$GEN->COM('sel_clear_feat');
$GUI->msgbox(-icon=>'error',-text=>$layer.'层资料中有负片,请先处理好!');
return 'Error';
}
my $bak_layer = $layer.($PAR->{bak_layer_suf});
#备份
$GEN->createLayer(job=>$Job,layer=>$bak_layer,context=>'misc',type=>'document',delete_exists=>'yes');
$GEN->selCopyOther(target_layer=>$bak_layer,invert=>'no');
#铜皮层
my $cu_tmp_layer = $layer.'+-+tmp+cu++';
$GEN->createLayer(job=>$Job,layer=>$cu_tmp_layer,context=>'misc',type=>'document',delete_exists=>'yes');
$GEN->selectByFilter(feat_types=>'surface',polarity=>'positive',profile=>'all');
if(defined($PAR->{ignore_attributes})){
$GEN->selectByFilter(attribute=>[{attribute=>'tl_string',text=>$PAR->{ignore_attributes}}],operation=>'unselect');
}
if ( $GEN->getSelectCount() > 0 ){
$GEN->selMoveOther(target_layer=>$cu_tmp_layer,invert=>'no',dx=>0,dy=>0,size=>0);
push @del_layers,$cu_tmp_layer;
}else{
next;
}
#SMD层
my $smd_tmp_layer = $layer.'+-+tmp+smd++';
if($ShowForm->{$layer}{smd_cu} > 0){
$GEN->createLayer(job=>$Job,layer=>$smd_tmp_layer,context=>'misc',type=>'document',delete_exists=>'yes');
$GEN->selectByFilter(feat_types=>'pad',attribute=>[{attribute=>'.smd'}],polarity=>'positive',profile=>'all');
$GEN->selectByFilter(attribute=>[{attribute=>'.bga'}],operation=>'unselect');
$GEN->selMoveOther(target_layer=>$smd_tmp_layer,invert=>'no',dx=>0,dy=>0,size=>0) if ( $GEN->getSelectCount() > 0 );
push @del_layers,$smd_tmp_layer;
}
#BGA层
my $bga_tmp_layer = $layer.'+-+tmp+bga++';
if($ShowForm->{$layer}{bga_cu} > 0){
$GEN->createLayer(job=>$Job,layer=>$bga_tmp_layer,context=>'misc',type=>'document',delete_exists=>'yes');
$GEN->selectByFilter(feat_types=>'pad',attribute=>[{attribute=>'.bga'}],polarity=>'positive',profile=>'all');
$GEN->selMoveOther(target_layer=>$bga_tmp_layer,invert=>'no',dx=>0,dy=>0,size=>0) if ( $GEN->getSelectCount() > 0 );
push @del_layers,$bga_tmp_layer;
}
#PAD层
my $pad_tmp_layer = $layer.'+-+tmp+pad++';
if($ShowForm->{$layer}{pad_cu} > 0){
$GEN->createLayer(job=>$Job,layer=>$pad_tmp_layer,context=>'misc',type=>'document',delete_exists=>'yes');
$GEN->selectByFilter(feat_types=>'pad',polarity=>'positive',profile=>'all');
$GEN->selMoveOther(target_layer=>$pad_tmp_layer,invert=>'no',dx=>0,dy=>0,size=>0) if ( $GEN->getSelectCount() > 0 );
push @del_layers,$pad_tmp_layer;
}
#line层
my $line_tmp_layer = $layer.'+-+tmp+line++';
if($ShowForm->{$layer}{line_cu} > 0){
$GEN->createLayer(job=>$Job,layer=>$line_tmp_layer,context=>'misc',type=>'document',delete_exists=>'yes');
$GEN->selectByFilter(feat_types=>'line\;arc',polarity=>'positive',profile=>'all');
$GEN->selMoveOther(target_layer=>$line_tmp_layer,invert=>'no',dx=>0,dy=>0,size=>0) if ( $GEN->getSelectCount() > 0 );
push @del_layers,$line_tmp_layer;
}
#掏铜
my %feat_hist = $GEN->getLayerFeatHist(job=>$Job,step=>$Step,layer=>$cu_tmp_layer);
my $tmp_layer = 'tl++tmp+cu+++';
$GEN->createLayer(job=>$Job,layer=>$tmp_layer,context=>'misc',type=>'document',delete_exists=>'yes');
for(my $index = 1;$index <= $feat_hist{total};$index++){
update_loading('一共'.($feat_hist{total}).'铜皮'.' '.'第'.$index.'块优化中...',0,position=>'n');
$GEN->affectedLayer(affected=>'yes',layer=>$cu_tmp_layer,clear_before=>'yes');
$GEN->COM('sel_layer_feat',operation=>'select',layer=>$cu_tmp_layer,index=>$index);
$GEN->selMoveOther(target_layer=>$tmp_layer,invert=>'no',dx=>0,dy=>0,size=>0);
if($ShowForm->{$layer}{smd_cu} > 0){
$GEN->affectedLayer(affected=>'yes',layer=>$smd_tmp_layer,clear_before=>'yes');
$GEN->selRefFeat(layers=>$tmp_layer,use=>'filter',mode=>'disjoint');
$GEN->selCopyOther(target_layer=>$tmp_layer,invert=>'yes',size=>2*$ShowForm->{$layer}{smd_cu}) if ( $GEN->getSelectCount() > 0 );
}
if($ShowForm->{$layer}{bga_cu} > 0){
$GEN->affectedLayer(affected=>'yes',layer=>$bga_tmp_layer,clear_before=>'yes');
$GEN->selRefFeat(layers=>$tmp_layer,use=>'filter',mode=>'disjoint');
$GEN->selCopyOther(target_layer=>$tmp_layer,invert=>'yes',size=>2*$ShowForm->{$layer}{bga_cu}) if ( $GEN->getSelectCount() > 0 );
}
if($ShowForm->{$layer}{pad_cu} > 0){
$GEN->affectedLayer(affected=>'yes',layer=>$pad_tmp_layer,clear_before=>'yes');
$GEN->selRefFeat(layers=>$tmp_layer,use=>'filter',mode=>'disjoint');
$GEN->selCopyOther(target_layer=>$tmp_layer,invert=>'yes',size=>2*$ShowForm->{$layer}{pad_cu}) if ( $GEN->getSelectCount() > 0 );
}
if($ShowForm->{$layer}{line_cu} > 0){
$GEN->affectedLayer(affected=>'yes',layer=>$line_tmp_layer,clear_before=>'yes');
$GEN->selRefFeat(layers=>$tmp_layer,use=>'filter',mode=>'disjoint');
$GEN->selCopyOther(target_layer=>$tmp_layer,invert=>'yes',size=>2*$ShowForm->{$layer}{line_cu}) if ( $GEN->getSelectCount() > 0 );
}
#NP孔到铜
$GEN->affectedLayer(affected=>'yes',layer=>$PAR->{drl_layer},clear_before=>'yes');
$GEN->selectByFilter(attribute=>[{attribute=>'.drill',option=>'non_plated'}]);
$GEN->selCopyOther(target_layer=>$tmp_layer,invert=>'yes',size=>2*$ShowForm->{$layer}{np_cu}) if ( $GEN->getSelectCount() > 0 );
if($ShowForm->{$layer}{drl_cu} > 0){
$GEN->selRefFeat(layers=>$tmp_layer,use=>'filter',mode=>'disjoint');
$GEN->selCopyOther(target_layer=>$tmp_layer,invert=>'yes',size=>2*$ShowForm->{$layer}{drl_cu}) if ( $GEN->getSelectCount() > 0 );
}
#外形到铜
$GEN->affectedLayer(affected=>'yes',layer=>$PAR->{outline_cu},clear_before=>'yes');
$GEN->selCopyOther(target_layer=>$tmp_layer,invert=>'yes',size=>2*$ShowForm->{$layer}{outline_cu}) if ( $GEN->getSelectCount() > 0 );
#铜到铜
$GEN->affectedLayer(affected=>'yes',layer=>$cu_tmp_layer,clear_before=>'yes');
$GEN->selRefFeat(layers=>$tmp_layer,use=>'filter',mode=>'disjoint');
$GEN->selCopyOther(target_layer=>$tmp_layer,invert=>'yes',size=>$ShowForm->{$layer}{cu_cu}) if ( $GEN->getSelectCount() > 0 );
#转铜,除细丝
$GEN->affectedLayer(affected=>'yes',layer=>$tmp_layer,clear_before=>'yes');
$GEN->selContourize();
if($PAR->{fill_data}){
$GEN->selFill(solid_type=>'fill',min_brush=>$PAR->{fill_data});
$GEN->selContourize();
}
$GEN->selMoveOther(target_layer=>$layer,invert=>'no',dx=>0,dy=>0,size=>0);
$GEN->deleteLayer(job=>$Job,layer=>$tmp_layer);
}
#与铜皮相连的PAD处理
#补铜桥部分
#物件还原
foreach my $tmp (@del_layers){
if($GEN->isLayerExists(job=>$Job,layer=>$tmp) and ! $GEN->isLayerEmpty(job=>$Job,step=>$Step,layer=>$tmp)){
$GEN->affectedLayer(affected=>'yes',layer=>$tmp,clear_before=>'yes');
$GEN->selMoveOther(target_layer=>$layer,invert=>'no',dx=>0,dy=>0,size=>0);
}
$GEN->deleteLayer(job=>$Job,layer=>$tmp);
}
}
###output and return status, if genesis error, it will output genesis error command
unless ($GEN->{STATUS}){
return $Report;
}
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->clearLayers();
$GEN->affectedLayer( mode=>'all',affected=>'no' );
$GEN->COM("disp_on");
};
sub isChecklistExist{
my %par = @_ ;
my @chklists = $GEN->getChecklist(job=>$par{job},step=>$par{step});
if(grep /^$par{checkklist}$/,@chklists){
return 1;
}
else{
return 0;
}
}
=head
选择线路层
=cut
sub get_work_layer{
# 获取工作层
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}{layer_type}) and $matrix{$layer}{layer_type} eq 'signal' and $matrix{$layer}{tl_type} eq $PAR->{opt_item}){
push @work_layers,$layer;
}
}
}
my %tmp_matrix;
foreach my $layer (@work_layers) {
$tmp_matrix{$layer} = $matrix{$layer};
}
if (@work_layers > 1) {
@work_layers = $GUI->select_layer(
-title=>'请选择工作层别',
-layermatrix=>\%tmp_matrix,
-selectmode => 'multiple');#single
return 'Cancel' unless(@work_layers);
}
else {
@work_layers = @work_layers;
}
return @work_layers;
}
#掏铜参数
# sub{
# my $cu = shift;
# my $data;
# @{$data->{0.5}}=(1,2,3,4,5,1,6);
# @{$data->{1}}=(2,3,4,5,6,2,7);
# if(defined($data->{$cu})){
# return @{$data->{$cu}};
# }else{
# return (0,0,0,0,0,0);
# }
# }