=head NAME: TL_PUB_create_impedance_coupon DESCRIPTION: 绘制阻抗图形 PARAMETER: [ ] VERSION_HISTORY: V1.00 2011-12-03 Tony Guo New Version V1.01 2013-06-09 Tony Guo Fixed bug when coplanar and normal impeance in same test coupon V1.02 2016-11-25 Bill Li 获取到的线宽间距等单位转换um2mil. V1.03 2016-11-25 Cody Yu 1.阻抗条长度和宽度取出来,不用/25.4 V1.04 2016-12-06 Cody Yu 1.阻抗线增加补偿 V2.00 2017-06-22 Tomy 1.转为EPQ版本,inch|mm用于设定阻抗表单存的coupon条size单位 mm时要除以25.4 V2.01 2017-09-21 Cody 1.文件存储改为string存储 V2.02 2017-09-22 Tomy 1.增加挡墨和防焊开窗,钻孔层定为dir层 V3.00 2017-10-26 Cody 1.产品升级到V6 V3.01 2017-12-14 Shyer 1.coupon线补偿带小数位修复 2.阻抗条尺寸公英制转换小数位异常修复 V3.02 2017-12-15 Shyer 1.共面阻抗铜面增加补偿(同线宽补偿) V3.03 2018-01-08 Tomy 1._um2mil公制转英制取消取三位小数 V3.04 2019-04-16 Shyer 1.新增单层body text位置获取 V3.05 2020-07-29 Kurri 1.body text修改为仅外层Top面添加 2.档点层别名支持做${layer_count}变量替换 V3.06 2020-11-30 Kurri 1.档点层改为正片 HELP: =cut use strict; use utf8; use Encode; use JSON; use Data::Dump 'dump'; my ($Job,$LayerCount,$Return,$WarningMsg,$units); $units = "inch"; #$units = "mm"; use_module("PubFunction"); my $F = PubFunction->new(); my $db_units = 'um'; # 数据库中存的线宽间距的单位 (um|mil) my $coupon_size_units='mm'; #inch|mm用于设定阻抗表单存的coupon条size单位 mm时要除以25.4 try{ unless ($JOB){ $JOB = $GUI->select_job(-title=>'请选择料号',-joblist=>$IKM->select_fieldarray(-table=>'pdm_job',-field=>'jobname',-order=>'id DESC')); return 'Cancel' unless $JOB; }; $JOB_ID = $IKM->get_job_id($JOB) unless $JOB_ID; $Job = lc($JOB) unless $Job ; ## if (! $GEN->isJobExists(job=>$Job) ){ $GUI->msgbox(-icon=>'error',-text=>"料号 $Job 在Genesis中不存在, 请检查!"); return 'Error'; } ## $Return = 'Done'; use_module('ImpCouponData'); #获取数据库里的料号层数 my $dbLayerCount = $IKM->get_jobinfo(-jobinfo=>'layer_count',-jobid=>$JOB_ID); #$dbLayerCount = 10; #检查DB上的层总数是否与genesis一致 $LayerCount = $GEN->getLayerCount(job=>$Job); if ( $dbLayerCount and $LayerCount != $dbLayerCount){ return 'Error' if ($GUI->confirm('Genesis料号里的板层数与数据内不一致,你确定要继续吗?') eq 'no'); } #$LayerCount = 10; #选择需要运行的coupon my $imps = $IKM->select_arrayhash(-table=>'pdm_job_imp',-field=>['target_impedance','coupon_name'],-where=>{job_id=>$JOB_ID}); unless(@$imps){ $GUI->msgbox(-icon=>'error',-text=>"料号 $Job 中没有阻抗信息, 请检查是否有录入!"); return 'Error'; } my (@coupon_list,@sel_coupons); my %coupons; foreach my $imp (@$imps){ my @cp_names = split(',',$imp->{coupon_name}); foreach my $cp_name (@cp_names){ $coupons{$cp_name}{$imp->{target_impedance}} = 1; } } foreach my $cp (sort keys %coupons){ push @coupon_list,$cp,uc($cp); #push @coupon_list,$cp,'< '.$cp.' > '.join(' | ',sort{$a <=> $b} keys %{$coupons{$cp}}); push @sel_coupons,$cp; } my %vform = $GUI->show_form( -defaultsize=>[350,400], -title => '请选择阻抗条', -items => [ {name=>'title1',type=>'frame',property=>{}}, { name => 'coupons', type => 'checkbox', property => { tl_list => \@coupon_list, tl_columns => 1, }, value => \@sel_coupons, }, { name => 'btn', label => '', type => 'label', button_position => 'left', buttons => [ {name=>'btn_sel_all',label=>'全选',command=>sub{ my %par = @_; $par{formpanel}->set_value('coupons',\@sel_coupons); }}, {name=>'btn_unsel_all',label=>'取消全选',command=>sub{ my %par = @_; $par{formpanel}->set_value('coupons',undef); }}, ] }, {name=>'title2',type=>'vbox',property=>{},overback=>1}, { name => 'show_form', label => '显示参数确认界面', type => 'radio', property => { tl_list => ['yes'=>'YES','no'=>'NO'], tl_columns => 3, }, value => 'no', } ] ); return 'Cancel' unless %vform; @sel_coupons = @{$vform{coupons}}; return 'Cancel' unless @sel_coupons; #查找HDI钻孔层 my $matrix = $GEN->getMatrix(job=>$Job,type=>'hash'); foreach my $cp_name (sort @sel_coupons){ my $COUPON_DATA; $COUPON_DATA->{coupon_name} = $cp_name; #foreach my $info ('coupon_length','coupon_width','coupon_template','coupon_position','coupon_layout_parameter'){ #$COUPON_DATA->{coupon_template} = $IKM->get_layerinfo(-jobid=>$JOB_ID,-layer=>$cp_name,-layerinfo=>'coupon_template_name'); #} $COUPON_DATA->{coupon_template} = 'coupon'; # FOR test #$IKM->command('function(){APP.setDebugMode(5)}',{},0); my $cfg = $IKM->select_value(-table=>'pub_conf',-field=>'json_data',-where=>{path => 'pdm/impedance_coupon_template'}); #$GUI->msgbox(-text=>dump($cfg)); # 转换配置 json2perl #my $file = ${ENV}{GENESIS_TMP}.'/impedance_coupon_template'; #$file = '>'.$file; #open(MF,$file); #print MF $cfg; #close MF; #$file = ${ENV}{GENESIS_TMP}.'/impedance_coupon_template'; #my $_data = $F->prase_file_json2perl_hash(file=>$file); my $_data = $F->prase_file_json2perl_hash(string=>$cfg); #unlink $file; #my $template_value = eval($cfg); my $template_value = $_data; foreach my $item (keys %$template_value){ $COUPON_DATA->{$item} = $template_value->{$item}; } my $layout_param = $IKM->get_layerinfo(-jobid=>$JOB_ID,-layer=>$cp_name,-layerinfo=>'coupon_layout_parameter'); if ($layout_param){ $layout_param = eval($layout_param); foreach my $k (keys %{$layout_param}){ $COUPON_DATA->{$k} = $layout_param->{$k} if defined $layout_param->{$k}; } } $COUPON_DATA->{coupon_position} = $IKM->get_layerinfo(-jobid=>$JOB_ID,-layer=>$cp_name,-layerinfo=>'coupon_on_step'); $COUPON_DATA->{fixed_fields}{coupon_position} = 1; my $cp_length = $IKM->get_layerinfo(-jobid=>$JOB_ID,-layer=>$cp_name,-layerinfo=>'coupon_length'); my $cp_length_org = eval($cp_length); if($coupon_size_units eq 'mm'){ $cp_length = sprintf("%.3f",$cp_length/25.4); } #$cp_length = $cp_length/25.4; if ($cp_length){ $COUPON_DATA->{coupon_length} = $cp_length; $COUPON_DATA->{coupon_length_org} = $cp_length_org; $COUPON_DATA->{auto_enlarge_coupon_length} = 'no'; $COUPON_DATA->{fixed_fields}{coupon_length} = 1; $COUPON_DATA->{fixed_fields}{auto_enlarge_coupon_length} = 1; } my $cp_width = $IKM->get_layerinfo(-jobid=>$JOB_ID,-layer=>$cp_name,-layerinfo=>'coupon_width'); my $cp_width_org = eval($cp_width); if($coupon_size_units eq 'mm'){ $cp_width = sprintf("%.3f",$cp_width/25.4); } #$cp_width = $cp_width/25.4; if ($cp_width){ $COUPON_DATA->{coupon_body_width} = $COUPON_DATA->{coupon_header_width} = $cp_width; $COUPON_DATA->{coupon_body_width_org} = $COUPON_DATA->{coupon_header_width_org} = $cp_width_org; $COUPON_DATA->{auto_enlarge_coupon_header_width} = 'no'; $COUPON_DATA->{auto_enlarge_coupon_body_width} = 'no'; $COUPON_DATA->{fixed_fields}{coupon_body_width} = 1; $COUPON_DATA->{fixed_fields}{coupon_header_width} = 1; $COUPON_DATA->{fixed_fields}{auto_enlarge_coupon_header_width} = 1; $COUPON_DATA->{fixed_fields}{auto_enlarge_coupon_header_width} = 1; } my $all_imps = $IKM->select_arrayhash(-table=>'pdm_job_imp',-field=>['*'],-where=>{job_id=>$JOB_ID}); foreach my $imp (@$all_imps){ $imp->{signal1} = imp_layernum2tlname($imp->{signal1}); $imp->{signal2} = imp_layernum2tlname($imp->{signal2}); $imp->{reference1} = imp_layernum2tlname($imp->{reference1}); $imp->{reference2} = imp_layernum2tlname($imp->{reference2}); $imp->{id} = $imp->{uuid}; my @cp_names = split(',',$imp->{coupon_name}); foreach my $cp_nm (@cp_names){ if ($cp_name eq $cp_nm){ if ($db_units eq 'um') { # 数据转换 um2mil by Bill 20161125 $imp->{org_line_width1} = sprintf("%.1f",_um2mil($imp->{org_line_width1})); $imp->{org_spacing} = sprintf("%.1f",_um2mil($imp->{org_spacing})); $imp->{line_width1} = sprintf("%.1f",_um2mil($imp->{line_width1})); #1 $imp->{line_width1_adjust_max} = sprintf("%.1f",_um2mil($imp->{line_width1_adjust_max})); $imp->{line_width1_adjust_min} = sprintf("%.1f",_um2mil($imp->{line_width1_adjust_min})); $imp->{spacing} = sprintf("%.1f",_um2mil($imp->{spacing})); #1 #$imp->{target_impedance_max} = _um2mil($imp->{target_impedance_max}); #$imp->{target_impedance_min} = _um2mil($imp->{target_impedance_min}); $imp->{target_impedance_max} = $imp->{target_impedance_max}; $imp->{target_impedance_min} =$imp->{target_impedance_min}; $imp->{test_line_length} = sprintf("%.1f",_um2mil($imp->{test_line_length})); #添加一个 coplanar_spacing 转换 Tomy 20170621 $imp->{coplanar_spacing} = sprintf("%.1f",_um2mil($imp->{coplanar_spacing})); #1 } push @{$COUPON_DATA->{impedances}},$imp; } } } $COUPON_DATA->{GEN} = $GEN; $COUPON_DATA->{job_id} = $JOB_ID; $COUPON_DATA->{job_name} = $JOB; my $coupon_object = Top::ImpCouponData->new(-IKM=>$IKM); $coupon_object->set_coupon_data($COUPON_DATA); $coupon_object->set_layer_count($LayerCount); $coupon_object->set_matrix($matrix); $coupon_object->coupon_to_layer(); if ($vform{show_form} eq 'yes' or !$COUPON_DATA->{coupon_template}){ return 'Cancel' unless $coupon_object->show_coupon_form(); } $coupon_object->convert_units(); $coupon_object->convert_matrix(); $coupon_object->analysis_group(); $coupon_object->line_copmensation(); $coupon_object->group_left_right(); $coupon_object->init_pad_position(); $coupon_object->adjust_coupon_length(); $coupon_object->init_line_y_sequence(); $coupon_object->calc_line_y(); $coupon_object->layout_header_lines(); $coupon_object->header_text_position(); $coupon_object->adjust_coupon_width(); my %gen_layer; foreach my $item (keys %{$COUPON_DATA->{matrix}}){ if ($COUPON_DATA->{matrix}{$item}{tl_name}){ $gen_layer{$COUPON_DATA->{matrix}{$item}{tl_name}} = $item; } } my $step = lc($cp_name); if ($GEN->isStepExists(job=>$Job,step=>$step)){ return 'Cancel' unless ($GUI->confirm("Step $step 已经存在,确定要覆盖它吗?") eq 'yes'); my @boardLayers; foreach my $item (keys %$matrix){ if ($matrix->{$item}{context} eq 'board'){ push @boardLayers,$item; } } $GEN->openStep(job=>$Job,name=>$step); $GEN->clearLayers(); $GEN->affectedLayer(mode=>'all',affected=>'yes'); $GEN->COM('sel_all_feat'); $GEN->selDelete(); } else{ $GEN->createStep(job=>$Job,name=>$step); $GEN->openStep(job=>$Job,name=>$step); } if ($COUPON_DATA->{coupon_layout_path} eq 'customize'){ $GEN->clearLayers(); $GEN->affectedLayer(mode=>'all',affected=>'no'); $GEN->PAUSE('Select Coupon Layout Path'); my $work_layer =$GEN->getWorkLayer(); my @feats = $GEN->getFeatures(job=>$Job,step=>$step,layer=>$work_layer,options=>'select',units=>'inch') if $work_layer; if (@feats){ @feats = opt_lines(@feats); my $ps = TL::GenMath->calc_point_on_line($feats[0],$COUPON_DATA->{'left_header_area_rect'}{xmax} - $COUPON_DATA->{'left_header_area_rect'}{xmin}); my $pe = TL::GenMath->calc_point_on_line({xs=>$feats[-1]{xe},ys=>$feats[-1]{ye},xe=>$feats[-1]{xs},ye=>$feats[-1]{ys}},$COUPON_DATA->{'right_header_area_rect'}{xmax} - $COUPON_DATA->{'right_header_area_rect'}{xmin}); ($feats[0]{xs},$feats[0]{ys}) = ($ps->{x},$ps->{y}); ($feats[-1]{xe},$feats[-1]{ye}) = ($pe->{x},$pe->{y}); my @line_path = ({x=>$feats[0]{xs},y=>$feats[0]{ys}}); foreach my $feat (@feats){ my $tmp = {x=>$feat->{xe},y=>$feat->{ye}}; if ($feat->{type} eq 'arc'){ @{$tmp}{'xc','yc','direction'} = @{$feat}{'xc','yc','direction'}; } push @line_path,$tmp; } $coupon_object->{COUPON_DATA}{line_path} = \@line_path; } } $coupon_object->layout_path_lines(); $coupon_object->body_text_position(); $coupon_object->layer_body_text_position(); $coupon_object->coplanar_hole_position(); #$GUI->debug(dump($COUPON_DATA)); $GEN->COM('disp_off'); #$GEN->COM('disp_on'); $GEN->clearLayers(); $GEN->affectedLayer(mode=>'all',affected=>'no'); $GEN->units(type=>$units); #创建Profile my ($ShiftX,$ShiftY) = (-$COUPON_DATA->{left_down_zero_pad}{x},-$COUPON_DATA->{left_down_zero_pad}{y}); my $trans; $trans->{left}{angle} = 360-$COUPON_DATA->{left_header_transform}{angle}; $trans->{left}{angle} -= 360 if $trans->{left}{angle} >= 360; $trans->{left}{x_anchor} = $COUPON_DATA->{left_header_transform}{x} + $ShiftX; $trans->{left}{y_anchor} = $COUPON_DATA->{left_header_transform}{y} + $ShiftY; $trans->{right}{angle} = 360-$COUPON_DATA->{right_header_transform}{angle}; $trans->{right}{angle} -= 360 if $trans->{right}{angle} >= 360; $trans->{right}{x_anchor} = $COUPON_DATA->{right_header_transform}{x} + $ShiftX; $trans->{right}{y_anchor} = $COUPON_DATA->{right_header_transform}{y} + $ShiftY; my $tmp_layer = 'tl_script_tmp_layer'; if ($COUPON_DATA->{coupon_layout_path} eq 'customize'){ $GEN->deleteLayer(job=>$Job,layer=>$tmp_layer); $GEN->createLayer(job=>$Job,layer=>$tmp_layer,context=>'misc',type=>'signal'); $GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>$tmp_layer,clear_before=>'yes'); my ($xs,$ys) = ($COUPON_DATA->{center_path_lines}[0]{x},$COUPON_DATA->{center_path_lines}[0]{y}); my $sym = 'r'.($COUPON_DATA->{coupon_body_width}*1000); foreach my $n (1..scalar(@{$COUPON_DATA->{center_path_lines}})-1){ my $it = $COUPON_DATA->{center_path_lines}[$n]; if ($it->{direction}){ $GEN->addArc(xs=>$xs+$ShiftX,ys=>$ys+$ShiftY,xe=>$it->{x}+$ShiftX,ye=>$it->{y}+$ShiftY,xc=>$it->{xc}+$ShiftX,yc=>$it->{yc}+$ShiftY,direction=>$it->{direction},symbol=>$sym); } else{ $GEN->addLine(xs=>$xs+$ShiftX,ys=>$ys+$ShiftY,xe=>$it->{x}+$ShiftX,ye=>$it->{y}+$ShiftY,symbol=>$sym); } ($xs,$ys) = ($it->{x},$it->{y}); } my $clip_w = $COUPON_DATA->{coupon_body_width} + 0.0002; $GEN->addPad(x=>$COUPON_DATA->{left_zero_pad}{x}-$clip_w/2+$ShiftX,y=>$COUPON_DATA->{left_zero_pad}{y}+$ShiftY,symbol=>'s'.($clip_w*1000), polarity=>'negative',attributes=>{attribute=>'.string',text=>'left_side'}); $GEN->addPad(x=>$COUPON_DATA->{right_zero_pad}{x}+$clip_w/2+$ShiftX,y=>$COUPON_DATA->{right_zero_pad}{y}+$ShiftY,symbol=>'s'.($clip_w*1000), polarity=>'negative',attributes=>{attribute=>'.string',text=>'right_side'}); foreach my $lr ('left','right'){ $GEN->addRectangle(x1=>$COUPON_DATA->{$lr.'_header_area_rect'}{xmin}+$ShiftX,y1=>$COUPON_DATA->{$lr.'_header_area_rect'}{ymin}+$ShiftY, x2=>$COUPON_DATA->{$lr.'_header_area_rect'}{xmax}+$ShiftX,y2=>$COUPON_DATA->{$lr.'_header_area_rect'}{ymax}+$ShiftY, attributes=>{attribute=>'.string',text=>$lr.'_side'} ) if ($COUPON_DATA->{$lr.'_header_area_rect'}); } foreach my $lr ('left','right'){ if ($trans->{$lr}{angle}){ $GEN->selClearFeature(); $GEN->selectByFilter(attribute=>[{attribute=>'.string',text=>$lr.'_side'}]); $GEN->COM('sel_transform',mode=>'anchor',oper=>'rotate',duplicate=>'no',%{$trans->{$lr}}) ; } } $GEN->COM('sel_all_feat'); $GEN->selContourize(); $GEN->COM('sel_all_feat'); $GEN->COM('sel_surf2outline',width=>0.1); $GEN->COM('sel_all_feat'); $GEN->COM('sel_create_profile'); $GEN->deleteLayer(job=>$Job,layer=>$tmp_layer); } else{ if($coupon_size_units eq 'mm'){ $GEN->units(type=>$coupon_size_units); $GEN->panelSize(width=>$COUPON_DATA->{coupon_length_org},height=>$COUPON_DATA->{coupon_body_width_org}); $GEN->units(type=>$units); }else{ $GEN->panelSize(width=>$COUPON_DATA->{coupon_length},height=>$COUPON_DATA->{coupon_body_width}); } } my $outer_tpad_sym = $COUPON_DATA->{outer_tpad_shape} . $COUPON_DATA->{pad_size}; my $inner_tpad_sym = $COUPON_DATA->{inner_tpad_shape} . $COUPON_DATA->{pad_size}; my $outer_gpad_sym = $COUPON_DATA->{outer_gpad_shape} . $COUPON_DATA->{pad_size}; my $inner_gpad_sym = $COUPON_DATA->{inner_gpad_shape} . $COUPON_DATA->{pad_size}; my $outer_tpad_clear_sym = $COUPON_DATA->{outer_tpad_shape} . ($COUPON_DATA->{pad_size} + $COUPON_DATA->{outer_pad2copper} * 2); my $inner_tpad_clear_sym = $COUPON_DATA->{inner_tpad_shape} . ($COUPON_DATA->{pad_size} + $COUPON_DATA->{inner_pad2copper} * 2); my $outer_gpad_clear_sym = $COUPON_DATA->{outer_gpad_shape} . ($COUPON_DATA->{pad_size} + $COUPON_DATA->{outer_pad2copper} * 2); my $inner_gpad_clear_sym = $COUPON_DATA->{inner_gpad_shape} . ($COUPON_DATA->{pad_size} + $COUPON_DATA->{inner_pad2copper} * 2); my $outer_tdrl_clear_sym = $COUPON_DATA->{outer_tpad_shape} . ($COUPON_DATA->{hole_size} + $COUPON_DATA->{drill2copper} * 2); my $inner_tdrl_clear_sym = $COUPON_DATA->{inner_tpad_shape} . ($COUPON_DATA->{hole_size} + $COUPON_DATA->{drill2copper} * 2); my $outer_gdrl_clear_sym = $COUPON_DATA->{outer_gpad_shape} . ($COUPON_DATA->{hole_size} + $COUPON_DATA->{drill2copper} * 2); my $inner_gdrl_clear_sym = $COUPON_DATA->{inner_gpad_shape} . ($COUPON_DATA->{hole_size} + $COUPON_DATA->{drill2copper} * 2); #patch_ref_sym #填补影响层上漏出线路时用 my $max_clear = (sort {$b <=> $a} ($COUPON_DATA->{pad_size} + 2*$COUPON_DATA->{outer_pad2copper}, $COUPON_DATA->{pad_size} + 2*$COUPON_DATA->{inner_pad2copper}, $COUPON_DATA->{hole_size} + 2*$COUPON_DATA->{drill2copper}))[0] + 2; my $outer_patch_ref_clear_sym = $COUPON_DATA->{outer_tpad_shape} . $max_clear; my $inner_patch_ref_clear_sym = $COUPON_DATA->{outer_tpad_shape} . $max_clear; my $tmp_size = ($COUPON_DATA->{pad_size} + $COUPON_DATA->{outer_pad2copper} * 2); my $outer_gpad_thermal_sym = $COUPON_DATA->{outer_gpad_thermal}; $outer_gpad_thermal_sym =~ s/\$\{OUT\}/$tmp_size/; $tmp_size = $COUPON_DATA->{pad_size}; $outer_gpad_thermal_sym =~ s/\$\{IN\}/$tmp_size/; $tmp_size = ($COUPON_DATA->{pad_size} + $COUPON_DATA->{inner_pad2copper} * 2); my $inner_gpad_thermal_sym = $COUPON_DATA->{inner_gpad_thermal}; $inner_gpad_thermal_sym =~ s/\$\{OUT\}/$tmp_size/; $tmp_size = $COUPON_DATA->{pad_size}; $inner_gpad_thermal_sym =~ s/\$\{IN\}/$tmp_size/; foreach my $layer_number (1 .. $COUPON_DATA->{layer_count}){ my $tl_name; if ($layer_number == 1){ $tl_name = 'top'; } elsif($layer_number == $COUPON_DATA->{layer_count}){ $tl_name = 'bottom'; } else{ $tl_name = 'l'.$layer_number; } my $layer_name = $gen_layer{$tl_name}; my $layer_matrix = $matrix->{$layer_name}; my $layer_polarity = $layer_matrix->{polarity}; my $layer_polarity_n = ($layer_polarity eq 'positive')?'negative':'positive'; #my $layer_side = ($layer_number <= $COUPON_DATA->{layer_count}/2)?'front':'back'; my $layer_side ; if ($layer_number == 1) { $layer_side = 'front'; }elsif( $layer_number == $COUPON_DATA->{layer_count}){ $layer_side = 'back'; }else{ $layer_side = $layer_number%2 ? 'back':'front'; } my ($layer_tpad_sym,$layer_gpad_sym,$layer_tpad_clear_sym,$layer_gpad_clear_sym, $layer_tdrl_clear_sym,$layer_gdrl_clear_sym,$layer_gpad_thermal_sym,$layer_patch_ref_clear_sym); if ($layer_number == 1 or $layer_number == $COUPON_DATA->{layer_count}){ $layer_tpad_sym = $outer_tpad_sym; $layer_gpad_sym = $outer_gpad_sym; $layer_tpad_clear_sym = $outer_tpad_clear_sym; $layer_gpad_clear_sym = $outer_gpad_clear_sym; $layer_tdrl_clear_sym = $outer_tdrl_clear_sym; $layer_gdrl_clear_sym = $outer_gdrl_clear_sym; $layer_gpad_thermal_sym = $outer_gpad_thermal_sym; $layer_patch_ref_clear_sym = $outer_patch_ref_clear_sym; } else{ $layer_tpad_sym = $inner_tpad_sym; $layer_gpad_sym = $inner_gpad_sym; $layer_tpad_clear_sym = $inner_tpad_clear_sym; $layer_gpad_clear_sym = $inner_gpad_clear_sym; $layer_tdrl_clear_sym = $inner_tdrl_clear_sym; $layer_gdrl_clear_sym = $inner_gdrl_clear_sym; $layer_gpad_thermal_sym = $inner_gpad_thermal_sym; $layer_patch_ref_clear_sym = $inner_patch_ref_clear_sym; } #layer type my $layer_type; foreach my $imp_layer (values %{$COUPON_DATA->{layers}}){ if ($imp_layer->{layer_number} == $layer_number){ $layer_type = $imp_layer->{layer_type}; last; } } #层属于哪些group my @layer_blong_grps; foreach my $grp (keys %{$COUPON_DATA->{group}}){ foreach my $lyr (@{$COUPON_DATA->{group}{$grp}{all_layer}}){ if ($COUPON_DATA->{layers}{$lyr}{layer_number} == $layer_number){ push @layer_blong_grps , $grp unless grep({$_ eq $grp} @layer_blong_grps); } } } #层包含的group my @layer_include_grps; foreach my $drill (values %{$COUPON_DATA->{drills}}){ if ($drill->{drl_start_num} == $layer_number or $drill->{drl_end_num} == $layer_number){ @layer_include_grps = @{$drill->{include_coupon_groups}} if $drill->{include_coupon_groups}; last; } } $GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>$layer_name,clear_before=>'yes'); #铺背景铜, if ($layer_polarity eq 'negative'){ $GEN->srFill(layer=>$layer_name,step_margin_x=>-$COUPON_DATA->{neg_copper_margin}/1000,step_margin_y=>-$COUPON_DATA->{neg_copper_margin}/1000,polarity=>$layer_polarity_n); } $GEN->srFill(layer=>$layer_name,step_margin_x=>$COUPON_DATA->{rout2copper_spacing}/1000,step_margin_y=>$COUPON_DATA->{rout2copper_spacing}/1000,polarity=>$layer_polarity); #添加信号线隔离; if ($layer_type =~ /^(S|B)$/){ my $grp = $layer_blong_grps[0]; #为信号层和空层添加信号组隔离线 foreach my $imp_lyr (@{$COUPON_DATA->{group}{$grp}{signal_layer}}){ my $imp_layer = $COUPON_DATA->{layers}{$imp_lyr}; my $sym = 'r'.($imp_layer->{cam_line_width}+$imp_layer->{imp_line2copper}*2-$imp_layer->{default_compensation}); foreach my $m ('lines1','lines2'){ if ($imp_layer->{$m} and @{$imp_layer->{$m}}){ my ($xs,$ys) = ($imp_layer->{$m}[0]{x},$imp_layer->{$m}[0]{y}); foreach my $n (1..scalar(@{$imp_layer->{$m}})-1){ my $it = $imp_layer->{$m}[$n]; if ($it->{direction}){ $GEN->addArc(xs=>$xs+$ShiftX,ys=>$ys+$ShiftY,xe=>$it->{x}+$ShiftX,ye=>$it->{y}+$ShiftY,xc=>$it->{xc}+$ShiftX,yc=>$it->{yc}+$ShiftY,direction=>$it->{direction},symbol=>$sym,polarity=>$layer_polarity_n); } else{ $GEN->addLine(xs=>$xs+$ShiftX,ys=>$ys+$ShiftY,xe=>$it->{x}+$ShiftX,ye=>$it->{y}+$ShiftY,symbol=>$sym,polarity=>$layer_polarity_n); } ($xs,$ys) = ($it->{x},$it->{y}); } } } if ($imp_layer->{center_lines} and @{$imp_layer->{center_lines}}){ my ($xs,$ys) = ($imp_layer->{center_lines}[0]{x},$imp_layer->{center_lines}[0]{y}); foreach my $n (1..scalar(@{$imp_layer->{center_lines}})-1){ my $it = $imp_layer->{center_lines}[$n]; if ($it->{direction}){ $GEN->addArc(xs=>$xs+$ShiftX,ys=>$ys+$ShiftY,xe=>$it->{x}+$ShiftX,ye=>$it->{y}+$ShiftY,xc=>$it->{xc}+$ShiftX,yc=>$it->{yc}+$ShiftY,direction=>$it->{direction},symbol=>'r'.$imp_layer->{cam_total_width},polarity=>$layer_polarity_n); } else{ $GEN->addLine(xs=>$xs+$ShiftX,ys=>$ys+$ShiftY,xe=>$it->{x}+$ShiftX,ye=>$it->{y}+$ShiftY,symbol=>'r'.$imp_layer->{cam_total_width},polarity=>$layer_polarity_n); } ($xs,$ys) = ($it->{x},$it->{y}); } } #aoi pad 隔离 if ($COUPON_DATA->{add_aoi_pad} eq 'yes'){ my $sym; if ($imp_layer->{impedance_type} =~ /coplanar/){ $sym = 'r'.($imp_layer->{cam_line_width}+$COUPON_DATA->{aoi_pad_ar}*2+$imp_layer->{imp_line2copper}*2); } else{ $sym = 'r'.($imp_layer->{cam_line_width}+$COUPON_DATA->{aoi_pad_ar}*2+$COUPON_DATA->{aoi_pad2copper}*2); } foreach my $it (@{$imp_layer->{aoi_pads}}){ $GEN->addPad(x=>$it->{x}+$ShiftX,y=>$it->{y}+$ShiftY,symbol=>$sym,polarity=>$layer_polarity_n); } } } } #文字隔离 if ($COUPON_DATA->{body_text_polarity} eq 'positive'){ if ($COUPON_DATA->{body_text_pos}{$tl_name} and !$COUPON_DATA->{'body_text_not_enought_space'}{$tl_name}){ my $n = 0; foreach my $text (@{$COUPON_DATA->{body_text_pos}{$tl_name}}){ $n++; $GEN->addRectangle(x1=>$text->{xmin}-$COUPON_DATA->{body_text_free_x}/1000+$ShiftX, y1=>$text->{ymin}-$COUPON_DATA->{body_text_free_y}/1000+$ShiftY, x2=>$text->{xmax}+$COUPON_DATA->{body_text_free_x}/1000+$ShiftX, y2=>$text->{ymax}+$COUPON_DATA->{body_text_free_y}/1000+$ShiftY, attributes=>{attribute=>'.string',text=>'body_text_clear_'.$n}, polarity=>$layer_polarity_n, ); if ($text->{angle}){ my $angle = -$text->{angle}; $angle = 360 + $angle if $angle < 0; $GEN->selClearFeature(); $GEN->selectByFilter(attribute=>[{attribute=>'.string',text=>'body_text_clear_'.$n}]); $GEN->COM('sel_transform',mode=>'anchor',oper=>'rotate',duplicate=>'no', x_anchor=>$text->{bx}+$ShiftX,y_anchor=>$text->{by}+$ShiftY, angle=>$angle,x_scale=>1,y_scale=>1,x_offset=>0,y_offset=>0) if $GEN->getSelectCount();; } } } } #添加pin hole clearance my $pin_clear_symbol = 'r'.($COUPON_DATA->{pin_hole_size} + 2*$COUPON_DATA->{pin_hole_clearance}); foreach my $lr ('left','right'){ if ($COUPON_DATA->{$lr.'_pin_hole'}){ $GEN->addPad(x=>$COUPON_DATA->{$lr.'_pin_hole'}{x}+$ShiftX,y=>$COUPON_DATA->{$lr.'_pin_hole'}{y}+$ShiftY,symbol=>$pin_clear_symbol,polarity=>$layer_polarity_n); } } #添加test pad隔离 foreach my $grp (keys %{$COUPON_DATA->{group}}){ my $tmp_tst_clear_sym; if (($layer_type eq 'S' and grep({$_ eq $grp} @layer_blong_grps)) or grep({$_ eq $grp} @layer_include_grps)){ # $tmp_tst_clear_sym = $layer_tpad_clear_sym; } else{ $tmp_tst_clear_sym = $layer_tdrl_clear_sym; } foreach my $imp_lyr (@{$COUPON_DATA->{group}{$grp}{signal_layer}}){ my $imp_layer = $COUPON_DATA->{layers}{$imp_lyr}; foreach my $lr ('left','right'){ if ($imp_layer->{$lr.'_tpads'}){ foreach my $it (@{$imp_layer->{$lr.'_tpads'}}){ $GEN->addPad(x=>$it->{x}+$ShiftX,y=>$it->{y}+$ShiftY,symbol=>$tmp_tst_clear_sym,polarity=>$layer_polarity_n,attributes=>{attribute=>'.string',text=>$lr.'_clear_pad'}); } } } } } #添加gnd pad隔离 if ($layer_type =~ /^(S|B)$/){ if ($COUPON_DATA->{is_coplanar}){ foreach my $grp (keys %{$COUPON_DATA->{group}}){ foreach my $imp_lyr (@{$COUPON_DATA->{group}{$grp}{signal_layer}}){ my $imp_layer = $COUPON_DATA->{layers}{$imp_lyr}; my ($tmp_sym,$tmp_polarity); if (grep({$grp eq $_} @layer_blong_grps)){ if ($imp_layer->{impedance_type} =~ /coplanar/i){ $tmp_sym = $layer_gpad_sym;$tmp_polarity = $layer_polarity; } else{ $tmp_sym = $layer_gpad_clear_sym; $tmp_polarity = $layer_polarity_n; } } elsif(grep({$grp eq $_} @layer_include_grps)){ $tmp_sym = $layer_gpad_clear_sym; $tmp_polarity = $layer_polarity_n; } else{ $tmp_sym = $layer_gdrl_clear_sym; $tmp_polarity = $layer_polarity_n; } foreach my $lr ('left','right') { if ($imp_layer->{$lr.'_gpads'}) { foreach my $it (@{$imp_layer->{$lr.'_gpads'}}) { $GEN->addPad(x=>$it->{x}+$ShiftX,y=>$it->{y}+$ShiftY,symbol=>$tmp_sym,polarity=>$tmp_polarity,attributes=>{attribute=>'.string',text=>$lr.'_clear_pad'}); } } } } } } else{ foreach my $grp (keys %{$COUPON_DATA->{group}}){ my ($tmp_sym,$tmp_polarity); if(grep({$grp eq $_} @layer_include_grps)){ $tmp_sym = $layer_gpad_clear_sym; $tmp_polarity = $layer_polarity_n; } else{ $tmp_sym = $layer_gdrl_clear_sym; $tmp_polarity = $layer_polarity_n; } foreach my $imp_lyr (@{$COUPON_DATA->{group}{$grp}{signal_layer}}){ my $imp_layer = $COUPON_DATA->{layers}{$imp_lyr}; foreach my $lr ('left','right'){ if ($imp_layer->{$lr.'_gpads'}){ foreach my $it (@{$imp_layer->{$lr.'_gpads'}}){ $GEN->addPad(x=>$it->{x}+$ShiftX,y=>$it->{y}+$ShiftY,symbol=>$tmp_sym,polarity=>$tmp_polarity,attributes=>{attribute=>'.string',text=>$lr.'_clear_pad'}); } } } } } if ((($layer_number == 1 or $layer_number == $COUPON_DATA->{layer_count}) and $COUPON_DATA->{header_copper_fill} !~ /outer/) or (($layer_number != 1 and $layer_number != $COUPON_DATA->{layer_count}) and $COUPON_DATA->{header_copper_fill} !~ /inner/)) { foreach my $lr ('left','right'){ $GEN->addRectangle(x1=>$COUPON_DATA->{$lr.'_header_copper_clip'}{xmin}+$ShiftX,y1=>$COUPON_DATA->{$lr.'_header_copper_clip'}{ymin}+$ShiftY, x2=>$COUPON_DATA->{$lr.'_header_copper_clip'}{xmax}+$ShiftX,y2=>$COUPON_DATA->{$lr.'_header_copper_clip'}{ymax}+$ShiftY, attributes=>{attribute=>'.string',text=>$lr.'_clear_pad'},polarity=>$layer_polarity_n ) if ($COUPON_DATA->{$lr.'_header_copper_clip'} and abs($COUPON_DATA->{$lr.'_header_copper_clip'}{xmax} - $COUPON_DATA->{$lr.'_header_copper_clip'}{xmin}) > 0.001); } } else{ if ((($layer_number == 1 or $layer_number == $COUPON_DATA->{layer_count}) and $COUPON_DATA->{header_clear_p2p_copper} =~ /outer/) or (($layer_number != 1 and $layer_number != $COUPON_DATA->{layer_count}) and $COUPON_DATA->{header_clear_p2p_copper} =~ /inner/)) { #刮Pad中间的残铜 my $tmp_resize; if ($layer_number == 1 or $layer_number == $COUPON_DATA->{layer_count}){ $tmp_resize = $COUPON_DATA->{pad_size}/2000 + $COUPON_DATA->{outer_pad2copper}/1000; } else{ $tmp_resize = $COUPON_DATA->{pad_size}/2000 + $COUPON_DATA->{inner_pad2copper}/1000; } foreach my $lr ('left','right'){ my @tmp_x; my @tmp_y; foreach my $grp (keys %{$COUPON_DATA->{group}}){ foreach my $imp_lyr (@{$COUPON_DATA->{group}{$grp}{signal_layer}}){ my $imp_layer = $COUPON_DATA->{layers}{$imp_lyr}; foreach my $tg ('tpads','gpads'){ if ($imp_layer->{$lr.'_'.$tg}){ foreach my $it (@{$imp_layer->{$lr.'_'.$tg}}){ push @tmp_x, $it->{x} + $tmp_resize; push @tmp_x, $it->{x} - $tmp_resize; push @tmp_y, $it->{y} + $tmp_resize; push @tmp_y, $it->{y} - $tmp_resize; } } } } } @tmp_x = sort{$a <=> $b} @tmp_x; @tmp_y = sort{$a <=> $b} @tmp_y; my $min_x = $tmp_x[0]; my $min_y = $tmp_y[0]; my $max_x = $tmp_x[-1]; my $max_y = $tmp_y[-1]; if ($max_x - $min_x > 0.0001 and $max_y - $min_y > 0.0001){ $GEN->addRectangle(x1=>$min_x+$ShiftX,y1=>$min_y+$ShiftY, x2=>$max_x+$ShiftX,y2=>$max_y+$ShiftY, attributes=>{attribute=>'.string',text=>$lr.'_clear_pad'},polarity=>$layer_polarity_n ); } } } } } } elsif($layer_type eq 'R'){ foreach my $grp (keys %{$COUPON_DATA->{group}}){ my ($tmp_sym,$tmp_polarity); if (grep({$grp eq $_} @layer_blong_grps)){ $tmp_sym = $layer_gpad_sym;$tmp_polarity = $layer_polarity; } elsif(grep({$grp eq $_} @layer_include_grps)){ $tmp_sym = $layer_gpad_clear_sym; $tmp_polarity = $layer_polarity_n; } else{ $tmp_sym = $layer_gdrl_clear_sym; $tmp_polarity = $layer_polarity_n; } foreach my $imp_lyr (@{$COUPON_DATA->{group}{$grp}{signal_layer}}){ my $imp_layer = $COUPON_DATA->{layers}{$imp_lyr}; foreach my $lr ('left','right'){ if ($imp_layer->{$lr.'_gpads'}){ foreach my $it (@{$imp_layer->{$lr.'_gpads'}}){ $GEN->addPad(x=>$it->{x}+$ShiftX,y=>$it->{y}+$ShiftY,symbol=>$tmp_sym,polarity=>$tmp_polarity,attributes=>{attribute=>'.string',text=>$lr.'_clear_pad'}); } } } } } } else{ foreach my $grp (keys %{$COUPON_DATA->{group}}){ my $tmp_gnd_clear_sym; if (grep({$_ eq $grp} @layer_include_grps)){ # $tmp_gnd_clear_sym = $layer_gpad_clear_sym; } else{ $tmp_gnd_clear_sym = $layer_gdrl_clear_sym; } foreach my $imp_lyr (@{$COUPON_DATA->{group}{$grp}{signal_layer}}){ my $imp_layer = $COUPON_DATA->{layers}{$imp_lyr}; foreach my $lr ('left','right'){ if ($imp_layer->{$lr.'_gpads'}){ foreach my $it (@{$imp_layer->{$lr.'_gpads'}}){ $GEN->addPad(x=>$it->{x}+$ShiftX,y=>$it->{y}+$ShiftY,symbol=>$tmp_gnd_clear_sym,polarity=>$layer_polarity_n,attributes=>{attribute=>'.string',text=>$lr.'_clear_pad'}); } } } } } if ((($layer_number == 1 or $layer_number == $COUPON_DATA->{layer_count}) and $COUPON_DATA->{header_copper_fill} !~ /outer/) or (($layer_number != 1 and $layer_number != $COUPON_DATA->{layer_count}) and $COUPON_DATA->{header_copper_fill} !~ /inner/)) { foreach my $lr ('left','right'){ $GEN->addRectangle(x1=>$COUPON_DATA->{$lr.'_header_copper_clip'}{xmin}+$ShiftX,y1=>$COUPON_DATA->{$lr.'_header_copper_clip'}{ymin}+$ShiftY, x2=>$COUPON_DATA->{$lr.'_header_copper_clip'}{xmax}+$ShiftX,y2=>$COUPON_DATA->{$lr.'_header_copper_clip'}{ymax}+$ShiftY, attributes=>{attribute=>'.string',text=>$lr.'_clear_pad'},polarity=>$layer_polarity_n ) if ($COUPON_DATA->{$lr.'_header_copper_clip'} and abs($COUPON_DATA->{$lr.'_header_copper_clip'}{xmax} - $COUPON_DATA->{$lr.'_header_copper_clip'}{xmin}) > 0.001); } } } if ($COUPON_DATA->{thermal_as_surface} eq 'yes'){ #添加gnd thermal if ($layer_type =~ /^(S|B)$/ and $COUPON_DATA->{is_coplanar}){ foreach my $grp (keys %{$COUPON_DATA->{group}}){ my ($tmp_sym,$tmp_polarity); if (grep({$grp eq $_} @layer_blong_grps)){ $tmp_sym = $layer_gpad_thermal_sym;$tmp_polarity = $layer_polarity_n; } next unless $tmp_sym; foreach my $imp_lyr (@{$COUPON_DATA->{group}{$grp}{signal_layer}}){ my $imp_layer = $COUPON_DATA->{layers}{$imp_lyr}; foreach my $lr ('left','right'){ if ($imp_layer->{$lr.'_gpads'}){ foreach my $it (@{$imp_layer->{$lr.'_gpads'}}){ $GEN->addPad(x=>$it->{x}+$ShiftX,y=>$it->{y}+$ShiftY,symbol=>$tmp_sym,polarity=>$tmp_polarity,attributes=>{attribute=>'.string',text=>$lr.'_clear_pad'}); } } } } } } elsif($layer_type eq 'R'){ foreach my $grp (keys %{$COUPON_DATA->{group}}){ my ($tmp_sym,$tmp_polarity); if (grep({$grp eq $_} @layer_blong_grps)){ $tmp_sym = $layer_gpad_thermal_sym;$tmp_polarity = $layer_polarity_n; } next unless $tmp_sym; foreach my $imp_lyr (@{$COUPON_DATA->{group}{$grp}{signal_layer}}){ my $imp_layer = $COUPON_DATA->{layers}{$imp_lyr}; foreach my $lr ('left','right'){ if ($imp_layer->{$lr.'_gpads'}){ foreach my $it (@{$imp_layer->{$lr.'_gpads'}}){ $GEN->addPad(x=>$it->{x}+$ShiftX,y=>$it->{y}+$ShiftY,symbol=>$tmp_sym,polarity=>$tmp_polarity,attributes=>{attribute=>'.string',text=>$lr.'_clear_pad'}); } } } } } } if ($COUPON_DATA->{patch_ref_layer_hole} and $layer_type eq 'R'){ $GEN->deleteLayer(job=>$Job,layer=>$tmp_layer); $GEN->createLayer(job=>$Job,layer=>$tmp_layer,context=>'misc',type=>'signal'); $GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>$tmp_layer,clear_before=>'yes'); foreach my $grp (@layer_blong_grps){ foreach my $imp_lyr (@{$COUPON_DATA->{group}{$grp}{signal_layer}}){ my $imp_layer = $COUPON_DATA->{layers}{$imp_lyr}; my $sym = 'r'.($imp_layer->{cam_line_width} + $COUPON_DATA->{patch_ref_layer_hole}*2); foreach my $m ('lines1','lines2'){ if ($imp_layer->{$m} and @{$imp_layer->{$m}}){ my ($xs,$ys) = ($imp_layer->{$m}[0]{x},$imp_layer->{$m}[0]{y}); foreach my $n (1..scalar(@{$imp_layer->{$m}})-1){ my $it = $imp_layer->{$m}[$n]; if ($it->{direction}){ $GEN->addArc(xs=>$xs+$ShiftX,ys=>$ys+$ShiftY,xe=>$it->{x}+$ShiftX,ye=>$it->{y}+$ShiftY,xc=>$it->{xc}+$ShiftX,yc=>$it->{yc}+$ShiftY,direction=>$it->{direction},symbol=>$sym,polarity=>'positive'); } else{ $GEN->addLine(xs=>$xs+$ShiftX,ys=>$ys+$ShiftY,xe=>$it->{x}+$ShiftX,ye=>$it->{y}+$ShiftY,symbol=>$sym,polarity=>'positive'); } ($xs,$ys) = ($it->{x},$it->{y}); } } } if ($imp_layer->{center_lines} and @{$imp_layer->{center_lines}}){ my ($xs,$ys) = ($imp_layer->{center_lines}[0]{x},$imp_layer->{center_lines}[0]{y}); foreach my $n (1..scalar(@{$imp_layer->{center_lines}})-1){ my $it = $imp_layer->{center_lines}[$n]; if ($it->{direction}){ $GEN->addArc(xs=>$xs+$ShiftX,ys=>$ys+$ShiftY,xe=>$it->{x}+$ShiftX,ye=>$it->{y}+$ShiftY,xc=>$it->{xc}+$ShiftX,yc=>$it->{yc}+$ShiftY,direction=>$it->{direction},symbol=>'r'.$imp_layer->{cam_total_width},polarity=>$layer_polarity_n); } else{ $GEN->addLine(xs=>$xs+$ShiftX,ys=>$ys+$ShiftY,xe=>$it->{x}+$ShiftX,ye=>$it->{y}+$ShiftY,symbol=>'r'.$imp_layer->{cam_total_width},polarity=>'positive'); } ($xs,$ys) = ($it->{x},$it->{y}); } } foreach my $lr ('left','right'){ if ($imp_layer->{$lr.'_tpads'}){ foreach my $it (@{$imp_layer->{$lr.'_tpads'}}){ $GEN->addPad(x=>$it->{x}+$ShiftX,y=>$it->{y}+$ShiftY,symbol=>$layer_patch_ref_clear_sym,polarity=>'negative',attributes=>{attribute=>'.string',text=>$lr.'_patch_ref_clear_pad'}); } } } foreach my $lr ('left','right'){ if ($trans->{$lr}{angle}){ $GEN->selClearFeature(); $GEN->selectByFilter(attribute=>[{attribute=>'.string',text=>$lr.'_patch_ref_clear_pad'}]); $GEN->COM('sel_transform',mode=>'anchor',oper=>'rotate',duplicate=>'no',%{$trans->{$lr}}) if $GEN->getSelectCount();; } } $GEN->COM('sel_all_feat'); $GEN->selContourize(accuracy=>0.1,break_to_islands=>'yes',clean_hole_size=>0.1,clean_hole_mode=>'x_or_y'); $GEN->COM('sel_all_feat'); $GEN->COM('sel_move_other',target_layer=>$layer_name,invert=>($layer_polarity eq 'positive')?'no':'yes',dx=>0,dy=>0,size=>0); } } $GEN->deleteLayer(job=>$Job,layer=>$tmp_layer); $GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>$layer_name,clear_before=>'yes'); foreach my $lr ('left','right'){ if ($trans->{$lr}{angle}){ $GEN->selClearFeature(); $GEN->selectByFilter(attribute=>[{attribute=>'.string',text=>$lr.'_clear_pad'}]); $GEN->COM('sel_transform',mode=>'anchor',oper=>'rotate',duplicate=>'no',%{$trans->{$lr}}) if $GEN->getSelectCount();; } } $GEN->COM('sel_all_feat'); $GEN->selContourize(accuracy=>0.1,break_to_islands=>'yes',clean_hole_size=>$COUPON_DATA->{inner_pad2copper} - 1,clean_hole_mode=>'x_or_y'); } } foreach my $lr ('left','right'){ if ($trans->{$lr}{angle}){ $GEN->selClearFeature(); $GEN->selectByFilter(attribute=>[{attribute=>'.string',text=>$lr.'_clear_pad'}]); $GEN->COM('sel_transform',mode=>'anchor',oper=>'rotate',duplicate=>'no',%{$trans->{$lr}}) if $GEN->getSelectCount();; } } $GEN->COM('sel_all_feat'); $GEN->selContourize(accuracy=>0.1,break_to_islands=>'yes',clean_hole_size=>0.1,clean_hole_mode=>'x_or_y'); if ($layer_polarity eq 'negative'){ $GEN->clipArea(area=>'profile',area_type=>'rectangle',inout=>'outside',contour_cut=>'yes',margin=>$COUPON_DATA->{neg_copper_margin}); } else{ $GEN->COM('sel_all_feat'); $GEN->selFill(type=>'solid',solid_type=>'fill',min_brush=>$COUPON_DATA->{copper_fill_line_width}); $GEN->COM('sel_all_feat'); $GEN->selContourize(accuracy=>0.1,break_to_islands=>'yes',clean_hole_size=>0.1,clean_hole_mode=>'x_or_y'); $GEN->createLayer(job=>$Job,layer=>$tmp_layer,context=>'misc',type=>'signal') unless ($GEN->isLayerExists(job=>$Job,layer=>$tmp_layer));; $GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>$tmp_layer,clear_before=>'yes'); $GEN->COM('sel_all_feat'); $GEN->selDelete(); $GEN->srFill(layer=>$tmp_layer,step_margin_x=>$COUPON_DATA->{rout2copper_spacing}/1000-0.1,step_margin_y=>$COUPON_DATA->{rout2copper_spacing}/1000-0.1,polarity=>$layer_polarity); $GEN->copyLayer(source_job=>$Job,source_step=>$step,source_layer=>$layer_name,dest_layer=>$tmp_layer,mode=>'append',invert=>'yes'); $GEN->COM('sel_all_feat'); $GEN->selContourize(accuracy=>0.1,break_to_islands=>'yes',clean_hole_size=>0.1,clean_hole_mode=>'x_or_y'); $GEN->COM('sel_all_feat'); $GEN->selFill(type=>'solid',solid_type=>'fill',min_brush=>$COUPON_DATA->{copper_fill_sliver_width}); $GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>$layer_name,clear_before=>'yes'); $GEN->COM('sel_all_feat'); $GEN->selDelete(); $GEN->srFill(layer=>$layer_name,step_margin_x=>$COUPON_DATA->{rout2copper_spacing}/1000,step_margin_y=>$COUPON_DATA->{rout2copper_spacing}/1000,polarity=>$layer_polarity); $GEN->copyLayer(source_job=>$Job,source_step=>$step,source_layer=>$tmp_layer,dest_layer=>$layer_name,mode=>'append',invert=>'yes'); $GEN->COM('sel_all_feat'); $GEN->selContourize(accuracy=>0.1,break_to_islands=>'yes',clean_hole_size=>0.1,clean_hole_mode=>'x_or_y'); if ($COUPON_DATA->{clean_surface_size}){ $GEN->runSingleDfm(chklist=>'valor_dfm_clean_holes', params=>{pp_layer => $layer_name, pp_size=>$COUPON_DATA->{clean_surface_size}, pp_mode=>'X and Y', pp_hi=>'Cover islands', pp_cover_f=>'Surfaces',}, area => 'global',show => 'no',show_res=>'no'); $GEN->COM('sel_all_feat'); $GEN->selContourize(accuracy=>0.1,break_to_islands=>'yes',clean_hole_size=>0.1,clean_hole_mode=>'x_or_y'); $GEN->deleteLayer(job=>$Job,layer=>$layer_name.'+++'); } } $GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>$layer_name,clear_before=>'yes'); #添加test pad foreach my $grp (keys %{$COUPON_DATA->{group}}){ if ($COUPON_DATA->{remove_nfp} ne 'yes' or (grep({$grp eq $_} @layer_blong_grps) and $layer_type eq 'S' ) or grep({$grp eq $_} @layer_include_grps )) { foreach my $imp_lyr (@{$COUPON_DATA->{group}{$grp}{signal_layer}}){ my $imp_layer = $COUPON_DATA->{layers}{$imp_lyr}; if ($COUPON_DATA->{remove_nfp} ne 'yes' or $imp_layer->{layer_number} == $layer_number or $layer_number == 1 or $layer_number == $COUPON_DATA->{layer_count}){ foreach my $lr ('left','right'){ if ($imp_layer->{$lr.'_tpads'}){ foreach my $it (@{$imp_layer->{$lr.'_tpads'}}){ $GEN->addPad(x=>$it->{x}+$ShiftX,y=>$it->{y}+$ShiftY,symbol=>$layer_tpad_sym,polarity=>$layer_polarity,attributes=>{attribute=>'.string',text=>$lr.'_pad'}); } } } } } } } #添加gnd pad if ($layer_type =~ /^(S|B)$/){ if ($COUPON_DATA->{is_coplanar}){ foreach my $grp (keys %{$COUPON_DATA->{group}}){ foreach my $imp_lyr (@{$COUPON_DATA->{group}{$grp}{signal_layer}}){ my $imp_layer = $COUPON_DATA->{layers}{$imp_lyr}; my ($tmp_sym,$tmp_polarity); if (grep({$grp eq $_} @layer_blong_grps)){ if ($imp_layer->{impedance_type} =~ /coplanar/i){ unless ($COUPON_DATA->{thermal_as_surface} eq 'yes'){ $tmp_sym = $layer_gpad_thermal_sym;$tmp_polarity = $layer_polarity_n; } } else{ $tmp_sym = $layer_gpad_sym; $tmp_polarity = $layer_polarity; } } elsif(grep({$grp eq $_} @layer_include_grps)){ $tmp_sym = $layer_gpad_sym; $tmp_polarity = $layer_polarity; } elsif($COUPON_DATA->{remove_nfp} ne 'yes'){ $tmp_sym = $layer_gpad_sym; $tmp_polarity = $layer_polarity; } next unless $tmp_sym; foreach my $lr ('left','right'){ if ($imp_layer->{$lr.'_gpads'}){ foreach my $it (@{$imp_layer->{$lr.'_gpads'}}){ $GEN->addPad(x=>$it->{x}+$ShiftX,y=>$it->{y}+$ShiftY,symbol=>$tmp_sym,polarity=>$tmp_polarity,attributes=>{attribute=>'.string',text=>$lr.'_pad'}); } } } } } } else{ foreach my $grp (keys %{$COUPON_DATA->{group}}){ my ($tmp_sym,$tmp_polarity); if(grep({$grp eq $_} @layer_include_grps)){ $tmp_sym = $layer_gpad_sym; $tmp_polarity = $layer_polarity; } elsif($COUPON_DATA->{remove_nfp} ne 'yes'){ $tmp_sym = $layer_gpad_sym; $tmp_polarity = $layer_polarity; } next unless $tmp_sym; foreach my $imp_lyr (@{$COUPON_DATA->{group}{$grp}{signal_layer}}){ my $imp_layer = $COUPON_DATA->{layers}{$imp_lyr}; foreach my $lr ('left','right'){ if ($imp_layer->{$lr.'_gpads'}){ foreach my $it (@{$imp_layer->{$lr.'_gpads'}}){ $GEN->addPad(x=>$it->{x}+$ShiftX,y=>$it->{y}+$ShiftY,symbol=>$tmp_sym,polarity=>$tmp_polarity,attributes=>{attribute=>'.string',text=>$lr.'_pad'}); } } } } } } } elsif($layer_type eq 'R'){ foreach my $grp (keys %{$COUPON_DATA->{group}}){ my ($tmp_sym,$tmp_polarity); if (grep({$grp eq $_} @layer_blong_grps)){ unless ($COUPON_DATA->{thermal_as_surface} eq 'yes'){ $tmp_sym = $layer_gpad_thermal_sym;$tmp_polarity = $layer_polarity_n; } } elsif(grep({$grp eq $_} @layer_include_grps)){ $tmp_sym = $layer_gpad_sym; $tmp_polarity = $layer_polarity; } elsif($COUPON_DATA->{remove_nfp} ne 'yes'){ $tmp_sym = $layer_gpad_sym; $tmp_polarity = $layer_polarity; } next unless $tmp_sym; foreach my $imp_lyr (@{$COUPON_DATA->{group}{$grp}{signal_layer}}){ my $imp_layer = $COUPON_DATA->{layers}{$imp_lyr}; foreach my $lr ('left','right'){ if ($imp_layer->{$lr.'_gpads'}){ foreach my $it (@{$imp_layer->{$lr.'_gpads'}}){ $GEN->addPad(x=>$it->{x}+$ShiftX,y=>$it->{y}+$ShiftY,symbol=>$tmp_sym,polarity=>$tmp_polarity,attributes=>{attribute=>'.string',text=>$lr.'_pad'}); } } } } } } else{ foreach my $grp (keys %{$COUPON_DATA->{group}}){ my ($tmp_sym,$tmp_polarity); if(grep({$grp eq $_} @layer_include_grps)){ $tmp_sym = $layer_gpad_sym; $tmp_polarity = $layer_polarity; } elsif($COUPON_DATA->{remove_nfp} ne 'yes'){ $tmp_sym = $layer_gpad_sym; $tmp_polarity = $layer_polarity; } next unless $tmp_sym; foreach my $imp_lyr (@{$COUPON_DATA->{group}{$grp}{signal_layer}}){ my $imp_layer = $COUPON_DATA->{layers}{$imp_lyr}; foreach my $lr ('left','right'){ if ($imp_layer->{$lr.'_gpads'}){ foreach my $it (@{$imp_layer->{$lr.'_gpads'}}){ $GEN->addPad(x=>$it->{x}+$ShiftX,y=>$it->{y}+$ShiftY,symbol=>$tmp_sym,polarity=>$tmp_polarity,attributes=>{attribute=>'.string',text=>$lr.'_pad'}); } } } } } } if ($COUPON_DATA->{patch_ref_layer_hole} and $COUPON_DATA->{thermal_as_surface} ne 'yes' and $layer_type eq 'R'){ $GEN->deleteLayer(job=>$Job,layer=>$tmp_layer); $GEN->createLayer(job=>$Job,layer=>$tmp_layer,context=>'misc',type=>'signal'); $GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>$tmp_layer,clear_before=>'yes'); foreach my $grp (@layer_blong_grps){ foreach my $imp_lyr (@{$COUPON_DATA->{group}{$grp}{signal_layer}}){ my $imp_layer = $COUPON_DATA->{layers}{$imp_lyr}; my $sym = 'r'.($imp_layer->{cam_line_width} + $COUPON_DATA->{patch_ref_layer_hole}*2); foreach my $m ('lines1','lines2'){ if ($imp_layer->{$m} and @{$imp_layer->{$m}}){ my ($xs,$ys) = ($imp_layer->{$m}[0]{x},$imp_layer->{$m}[0]{y}); foreach my $n (1..scalar(@{$imp_layer->{$m}})-1){ my $it = $imp_layer->{$m}[$n]; if ($it->{direction}){ $GEN->addArc(xs=>$xs+$ShiftX,ys=>$ys+$ShiftY,xe=>$it->{x}+$ShiftX,ye=>$it->{y}+$ShiftY,xc=>$it->{xc}+$ShiftX,yc=>$it->{yc}+$ShiftY,direction=>$it->{direction},symbol=>$sym,polarity=>'positive'); } else{ $GEN->addLine(xs=>$xs+$ShiftX,ys=>$ys+$ShiftY,xe=>$it->{x}+$ShiftX,ye=>$it->{y}+$ShiftY,symbol=>$sym,polarity=>'positive'); } ($xs,$ys) = ($it->{x},$it->{y}); } } } foreach my $lr ('left','right'){ if ($imp_layer->{$lr.'_tpads'}){ foreach my $it (@{$imp_layer->{$lr.'_tpads'}}){ $GEN->addPad(x=>$it->{x}+$ShiftX,y=>$it->{y}+$ShiftY,symbol=>$layer_patch_ref_clear_sym,polarity=>'negative',attributes=>{attribute=>'.string',text=>$lr.'_patch_ref_clear_pad'}); } } } foreach my $lr ('left','right'){ if ($trans->{$lr}{angle}){ $GEN->selClearFeature(); $GEN->selectByFilter(attribute=>[{attribute=>'.string',text=>$lr.'_patch_ref_clear_pad'}]); $GEN->COM('sel_transform',mode=>'anchor',oper=>'rotate',duplicate=>'no',%{$trans->{$lr}}) if $GEN->getSelectCount();; } } $GEN->COM('sel_all_feat'); $GEN->selContourize(accuracy=>0.1,break_to_islands=>'yes',clean_hole_size=>0.1,clean_hole_mode=>'x_or_y'); $GEN->COM('sel_all_feat'); $GEN->COM('sel_move_other',target_layer=>$layer_name,invert=>($layer_polarity eq 'positive')?'no':'yes',dx=>0,dy=>0,size=>0); } } $GEN->deleteLayer(job=>$Job,layer=>$tmp_layer); $GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>$layer_name,clear_before=>'yes'); } #添加信号线及AOI Pad foreach my $imp_layer (values %{$COUPON_DATA->{layers}}){ if ($imp_layer->{layer_number} == $layer_number){ my $sym = 'r'.($imp_layer->{cam_line_width}); foreach my $m ('lines1','lines2'){ if ($imp_layer->{$m} and @{$imp_layer->{$m}}){ my ($xs,$ys) = ($imp_layer->{$m}[0]{x},$imp_layer->{$m}[0]{y}); foreach my $n (1..scalar(@{$imp_layer->{$m}})-1){ my $it = $imp_layer->{$m}[$n]; if ($it->{direction}){ $GEN->addArc(xs=>$xs+$ShiftX,ys=>$ys+$ShiftY,xe=>$it->{x}+$ShiftX,ye=>$it->{y}+$ShiftY,xc=>$it->{xc}+$ShiftX,yc=>$it->{yc}+$ShiftY,direction=>$it->{direction},symbol=>$sym,polarity=>$layer_polarity); } else{ $GEN->addLine(xs=>$xs+$ShiftX,ys=>$ys+$ShiftY,xe=>$it->{x}+$ShiftX,ye=>$it->{y}+$ShiftY,symbol=>$sym,polarity=>$layer_polarity); } ($xs,$ys) = ($it->{x},$it->{y}); } } } if ($COUPON_DATA->{add_aoi_pad} eq 'yes'){ foreach my $it (@{$imp_layer->{aoi_pads}}){ $GEN->addPad(x=>$it->{x}+$ShiftX,y=>$it->{y}+$ShiftY,symbol=>'r'.($imp_layer->{cam_line_width}+$COUPON_DATA->{aoi_pad_ar}*2),polarity=>$layer_polarity); } } } } #添加头部文字 foreach my $lr ('left','right'){ if ($COUPON_DATA->{$lr.'_header_text_pos'}{$tl_name}){ foreach my $sig (keys %{$COUPON_DATA->{$lr.'_header_text_pos'}{$tl_name}}){ foreach my $v (values %{$COUPON_DATA->{$lr.'_header_text_pos'}{$tl_name}{$sig}}){ my $tmp_polarity = ($v->{polarity} eq 'positive')?$layer_polarity:$layer_polarity_n; $GEN->addText(x=>$v->{x}+$ShiftX,y=>$v->{y}+$ShiftY,text=>$v->{text},angle=>$v->{angle},mirror=>($layer_side eq 'front')?'no':'yes', x_size=>$v->{x_size},y_size=>$v->{y_size},line_width=>$v->{line_width},anchor=>$v->{anchor}, polarity=>$tmp_polarity,fontname=>$COUPON_DATA->{header_text_font}, attributes=>{attribute=>'.string',text=>$lr.'_pad'}); } } } } foreach my $lr ('left','right'){ if ($trans->{$lr}{angle}){ $GEN->selClearFeature(); $GEN->selectByFilter(attribute=>[{attribute=>'.string',text=>$lr.'_pad'}]); $GEN->COM('sel_transform',mode=>'anchor',oper=>'rotate',duplicate=>'no',%{$trans->{$lr}}) if $GEN->getSelectCount(); } } #$GUI->debug(-text=>dump($COUPON_DATA->{body_text_pos},$tl_name)); #添加body文字 if ($tl_name eq 'top' and $COUPON_DATA->{body_text_pos}{$tl_name}){ unless ($COUPON_DATA->{'body_text_not_enought_space'}{$tl_name}){ my $n = 0; foreach my $text (@{$COUPON_DATA->{body_text_pos}{$tl_name}}){ $n++; $GEN->addText(x=>$text->{x}+$ShiftX,y=>$text->{y}+$ShiftY,text=>$text->{text},angle=>0,polarity=>($COUPON_DATA->{body_text_polarity} eq 'positive')?$layer_polarity:$layer_polarity_n, x_size=>$text->{x_size},y_size=>$text->{y_size},line_width=>$text->{line_width},mirror=>($layer_side eq 'front')?'no':'yes', anchor=>$text->{anchor},text_length=>$text->{text_length},attributes=>{attribute=>'.string',text=>'body_text_'.$n},fontname=>$COUPON_DATA->{body_text_font},); if ($text->{angle}){ my $angle = -$text->{angle}; $angle = 360 + $angle if $angle < 0; $GEN->selClearFeature(); $GEN->selectByFilter(attribute=>[{attribute=>'.string',text=>'body_text_'.$n}]); $GEN->COM('sel_transform',mode=>'anchor',oper=>'rotate',duplicate=>'no', x_anchor=>$text->{bx}+$ShiftX,y_anchor=>$text->{by}+$ShiftY, angle=>$angle,x_scale=>1,y_scale=>1,x_offset=>0,y_offset=>0) if $GEN->getSelectCount();; } } } else{ my $tmp_body_text_layer = $layer_name.($COUPON_DATA->{body_text_tmp_layer_postfix} || '_imptext+++'); push @$WarningMsg,"${step}的${layer_name}层没有足够的空间添加文字,现将文字添加到${tmp_body_text_layer}中!"; $GEN->createLayer(job=>$Job,layer=>$tmp_body_text_layer,context=>'misc',type=>'signal') unless ($GEN->isLayerExists(job=>$Job,layer=>$tmp_body_text_layer));; $GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>$tmp_body_text_layer,clear_before=>'yes'); $GEN->COM('sel_all_feat'); $GEN->selDelete(); foreach my $text (@{$COUPON_DATA->{body_text_pos}{$tl_name}}){ $GEN->addText(x=>$text->{x},y=>$text->{y},text=>$text->{text},angle=>0,polarity=>$layer_polarity, x_size=>$text->{x_size},y_size=>$text->{y_size},line_width=>$text->{line_width},mirror=>($layer_side eq 'front')?'no':'yes', anchor=>$text->{anchor},fontname=>$COUPON_DATA->{body_text_font},); } $GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>$layer_name,clear_before=>'yes'); } } =exp foreach my $layer (keys %{$COUPON_DATA->{body_text_pos}}) { unless ($COUPON_DATA->{'body_text_not_enought_space'}{$layer}){ my $n = 0; foreach my $text (@{$COUPON_DATA->{body_text_pos}{$layer}}){ my ($txt_lyr) = $text->{text} =~ /(\w+)\//i; $GEN->PAUSE($text->{text}.' -- '.$txt_lyr.' --- '.$tl_name); if (lc($txt_lyr) eq $tl_name or $text->{text} =~ /\$\$JOB/) { $n++; $GEN->addText(x=>$text->{x}+$ShiftX,y=>$text->{y}+$ShiftY,text=>$text->{text},angle=>0,polarity=>($COUPON_DATA->{body_text_polarity} eq 'positive')?$layer_polarity:$layer_polarity_n, x_size=>$text->{x_size},y_size=>$text->{y_size},line_width=>$text->{line_width},mirror=>($layer_side eq 'front')?'no':'yes', anchor=>$text->{anchor},text_length=>$text->{text_length},attributes=>{attribute=>'.string',text=>'body_text_'.$n},fontname=>$COUPON_DATA->{body_text_font},); if ($text->{angle}){ my $angle = -$text->{angle}; $angle = 360 + $angle if $angle < 0; $GEN->selClearFeature(); $GEN->selectByFilter(attribute=>[{attribute=>'.string',text=>'body_text_'.$n}]); $GEN->COM('sel_transform',mode=>'anchor',oper=>'rotate',duplicate=>'no', x_anchor=>$text->{bx}+$ShiftX,y_anchor=>$text->{by}+$ShiftY, angle=>$angle,x_scale=>1,y_scale=>1,x_offset=>0,y_offset=>0) if $GEN->getSelectCount();; } } } }else{ my $tmp_body_text_layer = $layer_name.($COUPON_DATA->{body_text_tmp_layer_postfix} || '_imptext+++'); push @$WarningMsg,"${step}的${layer_name}层没有足够的空间添加文字,现将文字添加到${tmp_body_text_layer}中!"; $GEN->createLayer(job=>$Job,layer=>$tmp_body_text_layer,context=>'misc',type=>'signal') unless ($GEN->isLayerExists(job=>$Job,layer=>$tmp_body_text_layer));; $GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>$tmp_body_text_layer,clear_before=>'yes'); $GEN->COM('sel_all_feat'); $GEN->selDelete(); foreach my $text (@{$COUPON_DATA->{body_text_pos}{$layer}}){ $GEN->addText(x=>$text->{x},y=>$text->{y},text=>$text->{text},angle=>0,polarity=>$layer_polarity, x_size=>$text->{x_size},y_size=>$text->{y_size},line_width=>$text->{line_width},mirror=>($layer_side eq 'front')?'no':'yes', anchor=>$text->{anchor},fontname=>$COUPON_DATA->{body_text_font},); } $GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>$layer_name,clear_before=>'yes'); } } =cut } if ($COUPON_DATA->{header_not_enought_space}){ #push @$WarningMsg,"${step}中没有足够的空间添加头部文字,请检查并处理!"; } #添加钻孔 foreach my $drl (keys %{$COUPON_DATA->{drills}}){ my $drl_layer = $gen_layer{$drl}; $GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>$drl_layer,clear_before=>'yes'); my $hole_sym = 'r'.(($drl eq 'drill')?$COUPON_DATA->{hole_size}:$COUPON_DATA->{hdi_hole_size}); if ($COUPON_DATA->{drills}{$drl}{include_coupon_groups}){ foreach my $grp (@{$COUPON_DATA->{drills}{$drl}{include_coupon_groups}}){ foreach my $imp_lyr (@{$COUPON_DATA->{group}{$grp}{signal_layer}}){ my $imp_layer = $COUPON_DATA->{layers}{$imp_lyr}; foreach my $lr ('left','right'){ foreach my $pad ('_tpads','_gpads'){ if ($imp_layer->{$lr.$pad}){ foreach my $it (@{$imp_layer->{$lr.$pad}}){ $GEN->addPad(x=>$it->{x}+$ShiftX,y=>$it->{y}+$ShiftY,symbol=>$hole_sym,polarity=>'positive',attributes=>[{attribute=>'.string',text=>$lr.'_hole'},{attribute=>'.drill',option=>'plated'}]); } } } } } } } foreach my $lr ('left','right'){ if ($trans->{$lr}{angle}){ $GEN->selClearFeature(); $GEN->selectByFilter(attribute=>[{attribute=>'.string',text=>$lr.'_hole'}]); $GEN->COM('sel_transform',mode=>'anchor',oper=>'rotate',duplicate=>'no',%{$trans->{$lr}}) if $GEN->getSelectCount();; } } if ($drl eq 'drill'){ #pin_hole foreach my $lr ('left','right'){ if ($COUPON_DATA->{$lr.'_pin_hole'}){ $GEN->addPad(x=>$COUPON_DATA->{$lr.'_pin_hole'}{x}+$ShiftX,y=>$COUPON_DATA->{$lr.'_pin_hole'}{y}+$ShiftY,symbol=>'r'.$COUPON_DATA->{pin_hole_size},polarity=>'positive',attributes=>[{attribute=>'.drill',option=>'non_plated'}]); } } #coplanar hole foreach my $ud ('up','down'){ if ($COUPON_DATA->{$ud.'_coplanar_holes'}){ foreach my $it (@{$COUPON_DATA->{$ud.'_coplanar_holes'}}){ $GEN->addPad(x=>$it->{x}+$ShiftX,y=>$it->{y}+$ShiftY,symbol=>'r'.$COUPON_DATA->{coplanar_hole_size},attributes=>[{attribute=>'.drill',option=>'plated'}]); } } } } } #npth if ($COUPON_DATA->{add_pin_hole} eq 'yes' and $gen_layer{npth}){ $GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>$gen_layer{npth},clear_before=>'yes'); foreach my $lr ('left','right'){ if ($COUPON_DATA->{$lr.'_pin_hole'}){ $GEN->addPad(x=>$COUPON_DATA->{$lr.'_pin_hole'}{x}+$ShiftX,y=>$COUPON_DATA->{$lr.'_pin_hole'}{y}+$ShiftY,symbol=>'r'.$COUPON_DATA->{pin_hole_size},polarity=>'positive',attributes=>[{attribute=>'.drill',option=>'non_plated'}]); } } } #防焊 foreach my $item ('sm_fr','sm_ba'){ #foreach my $item ('smt','smb'){ my $tpad_sm_sym = $COUPON_DATA->{outer_tpad_shape} . ($COUPON_DATA->{pad_size} + $COUPON_DATA->{sm_opening_ar}*2); my $gpad_sm_sym = $COUPON_DATA->{outer_gpad_shape} . ($COUPON_DATA->{pad_size} + $COUPON_DATA->{sm_opening_ar}*2); if ($gen_layer{$item}){ $GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>$gen_layer{$item},clear_before=>'yes'); foreach my $imp_layer (values %{$COUPON_DATA->{layers}}){ next unless $imp_layer->{layer_type} eq 'S'; foreach my $lr ('left','right'){ if ($imp_layer->{$lr.'_tpads'}){ foreach my $it (@{$imp_layer->{$lr.'_tpads'}}){ $GEN->addPad(x=>$it->{x}+$ShiftX,y=>$it->{y}+$ShiftY,symbol=>$tpad_sm_sym,polarity=>'positive',attributes=>[{attribute=>'.string',text=>$lr.'_sm'}]); } } if ($imp_layer->{$lr.'_gpads'}){ foreach my $it (@{$imp_layer->{$lr.'_gpads'}}){ $GEN->addPad(x=>$it->{x}+$ShiftX,y=>$it->{y}+$ShiftY,symbol=>$gpad_sm_sym,polarity=>'positive',attributes=>[{attribute=>'.string',text=>$lr.'_sm'}]); } } } } foreach my $lr ('left','right'){ if ($trans->{$lr}{angle}){ $GEN->selClearFeature(); $GEN->selectByFilter(attribute=>[{attribute=>'.string',text=>$lr.'_sm'}]); $GEN->COM('sel_transform',mode=>'anchor',oper=>'rotate',duplicate=>'no',%{$trans->{$lr}}) if $GEN->getSelectCount();; } } #添加pin hole sm foreach my $lr ('left','right'){ if ($COUPON_DATA->{$lr.'_pin_hole'}){ $GEN->addPad(x=>$COUPON_DATA->{$lr.'_pin_hole'}{x}+$ShiftX,y=>$COUPON_DATA->{$lr.'_pin_hole'}{y}+$ShiftY,symbol=>'r'.($COUPON_DATA->{pin_hole_size} + 2*$COUPON_DATA->{pin_hole_sm_ar}),polarity=>'positive',); } } #添加信号线SM开窗 foreach my $imp_layer (values %{$COUPON_DATA->{layers}}){ if (($imp_layer->{layer_number} == 1 and $item eq 'sm_fr' and lc($imp_layer->{sm_open}) eq 'yes') or ($imp_layer->{layer_number} == $LayerCount and $item eq 'sm_ba' and lc($imp_layer->{sm_open}) eq 'yes') ){ my $sym_size = ($imp_layer->{cam_line_width} + ($COUPON_DATA->{line_sm_opening_ar} || $COUPON_DATA->{sm_opening_ar})*2); foreach my $m ('lines1','lines2'){ if ($imp_layer->{$m} and @{$imp_layer->{$m}}){ my ($xs,$ys) = ($imp_layer->{$m}[0]{x},$imp_layer->{$m}[0]{y}); foreach my $n (1..scalar(@{$imp_layer->{$m}})-1){ my $it = $imp_layer->{$m}[$n]; if ($it->{direction}){ $GEN->addArc(xs=>$xs+$ShiftX,ys=>$ys+$ShiftY,xe=>$it->{x}+$ShiftX,ye=>$it->{y}+$ShiftY,xc=>$it->{xc}+$ShiftX,yc=>$it->{yc}+$ShiftY,direction=>$it->{direction},symbol=>'r'.$sym_size,polarity=>'positive'); } else{ $GEN->addLine(xs=>$xs+$ShiftX,ys=>$ys+$ShiftY,xe=>$it->{x}+$ShiftX,ye=>$it->{y}+$ShiftY,symbol=>'r'.$sym_size,polarity=>'positive'); } ($xs,$ys) = ($it->{x},$it->{y}); } } } if ($COUPON_DATA->{add_aoi_pad} eq 'yes'){ foreach my $it (@{$imp_layer->{aoi_pads}}){ $GEN->addPad(x=>$it->{x}+$ShiftX,y=>$it->{y}+$ShiftY,symbol=>'r'.($sym_size+$COUPON_DATA->{aoi_pad_ar}*2),polarity=>'positive'); } } } } } } #outline if ($gen_layer{'outline'}){ $GEN->COM('profile_to_rout',layer=>$gen_layer{'outline'},width=>$COUPON_DATA->{outline_width}||1); } #档点 if ($COUPON_DATA->{plug_layers}){ # 层名做变量替换 $COUPON_DATA->{plug_layers} =~ s/\$\{layer_count\}/sprintf("%02d", $COUPON_DATA->{layer_count})/ge; my $layers = eval($COUPON_DATA->{plug_layers}); while ($layers and @$layers){ my $plug_layer = shift @$layers; my $action = shift @$layers; if ($action eq 'create'){ if (!$GEN->isLayerExists(job=>$Job,layer=>$plug_layer)){ $GEN->createLayer(job=>$Job,layer=>$plug_layer); } } next unless $GEN->isLayerExists(job=>$Job,layer=>$plug_layer); $GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>$plug_layer,clear_before=>'yes'); $GEN->COM('sel_all_feat'); $GEN->selDelete; ##挡点需要填充 #$GEN->srFill(step_margin_x=>-0.005,step_margin_y=>-0.005); my $drl_layer = $gen_layer{drill}; my $via_sym = 'r'.($COUPON_DATA->{hole_size} + 2*$COUPON_DATA->{plug_ar}); if ($COUPON_DATA->{drills}{drill}{include_coupon_groups}){ foreach my $grp (@{$COUPON_DATA->{drills}{drill}{include_coupon_groups}}){ foreach my $imp_lyr (@{$COUPON_DATA->{group}{$grp}{signal_layer}}){ my $imp_layer = $COUPON_DATA->{layers}{$imp_lyr}; foreach my $lr ('left','right'){ foreach my $pad ('_tpads','_gpads'){ if ($imp_layer->{$lr.$pad}){ foreach my $it (@{$imp_layer->{$lr.$pad}}){ $GEN->addPad(x=>$it->{x}+$ShiftX,y=>$it->{y}+$ShiftY,symbol=>$via_sym,polarity=>'positive',attributes=>[{attribute=>'.string',text=>$lr.'_hole'},{attribute=>'.drill',option=>'plated'}]); } } } } } } } foreach my $lr ('left','right'){ if ($trans->{$lr}{angle}){ $GEN->selClearFeature(); $GEN->selectByFilter(attribute=>[{attribute=>'.string',text=>$lr.'_hole'}]); $GEN->COM('sel_transform',mode=>'anchor',oper=>'rotate',duplicate=>'no',%{$trans->{$lr}}) if $GEN->getSelectCount();; } } #pin_hole foreach my $lr ('left','right'){ if ($COUPON_DATA->{$lr.'_pin_hole'}){ $GEN->addPad(x=>$COUPON_DATA->{$lr.'_pin_hole'}{x}+$ShiftX,y=>$COUPON_DATA->{$lr.'_pin_hole'}{y}+$ShiftY,symbol=>'r'.($COUPON_DATA->{pin_hole_size} + 2*$COUPON_DATA->{plug_ar}),polarity=>'positive',attributes=>[{attribute=>'.drill',option=>'non_plated'}]); } } #coplanar hole foreach my $ud ('up','down'){ if ($COUPON_DATA->{$ud.'_coplanar_holes'}){ foreach my $it (@{$COUPON_DATA->{$ud.'_coplanar_holes'}}){ $GEN->addPad(x=>$it->{x}+$ShiftX,y=>$it->{y}+$ShiftY,symbol=>'r'.($COUPON_DATA->{coplanar_hole_size} + 2*$COUPON_DATA->{plug_ar}),attributes=>[{attribute=>'.drill',option=>'plated'}]); } } } } } $GEN->deleteLayer(job=>$Job,layer=>$tmp_layer); $GEN->affectedLayer(mode=>'all',affected=>'yes'); $GEN->COM('sel_all_feat'); $GEN->COM('sel_delete_atr',attributes=>'.string'); $GEN->COM('disp_on'); $GEN->affectedLayer(mode=>'all',affected=>'no'); if ($COUPON_DATA->{hooks_draw_post}){ eval($COUPON_DATA->{hooks_draw_post}); } ##阻抗线补偿 Tomy 2017.12.14 阻抗在系统内部有做补偿脚本中不需要再补偿 ###$GEN->COM('disp_off'); ###foreach my $layer (sort {$matrix->{$a}{row} <=> $matrix->{$b}{row}} keys %$matrix) { ### if($matrix->{$layer}{tl_type} =~ /(inner|outer)/ ){ ### my $value = 0; ### if($matrix->{$layer}{tl_type} =~ /(inner)/ ){ ### $value = $IKM->get_jobinfo(-jobid=>$JOB_ID,-jobcategory=>'work',-jobinfo=>'line_compensation_inner'); ### } ### else{ ### $value = $IKM->get_jobinfo(-jobid=>$JOB_ID,-jobcategory=>'work',-jobinfo=>'line_compensation_outer'); ### } ### next unless $value; ### $GEN->affectedLayer(affected=>'yes',layer=>[$layer],clear_before=>'yes'); ### $GEN->selectByFilter(feat_types=>'line\;arc',polarity=>'positive',profile=>'all'); ### $GEN->selAddAttr(attribute=>[{attribute=>'tl_string',text=>'compensation_'.$value.'_mil'}])if ( $GEN->getSelectCount() > 0 ); ### $GEN->selectByFilter(attribute=>[{attribute=>'tl_string',text=>'compensation_'.$value.'_mil'}]); ### $GEN->COM('sel_resize',size=>$value,corner_ctl=>'no')if ( $GEN->getSelectCount() > 0 ); ### } ###} ###$GEN->COM('disp_on'); $GEN->clearLayers(); $GEN->affectedLayer(mode=>'all',affected=>'no'); $GEN->closeStep(); } if ($WarningMsg){ $GUI->msgbox(-icon=>'warning',-text=>join("\n",@$WarningMsg)); #$GEN->PAUSE('Please Edit Then Continue'); my $html = ''; foreach my $item (@$WarningMsg){ $html .= $item.'

'; } $html .=''; $IKM->update_flow_report(-report=>$html,-job_id=>$ARGS{job_id},-process_id=>$ARGS{process_id}); $Return = 'Warning'; } else{ $IKM->update_flow_report(-report=>'',-job_id=>$ARGS{job_id},-process_id=>$ARGS{process_id}); } unless ($GEN->{STATUS}){ return $Return; } else{ $GUI->msgbox(-icon=>'error',-image=>'genesis_error',-compound=>'top',-text=>join("\n",@{$GEN->{STATUS}})); #addFlowNotes(-notes=>" Genesis Error:\n ".join("\n ",@{$GEN->{STATUS}})); return 'Error'; } } catch Error::Simple with { my $error = encode("utf8",shift); print $error,"\n"; $GUI->msgbox(-text=>$error); return 'Error'; } finally{ #$GEN->deleteLayer(layer=>$tmp_layer) if ($GEN->isLayerExists(job=>$job,layer=>$tmp_layer)); }; sub opt_lines{ my @lines = @_; my %lines_hash; my $n = 0; my @return = (shift @lines); foreach my $line (@lines){ $lines_hash{$n++} = $line; } #向前查找 my ($xs,$ys) = ($return[0]{xs},$return[0]{ys}); my ($xe,$ye) = ($return[0]{xe},$return[0]{ye}); my $last_count = 0; while($last_count != scalar(keys %lines_hash)){ $last_count = scalar(keys %lines_hash); foreach my $n (keys %lines_hash){ my $line = $lines_hash{$n}; if (abs($xs - $line->{xs}) < 0.0001 && abs($ys - $line->{ys}) < 0.0001){ ($line->{xs},$line->{ys},$line->{xe},$line->{ye}) = ($line->{xe},$line->{ye},$line->{xs},$line->{ys}); $line->{direction} = ($line->{direction} eq 'cw') ? 'ccw' : 'cw'; ($xs,$ys) = ($line->{xs},$line->{ys}); delete $lines_hash{$n}; unshift @return,$line; } elsif (abs($xs - $line->{xe}) < 0.0001 && abs($ys - $line->{ye}) < 0.0001){ ($xs,$ys) = ($line->{xs},$line->{ys}); delete $lines_hash{$n}; unshift @return,$line; } } } $last_count = 0; while($last_count != scalar(keys %lines_hash)){ $last_count = scalar(keys %lines_hash); foreach my $n (keys %lines_hash){ my $line = $lines_hash{$n}; if (abs($xe - $line->{xs}) < 0.0001 && abs($ye - $line->{ys}) < 0.0001){ ($xe,$ye) = ($line->{xe},$line->{ye}); delete $lines_hash{$n}; push @return,$line; } elsif (abs($xe - $line->{xe}) < 0.0001 && abs($ye - $line->{ye}) < 0.0001){ ($line->{xs},$line->{ys},$line->{xe},$line->{ye}) = ($line->{xe},$line->{ye},$line->{xs},$line->{ys}); $line->{direction} = ($line->{direction} eq 'cw') ? 'ccw' : 'cw'; ($xe,$ye) = ($line->{xe},$line->{ye}); delete $lines_hash{$n}; push @return,$line; } } } return @return; } #pcbpdm里层是存的数字,为了兼容要转为tlname sub imp_layernum2tlname { my $iLyrNum = shift; my $ret; if ($iLyrNum == 1) { $ret = "top"; }elsif ($iLyrNum == $LayerCount) { $ret = "bottom"; }elsif($iLyrNum){ $ret = "l".$iLyrNum; } return $ret; } sub _um2mil{ my $value = shift; return ($value/25.4); }