=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;
}