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++
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
|