=head NAME: TL_PUB_update_sm_defined_opening DESCRIPTION: Update soldermask opening which covered by copper or heavy line PARAMETER: [ { name : 'step_filter', type : 'LineEdit', title : 'step过滤', pack : {row:0,column:1}, property:{tool_tip:'选择step时候的过滤器'}, }, { name : 'drill_layer', type : 'LineEdit', title : '外层机械钻孔层', pack : {row:0,column:1}, property:{tool_tip:''}, }, { name : 'smd', title : '处理SMD盘', type : 'RadioBox', property : { size_policy:'Expanding,Fixed', item_list:[ {name:'Yes',text:'Yes'}, {name:'No',text:'No'}, ], tool_tip:'是否处理SMD盘' }, pack : {row:1,column:1}, value : 'Yes' }, { name : 'bga', title : '处理BGA盘', type : 'RadioBox', property : { size_policy:'Expanding,Fixed', item_list:[ {name:'Yes',text:'Yes'}, {name:'No',text:'No'}, ], tool_tip:'是否处理BGA盘' }, pack : {row:1,column:1}, value : 'Yes' }, { name : 'pth', title : '处理非Via孔的pth孔盘', type : 'RadioBox', property : { size_policy:'Expanding,Fixed', item_list:[ {name:'Yes',text:'Yes'}, {name:'No',text:'No'}, ], tool_tip:'是否处理PTH所对应的盘' }, pack : {row:1,column:1}, value : 'No' }, { name : 'via', title : '处理Via孔盘', type : 'RadioBox', property : { size_policy:'Expanding,Fixed', item_list:[ {name:'Yes',text:'Yes'}, {name:'No',text:'No'}, ], tool_tip:'是否处理Via孔所对应的盘' }, pack : {row:1,column:1}, value : 'No' }, { name : 'pad', title : '处理其它盘', type : 'RadioBox', property : { size_policy:'Expanding,Fixed', item_list:[ {name:'Yes',text:'Yes'}, {name:'No',text:'No'}, ], tool_tip:'是否处理除SMD,BGA,和PTH孔对应盘以外的所有pad' }, pack : {row:1,column:1}, value : 'No' }, { name : 'include_pad', title : '附近无开窗pad当大铜面', type : 'RadioBox', property : { size_policy:'Expanding,Fixed', item_list:[ {name:'Yes',text:'Yes'}, {name:'No',text:'No'}, ], tool_tip:'附近无开窗pad当大铜面' }, pack : {row:1,column:1}, value : 'No' }, { name : 'ignore_bgasmd', title : '允许smdbga上的盘制作', type : 'RadioBox', property : { size_policy:'Expanding,Fixed', item_list:[ {name:'Yes',text:'Yes'}, {name:'No',text:'No'}, ], tool_tip:'除SMD,BGA外的盘在做完bga和smd后任运行制作' }, pack : {row:1,column:1}, value : 'No' }, { name : 'make_sm_less_pad', title : '自动优化防焊ON PAD', type : 'RadioBox', property : { size_policy:'Expanding,Fixed', item_list:[ {name:'Yes',text:'Yes'}, {name:'No',text:'No'}, ], tool_tip:'默认参数为铜面上单边开窗(mil)大小' }, pack : {row:1,column:1}, value : 'No' }, { name : 'delete_samll_area', title : '允许删除小面积开窗', type : 'RadioBox', property : { size_policy:'Expanding,Fixed', item_list:[ {name:'Yes',text:'Yes'}, {name:'No',text:'No'}, ], tool_tip:'允许删除小面积开窗' }, pack : {row:1,column:1}, value : 'No' }, { name : 'small_area_open', type : 'LineEdit', title : '认为是小面积开窗的面积', pack : {row:0,column:1}, units:'mil', property:{tool_tip:'认为是小面积开窗的面积大小,默认0.01'}, value : 10 }, { name : 'smd_line', type : 'LineEdit', title : 'SMD认为是铜面的最小线', pack : {row:0,column:1}, units:'mil', property:{tool_tip:'SMD认为是铜面的最小线'}, value : 10 }, { name : 'bga_line', type : 'LineEdit', title : 'BGA认为是铜面的最小线', pack : {row:0,column:1}, units:'mil', property:{tool_tip:'BGA认为是铜面的最小线'}, value : 5 }, { name : 'coverage', type : 'LineEdit', title : '最小Coverage(去除Coverage Tol)', pack : {row:0,column:1}, units:'mil', property:{tool_tip:'最小Coverage'}, value : 2 }, { name : 'coverage_tol', type : 'LineEdit', title : 'Coverage Tol', pack : {row:0,column:1}, units:'mil', property:{tool_tip:'主要用于铜面比线路pad稍微大一点时,忽略宽度的值,会纳入最小Coverage计算'}, value : 2 }, { name : 'bga_copperopen', type : 'LineEdit', title : 'BGA铜面上单边开窗', pack : {row:0,column:1}, units:'mil', property:{tool_tip:'BGA铜面上单边开窗'}, value : 0.5 }, { name : 'spec_bga_copperopen', type : 'LineEdit', title : '特殊BGA铜面上单边开窗', pack : {row:0,column:1}, units:'mil', property:{tool_tip:'特殊BGA铜面上单边开窗'}, value : 0.5 }, { name : 'smd_copperopen', type : 'LineEdit', title : 'SMD铜面上单边开窗', pack : {row:0,column:1}, units:'mil', property:{tool_tip:'SMD铜面上单边开窗'}, value : 0.5 }, { name : 'pth_copperopen', type : 'LineEdit', title : 'PTH孔盘铜面上单边开窗', pack : {row:0,column:1}, units:'mil', property:{tool_tip:'PTH孔盘铜面上单边开窗'}, value : 0.5 }, { name : 'via_copperopen', type : 'LineEdit', title : 'VIA孔盘铜面上单边开窗', pack : {row:0,column:1}, units:'mil', property:{tool_tip:'VIA孔盘铜面上单边开窗'}, value : 0.5 }, { name : 'pad_copperopen', type : 'LineEdit', title : '其他PAD铜面上单边开窗', pack : {row:0,column:1}, units:'mil', property:{tool_tip:'其他PAD铜面上单边开窗'}, value : 0.5 }, { name : 'opt_open', type : 'LineEdit', title : '正常最优单边开窗', pack : {row:0,column:1}, units:'mil', property:{tool_tip:'正常最优单边开窗'}, value : 1.5 }, { name : 'update_max_opening', type : 'LineEdit', title : '允许优化的单边最大开窗', pack : {row:0,column:1}, units:'mil', property:{tool_tip:'pad单边放大这个值后,开窗在里面的才优化'}, value : 3 }, { name : 'keep_gasket', type : 'RadioBox', title : '是否保证Gasket', property : { tool_tip:'是否保证开窗下面的垫圈', size_policy:'Expanding,Fixed', item_list:[ {name:'Yes',text:'Yes'}, {name:'No',text:'No'} ] }, pack : {row:0,column:2}, value:'No' }, { name : 'gasket_size', type : 'LineEdit', title : '开窗gasket最小', pack : {row:0,column:1}, units:'mil', property:{tool_tip:'为了保证完全落于铜面的开窗大小,对于靠在边上的下面加垫圈'}, value:1.5 }, { name : 'bga_attr', type : 'LineEdit', title : '定义为BGA Pad的属性名字', pack : {row:0,column:1}, units:'mil', property:{tool_tip:'定义BGA的属性名字'}, value:'.bga' }, { name : 'smd_attr', type : 'LineEdit', title : '定义为SMD Pad的属性名字', pack : {row:0,column:1}, units:'mil', property:{tool_tip:'定义SMD的属性名字'}, value:'.smd' }, { name : 'ignore_attr', type : 'LineEdit', title : 'SM忽略处理开窗的属性名字', pack : {row:0,column:1}, units:'mil', property:{tool_tip:'定义需要被忽略处理的开窗所加属性名字'}, value:'.ignore_action' }, { name : 'include_teardrop', type : 'RadioBox', title : '大铜面包含.tear_drop', property : { tool_tip:'碰到大铜面或者粗线的.tear_drop是否也当成大铜面处理', size_policy:'Expanding,Fixed', item_list:[ {name:'Yes',text:'Yes'}, {name:'No',text:'No'}, {name:'Manual',text:'Manual'}, ] }, pack : {row:0,column:2}, value:'No' }, { name : 'laser_pad_attr', type : 'LineEdit', title : '镭射Pad属性', pack : {row:0,column:1}, units:'mil', property:{tool_tip:'定义Laser Pad的属性名字'}, value:'' }, { name : 'ignore_attr_comp', type : 'RadioBox', title : '补偿有属性的忽略开窗', property : { tool_tip:'对定义属性的开窗,是否进行铜面补偿', size_policy:'Expanding,Fixed', item_list:[ {name:'Yes',text:'Yes'}, {name:'No',text:'No'} ] }, pack : {row:0,column:2}, value:'No' }, { name : 'specifical_opening_suffix', type : 'LineEdit', title : '特殊情况报警层后缀', pack : {row:0,column:1}, units:'mil', property:{tool_tip:'定义特殊的开窗不能处理,报警层后缀名'}, value:'' }, { name : 'backup_suffix', type : 'LineEdit', title : '备份层后缀', pack : {row:0,column:1}, units:'mil', property:{tool_tip:'定义备份层后缀名'}, value:'._tl+++' }, { name : 'is_select_lyr', title : '选择层别', type : 'RadioBox', property : { size_policy:'Expanding,Fixed', item_list:[ {name:'Yes',text:'Yes'}, {name:'No',text:'No'}, ], tool_tip:'未设定,默认为yes' }, pack : {row:1,column:1}, value : 'Yes' }, ] VERSION_HISTORY: V1.00 2011-03-28 Jacket Wu Release first version according to request V1.10 2011-06-01 Jacket Wu 增加了补偿值对忽略的属性,并有参数可以定义 V1.20 2011-06-03 Jacket Wu 修正bug,对于特殊属性补偿,系统运行根据需要做的情况有好几次,目前改为一次 V1.30 2012-01-10 Jacket Wu 最优窗口支持不同pad size有不同的值,可以定义为如下的一个结构或者一个值 [{min=>0,max=>10,cmp=>2.5},{min=>10,max=>10000,cmp=>2},{type=>'others',cmp=>2}] V1.40 2012-01-17 Jacket Wu 调整料号选择,可以支持几个料号名字优先排列 V1.50 2012-01-19 Jacket Wu 添加备份层后缀名参数 V1.51 2012-02-02 Jacket Wu 更改开窗大小的时候pad从大到小改 V1.52 2012-02-16 Jacket Wu 对于需要shave的地方,如果在sm层碰到surface就去掉 V1.60 2013-07-09 Jacket Wu 分开不同类型pad可以设定不同的铜面开窗大小 V1.70 2015-04-16 Jacket Wu 1. 修正整个负数据覆盖pad及部分pad 不应该处理也处理的情况 2. 增加允许对单边开窗用负的数据,就是开窗比pad小 V1.71 2015-04-21 Jacket Wu 1.分开标准pth孔与via孔可以设定不同的铜面开窗大小 2.优化执行效率 V1.72 2015-04-24 Sting Chen 1.优化转换铜面参数 V1.73 2016-11-21 Cody Yu 1.脚本参数转换为c++格式 V1.74 2016-12-09 Cody Yu 1.铜面上的开窗,在参数确认界面上自动缩小补偿值 V1.75 2018-05-02 Shyer Wang 1.去除2018-3-23更改逻辑 2.修复铜面重复pad不做优化的问题 V1.76 2018-05-11 Shyer Wang 1.更改界面默认参数 2.取消pad碰到钻孔不做sm_defined的逻辑 3.增加附近无开窗pad当大铜面参数设置 4.增加允许smdbga上的盘再次制作sm_defined的参数设置 V1.77 2018-05-15 Shyer Wang 1.去除普通pad碰到pth孔 V1.78 2018-05-16 Shyer Wang 1.开窗层过滤掉负性物件制作 2.via负性和sm_defined合并 V1.79 2018-05-17 Shyer Wang 1.增加脚本参数控制是否清除小面积开窗 2.增加脚本参数设置清除小面积开窗的面积 V1.80 2018-05-19 Shyer Wang 1.优化尖角 2.优化负属性物件制作逻辑 V1.81 2018-05-29 Shyer Wang 1.on pad制作增加脚本参数控制 2.修复负片层确实问题 V1.82 2018-06-04 Shyer Wang 1.优化负片逻辑 2.大铜面碰到的pad选择逻辑变更 V1.83 2018-06-04 Shyer Wang 1.优化增加泪滴逻辑 2.增加特殊bga参数‘tl_spec_bga’ V1.84 2018-08-07 Shyer Wang 1.增加coverage 公差,用于支持线与smd等等大情况的 V1.85 2018-08-15 Shyer Wang 1.前台界面增加是否忽略泪滴的脚本参数 V1.86 2018-09-25 Alan 1.修复via盘参数选择no,还处理的bug HELP:

功能简介


分开处理在铜面上的Pad开窗和正常没有铜面开窗



参数配置


● 料号名


设置genesis中料号的名字,${JOB}表示跟TopCAM中的料号名字一样,TL_genesis_work_jobname表示用这个料号属性定义的名字


● step过滤


选择step时候的过滤器


● 外层机械钻孔层


定义外层机械钻孔层得固定名字


● 处理SMD盘


定义缺省的是否处理SMD pad


● 处理BGA盘


定义缺省的是否处理BGA pad


● 处理pth 孔盘


定义缺省的是否处理非via孔的PTH孔所对应的盘


● 处理via 孔盘


定义缺省的是否处理via孔所对应的盘


● 处理其它盘


定义缺省的是否处理除SMD,BGA,PTH和Via孔对应盘以外的所有pad


● SMD认为是铜面的最小线


对于非BGA盘对应的线,需要当作铜面处理的最小线宽。也就是大于等于这个线宽的线并且跟盘相连,将当铜面处理


● BGA认为是铜面的最小线


对于BGA盘对应的线,需要当作铜面处理的最小线宽。也就是大于等于这个线宽的线并且是跟BGA相连,将当铜面处理


● 最小Coverage


定义缺省开窗到线或需要用绿油盖起来的元素的最小安全距离


● 铜面上单边开窗


pad落于大铜面上的开窗的大小要求,指的是单面的


● 正常最优单边开窗


没有落于大铜面的最优开窗大小,指的是单边的


● 允许优化的单边最大开窗


定义允许进行优化操作的最大单边开窗,如果开窗超过这个值,将不进行优化


● 是否保证Gasket


定义对开窗正好在大铜面边上,并且都落于大铜面上,是否要在外层加个垫圈,以防治开窗制作公差引起铜面变小


● 开窗gasket最小


在需要保证gastet的情况下,铜面必须比开窗单边大的尺寸要求


● 定义为BGA Pad的属性名字


BGA pad所加的属性名字


● 定义为SMD Pad的属性名字


SMD pad所加的属性名字


● SM忽略处理开窗的属性名字


定义需要被忽略处理的属性名字,这个属性名字是加在 solder mask层上的


● 大铜面包含.tear_drop


定义碰到大铜面或者粗线的.tear_drop是否也当成大铜面处理


● 镭射Pad属性


定义laser pad属性名字,如果定义了laser pad,系统将把laser pad过滤掉来处理


● 补偿有属性的忽略开窗


对于定义需要被忽略处理的开窗,是否需要做大铜面补偿值


注意事项


● 在solder mask层上面是surface的将不被优化


● 如果一个开窗下面对应有超过并等于2个盘得情况也将不做处理


● 对于开窗形状和pad形状不是相同的情况下也将过滤不处理



=cut use strict; #my ($JOB,$GEN,$GUI,$DB,$JOB_ID,$PAR); #####使用时间控制 #my $year = (localtime())[5] + 1900; #my $mon = (localtime())[4]; #if ( $year > 2012 or ($year == 2012 and $mon > 12) ) { # $GUI->msgbox(-text=>"License is out of date! Please check with TopLinker!"); # return; #} use utf8; use Encode; use Data::Dump qw/dump/; my $Return = 'Done'; my ($Job,$Step) = ($JOB,undef); ###处理step过滤 $PAR->{step_filter} = $PAR->{step_filter} ? $PAR->{step_filter} : '.*'; $PAR->{is_select_lyr} = 'yes' unless $PAR->{is_select_lyr}; my $DrillLayer = $PAR->{drill_layer}; my $MinSMDCopperLine = $PAR->{smd_line}; my $MinBGACopperLine = $PAR->{bga_line}; my $Coverage = $PAR->{coverage}; my $CoverageTol = $PAR->{coverage_tol}; my $BGACopperOpening = $PAR->{bga_copperopen}; my $SpecBGACopperOpening = $PAR->{spec_bga_copperopen}; my $SMDCopperOpening = $PAR->{smd_copperopen}; my $PTHCopperOpening = $PAR->{pth_copperopen}; my $VIACopperOpening = $PAR->{via_copperopen}; my $PADCopperOpening = $PAR->{pad_copperopen}; my $CopperOpening; my $OptOpening = $PAR->{opt_open}; my $UpdateMaxOpening = $PAR->{update_max_opening}; my $GasketSize = $PAR->{gasket_size}; my $DoSMD = $PAR->{smd}; my $DoPTH = $PAR->{pth}; my $DoVIA = $PAR->{via}; my $DoBGA = $PAR->{bga}; my $DoPAD = $PAR->{pad}; my $KeepGasket = $PAR->{keep_gasket}; my $IgnoreAttr = $PAR->{ignore_attr} || ''; my $IncludeTearDrop = $PAR->{include_teardrop}; my $IncludePad = $PAR->{include_pad}|| 'No'; my $InIgnoreSmdBga = $PAR->{ignore_bgasmd}|| 'No'; my $DeleteSamllArea = $PAR->{delete_samll_area}||'No'; my $SmallAreaOpen = $PAR->{small_area_open}||'0.01'; my $AttrHash = {bga=>$PAR->{bga_attr},smd=>$PAR->{smd_attr}}; my $LaserPadAttr = $PAR->{laser_pad_attr} || ''; my $SpecificalWarningSuffix = $PAR->{specifical_opening_suffix} || ''; my $BakSuffix = $PAR->{backup_suffix} || '+++'; $PAR->{is_select_lyr} = 'Yes' unless $PAR->{is_select_lyr}; my %TmpLayer = ( tmp_layer => 'tl_script_tmp_layer', ###临时中间使用的层 big_copper_layer => 'tl_script_tmp_layer1', ###铜面和粗线 pad_touch_copper => 'tl_script_tmp_layer2', ###碰到 big_copper_layer 的所有盘 pad_opening => 'tl_script_tmp_layer3', ###pad_touch_copper 盘所对应的开窗 sm_opening => 'tl_script_tmp_layer31', ###solder mask 层所有东西复制到这里并做contourize org_pad_opening => 'tl_script_tmp_layer4', ###pad_touch_copper 盘所对应的原稿开窗 opt_big_copper => 'tl_script_tmp_layer5', ####优化铜面和粗线,来制作缺口和coverage correct_sm_opening => 'tl_script_tmp_layer6', ####制作准确的开窗 sm_opening_free => 'tl_script_tmp_layer7', ####制作开窗要的负片层 npth_layer=> 'tl_script_tmp_layer8', ####npth drill layer sm_less_pad => 'tl_script_tmp_layer9', ####开窗比盘小 (有一边小就算) pad_on_copper_gasket => 'tl_script_tmp_layer10', ####开窗比盘小 (有一边小就算) remove_specifical_sm => 'tl_script_tmp_layer11', ####特殊开窗不处理 all_pad_with_attr => 'tl_script_tmp_layer12', ####符合条件的所有pad sliver_layer => 'tl_script_tmp_layer13', ####需要优化掉的小细丝层 smd_bga_pad => 'tl_script_tmp_layer15', ####smd bga attribute pad via_drill_layer => 'tl_script_tmp_layer16', ####via drill layer samll_area_layer=>'tl_script_tmp_layer17', #####制作去除小面积开窗层 sm_defined_tmp_layer=>'tl_script_tmp_layer18', #####临时sm defined层 ); try{ ###Check genesis job name exist or not unless ( $Job and $GEN->isJobExists(job=>$Job) ){ $Job = $GUI->select_job( -title=>'请选择料号', -joblist=>[$GEN->getJobList()] ); return 'Cancel' if (! defined $Job or (defined $Job and $Job eq '')); } ###open Job $GEN->openJob(job=>$Job) unless ($GEN->isJobOpen(job=>$Job)); ###check and get work Step name my @steps = $GEN->getStepList(job=>$Job); if ( @steps == 0 ) { $GUI->msgbox(-icon=>'error',-text=>'在料号中没有Step存在,你将退出!'); return 'Cancel'; } elsif (@steps != 1){ my @tmp_steps = grep(/$PAR->{step_filter}/,@steps); if ( @tmp_steps == 0 ) { $GUI->msgbox(-icon=>'warning',-text=>'根据脚本参数过滤出来的step不存在,请检查资料或者脚本参数配置!'); return 'Cancel'; } elsif ( @tmp_steps == 1 ) { $Step = $tmp_steps[0]; } else { $Step = $GUI->select_step(-title=>'请选择工作Step', -steplist=>[@tmp_steps], -selectmode=>'single'); return 'Cancel' unless ($Step); } } else { $Step = $steps[0]; } ###Open step and clear layer $GEN->openStep(job=>$Job,name=>$Step); $GEN->COM("disp_off"); $GEN->clearLayers(); $GEN->affectedLayer(mode=>'all',affected=>'no'); $GEN->units(type=>'inch'); ####选择SM层,并寻找对应的外层 my %matrix=$GEN->getMatrix(job=>$Job,type=>'hash'); #my @smlayer = $GUI->select_layer(-title=>'Please select solder mask layer to opt Defined pad', # -layermatrix=>\%matrix); #return 'Cancel' unless ( @smlayer ); my $layers = select_work_layer(); return $layers if $layers eq 'Cancel'; my @smlayer = @{$layers}; my %smout; foreach my $item ( @smlayer ) { if ( $matrix{$item}{side} eq 'top' ) { foreach my $layer (keys %matrix) { if ( $matrix{$layer}{tl_name} eq 'top' ) { $smout{$item} = $layer; last; } } } elsif ( $matrix{$item}{side} eq 'bottom' ) { foreach my $layer (keys %matrix) { if ( $matrix{$layer}{tl_name} eq 'bottom' ) { $smout{$item} = $layer; last; } } } } #####确认外层名字 my $tmp; my $tmplayerhash; foreach my $item (keys %matrix) { push(@$tmplayerhash,{name=>$item}); } foreach my $item (@smlayer) { push(@$tmp, { name=>$item, label=>$item, type=>'enum', property=>{ tl_field=>[name=>'text'], tl_value_field=>'name', tl_data=>$tmplayerhash }, must_field=>1, value => $smout{$item} || '' } ); } if ( ! $GEN->isLayerExists(job=>$Job,layer=>$DrillLayer) ) { push(@$tmp, { name=>'drill', label=>'Drill Layer', type=>'enum', property=>{ tl_field=>[name=>'text'], tl_value_field=>'name', tl_data=>$tmplayerhash }, must_field=>1, value => $DrillLayer } ); } my %tmp = $GUI->show_form( -title => 'Set Outer Layer of defined SM Layer', -items => $tmp ); return 'Cancel' unless %tmp; if ( $tmp{drill} ) { $DrillLayer = delete $tmp{drill}; } ###获取补偿值 #my $out_comp = $IKM->get_jobinfo(-jobid=>$JOB_ID,-jobcategory=>'work',-jobinfo=>'outer_comp_value'); #my $bga_comp = $out_comp; #if( $out_comp ){ # my $customer_code = $IKM->select_value(-table=>'pdm_job',-field=>'customer_code',-where=>{id=>$JOB_ID}); # if( $customer_code =~ /(1812|1861)/ ){ # $bga_comp += 1; # } # else{ # $bga_comp += 0.5; # } #} #$out_comp = $out_comp/2 - 0.5; #$bga_comp = $bga_comp/2 - 0.5; #####confirm parameter my $info = [ { name=>'smd', label=>'处理SMD盘', type=>'enum', property=>{ tl_field=>[name=>'scalar',display_name=>'text'], tl_value_field=>'name', tl_data=>[ {name=>'Yes',display_name=>'Yes'}, {name=>'No',display_name=>'No'} ] }, must_field=>1, remark=>'是否处理SMD盘', value => $PAR->{smd}, }, { name=>'bga', label=>'处理BGA盘', type=>'enum', property=>{ tl_field=>[name=>'scalar',display_name=>'text'], tl_value_field=>'name', tl_data=>[ {name=>'Yes',display_name=>'Yes'}, {name=>'No',display_name=>'No'} ] }, must_field=>1, remark=>'是否处理BGA盘', value => $PAR->{bga}, }, { name=>'pth', label=>'处理pth 孔盘', type=>'enum', property=>{ tl_field=>[name=>'scalar',display_name=>'text'], tl_value_field=>'name', tl_data=>[ {name=>'Yes',display_name=>'Yes'}, {name=>'No',display_name=>'No'} ] }, must_field=>1, remark=>'是否处理PTH所对应的盘', value => $PAR->{pth}, }, { name=>'via', label=>'处理via 孔盘', type=>'enum', property=>{ tl_field=>[name=>'scalar',display_name=>'text'], tl_value_field=>'name', tl_data=>[ {name=>'Yes',display_name=>'Yes'}, {name=>'No',display_name=>'No'} ] }, must_field=>1, remark=>'是否处理VIA所对应的盘', value => $PAR->{via}, }, { name=>'pad', label=>'处理其它盘', type=>'enum', property=>{ tl_field=>[name=>'scalar',display_name=>'text'], tl_value_field=>'name', tl_data=>[ {name=>'Yes',display_name=>'Yes'}, {name=>'No',display_name=>'No'} ] }, must_field=>1, remark=>'是否处理除SMD,BGA,和PTH孔对应盘以外的所有pad', value => $PAR->{pad}, }, { name=>'smd_line', label=>'SMD认为是铜面的最小线(mil)', type=>'string', must_field=>1, remark=>'', value => $PAR->{smd_line}, }, { name=>'bga_line', label=>'BGA认为是铜面的最小线(mil)', type=>'string', must_field=>1, remark=>'', value => $PAR->{bga_line}, }, { name=>'coverage', label=>'最小Coverage(mil)', type=>'string', must_field=>1, remark=>'需去除Coverage Tol', value => $PAR->{coverage}, }, { name=>'coverage_tol', label=>'Coverage Tol(mil)', type=>'string', must_field=>1, remark=>'主要用于铜面比线路pad稍微大一点时,忽略宽度的值,会纳入最小Coverage计算', value => $PAR->{coverage_tol}, }, { name=>'bga_copperopen', label=>'BGA铜面上单边开窗(mil)', type=>'string', must_field=>1, remark=>'', value => $PAR->{bga_copperopen}, }, { name=>'spec_bga_copperopen', label=>'特殊BGA铜面上单边开窗(mil)', type=>'string', must_field=>1, remark=>'', value => $PAR->{spec_bga_copperopen}, }, { name=>'smd_copperopen', label=>'SMD铜面上单边开窗(mil)', type=>'string', must_field=>1, remark=>'', value => $PAR->{smd_copperopen}, }, { name=>'pth_copperopen', label=>'PTH盘铜面上单边开窗(mil)', type=>'string', must_field=>1, remark=>'', value => $PAR->{pth_copperopen}, }, { name=>'via_copperopen', label=>'VIA盘铜面上单边开窗(mil)', type=>'string', must_field=>1, remark=>'', value => $PAR->{via_copperopen}, }, { name=>'pad_copperopen', label=>'其他盘铜面上单边开窗(mil)', type=>'string', must_field=>1, remark=>'', value => $PAR->{pad_copperopen}, }, { name=>'opt_open', label=>'正常最优单边开窗(mil)', type=>'string', must_field=>1, remark=>'', value => $PAR->{opt_open}, }, { name=>'update_max_opening', label=>'允许优化的单边最大开窗(mil)', type=>'string', must_field=>1, remark=>'pad单边放大这个值后,开窗在里面的才优化', value => $PAR->{update_max_opening}, }, { name=>'include_teardrop', label=>'大铜面包含.tear_drop', type=>'enum', property=>{ tl_field=>[name=>'scalar',display_name=>'text'], tl_value_field=>'name', tl_data=>[ {name=>'Yes',display_name=>'Yes'}, {name=>'No',display_name=>'No'} ] }, must_field=>1, remark=>'碰到大铜面或者粗线的.tear_drop是否也当成大铜面处理', value => $PAR->{include_teardrop}, }, { name=>'keep_gasket', label=>'是否保证Gasket', type=>'enum', property=>{ tl_field=>[name=>'scalar',display_name=>'text'], tl_value_field=>'name', tl_data=>[ {name=>'Yes',display_name=>'Yes'}, {name=>'No',display_name=>'No'} ] }, must_field=>1, remark=>'是否保证开窗下面的垫圈', value => $PAR->{keep_gasket}, }, { name=>'gasket_size', label=>'开窗gasket最小(mil)', type=>'string', must_field=>1, remark=>'为了保证完全落于铜面的开窗大小,对于靠在边上的下面加垫圈', value => $PAR->{gasket_size}, }, ]; my %info = $GUI->show_form( -title=>'请设置缩铜面Pad参数', -items=>$info); return 'Cancel' unless %info; $MinSMDCopperLine = $info{smd_line}; $MinBGACopperLine = $info{bga_line}; $Coverage = $info{coverage}; $CoverageTol = $info{coverage_tol}; $BGACopperOpening = $info{bga_copperopen}; $SMDCopperOpening = $info{smd_copperopen}; $PTHCopperOpening = $info{pth_copperopen}; $VIACopperOpening = $info{via_copperopen}; $PADCopperOpening = $info{pad_copperopen}; $OptOpening = eval($info{opt_open}); $GasketSize = $info{gasket_size}; $DoSMD = $info{smd}; $DoBGA = $info{bga}; $DoPTH = $info{pth}; $DoVIA = $info{via}; $DoPAD = $info{pad}; $IncludeTearDrop = $info{include_teardrop}; $KeepGasket = $info{keep_gasket}; $UpdateMaxOpening = $info{update_max_opening}; %tmp = reverse %tmp; foreach my $layer (keys %tmp) { my $ref_layer = $tmp{$layer}.'_ref'; if ( $GEN->isLayerExists(job=>$Job,layer=>$ref_layer) ) { $GEN->workLayer(name=>$ref_layer,number=>1); $GEN->selDelete(); } else { $GEN->createLayer(job=>$Job,layer=>$ref_layer); } $GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$tmp{$layer},dest_layer=>$tmp{$layer}.$BakSuffix); $GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$layer,dest_layer=>$layer.$BakSuffix); $GEN->workLayer(name=>$tmp{$layer},number=>1); $GEN->selectByFilter(attribute=>[{attribute=>'.string',text=>'sm_defined_pad_shave'}]); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); ##移除via $GEN->selectByFilter(attribute=>[{attribute=>'.drill',option=>'via'}],polarity=>'positive'); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); my $sm_tmp_bk = $tmp{$layer}.'_tl_script_bk'; $GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$tmp{$layer},dest_layer=>$sm_tmp_bk); #$GEN->selectByFilter(attribute=>[{attribute=>'.shave'}]); $GEN->selectByFilter(polarity=>'negative'); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); $GEN->workLayer(name=>$layer,number=>1); $GEN->selectByFilter(attribute=>[{attribute=>'.string',text=>'smdef_gasket'}]); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); _deleteLayer(layer=>[$tmp{$layer}.$SpecificalWarningSuffix]); foreach my $item ('smd','bga','pth','via','pad') {#'smd','bga','pth','via','pad' next unless ( defined $info{$item} and $info{$item} eq 'Yes' ); my $Coverage_tmp = $Coverage; my $CoverageTol_tmp = $CoverageTol; if ( $item eq 'smd' or $item eq 'bga' ) { next unless ( $AttrHash->{$item} ); } _deleteLayer(layer=>[values %TmpLayer]); if ( $item eq 'smd' ) { $CopperOpening = $SMDCopperOpening; } elsif ( $item eq 'bga' ) { $CopperOpening = $BGACopperOpening; } elsif ( $item eq 'pth' ) { $CopperOpening = $PTHCopperOpening; } elsif ( $item eq 'via' ) { $CopperOpening = $VIACopperOpening; } elsif ( $item eq 'pad' ) { $CopperOpening = $PADCopperOpening; } ####制作npth and via drill layer $GEN->createLayer(job=>$Job,layer=>$TmpLayer{npth_layer}); $GEN->workLayer(name=>$DrillLayer,number=>1); $GEN->selectByFilter(attribute=>[{attribute=>'.drill',option=>'non_plated'}]); if ( $GEN->getSelectCount() > 0 ) { $GEN->selCopyOther(target_layer=>$TmpLayer{npth_layer}); } $GEN->selectByFilter(attribute=>[{attribute=>'.drill',option=>'via'}]); if ( $GEN->getSelectCount() > 0 ) { $GEN->selCopyOther(target_layer=>$TmpLayer{via_drill_layer}); } ####制作铜面和粗线层(有碰到的.tear_drop也包括) 到辅助层 big_copper_layer $GEN->workLayer(name=>$layer,number=>1); $GEN->selectByFilter(feat_types=>'surface'); $GEN->selectByFilter(polarity=>'negative'); my $tmp_line = $MinSMDCopperLine; if ( $item eq 'bga' ) { $tmp_line = $MinBGACopperLine; } my %symhist = $GEN->getLayerSymsHist(job=>$Job,step=>$Step,layer=>$layer); foreach my $sym (keys %symhist) { if ( $sym =~ /^(r|s)[0-9]+\.?[0-9]*$/ and $symhist{$sym}{size} >= $tmp_line ) { $GEN->selectByFilter(include_syms=>$sym, feat_types=>'line\;arc', polarity=>'positive'); } } if ( $IncludeTearDrop eq 'No' ) { $GEN->selectByFilter( attribute=>'.tear_drop', operation=>'unselect' ); } if ( $GEN->getSelectCount() > 0 ) { $GEN->selCopyOther(target_layer=>$TmpLayer{big_copper_layer}); } else { next; } if ( $IncludeTearDrop eq 'Yes' ) { $GEN->selRefFeat( layers=>$TmpLayer{big_copper_layer}, use=>'filter', mode=>'touch', f_types=>'line\;arc', polarity=>'positive', filter=>{ filter_name => 'popup', attribute=>[{attribute=>'.tear_drop'}], } ); if ( $GEN->getSelectCount() > 0 ) { $GEN->selCopyOther(target_layer=>$TmpLayer{big_copper_layer}); } } if( $IncludePad eq 'Yes' ){ $GEN->attributeReset(); $GEN->COM('filter_reset',filter_name=>'popup'); $GEN->selRefFeat( layers=>$TmpLayer{big_copper_layer}, use=>'filter', mode=>'touch', f_types=>'line\;arc', polarity=>'positive', filter=>{ filter_name => 'popup', feat_types=>'pad', polarity=>'positive', } ); if ( $GEN->getSelectCount() > 0 ) { my $include_pad_lyr = '__include_pad_lyr__tl_script__'; $GEN->createLayer(job=>$Job,layer=>$include_pad_lyr,conext=>'misc',type=>'document',delete_exists =>'yes'); $GEN->selCopyOther(target_layer=>$include_pad_lyr); $GEN->workLayer(name=>$include_pad_lyr,number=>1); $GEN->attributeReset(); $GEN->COM('filter_reset',filter_name=>'popup'); $GEN->selRefFeat( layers=>$tmp{$layer}, use=>'filter', mode=>'disjoint' ); $GEN->selRefFeat( layers=>$tmp{$layer}, use=>'filter', mode=>'cover' ); $GEN->selRefFeat( layers=>$tmp{$layer}, use=>'filter', mode=>'include' ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); $GEN->workLayer(name=>$include_pad_lyr,number=>1); $GEN->COM("sel_all_feat"); if ( $GEN->getSelectCount() > 0 ){ $GEN->selCopyOther(target_layer=>$TmpLayer{big_copper_layer}); $GEN->workLayer(name=>$layer,number=>1); $GEN->selectByFilter(polarity=>'negative'); $GEN->selCopyOther(target_layer=>$TmpLayer{big_copper_layer}) if ( $GEN->getSelectCount() > 0 ); } _deleteLayer(layer=>[$include_pad_lyr]); } } $GEN->workLayer(name=>$TmpLayer{big_copper_layer},number=>1); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); $GEN->selectByFilter(); if ( $GEN->getSelectCount() == 1 ) { $GEN->COM('sel_decompose',overlap=>'yes'); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); } else { $GEN->selClearFeature(); } #####选择有碰到大铜面的盘到临时层 pad_touch_copper #####如果是pth会去除smd和bga #####如果是smd会去除bga my $tmp_work_layer = $layer.'_tmp_script__'; $GEN->copyLayer(source_job=>$Job, source_step=>$Step, source_layer=>$layer, dest_layer=>$tmp_work_layer, mode=>'replace', #append/replace invert=>'no') ;#|'yes' $GEN->workLayer(name=>$tmp_work_layer,number=>1); $GEN->attributeReset(); $GEN->COM('filter_reset',filter_name=>'popup'); $GEN->selectByFilter( attribute=>[{attribute=>'tl_string',text=>'pad_touch_copper_tmp_attr'}], ); if ($GEN->getSelectCount() > 0) { #$GEN->COM( "sel_delete_atr,attributes=tl_string,text=pad_touch_copper_tmp_attr" ); $GEN->COM( "sel_delete_atr,attributes=tl_string" ); } if ($item eq 'pad') { #if ( $GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{via_drill_layer}) ) { $GEN->COM("filter_reset,filter_name=popup"); $GEN->COM("filter_set,filter_name=popup,update_popup=no,feat_types=pad,polarity=positive"); $GEN->COM("sel_ref_feat,layers=$TmpLayer{via_drill_layer},use=filter,mode=touch,pads_as=shape,f_types=pad,polarity=positive,include_syms=,exclude_syms="); $GEN->COM("filter_reset,filter_name=popup"); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); #} } $GEN->selectByFilter(attribute=>$AttrHash->{bga}); $GEN->selCopyOther(target_layer=>$TmpLayer{smd_bga_pad}) if ( $GEN->getSelectCount() > 0 ); $GEN->selectByFilter(attribute=>$AttrHash->{smd}); $GEN->selCopyOther(target_layer=>$TmpLayer{smd_bga_pad}) if ( $GEN->getSelectCount() > 0 ); if ( $item eq 'pth' or $item eq 'pad' or $item eq 'via' ) { $GEN->selRefFeat( layers=>$TmpLayer{big_copper_layer}, use=>'filter', mode=>'touch', filter=>{ filter_name => 'popup', feat_types=>'pad', polarity=>'positive', } ); } else { $GEN->selRefFeat( layers=>$TmpLayer{big_copper_layer}, use=>'filter', mode=>'touch', filter=>{ filter_name => 'popup', attribute=> $AttrHash->{$item} } ); } if ( $item eq 'smd' ) { $GEN->selectByFilter( attribute=>$AttrHash->{bga}, operation=>'unselect' ); } elsif ( $item eq 'pth' or $item eq 'pad' or $item eq 'via' ) { $GEN->selectByFilter( attribute=>$AttrHash->{bga}, operation=>'unselect' ); $GEN->selectByFilter( attribute=>$AttrHash->{smd}, operation=>'unselect' ); } if ( $GEN->getSelectCount() > 0 ) { $GEN->selAddAttr(attribute=>[{attribute=>'tl_string',text=>'pad_touch_copper_tmp_attr'}]); $GEN->selectByFilter( attribute=>[{attribute=>'tl_string',text=>'pad_touch_copper_tmp_attr'}], ); if ( $item eq 'pth' or $item eq 'pad' or $item eq 'via' ) { $GEN->selRefFeat( use=>'select', mode=>'touch', filter=>{ filter_name => 'popup', feat_types=>'pad', polarity=>'positive', } ); $GEN->selectByFilter( attribute=>$AttrHash->{bga}, operation=>'unselect' ); $GEN->selectByFilter( attribute=>$AttrHash->{smd}, operation=>'unselect' ); }else{ $GEN->selRefFeat( use=>'select', mode=>'touch', filter=>{ polarity=>'positive', attribute=>$AttrHash->{$item}, } ); $GEN->selectByFilter( attribute=>$AttrHash->{bga}, operation=>'unselect' ); } $GEN->selAddAttr(attribute=>[{attribute=>'tl_string',text=>'pad_touch_copper_tmp_attr'}])if ( $GEN->getSelectCount() > 0 ); $GEN->selectByFilter( attribute=>[{attribute=>'tl_string',text=>'pad_touch_copper_tmp_attr'}], ); $GEN->selCopyOther(target_layer=>$TmpLayer{pad_touch_copper}); $GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1); if ( $item eq 'pth' or $item eq 'via' ) { $GEN->selRefFeat( layers=>$DrillLayer, use=>'filter', mode=>'disjoint' ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); if ( $GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{via_drill_layer}) ) { if ( $item eq 'pth' ) { $GEN->selRefFeat( layers=>$TmpLayer{via_drill_layer}, use=>'filter', mode=>'touch' ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); } elsif ( $item eq 'via' ) { $GEN->selRefFeat( layers=>$TmpLayer{via_drill_layer}, use=>'filter', mode=>'disjoint' ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); } } } elsif ( $item eq 'pad' ) { #$GEN->selRefFeat( # layers=>$DrillLayer, # use=>'filter', # mode=>'touch' #); #$GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); $GEN->COM("filter_atr_set,filter_name=ref_select,condition=yes,attribute=.drill,option=plated"); $GEN->selRefFeat( layers=>$DrillLayer, use=>'filter', mode=>'touch' ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); $GEN->COM("filter_atr_reset,filter_name=ref_select"); } if ( ($item eq 'pth' or $item eq 'pad' or $item eq 'via') and ( $GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{smd_bga_pad}) ) and $InIgnoreSmdBga eq 'No') { $GEN->selRefFeat( layers=>$TmpLayer{smd_bga_pad}, use=>'filter', mode=>'touch' ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); } $GEN->selRefFeat( layers=>$TmpLayer{npth_layer}, use=>'filter', mode=>'touch' ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); } else { next; } ###去除laser Pad $GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1); if ( $LaserPadAttr ) { $GEN->selectByFilter( feat_types=>'pad', polarity=>'positive', attribute=>$LaserPadAttr ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); } ####制作符合条件的所有pad 到辅助层 all_pad_with_attr $GEN->workLayer(name=>$layer,number=>1); $GEN->attributeReset(); $GEN->COM('filter_reset',filter_name=>'popup'); if ( $item eq 'pth' or $item eq 'via' ) { $GEN->selRefFeat( layers=>$DrillLayer, use=>'filter', mode=>'touch', filter=>{ filter_name => 'popup', feat_types=>'pad' } ); } elsif ( $item eq 'pad' ) { #$GEN->selRefFeat( # layers=>$DrillLayer, # use=>'filter', # mode=>'touch', # filter=>{ # filter_name => 'popup', # feat_types=>'pad' # } #); $GEN->COM("filter_atr_set,filter_name=ref_select,condition=yes,attribute=.drill,option=plated"); $GEN->selRefFeat( layers=>$DrillLayer, use=>'filter', mode=>'disjoint', filter=>{ filter_name => 'popup', feat_types=>'pad' } ); $GEN->COM("filter_atr_reset,filter_name=ref_select"); } else { $GEN->selectByFilter( feat_types=>'pad', polarity=>'positive', attribute=>$AttrHash->{$item} ); } if ( $item eq 'smd' ) { $GEN->selectByFilter( attribute=>$AttrHash->{bga}, operation=>'unselect' ); } elsif ( $item eq 'pth' or $item eq 'pad' ) { $GEN->selectByFilter( attribute=>$AttrHash->{bga}, operation=>'unselect' ); $GEN->selectByFilter( attribute=>$AttrHash->{smd}, operation=>'unselect' ); } if ( $GEN->getSelectCount() > 0 ) { $GEN->selCopyOther(target_layer=>$TmpLayer{all_pad_with_attr}); $GEN->workLayer(name=>$TmpLayer{all_pad_with_attr},number=>1); $GEN->selRefFeat( layers=>$TmpLayer{npth_layer}, use=>'filter', mode=>'touch' ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); if ( $GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{via_drill_layer}) ) { if ( $item eq 'pth' ) { $GEN->selRefFeat( layers=>$TmpLayer{via_drill_layer}, use=>'filter', mode=>'touch' ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); } elsif ( $item eq 'via' ) { $GEN->selRefFeat( layers=>$TmpLayer{via_drill_layer}, use=>'filter', mode=>'disjoint' ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); } } if ( $GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{smd_bga_pad}) and ( $item eq 'pth' or $item eq 'via' or $item eq 'pad' ) and $InIgnoreSmdBga eq 'No') { $GEN->selRefFeat( layers=>$TmpLayer{smd_bga_pad}, use=>'filter', mode=>'touch' ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); } } else { next; } ###去除laser Pad $GEN->workLayer(name=>$TmpLayer{all_pad_with_attr},number=>1); if ( $LaserPadAttr ) { $GEN->selectByFilter( feat_types=>'pad', polarity=>'positive', attribute=>$LaserPadAttr ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); } ####制作碰到大铜面的pad所对应的开窗到临时层pad_opening $GEN->workLayer(name=>$tmp{$layer},number=>1); $GEN->selCopyOther(target_layer=>$TmpLayer{pad_opening}); $GEN->workLayer(name=>$TmpLayer{pad_opening},number=>1); $GEN->selectByFilter(feat_types=>'surface'); $GEN->selectByFilter(polarity=>'negative');##删除所有负片 $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); #remove npth opening $GEN->selRefFeat( layers=>$TmpLayer{npth_layer}, use=>'filter', mode=>'touch' ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); $GEN->selRefFeat( layers=>$TmpLayer{pad_touch_copper}, use=>'filter', mode=>'disjoint' ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); ####去除客户定义不需要处理的开窗 if ( $IgnoreAttr ) { $GEN->selectByFilter(attribute=>$IgnoreAttr); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); } #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); $GEN->selectByFilter(); if ( $GEN->getSelectCount() == 1 ) { $GEN->COM('sel_decompose',overlap=>'yes'); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); } else { $GEN->selClearFeature(); } ###去除特殊开窗 $GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1); $GEN->selCopyOther(target_layer=>$TmpLayer{tmp_layer}); $GEN->workLayer(name=>$TmpLayer{tmp_layer},number=>1); $GEN->COM('sel_resize',size=>$UpdateMaxOpening*3,corner_ctl=>'no'); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); $GEN->selectByFilter(); if ( $GEN->getSelectCount() == 1 ) { $GEN->COM('sel_decompose',overlap=>'yes'); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); } else { $GEN->selClearFeature(); } $GEN->workLayer(name=>$TmpLayer{pad_opening},number=>1); $GEN->selRefFeat( layers=>$TmpLayer{tmp_layer}, use=>'filter', mode=>'cover' ); #$GEN->COM('disp_on'); $GEN->selReverse(); if ( $GEN->getSelectCount() > 0 ) { $GEN->selCopyOther(target_layer=>$TmpLayer{remove_specifical_sm}); ##2018-3-23修复如果防焊开窗ring本来满足要求,就会放到报警层而不制作smdefined的问题 -- start #$GEN->workLayer(name=>$TmpLayer{remove_specifical_sm},number=>1); #$GEN->selRefFeat( # layers=>$TmpLayer{tmp_layer}, # use=>'filter', # mode=>'include' #); #$GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); ##2018-3-23 -- end ## $GEN->workLayer(name=>$TmpLayer{pad_opening},number=>1); $GEN->selRefFeat( layers=>$TmpLayer{remove_specifical_sm}, use=>'filter', mode=>'touch' ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); if ( $SpecificalWarningSuffix ) { $GEN->workLayer(name=>$TmpLayer{remove_specifical_sm},number=>1); $GEN->selCopyOther(target_layer=>$tmp{$layer}.$SpecificalWarningSuffix); } } #$GEN->PAUSE('tttt'); _deleteLayer(layer=>[$TmpLayer{tmp_layer}]); ####去除没有被覆盖在开窗里面的pad $GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1); $GEN->selRefFeat( layers=>$TmpLayer{pad_opening}, use=>'filter', mode=>'cover' ); $GEN->selReverse(); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); ####所有SM开窗到临时层sm_opening $GEN->workLayer(name=>$tmp{$layer},number=>1); $GEN->selCopyOther(target_layer=>$TmpLayer{sm_opening}); $GEN->workLayer(name=>$TmpLayer{sm_opening},number=>1); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); $GEN->selectByFilter(); if ( $GEN->getSelectCount() == 1 ) { $GEN->COM('sel_decompose',overlap=>'yes'); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); } else { $GEN->selClearFeature(); } ###制作开窗比pad小的到临时层 sm_less_pad $GEN->workLayer(name=>$TmpLayer{all_pad_with_attr},number=>1); $GEN->selCopyOther(target_layer=>$TmpLayer{tmp_layer}); $GEN->workLayer(name=>$TmpLayer{tmp_layer},number=>1); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); $GEN->selectByFilter(); if ( $GEN->getSelectCount() == 1 ) { $GEN->COM('sel_decompose',overlap=>'yes'); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); } else { $GEN->selClearFeature(); } $GEN->workLayer(name=>$tmp{$layer},number=>1); $GEN->selRefFeat( layers=>$TmpLayer{tmp_layer}, use=>'filter', mode=>'include' ); $GEN->selReverse(); if ( $GEN->getSelectCount() > 0 ) { $GEN->selCopyOther(target_layer=>$TmpLayer{sm_less_pad}); $GEN->workLayer(name=>$TmpLayer{sm_less_pad},number=>1); $GEN->selRefFeat( layers=>$TmpLayer{tmp_layer}, use=>'filter', mode=>'cover' ); $GEN->selReverse(); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); } _deleteLayer(layer=>[$TmpLayer{tmp_layer}]); ###制作正式层上开窗比pad小的情况 if ( $GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{sm_less_pad}) and $PAR->{make_sm_less_pad} eq 'Yes') { $GEN->workLayer(name=>$tmp{$layer},number=>1); $GEN->selRefFeat( layers=>$TmpLayer{sm_less_pad}, use=>'filter', mode=>'cover' ); $GEN->selectByFilter( attribute=>[{attribute=>'.string',text=>'smdefpad_sm'}], operation=>'unselect' ); ####去除客户定义不需要处理的开窗 if ( $IgnoreAttr ) { $GEN->selectByFilter(attribute=>$IgnoreAttr, operation=>'unselect'); } if ( $GEN->getSelectCount() > 0 ) { $GEN->selCopyOther(target_layer=>$TmpLayer{tmp_layer}); $GEN->selRefFeat( layers=>$TmpLayer{tmp_layer}, use=>'filter', mode=>'cover' ); $GEN->selAddAttr(attribute=>[{attribute=>'.string',text=>'smdefpad_sm_'.$item},'smdefpad_sm']) if ( $GEN->getSelectCount() > 0 ); $GEN->selectByFilter(attribute=>[{attribute=>'.string',text=>'smdefpad_sm_'.$item}]); if ( $GEN->getSelectCount() > 0 ) { $GEN->selCopyOther(target_layer=>$ref_layer); } $GEN->selectByFilter(attribute=>[{attribute=>'.string',text=>'smdefpad_sm_'.$item}]); $GEN->COM('sel_resize',size=>$CopperOpening*2,corner_ctl=>'no') if ( $GEN->getSelectCount() > 0 ); $GEN->workLayer(name=>$TmpLayer{pad_opening},number=>1); $GEN->selRefFeat( layers=>$TmpLayer{tmp_layer}, use=>'filter', mode=>'touch' ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); $GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1); $GEN->selRefFeat( layers=>$TmpLayer{tmp_layer}, use=>'filter', mode=>'touch' ); $GEN->workLayer(name=>$TmpLayer{all_pad_with_attr},number=>1); $GEN->selRefFeat( layers=>$TmpLayer{tmp_layer}, use=>'filter', mode=>'touch' ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); _deleteLayer(layer=>[$TmpLayer{tmp_layer}]); } } ####gaster 制作(copy 外层pad加大(gasketsize+$CopperOpening)*2 到当前层为surface) $GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1); $GEN->selRefFeat( layers=>$TmpLayer{big_copper_layer}, use=>'filter', mode=>'cover' ); if ( $GEN->getSelectCount() > 0 ) { $GEN->selCopyOther(target_layer=>$TmpLayer{tmp_layer}); $GEN->workLayer(name=>$TmpLayer{tmp_layer},number=>1); $GEN->selRefFeat( layers=>$TmpLayer{pad_opening}, use=>'filter', mode=>'cover' ); if ( $GEN->getSelectCount() > 0 ) { $GEN->selCopyOther(target_layer=>$TmpLayer{pad_on_copper_gasket}); } } _deleteLayer(layer=>[$TmpLayer{tmp_layer}]); if ( $KeepGasket eq 'Yes' and $GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{pad_on_copper_gasket}) ) { $GEN->workLayer(name=>$TmpLayer{pad_on_copper_gasket},number=>1); $GEN->COM('sel_resize',size=>($GasketSize+$CopperOpening)*2,corner_ctl=>'no'); $GEN->selAddAttr(attribute=>['gasket',{attribute=>'.string',text=>'smdef_gasket'}]); $GEN->selCopyOther(target_layer=>$layer); $GEN->selCopyOther(target_layer=>$TmpLayer{big_copper_layer}); $GEN->workLayer(name=>$TmpLayer{big_copper_layer},number=>1); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); $GEN->selectByFilter(); if ( $GEN->getSelectCount() == 1 ) { $GEN->COM('sel_decompose',overlap=>'yes'); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); } else { $GEN->selClearFeature(); } } ####开窗不足最优的情况下最优化开窗 $GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1); $GEN->selCopyOther(target_layer=>$TmpLayer{tmp_layer}); $GEN->workLayer(name=>$TmpLayer{tmp_layer},number=>1); if ( ref $OptOpening eq 'ARRAY' ) { my %symhist = $GEN->getLayerSymsHist(job=>$Job,step=>$Step,layer=>$TmpLayer{tmp_layer}); foreach my $item (sort { $symhist{$b}{size} <=> $symhist{a}{size} } keys %symhist) { my $size = $symhist{$item}{size}; if ( ! $size ) { $size = ($symhist{$item}{width} < $symhist{$item}{length}) ? $symhist{$item}{width} : $symhist{$item}{length}; } my $cmp; foreach my $v (@$OptOpening) { if ( $size ) { next if ( $v->{type} eq 'others' ); if ( $size > $v->{min} and $size <= $v->{max} ) { $cmp = $v->{cmp}; last; } } else { if ( $v->{type} eq 'others' ) { $cmp = $v->{cmp}; last; } } } if ( $cmp ) { $GEN->selectByFilter(include_syms=>$item); $GEN->COM('sel_resize',size=>$cmp*2,corner_ctl=>'no') if ( $GEN->getSelectCount() > 0 ); } else { $GUI->msgbox(-icon=>'error',-text=>"symbol $item 找不到最优开窗大小!"); return 'Error'; } } } else { $GEN->COM('sel_resize',size=>$OptOpening*2,corner_ctl=>'no'); } $GEN->selRefFeat( layers=>$TmpLayer{pad_opening}, use=>'filter', mode=>'include' ); $GEN->selReverse(); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); $GEN->workLayer(name=>$tmp{$layer},number=>1); $GEN->selRefFeat( layers=>$TmpLayer{tmp_layer}, use=>'filter', mode=>'cover' ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); $GEN->workLayer(name=>$TmpLayer{tmp_layer},number=>1); $GEN->selCopyOther(target_layer=>$tmp{$layer}); $GEN->selCopyOther(target_layer=>$TmpLayer{pad_opening}); $GEN->selCopyOther(target_layer=>$TmpLayer{sm_opening}); $GEN->workLayer(name=>$TmpLayer{pad_opening},number=>1); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); $GEN->selectByFilter(); if ( $GEN->getSelectCount() == 1 ) { $GEN->COM('sel_decompose',overlap=>'yes'); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); } else { $GEN->selClearFeature(); } $GEN->workLayer(name=>$TmpLayer{sm_opening},number=>1); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); $GEN->selectByFilter(); if ( $GEN->getSelectCount() == 1 ) { $GEN->COM('sel_decompose',overlap=>'yes'); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); } else { $GEN->selClearFeature(); } _deleteLayer(layer=>[$TmpLayer{tmp_layer}]); ####制作优化的大铜面到临时层 opt_big_copper #my $CoverageTol = 1; if ($item ne 'smd') { $Coverage_tmp = $Coverage_tmp + $CoverageTol_tmp/2; $CoverageTol_tmp = 0; } #$Coverage = $CopperOpening < 0 ? -$Coverage : $Coverage; $GEN->workLayer(name=>$TmpLayer{big_copper_layer},number=>1); $GEN->selCopyOther(target_layer=>$TmpLayer{opt_big_copper},size=>$Coverage_tmp); $GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1); $GEN->selRefFeat( layers=>$TmpLayer{pad_opening}, use=>'filter', mode=>'include' ); if ($item eq 'bga') { $GEN->selectByFilter(attribute=>[{attribute=>'tl_spec_bga'}],operation=>'unselect');#non_plated,plated,via } $GEN->selCopyOther(target_layer=>$TmpLayer{opt_big_copper},size=>2*$CopperOpening+$Coverage_tmp+$CoverageTol_tmp,invert=>'yes') if ( $GEN->getSelectCount() > 0 ); $GEN->selRefFeat( layers=>$TmpLayer{pad_opening}, use=>'filter', mode=>'cover' ); if ($item eq 'bga') { $GEN->selectByFilter(attribute=>[{attribute=>'tl_spec_bga'}],operation=>'unselect');#non_plated,plated,via } $GEN->selCopyOther(target_layer=>$TmpLayer{opt_big_copper},size=>2*$CopperOpening+$Coverage_tmp+$CoverageTol_tmp,invert=>'yes') if ( $GEN->getSelectCount() > 0 ); if ($item eq 'bga') { $GEN->selectByFilter(attribute=>[{attribute=>'tl_spec_bga'}]);#non_plated,plated,via $GEN->selCopyOther(target_layer=>$TmpLayer{opt_big_copper},size=>2*$SpecBGACopperOpening+$Coverage_tmp+$CoverageTol_tmp,invert=>'yes') if ( $GEN->getSelectCount() > 0 ); } $GEN->workLayer(name=>$TmpLayer{opt_big_copper},number=>1); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); $GEN->selectByFilter(); if ( $GEN->getSelectCount() == 1 ) { $GEN->COM('sel_decompose',overlap=>'yes'); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); } else { $GEN->selClearFeature(); } $GEN->COM('sel_resize',size=>$Coverage_tmp+$CoverageTol_tmp,corner_ctl=>'no'); ####制作准确的大铜面pad开窗到临时层 correct_sm_opening $GEN->workLayer(name=>$TmpLayer{pad_opening},number=>1); $GEN->selCopyOther(target_layer=>$TmpLayer{correct_sm_opening},size=>2); $GEN->workLayer(name=>$TmpLayer{opt_big_copper},number=>1); $GEN->selCopyOther(target_layer=>$TmpLayer{correct_sm_opening},invert=>'yes'); $GEN->workLayer(name=>$TmpLayer{correct_sm_opening},number=>1); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); $GEN->selectByFilter(); if ( $GEN->getSelectCount() == 1 ) { $GEN->COM('sel_decompose',overlap=>'yes'); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); } else { $GEN->selClearFeature(); } $GEN->selRefFeat( layers=>$TmpLayer{pad_touch_copper}, use=>'filter', mode=>'disjoint' ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); ####制作需要刮开的开窗部分 $GEN->workLayer(name=>$TmpLayer{pad_opening},number=>1); $GEN->selCopyOther(target_layer=>$TmpLayer{sm_opening_free},size=>1); $GEN->workLayer(name=>$TmpLayer{correct_sm_opening},number=>1); $GEN->selCopyOther(target_layer=>$TmpLayer{sm_opening_free},invert=>'yes'); $GEN->workLayer(name=>$tmp{$layer}.$BakSuffix,number=>1); $GEN->attributeReset(); $GEN->COM('filter_reset',filter_name=>'popup'); $GEN->selectByFilter(attribute=>[{attribute=>'.drill',option=>'via'}],polarity=>'negative'); if ( $GEN->getSelectCount() > 0 ){ $GEN->selCopyOther(target_layer=>$TmpLayer{sm_opening_free}); } $GEN->workLayer(name=>$TmpLayer{sm_opening_free},number=>1); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); $GEN->selectByFilter(); if ( $GEN->getSelectCount() == 1 ) { $GEN->COM('sel_decompose',overlap=>'yes'); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); } else { $GEN->selClearFeature(); } $GEN->COM('sel_resize',size=>-0.05,corner_ctl=>'no'); $GEN->selRefFeat( layers=>$TmpLayer{sm_opening}, use=>'filter', mode=>'cover' ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); $GEN->selRefFeat( layers=>$TmpLayer{sm_opening}, use=>'filter', mode=>'disjoint' ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); $GEN->selRefFeat( layers=>$TmpLayer{sm_opening}, use=>'filter', mode=>'include' ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); if ( $CopperOpening > 0 ) { $GEN->selRefFeat( layers=>$TmpLayer{pad_touch_copper}, use=>'filter', mode=>'touch' ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); } $GEN->COM('sel_resize',size=>0.05,corner_ctl=>'no'); #####去除小细丝 $GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$tmp{$layer},dest_layer=>$TmpLayer{tmp_layer}); $GEN->workLayer(name=>$TmpLayer{sm_opening_free},number=>1); $GEN->selCopyOther(target_layer=>$TmpLayer{tmp_layer},invert=>'yes'); $GEN->workLayer(name=>$TmpLayer{tmp_layer},number=>1); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); $GEN->selectByFilter(); if ( $GEN->getSelectCount() == 1 ) { $GEN->COM('sel_decompose',overlap=>'yes'); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); } else { $GEN->selClearFeature(); } $GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$TmpLayer{tmp_layer},dest_layer=>$TmpLayer{sliver_layer}); #$GEN->COM('sel_resize',size=>-1,corner_ctl=>'no'); #$GEN->COM('sel_resize',size=>1,corner_ctl=>'no'); $GEN->selFill(min_brush=>2); $GEN->selContourize(); $GEN->selCopyOther(target_layer=>$TmpLayer{sliver_layer},invert=>'yes',size=>0.05); $GEN->workLayer(name=>$TmpLayer{sliver_layer},number=>1); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); $GEN->COM('sel_resize',size=>-0.05,corner_ctl=>'no'); $GEN->COM('sel_resize',size=>0.05,corner_ctl=>'no'); $GEN->selectByFilter(); if ( $GEN->getSelectCount() == 1 ) { $GEN->COM('sel_decompose',overlap=>'yes'); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); } else { $GEN->selClearFeature(); } $GEN->selectByFilter(polarity=>'positive'); if ( $GEN->getSelectCount() > 0 ) { $GEN->selCopyOther(target_layer=>$TmpLayer{sm_opening_free},size=>0.05); $GEN->workLayer(name=>$TmpLayer{sm_opening_free},number=>1); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); $GEN->selectByFilter(); if ( $GEN->getSelectCount() == 1 ) { $GEN->COM('sel_decompose',overlap=>'yes'); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); } else { $GEN->selClearFeature(); } } $GEN->selClearFeature(); ##去除小面积物件 if ($DeleteSamllArea eq 'Yes') { $GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$tmp{$layer},dest_layer=>$TmpLayer{tmp_layer}); $GEN->workLayer(name=>$TmpLayer{sm_opening_free},number=>1); $GEN->selCopyOther(target_layer=>$TmpLayer{tmp_layer},invert=>'yes'); $GEN->workLayer(name=>$TmpLayer{tmp_layer},number=>1); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); $GEN->selectByFilter(); if ( $GEN->getSelectCount() == 1 ) { $GEN->COM('sel_decompose',overlap=>'yes'); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); } else { $GEN->selClearFeature(); } $GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$TmpLayer{tmp_layer},dest_layer=>$TmpLayer{samll_area_layer}); $GEN->workLayer(name=>$TmpLayer{tmp_layer},number=>1); $GEN->selectByFilter(polarity=>'positive'); $GEN->COM("sel_clean_surface,accuracy=0,clean_size=$SmallAreaOpen,clean_mode=area,max_fold_len=0"); $GEN->workLayer(name=>$TmpLayer{samll_area_layer},number=>1); $GEN->selRefFeat( layers=>$TmpLayer{tmp_layer}, use=>'filter', mode=>'touch' ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); $GEN->selectByFilter(polarity=>'positive'); if ( $GEN->getSelectCount() > 0 ) { $GEN->selCopyOther(target_layer=>$TmpLayer{sm_opening_free},size=>0.05); $GEN->workLayer(name=>$TmpLayer{sm_opening_free},number=>1); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); $GEN->selectByFilter(); if ( $GEN->getSelectCount() == 1 ) { $GEN->COM('sel_decompose',overlap=>'yes'); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); } else { $GEN->selClearFeature(); } } $GEN->selClearFeature(); } ###add smdefpad_sm_totally and smdefpad_sm_partly _deleteLayer(layer=>[$TmpLayer{tmp_layer}]); if ( $GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{pad_on_copper_gasket}) ) { $GEN->workLayer(name=>$TmpLayer{pad_touch_copper},number=>1); $GEN->selRefFeat( layers=>$TmpLayer{pad_on_copper_gasket}, use=>'filter', mode=>'touch' ); if ( $GEN->getSelectCount() > 0 ) { $GEN->selCopyOther(target_layer=>$TmpLayer{tmp_layer}); $GEN->workLayer(name=>$tmp{$layer},number=>1); $GEN->selRefFeat( layers=>$TmpLayer{tmp_layer}, use=>'filter', mode=>'include' ); if ( $GEN->getSelectCount() > 0 ) { $GEN->selAddAttr(attribute=>'smdefpad_sm_totally'); } } } $GEN->workLayer(name=>$tmp{$layer},number=>1); $GEN->selRefFeat( layers=>$TmpLayer{sm_opening_free}, use=>'filter', mode=>'touch' ); $GEN->selectByFilter( attribute=>'smdefpad_sm', operation=>'unselect' ); $GEN->selectByFilter( attribute=>'smdefpad_sm_totally', operation=>'unselect' ); if ( $GEN->getSelectCount() > 0 ) { $GEN->selAddAttr(attribute=>'smdefpad_sm_partly'); } _deleteLayer(layer=>[$TmpLayer{tmp_layer}]); ###copy to sm layer $GEN->workLayer(name=>$TmpLayer{sm_opening_free},number=>1); $GEN->COM('sel_delete_atr',attributes=>'smdefpad_sm'); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); $GEN->selectByFilter(); if ( $GEN->getSelectCount() == 1 ) { $GEN->COM('sel_decompose',overlap=>'yes'); #$GEN->selContourize(); $GEN->COM('sel_cont_resize',accuracy=>0.1,break_to_islands=>"yes",island_size=>0,hole_size=>0,drill_filter=>"no",corner_ctl=>"no"); } else { $GEN->selClearFeature(); } $GEN->selAddAttr(attribute=>[{attribute=>'.string',text=>'sm_defined_pad_shave'}]); ###去掉有shave碰到开窗上是surface的部分 $GEN->workLayer(name=>$TmpLayer{sm_opening_free},number=>1); $GEN->selRefFeat( layers=>$tmp{$layer}, use=>'filter', mode=>'touch', f_types=>'surface' ); $GEN->selDelete() if ( $GEN->getSelectCount() > 0 ); $GEN->selCopyOther(target_layer=>$TmpLayer{sm_defined_tmp_layer},invert=>'yes'); $GEN->selCopyOther(target_layer=>$sm_tmp_bk,invert=>'yes'); $GEN->selCopyOther(target_layer=>$ref_layer); } if($GEN->isLayerExists(job=>$Job,layer=>$TmpLayer{sm_defined_tmp_layer})){ $GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$TmpLayer{sm_defined_tmp_layer},dest_layer=>$tmp{$layer},mode=>'append',invert=>'no'); } $GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$sm_tmp_bk,dest_layer=>$tmp{$layer}); $GEN->COM("disp_on"); _deleteLayer(layer=>[$sm_tmp_bk,$TmpLayer{sm_defined_tmp_layer}]); ###补偿用户定义的属性将忽略处理的开窗 $GEN->workLayer(name=>$tmp{$layer},number=>1); if ( $PAR->{ignore_attr_comp} and $PAR->{ignore_attr_comp} eq 'Yes' and $IgnoreAttr ) { $GEN->workLayer(name=>$tmp{$layer},number=>1); $GEN->selectByFilter(attribute=>$IgnoreAttr); if ( $GEN->getSelectCount() > 0 ) { $GEN->COM('sel_resize',size=>$CopperOpening*2,corner_ctl=>'no'); } } ##恢复via $GEN->workLayer(name=>$tmp{$layer}.$BakSuffix,number=>1); $GEN->attributeReset(); $GEN->COM('filter_reset',filter_name=>'popup'); $GEN->selectByFilter(attribute=>[{attribute=>'.drill',option=>'via'}],polarity=>'positive'); if ( $GEN->getSelectCount() > 0 ){ $GEN->selCopyOther(target_layer=>$tmp{$layer}); $GEN->selCopyOther(target_layer=>$sm_tmp_bk); } # # 恢复负片层 # my $negative_open_lyr = $tmp{$layer}.'_negative_open_lyr_tl_script'; # $GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$tmp{$layer}.$BakSuffix,dest_layer=>$negative_open_lyr); # $GEN->workLayer(name=>$negative_open_lyr,number=>1); # $GEN->attributeReset(); # $GEN->COM('filter_reset',filter_name=>'popup'); # $GEN->selectByFilter(polarity=>'positive'); # if ( $GEN->getSelectCount() > 0 ){ # $GEN->selectByFilter(polarity=>'positive'); # $GEN->COM('sel_resize',size=>'-1',corner_ctl=>'no'); # } # $GEN->attributeReset(); # $GEN->COM('filter_reset',filter_name=>'popup'); # $GEN->selectByFilter(polarity=>'negative'); # $GEN->COM('sel_resize',size=>1,corner_ctl=>'no') if ( $GEN->getSelectCount() > 0 ); # $GEN->selContourize(); # # $GEN->workLayer(name=>$tmp{$layer}.$BakSuffix,number=>1); # $GEN->selRefFeat( # layers=>$negative_open_lyr, # use=>'filter', # mode=>'disjoint', # filter=>{ # filter_name => 'popup', # polarity=>'negative', # } # ); # if ( $GEN->getSelectCount() > 0 ){ # $GEN->selCopyOther(target_layer=>$tmp{$layer},size=>0); # } #_deleteLayer(layer=>[$negative_open_lyr]); $GEN->workLayer(name=>$tmp{$layer},number=>1); } ###output and return status, if genesis error, it will output genesis error command unless ($GEN->{STATUS}){ $GEN->COM("disp_on"); return $Return; } else{ $GEN->COM("disp_on"); $GUI->msgbox(-icon=>'error',-text=>join("\n",@{$GEN->{STATUS}})); #addFlowNotes(-notes=>" Genesis Error:\n ".join("\n ",@{$GEN->{STATUS}})); return 'Error'; } } catch Error::Simple with { $GEN->COM("disp_on"); my $error = encode("utf8",shift); $GUI->msgbox(-icon=>'error',-text=>$error); return 'Error'; } finally{ $GEN->COM("disp_on"); _deleteLayer(layer=>[values %TmpLayer]); }; sub _deleteLayer{ my %par = @_; foreach my $layer(@{$par{layer}}){ $GEN->deleteLayer(layer=>$layer) if ($GEN->isLayerExists(job=>$Job,layer=>$layer)); } } sub select_work_layer{ my %par = @_; ##获取工作层 my @sm; my %matrix = $GEN->getMatrix(job=>$Job,type=>'hash'); foreach my $layer (sort {$matrix{$a}{row} <=> $matrix{$b}{row}} keys %matrix) { if(defined($matrix{$layer}{context}) and $matrix{$layer}{context} eq 'board' ){ if (defined($matrix{$layer}{tl_type}) and $matrix{$layer}{tl_type} eq 'solder_mask') { push @sm,$layer; } } } ## unless( @sm ){ $GUI->msgbox(-icon=>'warning',-text=>'资料中无防焊层,请确认'); return 'Cancel'; } ## if ($PAR->{is_select_lyr} eq 'Yes' and scalar(@sm) > 1) { my (%tmp_matrix); foreach my $layer (@sm) { $tmp_matrix{$layer} = $matrix{$layer}; } @sm = $GUI->select_layer( -title=>'请选择工作层别', -layermatrix=>\%tmp_matrix, -default => [keys %tmp_matrix], -selectmode => 'multiple');#single return 'Cancel' unless(@sm); } return \@sm; }