Commit 55212463 authored by Scott Sun's avatar Scott Sun

scott

parent 59890c98
=head
NAME:
DESCRIPTION: 检查钻孔Pad大小.
PARAMETER:
{items => [
{
name=>'job',
label=>'原稿检查料号名',
type=>'editable_enum',
property=>{
tl_field=>[name=>'text'],
tl_data=>[
{name=>'${JOB}',},
{name=>'${JOB}_org',},
{name=>'${JOB}_chk',},
{name=>'${JOB}_pre',},
]
},
remark=>'原稿检查料号名',
must_field=>1,
value=>'',
},
]}
VERSION_HISTORY:
V1.00 2011-05-27 Tony Guo
1.新版本
HELP:
<html><body bgcolor="#DDECFE">
<font size="3" color="#003DB2"><p>功能简介</p></font>
<p> 检查原稿最小线宽线距.</p>
<br>
<font size="3" color="#003DB2"><p>参数配置</p></font>
<font color="#008000"><p> ● 原稿检查料号名</p></font>
<p> 设置原稿料号名,如:${JOB}_chk;其中${JOB}是代表系统中的料号名.</p>
<font color="#008000"><p> ● CheckList名称</p></font>
<p> 设置CheckList名称.</p>
<font color="#008000"><p> ● Drill Summary CheckList编号</p></font>
<p> 设置Drill Summary CheckList编号.</p>
<br>
</body></html>
=cut
#use strict;
#my ($JOB,$GEN,$GUI,$DB,$JOB_ID,$PAR,$APP,$MW);
use utf8;
use Encode;
use Data::Dump 'dump';
my $Return = 'Done';
my $Job;
my $matrix;
my $max_via_size = 160;
try {
#确定料号名;
if(defined $PAR->{job}){
$Job = $PAR->{job};
$Job =~ s/\$\{JOB\}/$JOB/g;
}
if (!defined $Job or $Job =~ /^\s*$/){
$GUI->msgbox(-icon=>'error',-text=>'未定义料号名');
return 'Error';
}
my $layercount = $DB->get_jobinfo(-jobid=>$JOB_ID,
-jobcategory=>'org',
-jobinfo=>'TL_layer_count');
if ($layercount == 2){
$GUI->msgbox(-text=>"2层板不存在Stack 结构的孔");
$DB->save_jobinfo( -jobid=>$JOB_ID,-jobcategory=>'org',
-jobinfohash=>{ATS_max_laser_stack_num=>0});
return $Return;
}
#判断料号是否存在;
unless ($GEN->isJobExists(job=>$Job)){
$GUI->msgbox(-icon=>'error',-text=>"料号[$Job]不存在!");
return 'Error';
}
$GEN->openJob(job=>$Job);
$GEN->PAUSE("Before Run Script,Drill matrix must be right!And make sure no outline on Drill layers!");
my @steps = $GEN->getStepList(job=>$Job);
my @selstep;
if (@steps != 1){
@selstep = $GUI->select_step(-title=>'请选择包含钻孔信息的Step',-steplist=>\@steps,-selectmode=>'multiple');
return 'Cancel' unless @selstep;
}
else{
@selstep = @steps;
}
#my %matrix = $GEN->getMatrix(job=>$Job);
my %matrix=$GEN->getMatrix(job=>$Job,type=>'hash');
############得到钻孔的层###########
my %drill_info;
foreach my $step(@selstep){
foreach my $drill (sort {$matrix{$a}{row} <=>$matrix{$b}{row}} keys %matrix){
if ($matrix{$drill}{context} eq 'board' and $matrix{$drill}{layer_type} eq 'drill' ){
$drill_info{$step}{$drill} = $matrix{$drill};
if ($drill_info{$step}{$drill}{drl_start_num} > $drill_info{$step}{$drill}{drl_end_num}) {
($drill_info{$step}{$drill}{drl_start_num},$drill_info{$step}{$drill}{drl_end_num}) = ($drill_info{$step}{$drill}{drl_end_num},$drill_info{$step}{$drill}{drl_start_num});
$drill_info{$step}{$drill}{tl_name} = 'drill'.$drill_info{$step}{$drill}{drl_start_num}.'-'.$drill_info{$step}{$drill}{drl_end_num};
}
}
}
}
my %include_symbol;
my %laser_layer;
my %sel_layer;
foreach my $step(@selstep){
$GEN->openStep(job=>$Job,name=>$step);
$GEN->units(type=>'mm');
foreach my $layer(sort {$drill_info{$step}{$a}{drl_start_num} <=>$drill_info{$step}{$b}{drl_start_num} || $drill_info{$step}{$a}{drl_end_num} <=>$drill_info{$step}{$b}{drl_end_num}} keys %{$drill_info{$step}}){
$GEN->workLayer(name=>$layer,clear_before=>'yes');
my @features = $GEN->getFeatures(job=>$Job,step=>$step,layer=>$layer,units=>'mm');
foreach my $size(@features){
if ($size->{symbol}=~/r(\d+.?\d+)/i){
if($1 < $max_via_size){
if (!grep /$1/,@{$include_symbol{$step}{$layer}}){
push @{$include_symbol{$step}{$layer}},"r".$1;
}
}
}
}
if ( not @{$include_symbol{$step}{$layer}}){
next;
}
$GEN->COM('filter_set',filter_name=>"popup",update_popup=>"no",include_syms=>join(";",@{$include_symbol{$step}{$layer}}));
$GEN->COM('filter_area_end',layer=>$layer,filter_name=>"popup",operation=>"select",area_type=>"none",inside_area=>"no",
intersect_area=>"no",lines_only=>"no",ovals_only=>"no",min_len=>0,max_len=>0,min_angle=>0,max_angle=>0);
my $nnn;
if ($GEN->getSelectCount()>0){
foreach my $num($drill_info{$step}{$layer}{drl_start_num}..$drill_info{$step}{$layer}{drl_end_num}-1){
$GEN->COM('filter_area_end',layer=>$layer,filter_name=>"popup",operation=>"select",area_type=>"none",inside_area=>"no",
intersect_area=>"no",lines_only=>"no",ovals_only=>"no",min_len=>0,max_len=>0,min_angle=>0,max_angle=>0);
$nnn=$num+1;
my $tmp_layer = "scr_drl_".$num."_".$nnn;
$GEN->selCopyOther(dest=>'layer_name',target_layer=>$tmp_layer);
$laser_layer{$step}{$tmp_layer}{start_num} = $num;
$laser_layer{$step}{$tmp_layer}{end_num} = $nnn;
push @{$sel_layer{$step}},$tmp_layer if (!grep /$tmp_layer/,@{$sel_layer{$step}});
}
}
}
my $sym = "r120";
foreach my $change_layer(@{$sel_layer{$step}}){
$GEN->workLayer(name=>$change_layer,clear_before=>'yes');
$GEN->selChangeSym(symbol=>$sym);
}
$GEN->closeStep();
}
# $GUI->debug(dump(\%laser_layer));
# $GUI->debug(dump(keys %sel_layer));
# return;
my @layer;
my %laser_stack;
my $tmp_layer = "script_tmp";
# foreach my $step(keys %sel_layer){
foreach my $step(keys %laser_layer){
$GEN->openStep(job=>$Job,name=>$step);
my $i=0;
if (@{$sel_layer{$step}}<2){
$GEN->deleteLayer(step=>$step,job=>$Job,layer=>"scr_drl_1_2") if ($GEN->isLayerExists(job=>$Job,layer=>"scr_drl_1_2"));
$GEN->closeStep();
next;
}
foreach my $layer(@{$sel_layer{$step}}){
my ($sta,$end) = $layer =~ /scr_drl_(\d+)_(\d+)/i;
my $j = $i;
my $sel_count = 0;
$j=$j+1;
my $cul_layer = $layer;
$GEN->copyLayer(source_job=>$Job,source_step=>$step,source_layer=>$cul_layer,dest_layer=>$tmp_layer,mode=>'replace');
while($j<=@{$sel_layer{$step}}){
$GEN->workLayer(name=>$tmp_layer,clear_before=>'yes');
my $next_layer = $sel_layer{$step}[$j];
my $tmp = $sel_layer{$step}[$j-1];
if ($laser_layer{$step}{$tmp}{end_num} == $laser_layer{$step}{$next_layer}{start_num}){
$GEN->selRefFeat(
layers=>$next_layer,
use=>'filter',
# mode=>'touch',
mode=>'cover',
f_types=>'pad',
polarity=>'positive',
filter=>{feat_types=>'pad',
polarity=>'positive',
},
);
if ($GEN->getSelectCount()>0){
$sel_count++;
$GEN->selReverse();
$GEN->selDelete() if($GEN->getSelectCount()>0);
}else{
last;
}
}else{
last;
}
$j++;
}
$GEN->deleteLayer(job=>$Job,step=>$step,layer=>$step.'_drl'.$sta.'_'.$end."_stack_laser") if ($GEN->isLayerExists(job=>$Job,layer=>$step.'_drl'.$sta.'_'.$end."_stack_laser"));
if ($sel_count >= 11) {
$GEN->selCopyOther(dest=>'layer_name',target_layer=>$step.'_drl'.$sta.'_'.$end."_stack_laser");
}
$GEN->deleteLayer(job=>$Job,step=>$step,layer=>$tmp_layer) if ($GEN->isLayerExists(job=>$Job,layer=>$tmp_layer));
$laser_stack{$step}{$layer} = $sel_count;
$i++;
}
$GEN->closeStep();
}
# $GUI->debug(dump(\%laser_stack));
# return;
my $max_stack_via = 0;
foreach my $step (keys %laser_stack){
foreach my $layer(keys %{$laser_stack{$step}}){
$GEN->deleteLayer(job=>$Job,step=>$step,layer=>$layer) if ($GEN->isLayerExists(job=>$Job,layer=>$layer));
if ($max_stack_via < $laser_stack{$step}{$layer}){
$max_stack_via = $laser_stack{$step}{$layer};
}
}
}
# $GUI->debug(dump(%laser_stack));
if ($max_stack_via == 0){
$GUI->msgbox(-text=>"此板不存在Stack 结构的孔");
}
$DB->save_jobinfo( -jobid=>$JOB_ID,-jobcategory=>'org',
-jobinfohash=>{ATS_max_laser_stack_num=>$max_stack_via});
unless ($GEN->{STATUS}){
return $Return;
}
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 = encode("utf8",shift);
$GUI->msgbox(-icon=>'error',-text=>$error);
return 'Error';
}
finally{
};
__END__
=head
NAME:
DESCRIPTION:
PARAMETER:
{items => [
{
name=>'job',
label=>'料号名',
type=>'editable_enum',
property=>{
tl_field=>[name=>'text'],
tl_data=>[
{name=>'${JOB}',},
{name=>'TL_genesis_work_jobname',},
{name=>'TL_genesis_org_jobname',},
]
},
must_field=>1,
remark=>'程序会根据不同的选择来命名Genesis中的料号名字',
value=>'${JOB}_chk',
},
]}
VERSION_HISTORY:
V1.00 2011-06-13 Janson Zhang
1.新版本
V1.01 2015-11-05 Mast Pei
1.检查铜分布率时,先去除掉之前的值
Ferre -- 已经取消, 做错了,需重做
V1.05 2016-04-14 mast
添加 rigid_flex料号,检查内层是否存在SMD/BGA,并需要手动制作到EP层上
V1.06 2016-10-25 mast pei
修改deleteLayer中的bug
V1.07 2016-11-15 John
Change resolution_value to 10um
V1.09 2017-05-09 mast
系统编号:867
2171 料号触发后台服务
计算每层原稿 PCB的 6X6 /9X9/12X12 区域的 铜分布率分布情况。
1. If the left area less than total area 50% ,can skip the small area .
2.offset as 0.5 times by X , Y and X &Y .
3.The calculate area can set 6*6, 9*9 ,12*12mm
V1.09 2017-12-25 mast
添加ATS_org_pcb_area pcb面积计算
V1.10 2019-05-14 mast
按照SSS添加3x3计算模式
V1.11 2019-08-30 mast
系统需求:2364
consider the rout area to calculate the copper density
V1.12 2020-09-07 John
系统需求:3132
Cancel RF PN
HELP:
<html><body bgcolor="#DDECFE">
<font size="3" color="#003DB2"><p>功能简介</p></font>
<p> Create PRE prepare step.</p>
<br>
<font size="3" color="#003DB2"><p>参数配置</p></font>
<font color="#008000"><p> ● 料号名</p></font>
<p> 设置genesis中料号的名字,${JOB}表示跟TopCAM中的料号名字一样,TL_genesis_work_jobname表示用这个料号属性定义的名字</p>
<font color="#008000"><p> ● step过滤</p></font>
<p> 选择step时候的过滤器</p>
<font size="3" color="#003DB2"><p>注意事项</p></font>
<p> ● </p>
<br>
</body></html>
=cut
#use strict;
#my ($JOB,$GEN,$GUI,$DB,$JOB_ID,$PAR,%ARGS);
use utf8;
use Encode;
use Data::Dump 'dump';
my ($Job,$Step);
my $Return = 'Done';
###确定料号名;
# if (defined $PAR->{job} and ($PAR->{job} eq 'TL_genesis_org_jobname' or $PAR->{job} eq 'TL_genesis_work_jobname')){
# $Job = $DB->get_jobinfo(-jobid=>$JOB_ID,-jobcategory=>'work',-jobinfo=>$PAR->{job});
# }
# elsif(defined $PAR->{job}){
# $Job = $PAR->{job};
# $Job =~ s/\$\{JOB\}/$JOB/g;
# $Job = lc($Job);
# }
# if ( ! defined $Job or $Job =~ /^\s*$/) {
# $GUI->msgbox(-icon=>'error',-text=>'未定义料号名');
# return 'Error';
# }
###处理step过滤
my $customer = $ARGS{CUSTOMER};
$Job=$JOB.'_chk';
my $incam = 'no';
if ($GEN->{GEN_TYPE} eq 'incam') {
$incam = 'yes';
}
my @parameter=('3x3','6x6','9x9','12x12');
my $ORG_job= $JOB.'_org';
my $genesisid = `ps -p $$ -o ppid=`;
$genesisid =~ s/\s//g;
$genesisid = `ps -p $genesisid -o ppid=`;
$genesisid =~ s/\s//g;
try{
###检查Genesis料号是否存在并打开
if (! $GEN->isJobExists(job=>$Job) ){
$GUI->msgbox(-icon=>'error',-text=>"料号 $Job 在Genesis中不存在, 请检查!");
return 'Error';
}
my $user_name =$GEN->getUserName();
if ( $user_name=~/^(cam|check|qm|pe|imp|cam\d+|genesis)$/i){
$GUI->msgbox(-icon=>'error',-text=>"[$user_name]账号不能保存资料,请用可以保存的Genesis账号放行资料");
return 'Error';
}
my $genusername =$GEN->getUserName();
my $check = $GEN->checkInout(job=>$ORG_job,mode=>'test');
if ($genusername ne $check and $check!=0) {
$GUI->msgbox(-icon=>'error',-text=>"$ORG_job 被其他用户锁定,请解锁[$check]");
return 'Error';
}
if ($check ==0) {
$GEN->checkInout(job=>$ORG_job,mode=>'out');
}
$GEN->openJob(job=>$ORG_job);
if ($GEN->{STATUS}){
$GUI->msgbox(-icon=>'error',-text=>"$ORG_job [$genusername]打开,[$genusername]关闭料号");
return 'Error';
}
#$GEN->PAUSE("1111111111111 ");
$GEN->openJob(job=>$Job);
my %matrix=$GEN->getMatrix(job=>$Job,type=>'hash');
#$GUI->debug("$customer $Job");
my @tmp_array1 = {
name=>'add_array_copper',
label=>"Array copper",
type=>'enum',
must_field=>1,
property=>{
tl_field=>['name'=>'text',tl_name=>'scalar'],
tl_value_field=>'tl_name',
tl_data=>[
{name=>'YES',tl_name=>'Yes'},
{name=>'NO',tl_name=>'No'},
]
}
};
my %tmp_array = $GUI->show_form(-title=>'请确认Array边是否有铜',-items=>\@tmp_array1,-defaultsize=>[300,300],-showcheck => 1,-gen => $GEN);
return 'Cancel' unless %tmp_array;
$DB->save_jobinfo(
-jobid=>$JOB_ID,
-jobcategory=>'org',
-jobinfohash=>{'ATS_array_frame_with_copper'=>$tmp_array{add_array_copper}});
my $LAYER_COUNT = $DB->get_jobinfo(-jobid=>$JOB_ID,-jobcategory=>'org',-jobinfo=>'TL_layer_count');
my $ans_array;
my @mode=('card');
if($tmp_array{add_array_copper} eq 'Yes'){
@mode=('card','array');
}
# $GUI->debug("@mode $tmp_array{add_array_copper}");
my @steps = $GEN->getStepList(job=>$Job);
my @step_list;
foreach my $step (@steps){
if ($step!~ /^(.*)(\d{8})\-(\d{6})$/){
push @step_list,$step;
}
}
my @items_step_list;
my (@Probfr,@Probba);
foreach my $layer (sort {$matrix{$a}{row} <=> $matrix{$b}{row}} keys %matrix) {
push(@Probfr,{name=>$layer}) if($matrix{$layer}{side} eq 'top' and $matrix{$layer}{layer_type} eq 'solder_mask');
push(@Probba,{name=>$layer}) if($matrix{$layer}{side} eq 'bottom' and $matrix{$layer}{layer_type} eq 'solder_mask');
}
push(@Probfr,{name=>'NA'});
push(@Probba,{name=>'NA'});
foreach my $mode (@mode){
push @items_step_list,{
name => $mode,
label => $mode.' Step',
type => 'step',
must_field=>1,
value=>@step_list==1?$step_list[0]:'',
property=>{
tl_steplist=>[@step_list],
},
};
}
my @sminfo;
push @sminfo,
{
name=>'Probfr',
label=>'Probfr Layer',
type=>'enum',
property=>{
tl_field=>[name=>'text'],
tl_value_field=>'name',
tl_data=>\@Probfr,
},
# must_field=>1,
value => $Probfr[0]->{name} ? $Probfr[0]->{name} : 'NA',
},
{
name=>'Probba',
label=>'Probba Layer',
type=>'enum',
property=>{
tl_field=>[name=>'text'],
tl_value_field=>'name',
tl_data=>\@Probba,
},
# must_field=>1,
value => $Probba[0]->{name} ? $Probba[0]->{name} : 'NA',
};
my %info = $GUI->show_form(
-title => "确认[@mode]step/SM ",
-showcheck => 1,
-gen => $GEN,
-items=>[
{type=>'title',property=>{title=>'1.根据您当前step,请匹配step信息'}},
@items_step_list,
{type=>'title',property=>{title=>'2.Please select solder mask layer'}},
@sminfo,
]
);
return 'Cancel' unless %info;
#my $rf_mark= $GUI ->confirm("是否是RF料号");
my $rf_mark= "no";
my $mark_rout_area;
if ($info{card} eq $info{array}) {
@mode=('array','card');
$mark_rout_area='yes';
}
my $rout_copper_array='rout_copper_array';
my $base_copper='base_copper_script';
my $rout_copper='rout_copper_script';
$GEN->openStep(job=>$Job,name=>$steps[0]);
_deleteLayer(step=>$steps[0],layer=>[$rout_copper_array,$base_copper,$rout_copper]);
my %sync_base_copper;
my $pcb_step_tmp;
foreach my $layer (sort {$matrix{$a}{row} <=> $matrix{$b}{row}} keys %matrix) {
if(defined($matrix{$layer}{tl_name}) and $matrix{$layer}{tl_name} =~ /^(top|bottom|l\d+)$/ ){
my $tl = $matrix{$layer}{tl_name};
foreach my $att ('TL_array_copper_distribution','TL_card_copper_distribution'){
$DB->save_layerinfo(-jobid=>$JOB_ID,
-tlname=>$tl,
-jobcategory=>'org',
-layerinfohash=>{$att=>''}
);
}
foreach my $att ('TL_array_copper_distribution_add_rout_area','TL_card_copper_distribution_add_rout_area'){
$DB->save_layerinfo(-jobid=>$JOB_ID,
-tlname=>$tl,
-jobcategory=>'org',
-layerinfohash=>{$att=>''}
);
}
}
}
foreach my $checkstep (@mode) {
my $copper_distribution;
my ($area_all,$area_tmp);
if ( $checkstep eq 'array' ) {
$ans_array = $GUI ->confirm('Have array data exists for the copper distribution?');
if ($ans_array eq 'no'){
$mark_rout_area='yes';
next;
}
}
my $step = $info{$checkstep};
$GEN->openStep(job=>$Job,name=>$step);
$GEN->closeStep();
$GEN->openStep(job=>$Job,name=>$step);
$GEN->clearLayers();
$GEN->affectedLayer(mode=>'all',affected=>'no');
$GEN->units(type=>'mm');
$GEN->zoomHome();
#$GEN->closeJob(job=>$ORG_job);
return unless($GEN->PAUSE("Please change the[$Job] [$checkstep] profile to get the copper area for Step [${step}]!"));
#my $ans = $GEN->PAUSE("Please change the [$checkstep] profile to get the copper area for Step [${step}]!");
#unless (defined $ans and $ans eq 'OK' ) {
# return 'Cancel';
#}
# if ($customer eq 'APP' and $checkstep eq 'card' and $incam eq 'no'){
if (
## Open For All PNs at 2018-01-02
#$customer eq 'APP' and
$checkstep eq 'card'){
if ($mark_rout_area ne 'yes') {
my $profile_limits = $GEN->getProfileLimits(job=>$Job,step=>$step,units=>'mm');
my $profile_x=$profile_limits->{xsize};
my $profile_y=$profile_limits->{ysize};
$GEN->createLayer(job=>$Job,layer=>$base_copper,conext=>'misc',type=>'signal')if (!$GEN->isLayerExists(job=>$Job,layer=>$base_copper));
$GEN->units(type=>'inch');
$GEN->srFill(dest=>'layer_name',layer=>$base_copper);
$GEN->units(type=>'mm');
$GEN->workLayer(name=>$base_copper,number=>1);
$GUI->msgbox(-text=>"请给${checkstep}[$step]制作铜面区域;去除Routing区域废铜\n用来计算'3x3','6x6','9x9','12x12' area,不需考虑Routing/Npth避铜问题");
return unless($GEN->PAUSE("Pls delete the dummy copper on routing area of layer [ $base_copper ] by manually"));
$GEN->checkInout(job=>$Job,mode=>'out');
$GEN->units(type=>'mm');
$GEN->clearLayers();
$GEN->affectedLayer(mode=>'all',affected=>'no');
$GEN->workLayer(name=>$base_copper,number=>1);
$GEN->selContourize();
#$sync_base_copper{$step}=$base_copper;
push @{$sync_base_copper{$step}},$base_copper if(!grep /@{$sync_base_copper{$step}}/,$base_copper);
$GEN->createLayer(job=>$Job,layer=>$rout_copper,conext=>'misc',type=>'signal')if (!$GEN->isLayerExists(job=>$Job,layer=>$rout_copper));
$GEN->units(type=>'inch');
$GEN->workLayer(name=>$rout_copper,number=>1);
$GEN->srFill(dest=>'layer_name',layer=>$rout_copper);
$GEN->units(type=>'mm');
if ($GEN->isLayerExists(job=>$Job,layer=>$base_copper)) {
#$GEN->COM('sel_resize',size=>-4000,corner_ctl=>'no');
$GEN->copyLayer(source_job=>$Job,
source_step=>$step,
source_layer=>$base_copper,
dest_layer=>$rout_copper,
invert=>'yes',
mode=>'append',
);
$GEN->selContourize();
$GEN->COM('sel_resize',size=>-4000,corner_ctl=>'no');
}
}
else{
$GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>[$base_copper,$rout_copper],clear_before=>'yes');
$GEN->COM('clip_area_strt');
$GEN->COM('clip_area_end,layers_mode=affected_layers,layer=,area=profile,area_type=rectangle,inout=outside,contour_cut=no,margin=0');
}
my $copper_area = $GEN->copperArea(layer1=>$base_copper,resolution_value=>10);
my $area =sprintf ('%.4f',$copper_area->{area} / 10000); ### units: dm2
$DB->save_jobinfo(
-jobid=>$JOB_ID,
-jobcategory=>'org',
-jobinfohash=>{'ATS_org_pcb_area'=>$copper_area->{area}/0.00001});
$GEN->saveJob(job=>$Job);
if ($incam ne 'no') {
$GEN->checkInout(job=>$Job,mode=>'in');
$GEN->checkInout(job=>$Job,mode=>'out');
}
unless ($GEN->{STATUS}){
$pcb_step_tmp = $step;
}
}
elsif ($mark_rout_area eq 'yes') {
my $profile_limits = $GEN->getProfileLimits(job=>$Job,step=>$step,units=>'mm');
my $profile_x=$profile_limits->{xsize};
my $profile_y=$profile_limits->{ysize};
my $base_copper='base_copper_script';
$GEN->createLayer(job=>$Job,layer=>$base_copper,conext=>'misc',type=>'signal')if (!$GEN->isLayerExists(job=>$Job,layer=>$base_copper));
$GEN->units(type=>'inch');
$GEN->srFill(dest=>'layer_name',layer=>$base_copper);
$GEN->units(type=>'mm');
$GEN->workLayer(name=>$base_copper,number=>1);
$GUI->msgbox(-text=>"请给${checkstep}[$step]制作铜面区域;去除Routing区域废铜\n用来计算'3x3','6x6','9x9','12x12' area,不需考虑Routing/Npth避铜问题");
return unless($GEN->PAUSE("Pls make copper on [$base_copper],use cal '3x3','6x6','9x9','12x12' area"));
$GEN->checkInout(job=>$Job,mode=>'out');
$GEN->units(type=>'mm');
$GEN->clearLayers();
$GEN->affectedLayer(mode=>'all',affected=>'no');
$GEN->workLayer(name=>$base_copper,number=>1);
$GEN->selContourize();
$GEN->createLayer(job=>$Job,layer=>$rout_copper,conext=>'misc',type=>'signal')if (!$GEN->isLayerExists(job=>$Job,layer=>$rout_copper));
$GEN->units(type=>'inch');
$GEN->workLayer(name=>$rout_copper,number=>1);
$GEN->srFill(dest=>'layer_name',layer=>$rout_copper);
$GEN->units(type=>'mm');
if ($GEN->isLayerExists(job=>$Job,layer=>$base_copper)) {
$GEN->COM('sel_resize',size=>-4000,corner_ctl=>'no');
$GEN->copyLayer(source_job=>$Job,
source_step=>$step,
source_layer=>$base_copper,
dest_layer=>$rout_copper,
invert=>'yes',
mode=>'append',
);
$GEN->selContourize();
$GEN->COM('sel_resize',size=>-4000,corner_ctl=>'no');
#$sync_base_copper{$step}=$rout_copper;
push @{$sync_base_copper{$step}},$rout_copper if(!grep /@{$sync_base_copper{$step}}/,$rout_copper);
}
push @{$sync_base_copper{$step}},$base_copper if(!grep /@{$sync_base_copper{$step}}/,$base_copper);
$GEN->openJob(job=>$ORG_job);
my @org_steps = $GEN->getStepList(job=>$ORG_job);
foreach my $step (keys %sync_base_copper){
if ($GEN->isStepExists(job=>$ORG_job,step=>$step) ) {
$GEN->openStep(job=>$ORG_job,name=>$step);
foreach my $f (@{$sync_base_copper{$step}}){
my $f1 ='ats_rout_copper_ref' if ($f=~/rout_copper/);
$f1 ='ats_base_copper_ref' if ($f=~/base_copper/);
$GEN->copyLayer(source_job=>$Job,
source_step=>$step,
source_layer=>$f,
dest_layer=>$f1,
);
}
$GEN->closeStep();
}
else{
my $step1 = $GUI->select_step(
-title => "[$step]所对应的${ORG_job}中的Step",
-steplist => [@org_steps],
);
return 'Cancel' unless ( $step1);
$GEN->openStep(job=>$ORG_job,name=>$step1);
foreach my $f (@{$sync_base_copper{$step}}){
my $f1 ='ats_rout_copper_ref' if ($f=~/rout_copper/);
$f1 ='ats_base_copper_ref' if ($f=~/base_copper/);
$GEN->copyLayer(source_job=>$Job,
source_step=>$step,
source_layer=>$f,
dest_layer=>$f1,
);
}
$GEN->closeStep();
}
}
$GEN->closeJob(job=>$ORG_job)
}
my (%copper_distribution,%copper_distribution_add_rout);
$GEN->openStep(job=>$Job,name=>$step);
$GEN->units(type=>'mm');
$GEN->clearLayers();
$GEN->affectedLayer(mode=>'all',affected=>'no');
my $tmp_copper='ats_script_copper';
my ($layer_profile,@have_sel_line);
while(1){
my $mm;
foreach my $layer (sort {$matrix{$a}{row} <=> $matrix{$b}{row}} keys %matrix) {
if(defined($matrix{$layer}{tl_name}) and $matrix{$layer}{tl_name} =~ /^(top|bottom|l\d+)$/ ){
$mm++;
_deleteLayer(step=>$step,layer=>[$tmp_copper]);
if ($rf_mark =~/yes/i and $checkstep eq 'card' and $mm==1){
if (!$layer_profile){
$GUI->msgbox(-icon=>'info',-text=>"RF JOB:请确认硬板区域out层的线宽不一样.");
my $ans = $GEN->PAUSE("RF job:Pls change.");
unless (defined $ans and $ans eq 'OK' ) {
return 'Cancel';
}
$layer_profile = $GUI->select_layer(-title=>'选择硬板区域out层',
-layermatrix=>{$GEN->getMatrix(job=>$Job,type=>'hash')},
-selectmode => 'single');
return 'Cancel' if(!$layer_profile);
my %symlist = $GEN->getLayerSymsHist(job=>$Job,step=>$step,layer=>$layer_profile,units=>"mm");
foreach my $symbol (keys %symlist) {
if ( $symlist{$symbol}{line} > 0 or $symlist{$symbol}{arc} > 0 ) {
push @have_sel_line,$symbol if (!grep /$symbol$/,@have_sel_line);
}
}
}
$GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>[$layer_profile],clear_before=>'yes');
$GEN->selectByFilter(
feat_types=>'line\;arc',
include_syms=>$have_sel_line[0],
);
@have_sel_line=grep{$_ ne $have_sel_line[0]}@have_sel_line;
if ($GEN->getSelectCount()>0){
$GEN->COM('sel_create_profile');
$GEN->affectedLayer(mode=>'all',affected=>'no');
}
else{
$GUI->msgbox(-icon=>'error',-text=>"profile没有定义成功");
return 'Error';
}
# $GEN->PAUSE("11111111111111");
_deleteLayer(step=>$step,layer=>['rf_ats_script_copper']);
$GEN->COM('create_layer',layer=>'rf_ats_script_copper') if (!$GEN->isLayerExists(job=>$Job,layer=>'rf_ats_script_copper'));
_copperFill('rf_ats_script_copper','solid','',0.0254,0.0254,'positive',0,0,0,0,'no');
$GEN->units(type=>'mm');
my $copper_area = $GEN->copperArea(layer1=>'rf_ats_script_copper',resolution_value=>10);
$copper_distribution{$matrix{$layer}->{tl_name}}{area_all}+=$copper_area->{area} if ($rf_mark =~/yes/i);
}
# $GUI->debug(dump \%copper_distribution);
$GEN->flattenLayer(source_layer=>$layer,target_layer=>$tmp_copper);
$GEN->workLayer(name=>$tmp_copper,number=>1);
$GEN->COM('clip_area_strt');
# $GEN->PAUSE("$copper_area->{area} $layer ");
$GEN->COM('clip_area_end',layers_mode=>'affected_layers',
# layer=>'',
area=>'profile',
area_type=>'rectangle',
inout=>'outside',
contour_cut=>'yes',
margin=>0);
# $GUI->debug(dump \%copper_distribution);
$GEN->units(type=>'mm');
my $copper_area = $GEN->copperArea(layer1=>$tmp_copper,resolution_value=>10);
$copper_distribution{$matrix{$layer}->{tl_name}}{area_tmp}+=$copper_area->{area} if ($rf_mark =~/yes/i);
$copper_distribution{$matrix{$layer}->{tl_name}}{area_all}=$copper_distribution{'top'}{area_all} if ($rf_mark =~/yes/i);
$copper_distribution{$matrix{$layer}->{tl_name}}{percent}=$copper_area->{percent};
if (grep /^card$/,@mode and $checkstep eq 'array') {
if (!$GEN->isLayerExists(job=>$Job,layer=>$rout_copper_array)) {
if ($GEN->isLayerExists(job=>$Job,layer=>$rout_copper)) {
$GEN->flattenLayer(source_layer=>$rout_copper,target_layer=>$rout_copper_array);
}
}
if (!$GEN->isLayerEmpty(job=>$Job,step=>$step,layer=>$rout_copper_array)){
push @{$sync_base_copper{$step}},$rout_copper_array if(!grep /@{$sync_base_copper{$step}}/,$rout_copper_array);
$GEN->copyLayer(source_job=>$Job,
source_step=>$step,
source_layer=>$rout_copper_array,
dest_layer=>$tmp_copper,
mode=>'append');
my $copper_area1 = $GEN->copperArea(layer1=>$tmp_copper,resolution_value=>10);
$copper_distribution_add_rout{$matrix{$layer}->{tl_name}}{percent}+=$copper_area1->{percent};
}
}
elsif ($GEN->isLayerExists(job=>$Job,layer=>$rout_copper)) {
if (!$GEN->isLayerEmpty(job=>$Job,step=>$step,layer=>$rout_copper)){
push @{$sync_base_copper{$step}},$rout_copper if(!grep /@{$sync_base_copper{$step}}/,$rout_copper);
$GEN->copyLayer(source_job=>$Job,
source_step=>$step,
source_layer=>$rout_copper,
dest_layer=>$tmp_copper,
#invert=>'yes',
mode=>'append',
);
my $copper_area1 = $GEN->copperArea(layer1=>$tmp_copper,resolution_value=>10);
$copper_distribution_add_rout{$matrix{$layer}->{tl_name}}{percent}+=$copper_area1->{percent};
}
}
}
}
if ($rf_mark !~/yes/i ){
last;
}
elsif ($rf_mark =~/yes/i){
last if (!@have_sel_line);
}
}
# $GUI->debug(dump \%copper_distribution);
foreach my $tl(keys %copper_distribution){
if (defined $copper_distribution{$tl}{area_tmp} and defined $copper_distribution{$tl}{area_all}){
my$rr=sprintf("%.3f",($copper_distribution{$tl}{area_tmp}/$copper_distribution{$tl}{area_all})*100);
$DB->save_layerinfo(-jobid=>$JOB_ID,
-tlname=>$tl,
-jobcategory=>'org',
-layerinfohash=>{'TL_'.$checkstep.'_copper_distribution'=>$rr}
);
}
else{
$DB->save_layerinfo(-jobid=>$JOB_ID,
-tlname=>$tl,
-jobcategory=>'org',
-layerinfohash=>{'TL_'.$checkstep.'_copper_distribution'=>$copper_distribution{$tl}{percent}}
);
$DB->save_layerinfo(-jobid=>$JOB_ID,
-tlname=>$tl,
-jobcategory=>'org',
-layerinfohash=>{'TL_'.$checkstep.'_copper_distribution_add_rout_area'=>$copper_distribution_add_rout{$tl}{percent}}
) if ($copper_distribution_add_rout{$tl}{percent});
}
}
_deleteLayer(step=>$step,layer=>['script_tmp']);
if ( $checkstep eq 'card' ) {
if ($rf_mark =~/yes/i){
my $ans = $GEN->PAUSE("RF job:Please change the [$checkstep] profile to get the SM point for Step [${step}] all !");
unless (defined $ans and $ans eq 'OK' ) {
return 'Cancel';
}
}
next if ($info{Probfr} eq 'NA' and $info{Probba} eq 'NA');
foreach my $layer ($info{Probfr},$info{Probba}) {
next if ($layer eq 'NA');
#转标准层名 存入数据库
my $standard_layer_name=$matrix{$layer}->{tl_name};
$GEN->copyLayer(source_job=>$Job,
source_step=>$step,
source_layer=>$layer,
dest_layer=>$layer.'1',
mode=>'replace');
$GEN->zoomHome();
$GEN->workLayer(name=>$layer.'1',number=>1);
$GEN->selBreak();
$GEN->selContourize();
$GEN->COM('sel_decompose',overlap=>'yes');
$GEN->COM('clip_area_strt');
$GEN->COM('clip_area_end,layers_mode=affected_layers,layer=,area=profile,area_type=rectangle,inout=outside,contour_cut=no,margin=0');
$GEN->selectByFilter(
feat_types=>'surface',
profile=>'in',
);
#$GEN->PAUSE("opop fffff 55555");
my $num = $GEN->getSelectCount();
#$GEN->PAUSE("opop fffff 55555 $num");
#$GEN->COM('reread_layer',layer=>$layer);
$DB->save_layerinfo(-jobid=>$JOB_ID,
-tlname=>$standard_layer_name,
-jobcategory=>'org',
-layerinfohash=>{'ATS_sm_opening_num'=>$num,}
);
}
}
}
$GEN->clearLayers();
$GEN->affectedLayer(mode=>'all',affected=>'no');
my @org_steps = $GEN->getStepList(job=>$ORG_job);
if ($mark_rout_area ne 'yes'){
$GEN->openJob(job=>$ORG_job);
foreach my $step (keys %sync_base_copper){
if ($GEN->isStepExists(job=>$ORG_job,step=>$step) ) {
$GEN->openStep(job=>$ORG_job,name=>$step);
foreach my $f (@{$sync_base_copper{$step}}){
my $f1 ='ats_rout_copper_ref' if ($f=~/rout_copper/);
$f1 ='ats_base_copper_ref' if ($f=~/base_copper/);
$GEN->copyLayer(source_job=>$Job,
source_step=>$step,
source_layer=>$f,
dest_layer=>$f1,
);
}
}
else{
my $step1 = $GUI->select_step(
-title => "[$step]所对应的${ORG_job}中的Step",
-steplist => [@org_steps],
);
return 'Cancel' unless ( $step1);
$GEN->openStep(job=>$ORG_job,name=>$step1);
foreach my $f (@{$sync_base_copper{$step}}){
my $f1 ='ats_rout_copper_ref' if ($f=~/rout_copper/);
$f1 ='ats_base_copper_ref' if ($f=~/base_copper/);
$GEN->copyLayer(source_job=>$Job,
source_step=>$step,
source_layer=>$f,
dest_layer=>$f1,
);
}
}
}
$GEN->closeStep();
}
$GEN->openStep(job=>$ORG_job,name=>$org_steps[0]);
$GEN->saveJob(job=>$ORG_job);
$GEN->checkInout(job=>$ORG_job,mode=>'in');
$GEN->closeJob(job=>$ORG_job);
if ($GEN->{STATUS}){
$GUI->msgbox(-icon=>'error',-text=>join("\n",@{$GEN->{STATUS}}));
return 'Error';
}
###output and return status, if genesis error, it will output genesis error command
unless ($GEN->{STATUS}){
if ($pcb_step_tmp) {
my $return1 = $DB->insert(
-table=>'ats_genesis_background_server',
-data=>{
job_name=>$Job,
step_name=>$pcb_step_tmp,
status=> 'Active',
use_mode => 'check_pcb_copper_density',
try_times=>1,
layer_name => '',
job_id=>$JOB_ID,
cam_user=>$APP->{USER_NAME},
process_id=>$ARGS{process_id},
parameter=>(dump @parameter),
},
-return=>['id'],
);
if (!$return1->{id}){
$GUI->msgbox(-icon=>'error',-text=>"Update database error,请重新申请");
return 'Error';
}
if ($GEN->{STATUS}){
$GUI->msgbox(-icon=>'error',-text=>join("\n",@{$GEN->{STATUS}}));
return 'Error';
}
}
return $Return;
}
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 = encode("utf8",shift);
$GUI->msgbox(-icon=>'error',-text=>$error);
return 'Error';
}
finally{
};
sub _deleteLayer{
my %par = @_;
foreach my $layer(@{$par{layer}}){
$GEN->deleteLayer(layer=>$layer) if ($GEN->isLayerExists(job=>$Job,layer=>$layer));
}
$GEN->openStep(job=>$Job,name=>$par{step}) if ($par{step});
}
sub _copperFill {
my $layer = shift;
my $type = shift;
my $symbol = shift;
my $dx = shift;
my $dy = shift;
my $polarity = shift;
my $step_x = shift;
my $step_y = shift;
my $sr_x = shift;
my $sr_y = shift;
my $consider_feat = (shift or 'yes');
my $feat_margin = (shift or 0.03);
$GEN->COM('fill_params',
type=>$type,
origin_type=>"datum",
solid_type=>"surface",
min_brush=>1,
use_arcs=>"yes",
symbol=>$symbol,
dx=>$dx,
dy=>$dy,
break_partial=>"yes",
cut_prims=>"no",
outline_draw=>"no",
outline_width=>0,
outline_invert=>"no");
$GEN->COM('sr_fill',
polarity=>$polarity,
step_margin_x=>$step_x,
step_margin_y=>$step_y,
step_max_dist_x=>100,
step_max_dist_y=>100,
sr_margin_x=>$sr_x,
sr_margin_y=>$sr_y,
sr_max_dist_x=>0,
sr_max_dist_y=>0,
nest_sr=>"no",
consider_feat=>$consider_feat,
feat_margin=>$feat_margin,
consider_drill=>"no",
drill_margin=>0,
consider_rout=>"no",
dest=>'layer_name',
layer=>$layer,
attributes=>"no");
}
=head
NAME:
DESCRIPTION:
PARAMETER:
{items => [
{
name=>'job',
label=>'料号名',
type=>'editable_enum',
property=>{
tl_field=>[name=>'text'],
tl_data=>[
{name=>'${JOB}',},
{name=>'TL_genesis_work_jobname',},
{name=>'TL_genesis_org_jobname',},
]
},
must_field=>1,
value=>'${JOB}_chk',
},
{
name=>'send_mail',
label=>'是否发邮件',
type=>'editable_enum',
property=>{
tl_field=>[name=>'text'],
tl_data=>[
{name=>'yes',},
{name=>'no',},
]
},
must_field=>1,
value=>'yes',
},
{
name=>'mail_group',
label=>'Mail Group Name',
type=>'string',
must_field=>1,
value => 'goldarea>2.5sqin',
},
]}
VERSION_HISTORY:
V1.00 2011-06-13 Janson Zhang
1.新版本
V1.01 2011-06-13 John Sun
1.INCAM 中没有ATS菜单下的功能,现在用另外一种方法来代替完成,保证INCAM和Genesis能同时运行。
V1.02 2016-10-26 mast pei
修改deleteLayer中的bug
V1.03 2019-07-25 mast pei
添加自动邮件 系统需求:2264
V1.04 2020-08-11 weiss
确认为多card板子时直接完成脚本 CQ2系统需求:2174
V1.05 2020-05-05 mast pei
添加自动邮件 系统需求:2822
修改触发邮件规则 和条件
V1.06 2020-09-07 John
系统需求:3132
Cancel RF PN
HELP:
<html><body bgcolor="#DDECFE">
<font size="3" color="#003DB2"><p>功能简介</p></font>
<p> Create PRE prepare step.</p>
<br>
<font size="3" color="#003DB2"><p>参数配置</p></font>
<font color="#008000"><p> ● 料号名</p></font>
<p> 设置genesis中料号的名字,${JOB}表示跟TopCAM中的料号名字一样,TL_genesis_work_jobname表示用这个料号属性定义的名字</p>
<font size="3" color="#003DB2"><p>注意事项</p></font>
<p> ● </p>
<br>
</body></html>
=cut
#use strict;
#my ($JOB,$GEN,$GUI,$DB,$JOB_ID,$PAR,$APP);
use utf8;
use Encode;
use_module('ATS::GenMath');
use Data::Dump 'dump';
use_module('Top::MailSender');
my $ATS_GenMath = ATS::GenMath->new();
my ($Job,$Step);
my $Return = 'Done';
my $incam = 'no';
if ($GEN->{GEN_TYPE} =~/incam/i) {
$incam = 'yes';
}
###确定料号名;
if (defined $PAR->{job} and ($PAR->{job} eq 'TL_genesis_org_jobname' or $PAR->{job} eq 'TL_genesis_work_jobname')){
$Job = $DB->get_jobinfo(-jobid=>$JOB_ID,-jobcategory=>'work',-jobinfo=>$PAR->{job});
}
elsif(defined $PAR->{job}){
$Job = $PAR->{job};
$Job =~ s/\$\{JOB\}/$JOB/g;
$Job = lc($Job);
}
if ( ! defined $Job or $Job =~ /^\s*$/) {
$GUI->msgbox(-icon=>'error',-text=>'未定义料号名');
return 'Error';
}
my $PLAN_STATE='SHA';
if ( $DB->{DB_NAME} =~ /ATC/i) {
$PLAN_STATE='CQ';
}
###处理step过滤
$PAR->{step_filter} = $PAR->{step_filter} ? $PAR->{step_filter} : '.*';
try{
if ($PLAN_STATE eq 'CQ' and $GUI->confirm("是否存在多card 需要用array拼好后在pre分析?") eq 'yes' ){
return $Return;
}
###检查Genesis料号是否存在并打开
if (! $GEN->isJobExists(job=>$Job) ){
$GUI->msgbox(-icon=>'error',-text=>"料号 $Job 在Genesis中不存在, 请检查!");
return 'Error';
}
$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 0;
}
elsif (@steps != 1){
my @tmp_steps = grep(/$PAR->{step_filter}/,@steps);
if ( @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->clearLayers();
$GEN->affectedLayer(mode=>'all',affected=>'no');
$GEN->units(type=>'inch');
my $ans = $GEN->PAUSE("Please check the profile which used as check area!");
unless (defined $ans and $ans eq 'OK' ) {return 'Cancel';}
#my $rf_mark= $GUI ->confirm("是否是RF料号");
my $rf_mark="no";
if ($rf_mark eq 'yes'){
$GUI->msgbox(-icon=>'info',-text=>'请检查软板层上是否有SMD/BGA要算金面积');
return unless ($GEN->PAUSE("Pls checking"));
}
my (@tl_data,@Front,@Back,@Probfr,@Probba,@Goldfr,@Goldba,@Drill);
my %matrix=$GEN->getMatrix(job=>$Job,type=>'hash');
foreach my $layer (sort {$matrix{$a}{row} <=> $matrix{$b}{row}} keys %matrix) {
push(@tl_data,{name=>$layer});
push(@Front,{name=>$layer}) if(defined($matrix{$layer}{tl_name}) and $matrix{$layer}{tl_name} =~ /^(top)$/ );
push(@Back,{name=>$layer}) if(defined($matrix{$layer}{tl_name}) and $matrix{$layer}{tl_name} =~ /^(bottom)$/);
push(@Probfr,{name=>$layer}) if($matrix{$layer}{side} eq 'top' and $matrix{$layer}{layer_type} eq 'solder_mask');
push(@Probba,{name=>$layer}) if($matrix{$layer}{side} eq 'bottom' and $matrix{$layer}{layer_type} eq 'solder_mask');
push(@Goldfr,{name=>$layer}) if($matrix{$layer}{side} eq 'top' and $matrix{$layer}{layer_type} eq 'solder_paste');
push(@Goldba,{name=>$layer}) if($matrix{$layer}{side} eq 'bottom' and $matrix{$layer}{layer_type} eq 'solder_paste');
push(@Drill,{name=>$layer}) if($matrix{$layer}{layer_type} eq 'drill');
}
my $layerinfo = [
{type=>'title',property=>{title=>'1.Carbon layer'}},
{
name=>'Carbon_layer',
label=>'Is Carbon layer',
type=>'enum',
property=>{
tl_field=>[name=>'text'],
tl_value_field => 'name',
tl_data=>[
{name=>'Yes',},
{name=>'No',},
]
},
must_field=>1,
value=>'No',
},
{type=>'title',property=>{title=>'2.array or card'}},
{
name=>'sel',
label=>'Surface calculation is based on',
type=>'radio',
property=>{
tl_columns=>3,
tl_list=>['Array'=>'Array','Card'=>'Card'],
},
must_field=>1,
value=>'',
},
{type=>'title',property=>{title=>'3.Setting'}},
{
name=>'Front',
label=>'Front Layer',
type=>'enum', #editable_enum
property=>{
tl_field=>[name=>'text'],
tl_value_field=>'name',
tl_data=>\@Front,
},
must_field=>1,
value => (($#Front == 0) ? $Front[0]->{name} : ''),
},
#2
{
name=>'Probfr',
label=>'Probfr Layer',
type=>'enum',
property=>{
tl_field=>[name=>'text'],
tl_value_field=>'name',
tl_data=>\@Probfr,
},
#must_field=>1,
value => ($#Probfr == 0) ? $Probfr[0]->{name} : '',
},
#3
{
name=>'Goldfr',
label=>'Front Reference Layer',
type=>'enum',
property=>{
tl_field=>[name=>'text'],
tl_value_field=>'name',
#tl_data=>\@Goldfr,
tl_data=>[{name=>''},@Goldfr],
},
#must_field=>1,
value => ($#Goldfr == 0) ? $Goldfr[0]->{name} : '',
},
#4
{
name=>'Reffr',
label=>'Front Reference As',
type=>'enum',
property=>{
tl_field=>[name=>'text'],
tl_value_field=>'name',
tl_data=>[
{name=>''},
{name=>'GOLD'},
{name=>'OSP'},
],
},
value => '',
},
#5
{
name=>'Back',
label=>'Back Layer',
type=>'enum',
property=>{
tl_field=>[name=>'text'],
tl_value_field=>'name',
tl_data=>\@Back,
},
must_field=>1,
value => ($#Back == 0) ? $Back[0]->{name} : '',
},
#6
{
name=>'Probba',
label=>'Probba Layer',
type=>'enum',
property=>{
tl_field=>[name=>'text'],
tl_value_field=>'name',
tl_data=>\@Probba,
},
#must_field=>1,
value => ($#Probba == 0) ? $Probba[0]->{name} : '',
},
#7
{
name=>'Goldba',
label=>'Back Reference Layer',
type=>'enum',
property=>{
tl_field=>[name=>'text'],
tl_value_field=>'name',
tl_data=>\@Goldba,
tl_data=>[{name=>''},@Goldba],
},
value => ($#Goldba == 0) ? $Goldba[0]->{name} : '',
},
#8
{
name=>'Refba',
label=>'Back Reference As',
type=>'enum',
property=>{
tl_field=>[name=>'text'],
tl_value_field=>'name',
tl_data=>[
{name=>''},
{name=>'GOLD'},
{name=>'OSP'},
],
},
value => '',
},
#9
{
name=>'Drill',
label=>'Main Drill Layer',
type=>'enum',
property=>{
tl_field=>[name=>'text'],
tl_value_field=>'name',
tl_data=>[{name=>'NA'},@Drill],
},
must_field=>1,
value => '',
},
#10
{
name=>'Thickness',
label=>'Board Thickness(mm)',
type=>'number',
units=> 'mm',
must_field=>1,
value =>1.0,
validation=>[
{
condition=>'$Value < 0.1',
msg_type=>'error',
msg=>'Value should > 0.1',
style=>{base=>'red'},
},
{
condition=>'$Value > 3',
msg_type=>'error',
msg=>'Value should < 3',
style=>{base=>'red'},
},
]
},
];
$layerinfo = $GUI->show_form(
-title=>'Please fill the layer name',-defaultsize => [740,660],
-showcheck => 1,-gen => $GEN,
-items=>$layerinfo);
return 'Cancel' unless (%$layerinfo);
my $thick=$layerinfo->{'Thickness'}*1000;
$ans = $GEN->PAUSE('Please contourize surface to save script running time');
unless (defined $ans and $ans eq 'OK' ) {
return 'Cancel';
}
@steps = $GEN->getStepList(job=>$Job);
_deleteLayer(step=>$steps[0],layer=>['qec_goldfr','qec_goldba','qec_ospfr','qec_ospba',
'rel_qec_goldfr+qec_ospfr','rel_qec_goldba+qec_ospba',
'qec_goldfr+++','qec_goldba+++','qec_ospfr+++','qec_ospba+++',
'rel_qec_goldfr+qec_ospfr+++','rel_qec_goldba+qec_ospba+++']);
if ($layerinfo->{Drill} eq 'NA'){
$layerinfo->{Drill} = 'ats_drill' ;
$GEN->matrixAddLayer(job=>$Job,layer=>$layerinfo->{Drill},type=>'drill',context=>'board',polarity=>'positive',) unless ($GEN->isLayerExists(job=>$Job,layer=>$layerinfo->{Drill}));
}
_deleteLayer(step=>$Step,layer=>['ref_layer_c_fr','ref_layer_c_ba']);
foreach my $subStep (@steps){
next if ($subStep =~ /^(.*)(\d{8})\-(\d{6})$/) ;
$GEN->openStep(job=>$Job,name=>$subStep);
$GEN->units(type=>'mm');
$GEN->createLayer(job=>$Job,layer=>'ats_empty') unless ($GEN->isLayerExists(job=>$Job,layer=>'ats_empty'));
if ($incam eq 'no'){
if ($layerinfo->{Goldfr} and $layerinfo->{Reffr}){
CreateGoldLayer($layerinfo->{Front},$layerinfo->{Probfr},$layerinfo->{Goldfr},$layerinfo->{Reffr},$layerinfo->{Drill},'qec_goldfr','qec_ospfr');
}
elsif ($layerinfo->{Front} and $layerinfo->{Probfr}){
$GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>[$layerinfo->{Front},$layerinfo->{Probfr}],clear_before=>'yes');
calc_area('ref_layer_c_fr');
}
if ($layerinfo->{Goldba} and $layerinfo->{Refba}){
CreateGoldLayer($layerinfo->{Back} ,$layerinfo->{Probba},$layerinfo->{Goldba},$layerinfo->{Refba},$layerinfo->{Drill},'qec_goldba','qec_ospba') ;
}
elsif ($layerinfo->{Back} and $layerinfo->{Probba}){
$GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>[$layerinfo->{Back},$layerinfo->{Probba}],clear_before=>'yes');
calc_area('ref_layer_c_ba');
}
}
else{
if ($layerinfo->{Goldfr} and $layerinfo->{Reffr}){
INCAM_CreateGoldLayer($layerinfo->{Front},$layerinfo->{Probfr},$layerinfo->{Goldfr},$layerinfo->{Reffr},$layerinfo->{Drill},'qec_goldfr','qec_ospfr',$subStep) ;
}
elsif ($layerinfo->{Front} and $layerinfo->{Probfr}){
$GEN->units(type=>'inch');
INCAM_CreateMetalLayer(step=>$subStep,outputLayer=>'ref_layer_c_fr',ep=>$layerinfo->{Front},sm=>$layerinfo->{Probfr});
}
if ($layerinfo->{Goldba} and $layerinfo->{Refba}){
INCAM_CreateGoldLayer($layerinfo->{Back} ,$layerinfo->{Probba},$layerinfo->{Goldba},$layerinfo->{Refba},$layerinfo->{Drill},'qec_goldba','qec_ospba',$subStep)
}
elsif ($layerinfo->{Back} and $layerinfo->{Probba}){
$GEN->units(type=>'inch');
INCAM_CreateMetalLayer(step=>$subStep,outputLayer=>'ref_layer_c_ba',ep=>$layerinfo->{Back},sm=>$layerinfo->{Probba});
}
}
$GEN->units(type=>'mm');
$GEN->closeStep();
}
_deleteLayer(step=>$Step,layer=>['qec_goldfr+++','qec_goldba+++','qec_ospfr+++','qec_ospba+++',
'rel_qec_goldfr+qec_ospfr+++','rel_qec_goldba+qec_ospba+++']);
$GEN->openStep(job=>$Job,name=>$Step);
$ans = $GEN->PAUSE('Please Check gold layer features,then continue');
unless (defined $ans and $ans eq 'OK' ) {
return 'Cancel';
}
my $info_step=$layerinfo->{sel};
$GEN->openStep(job=>$Job,name=>$Step);
$GEN->units(type=>'mm');
if ($PLAN_STATE eq 'SHA') {
my %guard_warning;
foreach my $ref_layer_c('ref_layer_c_fr','ref_layer_c_ba'){
my $ll='Front';
my @refs= ('qec_goldfr','qec_ospfr');
if ($ref_layer_c eq 'ref_layer_c_ba'){
@refs= ('qec_goldba','qec_ospba') ;
$ll='Back';
}
if (!$GEN->isLayerExists(job=>$Job,layer=>$ref_layer_c)){
foreach my $ggg (@refs){
if ($GEN->isLayerExists(job=>$Job,layer=>$ggg)){
my @steps11 = $GEN->getSubSteps(job=>$Job,step=>$Step);
if (@steps11) {
foreach my $f (@steps11){
$GEN->openStep(job=>$Job,name=>$f);
$GEN->units(type=>'mm');
$GEN->copyLayer(source_job=>$Job,
source_step=>$Step,
source_layer=>$ggg,
dest_layer=>$ref_layer_c.'_tmp',
mode=>'append', #append
invert=>'yes');#|'yes'
}
$GEN->openStep(job=>$Job,name=>$Step);
$GEN->units(type=>'mm');
$GEN->flattenLayer(source_layer=>$ref_layer_c.'_tmp',target_layer=>$ref_layer_c.'_tmp1');
$GEN->copyLayer(source_job=>$Job,
source_step=>$Step,
source_layer=>$ref_layer_c.'_tmp1',
dest_layer=>$ref_layer_c,
#mode=>'append', #append
invert=>'no');#|'yes'
}
else{
$GEN->copyLayer(source_job=>$Job,
source_step=>$Step,
source_layer=>$ggg,
dest_layer=>$ref_layer_c,
mode=>'append', #append
invert=>'no');#|'yes'
}
}
}
}
if ($GEN->isLayerExists(job=>$Job,layer=>$ref_layer_c)){
my $ff = exposed_pad_size($Job,$Step,$layerinfo->{$ll},$ref_layer_c,$info_step);
foreach my $num (keys %$ff){
$guard_warning{$ll}{$num}=$ff->{$num};
}
#push @guard_warning , "On $ll side, ".join("<br>",@$ff) if (@$ff);
}
else{
$guard_warning{1} ="On $ll side, All layer exposed";
}
}
if (keys %guard_warning) {
my $subject = "AUTO MAIL:GE01 risk PN[$JOB]";
my $sent_mail = "Base on [$info_step],High Risk PN [$JOB]: <br>";
$sent_mail.='<font size="4" ><u><b>Design information:</b></u></font><br>';
$sent_mail.='1, ID Print Side: ${ID_LAYER}<br>';
$sent_mail.='2, MF information: ${Array}/Panel, ${PCB}/Array<br>';
my $n1=3;
foreach my $layer (qw/Front Back/){
if (keys %{$guard_warning{$layer}}){
$sent_mail.='On '.$layer.'<br>';
for my $n (1,2){
$sent_mail.=$n1.','.$guard_warning{$layer}{$n}.'<br>';
$n1++;
}
}
}
$sent_mail.='<br><br><font size="4" ><u><b>Action required:</b></u></font><br>';
$sent_mail.='SM to MF: Use Panel interleaf<br>';
#$sent_mail.='RT to FI: Use Array interleaf (FR4)<br><br>';
$sent_mail.='${et_workflow_sap}<br><br>';
$sent_mail.='<font size="4" ><u><b>Part number alarm information:</b></u></font><br>';
foreach my $layer (qw/Front Back/){
if (@{$guard_warning{$layer}{3}}) {
$sent_mail.='On '.$layer.'<br>';
foreach my $f (@{$guard_warning{$layer}{3}}){
$sent_mail.=$f;
}
}
}
#$GUI->debug("$sent_mail");
$DB->save_jobinfo(
-jobid=>$JOB_ID,
-jobcategory=>'org',
-jobinfohash=>{ATS_GE01_mail =>$sent_mail});
}
}
#if ($PLAN_STATE eq 'SHA') {
# my @guard_warning;
# foreach my $ref_layer_c('ref_layer_c_fr','ref_layer_c_ba'){
# my $ll='top';
# my @refs= ('qec_goldfr','qec_ospfr');
# if ($ref_layer_c eq 'ref_layer_c_ba'){
# @refs= ('qec_goldba','qec_ospba') ;
# $ll='bottom';
# }
#
# if (!$GEN->isLayerExists(job=>$Job,layer=>$ref_layer_c)){
# foreach my $ggg (@refs){
# if ($GEN->isLayerExists(job=>$Job,layer=>$ggg)){
# my @steps11 = $GEN->getSubSteps(job=>$Job,step=>$Step);
# if (@steps11) {
# foreach my $f (@steps11){
# $GEN->openStep(job=>$Job,name=>$f);
# $GEN->units(type=>'mm');
# $GEN->copyLayer(source_job=>$Job,
# source_step=>$Step,
# source_layer=>$ggg,
# dest_layer=>$ref_layer_c.'_tmp',
# mode=>'append', #append
# invert=>'yes');#|'yes'
# }
#
# $GEN->openStep(job=>$Job,name=>$Step);
# $GEN->units(type=>'mm');
# $GEN->flattenLayer(source_layer=>$ref_layer_c.'_tmp',target_layer=>$ref_layer_c.'_tmp1');
# $GEN->copyLayer(source_job=>$Job,
# source_step=>$Step,
# source_layer=>$ref_layer_c.'_tmp1',
# dest_layer=>$ref_layer_c,
# #mode=>'append', #append
# invert=>'no');#|'yes'
# }
# else{
# $GEN->copyLayer(source_job=>$Job,
# source_step=>$Step,
# source_layer=>$ggg,
# dest_layer=>$ref_layer_c,
# mode=>'append', #append
# invert=>'no');#|'yes'
# }
# }
#
# }
# }
#
#
# if ($GEN->isLayerExists(job=>$Job,layer=>$ref_layer_c)){
# my $ff = exposed_pad_size($Job,$Step,$ll,$ref_layer_c,$info_step);
# push @guard_warning , "On $ll side, ".join("<br>",@$ff) if (@$ff);
# }
# else{
# push @guard_warning , "On $ll side, All layer exposed";
# }
# }
#
# if (@guard_warning) {
# my $subject = "AUTO MAIL:GE01 risk PN[$JOB]";
# my $sent_mail = "Base on [$info_step]<br>".join("<br>",@guard_warning);
# mail_sand_task(jobname=>$JOB,
# title=>'exposed_pad_Area_GE01',
# subject=>$subject,
# body=>$sent_mail,
# #sand_mode=>'always',
# );
# ##### 生产拷贝文件
# #my $output_path = "/winshare/Z_customerdrawing/$Job";
# #my $tmp_path = "/winshare/Z_customerdrawing/".uc $Job;
# #if (-d $tmp_path){
# # `mv $tmp_path $output_path`;
# #}else{
# # mkdir $output_path ;
# #}
# #open(my $fh , ">$output_path/GE01 risk PN [$JOB].html");
# #print $fh "GE01 risk PN[$JOB]<br>";
# #print $fh "$sent_mail";
# #close($fh);
# }
#}
my %surface;
$surface{'gold_fr'}=0;
$surface{'gold_ba'}=0;
$surface{'gold_total'}=0;
if($layerinfo->{Probfr}){
$surface{'cp_fr'}=exposedArea($Job,$Step,$thick,$layerinfo->{Front},$layerinfo->{Probfr},'','',$layerinfo->{Drill});
}
else{
$surface{'cp_fr'}=expcopperArea($Job,$Step,$thick,$layerinfo->{Front},$layerinfo->{Probfr},'','',$layerinfo->{Drill});
}
if($layerinfo->{Probba}){
$surface{'cp_ba'}=exposedArea($Job,$Step,$thick,'','',$layerinfo->{Back},$layerinfo->{Probba},$layerinfo->{Drill});
}
else{
$surface{'cp_ba'}=expcopperArea($Job,$Step,$thick,'','',$layerinfo->{Back},$layerinfo->{Probba},$layerinfo->{Drill});
}
$surface{'ref_fr'}=$layerinfo->{Reffr};
$surface{'ref_ba'}=$layerinfo->{Refba};
#$GEN->PAUSE("11111111111111 $drill $layerinfo->{Goldfr} and $layerinfo->{Reffr}");
$surface{'gold_fr'}=exposedArea($Job,$Step,$thick,$layerinfo->{Front},'qec_goldfr',$layerinfo->{Back},'ats_empty',$layerinfo->{Drill}) if ($layerinfo->{Goldfr} and $layerinfo->{Reffr});
$surface{'gold_ba'}=exposedArea($Job,$Step,$thick,$layerinfo->{Front},'ats_empty',$layerinfo->{Back},'qec_goldba',$layerinfo->{Drill}) if ($layerinfo->{Goldba} and $layerinfo->{Refba});
if(($layerinfo->{Goldfr} eq '' or $layerinfo->{Goldfr} == 0) and $layerinfo->{Reffr} =~ /gold/i and !$layerinfo->{Goldfr}){
$surface{'gold_fr'}=$surface{'cp_fr'};
}
if(($layerinfo->{Goldba} eq '' or $layerinfo->{Goldba} == 0) and $layerinfo->{Refba} =~ /gold/i and !$layerinfo->{Goldba}){
$surface{'gold_ba'}=$surface{'cp_ba'};
}
$surface{'cp_total'}=$surface{'cp_fr'}+$surface{'cp_ba'};
$surface{'gold_total'}=$surface{'gold_fr'}+$surface{'gold_ba'} if ($surface{'gold_fr'} and $surface{'gold_ba'});
$surface{'carbon'}='__NA__';
if ( $layerinfo->{Carbon_laye} eq 'Yes'){
$surface{'carbon'}=0;
my @layer = $GUI->select_layer( -title=>'Select Carbon Layers',
-layermatrix=>{$GEN->getMatrix(job=>$Job)},
-default => [],
-selectmode => 'multiple');
return 'Cancel' if(!defined($layer[0]));
foreach my $layer (@layer) {
my $reprot = $GEN->copperArea(layer1=>$layer);
my $tmp = sprintf ('%.4f',$reprot->{area});
$surface{'carbon'}+=$tmp;
}
$surface{'carbon'}=$surface{'carbon'} / 10000;
$surface{'carbon'}=sprintf('%.4f',$surface{'carbon'});
}
#= $GUI->select_single(
# -title=>'All the surface calculation is based on:',
# -list=>['Card'=>'Card','Array'=>'Array'],
# -defaultvalue=>'all_left'
#);
$surface{'baseon'} = $info_step;
# $GEN->PAUSE("$surface{baseon} g $surface{ref_fr} h $surface{ref_ba} ");
my %InfoHash;
$InfoHash{TL_exposed_area_front}=$surface{cp_fr};
$InfoHash{TL_exposed_area_back}=$surface{cp_ba};
$InfoHash{TL_gold_area_front}=$surface{gold_fr} * 1.1;
$InfoHash{TL_gold_area_back}=$surface{gold_ba} * 1.1;
#
if ($layerinfo->{Goldfr}) {
$InfoHash{ATS_selection_reference_layer_front}=$layerinfo->{Goldfr};
$InfoHash{ATS_selection_reference_type_front}=$surface{ref_fr};
## Fix BUG 2017-04-25 When REF GOLD, Set REF = GOLD AREA,
## ELSE ,Set REF = ALL - GOLD AREA
if ($InfoHash{ATS_selection_reference_type_front} eq 'GOLD') {
$InfoHash{ATS_selection_reference_area_front}=$surface{gold_fr};
}else {
$InfoHash{ATS_selection_reference_area_front}=$surface{cp_fr} - $surface{gold_fr};
}
$InfoHash{ATS_org_area_type_full_front}='';
}else {
$InfoHash{ATS_selection_reference_layer_front}='';
$InfoHash{ATS_selection_reference_type_front}='';
$InfoHash{ATS_selection_reference_area_front}='';
$InfoHash{ATS_org_area_type_full_front}='GOLD';
}
if ($layerinfo->{Goldba}) {
$InfoHash{ATS_selection_reference_layer_back}=$layerinfo->{Goldba};
$InfoHash{ATS_selection_reference_type_back}=$surface{ref_ba};
if ($InfoHash{ATS_selection_reference_type_back}eq 'GOLD') {
$InfoHash{ATS_selection_reference_area_back}=$surface{gold_ba};
}else {
$InfoHash{ATS_selection_reference_area_back}= $surface{cp_ba} - $surface{gold_ba};
}
$InfoHash{ATS_org_area_type_full_back}='';
}else {
$InfoHash{ATS_selection_reference_layer_back}='';
$InfoHash{ATS_selection_reference_type_back}='';
$InfoHash{ATS_selection_reference_area_back}='';
$InfoHash{ATS_org_area_type_full_back}='GOLD';
}
$InfoHash{ATS_org_area_pe_check}='no';
$InfoHash{TL_carbon_area}=$surface{carbon};
$InfoHash{ATS_surface_area_base_on}=$surface{baseon};
$DB->save_jobinfo(
-jobid=>$JOB_ID,
-jobcategory=>'org',
-jobinfohash=>\%InfoHash);
# $GUI->debug(dump(\%InfoHash));
my $Check_gold_size= sprintf('%-15s',' ').sprintf('%-15s','Exposed').sprintf('%-15s','Gold').sprintf('%-15s','Sel.Ref (sqin)')."\n";
my $Check_gold_state = 0;
my($step_size_x,$step_size_y);
if ($Job =~ /^coc/i ){
my $tmpm1=$InfoHash{TL_gold_area_front}*15.500031000062;
my $tmpm2=$InfoHash{TL_gold_area_back}*15.500031000062;
my $tmpm3=$InfoHash{TL_exposed_area_front}*15.500031000062;
my $tmpm4=$InfoHash{TL_exposed_area_back}*15.500031000062;
$tmpm1=sprintf "%.4f",$tmpm1;
$tmpm2=sprintf "%.4f",$tmpm2;
$tmpm3=sprintf "%.4f",$tmpm3;
$tmpm4=sprintf "%.4f",$tmpm4;
if ($tmpm1 > 2.5 or $tmpm2 > 2.5 and $InfoHash{selection_reference_type_front} =~/^gold$/i and $InfoHash{selection_reference_type_back} =~/^gold$/i){
$Check_gold_state=1;
}
$Check_gold_size.= sprintf('%-15s','front').sprintf('%-15s',$tmpm3).sprintf('%-15s',$tmpm1).sprintf('%-15s',$InfoHash{selection_reference_type_front})."\n";
$Check_gold_size.= sprintf('%-15s','back').sprintf('%-15s',$tmpm4).sprintf('%-15s',$tmpm2).sprintf('%-15s',$InfoHash{selection_reference_type_back})."\n";
my $tmpmm="Base on :$InfoHash{surface_area_base_on}";
$Check_gold_size.= sprintf('%-15s',$tmpmm)."\n";
}
# if ($Check_gold_state==1 and $Job =~/^coc/i){
# my $profile_limits = $GEN->getProfileLimits(job=>$Job,step=>$Step,units=>'mm');
# my $Card_sizex=sprintf "%.2f",$profile_limits->{xsize};
# my $Card_sizey=sprintf "%.2f",$profile_limits->{ysize};
# my $Card_size="Card size: X $Card_sizex,Y $Card_sizey (mm)";
# my $subject = "Please be informed P/N $Job gold area > 2.5sqin per single card per side";
# my $content = "Dear All\n Pls be informed gold area > 2.5sqin \nIf any feedback Please contact PE!\n\n\n$Check_gold_size${Card_size}";
# my $title="Pls be informed gold area > 2.5sqin";
# my $mails = $DB->select_arrayhash(
# -table => 'ats_auto_mail_record',
# -where => {job_id => $JOB_ID}
# );
# my $n=0;
# foreach my $item (@$mails) {
# if ( $item->{mail_subject} eq $subject) {
# $n=1;
# last;
# }
# }
# if ($PAR->{send_mail} eq 'yes' and $n==0){
# my $username =$GEN->getUserName();
# Top::MailSender->send_mail(
# subject => $subject,#标题不能为中文
# group => $PAR->{mail_group},
# to => $PAR->{internal_mail_group},
# cc_user=>[$username],
# body=>$content,
# );
# $DB->insert(
# -table => 'ats_auto_mail_record',
# -data => {
# job_id => $JOB_ID,
# mail_from => $username,
# mail_to => join(',',Top::MailSender->get_mail_list($PAR->{$PAR->{mail_group}},'to')),
# mail_cc => $username,
# mail_subject => $subject,
# mail_title => $title,
# mail_content => $content,
# mail_version => 1
# }
# )
# }
#$sql="select mail_title from auto_mail_record where job_id=$processInfo{job_id} and mail_title='Pls be informed gold area > 2.5sqin'";
#my $db1 = DB::ACAMMysql->new();
#$db1->run($sql);
#my $mail_title=$db1->next();
#my $n=0;
#if ($mail_title){
# $n=1;
# return 1;
#}
#
#if ($n==0){
# # my @mailto1=('m.pei@cn.ats.net');
# my @mailto1 = $CAM->getMailListByTypeAndCategory(-type=>'gold area > 2.5sqin',-category=>'to');
# my $mailfrom1 = $CAM->getGenesisUserMail(-username=>$USERNAME);
# my @mailcc1=('SHA_PE','m.pei@cn.ats.net',$mailfrom1);
# my $subject1 = "Pls be informed P/N ${JOB_NAME} gold area > 2.5sqin per single card per side";
# my $content1 = "Dear All\n Pls be informed gold area > 2.5sqin \nIf any feedback Please contact PE!\n\n\n$Check_gold_size${Card_size}";
#
# Lib::MailMix->sendmail_ATSMail( -mailfrom =>$mailfrom1,
# -mailto =>\@mailto1,
# -mailcc =>\@mailcc1,
# -subject =>$subject1,
# -content =>$content1
# );
#
# my $nowtime=$Genesis->localtimemysql();
# &RecordMail(-jobname=>$JOB_NAME,
# -mail_from=>$mailfrom1,
# -mail_to=>join(',',@mailto1),
# -mail_cc=>join(',',@mailcc1),
# -mail_subject=>$subject1,
# -mail_title=>"Pls be informed gold area > 2.5sqin",
# -mail_content=>$content1,
# -mail_send_time=>$nowtime,
# -mail_attachment=>''
# );
#}
# }
###output and return status, if genesis error, it will output genesis error command
unless ($GEN->{STATUS}){
return $Return;
}
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 = encode("utf8",shift);
$GUI->msgbox(-icon=>'error',-text=>$error);
return 'Error';
}
finally{
};
sub _deleteLayer{
my %par = @_;
foreach my $layer(@{$par{layer}}){
$GEN->deleteLayer(layer=>$layer) if ($GEN->isLayerExists(job=>$Job,layer=>$layer));
}
$GEN->openStep(job=>$Job,name=>$par{step}) if ($par{step});
}
sub CreateGoldLayer{
my ($ep,$sm,$ref,$refas,$drill,$gold,$osp) = @_;
$GEN->COM('chklist_single',action=>'ats_dfm_sit',show=>'no');
$GEN->COM('chklist_cupd',chklist=>'ats_dfm_sit',nact=>1,
params=>"((pp_outlayer=$ep)(pp_smlayer=$sm)(pp_refmode=$refas)(pp_reflayer=$ref)(pp_drilllayer=$drill)(pp_goldlayer=$gold)(pp_osplayer=$osp))",
mode=>'regular');
$GEN->COM('chklist_run',chklist=>'ats_dfm_sit',
nact=>1,area=>'global');
`touch /tmp/script.flag` if( ! (-e "/tmp/script.flag"));
}
sub INCAM_CreateGoldLayer{
my ($ep,$sm,$ref,$refas,$drill,$gold,$osp,$subStep) = @_;
my $tmp_sm = 'script_sm';
my $tmp_ep = 'script_ep';
my $tmp_sm_backup = 'ref_expgold+exposp';
$GEN->units(type=>'mm');
_deleteLayer(step=>$subStep,layer=>[$tmp_sm,$tmp_ep,$tmp_sm_backup]);
$GEN->workLayer(name=>$sm,display_number=>1,clear_before=>'yes');
$GEN->selCopyOther(dest=>'layer_name',target_layer=>$tmp_sm);
$GEN->workLayer(name=>$tmp_sm,display_number=>1,clear_before=>'yes');
$GEN->COM("sel_contourize,accuracy=0,break_to_islands=yes,clean_hole_size=0,clean_hole_mode=x_and_y");
$GEN->selCopyOther(dest=>'layer_name',target_layer=>$tmp_sm_backup);
$GEN->workLayer(name=>$ep,display_number=>1,clear_before=>'yes');
$GEN->selCopyOther(dest=>'layer_name',target_layer=>$tmp_ep);
$GEN->workLayer(name=>$tmp_ep,display_number=>1,clear_before=>'yes');
$GEN->COM("sel_contourize,accuracy=0,break_to_islands=yes,clean_hole_size=0,clean_hole_mode=x_and_y");
$GEN->selCopyOther(dest=>'layer_name',target_layer=>$tmp_sm,invert=>'yes',size=>2);
$GEN->workLayer(name=>$tmp_sm,display_number=>1,clear_before=>'yes');
$GEN->COM("sel_contourize,accuracy=0,break_to_islands=yes,clean_hole_size=0,clean_hole_mode=x_and_y");
$GEN->selCopyOther(dest=>'layer_name',target_layer=>$tmp_sm_backup,invert=>'yes',size=>2);
$GEN->workLayer(name=>$tmp_sm_backup,display_number=>1,clear_before=>'yes');
$GEN->COM("sel_contourize,accuracy=0,break_to_islands=yes,clean_hole_size=0,clean_hole_mode=x_and_y");
$GEN->selRefFeat(
layers=>$ref,
use=>'filter',
mode=>'touch',
f_types=>'surface\;pad\;text\;line\;arc',
polarity=>'positive',
);
if ( $GEN->getSelectCount() > 0 ){
if ($refas eq 'GOLD'){
$GEN->selMoveOther(target_layer=>$gold) ;
$GEN->selMoveOther(target_layer=>$osp) ;
}elsif($refas eq 'OSP'){
$GEN->selMoveOther(target_layer=>$osp) ;
$GEN->selMoveOther(target_layer=>$gold) ;
}
}
_deleteLayer(layer=>[$tmp_sm,$tmp_ep,$tmp_sm_backup]);
$GEN->units(type=>'inch');
`touch /tmp/script.flag` if( ! (-e "/tmp/script.flag"));
}
sub expcopperArea {
my ($job,$step,$thick,$layer1,$mask1,$layer2,$mask2,$drill) = @_;
$GEN->openStep(job=>$Job,name=>$Step);
$GEN->units(type=>'mm');
my $reprot;
$reprot =$GEN->copperArea(
'layer1'=>$layer1?$layer1:'',
'layer2'=>$layer2?$layer2:'',
'drills'=>$drill?'yes':'no',
'consider_rout'=>'no',
'drills_source'=>'matrix',
'drills_list'=>$drill,
'thickness'=>$thick,
'resolution_value'=>10,
'x_boxes'=>3,
'y_boxes'=>3,
'area'=>'no',
'dist_map'=>'yes'
);
$reprot = sprintf "%0.4f",$reprot->{area}/10000;
return $reprot;
}
sub exposedArea {
my ($job,$step,$thick,$layer1,$mask1,$layer2,$mask2,$drill) = @_;
$GEN->openStep(job=>$Job,name=>$Step);
$GEN->units(type=>'mm');
my $reprot;
$reprot = $GEN->exposedArea(
'layer1'=>$layer1?$layer1:'',
'mask1'=>$mask1?$mask1:'',
'layer2'=>$layer2?$layer2:'',
'mask2'=>$mask2?$mask2:'',
'drills'=>$drill?'yes':'no',
'consider_rout'=>'no',
'drills_source'=>'matrix',
'drills_list'=>$drill,
'thickness'=>$thick,
'resolution_value'=>10,
'x_boxes'=>3,
'y_boxes'=>3,
'area'=>'no',
'dist_map'=>'yes',
);
$reprot = sprintf "%0.4f",$reprot->{area}/10000;
return $reprot;
}
#exposed_pad_size($Job,$Step,$layer,$ref_layer);
sub exposed_pad_size{
my $Job=shift;
my $Step= shift;
my $layer= shift;
my $ref_layer=shift;
my $base_on =shift;
$GEN->openStep(job=>$Job,name=>$Step);
$GEN->units(type=>'mm');
$GEN->workLayer(name=>$ref_layer,display_number=>1,clear_before=>'yes');
$GEN->COM("sel_contourize,accuracy=0,break_to_islands=yes,clean_hole_size=0,clean_hole_mode=x_and_y");
$GEN->COM("sel_clean_surface,accuracy=10,clean_size=75,clean_mode=x_or_y,max_fold_len=0");
$GEN->COM("sel_clean_surface,accuracy=2.54,clean_size=75,clean_mode=x_and_y,max_fold_len=0");
$GEN->copyLayer(source_job=>$Job,
source_step=>$Step,
source_layer=>$layer,
dest_layer=>'copper_cal',
);
my $copper_a =$GEN->copperArea(
'layer1'=>'copper_cal',
'layer2'=>'',
'drills'=>'no',
'consider_rout'=>'no',
'drills_source'=>'matrix',
'drills_list'=>'',
'thickness'=>'1',
'resolution_value'=>10,
'x_boxes'=>3,
'y_boxes'=>3,
'area'=>'no',
'dist_map'=>'yes'
);
$copper_a = sprintf "%0.4f",$copper_a->{area};
my $f_all =$GEN->copperArea(
'layer1'=>$ref_layer,
'layer2'=>'',
'drills'=>'no',
'consider_rout'=>'no',
'drills_source'=>'matrix',
'drills_list'=>'',
'thickness'=>'1',
'resolution_value'=>10,
'x_boxes'=>3,
'y_boxes'=>3,
'area'=>'no',
'dist_map'=>'yes'
);
$f_all = sprintf "%0.4f",$f_all->{area};
my $percent =12;
my $all_percent = 45;#
my $all_ratio = sprintf "%0.3f",($f_all/$copper_a)*100;
my %guard_warning1=();
my ($condition1,$condition2);
my @guard_warning1;
if ($all_ratio >= $all_percent) {
$condition2 ='ok';
push @guard_warning1,"All exposed pad area: ${f_all} mm2 ; Ratio: $all_ratio%";
}
my @features1 = $GEN->getFeatures(job=>$Job,step=>$Step,layer=>$ref_layer,units=>'mm',surface=>1);
my @guard_warning=();
my (%max1,%max2);
foreach my $surface (@features1){
my $f =$ATS_GenMath->Polygon_Calculate_getArea(polygon=>\@{$surface->{feats}},tol=>'0.1',mode=> 'surface');
$f = sprintf "%0.4f",$f;
next if ($f==0);
my $ratio=sprintf "%0.3f",($f/$copper_a)*100;
my $ratio1=sprintf "%0.3f",($f/$f_all)*100;
$max1{$f}=$ratio;
$max2{$f}=$ratio1;
if ($ratio >= $percent ) {
my $Center = $ATS_GenMath->Calculate_Surface_Center(polygon=>\@{$surface->{feats}},precision=>'1',units=>'mm');
push @guard_warning ,"Exposed Pad Size all Area :${f_all}mm2 ,Single Area:${f}mm2;Ratio:[$ratio%].Pad Point :X:$Center->{1}{x}mm,Y:$Center->{1}{y}mm<br>";
$condition1= 'ok';
}
}
#$GUI->debug("$condition1 $condition2 $all_ratio");
if ($condition1 eq 'ok' or $condition2 eq 'ok'){
my ($max1) = sort {$b <=> $a} %max1;
$guard_warning1{1}="The Max exposed pad area: ${max1} mm2 ; Ratio: $max1{$max1}%";
$guard_warning1{2}="All exposed pad area: ${f_all} mm2 ; Ratio: $all_ratio%";
if (@guard_warning1) {
push @{$guard_warning1{3}},@guard_warning1;
}
push @{$guard_warning1{3}},@guard_warning if ($condition1 eq 'ok');
}
return \%guard_warning1;
}
sub exposed_pad_size1{
my $Job=shift;
my $Step= shift;
my $layer= shift;
my $ref_layer=shift;
my $base_on =shift;
my $f_all;
$GEN->openStep(job=>$Job,name=>$Step);
$GEN->units(type=>'mm');
$GEN->workLayer(name=>$ref_layer,display_number=>1,clear_before=>'yes');
$GEN->COM("sel_contourize,accuracy=0,break_to_islands=yes,clean_hole_size=0,clean_hole_mode=x_and_y");
$GEN->COM("sel_clean_surface,accuracy=10,clean_size=75,clean_mode=x_or_y,max_fold_len=0");
$f_all =$GEN->copperArea(
'layer1'=>$ref_layer,
'layer2'=>'',
'drills'=>'no',
'consider_rout'=>'no',
'drills_source'=>'matrix',
'drills_list'=>'',
'thickness'=>'1',
'resolution_value'=>10,
'x_boxes'=>3,
'y_boxes'=>3,
'area'=>'no',
'dist_map'=>'yes'
);
$f_all = sprintf "%0.4f",$f_all->{area};
my @features1 = $GEN->getFeatures(job=>$Job,step=>$Step,layer=>$ref_layer,units=>'mm',surface=>1);
my $guard_Area= 400;#mm
my $percent =35;
my @guard_warning=();
foreach my $surface (@features1){
my $f =$ATS_GenMath->Polygon_Calculate_getArea(polygon=>\@{$surface->{feats}},tol=>'0.1',mode=> 'surface');
$f = sprintf "%0.4f",$f;
next if ($f==0);
my $ratio=sprintf "%0.3f",($f/$f_all)*100;
if ($f >$guard_Area or $ratio > $percent) {
my $Center = $ATS_GenMath->Calculate_Surface_Center(polygon=>\@{$surface->{feats}},precision=>'1',units=>'mm');
push @guard_warning ,"Exposed Pad Size all Area :${f_all}mm2 ,Single Area:${f}mm2;Ratio:[$ratio%].Pad Point :X:$Center->{1}{x}mm,Y:$Center->{1}{y}mm";
}
}
#$GUI->debug("@guard_warning");
return \@guard_warning;
}
sub polygon_surface{
my $Job=shift;
my $Step= shift;
my $layer= shift;
my $options = shift;#select
my $units= shift;
my $cshfile;
$cshfile=$GEN->INFO('entity_type'=>'layer',
'entity_path'=>"$Job/$Step/$layer",
'data_type'=>'FEATURES',
'parse'=>'no',
units=>$units,
) if (!$options);
$cshfile=$GEN->INFO('entity_type'=>'layer',
'entity_path'=>"$Job/$Step/$layer",
'data_type'=>'FEATURES',
'parse'=>'no',
options=>$options,
units=>$units,
) if ($options);
open(CSHFILE,"$cshfile");
my @polygon=<CSHFILE>;
close(CSHFILE);
shift @polygon;
return @polygon;
}
sub mail_sand_task {
my %par = @_; ## subject ##body ## title
my $mailinfo=$DB->select_hash(-table=>'ats_mail_sand_task',-where=>{mail_title=>$par{title}});
if ($mailinfo->{status} eq 'Start'){
my $mail_to=$mailinfo->{mail_to};
my $mail_cc=$mailinfo->{mail_cc};
if ($mail_to=~/^sub/){
$mail_to=eval($mail_to);
$mail_to= $mail_to->(job_id=>$JOB_ID);
}
else{
$mail_to=eval($mail_to) if ($mail_to=~/^\$/);
}
if ($mail_cc=~/^sub/){
$mail_cc=eval($mail_cc);
$mail_cc= $mail_cc->(job_id=>$JOB_ID);
}
else{
$mail_cc=eval($mail_cc) if ($mail_cc=~/^\$/);
}
my @to = split(/\;|\:|\,|\n/,$mail_to);
foreach my $it (@to){
$it =~ s/(^\s+|\s+$)//g;
}
$par{-to} = \@to;
#$data{cc} =~ s/\s+//g;
my @cc = split(/\;|\:|\,|\n/,$mail_cc);
foreach my $it (@cc){
$it =~ s/(^\s+|\s+$)//g;
}
$par{-cc} = \@cc;
$par{cc_user}='';
$par{group}='';
#$GUI->debug("@to m @cc ");
my $subject=$par{subject};
my $body = $par{body};
my $mail_version = $DB->select_value(
-table=>'ats_auto_mail_record',
-field=>'max(mail_version)',
-where=>"job_id = $JOB_ID and mail_title = '$par{title}'",
);
$mail_version = 0 unless ($mail_version);
$mail_version++;
my $resart_mail= 'yes';
if ($mail_version > 1 and $par{sand_mode} ne 'always' ){
my $tmp_v=$mail_version-1;
my $mail_subject = $DB->select_value(
-table=>'ats_auto_mail_record',
-field=>'mail_subject',
-where=>"job_id = $JOB_ID and mail_title = '$par{title}' and mail_version = $tmp_v",
);
my $mail_body = $DB->select_value(
-table=>'ats_auto_mail_record',
-field=>'mail_content',
-where=>"job_id = $JOB_ID and mail_title = '$par{title}' and mail_version = $tmp_v",
);
if ($mail_subject eq $subject){
$resart_mail='no';
if ($mail_body ne $body){
$resart_mail='yes';
}
}
elsif ($mail_body ne $body){
$resart_mail='yes';
}
}
#$GUI->debug(dump\%par);
#exit;
if ($resart_mail eq 'yes'){
Top::MailSender->send_mail(%par);
my ($content,$att);
if (ref $par{body} eq 'ARRAY') {
($content,$att) = @{$par{body}};
}
else {
$content = $par{body};
}
if ($att) {
my @att = @{$att};
if (@att) {
$att = join(',',@att);
$att = '' unless ($att);
}else {
$att = '';
}
}
else {
$att = '';
}
$DB->insert(
-table=>'ats_auto_mail_record',
-data=>{
job_id => $JOB_ID,
mail_from=>$APP->{USER_NAME},
mail_to=>$mail_to,
mail_cc=>$mail_cc,
mail_subject=>$par{subject},
mail_title=>$par{title},
mail_content=>$content,
mail_attachment=>$att,
mail_version=>$mail_version,
}
);
}
}
}
sub calc_area{
my $output_layer=shift;
$GEN->COM('chklist_single,action=ats_analysis_calc_area,show=no');
$GEN->COM("chklist_cupd,chklist=ats_analysis_calc_area,nact=1,params=((pp_layer=.affected)(pp_output_layer=$output_layer)(pp_flatten_mode=Yes)),mode=regular");
$GEN->COM('chklist_run,chklist=ats_analysis_calc_area,nact=1,area=profile');
}
sub INCAM_CreateMetalLayer{
my %par = @_;
my $outputLayer=$par{outputLayer};
my $ep = $par{ep};
my $sm = $par{sm};
my $tmp_ep = "script_".$ep;
my $tmp_sm = "script_".$sm;
my $step = $par{step};
$GEN->copyLayer(source_job=>$Job,source_step=>$step,source_layer=>$ep,dest_layer=>$tmp_ep);
$GEN->copyLayer(source_job=>$Job,source_step=>$step,source_layer=>$sm,dest_layer=>$tmp_sm);
$GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>[$tmp_ep,$tmp_sm],clear_before=>'yes');
$GEN->selContourize();
$GEN->COM("sel_feat2outline,width=0,location=on_edge,offset=0,polarity=as_feature,keep_original=no,text2limit=no");
$GEN->COM("sel_cut_data,det_tol=1,con_tol=1,rad_tol=0,ignore_width=yes,filter_overlaps=no,delete_doubles=no,use_order=yes,ignore_holes=none,start_positive=yes,polarity_of_touching=same,contourize=yes,simplify=yes,resize_thick_lines=no");
$GEN->COM("rv_tab_view_results_enabled,report=cut_data_rep,is_enabled=no,serial_num=-1,all_count=-1");
$GEN->copyLayer(source_job=>$Job,source_step=>$step,source_layer=>$tmp_sm,dest_layer=>$outputLayer);
$GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>[$tmp_sm],clear_before=>'yes');
$GEN->COM("sel_resize,size=0.5,corner_ctl=no");
$GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>[$tmp_ep],clear_before=>'yes');
$GEN->selCopyOther(dest=>'layer_name',target_layer=>$tmp_sm,invert=>'yes',size=>0.5);
$GEN->workLayer(name=>$tmp_sm,display_number=>1,clear_before=>'yes');
$GEN->COM("sel_contourize,accuracy=0,break_to_islands=yes,clean_hole_size=0,clean_hole_mode=x_and_y");
$GEN->selCopyOther(dest=>'layer_name',target_layer=>$outputLayer,invert=>'yes',size=>0.5);
$GEN->workLayer(name=>$outputLayer,display_number=>1,clear_before=>'yes');
$GEN->selContourize();
_deleteLayer(job=>$Job,step=>$step,layer=>[$tmp_ep,$tmp_sm]);
}
\ No newline at end of file
=head
NAME: TL_READIN_check_org_linewidth_spacing
DESCRIPTION: 检查钻孔Pad大小.
PARAMETER:
{items => [
{
name=>'check_list',
label=>'CheckList名称',
type=>'string',
remark=>'CheckList名称',
must_field=>1,
},
{
name=>'drill_summary_nact',
label=>'Drill Summary CheckList编号',
type=>'integer',
remark=>'Drill Summary CheckList编号',
must_field=>1,
},
]}
VERSION_HISTORY:
V1.00 2011-05-27 Tony Guo
1.新版本
V1.01 2016-09-26 mast
添加rill summary分析出错原因
V1.02 2016-10-18 John
更新INCAM和Genesis取分析结果错误的不同点。
V1.03 2017-02-22 Ferre
Fixed Bug for Same Hole size with Both Via & PTH.
V1.04 2018-09-10 Ferre
Add SymmetricalDrill Check on Laser/Mech Type Define.
V1.05 2019-04-20 mast
优化 2038
Echk tool PE定义drill infos=》 CAM根据PE信息,更改echk料号孔径
V1.06 2019-05-13 mast
优化 2051
在Read in item 33: Update drill info to database
1,程序判断出有laser drill on or close mechanical,邮件中带上如下信息,发自动邮件给PE CAM.
(There is FV2 stack up which is forbidden in SHA plant.)
2,并推送EQ条目和建议。
V1.07 2019-05-20 mast
系统优化:2089
Checked with Spring
Follow the same rule to identy the drill type on QEC stage
the old rule : Hole size >=7mil , Type = mechanical hole
Hole size <7mil , Type =laser hole
The Revision: hole size >= 150um ,Type = mechanical hole
hole size <150um ,Type = laser hole
V1.08 2019-09-05 mast
系统优化:2293
分割孔带中的component_via属性,再上传原稿drill信息时,额外开一条记录,并且在数据库中勾选上laser_on_component
传PE 孔层时,按照ho12层合并到laser层中,如laser2-2,和合并到laser2-3 (4层板)
V1.09 2020-04-02 john
优化 2749
存在非FV3结构,请联系Cassiel/8127设计新版本TCT及Efid coupon!
V1.09 2020-06-08 john
优化 2843
存在FV2结构,暂停,让人工在判断一次!
V1.10 2020-09-25 mast
优化 3224
show_form 窗口不输入值的时候可以继续运行
HELP:
<html><body bgcolor="#DDECFE">
<font size="3" color="#003DB2"><p>功能简介</p></font>
<p> 检查原稿最小线宽线距.</p>
<br>
<font size="3" color="#003DB2"><p>参数配置</p></font>
<font color="#008000"><p> ● CheckList名称</p></font>
<p> 设置CheckList名称.</p>
<font color="#008000"><p> ● Drill Summary CheckList编号</p></font>
<p> 设置Drill Summary CheckList编号.</p>
<br>
</body></html>
=cut
#use strict;
#my ($JOB,$GEN,$GUI,$DB,$JOB_ID,$PAR,$APP,$MW);
use utf8;
use Encode;
use Data::Dump 'dump';
my $Return = 'Done';
my $Job = $JOB.'_chk';
my $incam = 'no';
if ($GEN->{GEN_TYPE} =~/incam/i) {
$incam = 'yes';
}
my $max_drill=150/25.4;
my @selstep;
use_module('Top::MailSender');
my $customer = $ARGS{CUSTOMER};
try {
if (!defined $Job or $Job =~ /^\s*$/){
$GUI->msgbox(-icon=>'error',-text=>'未定义料号名');
return 'Error';
}
my $layercount = $GEN->getLayerCount(job=>$Job);
my $half_layercount = $layercount/2 + 0.5;
my $arrayhash = $DB->select_arrayhash(-table=>'job_org_layer', -field=>['drl_connect_to','drl_connect_point','tl_name'],-where=>{job_id=>$JOB_ID,type=>'drill'});
my @fv2_error;
my @fv2_mail;
my (@num_count,$Core_mark);
foreach my $hash (@$arrayhash) {
if ($hash->{tl_name} =~/^laser/) {
if ($hash->{drl_connect_to} =~/^(ftdrill\d+\-\d+)$/) {
if ($hash->{drl_connect_point}> 0){
push @fv2_error,$hash->{drl_connect_point};
push @fv2_mail, $hash->{drl_connect_to}.' touch '.$hash->{tl_name}." count $hash->{drl_connect_point}";
}
}
my ($tmp_START,$tmp_END) = $hash->{tl_name} =~/^laser(\d+)\-(\d+)/i;
if ($tmp_START < $half_layercount and $tmp_END >$half_layercount) {
$Core_mark = "yes";
}
foreach my $tmp($tmp_START..$tmp_END){
push @num_count,$tmp if (!grep/^$tmp$/,@num_count);
}
}
}
if ( $customer eq '1352' and ($Core_mark ne "yes" or @num_count != $layercount)) {
#$GUI->msgbox(-icon=>'info',-text=>"存在非FV3结构,请联系Cassiel/8127设计新版本TCT及Efid coupon!");
my $ans = $GUI->confirm("存在非FV3结构,请联系Cassiel/8127设计新版本TCT及Efid coupon,是否发送邮件?");
if ($ans eq "yes") {
my $username =$GEN->getUserName();
my $subject = "$Job is not ncn strucutre , please contact with Cassiel design TCT and Efid Coupon";
my $body = "$Job is not ncn strucutre , please contact with Cassiel design TCT and Efid Coupon";
Top::MailSender->send_mail(
subject => $subject,
#to => 'john.sun@cn.ats.net,cassiel.zhang@cn.ats.net',
# cc_user=>join(',',Top::MailSender->get_mail_list($PAR->{mail_group},'cc')),
cc_user=>[$username],
group => "1352_ncn_inform",
# to =>'test1',
body=>[$body],
);
}
}
if (@fv2_error) {
my $confirm = $GUI->msgbox(-title=>'Confirm',-text=>"判断是FV2,请确认是否OK。",-buttons=>['No'=>'no','Yes'=>'yes',"查看"=>'close']);
if ($confirm eq "close") {
while (1) {
my $result = $GEN->PAUSE("Check Netlist");
if ($result eq "OK") {
$confirm = $GUI->msgbox(-title=>'Confirm',-text=>"判断是FV2,请确认是否OK。",-buttons=>['No'=>'no','Yes'=>'yes',"查看"=>'close']);
last if ($confirm ne "close");
}else{
last;
}
}
}
mail_sand_task(jobname=>$JOB,
title=>'FV2_mail',
subject=>"[$JOB]There is FV2 stack up which is forbidden in SHA plant",
body=>join("<br>",@fv2_mail),
sand_mode=>'always',
) if ($confirm eq "yes");
}
#
#@fv2_error='';
my $check_eq=$DB->get_job_engchk(-jobid=>$JOB_ID,-engchkitemid=>2180);
#$GUI->debug("@fv2_error");
#$GUI->debug(dump \$check_eq);
my $ENUM_ENGCHK_STATUS = $APP->{DB}->get_enum_hash(-category=>'enum_engchk_status');
my $eq_version = $DB->get_job_engchk_version(-jobid=>$JOB_ID);
my ($exist_eq,$check_by_pe);
my $mark_cam;
my $item_max_version = $check_eq->{version};
foreach my $f (@{$check_eq->{problems}}){
if ($f->{selected}==1 and $item_max_version == $f->{version}){
#Replied
#Check_Finish
if ($ENUM_ENGCHK_STATUS->{$f->{enum_engchk_status}}{flow_order} >= $ENUM_ENGCHK_STATUS->{'Replied'}{flow_order}){
$check_by_pe ='yes';
}
if ($ENUM_ENGCHK_STATUS->{$f->{enum_engchk_status}}{flow_order} >= $ENUM_ENGCHK_STATUS->{'Check_Finish'}{flow_order} and ($f->{enum_engchk_problem_type} =~/ok/i or $f->{enum_engchk_problem_type} =~/na/i)){
$check_by_pe ='yes';
}
$exist_eq ='yes';
}
}
my $now = $APP->{DB}->get_now();
my $log = dump({who=>$APP->{USER_NAME},type=>'info',action=>'System update',date_time=>$now,remark=>'Create EQ'}).',';
####如果有问题,并且状态在cam这里,将直接删除后更新。
#$GUI->debug("$check_by_pe");
if (!$check_by_pe and $fv2_error[0]>0) {
my $questions;
$questions->{'question1'}{'value'}={quantity=>join(";",@fv2_error)};
if ($exist_eq eq 'yes') {
if ($GUI->confirm("EQ:[$check_eq->{display_name}]\n已经存在,是否更新?") eq 'yes'){
foreach my $f (@{$check_eq->{problems}}){
#if ($f->{selected}==1 and ($f->{enum_engchk_problem_type} =~/ok/i or $f->{enum_engchk_problem_type} =~/na/i)){
save_job_engchk_question(-jobid=>$JOB_ID,-engchkitem=>'EQM_if_laser_drill_on_mechanical_hole',-log=>$log,-questions=>\%$questions,-delete=>'yes',-version=>$check_eq->{version});
$mark_cam='yes';
#next;
#}
}
}
}
else{
save_job_engchk_question(-jobid=>$JOB_ID,-engchkitem=>'EQM_if_laser_drill_on_mechanical_hole',-log=>$log,-questions=>\%$questions,-delete=>'yes');
}
}
elsif ($check_by_pe eq 'yes'){
#$GUI->debug(dump \@{$check_eq->{problems}});
foreach my $f (@{$check_eq->{problems}}){
if (($f->{selected}==1 and ($f->{enum_engchk_problem_type} =~/ok/i or $f->{enum_engchk_problem_type} =~/na/i)) or @fv2_error){
#or ($f->{name} eq 'question1' and !$f->{selected})
my $questions;
$questions->{'question1'}{'value'}={quantity=>join(";",@fv2_error)};
if ($ENUM_ENGCHK_STATUS->{$f->{enum_engchk_status}}{display_name}) {
if ($GUI->confirm("EQ:[$check_eq->{display_name}]\n条目:$f->{display_name}\n并且为[$f->{enum_engchk_problem_type}]项目\n此EQ已经Follow PE EQ状态:[$ENUM_ENGCHK_STATUS->{$f->{enum_engchk_status}}{display_name}]\n是否升级更新?") eq 'yes'){
if ($eq_version >= $f->{version}){
my $eq_version1=$eq_version+1;
save_job_engchk_question(-jobid=>$JOB_ID,-engchkitem=>'EQM_if_laser_drill_on_mechanical_hole',-version=>$eq_version1,-questions=>\%$questions);
$mark_cam='yes';
}
}
}
}
}
}
elsif(!$exist_eq){
my $ok;
$ok->{'na'}= 'ok';
save_job_engchk_question(-jobid=>$JOB_ID,-engchkitem=>'EQM_if_laser_drill_on_mechanical_hole',-log=>$log,-questions=>\%$ok);
}
if ($mark_cam) {
$GUI->msgbox(-icon=>'info',-text=>"[$check_eq->{display_name}]有升级或刷新,请到[EQ-3 Drill check]workflow再次检查后follow EQ");
}
#判断料号是否存在;
unless ($GEN->isJobExists(job=>$Job)){
$GUI->msgbox(-icon=>'error',-text=>"料号[$Job]不存在!");
return 'Error';
}
$GEN->openJob(job=>$Job);
my @steps = $GEN->getStepList(job=>$Job);
if (@steps != 1){
@selstep = $GUI->select_step(-title=>'请选择包含钻孔信息的Step',-steplist=>\@steps,-selectmode=>'multiple');
return 'Cancel' unless @selstep;
}
else{
@selstep = @steps;
}
$GEN->openStep(job=>$Job,name=>$selstep[0]);
my @form_items;
foreach my $item (@selstep){
my $tmp = {
name=>$item,
label=>$item,
type=>'enum',
must_field=>1,
property=>{
tl_field=>['name'=>'scalar',display_name=>'text'],
tl_value_field=>'name',
tl_data=>[
{name=>'card',display_name=>'Card'},
{name=>'array',display_name=>'Array'},
#{name=>'coupon',display_name=>'Coupon'},
]
}
};
push @form_items,$tmp;
}
my $stepinfo = $GUI->show_form(-title=>'请定义Step类型',-items=>\@form_items,-defaultsize=>[300,300],-showcheck => 1,-gen => $GEN,);
return 'Cancel' unless $stepinfo;
my $check_list = $PAR->{check_list};
my $matrix = $GEN->getMatrix(job=>$Job);
my (@drill_layers,@signal_layers);
foreach my $item (sort{$a->{row} <=> $b->{row}} values %$matrix){
if ($item->{context} eq 'board' and $item->{layer_type} eq 'drill'){
push @drill_layers,$item;
}
elsif ($item->{context} eq 'board' and $item->{layer_type} =~ /^(signal|power_ground|mixed)$/){
push @signal_layers,$item;
}
}
my $num;
foreach my $drill (@drill_layers){
$num++;
$GEN->renameLayer(job=>$Job,layer=>$drill->{name},new_name=>$num.'_drill');
}
$matrix = $GEN->getMatrix(job=>$Job);
foreach my $layer (sort {$matrix->{$a}{row} <=> $matrix->{$b}{row}} keys %$matrix) {
if ($layer =~/comp_\+_top|comp_\+_bot/i ){
$GEN->COM('delete_comp');
last;
}
}
$matrix = $GEN->getMatrix(job=>$Job);
@drill_layers=();
@signal_layers=();
foreach my $item (sort{$a->{row} <=> $b->{row}} values %$matrix){
if ($item->{context} eq 'board' and $item->{layer_type} eq 'drill'){
push @drill_layers,$item;
}
elsif ($item->{context} eq 'board' and $item->{layer_type} =~ /^(signal|power_ground|mixed)$/){
push @signal_layers,$item;
}
}
### Update check if Drill layer is only 1-2/2-3/... and Symetrical Type , like 1-10,2-9,3-8 ... (10 Layer for example)
### If YES $isSymmetricalDrill = 1, Else take is 0
### SymmetricalDrill Means 1-10, 2-9 , should be Mech Hole, Even the hole size is < 7 mil
my $isSymmetricalDrill = 1;
foreach my $item (@drill_layers){
if (abs($item->{drl_start_num} - $item->{drl_end_num}) != 1
and $item->{drl_start_num} + $item->{drl_end_num} != $layercount + 1) {
$isSymmetricalDrill = 0;
last;
}
}
foreach my $item (@drill_layers){
my $type = check_drill_hole_size($item->{name});
if ($item->{drl_start_num}<$half_layercount and $item->{drl_end_num} < $half_layercount and $type eq 'laser'){
$item->{tl_name} = 'laser'.$item->{drl_start_num}.'-'.$item->{drl_end_num};
$item->{tl_type} = 'laser_drill';
my @c_drls;
foreach my $drl (@drill_layers){
if ($drl->{drl_start_num} == $item->{drl_end_num}){
push @c_drls,$drl,
}
}
if (@c_drls){
my @tl_data = ({name=>'',tl_name=>''});
foreach my $it (@c_drls){
push @tl_data,{name=>$it->{name},tl_name=>$it->{tl_name}};
}
my $tmp = {
name=>$item->{name},
label=>$item->{name},
type=>'enum',
property=>{
tl_field=>['name'=>'text',tl_name=>'scalar'],
tl_value_field=>'tl_name',
tl_data=>\@tl_data,
}
};
}
}
elsif($item->{drl_start_num}>$half_layercount and $item->{drl_end_num} > $half_layercount and $type eq 'laser'){
$item->{tl_name} = 'laser'.$item->{drl_start_num}.'-'.$item->{drl_end_num};
$item->{tl_type} = 'laser_drill';
my @c_drls;
foreach my $drl (@drill_layers){
if ($drl->{drl_end_num} == $item->{drl_start_num}){
push @c_drls,$drl,
}
}
if (@c_drls){
my @tl_data = ({name=>'',tl_name=>''});
foreach my $it (@c_drls){
push @tl_data,{name=>$it->{name},tl_name=>$it->{tl_name}};
}
my $tmp = {
name=>$item->{name},
label=>$item->{name},
type=>'enum',
property=>{
tl_field=>['name'=>'text',tl_name=>'scalar'],
tl_value_field=>'tl_name',
tl_data=>\@tl_data,
}
};
}
}
else{
if ($item->{drl_start_num} == 1 and $item->{drl_end_num} == $layercount){
if ($isSymmetricalDrill) {
$item->{tl_name} = 'drill';
$item->{tl_type} = 'main_drill';
}else {
if ($type eq 'laser'){
$item->{tl_name} = 'laser'.$item->{drl_start_num}.'-'.$item->{drl_end_num};
$item->{tl_type} = 'laser_drill';
}
elsif ($type eq 'mech'){
$item->{tl_name} = 'drill';
$item->{tl_type} = 'main_drill';
}
else{
$item->{tl_name} = 'drill';
$item->{tl_type} = 'main_drill';
}
}
}
else{
if ($isSymmetricalDrill and abs($item->{drl_start_num} - $item->{drl_end_num}) != 1) {
$item->{tl_name} = 'drill'.$item->{drl_start_num}.'-'.$item->{drl_end_num};
$item->{tl_type} = 'bury_drill';
}else {
my $singleType = check_hole_size($item->{name});
if ($singleType eq 'laser'){
$item->{tl_name} = 'laser'.$item->{drl_start_num}.'-'.$item->{drl_end_num};
$item->{tl_type} = 'laser_drill';
}
else{
$item->{tl_name} = 'drill'.$item->{drl_start_num}.'-'.$item->{drl_end_num};
$item->{tl_type} = 'bury_drill';
}
}
}
}
}
#$GUI->debug(dump \@drill_layers);
# exit;
$DB->delete(-table=>'job_org_layer_drillinfo',-where=>{job_id=>$JOB_ID});
foreach my $step (keys %$stepinfo){
$GEN->openStep(job=>$Job,name=>$step);
return unless ($GEN->PAUSE("Please check the profile which used as check area!"));
$GEN->openStep(job=>$Job,name=>$step);
$GEN->units(type=>'inch');
my @check_list = $GEN->getChecklist(job=>$Job,step=>$step);
if (! grep(/^\Q$check_list\E$/,@check_list)){
$GEN->chklistFromLib(chklist=>$check_list);
}
$GEN->chklistShow(chklist=>$check_list);
$GEN->chklistRun(chklist=>$check_list,nact=>$PAR->{drill_summary_nact});
# return unless ($GEN->PAUSE("FERRE MANUAL Check REPORT!"));
my @chkresult = $GEN->getCheckMeas(job=>$Job,step=>$step,chklist=>$check_list,nact=>$PAR->{drill_summary_nact});
my %error;
if ($incam eq "no") {
%error = $GEN->INFO(entity_type => 'check',
entity_path => "$Job/$step/$check_list",
data_type => 'STATUS',
options => "action=$PAR->{drill_summary_nact}",
);
}else{
%error = $GEN->INFO(entity_type => 'check',
angle_direction=>'ccw',
entity_path => "$Job/$step/$check_list",
data_type => 'STATUS',
options => "action=$PAR->{drill_summary_nact}",
);
}
if ($GEN->{doinfo}{gSTATUS} eq 'ERROR'){
$GUI->msgbox(-icon=>'error',-text=>"Drill summary分析出错,请检查Surface Analyzer,可能是surface问题造成");
exit;
}
my %pad_size;
foreach my $item (@chkresult){
my @tmp = split(/ /,$item);
next unless ($tmp[0] =~ /_(inner|outer)__(VIA|PTH)_(.*)_AR/);
my ($drillname) = $tmp[0] =~ /^(.*)_(?:inner|outer)/;
my $h_size = $tmp[4];
$h_size =~ s/r//i;
my $p_size = $tmp[2]*2+$h_size;
my $sig_layer = $tmp[1];
my $key = $drillname.':'.$h_size.':'.$sig_layer;
my $exist_size = $pad_size{$key}{min_pad_size};
## Fixed Bug for Same Hole size with Both Via & PTH, Ferre. 2017-02-22
if (! $exist_size or $exist_size > $p_size) {
$pad_size{$key}{drill_name} = $drillname;
$pad_size{$key}{hole_size} = $h_size;
$pad_size{$key}{signal_layer} = $sig_layer;
$pad_size{$key}{min_pad_size} = $p_size;
$pad_size{$key}{px} = $tmp[6];
$pad_size{$key}{py} = $tmp[7];
}
#unless ($pad_size{$key}{min_pad_size}){
# $pad_size{$key}{drill_name} = $drillname;
# $pad_size{$key}{hole_size} = $h_size;
# $pad_size{$key}{signal_layer} = $sig_layer;
# $pad_size{$key}{min_pad_size} = $p_size;
# $pad_size{$key}{px} = $tmp[6];
# $pad_size{$key}{py} = $tmp[7];
#}
}
#$GUI->debug(dump(\%pad_size));
# return unless ($GEN->PAUSE("FERRE check area!"));
foreach my $sig_layer (@signal_layers){
$GEN->workLayer(name=>$sig_layer->{name},clear_before=>'yes');
foreach my $item (values %pad_size){
if ($item->{signal_layer} eq $sig_layer->{name}){
$GEN->selClearFeature();
$GEN->selectByFilter(feat_types=>'pad',intersect_area=>'yes',area_rect=>{x1=>$item->{px}-0.003,y1=>$item->{py}-0.003,x2=>$item->{px}+0.003,y2=>$item->{py}+0.003});
my @feats = $GEN->getFeatures(job=>$Job,step=>$step,layer=>$sig_layer->{name},options=>'select');
my @rpad;
foreach my $feat (@feats){
if ($feat->{type} eq 'pad' and $feat->{symbol} =~ /^r(\d+(\.\d+)?)$/){
my ($s) = $feat->{symbol} =~ /^r(.*)$/;
push @rpad,$s;
}
}
foreach my $size (sort {$a<=>$b} @rpad) {
if (abs ($size - $item->{min_pad_size}) <= 0.002 or $size > $item->{min_pad_size}) {
$item->{min_pad_size} = $size;
last;
}
}
}
}
}
my %drl_tools;
my %num_plus;
foreach my $drl (@drill_layers){
$GEN->openStep(job=>$Job,name=>$step);
$GEN->units(type=>'inch');
$GEN->COM('tools_tab_reset');
$GEN->COM('tools_merge_ex',layer=>$drl->{name},mode=>'merge');
$GEN->COM('tools_set',layer=>$drl->{name},thickness=>0,user_params=>'',slots=>'by_length');
$GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>$drl->{name},clear_before=>'yes');
$GEN->selectByFilter(attribute=>['component_via']);
my $component_via_tmp = $drl->{tl_name}.'_ic_via';
_deleteLayer(step=>$step,layer=>[$component_via_tmp]);
if ( $GEN->getSelectCount() > 0 ){
#$GEN->PAUSE("111111111111111");
$GEN->selMoveOther(target_layer=>$component_via_tmp,invert=>'no');
$GEN->matrixLayerAttr(job=>$Job,layer=>$component_via_tmp,type=>'drill');
my $tool_via_tmps = $GEN->getTool(job=>$Job,step=>$step,layer=>$component_via_tmp);
my @drilled_layers;
foreach my $sig_layer (@signal_layers){
if ($sig_layer->{tl_num} >= $drl->{drl_start_num} and $sig_layer->{tl_num} <= $drl->{drl_end_num}){
push @drilled_layers,$sig_layer->{name};
}
}
$num_plus{$drl->{tl_name}} = 0 unless ($num_plus{$drl->{tl_name}});
my $tmp=0;
foreach my $tool (values %$tool_via_tmps){
if ($tool->{type} ne 'non_plated'){
foreach my $item (values %pad_size){
my $sig = $item->{signal_layer};
if ($item->{drill_name} eq $drl->{name} and
abs($item->{hole_size} - $tool->{drill_size}) < 0.001)
{
$tool->{min_pad_size}{$matrix->{$item->{signal_layer}}{tl_name}} = $item->{min_pad_size};
}
}
}
$tmp=$tool->{num} if ($tmp<$tool->{num});
my $slot=0;
$slot = $tool->{slot_len} + $tool->{drill_size} if ($tool->{slot_len} !=0);
$DB->insert(-table=>'job_org_layer_drillinfo',
-data=>{
job_id => $JOB_ID,
drill_tl_name => $drl->{tl_name},
step_type=>$stepinfo->{$step},
tool_num=>$tool->{num}+$num_plus{$drl->{tl_name}},
count => $tool->{count},
shape => $tool->{shape},
type => $tool->{type},
drill_size => $tool->{drill_size},
finish_size => $tool->{finish_size}==0?$tool->{drill_size}:$tool->{finish_size},
slot_length => $slot,
min_pad_size => dump($tool->{min_pad_size}),
max_drill_tol => $tool->{max_tol},
min_drill_tol => $tool->{min_tol},
laser_on_component=>'1',
},
);
#$GEN->PAUSE("222222222 $drl->{tl_name}");
}
$num_plus{$drl->{tl_name}}+=$tmp;
_deleteLayer(step=>$step,layer=>[$component_via_tmp]);
$GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>$drl->{name},clear_before=>'yes');
$GEN->selectByFilter();
next if ( !$GEN->getSelectCount());
}
$GEN->affectedLayer(affected=>'yes',mode=>'single',layer=>$drl->{name},clear_before=>'yes');
my $tools = $GEN->getTool(job=>$Job,step=>$step,layer=>$drl->{name});
my @drilled_layers;
foreach my $sig_layer (@signal_layers){
if ($sig_layer->{tl_num} >= $drl->{drl_start_num} and $sig_layer->{tl_num} <= $drl->{drl_end_num}){
push @drilled_layers,$sig_layer->{name};
}
}
$num_plus{$drl->{tl_name}} = 0 unless ($num_plus{$drl->{tl_name}});
my $tmp=0;
foreach my $tool (values %$tools){
if ($tool->{type} ne 'non_plated'){
foreach my $item (values %pad_size){
my $sig = $item->{signal_layer};
if ($item->{drill_name} eq $drl->{name} and
abs($item->{hole_size} - $tool->{drill_size}) < 0.001)
{
$tool->{min_pad_size}{$matrix->{$item->{signal_layer}}{tl_name}} = $item->{min_pad_size};
}
}
}
$tmp=$tool->{num} if ($tmp<$tool->{num});
my $slot=0;
$slot = $tool->{slot_len} + $tool->{drill_size} if ($tool->{slot_len} !=0);
$DB->insert(-table=>'job_org_layer_drillinfo',
-data=>{
job_id => $JOB_ID,
drill_tl_name => $drl->{tl_name},
step_type=>$stepinfo->{$step},
tool_num=>$tool->{num}+$num_plus{$drl->{tl_name}},
count => $tool->{count},
shape => $tool->{shape},
type => $tool->{type},
drill_size => $tool->{drill_size},
finish_size => $tool->{finish_size}==0?$tool->{drill_size}:$tool->{finish_size},
slot_length => $slot,
min_pad_size => dump($tool->{min_pad_size}),
max_drill_tol => $tool->{max_tol},
min_drill_tol => $tool->{min_tol},
},
);
#$GEN->PAUSE("111111111111111");
}
$num_plus{$drl->{tl_name}}+=$tmp;
if ($GEN->isLayerExists(job=>$Job,layer=>$component_via_tmp)){
$GEN->copyLayer(source_job=>$Job,source_step=>$step,source_layer=>$component_via_tmp,dest_layer=>$drl->{name},mode=>'append');
_deleteLayer(step=>$step,layer=>[$component_via_tmp]);
}
}
$GEN->clearLayers();
$GEN->affectedLayer(mode=>'all',affected=>'no');
#$GEN->closeStep();
}
my $jobpath = $GEN->getJobPath(job=>$Job);
`chmod -R 777 $jobpath` if (-d $jobpath);
$GEN->closeJob(job=>$Job);
$GEN->openJob(job=>$Job);
my $drill_info = $DB->get_jobinfo(-jobid=>$JOB_ID,
-jobcategory=>'work',
-jobinfo=>'pe_check_drill_info',
#-jobinfo=>'mast1',
);
$drill_info=eval($drill_info);
my %drill_info;
foreach my $ref (@$drill_info){
push @{$drill_info{$ref->{layer}}},{org_size=>$ref->{org_size},size=>$ref->{size}};
}
if (keys %drill_info) {
my $via_hole_um =500;
my $v_tmp;
my $layer_info = $DB->select_arrayhash(
-table => 'job_org_layer_drillinfo',
-where => "job_id = $JOB_ID ",
-field=>['drill_tl_name','drill_size','type','shape'],
);
my %laser;
foreach my $ref (@$layer_info){
#next if ($ref->{drill_tl_name} eq 'drill');
if ($ref->{drill_tl_name} eq 'drill') {
if ($ref->{type} ne 'non_plated' and $ref->{shape} ne 'slot' ) {
my $r = $ref->{drill_size}*25.4;
push @{$laser{$ref->{drill_tl_name}}},$r if (!grep /^$r$/,@{$laser{$ref->{drill_tl_name}}});
}
}
elsif ($ref->{drill_tl_name} =~/drill/ ){
my $r = $ref->{drill_size}*25.4;
push @{$laser{$ref->{drill_tl_name}}},$r if (!grep /^$r$/,@{$laser{$ref->{drill_tl_name}}});
}
else{
if ($ref->{drill_tl_name} =~/(\d+)\-(\d+)/) {
#next if ($max_drill < $ref->{drill_size});
my $s=$1;
my $e=$2;
my $r = $ref->{drill_size}*25.4;
if ($e==$s+1){
push @{$laser{$ref->{drill_tl_name}}},$r if (!grep /^$r$/,@{$laser{$ref->{drill_tl_name}}});
}
else{
for my $n ($s..$e){
last if ($n == $e);
my $n1=$n+1;
my $tl_name ='laser'.$n.'-'.$n1;
push @{$laser{$tl_name}},$r if (!grep /^$r$/,@{$laser{$tl_name}});
}
}
}
}
}
#$GUI->debug(dump \%laser);
my %sortdrill;
foreach my $layer (keys %laser){
if ($layer eq 'drill'){
push @{$sortdrill{0}},$layer;
}
elsif ($layer=~/(\d+)/) {
push @{$sortdrill{$1}},$layer;
}
}
foreach my $n (sort {$a<=>$b} keys %sortdrill){
my @layers =@{$sortdrill{$n}};
foreach my $layer (@layers){
if ($layer eq 'drill' ){
foreach my $size (@{$laser{$layer}}) {
if ($size > $via_hole_um) {
my $new_size =$size +100;
$new_size = sprintf("%.0f",$new_size);
push @$v_tmp,{layer=>$layer,org_size=>$size,color=>'purple',size=>$new_size};
}
else{
push @$v_tmp,{layer=>$layer,org_size=>$size,color=>'blue'};
}
}
}
elsif ($layer =~/drill/ ){
foreach my $size (@{$laser{$layer}}) {
push @$v_tmp,{layer=>$layer,org_size=>$size,color=>'red'};
}
}
else{
foreach my $size (@{$laser{$layer}}) {
push @$v_tmp,{layer=>$layer,org_size=>$size,color=>'black'};
}
}
}
}
my %get_database_drill;
foreach my $ref (@$v_tmp){
push @{$get_database_drill{$ref->{layer}}},{org_size=>$ref->{org_size},size=>$ref->{size}};
}
#
#$GUI->debug(dump \%drill_info);
#$GUI->debug(dump \%get_database_drill);
my @error;
foreach my $tl_name (keys %get_database_drill){
if (@{$drill_info{$tl_name}}) {
my @drill1s;
foreach my $ref (@{$get_database_drill{$tl_name}}){
push @drill1s,$ref->{org_size};
}
my @drill2s;
foreach my $ref1 (@{$drill_info{$tl_name}}){
push @drill2s,$ref1->{org_size};
}
my %seen=();
foreach (@drill1s){
$seen{$_}=1;
}
my @same=grep($seen{$_},@drill2s);
my @diff=grep(!$seen{$_},@drill2s);
if (@diff) {
push @error,"$tl_name [@diff]和PE之前load的Drill Org信息不一样";
}
}
else{
push @error,"原稿孔层[$tl_name]和PE定义的Drill层名对不上";
}
}
#$GUI->msgbox(-icon=>'error',-text=>join("\n",@error));
if (@error) {
my $sent_mail = join('<br>',@error)."<br>QEC孔层有更新,请再次检查PE预审信息中drill表";
mail_sand_task(jobname=>$JOB,
title=>'pe_eq_info_update_drill',
subject=>"Pls Update [$JOB] EQM Drill List in PE EQM PRE Info",
body=>$sent_mail,
sand_mode=>'always',
);
}
}
unless ($GEN->{STATUS}){
return $Return;
}
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 = encode("utf8",shift);
$GUI->msgbox(-icon=>'error',-text=>$error);
return 'Error';
}
finally{
};
sub check_hole_size{
my $layer = shift;
my @steps = $GEN->getStepList(job=>$Job);
my $drill_type = 'mech';
foreach my $step (@selstep){
$GEN->COM('tools_tab_reset');
$GEN->COM('tools_merge_ex',layer=>$layer,mode=>'merge');
$GEN->COM('tools_set',layer=>$layer,thickness=>0,user_params=>'',slots=>'by_length');
my $tools = $GEN->getTool(job=>$Job,step=>$step,layer=>$layer);
next unless (%$tools);
foreach my $tool (values %$tools){
next if ($tool->{drill_size} ==0);
if ($tool->{drill_size} < $max_drill){
$drill_type = 'laser';
last;
}
}
last if $drill_type eq 'mech';
}
return $drill_type;
}
sub check_drill_hole_size{
my $layer = shift;
my @steps = $GEN->getStepList(job=>$Job);
my $drill_type;
foreach my $step (@selstep){
$GEN->COM('tools_tab_reset');
$GEN->COM('tools_set',layer=>$layer,thickness=>0,user_params=>'',slots=>'by_length');
my $tools = $GEN->getTool(job=>$Job,step=>$step,layer=>$layer);
next unless (%$tools);
foreach my $tool (values %$tools){
next if ($tool->{drill_size} ==0);
if ($tool->{drill_size} < $max_drill and $drill_type !~/laser/){
$drill_type.= 'laser';
}
elsif ($tool->{drill_size} >= $max_drill and $drill_type !~/mech/){
$drill_type.='mech';
}
}
}
return $drill_type;
}
sub mail_sand_task {
my %par = @_; ## subject ##body ## title
my $mailinfo=$DB->select_hash(-table=>'ats_mail_sand_task',-where=>{mail_title=>$par{title}});
if ($mailinfo->{status} eq 'Start'){
my $mail_to=$mailinfo->{mail_to};
my $mail_cc=$mailinfo->{mail_cc};
if ($mail_to=~/^sub/){
$mail_to=eval($mail_to);
$mail_to= $mail_to->(job_id=>$job_id);
}
else{
$mail_to=eval($mail_to) if ($mail_to=~/^\$/);
}
if ($mail_cc=~/^sub/){
$mail_cc=eval($mail_cc);
$mail_cc= $mail_cc->(job_id=>$job_id);
}
else{
$mail_cc=eval($mail_cc) if ($mail_cc=~/^\$/);
}
my @to = split(/\;|\:|\,|\n/,$mail_to);
foreach my $it (@to){
$it =~ s/(^\s+|\s+$)//g;
}
$par{-to} = \@to;
#$data{cc} =~ s/\s+//g;
my @cc = split(/\;|\:|\,|\n/,$mail_cc);
foreach my $it (@cc){
$it =~ s/(^\s+|\s+$)//g;
}
$par{-cc} = \@cc;
$par{cc_user}='';
$par{group}='';
#$GUI->debug("@to m @cc ");
my $subject=$par{subject};
my $body = $par{body};
my $mail_version = $DB->select_value(
-table=>'ats_auto_mail_record',
-field=>'max(mail_version)',
-where=>"job_id = $JOB_ID and mail_title = '$par{title}'",
);
$mail_version = 0 unless ($mail_version);
$mail_version++;
my $resart_mail= 'yes';
if ($mail_version > 1 and $par{sand_mode} ne 'always' ){
my $tmp_v=$mail_version-1;
my $mail_subject = $DB->select_value(
-table=>'ats_auto_mail_record',
-field=>'mail_subject',
-where=>"job_id = $JOB_ID and mail_title = '$par{title}' and mail_version = $tmp_v",
);
my $mail_body = $DB->select_value(
-table=>'ats_auto_mail_record',
-field=>'mail_content',
-where=>"job_id = $JOB_ID and mail_title = '$par{title}' and mail_version = $tmp_v",
);
if ($mail_subject eq $subject){
$resart_mail='no';
if ($mail_body ne $body){
$resart_mail='yes';
}
}
elsif ($mail_body ne $body){
$resart_mail='yes';
}
}
#$GUI->debug(dump\%par);
#exit;
if ($resart_mail eq 'yes'){
Top::MailSender->send_mail(%par);
my ($content,$att);
if (ref $par{body} eq 'ARRAY') {
($content,$att) = @{$par{body}};
}
else {
$content = $par{body};
}
if ($att) {
my @att = @{$att};
if (@att) {
$att = join(',',@att);
$att = '' unless ($att);
}else {
$att = '';
}
}
else {
$att = '';
}
$DB->insert(
-table=>'ats_auto_mail_record',
-data=>{
job_id => $JOB_ID,
mail_from=>$APP->{USER_NAME},
mail_to=>$mail_to,
mail_cc=>$mail_cc,
mail_subject=>$par{subject},
mail_title=>$par{title},
mail_content=>$content,
mail_attachment=>$att,
mail_version=>$mail_version,
}
);
}
}
}
sub save_job_engchk_question{
my %par = @_;
$par{-version} = $DB->get_job_engchk_version(-jobid=>$par{-jobid}) unless $par{-version};
my $chkitem_id = $DB->select_value(-table=>'engchk_chkitem',-field=>'id',-where=>{name=>$par{-engchkitem}});
return unless $chkitem_id;
my $prob_ids = $DB->select_fieldarray(-table=>'engchk_problem',-field=>'id',-where=>{engchk_chkitem_id=>$chkitem_id});
my $prob_hash = $DB->select_hashhash(-table=>'engchk_problem',-field=>'*',-hashkey=>'name',-where=>{engchk_chkitem_id=>$chkitem_id});
my $err;
my $now = $DB->get_now();
$DB->begin();
$DB->delete(-table=>'job_engchk',-where=>{job_id=>$par{-jobid},version=>$par{-version},engchk_problem_id=>$prob_ids}) if ($par{-delete});
foreach my $prob_name (keys %{$par{-questions}}){
#$GUI->debug("$prob_name");
my $tmp = {
job_id=>$par{-jobid},
engchk_problem_id=>$prob_hash->{$prob_name}{id},
version=>$par{-version},
enum_engchk_status=>$par{-questions}->{$prob_name}{enum_engchk_status}||'New',
enum_engchk_problem_type=>$prob_hash->{$prob_name}{enum_engchk_problem_type},
enum_engchk_affected_tooling =>$prob_hash->{$prob_name}{enum_engchk_affected_tooling},
enum_engchk_problem_report_to =>$prob_hash->{$prob_name}{enum_engchk_problem_report_to},
log=>$par{-log},
};
$par{-questions}->{$prob_name}{text} = $prob_hash->{$prob_name}{problem_detail} unless defined $par{-questions}->{$prob_name}{text};
$par{-questions}->{$prob_name}{language} = $prob_hash->{$prob_name}{enum_display_name_language} unless defined $par{-questions}->{$prob_name}{language};
$par{-questions}->{$prob_name}{editable} = $prob_hash->{$prob_name}{editable} unless defined $par{-questions}->{$prob_name}{editable};
#$tmp->{question} = dump($par{-questions}->{$prob_name});
$tmp->{question_text} = (defined $par{-questions}->{$prob_name}{text})?$par{-questions}->{$prob_name}{text}:$prob_hash->{$prob_name}{problem_detail};
$tmp->{question_value} = $par{-questions}->{$prob_name}{value}?dump($par{-questions}->{$prob_name}{value}):undef;
$tmp->{question_attachment} = $par{-questions}->{$prob_name}{attachment}?dump($par{-questions}->{$prob_name}{attachment}):undef;
$tmp->{question_user} = $par{-questions}->{$prob_name}{user} || $APP->{USER_FULL_NAME};
$tmp->{question_timestamp} = $par{-questions}->{$prob_name}{timestamp} || $now;
#$GUI->debug(dump \$tmp);
$DB->update_with_insert(-table=>'job_engchk',-data=>$tmp,-where=>['job_id','engchk_problem_id','version']);
#save_job_engchk_question
$err = $DB->err;
last if $err;
}
if ($err){
$DB->rollback;
return $err;
}
else{
$DB->commit;
return 0;
}
}
sub _deleteLayer{
my %par = @_;
foreach my $layer(@{$par{layer}}){
$GEN->deleteLayer(layer=>$layer) if ($GEN->isLayerExists(job=>$Job,layer=>$layer));
}
$GEN->openStep(job=>$Job,name=>$par{step}) if ($par{step});
}
\ No newline at end of file
## 2171 ok
* 2171是tgz格式 已经有外形
## yucca
比较复杂 规律难总结
一些参考料号 20444453_220 88880010_110 88880033_133
没有合适的 fab层创建 规则
## vivo ok
```
先判断 有没有line层 有line层选择line层创建
没line层找top层 判断top层是否有外框 有外框选择外框创建
```
## Wistron ok
判读有没有outline层 全选outline层创建
有没有 contour 层 过滤contour层上边的描述框后创建
## 1352 ok
使用之前的做法
\ No newline at end of file
...@@ -167,10 +167,31 @@ if(mailUserList && mailUserList.length) { ...@@ -167,10 +167,31 @@ if(mailUserList && mailUserList.length) {
var cam_workflow_info = IKM.get_jobinfo({jobid:JobId, jobinfo:"cam_workflow_info"}); var cam_workflow_info = IKM.get_jobinfo({jobid:JobId, jobinfo:"cam_workflow_info"});
console.log("==========cam_workflow_info===========:" + cam_workflow_info); console.log("==========cam_workflow_info===========:" + cam_workflow_info);
try { try {
// if(cam_workflow_info == "err"){ // ! tmp if(cam_workflow_info == "err" && global._STATUS == "err"){
// console.log("==========cam_workflow_info===========:" + cam_workflow_info); console.log("==========cam_workflow_info===========:" + cam_workflow_info);
// throw cam_workflow_info throw cam_workflow_info
// } }
if(global._STATUS != "err") {
// 清空报错信息
var job_attrs = db.query("",function(q){
return q.selectValue({
table:'pdm_job',
field_format:{job_attrs:'json'},
field:'job_attrs',
where:{id : JobId}
})
});
if (!job_attrs ) { job_attrs = {}}
job_attrs.readin_result = "Readin"
db.query("",function(q){
return q.updateRow({
table:'pdm_job',
data:{job_attrs:job_attrs},
update_policy:{attr_data:'json_merge'},
where:{id : JobId}
})
});
}
cam_workflow_info = "sendmail" cam_workflow_info = "sendmail"
console.log("=============================================>anaysis_start"); console.log("=============================================>anaysis_start");
var par = PAR; var par = PAR;
...@@ -670,6 +691,11 @@ try { ...@@ -670,6 +691,11 @@ try {
GEN.COM("chklist_run,chklist=valor_cleanup_set_smd,nact=1,area=profile") GEN.COM("chklist_run,chklist=valor_cleanup_set_smd,nact=1,area=profile")
GEN.COM("chklist_close,chklist=valor_cleanup_set_smd,mode=hide") GEN.COM("chklist_close,chklist=valor_cleanup_set_smd,mode=hide")
}else{ }else{
// GEN.chklistRun({
// chklist: "quotation_check",
// nact: 4,
// area: 'profile'
// })
GEN.COM("chklist_single,show=yes,action=valor_cleanup_set_smd") GEN.COM("chklist_single,show=yes,action=valor_cleanup_set_smd")
GEN.COM("chklist_cupd,chklist=valor_cleanup_set_smd,nact=1,params=((pp_layer=.type=signal|mixed&side=top|bottom)(pp_work_on=SMD\;BGA)(pp_delete=No)(pp_types=Square\;Rect\;Oval)(pp_other_smd=)(pp_sm=No)(pp_drill=)(pp_rotate=No)(pp_ignore_covered=Yes)(pp_bga_types=Round)(pp_other_bga=)(pp_sm_bga=No)(pp_bga_max_pitch=70)(pp_bga_actions=Set attribute)(pp_bga_suffix=_bga)(pp_identify_gf=)),mode=regular") GEN.COM("chklist_cupd,chklist=valor_cleanup_set_smd,nact=1,params=((pp_layer=.type=signal|mixed&side=top|bottom)(pp_work_on=SMD\;BGA)(pp_delete=No)(pp_types=Square\;Rect\;Oval)(pp_other_smd=)(pp_sm=No)(pp_drill=)(pp_rotate=No)(pp_ignore_covered=Yes)(pp_bga_types=Round)(pp_other_bga=)(pp_sm_bga=No)(pp_bga_max_pitch=70)(pp_bga_actions=Set attribute)(pp_bga_suffix=_bga)(pp_identify_gf=)),mode=regular")
GEN.COM("get_user_name") GEN.COM("get_user_name")
...@@ -787,10 +813,20 @@ try { ...@@ -787,10 +813,20 @@ try {
GEN.closeStep() GEN.closeStep()
} }
}) })
// var info = {
// min_line_width: ["line","user_nor_line"],
// min_line_spacing: ["c2c","l2l","user_nor_line2nor_line"],
// min_line2pad: ["p2line","user_010052nor_line","user_bga2nor_line-1","user_smd2nor_line","user_self_spacing_smd2l"],
// min_pad2pad: ["p2p", "smd2smd", "smd2pad","via2via","bga2pad"],
// min_ar_laser:["laser_via_ar"],
// min_ar_via:["via_ar"],
// min_ar_pth:["pth_ar"],
// min_ar_npth:["npth_ar"]
// }
var info = { var info = {
min_line_width: ["line","user_nor_line"], min_line_width: ["line","user_nor_line"],
min_line_spacing: ["c2c","l2l","user_nor_line2nor_line"], min_line_spacing: ["c2c","l2l","user_nor_line2nor_line"],
min_line2pad: ["p2line","user_010052nor_line","user_bga2nor_line-1","user_smd2nor_line","user_self_spacing_smd2l"], min_line2pad: ["p2line","p2c"],
min_pad2pad: ["p2p", "smd2smd", "smd2pad","via2via","bga2pad"], min_pad2pad: ["p2p", "smd2smd", "smd2pad","via2via","bga2pad"],
min_ar_laser:["laser_via_ar"], min_ar_laser:["laser_via_ar"],
min_ar_via:["via_ar"], min_ar_via:["via_ar"],
...@@ -808,7 +844,7 @@ try { ...@@ -808,7 +844,7 @@ try {
// } else { // } else {
// jobpath = "/home/local_db/server_db/jobs/"+job // jobpath = "/home/local_db/server_db/jobs/"+job
// } // }
mkPath(jobpath,["user","opcam","steps"]) // mkPath(jobpath,["user","opcam","steps"])
script_info({ msg: "Error-Signal layer analysis" }) script_info({ msg: "Error-Signal layer analysis" })
script_info({ progress: 85 }) script_info({ progress: 85 })
stepList.forEach(function(step){ stepList.forEach(function(step){
...@@ -940,36 +976,50 @@ try { ...@@ -940,36 +976,50 @@ try {
console.log("==================================> chk signals analysis") console.log("==================================> chk signals analysis")
// 创建chklist并运行 如果chklist存在先删除 // 创建chklist并运行 如果chklist存在先删除
if (GEN.isChklistExists({ job: job, step: step, chklist: oChecklistName })) {
GEN.COM("chklist_delete", { chklist: oChecklistName }) // var tmpitem = {
} // name: "signal_layer_checks",
var tmpitem = { // nact: 1,
name: "signal_layer_checks", // action: "valor_analysis_signal",
nact: 1, // params: {
action: "valor_analysis_signal", // pp_layer: ".affected",
params: { // pp_spacing: 20,
pp_layer: ".affected", // pp_selected: "All",
pp_spacing: 20, // pp_r2c: 10,
pp_selected: "All", // pp_d2c: 15,
pp_r2c: 10, // pp_sliver: 8,
pp_d2c: 15, // pp_min_pad_overlap: 5,
pp_sliver: 8, // pp_check_missing_pads_for_drills: "Yes",
pp_min_pad_overlap: 5, // pp_use_compensated_rout: "Skeleton",
pp_check_missing_pads_for_drills: "Yes", // pp_sm_spacing: "Yes"
pp_use_compensated_rout: "Skeleton", // }
pp_sm_spacing: "Yes" // }
} // if(par.erf){
} // tmpitem.erf = par.erf
if(par.erf){ // }
tmpitem.erf = par.erf // createChklistAndRun({ // 创建checklist并运行
} // layers: signalLayers,
// items: [tmpitem]
// })
script_info({ msg: "Error-Run Checklist",result_severity:"ok" }) script_info({ msg: "Error-Run Checklist",result_severity:"ok" })
createChklistAndRun({ // 创建checklist并运行 // if (GEN.isChklistExists({ job: job, step: step, chklist: oChecklistName })) {
layers: signalLayers, // GEN.COM("chklist_delete", { chklist: oChecklistName })
items: [tmpitem] // }
GEN.COM("chklist_from_lib,chklist=quotation_check,profile=none,customer=")
GEN.chklistRun({
chklist: "quotation_check",
nact: 1,
area: 'profile'
})
GEN.chklistRun({
chklist: "quotation_check",
nact: 2,
area: 'profile'
}) })
// signal层分析结果 // signal层分析结果
var res = analysisChkAttr({layers:signalLayers, info:info, step:step, job:job, oChecklistName:oChecklistName,jobpath:jobpath}) script_info({ msg: "Error-get ChkRes",result_severity:"ok" })
var res = analysisChkAttr({layers:signalLayers, info:info, step:step, job:job, oChecklistName:"quotation_check",jobpath:jobpath})
// 数据入库 // 数据入库
Object.keys(res).forEach(function(key){ Object.keys(res).forEach(function(key){
var val = res[key] var val = res[key]
...@@ -988,7 +1038,7 @@ try { ...@@ -988,7 +1038,7 @@ try {
}) })
GEN.closeStep() GEN.closeStep()
}) })
mvOutProfile({job:job, step:pcs_step}) // mvOutProfile({job:job, step:pcs_step})
// 保存 // 保存
if(/yes/ig.test(par.auto_save)){ if(/yes/ig.test(par.auto_save)){
...@@ -1022,20 +1072,20 @@ try { ...@@ -1022,20 +1072,20 @@ try {
script_info({ progress: 95 }) script_info({ progress: 95 })
script_info({ msg: "analysis done" }) script_info({ msg: "analysis done" })
// 导出 //! means信息无法导出
if(par.export_path != "" && par.export_mode != "" && par.export_submode != "" ){ // if(par.export_path != "" && par.export_mode != "" && par.export_submode != "" ){
if(fs.exists(par.export_path)){ // if(fs.exists(par.export_path)){
if(GEN.GEN_TYPE == "genesis"){ // if(GEN.GEN_TYPE == "genesis"){
GEN.COM("export_job,job="+job+",path="+par.export_path+",mode="+par.export_mode+",submode="+par.export_submode+",overwrite=yes") // GEN.COM("export_job,job="+job+",path="+par.export_path+",mode="+par.export_mode+",submode="+par.export_submode+",overwrite=yes")
} else { // } else {
GEN.COM("export_job",{job:job,path:par.export_path,mode:par.export_mode,submode:par.export_submode,overwrite:"yes",format:"genesis",output_name:job}) // GEN.COM("export_job",{job:job,path:par.export_path,mode:par.export_mode,submode:par.export_submode,overwrite:"yes",format:"genesis",output_name:job})
GEN.COM("disp_on") // GEN.COM("disp_on")
GEN.COM("origin_on") // GEN.COM("origin_on")
} // }
} else { // } else {
resultData.push({ type: "error", title: "导出路径不存在!", detail: [{ desc: par.export_path }] }); // resultData.push({ type: "error", title: "导出路径不存在!", detail: [{ desc: par.export_path }] });
} // }
} // }
// 邮件触发 // 邮件触发
sendEmail({ sendEmail({
...@@ -2053,7 +2103,8 @@ function analysisChkAttr(par) { ...@@ -2053,7 +2103,8 @@ function analysisChkAttr(par) {
var job = par.job; var job = par.job;
var oChecklistName = par.oChecklistName var oChecklistName = par.oChecklistName
layers.forEach(function (v) { layers.forEach(function (v) {
saveMeans({job:job,step:par.step,chklist:oChecklistName,nact:1,layer:v,jobpath:par.jobpath}) var nact = /top|bot/.test(v) ? 1 : 2;
// saveMeans({job:job,step:par.step,chklist:oChecklistName,nact:nact,layer:v,jobpath:par.jobpath})
hash[v] = {} hash[v] = {}
Object.keys(info).forEach(function (key) { Object.keys(info).forEach(function (key) {
var val = info[key] var val = info[key]
...@@ -2062,7 +2113,7 @@ function analysisChkAttr(par) { ...@@ -2062,7 +2113,7 @@ function analysisChkAttr(par) {
job: job, job: job,
step: par.step, step: par.step,
checklist: oChecklistName, checklist: oChecklistName,
nact: 1, nact: nact,
attr: v + "_min_" + type attr: v + "_min_" + type
}) })
console.log("===================== " + v + "_min_" + type + " -> " + tmp); console.log("===================== " + v + "_min_" + type + " -> " + tmp);
...@@ -2081,6 +2132,8 @@ function analysisChkAttr(par) { ...@@ -2081,6 +2132,8 @@ function analysisChkAttr(par) {
} }
}) })
}) })
exportInfo(hash)
return hash return hash
} }
function analysisDrill(par, step){ function analysisDrill(par, step){
......
...@@ -99,9 +99,9 @@ if(mailUserList && mailUserList.length) { ...@@ -99,9 +99,9 @@ if(mailUserList && mailUserList.length) {
} }
var cam_workflow_info = IKM.get_jobinfo({jobid:JobId, jobinfo:"cam_workflow_info"}); var cam_workflow_info = IKM.get_jobinfo({jobid:JobId, jobinfo:"cam_workflow_info"});
try { try {
// if(cam_workflow_info && cam_workflow_info != ""){ //! tmp if(cam_workflow_info && cam_workflow_info != ""){
// throw cam_workflow_info throw cam_workflow_info
// } }
script_info({ msg: "Data formatting" ,result_severity:"info"}) script_info({ msg: "Data formatting" ,result_severity:"info"})
script_info({ progress: 35 }) script_info({ progress: 35 })
var par = PAR; var par = PAR;
...@@ -393,21 +393,34 @@ try { ...@@ -393,21 +393,34 @@ try {
script_info({ msg: "Creating Profile" ,result_severity:"info"}) script_info({ msg: "Creating Profile" ,result_severity:"info"})
script_info({ progress: 55 }) script_info({ progress: 55 })
var all_layer = Object.keys(tmp_matrix) var all_layer = Object.keys(tmp_matrix);
// 没有outline层 // 没有outline层
if(all_layer.indexOf("outline") >= 0) { profileRule.unshift("outline")}
if(profileRule){
// 判断有没有profile // 判断有没有profile
var tmp_step = GEN.getStepList({job:job})[0] var tmp_step = GEN.getStepList({job:job})[0]
GEN.openStep({job:job, name:tmp_step}) GEN.openStep({job:job, name:tmp_step})
var now_profile = GEN.getProfile({job:job, step:tmp_step}) if(!hasProfle({job:job, step:tmp_step})){ // 如果没有profile
if(now_profile.match(/\n/ig).length == 1){ // 如果没有profile if(/^2171$/ig.test(par.customer)){
// 看看有没有 outline 层或者rout层
var outlines = all_layer.filter(function(layer){return /^rout$/.test(layer)})
if(all_layer.indexOf("outline") >= 0){outlines.unshift("outline")}
if(outlines.length){
outlines.forEach(function(layer){
if(!hasProfle({job:job, step:tmp_step})) {
GEN.selClearFeature()
GEN.workLayer({name:layer,display_number:2,clear_before:'yes'})
GEN.selAllFeat()
if(GEN.getSelectCount() > 0) { GEN.COM("sel_create_profile,create_profile_with_holes=no") }
}
})
}
} else if (/^yucca$/ig.test(par.customer)) {
if(profileRule[0] == "outline" && /1352/ig.test(PAR.customer)) { if(profileRule[0] == "outline" && /1352/ig.test(PAR.customer)) {
GEN.workLayer({name:'outline',display_number:2,clear_before:'yes'}) GEN.workLayer({name:'outline',display_number:2,clear_before:'yes'})
GEN.selAllFeat() GEN.selAllFeat()
if(GEN.getSelectCount() > 0) { if(GEN.getSelectCount() > 0) {
if(GEN.GEN_TYPE == "genesis"){ if(GEN.GEN_TYPE == "genesis"){
GEN.selCreateProfile() GEN.selCreateProfile()
// GEN.COM("sel_create_profile,create_profile_with_holes=no")
} else { } else {
GEN.COM("profile_limits,layers=outline,type=lyrfilter,margin=0") GEN.COM("profile_limits,layers=outline,type=lyrfilter,margin=0")
} }
...@@ -420,6 +433,93 @@ try { ...@@ -420,6 +433,93 @@ try {
} else { } else {
createOutline({job:job, step:tmp_step, profileRule:profileRule}) createOutline({job:job, step:tmp_step, profileRule:profileRule})
} }
} else if (/^wistron$/ig.test(par.customer)) {
var contours = all_layer.filter(function(layer){return /contour/.test(layer)})
// 判读有没有outline层 全选outline层创建
if(all_layer.indexOf("outline") >= 0){
GEN.workLayer({name:"outline",display_number:2,clear_before:'yes'})
GEN.selAllFeat()
if(GEN.getSelectCount() > 0) { GEN.COM("sel_create_profile,create_profile_with_holes=no") }
} else if (contours.length) {
// 过滤上下方的框
profileRule.unshift("contour");
createOutline({job:job, step:tmp_step, profileRule:profileRule})
}
} else if (/^vivo$/ig.test(par.customer)) {
// 判断有没有line层
if(all_layer.indexOf("line") >= 0){
GEN.workLayer({name:"line",display_number:2,clear_before:'yes'})
GEN.selAllFeat()
if(GEN.getSelectCount() > 0) { GEN.COM("sel_create_profile,create_profile_with_holes=no") }
} else if(all_layer.indexOf("top") >= 0) {
GEN.selClearFeature()
GEN.workLayer({name:"top",display_number:2,clear_before:'yes'})
// 判断是否有外框
// 将top层根据形状创建一个 并将top层的线跟弧拷贝到辅助层tmp1
GEN.COM("profile_limits,layers=top,type=lyrfilter,margin=0")
GEN.selectByFilter({feat_types:"line\;arc\;surface"})
if(GEN.getSelectCount() > 0) {
GEN.selCopyOther({dest:'layer_name',target_layer:"tmp1",invert:'no',dx:0,dy:0,size:0})
// 根据形状画出线在辅助层 tmp2
GEN.COM("profile_to_rout,layer=tmp2,width=1")
// 看tmp1是否有跟tmp2碰到 没碰到就创建失败 有碰到的则递归选择线 然后创建
GEN.workLayer({name:"tmp1",display_number:2,clear_before:'yes'})
GEN.selRefFeat({layers:"tmp2",use:"filter",mode:"touch"})
if(GEN.getSelectCount() > 0 ){
(function(){
GEN.selMoveOther({target_layer:'tmp3',invert:'no',dx:0,dy:0,size:0})
GEN.selRefFeat({layers:"tmp3",use:"filter",mode:"touch"})
if(GEN.getSelectCount() > 0) {
arguments.callee()
}
})()
if(GEN.isLayerExists({job:job, layer:"tmp3"})){
GEN.workLayer({name:"tmp3",display_number:2,clear_before:'yes'})
GEN.selAllFeat()
GEN.COM("sel_create_profile,create_profile_with_holes=no")
}
}
}
if(GEN.isLayerExists({job:job, layer:"tmp1"})){GEN.deleteLayer({job:job, layer:["tmp1"]})}
if(GEN.isLayerExists({job:job, layer:"tmp2"})){GEN.deleteLayer({job:job, layer:["tmp2"]})}
if(GEN.isLayerExists({job:job, layer:"tmp3"})){GEN.deleteLayer({job:job, layer:["tmp3"]})}
}
} else if (/^1352$/ig.test(par.customer)) {
if(all_layer.indexOf("outline") >= 0) {
GEN.workLayer({name:'outline',display_number:2,clear_before:'yes'})
GEN.selAllFeat()
if(GEN.getSelectCount() > 0) {
if(GEN.GEN_TYPE == "genesis"){
GEN.selCreateProfile()
} else {
GEN.COM("sel_create_profile,create_profile_with_holes=no")
}
}
}
if(!hasProfle({job:job, step:tmp_step})){
createOutline({job:job, step:tmp_step, profileRule:profileRule})
}
}
// if(profileRule[0] == "outline" && /1352/ig.test(PAR.customer)) {
// GEN.workLayer({name:'outline',display_number:2,clear_before:'yes'})
// GEN.selAllFeat()
// if(GEN.getSelectCount() > 0) {
// if(GEN.GEN_TYPE == "genesis"){
// GEN.selCreateProfile()
// // GEN.COM("sel_create_profile,create_profile_with_holes=no")
// } else {
// GEN.COM("profile_limits,layers=outline,type=lyrfilter,margin=0")
// }
// }
// var hasProfile = GEN.getProfile({job:job, step:tmp_step})
// GEN.closeStep()
// if(hasProfile.match(/\n/ig).length == 1){
// createOutline({job:job, step:tmp_step, profileRule:profileRule})
// }
// } else {
// createOutline({job:job, step:tmp_step, profileRule:profileRule})
// }
var hasProfile = GEN.getProfile({job:job, step:tmp_step}) var hasProfile = GEN.getProfile({job:job, step:tmp_step})
if(hasProfile.match(/\n/ig).length == 1){ if(hasProfile.match(/\n/ig).length == 1){
script_info({ msg: "Failed to create profile" ,result_severity:"warn"}) script_info({ msg: "Failed to create profile" ,result_severity:"warn"})
...@@ -435,7 +535,8 @@ try { ...@@ -435,7 +535,8 @@ try {
throw "创建profile失败,请手动创建好profile后仅执行分析步骤" throw "创建profile失败,请手动创建好profile后仅执行分析步骤"
} }
} }
}
script_info({ msg: "Data format is done" ,result_severity:"warn"}) script_info({ msg: "Data format is done" ,result_severity:"warn"})
db.query("",function(q){ db.query("",function(q){
...@@ -489,7 +590,8 @@ catch (e) { ...@@ -489,7 +590,8 @@ catch (e) {
table: "pdm_job_jobattr", table: "pdm_job_jobattr",
where:{job_id:JobId, attr_name:"cam_workflow_info"}, where:{job_id:JobId, attr_name:"cam_workflow_info"},
}) })
IKM.save_job_info({jobid:JobId, jobinfohash:{cam_workflow_info:"err"}}) IKM.save_job_info({jobid:JobId, jobinfohash:{cam_workflow_info:"err"}});
global._STATUS = "err";
checkIn() checkIn()
// 发送邮件 // 发送邮件
// sendEmail({ // sendEmail({
...@@ -844,6 +946,7 @@ function createOutline(props){ ...@@ -844,6 +946,7 @@ function createOutline(props){
}) })
return flag return flag
}) })
// fs.writeFile("/home/toplinker/samba/scott_test/tmp", _.toString(outlines))
var drill_layer = Object.keys(matrix).filter(function(v){return matrix[v].layer_type=="drill" && matrix[v].context == "board"}) var drill_layer = Object.keys(matrix).filter(function(v){return matrix[v].layer_type=="drill" && matrix[v].context == "board"})
var tmp = "drill_all"; var tmp = "drill_all";
if(GEN.isLayerExists({job:job, layer:tmp})) { GEN.deleteLayer({job:job, layer:[tmp]})} if(GEN.isLayerExists({job:job, layer:tmp})) { GEN.deleteLayer({job:job, layer:[tmp]})}
...@@ -947,16 +1050,15 @@ function createOutline(props){ ...@@ -947,16 +1050,15 @@ function createOutline(props){
GEN.renameLayer({job:job, layer:l,new_name:'outline'}) GEN.renameLayer({job:job, layer:l,new_name:'outline'})
GEN.deleteLayer({job:job, layer:l}) GEN.deleteLayer({job:job, layer:l})
if(GEN.isLayerExists({job:job, layer:bk2})){ GEN.deleteLayer({job:job, layer:bk2}) } if(GEN.isLayerExists({job:job, layer:bk2})){ GEN.deleteLayer({job:job, layer:bk2}) }
if(GEN.isLayerExists({job:job, layer:tmp})){ GEN.deleteLayer({job:job, layer:tmp}) }
return true return true
} }
GEN.deleteLayer({job:job, layer:l}) GEN.deleteLayer({job:job, layer:l})
if(GEN.isLayerExists({job:job, layer:bk2})){ GEN.deleteLayer({job:job, layer:bk2}) } if(GEN.isLayerExists({job:job, layer:bk2})){ GEN.deleteLayer({job:job, layer:bk2}) }
if(GEN.isLayerExists({job:job, layer:tmp})){ GEN.deleteLayer({job:job, layer:tmp}) }
GEN.deleteLayer({job:job, layer:[tmp_layer]}) GEN.deleteLayer({job:job, layer:[tmp_layer]})
GEN.deleteLayer({job:job, layer:[tmp_layer]}) GEN.deleteLayer({job:job, layer:[tmp_layer]})
return false return false
} }
if(GEN.isLayerExists({job:job, layer:tmp})){ GEN.deleteLayer({job:job, layer:[tmp]}) }
} }
...@@ -1007,3 +1109,8 @@ function sendEmail(msg) { ...@@ -1007,3 +1109,8 @@ function sendEmail(msg) {
} }
} }
} }
function hasProfle(props) {
var now_profile = GEN.getProfile({job:props.job, step:props.step})
return now_profile.match(/\n/ig).length != 1
}
\ No newline at end of file
...@@ -325,7 +325,6 @@ try { ...@@ -325,7 +325,6 @@ try {
GEN.COM("input_manual") GEN.COM("input_manual")
}) })
} }
importOk = true importOk = true
} }
if(!importOk){ throw "import error"} if(!importOk){ throw "import error"}
...@@ -557,7 +556,6 @@ function reNameStep(job) { ...@@ -557,7 +556,6 @@ function reNameStep(job) {
}) })
} }
function script_info(props){ // result_severity progress function script_info(props){ // result_severity progress
if (mode === "aimdfm") { if (mode === "aimdfm") {
$.QDfm.updateRow({ $.QDfm.updateRow({
...@@ -584,6 +582,7 @@ function decompression(path, zips) { ...@@ -584,6 +582,7 @@ function decompression(path, zips) {
item.path = item.dir + "/" + mvname item.path = item.dir + "/" + mvname
} }
var dir_name = item.path.replace(/\.(zip|7z|rar)$/, ""); var dir_name = item.path.replace(/\.(zip|7z|rar)$/, "");
autoUn(item.path, dir_name); autoUn(item.path, dir_name);
return true return true
} }
...@@ -605,8 +604,6 @@ function changePath(path) { ...@@ -605,8 +604,6 @@ function changePath(path) {
} }
function autoUn(path, dirname) { function autoUn(path, dirname) {
console.log("=====path: " + path);
console.log("=====dirname: " + dirname);
if(/\.rar$/.test(path)){ if(/\.rar$/.test(path)){
fs.mkdir(dirname) fs.mkdir(dirname)
process.exec('unrar', ['x' , path, dirname, "-o+"]) process.exec('unrar', ['x' , path, dirname, "-o+"])
......
...@@ -188,10 +188,10 @@ ...@@ -188,10 +188,10 @@
"text_line_width": 0.0024 "text_line_width": 0.0024
}, },
"Excellon2_4": { "Excellon2_4": {
"nf1": 2, "nf1": 3,
"nf2": 3, "nf2": 3,
"units": "inch", "units": "mm",
"zeroes": "trailing", "zeroes": "leading",
"decimal": "no", "decimal": "no",
"nf_comp": 0, "nf_comp": 0,
"break_sr": "yes", "break_sr": "yes",
...@@ -201,7 +201,7 @@ ...@@ -201,7 +201,7 @@
"drill_only": "no", "drill_only": "no",
"multiplier": 1, "multiplier": 1,
"resolution": 3, "resolution": 3,
"tool_units": "inch", "tool_units": "mm",
"coordinates": "absolute", "coordinates": "absolute",
"merge_by_rule": "no", "merge_by_rule": "no",
"signed_coords": "no", "signed_coords": "no",
...@@ -876,7 +876,7 @@ ...@@ -876,7 +876,7 @@
{ {
"valid": function(props){ "valid": function(props){
var file = props.file; var file = props.file;
return /\.gdo$|\.pho$/ig.test(file.name) return /\.gdo$|\.pho$|^line$|^ftdrill/ig.test(file.name)
}, },
"type": "Gerber274x", "type": "Gerber274x",
"format": "Gerber274x_4" "format": "Gerber274x_4"
...@@ -905,8 +905,8 @@ ...@@ -905,8 +905,8 @@
{"orig_name" : ["osp-bottom\\.pho","solderpastebottom","past_botm"], "tl_name" : "past_botm" }, {"orig_name" : ["osp-bottom\\.pho","solderpastebottom","past_botm"], "tl_name" : "past_botm" },
{"orig_name" : ["pleg\\.art","^ss_top","silk_top"], "tl_name" : "silk_top" }, {"orig_name" : ["pleg\\.art","^ss_top","silk_top"], "tl_name" : "silk_top" },
{"orig_name" : ["sleg\\.art","^ss_bot","silk_bot"], "tl_name" : "silk_bot" }, {"orig_name" : ["sleg\\.art","^ss_bot","silk_bot"], "tl_name" : "silk_bot" },
{"orig_name" : ["soldermask-top","top-solder-mask\\.pho","soldermasktop","sm_top"], "tl_name" : "sm_top" }, {"orig_name" : ["soldermask1|soldermask-top","top-solder-mask\\.pho","soldermasktop","sm_top"], "tl_name" : "sm_top" },
{"orig_name" : ["soldermask-bottom","bottom-solder-mask\\.pho","soldermaskbottom","sm_bot"], "tl_name" : "sm_botm" }, {"orig_name" : ["soldermask2|soldermask-bottom","bottom-solder-mask\\.pho","soldermaskbottom","sm_bot"], "tl_name" : "sm_botm" },
{"orig_name" : ["top\\.pho","^top$","layertop"], "tl_name" : "top" }, {"orig_name" : ["top\\.pho","^top$","layertop"], "tl_name" : "top" },
{"orig_name" : ["^lay(\\d+)","layer(\\d+)\\.gdo","layer_(\\d+)"], "tl_name" : "l_($1)"}, {"orig_name" : ["^lay(\\d+)","layer(\\d+)\\.gdo","layer_(\\d+)"], "tl_name" : "l_($1)"},
{"orig_name" : ["^bottom\\.pho$","^bottom$","layerbottom"], "tl_name" : "bottom" }, {"orig_name" : ["^bottom\\.pho$","^bottom$","layerbottom"], "tl_name" : "bottom" },
...@@ -929,7 +929,7 @@ ...@@ -929,7 +929,7 @@
{orig_rule:["thruholenonplated"],drill_type:"non_plated",shape:"hole"}, {orig_rule:["thruholenonplated"],drill_type:"non_plated",shape:"hole"},
{orig_rule:["thruholeplated"],drill_type:"plated",shape:"hole"}, {orig_rule:["thruholeplated"],drill_type:"plated",shape:"hole"},
], ],
profile:["enig_bot","past_top"], profile:["top","enig_bot","past_top"],
laser : { laser : {
tl_name: "drill($1)-($2)", tl_name: "drill($1)-($2)",
regs: ["(\\d+)-(\\d+)plated\\.ncd$","(\\d+)-(\\d+)\\.drl$"] regs: ["(\\d+)-(\\d+)plated\\.ncd$","(\\d+)-(\\d+)\\.drl$"]
......
料号名称
0000/222 spt smt top isl2 ... isl7 bottom smb spb rout d_top_isl2 ... d_isl7_bottom drill bot_testpoint bot_stiffener top_osp bot_osp outline top_enig bot_enig top_assem bot_assem
3333333 spt smt top isl2 ... isl7 bottom smb spb rout d_top_isl2 ... d_isl7_bottom drill ssb sst top_testpoint bot_testpoint bot_assy_mate top_assy_mate
1 spt smt top isl2 ... isl7 bottom smb spb rout d_top_isl2 ... d_isl7_bottom drill top_assem bot_assem top_testpoint bot_testpoint
top_osp bot_osp top_enig bot_enig fab_page2 bot_assy_mate top_assy_mate tmp_top_shorts tmp_bot_shorts ssb sst
i3 bottom.art top.art fab.art lay2.art ... lay9.art multipack.art
outline.art pleg.art ppst.art psm.art sleg.art spst.art ssm.art k55387-002-1-10.drl k55387-002-1-2-laser.drl ... k55387-002-1-10.rou
i6 01_topccp_ms... 02ccp_ms... ... 06_botccp_ms... as_topccp_ms... dimensionsccp_ms... outlineccp_ms... pm_topccp_ms... sm_botccp_ms... sm_topccp_ms... ss_botccp_ms... ss_topccp_ms... via_plugccp_ms... ...1-2-laser.drl ...1-6.drl
vivo:
topenig
vpn: 5sMm2U71
\ No newline at end of file
...@@ -32,3 +32,20 @@ ...@@ -32,3 +32,20 @@
var GUI = require('topsin.gengui').newGui(); var GUI = require('topsin.gengui').newGui();
var logger = require('topsin.logger'); var logger = require('topsin.logger');
``` ```
A L13 17号点未知
B L1 23点如何判断 L6 28号点判断 L15 26号点判断
D L1 41 42点判断 L2
43 点判断
D L3 78点78由来
F L1 61点判断 79
77 76点判断
L5 64 72点判断
H L1 71判断
A线圈标点最后到20 21 B线圈接着到22 23 最大到28
C线圈直接从31开始 到37
D线圈从41 最大是78
E线圈51 98
/* /*
NAME: NAME:
DESCRIPTION: 原稿拼底片; DESCRIPTION: 锣带输出;
PARAMETER: PARAMETER:
[ [
{ {
name : 'out_line', name : 'Outpath',
title : '外形层', title : '导出路径',
type : 'LineEdit', type : 'LineEdit',
property : {tool_tip : '定原稿拼片的step,如未设定,默认为org'}, property : {tool_tip : '导出路径'},
}, },
{ {
name : 'step', name : 'step',
title : 'Org step', title : '工作step',
type : 'LineEdit', type : 'LineEdit',
property : {tool_tip : '定原稿拼片的step,如未设定,默认为org'}, property : {tool_tip : '工作step'},
},
{
name : 'job_suffix',
title : '料号后缀',
type : 'LineEdit',
property : {tool_tip : '定原稿拼片的料号后缀,如未设定,默认为-org'},
},
{
name : 'path',
title : '输出路径',
type : 'LineEdit',
property : {tool_tip : '定原稿拼片的路径'},
}, },
{ {
name : 'auto_save', name : 'auto_save',
...@@ -48,7 +36,7 @@ PARAMETER: ...@@ -48,7 +36,7 @@ PARAMETER:
HELP: HELP:
<html><body bgcolor="#DDECFE"> <html><body bgcolor="#DDECFE">
<font size="3" color="#003DB2"><p>功能简介</p></font> <font size="3" color="#003DB2"><p>功能简介</p></font>
<p> 原稿拼底片 </p> <p> 锣带输出 </p>
<br> <br>
<font size="3" color="#003DB2"><p>参数配置</p></font> <font size="3" color="#003DB2"><p>参数配置</p></font>
<p> step信息 </p> <p> step信息 </p>
...@@ -91,333 +79,50 @@ var Status = 'ok'; ...@@ -91,333 +79,50 @@ var Status = 'ok';
var resultData = []; var resultData = [];
var par = PAR; var par = PAR;
var default_par = { var default_par = {
out_line:"out", Outpath:"C:/Users/Administrator/Desktop/jobs/demo",
step:"step",
job_suffix:"-org",
path:"C:/Users/Administrator/Desktop/jobs/demo",
auto_save: "No", auto_save: "No",
step:"step",
units:"mm" units:"mm"
} }
for(var key in default_par){ if (!par.hasOwnProperty(key) || par[key] == ""){ par[key] = default_par[key] }} for(var key in default_par){ if (!par.hasOwnProperty(key) || par[key] == ""){ par[key] = default_par[key] }}
var job = Job; var job = Job;
var Step; var Step;
var film_size = ['20x24','22x26','24x28']; var rou_layer = [];
var film_tol_number = 0; // 总的底片数量
var sold_mask_layer = []; // 阻焊层
var cust_code = "",serial="";
if(/^(?:[a-z0-9]{2})([a-z0-9]{2})(?:[a-z0-9])(?:[a-z0-9])(?:[a-z0-9])([a-z0-9]{3})(?:(?:[a-z0-9])(?:[a-z0-9])(?:[a-z0-9])|sys)(?:\-s)?/i.test(job)){
cust_code = RegExp.$1;
serial = RegExp.$2;
}
par.film_name = cust_code + serial + '-org';
try { try {
if(_.isEmpty(job)){throw "参数job不存在"} else { job = job.toLowerCase() } if(_.isEmpty(job)){throw "参数job不存在"} else { job = job.toLowerCase() }
if(!GEN.isJobExists({job:job})){throw "料号"+job+"不存在"} if(!GEN.isJobExists({job:job})){throw "料号"+job+"不存在"}
var gotoFlag = false; // 选择工作step
Job = job + par.job_suffix; var workstep = getWorkStep()
// 检查拼片料号是否存在 if(workstep.length == 0){throw "未找到工作step"}
var films=[],tmp_matrix={};
if (GEN.isJobExists({job:Job}) ){
var matrix = GEN.getMatrix({job:Job});
// my $customer_code = $IKM->select_value(-sql =>"select c.name from job as j left join public_customer as c on j.customer_id = c.id where j.id = $JOB_ID");
Object.keys(matrix).forEach(function(layer){
var tmp_reg = new RegExp(par.film_name)
if( tmp_reg.test(layer) ){
films.push(layer);
tmp_matrix[layer] = matrix[layer];
}
})
if( films.length ){
if( GUI.confirm("料号"+Job+"在Genesis中已经存在,且已存在原稿拼片层,是否直接输出?",["yes", "no"], "question") == 'yes' ){
if( films.length > 1){
films = GUI.selectLayer({title:'请选择输出的原稿拼片层',
layermatrix:tmp_matrix,
layertype: "films", // default type of layertypelist
layertypelist: [
{name: "films", display_name: "films", filter: function(x) {
return films.indexOf(x["name"]) >= 0 ; }},
],
selectmode : 'multiple'}); // single
if(films.length == 0){throw "canel"}
}
gotoFlag = true;
}
}else{
IKM.msg("料号"+Job+"在Genesis中已经存在, 请检查!");
return 'Cancel';
}
}else{
GEN.copyJob({source_job:job,dest_job:Job,dest_database:GEN.getJobDbName({job:Job})});
}
if(!gotoFlag){
var stepList = GEN.getStepList({job:job})
stepList = stepList.filter(function(step){
var reg = new RegExp(par.step,"ig")
return reg.test(step)
})
Step = stepList[0]
if ( !GEN.isStepExists({job:Job,step:Step}) ){
IKM.msg(Step + "不存在,无法拼原稿!");
throw 'Cancel';
}
// 获取sold_mask_layer
sold_mask_layer = getLayer({layer_type:"solder_mask", context: "board"})
var matrix = GEN.getMatrix({job:Job});
var _default=[],films=[],tmp_matrix={};
for (var layer in matrix) {
if ( GEN.isLayerEmpty( {job:Job,step:Step,layer:layer}) ){
delete matrix[layer];
continue;
}
var tmp_reg = new RegExp(par.film_name)
if( tmp_reg.test(layer) ){
films.push(layer);
tmp_matrix[layer] = matrix[layer];
delete matrix[layer];
continue;
}
if( matrix[layer].context == 'board' && matrix[layer].layer_type != 'drill' ){
_default.push(layer)
}
else{
if(layer == "map" || /^m[12]\-/.test(layer)){
_default.push(layer);
}
}
}
//
if( films.length ){
if( GUI.confirm("已存在原稿拼片层,是否直接输出?" ["yes", "no"], "question") == 'yes' ){
if( films.length > 1){
films = GUI.selectLayer({title:'请选择输出的原稿拼片层',
layermatrix:tmp_matrix,
layertype: "films", // default type of layertypelist
layertypelist: [
{name: "films", display_name: "films", filter: function(x) {
return films.indexOf(x["name"]) >= 0 ; }},
],
selectmode : 'multiple'}); // single
if(films.length == 0){throw "canel"}
}
gotoFlag = true;
}
}
}
if(!gotoFlag){ workstep.forEach(function(step){
var tmplayers = GUI.selectLayer({ Step = step;
title:'请选择需拼片原稿层', GEN.openStep({job:Job,name:step});
layermatrix:matrix,
layertype:"_default",
layertypelist: [
{
name: "_default",
display_name: "_default",
filter: function (x) {
return _default.indexOf(x.name) >=0
}
},
{
name: "all",
display_name: "all",
filter: function (x) {
return true
}
}
],
selectmode:'multiple'});
if(tmplayers.length == 0){throw "cancel"}
tmplayers = tmplayers.map(function(v){return v.name})
// 创建拼片的辅助层
GEN.openStep({job:Job,name:Step});
GEN.clearLayers(); GEN.clearLayers();
GEN.affectedLayer( {mode:'all',affected:'no'} ); 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.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.units( {type:'mm'} );
GEN.zoomHome(); GEN.zoomHome();
if(!GEN.isLayerExists({job:Job,layer:par.out_line})){ var matrix = GEN.getMatrix({job:Job});
IKM.msg(par.out_line + "层不存在!!"); Object.keys(matrix).forEach(function(layer){
throw 'Cancel'; if(matrix[layer].context && matrix[layer].context == 'board' ){
} if(matrix[layer].layer_type == 'rout'){
if(GEN.isLayerEmpty({job:Job,step:Step,layer:par.out_line})){ rou_layer.push(layer)
IKM.msg(par.out_line + "层为空无法创建profice!!");
throw 'Cancel';
}
// 删除板外物 除map层外 2020-07-14 Super
GEN.affectedLayer({affected:'yes',layer:par.out_line,clear_before:'yes'});
GEN.COM('sel_reverse');
if ( GEN.getSelectCount() > 1 ){
GEN.COM('sel_create_profile');
GEN.affectedLayer( {mode:'all',affected:'no'} );
}else{
GEN.COM('sel_reverse');
GEN.affectedLayer( {mode:'all',affected:'no'} );
IKM.msg(par.out_line + "层外形数量太少无法创建profice!!");
throw 'Cancel';
}
tmplayers.forEach(function(layer){
if(!/^map$/.test(layer)){
GEN.affectedLayer({affected:'yes',layer:layer,clear_before:'no'});
}
})
GEN.clipArea({layers_mode:'affected_layers',area:'profile',inout:'outside',margin:0,contour_cut:'yes'});
// 复制外形
GEN.workLayer({name:par.out_line,display_number:1,clear_before:'yes'});
tmplayers.forEach(function(layer){
if(!/^map$/.test(layer)){
GEN.affectedLayer({affected:'yes',layer:layer,clear_before:'no'});
}
})
GEN.selCopyOther({dest:'affected_layers',invert:'no'});
GEN.clearLayers();
GEN.affectedLayer( {mode:'all',affected:'no'} );
// 创建阻焊负片层
var sold_mask_negative = [];
if(sold_mask_layer.length > 0){
sold_mask_layer.forEach(function(layer){
var tmp_layer = layer+'+1';
sold_mask_negative.push(tmp_layer)
var layer_limits = GEN.getLayerLimits({job:Job,step:Step,layer:layer,units:'inch'});
GEN.createLayer({job:Job,layer:tmp_layer,context:'misc',type:'document',delete_exists:'yes'});
GEN.affectedLayer({affected:'yes',layer:tmp_layer,clear_before:'yes'});
GEN.addRectangle({x1:Number(layer_limits.xmin)-0.1,y1:Number(layer_limits.ymin)-0.1,x2:Number(layer_limits.xmax)+0.1,y2:Number(layer_limits.ymax)+0.1});
GEN.affectedLayer({affected:'yes',layer:layer,clear_before:'yes'});
GEN.selCopyOther({target_layer:tmp_layer,invert:'yes'});
GEN.selContourize();
GEN.affectedLayer({mode:'all',affected:'no'});
})
}
// 总的底片数量
film_tol_number = tmplayers.length*2 + sold_mask_layer.length;
// 创建辅助层,返回实际需拼片的层
var tmp_layers = tmplayers;
tmp_layers = tmp_layers.concat(sold_mask_negative)
tmplayers = tmplayers.concat(tmp_layers);
// my @tmp_layers2 = @tmplayers;
create_tmp_layer({step:Step,layer:tmplayers,matrix:matrix});
var film_scheme;
var index = 1;
film_size.forEach(function(filmsize){
var info = get_repeat_info({step:Step,layer:tmplayers,film_size:filmsize});
film_scheme[index].info = info;
film_scheme[index].film_count = Object.keys(info).length;
film_scheme[index].film_size = filmsize;
index++ ;
})
IKM.msg(2)
// 选出最优方案
var best_scheme_index;
Object.keys(film_scheme).sort().forEach(function(index){
if(best_scheme_index){
if(film_scheme[index].film_count < film_scheme[best_scheme_index].film_count){
best_scheme_index = index;
} }
}else{
best_scheme_index = index;
} }
}) })
IKM.msg(3) if(rou_layer.length) {
film_repeat({step:Step,layer:tmplayers,info:film_scheme[best_scheme_index].info,film_size:film_scheme[best_scheme_index].film_size}); var info = confirm_gui({layers:rou_layer});
//画profile output_rou({job:Job,step:step,info:info});
var tmp_fs = film_scheme[best_scheme_index].film_size.split("x")
var film_width=tmp_fs[0],film_height = tmp_fs[1];
GEN.COM( 'profile_rect',{x1:0,y1:0,x2:film_width-0.005,y2:film_height-0.005});
//更改文字序列号
var change_layers = Object.keys(film_scheme[best_scheme_index].info).sort(function(a,b){
return film_scheme[best_scheme_index].info[a].num - film_scheme[best_scheme_index].info[b].num
})
var number = 1;
change_layers.forEach(function(layer){
GEN.affectedLayer({affected:'yes',mode:'single',layer:layer,clear_before:'yes'});
// GEN.selectByFilter(feat_types:'text',polarity:'positive',profile:'all');
var tmp_data = GEN.getFeature({job:Job,step:Step,layer:layer,surface:0,options:'feat_index'});
// var tmp_data = GEN.getFeatures(job:Job,step:Step,layer:layer,options:'select');
var txt_data = tmp_data.filter(function(v){return v.type=="text"})
// $GUI->debug(-text:dump(@txt_data,'---',layer,$Step,$Job));
txt_data.forEach(function(data){
GEN.COM('sel_layer_feat',{operation:'select',layer:layer,index:data.index});
var txt = data.text.split("/")
var new_text = number+'/'+txt[1];
GEN.COM( 'sel_change_txt',{
text:new_text,
x_size:data.x_size,
y_size:data.y_size,
w_factor:data.w_factor,
polarity:'no_change',
mirror:'no',
fontname:data.fontname
});
number++;
})
})
// 请检查拼片信息 input_layers({job:Job,step:step,info:info});
var n = 1;
var lastflag = true
Object.keys(film_scheme[best_scheme_index].info).sort(function(a,b){
return film_scheme[best_scheme_index].info[a].num - film_scheme[best_scheme_index].info[b].num
}).forEach(function(film){
if(lastflag){
if( n == 1 ){
GEN.workLayer({name:film,display_number:1,clear_before:'yes'});
}
else{
GEN.displayLayer({name:film,number:n});
}
n++;
} }
if (n > 4){lastflag = false};
}) })
GEN.PAUSE('Please Check Layer');
}
//
if(films.length == 0){
films = Object.keys(film_scheme[best_scheme_index].info).sort(function(a,b){
return film_scheme[best_scheme_index].info[a].num - film_scheme[best_scheme_index].info[b].num
})
}
//my $film_size = $film_scheme->{$best_scheme_index}{film_size};
//删除多余step和层别
var steps = GEN.getStepList({job:Job});
steps.forEach(function(step){
if(step != Step){
GEN.matrixDeleteStep({job:Job,step:step});
}
})
var matrix = GEN.getMatrix({job:Job});
Object.keys(matrix).forEach(function(layer){
var tmp_reg = new RegExp("^"+par.film_name)
if(!tmp_reg.test(layer)){
_deleteLayer({layer:[layer]});
}
})
GEN.checkInout({job:Job,mode:'out'});
// $GUI->debug(-text=>dump($PAR->{path}));
GEN.saveJob({job:Job});
GEN.COM('export_job',{job:Job,path:par.path,mode:'tar_gzip',submode:'full',overwrite:'yes'});
// 保存 // 保存
if(/yes/ig.test(par.auto_save)){GEN.checkInout({job:job,mode:"out"}); GEN.saveJob({ job: job });GEN.checkInout({job:job,mode:"in"});GEN.closeJob({job:job});} else {GEN.checkInout({job:job,mode:"in"})} if(/yes/ig.test(par.auto_save)){GEN.checkInout({job:job,mode:"out"}); GEN.saveJob({ job: job });GEN.checkInout({job:job,mode:"in"});GEN.closeJob({job:job});} else {GEN.checkInout({job:job,mode:"in"})}
...@@ -518,360 +223,207 @@ function NewGUI (gui) { ...@@ -518,360 +223,207 @@ function NewGUI (gui) {
} }
} }
function getLayer(props){ function getWorkStep(props){
if(!props){return} var steplists = GEN.getStepList({job:job});
if(!props.context){props.context = "board"} if(steplists.length == 0){return "该料号没有step"}
var matrix = GEN.getMatrix({job:job}) var steps_tmp = steplists.filter(function(name){
return Object.keys(matrix).reduce(function(a,b){ var reg = new RegExp(par.step, "ig")
var info = matrix[b]; return reg.test(name)
var ret = true;
for (var key in props) { if(!Array.isArray(props[key])){props[key] = [props[key]]}
if(info[key] && props[key].indexOf(info[key]) < 0){ ret = false } }
if(ret){ a.push(props.res == "info"? info : b) } return a
},[])
}
function _deleteLayer(layers){
layers = Array.isArray(layers.layer) ? layers.layer : [layers.layer];
layers.forEach(function(layer){
if(GEN.isLayerExists({job:Job,layer:layer})){
GEN.deleteLayer({job:Job,layer:[layer]})
}
})
}
function create_tmp_layer(par){
var matrix = par.matrix;
// 先清除原先存在的辅助层
Object.keys(matrix).forEach(function(layer){
if(/_$|_tl_angle$/ig.test(layer)){
GEN.deleteLayer({job:Job,layer:[layer],step:par.step})
}
})
par.layer.forEach(function(layer){
var tmp_layer = layer+'_';
var tmp_layer_angle = layer+'_tl_angle';
GEN.copyLayer({source_job:Job,source_step:par.step,source_layer:layer,dest_layer:tmp_layer,invert:'no',mode:'replace'});
// 打散层上字串
GEN.affectedLayer({affected:'yes',layer:[tmp_layer],clear_before:'yes'});
GEN.selectByFilter({feat_types:'text',profile:'all'});
if ( GEN.getSelectCount() > 0 ){GEN.COM("sel_break")};
if(matrix[layer] && matrix[layer].tl_type == 'inner' && matrix[layer].polarity != 'negative' ){
var layer_limits = GEN.getLayerLimits({job:Job,step:par.step,layer:layer,units:'inch'});
var tmp = 'pos_to_neg_tl';
GEN.createLayer({job:Job,layer:tmp,context:'board',type:'document',delete_exists:'yes'});
GEN.affectedLayer({affected:'yes',layer:[tmp],clear_before:'yes'});
GEN.addRectangle({x1:Number(layer_limits.xmin)-0.1,y1:Number(layer_limits.ymin)-0.1,x2:Number(layer_limits.xmax)+0.1,y2:Number(layer_limits.ymax)+0.1});
GEN.affectedLayer({affected:'yes',layer:[tmp_layer],clear_before:'yes'});
GEN.selCopyOther({target_layer:tmp,invert:'yes'});
GEN.copyLayer({source_job:Job,source_step:par.step,source_layer:tmp,dest_layer:tmp_layer,invert:'no',mode:'replace'});
GEN.deleteLayer({job:Job,layer:[tmp],step:par.step});
}
// $GUI->debug(dump(matrix[layer].tl_type));
GEN.copyLayer({source_job:Job,source_step:par.step,source_layer:tmp_layer,dest_layer:tmp_layer_angle,invert:'no',mode:'replace'});
//
GEN.affectedLayer({affected:'yes',layer:[tmp_layer],clear_before:'yes'});
var layer_limits = GEN.getLayerLimits({job:Job,step:par.step,layer:tmp_layer,units:'inch'});
GEN.selMove({dx:0-layer_limits.xmin+0.1,dy:0-layer_limits.ymin+0.1});
// 制作旋转辅助层
GEN.affectedLayer({affected:'yes',layer:[tmp_layer_angle],clear_before:'yes'});
GEN.selTransform({mode:'anchor',oper:'rotate',x_anchor:0,y_anchor:0,angle:90});
layer_limits = GEN.getLayerLimits({job:Job,step:par.step,layer:tmp_layer_angle,units:'inch'});
GEN.selMove({dx:0-layer_limits.xmin+0.1,dy:0-layer_limits.ymin+0.1});
// 添加文字标识
[tmp_layer,tmp_layer_angle].forEach(function(txt_data){
GEN.affectedLayer({affected:'yes',layer:txt_data,clear_before:'yes'});
var txt = '1/'+film_tol_number+' '+Job.toUpperCase()+' '+layer.toUpperCase();
var lay_limt = GEN.getLayerLimits({job:Job,step:par.step,layer:txt_data,units:'inch'});
Add_Text({x:lay_limt.xmin-0,y:lay_limt.ymin - 0.18,txt:txt,angle:0});
// GEN.createLayer(job:Job,layer:$txt_data.'+bak',context:'misc',type:'document',delete_exists:'yes');
// GEN.selCopyOther(target_layer:$txt_data.'+bak',invert:'no');
}) })
if(steplists.length == 0){return "根据脚本参数过滤出来的step不存在,请检查资料或者脚本参数配置!"}
var workstep = gui.selectMultiple({
title: "请先择工作step",
size:[200,100],
defaultsize:[200,100],
list: steplists.map(function(v){ var tmp = {}; tmp[v] = v ;return tmp}),
defaultvalue: steps_tmp,
columns: 1,
gen: GEN
}) })
if(workstep.length == 0 ) {return "没有先择step"}
return workstep
} }
function get_repeat_info(par){ // rou输出
// 判断不旋转 function output_rou(par) {
var info1 = {}; var info = par.info;
var film_size = par.film_size; // var PL = GEN.getProfileLimits({job:Job,step:Step,units:'mm'});
var tmp_film_size = film_size.split("x") var nc_set = 'zda';
var film_width = tmp_film_size[0],film_height = tmp_film_size[1]; var machine = 'sintai_excellon';
var film_org = PAR.film_name+'-'+film_size; var layers = [];
var film_name=film_org,film_num=0,film_status="old"; for (var key in info.layer_info) {
var first_area,last_area={},xstart={},ystart;//第一张底片的范围/上一张底片的范围 layers.push(info.layer_info[key])
par.layer.forEach(function(layer){
var tmp_layer = layer+'_';
film_status = last_area.xmin ? 'old' : 'new' ;
var layer_limits = GEN.getLayerLimits({job:Job,step:par.step,layer:tmp_layer,units:'inch'});
layer_limits.xsize = layer_limits.xsize - 0;
layer_limits.ysize = layer_limits.ysize - 0;
layer_limits.xmin = layer_limits.xmin - 0;
layer_limits.ymin = layer_limits.ymin - 0;
layer_limits.xmax = layer_limits.xmax - 0;
layer_limits.ymax = layer_limits.ymax - 0;
var tol_x = (layer_limits.xsize > layer_limits.ysize) ? 0.3 : 0.3;
var tol_y = (layer_limits.xsize > layer_limits.ysize) ? 0.3 : 0.3;
// 判断拼入后是否会超出范围
if( layer_limits.xsize > film_width && layer_limits.ysize > film_height ){
// xy都超出范围,一片一拼
film_status = 'new';
}
else if( layer_limits.xsize > film_width ){
film_status = 'new' ;//if ( ($last_area->{ymax}+ layer_limits.ysize) > $film_height );
}
else if( layer_limits.ysize > film_height ){
film_status = 'new' ;//if ( ($last_area->{xmax}+ layer_limits.xsize) > film_width );
}
else{
if ( (last_area.ymax+ layer_limits.ysize) > film_height && (last_area.xmax+ layer_limits.xsize) > film_width ){
film_status = 'new'
};
}
// 新底片的准备工作
if( film_status == 'new' ){
film_name = film_org+'-'+film_num;
if(!info1[film_name]){info1[film_name] = {}}
if(!info1[film_name].layers){info1[film_name].layers = []}
if(!info1[film_name][layer]){info1[film_name][layer] ={shift:{}}}
info1[film_name].layers.push(layer)
info1[film_name].num = film_num;
info1[film_name].type = 'no_angle';
info1[film_name][layer].shift.x = 0;
info1[film_name][layer].shift.y = 0;
xstart.status = 1;
xstart.shifty = info1[film_name][layer].shift.y;
first_area = {
xmin: layer_limits.xmin,
ymin: layer_limits.ymin,
xmax: layer_limits.xmax + tol_x,
ymax: layer_limits.ymax + tol_y,
xsize: layer_limits.xsize + tol_x,
ysize: layer_limits.ysize + tol_y
};
last_area = first_area;
film_num++;
}else{
// Y方向添加
if ( (last_area.xsize+ layer_limits.xsize+tol_x) > film_width ){
//print dump($last_area->{xsize},'--',layer_limits.xsize,'--',film_width),"\n";
//print dump(@{$info{$film_name}{layers}}),"\n";
//GEN.PAUSE('tttt++'.$layer);
if(!info1[film_name]){info1[film_name] = {}}
if(!info1[film_name].layers){info1[film_name].layers = []}
if(!info1[film_name][layer]){info1[film_name][layer] ={shift:{}}}
info1[film_name].layers.push(layer);
info1[film_name][layer].shift.x = 0;
info1[film_name][layer].shift.y = last_area.ymax-layer_limits.ymin;
xstart.status = 1;
xstart.shifty = info1[film_name][layer].shift.y;
//$ystart->{status} = 0;$xstart->{shiftx} = undef;
last_area = {
xmin: layer_limits.xmin,
ymin: layer_limits.ymin + info1[film_name][layer].shift.y,
xmax: layer_limits.xmax + tol_x,
ymax: info1[film_name][layer].shift.y + layer_limits.ymax + tol_y,
xsize: layer_limits.xsize + tol_x,
ysize: layer_limits.ysize + last_area.ysize + tol_y
};
}
// X方向添加
else{
if(!info1[film_name]){info1[film_name] = {}}
if(!info1[film_name].layers){info1[film_name].layers = []}
if(!info1[film_name][layer]){info1[film_name][layer] ={shift:{}}}
info1[film_name].layers.push(layer);
info1[film_name][layer].shift.x = last_area.xmax-layer_limits.xmin;
info1[film_name][layer].shift.y = xstart.status ? xstart.shifty : last_area.ymax-last_area.xmin;
//print dump($info{$film_name}{$layer}{shift}{x},'-----',$info{$film_name}{$layer}{shift}{y}),"\n";
//GEN.PAUSE('ttt++'.$layer);
xstart.status = 1;
xstart.shifty = info1[film_name][layer].shift.y;
var high = (layer_limits.ymax+info1[film_name][layer].shift.y-0+tol_y) > last_area.ymax ? layer_limits.ymax+info1[film_name][layer].shift.y-0+tol_y : last_area.ymax;
//$ystart->{status} = 1;$ystart->{shiftx} = undef;
last_area = {
xmin: layer_limits.xmin + info1[film_name][layer].shift.x,
ymin: layer_limits.ymin + info1[film_name][layer].shift.y,
xmax: layer_limits.xmax + info1[film_name][layer].shift.x + tol_x,
ymax: high,
xsize: layer_limits.xsize + last_area.xsize + tol_x,
ysize: layer_limits.ysize + tol_y
};
}
}
})
// 判断旋转90度
var info2 = {};
film_org = PAR.film_name+'-'+film_size;
film_name = film_org,film_num=0,film_status="old";
first_area={},last_area={},xstart={},ystart={};//第一张底片的范围/上一张底片的范围
par.layer.forEach(function(layer){
var tmp_layer = layer+'_tl_angle';
film_status = last_area.xmin ? 'old' : 'new' ;
var layer_limits = GEN.getLayerLimits({job:Job,step:par.step,layer:tmp_layer,units:'inch'});
layer_limits.xsize = layer_limits.xsize - 0;
layer_limits.ysize = layer_limits.ysize - 0;
layer_limits.xmin = layer_limits.xmin - 0;
layer_limits.ymin = layer_limits.ymin - 0;
layer_limits.xmax = layer_limits.xmax - 0;
layer_limits.ymax = layer_limits.ymax - 0;
var tol_x = (layer_limits.xsize > layer_limits.ysize) ? 0.3 : 0.3;
var tol_y = (layer_limits.xsize > layer_limits.ysize) ? 0.3 : 0.3;
//判断拼入后是否会超出范围
if( layer_limits.xsize > film_width && layer_limits.ysize > film_height ){
//xy都超出范围,一片一拼
film_status = 'new';
}
else if( layer_limits.xsize > film_width ){
film_status = 'new' ;//if ( ($last_area->{ymax}+ layer_limits.ysize) > $film_height );
}
else if( layer_limits.ysize > $film_height ){
film_status = 'new' ;//if ( ($last_area->{xmax}+ layer_limits.xsize) > film_width );
}
else{
if ( (last_area.ymax+ layer_limits.ysize) > film_height && (last_area.xmax+ layer_limits.xsize) > film_width ){
film_status = 'new'
};
}
//新底片的准备工作
if( film_status == 'new' ){
film_name = film_org+'-'+film_num;
if(!info2[film_name]){info2[film_name] = {}}
if(!info2[film_name].layers){info2[film_name].layers = []}
if(!info2[film_name][layer]){info2[film_name][layer] ={shift:{}}}
info2[film_name].layers.push(layer)
info2[film_name].num = film_num;
info2[film_name].type = 'angle';
info2[film_name][layer].shift.x = 0;
info2[film_name][layer].shift.y = 0;
xstart.status = 1;
xstart.shifty = info2[film_name][layer].shift.y;
first_area = {
xmin: layer_limits.xmin,
ymin: layer_limits.ymin,
xmax: layer_limits.xmax + tol_x,
ymax: layer_limits.ymax + tol_y,
xsize: layer_limits.xsize + tol_x,
ysize: layer_limits.ysize + tol_y
};
last_area = first_area;
film_num++;
}else{
//Y方向添加
if ( (last_area.xsize+ layer_limits.xsize+tol_x) > film_width ){
//print dump($last_area->{xsize},'--',layer_limits.xsize,'--',film_width),"\n";
//print dump(@{$info{$film_name}{layers}}),"\n";
//GEN.PAUSE('tttt++'.$layer);
if(!info2[film_name]){info2[film_name] = {}}
if(!info2[film_name].layers){info2[film_name].layers = []}
if(!info2[film_name][layer]){info2[film_name][layer] ={shift:{}}}
info2[film_name].layers.push(layer);
info2[film_name][layer].shift.x = 0;
info2[film_name][layer].shift.y = last_area.ymax-layer_limits.ymin;
xstart.status = 1;
xstart.shifty = info2[film_name][layer].shift.y;
//$ystart->{status} = 0;$xstart->{shiftx} = undef;
last_area = {
xmin: layer_limits.xmin,
ymin: layer_limits.ymin + info2[film_name][layer].shift.y,
xmax: layer_limits.xmax + tol_x,
ymax: info2[film_name][layer].shift.y + layer_limits.ymax + tol_y,
xsize: layer_limits.xsize + tol_x,
ysize: layer_limits.ysize + last_area.ysize + tol_y
};
} }
//#X方向添加 layers.forEach(function(layer){
else{ if(/^yes$/i.test(layer.output_flag)){
if(!info2[film_name]){info2[film_name] = {}} if(GEN.getNcsetsList({job:Job,step:Step,layer:layer.layer_name}).indexOf(nc_set) >= 0) {
if(!info2[film_name].layers){info2[film_name].layers = []} GEN.COM('ncrset_delete',{name:nc_set});
if(!info2[film_name][layer]){info2[film_name][layer] ={shift:{}}}
info2[film_name].layers.push(layer);
info2[film_name][layer].shift.x = last_area.xmax-layer_limits.xmin;
info2[film_name][layer].shift.y = xstart.status ? xstart.shifty : last_area.ymax-last_area.xmin;
//print dump($info{$film_name}{$layer}{shift}{x},'-----',$info{$film_name}{$layer}{shift}{y}),"\n";
//GEN.PAUSE('ttt++'.$layer);
xstart.status = 1;
xstart.shifty = info2[film_name][layer].shift.y;
var high = (layer_limits.ymax+info2[film_name][layer].shift.y-0+tol_y) > last_area.ymax ? layer_limits.ymax+info2[film_name][layer].shift.y-0+tol_y : last_area.ymax;
//$ystart->{status} = 1;$ystart->{shiftx} = undef;
last_area = {
xmin: layer_limits.xmin + info2[film_name][layer].shift.x,
ymin: layer_limits.ymin + info2[film_name][layer].shift.y,
xmax: layer_limits.xmax + info2[film_name][layer].shift.x + tol_x,
ymax: high,
xsize: layer_limits.xsize + last_area.xsize + tol_x,
ysize: layer_limits.ysize + tol_y
};
} }
GEN.COM('ncrset_cur',{job:Job,step:Step,layer:layer.layer_name,ncset:nc_set});
GEN.COM('ncr_set_machine',{machine:machine,thickness:0});
GEN.COM('ncr_register',{angle:0,mirror:layer.is_mirror,xoff:0,yoff:0,version:1,xorigin:0,yorigin:0,xscale:layer.scale_x,yscale:layer.scale_y,xscale_o:0,yscale_o:0});
GEN.COM('ncr_cre_rout');
GEN.COM('ncr_ncf_export',{dir:info.output_path,name:layer.layer_name});
GEN.COM('ncrset_delete',{name:nc_set});
} }
}) })
//
if( Object.keys(info2).length < Object.keys(info1).length){
return info2;
}
else{
return info1;
}
} }
function film_repeat(par){ // 用户配置参数
var film_size = par.film_size; function confirm_gui(par) {
var tmp_film_size = film_size.split("x") var rows={},n=0;
var film_width = tmp_film_size[0]; // var cam = IKM.get_jobinfo({jobname:Job,jobid:JobId,jobcategory:'work',jobinfo:'cam_serial_number',withspec:1});
var film_height = tmp_film_size[1]; var folder = 'rou';
var info = par.info; var path = PAR.Outpath+"/"+folder;
Object.keys(info).sort(function(a,b){return info[a].num - info[b].num}).forEach(function(film){ fs.mkdir(path)
if(info[film].layers){ par.layers.forEach(function(layer){
GEN.createLayer({job:Job,layer:film,conext:'misc',type:'document',delete_exists:'yes'});
GEN.affectedLayer({affected:'yes',layer:[film],clear_before:'yes'});
// my $all = scalar(@{$info{$film}{layers}});
// $GUI->debug(dump($film, $info{$film}{layers}));
var n = 1;
info[film].layers.forEach(function(layer){
var tmp_layer = info[film].type == 'no_angle' ? layer+'_' : layer+'_tl_angle';
GEN.affectedLayer({affected:'yes',layer:[tmp_layer],clear_before:'yes'});
GEN.selMove({dx:info[film][layer].shift.x,dy:info[film][layer].shift.y});
GEN.copyLayer({source_job:Job,source_step:par.step,source_layer:tmp_layer,dest_layer:film,invert:'no',mode:'append'});
GEN.selMove({dx:-info[film][layer].shift.x,dy:-info[film][layer].shift.y});
// GEN.deleteLayer(job:Job,layer:[$layer.'_',$layer.'_tl_angle'],step:par.step);
n++; n++;
rows[n] = {};
rows[n].sequence = n;
rows[n].layer_name = layer;
rows[n].scale_x = 1;
rows[n].scale_y = 1;
rows[n].output_flag = 'Yes';
rows[n].is_mirror = 'no';
}) })
rows.output_path = path;
GEN.affectedLayer({affected:'yes',layer:[film],clear_before:'yes'}); // var v_data = GUI.showForm({
// 移动居中 // title:"Rou输出参数确认单",
var layer_limits = GEN.getLayerLimits({job:Job,step:Step,layer:film,units:'inch'}); // defaultsize:[520,500],
layer_limits.xc = layer_limits.xsize/2-Math.abs(layer_limits.xmin); // items: [
layer_limits.yc = layer_limits.ysize/2-Math.abs(layer_limits.ymin); // {
GEN.selMove({dx:film_width/2-layer_limits.xc,dy:film_height/2-layer_limits.yc}); // type : 'title',
// // property:{
GEN.addRectangle({x1:0,y1:0,x2:film_width-0.005,y2:film_height-0.005,type:'line',symbol:'r5'}); // title:'输出料号和名称',
} // },
}) // n_columns:2,
// },
// {
// type : 'title',
// property:{
// title:'参数确认',
// },
// n_columns:8,
// },
// {
// name : 'layer_info',
// label :'参数确认',
// label_position : 'no',
// "class" : 'TL::Gtk2::TableFormPanel',
// expand : 1,
// property : {
// tl_columns :[
// {
// column_name:'layer_name',
// label:'层别名称',
// width:100,
// type:'label',
// },
// {
// column_name:'scale_x',
// label:'涨缩值X',
// width:80,
// type:'number',
// must_field:1,
// },
// {
// column_name:'scale_y',
// label:'涨缩值Y',
// width:80,
// type:'number',
// must_field:1,
// },
// {
// column_name:'output_flag',
// label:'是否输出',
// width:80,
// type:'radio',
// property:{
// tl_columns : 2,
// tl_list : [{'Yes' : '是'}, {'No':'否'}],
// },
// },
// {
// column_name:'is_mirror',
// label:'是否镜像',
// width:80,
// type:'radio',
// property:{
// tl_columns : 2,
// tl_list : [{'yes' : '是'}, {'no':'否'}],
// },
// }
// ],
// tl_rows:rows,
// },
// set_value_func : function(par){
// var data = par.value;
// Object.keys(data).forEach(function(row_name){
// Object.keys(data[row_name]).forEach(function(col_name){
// par.widget.set_value(row_name,col_name,data[row_name][col_name]);
// })
// })
// },
// get_value_func : function(par){return par.widget.get_all_value();},
// },
// {
// type : 'title',
// property:{
// title:'输出设置',
// },
// n_columns:1,
// },
// {
// name : 'username',
// label : '输出者:',
// type : 'string',
// value:GEN.getUserName(),
// width:100,
// must_field:1,
// },
// {
// name : 'output_path',
// label : '输出路径:',
// type : 'string',
// value:path,
// width:100,
// must_field:1,
// property : {
// editable:0,
// },
// buttons : [
// {
// name:'btn1',label:'选择路径',stock:'gtk-add',
// command:function(par){
// var folder = GUI.select_file({title:'选择路径',type:'select-folder',defaultdir:PAR.Outpath});
// if(!folder){return}
// p.formpanel.set_value('output_path', folder);
// }
// },
// ],
// },
// ]
// });
return rows;
} }
// =head // 文件导入设置
// 增加文字 Add_Text(x=>,y=>,txt=>,angle=>) function input_layers(par) {
// =cut var info = par.info;
function Add_Text(par){ var layers = [];
GEN.COM('add_text',{ for (var key in info.layer_info) {
attributes:'no', layers.push(info.layer_info[key])
type:'string', }
x:par.x, layers.forEach(function(lyr){
y:par.y, if(/yes/i.test(lyr.output_flag)){
text:par.txt, var name = info.output_path+'/'+lyr.layer_name;
x_size:0.15, var layer= lyr.layer_name.toLowerCase();
y_size:0.15, GEN.COM("input_manual_reset");
w_factor:1.6666666269, GEN.COM("input_manual_set,path="+name+",job="+par.job+",step="+par.step+
polarity:'positive', ",format=Excellon2,data_type=ascii,units=mm,coordinates=absolute,zeroes=none,nf1=3,nf2=3,decimal=no,separator=nl,tool_units=mm,layer="+layer
angle:par.angle, +",wheel=,wheel_template=,nf_comp=0,multiplier=1,text_line_width=0.0024,signed_coords=no,break_sr=yes,drill_only=no,merge_by_rule=no,threshold=200,resolution=3");
mirror:'no', GEN.COM("input_manual,script_path=");
fontname:'simple', GEN.COM("matrix_layer_context,job="+par.job+",matrix=matrix,layer="+layer+",context=misc");
ver:1 }
}) })
} }
\ No newline at end of file
=head =head
NAME: NAME:ZWZ_output_rou
DESCRIPTION: 钻孔输出 DESCRIPTION: 锣带输出
PARAMETER: PARAMETER:
[ [
{ {
name : 'step_filter', name : 'Outpath',
title : '工作step',
type : 'LineEdit', type : 'LineEdit',
property : {tool_tip : '过滤Step名称'}, title : 'path',
pack : {row:0,column:1},
property:{tool_tip:''},
}, },
{
name : 'out_dir',
title : '钻孔输出路径',
type : 'LineEdit',
property:{tool_tip:'例如: /output/drill'}
},
{
name : 'cool_spread',
title : '跳钻距离(um)',
type : 'LineEdit',
property:{tool_tip:'例如: 350'}
},
{
name : 'reread_layer',
type : 'RadioBox',
title : '回读钻孔程式',
property : {tool_tip:'未设定,则默认no',
size_policy:'Expanding,Fixed',item_list:[{name:'yes',text:'Yes'},{name:'no',text:'No'}]},
pack : {row:1,column:1},
},
{
name : 'is_select_lyr',
type : 'RadioBox',
title : '是否选择层别',
property : {tool_tip:'未设定,则默认no',
size_policy:'Expanding,Fixed',item_list:[{name:'yes',text:'Yes'},{name:'no',text:'No'}]},
pack : {row:1,column:1},
},
{
name : 'save_job',
title : '保存料号',
type : 'RadioBox',
property : {
size_policy:'Expanding,Fixed',
item_list:[
{name:'Yes',text:'Yes'},
{name:'No',text:'No'},
],
tool_tip:'脚本结束后自动保存料号,未设定,默认为No'
},
pack : {row:1,column:1},
}
] ]
VERSION_HISTORY: VERSION_HISTORY:
V1.00 2019-10-22 Super Zhang V1.01 2020-12-03 Super
1.新版本 1.新版本
V1.1 2020-03-11 Super Zhang
1.不同尺寸板子增加输出参数
V1.2 2020-03-12 Super
1.修改钻孔输出方式代码
V1.3 2020-03-23 Super
1.增加0.549的M97批号孔
V1.4 2020-3-25 Super
1.增加web server数据传输
V1.5 2020-03-27 Super
1.钻孔输出格式调整为3:3不省零 modal_coords=no
V1.6 2020-3-30 Super
1.修改涨缩参数
V1.7 2020-04-01 Super
1.钻带表头增加料号和涨缩信息
2.涨缩中心点按原点移动后的数据从新计算
V1.8 2020-04-02 Super
1.涨缩中心按改变原点前的坐标计算
v1.9 2020-04-04 Super
1.angle = 270
v2.0 2020-04-15 Kurri
1.增加跳刀参数
V2.1 2020-04-21 Super
1.调整T99坐标位置
2.T02板框监视孔的数据放到T01前面
V2.2 2020-05-14 Kurri
1.vpg层也插入M97,${JOB} $S$I
V2.3 2020-05-15 Kurri
1.修复涨缩小于1的程序没有正常输出的问题
V2.31 2020-06-09 Super
1.扩孔时不再增加G84代码
2.扩孔钻咀用3.151
3.修复ncset同名时钻孔无法输出
V2.32 2020-06-11 Super
1.输出命名更新
V2.33 2020-08-18 Super
1.读取map_info参数2.修复检测孔不是第二把刀的时候检测孔坐标乱刀序,3.双面3.054排序
V2.34 2020-10-13 Kurri
1.输出层别选择取消board属性限定
V2.35 2020-10-16 Kurri
1.增加程序上传的类型
V2.36 2020-10-16 Kurri
1.输出alp和alr时bottom层做mirror
V2.37 2020-10-21 Kurri
1.取消测试版本T2.37
T2.38 2020-10-22 Super
1.增加短槽拉伸
2.调整*的M97/M98模式
T2.39 2020-10-29 Super
1.更新拉伸规则
2.706*603的M97/M98位置调整
V2.38 2020-11-03 Super
1.测试版本到正式版
2.取消槽孔角度旋转
3.输出参数增加single_sr
V2.39 2020-11-06 Super
1.输出参数break_sr设置成yes
HELP: HELP:
<html><body bgcolor="#DDECFE"> <html><body bgcolor="#DDECFE">
<font size="3" color="#003DB2"><p>功能简介</p></font> <font size="3" color="#003DB2"><p>功能简介</p></font>
<p> 钻孔输出 </p> <p> 钻孔输出 </p>
<br> <br>
<font size="3" color="#003DB2"><p>参数配置</p></font> <font size="3" color="#003DB2"><p>参数配置</p></font>
<font color="#008000"><p> ● 无</p></font> <p> ● 无</p>
<font size="3" color="#003DB2"><p>注意事项</p></font> <font size="3" color="#003DB2"><p>注意事项</p></font>
<p> ● 无 </p> <p> ● 无 </p>
<br> <br>
...@@ -127,1025 +30,314 @@ ...@@ -127,1025 +30,314 @@
=cut =cut
use strict; use strict;
use Encode;
use utf8; use utf8;
use Encode;
use Data::Dump 'dump'; use Data::Dump 'dump';
use Number::Format 'round';
use File::Path 'make_path';
use File::Copy; use File::Copy;
use JSON; use Win32::OLE::Const ;
my $json = new JSON; my $EX_OB = Win32::OLE->new('Excel.Application', 'Quit');
# my $datum;#增加一个基准点数据 my $const = Win32::OLE::Const->Load($EX_OB);
# my @drl_section_data;#监视孔范围数据
# my (@drl_section,$section_tool,$section_number);#监视孔坐标
use_module('TL_GenMath'); use_module('TL_GenMath');
use_module('TL_OLE_Excel');
my ($Job,$Step)=($JOB,undef); my $json = new JSON;
my $units = 'mm'; my $obj = TL::GenMath->new();
# my $url = "http://10.87.66.216:9008/api/TOPMES6_SEC_V6/sec/sec-import_drill_program"; my $Job = $JOB;
# my $server_data; my $Step = $PAR->{step_filter} = $PAR->{step_filter} ? $PAR->{step_filter} : '.*';
my $Return = 'done';
# my $map_info = do($GEN->getJobPath(job=>$Job).'/user/PNL_map_info'); my $tmp_layer = 'tl_tmp_layer';
# my $new_name = get_new_layer_name("$Job"); my @rou_layer;
##host name为cody电脑名称,本地测试用本地目录 try{
use Sys::Hostname; if (! $GEN->isJobExists(job=>$Job) ){
my $hostname = hostname; $GUI->msgbox(-icon=>'error',-text=>"料号 $Job 在Genesis中不存在, 请检查!");
#$GUI->debug(dump($hostname)); return 'Error';
if( $hostname eq 'DESKTOP-010QP68' ){
$PAR->{out_dir} = 'D:/tmp';
}
if ($hostname eq 'g1kevnzhang'){
$PAR->{out_dir} = 'D:/tmp';
}
$PAR->{spread} = 2000 unless $PAR->{spread};
$PAR->{reread_layer} = 'no' unless $PAR->{reread_layer};
$PAR->{is_select_lyr} = 'no' unless $PAR->{is_select_lyr};
$PAR->{save_job} = 'No' unless $PAR->{save_job};
$PAR->{cool_spread} = 350 unless $PAR->{cool_spread};#跳孔间距
unless( $PAR->{out_dir} ){
$GUI->msgbox(-icon=>'warning',-text=>'请在脚本参数中设定钻孔输出路径');
return 'Cancel';
}
$PAR->{out_dir} = encode('gbk',$PAR->{out_dir});
##
unless( -d $PAR->{out_dir} ){
$GUI->msgbox(-icon=>'warning',-text=>"$PAR->{out_dir} 脚本参数设定的钻孔输出目录不存在,请确认!");
return 'Cancel';
}
$PAR->{out_dir} .= '/'.lc($new_name);
mkdir $PAR->{out_dir} unless ( -e $PAR->{out_dir});
my $info;
try {
show_loading("判断是否选择料号..",0,position=>'n');
unless( $Job){
$GUI->msgbox(-icon=>'error',-text=>"请先选择料号后再执行脚本!");
return 'Cancel';
}
##检查料号是否存在
update_loading("检查${Job}是否存在..",0,position=>'n');
unless ( $GEN->isJobExists(job=>$Job) ){
$GUI->msgbox(-icon=>'error',-text=>"料号 $Job 不存在,请确认。");
return 'Cancel';
} }
##
update_loading("正在打开料号${Job}...",0,position=>'n');
$GEN->openJob(job=>$Job) unless ($GEN->isJobOpen(job=>$Job)); $GEN->openJob(job=>$Job) unless ($GEN->isJobOpen(job=>$Job));
##
update_loading("过滤工作step...",0,position=>'n'); update_loading("过滤工作step...",0,position=>'n');
my $ans = get_work_step(); my $return = get_work_step();
return $ans if $ans; return 'Cancel' if $return eq 'Cancel';
##选择工作层
update_loading("过滤层别...",0,position=>'n');
my @work_layers = select_work_layer();
return 'Cancel' if $work_layers[0] eq 'Cancel';
##确认涨缩信息
my $scale = get_scale_info(layers=>\@work_layers);#-----涨缩值信息确认
return $scale if $scale eq 'Cancel';
$PAR->{scale} = $scale;
##
update_loading("正在打开料号$Step STEP...",0,position=>'n');
$GEN->openStep(job=>$Job,name=>$Step); $GEN->openStep(job=>$Job,name=>$Step);
$GEN->clearLayers(); $GEN->clearLayers();
$GEN->affectedLayer( mode=>'all',affected=>'no' ); $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->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=>$units ); $GEN->units( type=>'mm' );
$GEN->zoomHome(); $GEN->zoomHome();
update_loading("确认输出参数...",0,position=>'n');
$PAR->{profile_limits} = $GEN->getProfileLimits(job=>$Job,step=>$Step,units=>'mm'); my %matrix = $GEN->getMatrix(job=>$Job,type=>'hash');
$PAR->{profile_limits}{xc} = $PAR->{profile_limits}{xsize}/2-abs($PAR->{profile_limits}{xmin}); foreach my $layer (sort {$matrix{$a}{row} <=> $matrix{$b}{row}} keys %matrix) {
$PAR->{profile_limits}{yc} = $PAR->{profile_limits}{ysize}/2-abs($PAR->{profile_limits}{ymin}); if(defined($matrix{$layer}{context}) and $matrix{$layer}{context} eq 'board' ){
$PAR->{sr} = $GEN->getSRLimits(job=>$Job,step=>$Step,units=>'mm'); if($matrix{$layer}{layer_type} eq 'rout'){
push @rou_layer,$layer;
my $orgDrillToolInfo ;
foreach my $layer (@work_layers) {
##钻孔输出
update_loading("$layer 层钻孔正在输出...",0,position=>'n');
my $output_layer = $Job.'-'.$layer.'-ori';#$Job.'-'.$layer.'-ori'
my $ans = drill_out(layer=>$layer,output_layer=>$output_layer,scale_x=>$PAR->{scale}{$layer}{x},scale_y=>$PAR->{scale}{$layer}{y});
return $ans if $ans;
####钻孔程式编辑
my $new_layer;
if($PAR->{scale}{$layer}{x} != 1 or $PAR->{scale}{$layer}{y} != 1){
$new_layer= $new_name.'.'.$layer.('X').($PAR->{scale}{$layer}{x}).('Y').($PAR->{scale}{$layer}{y});
}else{
$new_layer= $new_name.'.'.$layer;
} }
my $new_file = $PAR->{out_dir}.'/'.$new_layer;
update_loading("$layer 层钻孔程式正在编辑...",0,position=>'n');
$ans = edit_nc_file(layer=>$layer,output_file=>$PAR->{out_dir}.'/'.$output_layer,new_file=>$new_file,x=>$PAR->{scale}{$layer}{x},y=>$PAR->{scale}{$layer}{y});#drl_type=>$drl_type
return $ans if $ans;
##删除钻孔输出的临时文件
unlink $PAR->{out_dir}.'/'.$output_layer;
##回读钻孔程式
if( $PAR->{reread_layer} =~ /yes/i){
update_loading("$layer 层钻孔程式回读中...",0,position=>'n');
my $new_layer_2 = $new_layer;
input_drill_program(layer=>$layer,file=>$PAR->{out_dir}.'/'.$new_layer_2,new_layer=>$new_layer);#drl_type=>$drl_type,drl_side=>$drl_side
} }
#传入web server数据
#if($layer =~ /(cdr|vpg|alp|alr|psp)/){
# update_loading("$layer 层web server数据上传中...",0,position=>'n');
# open(TMP,$new_file) || die "cannot open $PAR->{out_dir}/$new_layer";
# my @data = <TMP>;
# close (TMP);
# chomp(@data);
# my $file_data;
# $file_data = join("\n",@data);
# $server_data->{data} = [{
# tooling_type=>"mech_drill",
# tooling_name=>$new_layer,
# partnumber=>$Job,
# tooling_text_data=>$file_data,
# }];
# #$GUI->debug(-text=>dump($server_data));
# my $result = sec_web_services($url,$server_data);
# if($result){
# $GUI->msgbox(-icon=>'error',-text=>"Web services数据传输错误!");
# return 'Cancel';
# }
#}
} }
my $info = confirm_gui(layers=>[@rou_layer]);
return unless ($info);
hide_loading(); update_loading("rou输出中...",0,position=>'n');
output_rou(job=>$Job,step=>$Step,info=>$info);
##保存料号 update_loading("资料回读中...",0,position=>'n');
if( $PAR->{save_job} =~ /yes/i ){ input_layers(job=>$Job,step=>$Step,info=>$info);
show_loading("$Job 正在保存料号,请稍候...",0,position=>'n');
$GEN->checkInout(job=>$Job,mode=>'out');
$GEN->saveJob(job=>$Job);
hide_loading();
}
###output and return status, if genesis error, it will output genesis error command ###output and return status, if genesis error, it will output genesis error command
unless ($GEN->{STATUS}){ unless ($GEN->{STATUS}){
return 'done'; show_loading("资料输出完成....!",0,position=>'center');
sleep(1);
return $Return;
} }
else{ else{
$GUI->msgbox(-icon=>'error',-text=>join("\n",@{$GEN->{STATUS}})); $GUI->msgbox(-icon=>'error',-text=>join("\n",@{$GEN->{STATUS}}));
addFlowNotes(-notes=>" Genesis Error:\n ".join("\n ",@{$GEN->{STATUS}}));
return 'Error'; return 'Error';
} }
} }
catch Error::Simple with { catch Error::Simple with {
my $error = shift; my $error = encode("utf8",shift);
$GUI->msgbox(-icon=>'error',-text=>$error); $GUI->msgbox(-icon=>'error',-text=>$error);
return 'Error'; return 'Error';
} }
finally{ finally{
$GEN->COM('disp_on');
}; };
sub get_work_step {
my @steps = $GEN->getStepList(job=>$Job);
if ( @steps == 0 ) {
$GUI->msgbox(-icon=>'error',-text=>'在料号中没有Step存在,请确认。');
return 'Cancel';
}
elsif (@steps != 0){
$PAR->{step_filter} = '.*' unless $PAR->{step_filter};
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],
-default=>[$tmp_steps[0]],
-gen=>$GEN,
-selectmode=>'single');
return 'Cancel' unless ($Step);
}
}
return undef;
}
sub select_work_layer {
=head
rou输出
=cut
sub output_rou {
my %par = @_; my %par = @_;
my @drill; my $info = $par{info};
my %matrix = $GEN->getMatrix(job=>$Job,type=>'hash'); my $PL = $GEN->getProfileLimits(job=>$Job,step=>$Step,units=>'mm');
foreach my $layer (sort {$matrix{$a}{row} <=> $matrix{$b}{row}} keys %matrix) { my $nc_set = 'zwz';
next if $layer =~ /ddr/; my $machine = 'sintai_excellon';
if(defined($matrix{$layer}{layer_type}) and $matrix{$layer}{layer_type} eq 'drill'){ foreach my $layer (values %{$info->{layer_info}}) {
push @drill,$layer; next if ($layer->{output_flag} !~ /^yes$/i);
} $GEN->DO_INFO("-t layer -e $Job/$Step/$layer->{layer_name} -d NCRSETS_LIST");
} if( @{$GEN->{doinfo}{gNCRSETS_LIST}} ){
unless( @drill ){ if (grep (/^($nc_set)$/,@{$GEN->{doinfo}{gNCRSETS_LIST}})) {
$GUI->msgbox(-icon=>'warning',-text=>'资料中无钻孔层,请确认!'); $GEN->COM('ncrset_delete',name=>$nc_set);
return 'Cancel'; }
}
$GEN->COM('ncrset_cur',job=>$Job,step=>$Step,layer=>$layer->{layer_name},ncset=>$nc_set);
$GEN->COM('ncr_set_machine',machine=>$machine,thickness=>0);
$GEN->COM('ncr_register',angle=>0,mirror=>$layer->{is_mirror},xoff=>0,yoff=>0,version=>1,xorigin=>0,yorigin=>0,xscale=>$layer->{scale_x},yscale=>$layer->{scale_y},xscale_o=>0,yscale_o=>0);
$GEN->COM('ncr_cre_rout');
$GEN->COM('ncr_ncf_export',dir=>$info->{output_path},name=>$info->{prefix}.'.'.$layer->{layer_name});
$GEN->COM('ncrset_delete',name=>$nc_set);
} }
if ($PAR->{is_select_lyr} eq 'yes' and scalar @drill > 1) { unless ($GEN->{STATUS}){
my (%tmp_matrix); return ;
foreach my $layer (@drill) {
$tmp_matrix{$layer} = $matrix{$layer};
}
@drill = $GUI->select_layer(
-title=>'请选择输出层别',
-layermatrix=>\%tmp_matrix,
-default => ['drl','md','bk','lp'],
-selectmode => 'multiple');#single
return 'Cancel' unless(@drill);
} }
return @drill;
} }
sub get_scale_info{ =head
用户配置参数
=cut
sub confirm_gui {
my %par = @_; my %par = @_;
my (%rows,$n); my ($rows,$n);
foreach my $layer (@{$par{layers}}){ my $cam = $IKM->get_jobinfo(-jobname=>$Job,-jobid=>$JOB_ID,-jobcategory=>'work',-jobinfo=>'cam_serial_number',-withspec=>1);
my $folder = 'rou';
my $path = $PAR->{Outpath}."$cam/$folder";
make_path($path);
foreach my $layer (@{$par{layers}}) {
$n ++; $n ++;
$rows{$layer}{sequence} = $n; $rows->{$n}{sequence} = $n;
$rows{$layer}{layer} = $layer; $rows->{$n}{layer_name} = $layer;
if($layer eq "md"){ $rows->{$n}{scale_x} = 1;
$rows{$layer}{x} = 1.0004; $rows->{$n}{scale_y} = 1;
$rows{$layer}{y} = 1.0004; $rows->{$n}{output_flag} = 'Yes';
} $rows->{$n}{is_mirror} = 'no';
else{ }
$rows{$layer}{x} = 1.0000; my $v_data = $GUI->show_form(
$rows{$layer}{y} = 1.0000; -title=>"Rou输出参数确认单",
} -defaultsize=>[520,500],
-items=> [
} {
my $scale_factor = $GUI->show_tableform ( type => 'title',
-defaultsize=>[380,400],-title => '请确认涨缩值',-rows => \%rows, property=>{
-showcheck => 1,-gen => $GEN, title=>'输出料号和名称',
-columns => [ },
n_columns=>2,
},
{
name => 'prefix',
label => '输出档名:',
type => 'string',
value=>$cam,
width=>100,
must_field=>1,
},
{ {
column_name=>'layer', type => 'title',
label=>'层名称', property=>{
width=>70, title=>'参数确认',
},
n_columns=>8,
},
{
name => 'layer_info',
label =>'参数确认',
label_position => 'no',
class => 'TL::Gtk2::TableFormPanel',
expand => 1,
property => {
tl_columns =>[
{
column_name=>'layer_name',
label=>'层别名称',
width=>100,
type=>'label', type=>'label',
}, },
{ {
column_name=>'x', column_name=>'scale_x',
label=>'X涨缩值', label=>'涨缩值X',
width=>130, width=>80,
type=>'number', type=>'number',
must_field=>1,
}, },
{ {
column_name=>'y', column_name=>'scale_y',
label=>'Y涨缩值', label=>'涨缩值Y',
width=>130, width=>80,
type=>'number', type=>'number',
must_field=>1,
},
{
column_name=>'output_flag',
label=>'是否输出',
width=>80,
type=>'radio',
property=>{
tl_columns => 2,
tl_list => ['Yes' => '是', 'No'=>'否'],
},
},
{
column_name=>'is_mirror',
label=>'是否镜像',
width=>80,
type=>'radio',
property=>{
tl_columns => 2,
tl_list => ['yes' => '是', 'no'=>'否'],
}, },
],
);
return 'Cancel' unless ($scale_factor);
##
return $scale_factor;
}
=head
drillmarge 输出
=cut
sub drill_out
{
my %par = @_;
my $nc_set = 'sec-jt';
my @ncsets = $GEN->getNcsetsList(job=>$Job,step=>$Step,layer=>$par{layer});
if( @ncsets ){
if (grep (/^($nc_set)$/,@ncsets)) {
$GEN->COM('ncset_delete',name=>$nc_set);
}
}
#钻带涨缩中心点
my $x_anchor = ($par{scale_x} != 1 or $par{scale_y} != 1) ? $PAR->{profile_limits}{xc} : 0;
my $y_anchor = ($par{scale_x} != 1 or $par{scale_y} != 1) ? $PAR->{profile_limits}{yc} : 0;
unlink if(-e $PAR->{out_dir}.'/'.$par{output_layer});
my ($org_x,$org_y,$angle);
if($PAR->{profile_limits}{ysize} == 603 and $PAR->{profile_limits}{xsize} == 706){
$org_x = $PAR->{profile_limits}{yc};#- 15
$org_y = 5;
$angle = 270;
$datum->{x} = $PAR->{profile_limits}{xmax} - 5;
$datum->{y} = $PAR->{profile_limits}{yc};
$datum->{angle} = 90;
$datum->{type} = 1;#拼版类型
}elsif($PAR->{profile_limits}{ysize} == 603 and $PAR->{profile_limits}{xsize} == 606){
$datum->{x} = $org_x = $PAR->{profile_limits}{xc};#- 5
$datum->{y} = $org_y = 5;
$datum->{angle} = $angle = 0;
$datum->{type} = 0;#拼版类型
}else{
$datum->{x} = $org_x = $PAR->{profile_limits}{xc};#- 24
$datum->{y} = $org_y = 5;
$datum->{angle} = $angle = 0;
$datum->{type} = 0;#拼版类型
}
# 铝片塞防焊和铝片塞树脂程序,bot面时需要mirror
my $xmirror = 'no';
my $ymirror = 'no';
if ($par{layer} =~ /al[pr](\d\d)(\d\d)/) {
my $start = $1 + 0;
my $end = $2 + 0;
if ($start > $end) {
$xmirror = 'yes';
}
}
#获取@drl_section_data数据
if($par{layer} =~ /(cdr)/ and $GEN->getLayerCount(job=>$Job) >= 4){
my @feat = $GEN->getFeatures(job=>$Job,step=>$Step,layer=>'pnl-map',units=>'mm');
my @data_tmp = grep($_->{attributes}->[0] =~ /(DRL_SECTION)/,@feat);#获取监视孔坐标
$section_tool = $map_info->{P}{min_drl} >= 1100 ? 1100 : $map_info->{P}{min_drl};
@drl_section_data = TL::GenMath->p_trans($datum,$datum->{angle},'no',-$datum->{x},-$datum->{y},@data_tmp);
# if($datum->{angle} == 90){
# my @data_tmp = TL::GenMath->p_trans($datum,$datum->{angle},'no',0,0,@data_tmp);#坐标选择
# foreach my $data (@data_tmp){
# my $coorder_txt;
# $coorder_txt = change_coode(data=>$data,datum=>$datum);
# $drl_section_data->{$coorder_txt} = 1;
# }
# }else{
# foreach my $data (@data_tmp){
# my $coorder_txt;
# $coorder_txt = change_coode(data=>{x=>$data->{x},y=>},datum=>$datum);
# $drl_section_data->{$coorder_txt} = 1;
# }
# }
}
my $id = $nc_set;
$GEN->COM('ncset_units',units=>'mm');
if($par{layer} =~ /(cdr)/){
$GEN->affectedLayer(affected=>'yes',layer=>$par{layer},clear_before=>'yes');
$GEN->COM("adv_filter_reset");
$GEN->COM("reset_filter_criteria,filter_name=,criteria=all");
$GEN->selectByFilter(attribute=>[{attribute=>'tl_string',text=>"*LDI_HOLE_Two*"}]);
$GEN->selectByFilter(attribute=>[{attribute=>'tl_string',text=>"*XRAY_HOLE*"}]);
$GEN->COM("adv_filter_reset");
$GEN->COM("reset_filter_criteria,filter_name=,criteria=all");
$GEN->selChangeSym(symbol=>'r1') if $GEN->getSelectCount();
$GEN->affectedLayer( mode=>'all',affected=>'no' );
}
#$GEN->COM('open_sets_manager',test_current=>'no');
$GEN->COM('nc_create',ncset=>$id,device=>'basic_excellon',lyrs=>$par{layer},thickness=>0);
$GEN->COM('nc_set_advanced_params',layer=>$par{layer},ncset=>$id);
$GEN->COM('nc_set_current',job=>$Job,step=>$Step,layer=>$par{layer},ncset=>$id);
$GEN->COM('nc_set_file_params',single_sr=>'no',output_path=>$PAR->{out_dir},output_name=>$par{output_layer},zeroes=>'none',units=>'mm',tool_units=>'mm',nf1=>3,nf2=>3,decimal=>'no',modal_coords=>'no');
$GEN->COM('nc_register',angle=>$angle,xoff=>0,yoff=>0,version=>1,xorigin=>$org_x,yorigin=>$org_y,xscale=>$par{scale_x},yscale=>$par{scale_y},xscale_o=>$x_anchor,yscale_o=>$y_anchor,xmirror=>$xmirror,ymirror=>$ymirror);
$GEN->COM('nc_set_optim',optimize=>'yes',iterations=>5,reduction_percent=>1,cool_spread=>$PAR->{cool_spread},break_sr=>'yes',xspeed=>2540,yspeed=>2540,diag_mode=>'45ort');
$GEN->COM('nc_cre_output',layer=>$par{layer},ncset=>$id);
my $profile = $GEN->getProfileLimits(job=>$Job,step=>$Step,units=>'mm');
$GEN->origin(x=>$profile->{xmin},y=>$profile->{ymin});
if($par{layer} =~ /(cdr)/){
$GEN->affectedLayer(affected=>'yes',layer=>$par{layer},clear_before=>'yes');
$GEN->COM("adv_filter_reset");
$GEN->COM("reset_filter_criteria,filter_name=,criteria=all");
$GEN->selectByFilter(attribute=>[{attribute=>'tl_string',text=>"*LDI_HOLE_Two*"}]);
$GEN->selectByFilter(attribute=>[{attribute=>'tl_string',text=>"*XRAY_HOLE*"}]);
$GEN->COM("adv_filter_reset");
$GEN->COM("reset_filter_criteria,filter_name=,criteria=all");
$GEN->selChangeSym(symbol=>'r3054') if $GEN->getSelectCount();
$GEN->affectedLayer( mode=>'all',affected=>'no');
}
@ncsets = $GEN->getNcsetsList(job=>$Job,step=>$Step,layer=>$par{layer});
if( @ncsets ){
if (grep (/^($nc_set)$/,@ncsets)) {
$GEN->COM('ncset_delete',name=>$nc_set);
}
}
return undef;
}
sub edit_nc_file{
my %par = @_;
open(TMP,"$par{output_file}") || die "cannot open $par{output_file}";
my @data = <TMP>;
close (TMP);
chomp @data;
#
my %data = split_program(data=>\@data);
my $ans = convert_new_program(layer=>$par{layer},new_file=>$par{new_file},data=>\%data,x=>$par{x},y=>$par{y});
return $ans if $ans;
return undef;
}
sub split_program{
my %par = @_;
my $ui_info = $par{info};
my (%info);
my ($flag,$router_flag) = ('start',undef);
foreach my $line(@{$par{data}}){
if( $flag eq 'start' ){
if( $line eq 'M48' ){
$flag = 'overhead';
}
}
elsif( $flag eq 'overhead' ){
if( $line =~ /^T01C/i ){
$flag = 'head';
}
}
elsif( $flag eq 'head' ){
if( $line !~ /^T\d+/i ){
$flag = 'neck';
}
}
elsif( $flag eq 'neck' ){
if( $line =~ /^T01/i ){
$flag = 'body';
}
}
elsif( $flag eq 'body' ){
if( $line =~ /^M30$/i ){
$flag = 'end';
}
}
##
if( $flag eq 'overhead' ){
push @{$info{overhead}},$line;
}
elsif( $flag eq 'head' ){
if($line =~ /^T(\d+)C(.*)/){
if($2 - $section_tool/1000 < 0.0001){
$section_number = $1;
}
}
push @{$info{head}},$line;
}
elsif( $flag eq 'neck' ){
push @{$info{neck}},$line;
}
elsif( $flag eq 'body' ){
if( $line =~ /^(T(\d+))$/i ){
$router_flag = $1;
}
if($router_flag){
my ($num) = $router_flag =~ /^T(\d+)$/;
$info{body}{$router_flag}{num} = $num;
#判断孔的范围 2020-04-21
# if($num - $section_number < 0.001 and $line !~ /^T/){
# my $point = change_coode_to_vale($line);
# my $are_check = 0;
# foreach my $symbol (@drl_section_data){
# my $dist = TL::GenMath->point2sym_dist($point,$symbol);
# if($dist == 0){
# $are_check = 1;
# last;
# }
# }
# if($are_check){
# push @drl_section,$line;
# }else{
# push @{$info{body}{$router_flag}{value}},$line;
# }
# }else{
push @{$info{body}{$router_flag}{value}},$line;
# }
}
}
elsif( $flag eq 'end' ){
push @{$info{end}},$line;
}
##
}
if( wantarray ){
return %info;
}
else{
return \%info;
}
}
sub convert_new_program{
my %par = @_;
##
open(NEWMYFILE,">$par{new_file}");
my %data = %{$par{data}};
##0.插入表头
# if($par{x} != 1 or $par{y} != 1){
# print NEWMYFILE 'M47,'.$Job.' '.'X:'.$par{x}.' '.'Y:'.$par{y},"\n";
# }
##1.头顶(刀径清单之前的)/overhead
foreach my $line(@{$data{overhead}}){
print NEWMYFILE $line,"\n";
}
##
##2.程序头(router清单)/head
my $tool_change = get_tool_change(layer=>$par{layer},data=>$par{data});
#$GUI->debug(dump($tool_change));
###人工排序一次
# $tool_change = manual_sort_tool(layer=>$par{layer},data=>$par{data},info=>$tool_change);
# return $tool_change if $tool_change eq 'Cancel';
##目前扩孔后没有其它类型的孔
my $nibble_suffix = 1;
my $check_nibble_tool = 0;
foreach my $line(@{$data{head}}){
my ($tool,$suffix) = $line =~ /^(T\d+)C.*$/;
next unless $tool;
##刀序顺序使用最新的
next unless $tool_change->{$tool}{new_tool};
foreach my $item(values %$tool_change){
if( $tool eq $item->{new_tool} ){
if($tool_change->{$item->{new_tool}}{size} > 6.35){
if(! $check_nibble_tool){
print NEWMYFILE $tool.'C'.(3.15 + $nibble_suffix/1000),"\n";
#$nibble_suffix++;
$check_nibble_tool = 1;
}
}else{
print NEWMYFILE $item->{new_header},"\n";
}
$PAR->{tool_num_count} = $item->{new_tool_num} unless ($PAR->{tool_num_count} and $PAR->{tool_num_count} > $item->{new_tool_num});
#$hole_exit = 1 if $item->{new_header} =~ /503$/;
}
}
}
# if($par{layer} =~ /(cdr|vpg|alp|alr|psp)/){
# print NEWMYFILE 'T99C0.549',"\n";
# }
##3.脖子(程序头和正式T序坐标之间)/neck
foreach my $line(@{$data{neck}}){
next if $line =~ /g93/i;
print NEWMYFILE $line,"\n";
}
# if(@drl_section_data){
# print NEWMYFILE 'T'.$section_number,"\n";
# foreach my $tmp (@drl_section){
# print NEWMYFILE $tmp,"\n";
# }
# }
##4.实际的每把T序/body
my $nibble_tool_check = 0;
foreach my $tool (sort{$data{body}{$a}{num}<=>$data{body}{$b}{num}} keys %{$data{body}}){
##获取对应的新刀径
my $new_tool;
my $check_drl_section = 0;
foreach my $old_tool(keys %$tool_change){
if( $tool eq $tool_change->{$old_tool}{new_tool} ){
$new_tool = $old_tool;
}
}
next unless $new_tool;
foreach my $line(@{$data{body}{$new_tool}{value}}){
#if( abs($tool_change->{$new_tool}{size} - 3.175) < 0.001 ){
# if( $line =~ /^(T\d+)/ ){
# print NEWMYFILE '/',$tool,"\n";
# }
# else{
# print NEWMYFILE '/',$line,"\n";
# }
#}
#else{
#if( $line =~ /^(T\d+)/ ){
# print NEWMYFILE $tool,"\n";
#}
#else{
# print NEWMYFILE $line,"\n";
#}
#}
if( $tool_change->{$new_tool}{size} > 6.35 ){
if( $line =~ /^(T\d+)/ ){
if( !$nibble_tool_check ){
print NEWMYFILE $tool,"\n";
$nibble_tool_check = 1;
}
}
else{
print NEWMYFILE $line,"\n";#'G84X'.$tool_change->{$new_tool}{size}
}
}
else{
if( $line =~ /^(T\d+)/ ){
print NEWMYFILE $tool,"\n";
}
else{
if( $line =~ /X.*Y.*G85X.*Y.*/ ){
my ($tmp1,$tmp2) = $line =~ /(X\-?\d*\.?\d*Y\-?\d*\.?\d*)G85(X\-?\d*\.?\d*Y\-?\d*\.?\d*)/;
my $slot_star = change_coode_to_vale($tmp1);
my $slot_end = change_coode_to_vale($tmp2);
my $slot_size = $tool_change->{$new_tool}{size};
my $slot_length = $slot_size + TL::GenMath->line_length({xs=>$slot_star->{x},xe=>$slot_end->{x},ys=>$slot_star->{y},ye=>$slot_end->{y}});
my $slot_info = ger_short_slot_vale(slot_size=>$slot_size,slot_length=>$slot_length);
#if($slot_info){
# my $angle = $slot_info->{angle};
# my $point = TL::GenMath->rotate_point($slot_star,$slot_end,$angle);
# my $tmp_data = change_coode(data=>{x=>$point->{x},y=>$point->{y}},datum=>{x=>0,y=>0});
# my $tmp_line = $tmp1.'G85'.$tmp_data;
# print NEWMYFILE $tmp_line,"\n";
#}else{
print NEWMYFILE $line,"\n";
#}
}else{
print NEWMYFILE $line,"\n";
}
}
}
}
}
#插入M97坐标 'X-214500Y000000'
if($par{layer} =~ /(cdr|vpg|alp|alr|psp)/){
my @feat = $GEN->getFeatures(job=>$Job,step=>$Step,layer=>'pnl-map',units=>'mm');
my @feat_M97 = grep($_->{attributes}->[0] =~ /(DRL_TXT_DRL)/,@feat);
my $coordinate_txt;
my $mode;#判断*的位置是横放还是竖放 1 代表横放 2代表竖放
if($feat_M97[0]->{x} >= $PAR->{sr}{xmin} and $feat_M97[0]->{x} <= $PAR->{sr}{xmax}){
$mode = 1;
}else{
$mode = 2;
}
if($datum->{angle} == 90){
my @M97_tmp = TL::GenMath->p_trans($datum,$datum->{angle},'no',0,0,({x=>$feat_M97[0]->{x},y=>$feat_M97[0]->{y}}));#返回的是一个数组
if($mode == 1){
$coordinate_txt = change_coode(data=>{x=>$M97_tmp[0]->{x} + 2.5 - 0.275,y=>$M97_tmp[0]->{y} - 25 + 0.275},datum=>$datum);
}else{
$coordinate_txt = change_coode(data=>{x=>$M97_tmp[0]->{x} - 25 + 0.275,y=>$M97_tmp[0]->{y} - 2.5 + 0.275},datum=>$datum);
}
}else{
if($mode == 1){
$coordinate_txt = change_coode(data=>{x=>$feat_M97[0]->{x} - 25 + 0.275,y=>$feat_M97[0]->{y} - 2.5 + 0.275},datum=>$datum);
}else{
$coordinate_txt = change_coode(data=>{x=>$feat_M97[0]->{x} + 2.5 - 0.275,y=>$feat_M97[0]->{y} - 25 + 0.275},datum=>$datum);
}
}
if($datum->{angle} == 90){
print NEWMYFILE 'T99',"\n";
if($mode == 1){
#$GEN->PAUSE('M98');
print NEWMYFILE 'M98,'.substr($Job,0,6).' $S$I',"\n";
}else{
#$GEN->PAUSE('M97');
print NEWMYFILE 'M97,'.substr($Job,0,6).' $S$I',"\n";
}
print NEWMYFILE $coordinate_txt,"\n";
}else{
print NEWMYFILE 'T99',"\n";
if($mode == 1){
print NEWMYFILE 'M97,'.substr($Job,0,6).' $S$I',"\n"
}else{
print NEWMYFILE 'M98,'.substr($Job,0,6).' $S$I',"\n";
}
print NEWMYFILE $coordinate_txt,"\n";
}
}
##5.结束/end
foreach my $line(@{$data{end}}){
print NEWMYFILE $line,"\n";
}
##
close (NEWMYFILE);
return undef;
}
sub get_tool_change{
my %par = @_;
my %info;
my %data = %{$par{data}};
my $is_laser = $par{is_laser};
my $row_num = 0;
##
my (%head,%special,$exist_2500);
##先判断有无3.054的刀径(排第1)
foreach my $line(@{$data{head}}){
my ($tool,$size,$data) = $line =~ /^(T\d+)C(\d*\.?\d{3})(S?.*)$/;
next unless $tool;
$head{$tool}{data} = 'C'.$2;
####
if( abs($size - 0.001) < 0.0001 ){
$head{$tool}{data} = 'C3.054';
$row_num++;
$info{$tool}{new_tool_num} = $row_num;
$info{$tool}{new_tool} = 'T'.sprintf("%02s",$row_num);
$info{$tool}{size} = 3.054;
$info{$tool}{new_header} = $info{$tool}{new_tool}.$head{$tool}{data};
}
}
foreach my $line(@{$data{head}}){
my ($tool,$size,$data) = $line =~ /^(T\d+)C(\d*\.?\d{3})(.*)$/;
next unless $tool;
next if(abs($size - 0.001) < 0.0001);
$row_num++;
$info{$tool}{size} = $size;
$info{$tool}{new_tool_num} = $row_num;
$info{$tool}{new_tool} = 'T'.sprintf("%02s",$row_num);
$info{$tool}{new_header} = $info{$tool}{new_tool}.$head{$tool}{data};
} }
return \%info; ],
} tl_rows=>$rows,
},
sub manual_sort_tool{ set_value_func => sub{
my %par = @_; my %par = @_;
my $data = $par{data}; my $data = $par{value};
my $tool_info = $par{info}; foreach my $row_name (%$data){
my @items; foreach my $col_name (%{$data->{$row_name}}){
my ($slot_flag,@slot_size); $par{widget}->set_value($row_name,$col_name,$data->{$row_name}{$col_name});
foreach my $num(1..scalar(keys %{$data->{body}})){
my $tool = 'T'.sprintf("%02s",$num);
next unless $tool_info->{$tool}{new_tool};
foreach my $old_tool(sort{$tool_info->{$a}{new_tool_num}<=>$tool_info->{$b}{new_tool_num}} keys %$tool_info){
if( $tool eq $tool_info->{$old_tool}{new_tool} ){
my $suffix;
my $size = $tool_info->{$old_tool}{size};
push @items,{tool=>$old_tool,size=>$tool_info->{$old_tool}{size} >= 1 ? $tool_info->{$old_tool}{size} : '0'.$tool_info->{$old_tool}{size},suffix=>$suffix};
last;
}
} }
} }
update_loading("$par{layer} 层请确认钻刀排列顺序...",0,position=>'n');
my %form = $GUI->show_form(
-title => "请确认钻孔刀径顺序",
-defaultsize => [400,500],
-columns => 2,
-items => [
{
name => 'table',
type => 'treeview',
label => '',
label_position => 'top',
expand=>1,
scrolledwindow=>{},
property => {
height_request=>200,
tl_model_type => 'list',
enable_grid_lines => 'none',
tl_mapping =>['tool' => 'Glib::String','size' => 'Glib::String','suffix'=>'Glib::String'],
tl_columns =>[
{title=>'原始刀序',visible=>1,resizable=>1,min_width=>80,expand=>1,renders=>[{class=>'Text',property=>{editable=>0,background=>'#FCFBB6',foreground=>'#000000'},text=>'tool'}]},
{title=>'刀径',visible=>1,resizable=>1,min_width=>80,expand=>1,renders=>[{class=>'Text',property=>{editable=>0,background=>'#FCFBB6',foreground=>'#000000'},text=>'size'}]},
{title=>'后缀(可编辑)',visible=>1,resizable=>1,min_width=>80,expand=>1,renders=>[{class=>'Text',property=>{editable=>1,background=>'#C5DBF2',foreground=>'#000000'},text=>'suffix'}]},
],
}, },
value => \@items, get_value_func => sub{my %par = @_;return $par{widget}->get_all_value();},
get_value_func => sub{ my %par = @_;
my $tvdata = $par{widget}->tl_get_model_data();
return $tvdata;
}, },
set_value_func => sub{ my %par = @_; {
my $v = $par{value}; type => 'title',
$par{widget}->tl_set_data($v); property=>{
return 0; title=>'输出设置',
}, },
button_position=>'top', n_columns=>1,
buttons => [
{ name=>'top',label=>'置顶',stock=>'gtk-goto-top',
command=>sub{ my %p = @_;
my $widget = $p{formpanel}->get_widget('table');
$widget->set_property(reorderable=>1);
$widget->tl_sel_moveto_top();
$widget->set_property(reorderable=>0);
}
}, },
{ name=>'up',label=>'上移',stock=>'gtk-go-up', {
command=>sub{ my %p = @_; name => 'username',
my $widget = $p{formpanel}->get_widget('table'); label => '输出者:',
$widget->set_property(reorderable=>1); type => 'string',
$widget->tl_sel_move_up(); value=>$GEN->getUserName(),
$widget->set_property(reorderable=>0); width=>100,
} must_field=>1,
}, },
{ name=>'down',label=>'下移',stock=>'gtk-go-down', {
command=>sub{ my %p = @_; name => 'output_path',
my $widget = $p{formpanel}->get_widget('table'); label => '输出路径:',
$widget->set_property(reorderable=>1); type => 'string',
$widget->tl_sel_move_down(); value=>$path,
$widget->set_property(reorderable=>0); width=>100,
} must_field=>1,
property => {
editable=>0,
}, },
{ name=>'bottom',label=>'置底',stock=>'gtk-goto-bottom', buttons => [
command=>sub{ my %p = @_; {
my $widget = $p{formpanel}->get_widget('table'); name=>'btn1',label=>'选择路径',stock=>'gtk-add',
$widget->set_property(reorderable=>1); command=>sub{
$widget->tl_sel_moveto_bottom(); my %p = @_;
$widget->set_property(reorderable=>0); my $folder = $GUI->select_file(-title=>'选择路径',-type=>'select-folder',-defaultdir=>$PAR->{Outpath});
return unless($folder);
$p{formpanel}->set_value('output_path', $folder);
} }
}, },
], ],
}, },
] ]
); );
return 'Cancel' unless %form; return $v_data;
##将界面确认的结果重新整理一遍
my %info;
my @data = @{$form{table}};
my $row_num;
foreach my $item(@data){
$row_num++;
if( $item->{suffix} =~ /^\(w(\d+)\)$/i || $item->{suffix} =~ /^\(w(\d+)s\d+\)$/i || $item->{suffix} =~ /^\(s(\d+)\)$/i){
$info{$item->{tool}}{suffix} = $item->{suffix};
$info{$item->{tool}}{size} = $item->{size};
}
elsif($item->{suffix} =~ /^(\d+)$/i ){
$info{$item->{tool}}{suffix} = $item->{suffix}+0;
$info{$item->{tool}}{size} = $item->{size};
}
else{
$info{$item->{tool}}{size} = $item->{size};
}
$info{$item->{tool}}{new_tool_num} = $row_num;
$info{$item->{tool}}{new_tool} = 'T'.sprintf("%02s",$row_num);
if( $item->{suffix} =~ /^\((w|s)(\d+)\)$/i || $item->{suffix} =~ /^\(w(\d+)s(\d+)\)$/i){
$info{$item->{tool}}{new_header} = $info{$item->{tool}}{new_tool}.'C'.sprintf("%.3f",$info{$item->{tool}}{size}).$item->{suffix};
}
else{
$info{$item->{tool}}{new_header} = $info{$item->{tool}}{new_tool}.'C'.sprintf("%.3f",$info{$item->{tool}}{size});
}
}
##
return \%info;
}
sub input_drill_program{
my %par = @_;
$GEN->COM( "input_manual_reset");
$GEN->COM( "input_manual_set,path=$par{file},job=$Job,step=$Step,format=Excellon2,data_type=ascii,
units=mm,coordinates=absolute,zeroes=none,nf1=3,nf2=3,decimal=no,separator=nl,tool_units=mm,layer=$par{new_layer},wheel=,
wheel_template=,nf_comp=0,multiplier=1,text_line_width=0.0024,signed_coords=no,break_sr=yes,drill_only=no,merge_by_rule=no,threshold=200,resolution=3");
$GEN->COM( "input_manual,script_path=");
$GEN->zoomHome();
return undef;
} }
=head
web server数据传输
=cut
sub sec_web_services{
use LWP::UserAgent;
use LWP;
use HTTP::Headers;
use HTTP::Response;
use Encode;
use JSON;
use JSON qw(encode_json);
my $url = shift;
my $data = shift;
my $json = JSON->new->allow_nonref;
my $ua = LWP::UserAgent->new();
$ua->agent("Mozilla/5.0 (Windows NT 6.1; rv:30.0) Gecko/20100101 Firefox/30.0");
my $header = ['Content-Type' => 'application/json; charset=UTF-8'];
my $body = encode('utf8', $json->encode($data));
my $request = HTTP::Request->new('POST', $url, $header, $body);
my $res = $ua->request($request);
#$GUI->debug(-text=>dump($res,'-----------------------------------------------------------------',$res->is_success));
if ($res->is_success) {
return 0;
}else{
return 1;
}
}
=head
3:3 不省零
坐标转换 data=>{x=>,y=>} datum=>{x=>,y=>}
=cut
sub change_coode
{
my %par = @_;
my ($check_x,$check_y);
$par{data}->{x} = $par{data}->{x} - $par{datum}->{x};
$par{data}->{y} = $par{data}->{y} - $par{datum}->{y};
$check_x = $par{data}->{x} > 0 ? '': '-';
$check_y = $par{data}->{y} > 0 ? '': '-';
$par{data}->{x} = sprintf("%0.3f",$par{data}->{x});
$par{data}->{x} = sprintf("%06s",abs($par{data}->{x})*1000);
$par{data}->{y} = sprintf("%0.3f",$par{data}->{y});
$par{data}->{y} = sprintf("%06s",abs($par{data}->{y})*1000);
return 'X'.$check_x.($par{data}->{x}).'Y'.$check_y.($par{data}->{y});
}
=head =head
坐标转换成数值 文件导入设置
=cut =cut
sub change_coode_to_vale sub input_layers {
{
my $string = shift;
$string =~ /X(-?\w+)Y(-?\w+)/;
my $x_data = sprintf("%0.3f",$1/1000);
my $y_data = sprintf("%0.3f",$2/1000);
return {x=>$x_data,y=>$y_data};
}
sub _deleteLayer{
my %par = @_; my %par = @_;
foreach my $layer(@{$par{layer}}){ my $info = $par{info};
$GEN->deleteLayer(layer=>$layer) if ($GEN->isLayerExists(job=>$Job,layer=>$layer)); my @layers = values %{$info->{layer_info}};
foreach my $lyr (@layers) {
next unless ($lyr->{output_flag} =~ /yes/i);
my $name = $info->{output_path}.'/'.$info->{prefix}.'.'.$lyr->{layer_name};
my $layer= lc($info->{prefix}.'.'.$lyr->{layer_name});
$GEN->COM("input_manual_reset");
$GEN->COM("input_manual_set,path=$name,job=$par{job},step=$par{step},format=Excellon2,data_type=ascii,units=mm,coordinates=absolute,zeroes=none,nf1=3,nf2=3,decimal=no,separator=nl,tool_units=mm,layer=$layer,wheel=,wheel_template=,nf_comp=0,multiplier=1,text_line_width=0.0024,signed_coords=no,break_sr=yes,drill_only=no,merge_by_rule=no,threshold=200,resolution=3");
$GEN->COM("input_manual,script_path=");
$GEN->COM("matrix_layer_context,job=$Job,matrix=matrix,layer=$layer,context=misc");
} }
} }
=head =head
输出层新命名 获取工作step
=cut =cut
sub get_new_layer_name sub get_work_step {
{ update_loading("选择工作step...",0,position=>'n');
my $job = shift; my @steps = $GEN->getStepList(job=>$Job);
my @tmp = split/\-/,$job; if ( @steps == 0 ) {
splice(@tmp,2,1); $GUI->msgbox(-icon=>'error',-text=>'在料号中没有Step存在,你将退出!');
$tmp[2] =~ s/2//; return 'Cancel';
unless($tmp[2]){
splice(@tmp,2,1);
} }
my $new = join('-',@tmp); elsif (@steps != 0){
return $new; my @tmp_steps = grep(/$Step/,@steps);
} if ( @tmp_steps == 0 ) {
$GUI->msgbox(-icon=>'warning',-text=>'根据脚本参数过滤出来的step不存在,请检查资料或者脚本参数配置!');
=head return 'Cancel';
短槽拉伸值 slot_size=>,slot_length=>
=cut
sub ger_short_slot_vale
{
my %par = @_;
my $info = {
1.5 =>[
{size_min=>0.4,size_max=>0.55,length=>0,angle=>0},
{size_min=>0.6,size_max=>0.65,length=>0.07,angle=>5},
{size_min=>0.7,size_max=>0.75,length=>0.0625,angle=>4},
{size_min=>0.8,size_max=>0.95,length=>0.05,angle=>2.5},
{size_min=>1.0,size_max=>1.25,length=>0.045,angle=>2},
{size_min=>1.3,size_max=>1.6,length=>0.0375,angle=>1},
{size_min=>1.65,size_max=>2.5,length=>0.0375,angle=>1},
{size_min=>2.55,size_max=>999,length=>0.03,angle=>0.5},
],
1.75 =>[
{size_min=>0.4,size_max=>0.55,length=>0.055,angle=>4},
{size_min=>0.6,size_max=>0.65,length=>0.055,angle=>3},
{size_min=>0.7,size_max=>0.75,length=>0.05,angle=>2.5},
{size_min=>0.8,size_max=>0.95,length=>0.045,angle=>2},
{size_min=>1.0,size_max=>1.25,length=>0.0375,angle=>1},
{size_min=>1.3,size_max=>1.6,length=>0.03,angle=>0.5},
{size_min=>1.65,size_max=>2.5,length=>0.03,angle=>0.5},
{size_min=>2.55,size_max=>999,length=>0.025,angle=>0.5},
],
2.0 =>[
{size_min=>0.4,size_max=>0.55,length=>0.045,angle=>3},
{size_min=>0.6,size_max=>0.65,length=>0.0375,angle=>2},
{size_min=>0.7,size_max=>0.75,length=>0.0375,angle=>1.5},
{size_min=>0.8,size_max=>0.95,length=>0.03,angle=>1},
{size_min=>1.0,size_max=>1.25,length=>0.03,angle=>1},
{size_min=>1.3,size_max=>1.6,length=>0.025,angle=>0.5},
{size_min=>1.65,size_max=>2.5,length=>0.02,angle=>0.5},
{size_min=>2.55,size_max=>999,length=>0.02,angle=>0},
],
};
my $type;
if($par{slot_length}/$par{slot_size} <= 1.5){
$type = 1.5;
}elsif($par{slot_length}/$par{slot_size} > 1.5 and $par{slot_length}/$par{slot_size} <= 1.75){
$type = 1.75;
}elsif($par{slot_length}/$par{slot_size} > 1.75 and $par{slot_length}/$par{slot_size} <= 2){
$type = 2.0;
}elsif($par{slot_length}/$par{slot_size} > 2){
return 0;
} }
my $result; elsif (@tmp_steps == 1) {
foreach my $tmp (@{$info->{$type}}){ $Step = $tmp_steps[0];
if($par{slot_size} >= $tmp->{size_min} and $par{slot_size} <= $tmp->{size_max}){
$result = 1;
return $tmp;
} }
else {
$Step = $GUI->select_step(-title=>'请选择工作 Step',
-steplist=>[@tmp_steps],
-default=>[$tmp_steps[0]],
-gen=>$GEN,
-selectmode=>'single');
return 'Cancel' unless ($Step);
} }
unless ($result){
return 0;
} }
} }
__END__ __END__
...@@ -235,7 +235,6 @@ try { ...@@ -235,7 +235,6 @@ try {
selectmode:'multiple'}); selectmode:'multiple'});
if(tmplayers.length == 0){throw "cancel"} if(tmplayers.length == 0){throw "cancel"}
tmplayers = tmplayers.map(function(v){return v.name}) tmplayers = tmplayers.map(function(v){return v.name})
IKM.msg(tmplayers)
// 创建拼片的辅助层 // 创建拼片的辅助层
GEN.openStep({job:Job,name:Step}); GEN.openStep({job:Job,name:Step});
...@@ -309,15 +308,15 @@ try { ...@@ -309,15 +308,15 @@ try {
// 创建辅助层,返回实际需拼片的层 // 创建辅助层,返回实际需拼片的层
var tmp_layers = tmplayers; var tmp_layers = tmplayers;
tmp_layers = tmp_layers.concat(sold_mask_negative) tmp_layers = tmp_layers.concat(sold_mask_negative)
tmplayers = tmplayers.concat(tmp_layers);
// my @tmp_layers2 = @tmplayers; // my @tmp_layers2 = @tmplayers;
create_tmp_layer({step:Step,layer:tmplayers,matrix:matrix}); create_tmp_layer({step:Step,layer:tmplayers,matrix:matrix});
var film_scheme = {};
var film_scheme;
var index = 1; var index = 1;
tmplayers = tmplayers.concat(tmp_layers)
film_size.forEach(function(filmsize){ film_size.forEach(function(filmsize){
var info = get_repeat_info({step:Step,layer:tmplayers,film_size:filmsize}); var info = get_repeat_info({step:Step,layer:tmplayers,film_size:filmsize});
if(!film_scheme[index]){film_scheme[index] = {}}
film_scheme[index].info = info; film_scheme[index].info = info;
film_scheme[index].film_count = Object.keys(info).length; film_scheme[index].film_count = Object.keys(info).length;
film_scheme[index].film_size = filmsize; film_scheme[index].film_size = filmsize;
...@@ -336,6 +335,7 @@ try { ...@@ -336,6 +335,7 @@ try {
} }
}) })
IKM.msg(3)
film_repeat({step:Step,layer:tmplayers,info:film_scheme[best_scheme_index].info,film_size:film_scheme[best_scheme_index].film_size}); film_repeat({step:Step,layer:tmplayers,info:film_scheme[best_scheme_index].info,film_size:film_scheme[best_scheme_index].film_size});
//画profile //画profile
...@@ -350,7 +350,7 @@ try { ...@@ -350,7 +350,7 @@ try {
change_layers.forEach(function(layer){ change_layers.forEach(function(layer){
GEN.affectedLayer({affected:'yes',mode:'single',layer:layer,clear_before:'yes'}); GEN.affectedLayer({affected:'yes',mode:'single',layer:layer,clear_before:'yes'});
// GEN.selectByFilter(feat_types:'text',polarity:'positive',profile:'all'); // GEN.selectByFilter(feat_types:'text',polarity:'positive',profile:'all');
var tmp_data = GEN.getFeature({job:Job,step:Step,layer:layer,surface:0,options:'feat_index'}); var tmp_data = GEN.getFeatures({job:Job,step:Step,layer:layer,surface:0,options:'feat_index'});
// var tmp_data = GEN.getFeatures(job:Job,step:Step,layer:layer,options:'select'); // var tmp_data = GEN.getFeatures(job:Job,step:Step,layer:layer,options:'select');
var txt_data = tmp_data.filter(function(v){return v.type=="text"}) var txt_data = tmp_data.filter(function(v){return v.type=="text"})
// $GUI->debug(-text:dump(@txt_data,'---',layer,$Step,$Job)); // $GUI->debug(-text:dump(@txt_data,'---',layer,$Step,$Job));
...@@ -541,12 +541,14 @@ function _deleteLayer(layers){ ...@@ -541,12 +541,14 @@ function _deleteLayer(layers){
}) })
} }
function create_tmp_layer(par){ function create_tmp_layer(par){
var matrix = par.matrix; var matrix = par.matrix;
// 先清除原先存在的辅助层 // 先清除原先存在的辅助层
GEN.deleteLayer({job:Job,layer:['~_$'],step:par.step}); Object.keys(matrix).forEach(function(layer){
GEN.deleteLayer({job:Job,layer:['~_tl_angle$'],step:par.step}); if(/_$|_tl_angle$/ig.test(layer)){
GEN.deleteLayer({job:Job,layer:[layer],step:par.step})
}
})
par.layer.forEach(function(layer){ par.layer.forEach(function(layer){
var tmp_layer = layer+'_'; var tmp_layer = layer+'_';
var tmp_layer_angle = layer+'_tl_angle'; var tmp_layer_angle = layer+'_tl_angle';
...@@ -555,7 +557,7 @@ function create_tmp_layer(par){ ...@@ -555,7 +557,7 @@ function create_tmp_layer(par){
GEN.affectedLayer({affected:'yes',layer:[tmp_layer],clear_before:'yes'}); GEN.affectedLayer({affected:'yes',layer:[tmp_layer],clear_before:'yes'});
GEN.selectByFilter({feat_types:'text',profile:'all'}); GEN.selectByFilter({feat_types:'text',profile:'all'});
if ( GEN.getSelectCount() > 0 ){GEN.COM("sel_break")}; if ( GEN.getSelectCount() > 0 ){GEN.COM("sel_break")};
if( matrix[layer].tl_type == 'inner' && matrix[layer].polarity != 'negative' ){ if(matrix[layer] && matrix[layer].tl_type == 'inner' && matrix[layer].polarity != 'negative' ){
var layer_limits = GEN.getLayerLimits({job:Job,step:par.step,layer:layer,units:'inch'}); var layer_limits = GEN.getLayerLimits({job:Job,step:par.step,layer:layer,units:'inch'});
var tmp = 'pos_to_neg_tl'; var tmp = 'pos_to_neg_tl';
GEN.createLayer({job:Job,layer:tmp,context:'board',type:'document',delete_exists:'yes'}); GEN.createLayer({job:Job,layer:tmp,context:'board',type:'document',delete_exists:'yes'});
...@@ -598,7 +600,7 @@ function get_repeat_info(par){ ...@@ -598,7 +600,7 @@ function get_repeat_info(par){
var film_width = tmp_film_size[0],film_height = tmp_film_size[1]; var film_width = tmp_film_size[0],film_height = tmp_film_size[1];
var film_org = PAR.film_name+'-'+film_size; var film_org = PAR.film_name+'-'+film_size;
var film_name=film_org,film_num=0,film_status="old"; var film_name=film_org,film_num=0,film_status="old";
var first_area,last_area,xstart,ystart;//第一张底片的范围/上一张底片的范围 var first_area,last_area={},xstart={},ystart;//第一张底片的范围/上一张底片的范围
par.layer.forEach(function(layer){ par.layer.forEach(function(layer){
var tmp_layer = layer+'_'; var tmp_layer = layer+'_';
film_status = last_area.xmin ? 'old' : 'new' ; film_status = last_area.xmin ? 'old' : 'new' ;
...@@ -631,9 +633,13 @@ function get_repeat_info(par){ ...@@ -631,9 +633,13 @@ function get_repeat_info(par){
// 新底片的准备工作 // 新底片的准备工作
if( film_status == 'new' ){ if( film_status == 'new' ){
film_name = film_org+'-'+film_num; film_name = film_org+'-'+film_num;
if(!info1[film_name]){info1[film_name] = {}}
if(!info1[film_name].layers){info1[film_name].layers = []}
if(!info1[film_name][layer]){info1[film_name][layer] ={shift:{}}}
info1[film_name].layers.push(layer) info1[film_name].layers.push(layer)
info1[film_name].num = film_num; info1[film_name].num = film_num;
info1[film_name].type = 'no_angle'; info1[film_name].type = 'no_angle';
info1[film_name][layer].shift.x = 0; info1[film_name][layer].shift.x = 0;
info1[film_name][layer].shift.y = 0; info1[film_name][layer].shift.y = 0;
xstart.status = 1; xstart.status = 1;
...@@ -654,6 +660,9 @@ function get_repeat_info(par){ ...@@ -654,6 +660,9 @@ function get_repeat_info(par){
//print dump($last_area->{xsize},'--',layer_limits.xsize,'--',film_width),"\n"; //print dump($last_area->{xsize},'--',layer_limits.xsize,'--',film_width),"\n";
//print dump(@{$info{$film_name}{layers}}),"\n"; //print dump(@{$info{$film_name}{layers}}),"\n";
//GEN.PAUSE('tttt++'.$layer); //GEN.PAUSE('tttt++'.$layer);
if(!info1[film_name]){info1[film_name] = {}}
if(!info1[film_name].layers){info1[film_name].layers = []}
if(!info1[film_name][layer]){info1[film_name][layer] ={shift:{}}}
info1[film_name].layers.push(layer); info1[film_name].layers.push(layer);
info1[film_name][layer].shift.x = 0; info1[film_name][layer].shift.x = 0;
info1[film_name][layer].shift.y = last_area.ymax-layer_limits.ymin; info1[film_name][layer].shift.y = last_area.ymax-layer_limits.ymin;
...@@ -671,6 +680,9 @@ function get_repeat_info(par){ ...@@ -671,6 +680,9 @@ function get_repeat_info(par){
} }
// X方向添加 // X方向添加
else{ else{
if(!info1[film_name]){info1[film_name] = {}}
if(!info1[film_name].layers){info1[film_name].layers = []}
if(!info1[film_name][layer]){info1[film_name][layer] ={shift:{}}}
info1[film_name].layers.push(layer); info1[film_name].layers.push(layer);
info1[film_name][layer].shift.x = last_area.xmax-layer_limits.xmin; info1[film_name][layer].shift.x = last_area.xmax-layer_limits.xmin;
info1[film_name][layer].shift.y = xstart.status ? xstart.shifty : last_area.ymax-last_area.xmin; info1[film_name][layer].shift.y = xstart.status ? xstart.shifty : last_area.ymax-last_area.xmin;
...@@ -696,7 +708,7 @@ function get_repeat_info(par){ ...@@ -696,7 +708,7 @@ function get_repeat_info(par){
var info2 = {}; var info2 = {};
film_org = PAR.film_name+'-'+film_size; film_org = PAR.film_name+'-'+film_size;
film_name = film_org,film_num=0,film_status="old"; film_name = film_org,film_num=0,film_status="old";
first_area=undefined,last_area=undefined,xstart=undefined,ystart=undefined;//第一张底片的范围/上一张底片的范围 first_area={},last_area={},xstart={},ystart={};//第一张底片的范围/上一张底片的范围
par.layer.forEach(function(layer){ par.layer.forEach(function(layer){
var tmp_layer = layer+'_tl_angle'; var tmp_layer = layer+'_tl_angle';
film_status = last_area.xmin ? 'old' : 'new' ; film_status = last_area.xmin ? 'old' : 'new' ;
...@@ -717,7 +729,7 @@ function get_repeat_info(par){ ...@@ -717,7 +729,7 @@ function get_repeat_info(par){
else if( layer_limits.xsize > film_width ){ else if( layer_limits.xsize > film_width ){
film_status = 'new' ;//if ( ($last_area->{ymax}+ layer_limits.ysize) > $film_height ); film_status = 'new' ;//if ( ($last_area->{ymax}+ layer_limits.ysize) > $film_height );
} }
else if( layer_limits.ysize > $film_height ){ else if( layer_limits.ysize > film_height ){
film_status = 'new' ;//if ( ($last_area->{xmax}+ layer_limits.xsize) > film_width ); film_status = 'new' ;//if ( ($last_area->{xmax}+ layer_limits.xsize) > film_width );
} }
else{ else{
...@@ -729,6 +741,9 @@ function get_repeat_info(par){ ...@@ -729,6 +741,9 @@ function get_repeat_info(par){
//新底片的准备工作 //新底片的准备工作
if( film_status == 'new' ){ if( film_status == 'new' ){
film_name = film_org+'-'+film_num; film_name = film_org+'-'+film_num;
if(!info2[film_name]){info2[film_name] = {}}
if(!info2[film_name].layers){info2[film_name].layers = []}
if(!info2[film_name][layer]){info2[film_name][layer] ={shift:{}}}
info2[film_name].layers.push(layer) info2[film_name].layers.push(layer)
info2[film_name].num = film_num; info2[film_name].num = film_num;
info2[film_name].type = 'angle'; info2[film_name].type = 'angle';
...@@ -752,6 +767,9 @@ function get_repeat_info(par){ ...@@ -752,6 +767,9 @@ function get_repeat_info(par){
//print dump($last_area->{xsize},'--',layer_limits.xsize,'--',film_width),"\n"; //print dump($last_area->{xsize},'--',layer_limits.xsize,'--',film_width),"\n";
//print dump(@{$info{$film_name}{layers}}),"\n"; //print dump(@{$info{$film_name}{layers}}),"\n";
//GEN.PAUSE('tttt++'.$layer); //GEN.PAUSE('tttt++'.$layer);
if(!info2[film_name]){info2[film_name] = {}}
if(!info2[film_name].layers){info2[film_name].layers = []}
if(!info2[film_name][layer]){info2[film_name][layer] ={shift:{}}}
info2[film_name].layers.push(layer); info2[film_name].layers.push(layer);
info2[film_name][layer].shift.x = 0; info2[film_name][layer].shift.x = 0;
info2[film_name][layer].shift.y = last_area.ymax-layer_limits.ymin; info2[film_name][layer].shift.y = last_area.ymax-layer_limits.ymin;
...@@ -769,7 +787,9 @@ function get_repeat_info(par){ ...@@ -769,7 +787,9 @@ function get_repeat_info(par){
} }
//#X方向添加 //#X方向添加
else{ else{
if(!info2[film_name]){info2[film_name] = {}}
if(!info2[film_name].layers){info2[film_name].layers = []}
if(!info2[film_name][layer]){info2[film_name][layer] ={shift:{}}}
info2[film_name].layers.push(layer); info2[film_name].layers.push(layer);
info2[film_name][layer].shift.x = last_area.xmax-layer_limits.xmin; info2[film_name][layer].shift.x = last_area.xmax-layer_limits.xmin;
info2[film_name][layer].shift.y = xstart.status ? xstart.shifty : last_area.ymax-last_area.xmin; info2[film_name][layer].shift.y = xstart.status ? xstart.shifty : last_area.ymax-last_area.xmin;
......
/*
NAME:
DESCRIPTION: 锣带输出;
PARAMETER:
[
{
name : 'Outpath',
title : '导出路径',
type : 'LineEdit',
property : {tool_tip : '导出路径'},
},
{
name : 'step',
title : '工作step',
type : 'LineEdit',
property : {tool_tip : '工作step'},
},
{
name : 'auto_save',
title : '自动保存',
type : 'RadioBox',
property : {
item_list:[
{name:'yes',text:'YES'},
{name:'no',text:'NO'},
],
tool_tip:'是否自动保存料号开关'
}
}
]
VERSION_HISTORY:
V1.00 2020-09-01 Scott Sun
1.新版本
HELP:
<html><body bgcolor="#DDECFE">
<font size="3" color="#003DB2"><p>功能简介</p></font>
<p> 锣带输出 </p>
<br>
<font size="3" color="#003DB2"><p>参数配置</p></font>
<p> step信息 </p>
<br>
<font size="3" color="#003DB2"><p>注意事项</p></font>
<p> 无 </p>
<br>
</body></html>
*/
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
console.log("==============================>template");
// 引入模块 包
var $ = require('topcam.scriptfunc').argv();
var fs = require('fs');
var _ = require('lodash');
var mode = $.ikm ? "topcam" : "aimdfm";
var IKM = $.ikm;
if (IKM==undefined ) { IKM = require('topcam.ikm6')($) }
var GEN = $.gen;
var GUI = $.gui || {};
var Job = $.job || $.job_name;
var JobId = $.job_id;
var db = $.db || IKM.db
var PAR = {}
if ($.par) { PAR = $.par } else if ($.hasOwnProperty('script_parameter')){ PAR = JSON.parse($.script_parameter); }
if (mode === "aimdfm") {
var database = require("topsin.database");
database.addConnection($.conf.database_conf, "DFM");
var QDfm = database.query("DFM");
$.QDfm = QDfm;
if ($.conf.product_type == "aimdfm") {
QDfm.updateRow({ table: "pdm_aimdfm_task", data: { current_process_title: $.process_title }, where: { id: $.task_id } });
}
}
require("topsin.genmath")
var genMath = new GenMath();
var gui = new NewGUI(GUI);
var Status = 'ok';
var resultData = [];
var par = PAR;
var default_par = {
Outpath:"C:/Users/Administrator/Desktop/jobs/demo",
auto_save: "No",
step:"step",
units:"mm"
}
for(var key in default_par){ if (!par.hasOwnProperty(key) || par[key] == ""){ par[key] = default_par[key] }}
var job = Job;
var Step;
var rou_layer = [];
try {
if(_.isEmpty(job)){throw "参数job不存在"} else { job = job.toLowerCase() }
if(!GEN.isJobExists({job:job})){throw "料号"+job+"不存在"}
// 选择工作step
var workstep = getWorkStep()
if(workstep.length == 0){throw "未找到工作step"}
workstep.forEach(function(step){
Step = 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:'mm'} );
GEN.zoomHome();
var matrix = GEN.getMatrix({job:Job});
Object.keys(matrix).forEach(function(layer){
if(matrix[layer].context && matrix[layer].context == 'board' ){
if(matrix[layer].layer_type == 'rout'){
rou_layer.push(layer)
}
}
})
if(rou_layer.length) {
var info = confirm_gui({layers:rou_layer});
output_rou({job:Job,step:step,info:info});
input_layers({job:Job,step:step,info:info});
}
})
// 保存
if(/yes/ig.test(par.auto_save)){GEN.checkInout({job:job,mode:"out"}); GEN.saveJob({ job: job });GEN.checkInout({job:job,mode:"in"});GEN.closeJob({job:job});} else {GEN.checkInout({job:job,mode:"in"})}
if (mode === "aimdfm") {
$.QDfm.updateRow({table: "pdm_aimdfm_task",data: {progress: 33.33},where: { id: $.task_id }});
if (GEN.hasError()) { Status = 'error';resultData.push({ type: "error", title: "GEN错误!", detail: [{ desc: _.join(GEN.STATUS, "\n") }] });
return {status: Status,result_data: resultData};
} else { resultData.push({ type: "info", title: "操作完成, 请注意检查!" }); return {status: Status,result_data: resultData}; }
}else { return "Done" }
} catch (e) {
IKM.msg(_.join(GEN.STATUS, "\n"));IKM.msg(e);Status = 'error';
resultData.push({type: "error", title: "脚本执行出错!", detail: [{desc: _.toString(e)}]});
return (mode === "aimdfm") ? {status: Status, result_data: resultData} : "Error";
}
function NewGUI (gui) {
this.msgBox = function(props){ // title type content button
props = props || {}
return gui.msgBox(props.title || "title",props.type || "info",props.content || "content",props.button || ["ok", "cancel"]);
}
this.selectFromTreeview = gui.selectFromTreeview
this.selectFile = function(props){ // "choose something", "*", true, "file", "/home/abby/fast_io"
props = props || {}
return gui.selectFile(props.title || "choose something",props.filter || "*",props.multiple || false, "file","");
}
this.selectSingle = function(props) {
props = props || {}
return gui.selectSingle({
"title": props.title || "select",
"list": props.list || [],
"default": props["default"] || "",
"columns": props.columns || 2,
"gen":props.gen || GEN
});
}
this.selectMultiple = function(props) {
props = props || {}
return gui.selectMultiple({
"title": props.title || "select",
"list": props.list || [],
"defaultvalue": props["defaultvalue"] || [""],
"defaultsize": props["defaultsize"] || [200, 100],
"columns": props.columns || 2,
"gen":props.gen || GEN
});
}
this.selectFromTable = gui.selectFromTable
this.snapScreen = gui.snapScreen
this.imageViewer = gui.imageViewer
this.inputBox = gui.inputBox
this.showForm = gui.showForm
this.lockUnlockLayer = function(props){
props = props || {}
var tmp = {}
if (props.matrix) {
for (var key in props.matrix) {
var item = props.matrix[key]
tmp[key] = {
row : item.row,
name : item.name
}
}
}
return gui.lockUnlockLayer({
title: props.title || "lockUnlockLayer",
layermatrix:props.layermatrix || tmp
})
}
this.passwordBox = function(props){
props = props || {}
return gui.passwordBox({title:props.title || "password", password:props.password || "1212"})
}
this.selectJobLayer = function (props) {
props = props || {}
return gui.selectJobLayer({
layertypelist: props.layertypelist || [
{name: "all", display_name: "all", filter: function(x) { return x }},
{name: "signal", display_name: "signal", filter: function(x) { return x["layer_type"] === "signal"; }},
{name: "power_ground", display_name: "power_ground", filter: function(x) { return x["layer_type"] === "power_ground"; }},
{name: "mixed", display_name: "mixed", filter: function(x) { return x["layer_type"] === "mixed"; }},
{name: "solder_mask", display_name: "solder_mask", filter: function(x) { return x["layer_type"] === "solder_mask"; }},
{name: "silk_screen", display_name: "silk_screen", filter: function(x) { return x["layer_type"] === "silk_screen"; }},
{name: "solder_paste", display_name: "solder_paste", filter: function(x) { return x["layer_type"] === "solder_paste"; }},
{name: "drill", display_name: "drill", filter: function(x) { return x["layer_type"] === "drill"; }},
{name: "rout", display_name: "rout", filter: function(x) { return x["layer_type"] === "rout"; }},
{name: "document", display_name: "document", filter: function(x) { return x["layer_type"] === "document"; }}
],
//defaultlayertype: "ha",
joblist: props.joblist || [],
defaultJob: props.defaultJob || [], // select by default
steplist: props.steplist || [],
// defaultstep: "step3",
showstep: props.showstep || true,
selectmode: props.selectmode || "multiple", // single/multiple
layermatrix: props.layermatrix || { },
defaultlayer: props.defaultlayer || []
})
}
}
function getWorkStep(props){
var steplists = GEN.getStepList({job:job});
if(steplists.length == 0){return "该料号没有step"}
var steps_tmp = steplists.filter(function(name){
var reg = new RegExp(par.step, "ig")
return reg.test(name)
})
if(steplists.length == 0){return "根据脚本参数过滤出来的step不存在,请检查资料或者脚本参数配置!"}
var workstep = gui.selectMultiple({
title: "请先择工作step",
size:[200,100],
defaultsize:[200,100],
list: steplists.map(function(v){ var tmp = {}; tmp[v] = v ;return tmp}),
defaultvalue: steps_tmp,
columns: 1,
gen: GEN
})
if(workstep.length == 0 ) {return "没有先择step"}
return workstep
}
// rou输出
function output_rou(par) {
var info = par.info;
// var PL = GEN.getProfileLimits({job:Job,step:Step,units:'mm'});
var nc_set = 'zda';
var machine = 'sintai_excellon';
var layers = [];
for (var key in info.layer_info) {
layers.push(info.layer_info[key])
}
layers.forEach(function(layer){
if(/^yes$/i.test(layer.output_flag)){
if(GEN.getNcsetsList({job:Job,step:Step,layer:layer.layer_name}).indexOf(nc_set) >= 0) {
GEN.COM('ncrset_delete',{name:nc_set});
}
GEN.COM('ncrset_cur',{job:Job,step:Step,layer:layer.layer_name,ncset:nc_set});
GEN.COM('ncr_set_machine',{machine:machine,thickness:0});
GEN.COM('ncr_register',{angle:0,mirror:layer.is_mirror,xoff:0,yoff:0,version:1,xorigin:0,yorigin:0,xscale:layer.scale_x,yscale:layer.scale_y,xscale_o:0,yscale_o:0});
GEN.COM('ncr_cre_rout');
GEN.COM('ncr_ncf_export',{dir:info.output_path,name:layer.layer_name});
GEN.COM('ncrset_delete',{name:nc_set});
}
})
}
// 用户配置参数
function confirm_gui(par) {
var rows={},n=0;
// var cam = IKM.get_jobinfo({jobname:Job,jobid:JobId,jobcategory:'work',jobinfo:'cam_serial_number',withspec:1});
var folder = 'rou';
var path = PAR.Outpath+"/"+folder;
fs.mkdir(path)
par.layers.forEach(function(layer){
n++;
rows[n] = {};
rows[n].sequence = n;
rows[n].layer_name = layer;
rows[n].scale_x = 1;
rows[n].scale_y = 1;
rows[n].output_flag = 'Yes';
rows[n].is_mirror = 'no';
})
rows.output_path = path;
// var v_data = GUI.showForm({
// title:"Rou输出参数确认单",
// defaultsize:[520,500],
// items: [
// {
// type : 'title',
// property:{
// title:'输出料号和名称',
// },
// n_columns:2,
// },
// {
// type : 'title',
// property:{
// title:'参数确认',
// },
// n_columns:8,
// },
// {
// name : 'layer_info',
// label :'参数确认',
// label_position : 'no',
// "class" : 'TL::Gtk2::TableFormPanel',
// expand : 1,
// property : {
// tl_columns :[
// {
// column_name:'layer_name',
// label:'层别名称',
// width:100,
// type:'label',
// },
// {
// column_name:'scale_x',
// label:'涨缩值X',
// width:80,
// type:'number',
// must_field:1,
// },
// {
// column_name:'scale_y',
// label:'涨缩值Y',
// width:80,
// type:'number',
// must_field:1,
// },
// {
// column_name:'output_flag',
// label:'是否输出',
// width:80,
// type:'radio',
// property:{
// tl_columns : 2,
// tl_list : [{'Yes' : '是'}, {'No':'否'}],
// },
// },
// {
// column_name:'is_mirror',
// label:'是否镜像',
// width:80,
// type:'radio',
// property:{
// tl_columns : 2,
// tl_list : [{'yes' : '是'}, {'no':'否'}],
// },
// }
// ],
// tl_rows:rows,
// },
// set_value_func : function(par){
// var data = par.value;
// Object.keys(data).forEach(function(row_name){
// Object.keys(data[row_name]).forEach(function(col_name){
// par.widget.set_value(row_name,col_name,data[row_name][col_name]);
// })
// })
// },
// get_value_func : function(par){return par.widget.get_all_value();},
// },
// {
// type : 'title',
// property:{
// title:'输出设置',
// },
// n_columns:1,
// },
// {
// name : 'username',
// label : '输出者:',
// type : 'string',
// value:GEN.getUserName(),
// width:100,
// must_field:1,
// },
// {
// name : 'output_path',
// label : '输出路径:',
// type : 'string',
// value:path,
// width:100,
// must_field:1,
// property : {
// editable:0,
// },
// buttons : [
// {
// name:'btn1',label:'选择路径',stock:'gtk-add',
// command:function(par){
// var folder = GUI.select_file({title:'选择路径',type:'select-folder',defaultdir:PAR.Outpath});
// if(!folder){return}
// p.formpanel.set_value('output_path', folder);
// }
// },
// ],
// },
// ]
// });
return rows;
}
// 文件导入设置
function input_layers(par) {
var info = par.info;
var layers = [];
for (var key in info.layer_info) {
layers.push(info.layer_info[key])
}
layers.forEach(function(lyr){
if(/yes/i.test(lyr.output_flag)){
var name = info.output_path+'/'+lyr.layer_name;
var layer= lyr.layer_name.toLowerCase();
GEN.COM("input_manual_reset");
GEN.COM("input_manual_set,path="+name+",job="+par.job+",step="+par.step+
",format=Excellon2,data_type=ascii,units=mm,coordinates=absolute,zeroes=none,nf1=3,nf2=3,decimal=no,separator=nl,tool_units=mm,layer="+layer
+",wheel=,wheel_template=,nf_comp=0,multiplier=1,text_line_width=0.0024,signed_coords=no,break_sr=yes,drill_only=no,merge_by_rule=no,threshold=200,resolution=3");
GEN.COM("input_manual,script_path=");
GEN.COM("matrix_layer_context,job="+par.job+",matrix=matrix,layer="+layer+",context=misc");
}
})
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment