You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

363 lines
11 KiB
C++

#include "StdAfx.h"
#include "ObjFillMgr.h"
#include "CommandArray.h"
#include "CommandMgr.h"
#include "Layer.h"
#include "MsgBox.h"
#include "ObjPline.h"
#include "FileMgr.h"
#include "PenParMgr.h"
#include "Laser.h"
#include "ProgramLaserTuiHuo.h"
#include "WaferRecipeDataMgr.h"
#include "RecipeMgr.h"
#include "WorkRecord.h"
#include "LogMgr.h"
#if 1
CObjFillMgr gObjFillMgr;
CObjFillMgr::CObjFillMgr(void)
{
m_FillOffset = 1;//填充间隔mm
m_FillAngle = 90;//填充角度(360 角)
m_bDelEdgeObj = false;//是否删除轮廓obj
m_bCreatConnectLine = true;//是否创建连接线
m_CurScanType = _SCAN_TRACK_S_L_R;//当前的扫描方式
m_StartFillIdx = 0;//从第几根填充线开始
}
CObjFillMgr::~CObjFillMgr(void)
{
}
//更新扫描方式
void CObjFillMgr::UpdateCurScanType()
{
int WaferScanType = gProgramLaserTuiHuo->GetWaferScanType();
if(WaferScanType>=0&&WaferScanType<8)
{
m_CurScanType = (SCAN_TRACK_E)WaferScanType;
CString log;
log.Format("Func--->UpdateCurScanType = %ld",WaferScanType);
gLogMgr->WriteDebugLog(log);
}
}
//创建选择对象的填充数据
void CObjFillMgr::FillAllSelObj()
{
//所有obj 左旋转90 度(为了生成横向的扫描线)
if(gLaser->IsbScanByDirX())
gLayer.Rotato(90);
//更新扫描方式
UpdateCurScanType();
//初始化
m_ObjContainer.Clear();
m_ScanLineVec.clear();
//通过填充obj 来创建扫描线(保存在m_ScanLineVec)
if(!CreatScanLineByObjFill())
return;
//通过扫描线来创建obj
CreatObjByScanLine();
//将填充线添加到layer
FillObjAddToLayer();
//所有obj 右旋转90度
if(gLaser->IsbScanByDirX())
gLayer.Rotato(-90);
}
void CObjFillMgr::FillObjAddToLayer()
{
CObjContainer &ObjContainer = gLayer.GetObjContainer();
m_ObjContainer.AllObjAddToContainer(ObjContainer,false);
}
//创建索引号为idx 的obj 的填充
void CObjFillMgr::FillAllSelObjByIdx(int idx)
{
CObjContainer &ObjContainer = gLayer.GetObjContainer();
ObjContainer.NotSelAllObj();
}
//创建指令
void CObjFillMgr::CreatCmd()
{
if(!m_ObjContainer.Empty())
{
//创建撤销指令-------start
CCommandArray *pCmd = new CCommandArray;
gCommandMgr.AddUndoCommand(pCmd,m_ObjContainer.GetObjVec());
//删除轮廓obj
if(m_bDelEdgeObj)
{
pCmd->SaveBaseObj(gLayer.GetObjContainer());
}
//创建撤销指令-------end
pCmd->Excute();
}
}
//创建填充数据
void CObjFillMgr::CreatObjFillData(CObjContainer &ObjContainer)
{
SFillPar FillPar;
FillPar.m_FillAngle = m_FillAngle;
FillPar.bFill = true;
FillPar.m_FillGap = m_FillOffset;
ObjContainer.FillObj(FillPar,false);
}
//通过填充obj 来创建扫描线
bool CObjFillMgr::CreatScanLineByObjFill()
{
CObjContainer &ObjContainer = gLayer.GetObjContainer();
//创建填充数据
CreatObjFillData(ObjContainer);
//利用obj 填充算法来画出填充线-----------------------------
vector<Sptr<CObjBase>> &ObjVec = ObjContainer.GetObjVec();
vector<Sptr<CObjBase>>::iterator iter = ObjVec.begin();
vector<Sptr<CObjBase>>::iterator iter_end = ObjVec.end();
int idx = 0;
bool bNeedCloseLaser = true;//扫描不同区域是否需要关闭激光
vector<CScanLine> ScanLineVecTmp;
for(;iter!=iter_end;iter++,idx++)
{
ScanLineVecTmp.clear();
int CurPenNum = idx;//笔号设置为obj 的序列号
if(!(*iter)->IsbFillObj() && (*iter)->IsSelected())//过滤掉填充obj
{
vector<vector<Dbxy>> FillDataVec;
(*iter)->GetFillData(FillDataVec);
bool DirFlg = false;//反向标示
vector<vector<Dbxy>>::iterator iter1 = FillDataVec.begin();
vector<vector<Dbxy>>::iterator iter1_end = FillDataVec.end();
for(;iter1!=iter1_end;iter1++)
{
int size = (*iter1).size();
int idx1 = (DirFlg)?1:0;
int idx2 = (DirFlg)?0:1;
DirFlg = !DirFlg;//反向
Dbxy pt1 = (*iter1)[idx1];
Dbxy pt2 = (*iter1)[idx2];
if(size==2)
{
CScanLine ScanLine(pt1,pt2);//创建一条线
ScanLine.SetPenNum(CurPenNum);
ScanLineVecTmp.push_back(ScanLine);
}
}
//S 形排序-从下到上,从右到左需要逆序
SCAN_TRACK_E ScanTrack = m_CurScanType;
if(ScanTrack == _SCAN_TRACK_S_D_U ||ScanTrack == _SCAN_TRACK_S_R_L)
{
reverse(ScanLineVecTmp.begin(),ScanLineVecTmp.end());
}
vector<CScanLine>::iterator iter2 = ScanLineVecTmp.begin();
vector<CScanLine>::iterator iter2_end = ScanLineVecTmp.end();
bool bFirst = true;//标记第一条line
for(;iter2!=iter2_end;iter2++)
{
if(bFirst && bNeedCloseLaser)
{
(*iter2).SetbFirstLine();
bFirst = false;
}
m_ScanLineVec.push_back(*iter2);
}
}
}
if(!m_ScanLineVec.empty())
{
m_ScanLineVec[0].SetbFirstLine();//第一个对象强行设置
}
//调整扫描线,使扫描路径可以覆盖到晶圆
AdjustScanLine1();
//清空填充线
SFillPar FillPar;
FillPar.bFill = false;
ObjContainer.FillObj(FillPar,false);
return true;
}
//调整扫描线,使扫描路径可以覆盖到晶圆
void CObjFillMgr::AdjustScanLine1()
{
vector<CScanLine>::iterator iter = m_ScanLineVec.begin();
vector<CScanLine>::iterator iter_end = m_ScanLineVec.end();
for(;iter!=iter_end;iter++)
{
Dbxy StartPt = (*iter).GetStartPt();
Dbxy EndPt = (*iter).GetEndPt();
Dbxy pt1 = StartPt;
Dbxy pt2 = StartPt;
Dbxy pt3 = EndPt;
Dbxy pt4 = EndPt;
int PenNum = (*iter).GetPenNum();
double FillAngle;
GetAngle(FillAngle,PenNum);
if(FillAngle>0)
{
if(pt1.y>pt3.y)
{
ScanLineCoverWafer(pt1,pt2,true,PenNum);
ScanLineCoverWafer(pt3,pt4,false,PenNum);
}
else
{
ScanLineCoverWafer(pt3,pt4,true,PenNum);
ScanLineCoverWafer(pt1,pt2,false,PenNum);
}
StartPt.y = pt1.y;
EndPt.y = pt3.y;
}
else
{
if(pt1.x>pt3.x)
{
ScanLineCoverWafer(pt1,pt2,true,PenNum);
ScanLineCoverWafer(pt3,pt4,false,PenNum);
}
else
{
ScanLineCoverWafer(pt3,pt4,true,PenNum);
ScanLineCoverWafer(pt1,pt2,false,PenNum);
}
StartPt.x = pt1.x;
EndPt.x = pt3.x;
}
(*iter).SetStartPt(StartPt);
(*iter).SetEndPt(EndPt);
}
}
//调整扫描线覆盖住晶圆bDir 是调整方向
void CObjFillMgr::ScanLineCoverWafer(Dbxy &pt1,Dbxy &pt2,bool bDir,int PenNum)
{
//边缘划出距离
double Offset = 0;
if(Offset<=0)//等于0 会死循环
Offset = 0.05;
if(!bDir)
Offset*=-1;
double FillAngle;
GetAngle(FillAngle,PenNum);
while(gLayer.HasObjIntersectWithLine(DbLine(CDataPoint(pt1),CDataPoint(pt2))))
{
//只对晶圆边缘的点进行调整
if(FillAngle>0)
{
pt1.y += Offset;
pt2.y += Offset;
}
else
{
pt1.x += Offset;
pt2.x += Offset;
}
}
}
//调整每一行的end 点,和下一行的start 点比较,取X 为离晶圆较远的点
void CObjFillMgr::AdjustScanLine2()
{
int size = m_ScanLineVec.size();
for(int i=0;i<size-1;i++)
{
Dbxy EndPt = m_ScanLineVec[i].GetEndPt();
Dbxy NextStartPt = m_ScanLineVec[i+1].GetStartPt();
double FillAngle;
GetAngle(FillAngle,m_ScanLineVec[i].GetPenNum());
double *pVal1 = (FillAngle>0)?(&(EndPt.y)):(&(EndPt.x));
double *pVal2 = (FillAngle>0)?(&(NextStartPt.y)):(&(NextStartPt.x));
if(abs(*pVal1)<abs(*pVal2))
{
*pVal1 = *pVal2;
m_ScanLineVec[i].SetEndPt(EndPt);
}
else
{
*pVal2 = *pVal1;
m_ScanLineVec[i+1].SetStartPt(NextStartPt);
}
}
}
//通过扫描线来创建obj
void CObjFillMgr::CreatObjByScanLine()
{
//CScanState &ScanState = gWorkRecordMgr->GetCurScanState();
//int EndScanLineIdx = ScanState.m_EndScanLineIdx;
int size = m_ScanLineVec.size();
Dbxy PerPt;
int ScanLineIdx = 0;
for(int i=0;i<size;i++)
{
Dbxy StartPt = m_ScanLineVec[i].GetStartPt();
Dbxy EndPt = m_ScanLineVec[i].GetEndPt();
SCAN_TRACK_E ScanTrack = m_CurScanType;
if(ScanTrack == _SCAN_TRACK_U_D)//单向扫描-上到下
{
if(StartPt.y < EndPt.y)
swap(StartPt,EndPt);
}
if(ScanTrack == _SCAN_TRACK_D_U)//单向扫描-下到上
{
if(StartPt.y > EndPt.y)
swap(StartPt,EndPt);
}
if(ScanTrack == _SCAN_TRACK_R_L)//单向扫描-左到右
{
if(StartPt.x < EndPt.x)
swap(StartPt,EndPt);
}
if(ScanTrack == _SCAN_TRACK_L_R)//单向扫描-右到左
{
if(StartPt.x > EndPt.x)
swap(StartPt,EndPt);
}
//bool bScaned = (EndScanLineIdx>0 && ScanLineIdx<=EndScanLineIdx);
bool bScaned = false;
PerPt = EndPt;
CObjPline *pObjPline = new CObjPline;
pObjPline->SetbFillObj(true);//标记为填充对象
pObjPline->SetPenNum(m_ScanLineVec[i].GetPenNum());
pObjPline->Creat(StartPt,EndPt);
//标记被扫描过的线段
pObjPline->SetbScaned(bScaned);
if(ScanLineIdx>=m_StartFillIdx)
m_ObjContainer.AddObject(pObjPline);
//扫描线段
ScanLineIdx++;
}
}
//根据扫描模式获取角度,并返回是否横向扫描
bool CObjFillMgr::GetAngle(double &Angle,int PenNum)
{
SCAN_TRACK_E ScanTrack = m_CurScanType;
bool bhorizontal = false;
if(ScanTrack == _SCAN_TRACK_S_U_D || ScanTrack == _SCAN_TRACK_S_D_U|| ScanTrack == _SCAN_TRACK_L_R|| ScanTrack == _SCAN_TRACK_R_L)
{
bhorizontal = true;
Angle = 0;
}
else if(ScanTrack == _SCAN_TRACK_S_L_R || ScanTrack == _SCAN_TRACK_S_R_L|| ScanTrack == _SCAN_TRACK_U_D|| ScanTrack == _SCAN_TRACK_D_U)
{
Angle = 90;
}
return bhorizontal;
}
#endif