ZDA_2net_turn_pad.pl 8.51 KB
Newer Older
Scott Sun's avatar
Scott Sun committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
=head
 NAME: 
 DESCRIPTION: 自动转PAD
 PARAMETER:
	[
		{
			name : 'step_filter',
			type : 'LineEdit',
			title : 'step过滤',
			pack : {row:0,column:1},
			property:{tool_tip:'选择step时候的过滤器'},
		},
		{
			name : 'max_pad_size',
			type : 'LineEdit',
			title : 'PAD最大尺寸(mil)',
			pack : {row:0,column:1},
			property:{tool_tip:'PAD最大尺寸(mil)'},
		},
		{
			name : 'tolerance',
			type : 'LineEdit',
			title : '公差(mil)',
			pack : {row:0,column:1},
			property:{tool_tip:'公差(mil)'},
		},
		{
			name : 'bak_layer_pad',
			type : 'LineEdit',
			title : '备份层后缀',
			pack : {row:0,column:1},
			property:{tool_tip:'去铜丝参数'},
		}
	]
 VERSION_HISTORY:
	V1.00 2020-10-12 Super
	   1.新版本
 HELP:
	<html><body bgcolor="#DDECFE">
		<font size="3" color="#003DB2"><p>功能简介</p></font>
		  <p> DFM优化 </p>
		  <br>
		<font size="3" color="#003DB2"><p>参数配置</p></font>
		<font color="#008000"><p> ● 无</p></font>
		<font size="3" color="#003DB2"><p>注意事项</p></font>
		  <p> ● 无 </p>
		  <br>
	</body></html>
  
=cut

use strict;
use utf8;
use Data::Dump 'dump';
my ($Job,$Step)=($JOB,undef);
my $Report = 'done';

my @work_layers;
$PAR->{max_pad_size} = $PAR->{max_pad_size} ? $PAR->{max_pad_size} : 500;
$PAR->{tolerance} = $PAR->{tolerance} ? $PAR->{tolerance} : 1;
$PAR->{bak_layer_pad} = $PAR->{bak_layer_pad} ? $PAR->{bak_layer_pad} : '++-bak-pad++';

try {
	###检查Genesis料号是否存在并打开
	show_loading("检查${Job}是否存在..",0,position=>'n');
	if (! $GEN->isJobExists(job=>$Job) ){
        $GUI->msgbox(-icon=>'error',-text=>"料号 $Job 在Genesis中不存在, 请检查!");
        return 'Error';
    }

	update_loading("正在打开料号 ${Job} ...",0,position=>'n');
	$GEN->openJob(job=>$Job) unless ($GEN->isJobOpen(job=>$Job));
	my %matrix = $GEN->getMatrix(job=>$Job,type=>'hash');

	my @steps =  $GEN->getStepList(job=>$Job);
	if ( @steps == 0 ) {
		$GUI->msgbox(-icon=>'error',-text=>'在料号中没有Step存在,你将退出!');
		return 'Error';
	}
	elsif (@steps != 1){
		my $srep_filter = $PAR->{step_filter} ? $PAR->{step_filter} : '.*';
        my @tmp_steps = grep(/$srep_filter/,@steps);
		if ( @tmp_steps == 0 ) {
			$GUI->msgbox(-icon=>'error',-text=>'在料号中没有过滤器中的step存在,你将退出!');
			return 'Error';
		}
        elsif ( @tmp_steps == 1 ) {
            $Step = $tmp_steps[0];
        }
        else {
            $Step = $GUI->select_step(-title=>'请选择工作Step',
                                      -steplist=>\@tmp_steps,
                                      -selectmode=>'single');
            return 'Cancel' unless ($Step);            
        }
	}
    else {
        $Step = $steps[0];
    }

	##
	update_loading("过滤层别...",0,position=>'n');
	my @work_layers = get_work_layer();
	return 'Cancel' if grep /^Cancel$/,@work_layers;

	###打开step
	$GEN->openStep(job=>$Job,name=>$Step);
	$GEN->clearLayers();
	$GEN->affectedLayer( mode=>'all',affected=>'no' );
	$GEN->COM( "sel_options,clear_mode=clear_after,display_mode=all_layers,area_inout=inside,area_select=select,select_mode=standard,area_touching_mode=exclude");
	$GEN->units(type=>'inch');
	$GEN->zoomHome();
	
	#优化参数
	my $itm_info = {
						'ref'   => {action=>'valor_cleanup_ref_subst',erf=>'STD',params=>{pp_layer=>'.affected',pp_tol=>$PAR->{tolerance}}},
						'auto'  => {action=>'valor_cleanup_auto_subst',erf=>'STD'},
	};
	
	#冒泡排序一次优先转阻焊层
	for(my $i = 0; $i < @work_layers; $i++){
		for(my $k = 0; $k < @work_layers - $i; $k++){
			if ($matrix{$work_layers[$k]}{layer_type} ne 'solder_mask' and $matrix{$work_layers[$k+1]}{layer_type} eq 'solder_mask'){
				my $tmp = $work_layers[$k];
				$work_layers[$k] = $work_layers[$k+1];
				$work_layers[$k+1] = $tmp;
			}
		}
	}
	
	foreach my $layer (@work_layers) {
		#备份层
		my $bak_layer = $layer.$PAR->{bak_layer_pad};
		$GEN->createLayer(job=>$Job,layer=>$bak_layer,context=>'misc',type=>'document',delete_exists=>'yes');
		$GEN->copyLayer(source_job=>$Job,source_step=>$Step,source_layer=>$layer,dest_layer=>$bak_layer,mode=>'replace',invert=>'no');
		#外层要参考阻焊层转PAD
		my $mask_tmp_layer;
		if($matrix{$layer}{tl_type} eq 'outer'){
			foreach my $lay (sort {$matrix{$a}{row} <=> $matrix{$b}{row}}  keys %matrix) {
				if($matrix{$lay}{tl_type} eq 'solder_mask' and $matrix{$lay}{side} eq $matrix{$layer}{side}){
					$mask_tmp_layer = $lay;
				}
			}
			if(defined($mask_tmp_layer)){
				$GEN->affectedLayer(affected=>'yes',layer=>$mask_tmp_layer,clear_before=>'yes');
				$GEN->selectByFilter(feat_types=>'line\;arc',min_len=>0.004,max_len=>$PAR->{max_pad_size}/1000,polarity=>'positive',profile=>'all');
				if($GEN->getSelectCount() > 0){
					$GEN->displayLayer(name=>$mask_tmp_layer,number=>1);
					$GUI->msgbox(-icon=>'info',-text=>"阻焊层 $mask_tmp_layer 中含有规则物件!会影响 $layer 层转PAD效果,请确认。。。");
					$GEN->PAUSE('Please,Check Layer Features!');
					$GEN->COM('sel_clear_feat');
				}
			}
		}

		$GEN->affectedLayer(affected=>'yes',layer=>$layer,clear_before=>'yes');
		if($matrix{$layer}{tl_type} eq 'outer'){
			$GEN->runSingleDfm(
								chklist => $itm_info->{auto}{action},
								erf     => $itm_info->{auto}{erf},
								show_res=> 'no',
								params  => {
											   pp_layer  =>'.affected',  	 pp_in_selected=>'All',
											   pp_min_smd=>0.001,		 	 pp_max_smd=>$PAR->{max_pad_size},
											   pp_tol	 =>$PAR->{tolerance},pp_ref_sm=>$mask_tmp_layer,
											   pp_auto_ref=>'Auto Ref.',	 pp_sm_margin=>0,
											   pp_drill_margin=>0,			 pp_work=>'Features',
											   pp_construct=>'No'
								}
			);
		}else{
			$GEN->runSingleDfm(
								chklist => $itm_info->{auto}{action},
								erf     => $itm_info->{auto}{erf},
								show_res=> 'no',
								params  => {
											   pp_layer  =>'.affected',  	 pp_in_selected=>'All',
											   pp_min_smd=>0.004,		 	 pp_max_smd=>$PAR->{max_pad_size},
											   pp_tol	 =>$PAR->{tolerance},pp_ref_sm=>'',
											   pp_auto_ref=>'',				 pp_sm_margin=>0,
											   pp_drill_margin=>0,			 pp_work=>'Features',
											   pp_construct=>'No',
								}
			);
		}

		#全部是PAD的时候不需要手动操作
		$GEN->selectByFilter(polarity=>'positive',profile=>'all');
		$GEN->selectByFilter(feat_types=>'pad',operation=>'unselect');
		next unless ($GEN->getSelectCount());
		$GEN->COM('sel_clear_feat');
		$GEN->workLayer(name=>$layer,display_number=>1,clear_before=>'yes');
		$GEN->highlightByFilter(feat_types=>'pad',polarity=>'positive',profile=>'all');
		update_loading("请仔细检查 $layer 当前PAD,框选需要转PAD的物件,无需转PAD时框选空白结束...",0,position=>'n');
		while(1){
			my %mouse_area = $GEN->MOUSE(type=>'r',text=>'Please Select The Construct Pad Feature');
			$GEN->selectRectangle(x1=>$mouse_area{x1},y1=>$mouse_area{y1},x2=>$mouse_area{x2},y2=>$mouse_area{y2});
			unless ($GEN->getSelectCount()){
				$GEN->clearHighlight();
				last ;
			}else{
				$GEN->runSingleDfm(
						chklist  => $itm_info->{ref}{action},
						erf      => $itm_info->{ref}{erf},
						params   => $itm_info->{ref}{params},
						show_res => 'no'
				);
				$GEN->clearHighlight();
				$GEN->highlightByFilter(feat_types=>'pad',polarity=>'positive',profile=>'all');
			}
		}
	}

    ###output and return status, if genesis error, it will output genesis error command
	unless ($GEN->{STATUS}){
		return $Report;
	}
	else{
		$GUI->msgbox(-icon=>'error',-text=>join("\n",@{$GEN->{STATUS}}));
		addFlowNotes(-notes=>"   Genesis Error:\n ".join("\n   ",@{$GEN->{STATUS}}));
		return 'Error';
	}
}

catch Error::Simple with {
	my $error = shift;
	$GUI->msgbox(-icon=>'error',-text=>$error);
	return 'Error';
}

finally{
	$GEN->affectedLayer( mode=>'all',affected=>'no');

};


sub get_work_layer{	
	# 获取工作层
	my %matrix = $GEN->getMatrix(job=>$Job,type=>'hash');
	foreach my $layer (sort {$matrix{$a}{row} <=> $matrix{$b}{row}}  keys %matrix) {
		if(defined($matrix{$layer}{context}) and $matrix{$layer}{context} eq 'board' ){
			if(defined($matrix{$layer}{layer_type}) and ($matrix{$layer}{layer_type} eq 'solder_mask' or $matrix{$layer}{layer_type} eq 'signal')){
				push @work_layers,$layer;
			}
		}
	}
	##
	my %tmp_matrix;
	foreach my $layer (@work_layers) {
		$tmp_matrix{$layer} = $matrix{$layer};
	}	
	
	if (@work_layers > 1) {
		@work_layers = $GUI->select_layer(
			-title=>'请选择工作层别',
			-layermatrix=>\%tmp_matrix,
			-selectmode => 'multiple');#single
		return 'Cancel' unless(@work_layers);
	}
	else {
		@work_layers = @work_layers;
	}
	return @work_layers;
}