// Glass.cpp: implementation of the CGlass class.
|
//
|
//////////////////////////////////////////////////////////////////////
|
|
#include "stdafx.h"
|
#include "Glass_Data.h"
|
#include <math.h>
|
|
#ifndef M_PI
|
#define M_PI 3.14159265358979323846
|
#endif
|
|
#ifdef _DEBUG
|
#undef THIS_FILE
|
static char THIS_FILE[]=__FILE__;
|
#define new DEBUG_NEW
|
#endif
|
|
//////////////////////////////////////////////////////////////////////
|
// Construction/Destruction
|
//////////////////////////////////////////////////////////////////////
|
|
CGlass_Data::CGlass_Data(void)
|
{
|
m_pGlassRecipe = NULL;
|
m_pHardwareSetting = NULL;
|
m_nStageNo = 0;
|
m_bSimulation = FALSE;
|
|
ResetGlass();
|
}
|
|
CGlass_Data::~CGlass_Data()
|
{
|
ResetDefect();
|
}
|
|
void CGlass_Data::ResetDefect()
|
{
|
HANDLE hThread = GetCurrentThread();
|
CSingleLock localLock(&m_csGlassDefect);
|
localLock.Lock();
|
SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST);
|
|
m_nCurDefectIdx_NG = 0;
|
m_nCurDefectIdx_OK = 0;
|
m_nJudgeDefectCount = 0;
|
m_nCurDefectIdx_Total = 0;
|
|
CDefect* pData;
|
for (MapDefectIt it = m_MapDefect_NG.begin(); it != m_MapDefect_NG.end(); it++)
|
{
|
pData = static_cast<CDefect*> (it->second);
|
delete pData;
|
pData = NULL;
|
}
|
m_MapDefect_NG.clear();
|
|
for (MapDefectIt it = m_MapDefect_OK.begin(); it != m_MapDefect_OK.end(); it++)
|
{
|
pData = static_cast<CDefect*> (it->second);
|
delete pData;
|
pData = NULL;
|
}
|
m_MapDefect_OK.clear();
|
|
SetThreadPriority(hThread, THREAD_PRIORITY_NORMAL);
|
localLock.Unlock();
|
}
|
|
void CGlass_Data::ResetGlass()
|
{
|
ResetDefect();
|
|
m_strLoadingTime = _T("");
|
m_strUnloadingTime = _T("");
|
m_strScanStartTime = _T("");
|
m_strScanEndTime = _T("");
|
m_bPostProcessing = FALSE;
|
|
for(int i=0; i<MAX_DIMENSION_COUNT; i++)
|
m_SideData[i].Reset();
|
|
ZeroMemory(m_nStageLongTheta,sizeof(short)*2);
|
ZeroMemory(m_nStageShortTheta,sizeof(short)*2);
|
ZeroMemory(m_bScanEnd,sizeof(m_bScanEnd));
|
m_bScanStart = FALSE;
|
m_nStartCount = 0;
|
ZeroMemory(m_bScanEndCamera,sizeof(m_bScanEndCamera));
|
|
m_bInspectComplete = FALSE;
|
m_bJudgeNG = FALSE;
|
}
|
|
void CGlass_Data::SetScanStart(BOOL bStart)
|
{
|
m_bScanStart = bStart;
|
}
|
|
void CGlass_Data::SetScanEnd(int nScanIdx,BOOL bIsEnd)
|
{
|
m_bScanEnd[nScanIdx] = bIsEnd;
|
}
|
|
BOOL CGlass_Data::GetScanEnd(int nScanIdx)
|
{
|
return m_bScanEnd[nScanIdx];
|
}
|
|
int CGlass_Data::GetScanEndCameraCount()
|
{
|
int nCount = 0;
|
|
CSingleLock sLock(&m_csInsEnd);
|
sLock.Lock();
|
for(int iCam=0;iCam<MAX_CAMERA_COUNT;iCam++)
|
{
|
for(int iScan=0;iScan<MAX_SCAN_COUNT;iScan++)
|
{
|
if(m_bScanEndCamera[iCam][iScan] == TRUE)
|
nCount++;
|
}
|
}
|
sLock.Unlock();
|
|
return nCount;
|
}
|
|
void CGlass_Data::SetScanEndCamera(int iCam,int iScan)
|
{
|
CSingleLock sLock(&m_csInsEnd);
|
sLock.Lock();
|
m_bScanEndCamera[iCam][iScan] = TRUE;
|
sLock.Unlock();
|
}
|
|
void CGlass_Data::SetStageNo(int nStageNo)
|
{
|
if(nStageNo < 0 || MAX_STAGE_HAND_COUNT <= nStageNo)
|
return;
|
|
nStageNo = nStageNo;
|
}
|
|
CDefect* CGlass_Data::GetDefect_NG(int nDefecIdx)
|
{
|
CDefect *pDefect = NULL;
|
|
for(MapDefectIt it=m_MapDefect_NG.begin();it!=m_MapDefect_NG.end();it++)
|
{
|
if (m_nCurDefectIdx_NG > 0)
|
{
|
pDefect = static_cast<CDefect*>(it->second);
|
if (pDefect != NULL && pDefect->m_nIdx == nDefecIdx)
|
{
|
return pDefect;
|
}
|
}
|
}
|
|
return NULL;
|
}
|
|
CDefect* CGlass_Data::GetDefect_OK(int nDefecIdx)
|
{
|
CDefect *pDefect = NULL;
|
|
for(MapDefectIt it=m_MapDefect_OK.begin();it!=m_MapDefect_OK.end();it++)
|
{
|
if (m_nCurDefectIdx_OK > 0)
|
{
|
pDefect = static_cast<CDefect*>(it->second);
|
if (pDefect != NULL && pDefect->m_nIdx == nDefecIdx)
|
{
|
return pDefect;
|
}
|
}
|
}
|
|
return NULL;
|
}
|
|
BOOL CGlass_Data::TrimString(const CString& strDataInput, std::vector<CString> &arrString, const CString& strSign/*=_T(",")*/) {
|
/* code */
|
arrString.clear();
|
|
CString strData = strDataInput;
|
strData.Trim(); //??3y??óD????μ??é??
|
if (strData.IsEmpty()) {
|
return TRUE;
|
}
|
if (-1 == strData.Find(strSign)) { //2?°üo?·???·?
|
arrString.push_back(strData);
|
return TRUE;
|
}
|
while (0 == strData.Find(strSign)) { //?-?·é?3yê×??é?μ?·???·?
|
strData.Delete(0, strSign.GetLength());
|
}
|
strData += strSign;
|
CString str = _T("");
|
long lIndex = strData.Find(strSign);
|
while (-1 < lIndex)
|
{
|
str.Empty();
|
str = strData.Left(lIndex).Trim();
|
if (!str.IsEmpty())
|
{
|
arrString.push_back(str);
|
}
|
strData.Delete(0, lIndex + strSign.GetLength());
|
lIndex = strData.Find(strSign);
|
}
|
return TRUE;
|
}
|
|
int CGlass_Data::DecodePose(CString strDirection) {
|
/* code */
|
USES_CONVERSION;
|
std::string strCode(W2A(strDirection));
|
if (0 == strCode.compare("C1-L")) {
|
return 0;
|
}
|
else if (0 == strCode.compare("C1-S")) {
|
return 1;
|
}
|
else if (0 == strCode.compare("C1-C2")) {
|
return 2;
|
}
|
else if (0 == strCode.compare("C1-C4")) {
|
return 3;
|
}
|
else if (0 == strCode.compare("C2-L")) {
|
return 4;
|
}
|
else if (0 == strCode.compare("C2-S")) {
|
return 5;
|
}
|
else if (0 == strCode.compare("C2-C3")) {
|
return 6;
|
}
|
else if (0 == strCode.compare("C3-L")) {
|
return 7;
|
}
|
else if (0 == strCode.compare("C3-S")) {
|
return 8;
|
}
|
else if (0 == strCode.compare("C3-C4")) {
|
return 9;
|
}
|
else if (0 == strCode.compare("C4-L")) {
|
return 10;
|
}
|
else if (0 == strCode.compare("C4-S")) {
|
return 11;
|
}
|
|
return -1;
|
}
|
|
int CGlass_Data::DecodeDefectPose(CDefect_Info *pDefect, CString& strResult, const int defaultInt) {
|
/* code */
|
int nRet = defaultInt;
|
if (pDefect == NULL) {
|
return nRet;
|
}
|
|
//1. SideData
|
int idx = pDefect->m_nSideIdx;
|
CSide_Data *pSideData = &m_SideData[idx];
|
if (!pSideData->m_bFindGlassStartLine) {
|
return nRet;
|
}
|
int nStartLine = pSideData->m_nGlassStartLine;
|
|
CSIDE_PARM *pSideParam = &m_pGlassRecipe->m_SideParam[idx];
|
int yMinEdge = nStartLine + pSideParam->m_nCenterJudgeArea_StartLine_To_Start_pxl;
|
int yMaxEdge = nStartLine + pSideParam->m_nCenterJudgeArea_StartLine_To_End_pxl;
|
int yPos = (int)(pDefect->m_ptDefectPos_pxl.y);
|
|
CString strSign = _T("-");
|
std::vector<CString> vStrings;
|
TrimString(pSideParam->m_strPosDirection, vStrings, strSign);
|
|
if (vStrings.size() < 3) {
|
strResult.Format(_T("------"));
|
return nRet;
|
}
|
|
if (yPos <= yMinEdge) {
|
nRet = 0;
|
strResult.Format(_T("%s-%s"), vStrings[0], vStrings[2]);
|
}
|
else if (yPos >= yMaxEdge) {
|
nRet = 2;
|
strResult.Format(_T("%s-%s"), vStrings[1], vStrings[2]);
|
}
|
else {
|
nRet = 1;
|
strResult.Format(_T("%s-%s"), vStrings[0], vStrings[1]);
|
}
|
|
nRet = DecodePose(strResult);
|
|
return nRet;
|
}
|
|
int CGlass_Data::PointToLineDistance(CPoint A, CPoint B, CPoint C)
|
{
|
int nDistance = -1;
|
int A_coeff = B.y - A.y;
|
int B_coeff = A.x - B.x;
|
int C_coeff = B.x * A.y - A.x * B.y;
|
|
if (0 == A_coeff && 0 == B_coeff)
|
{
|
nDistance = std::sqrt((C.y - A.y) * (C.y - A.y) - (C.x - A.x) * (C.x - A.x));
|
return nDistance;
|
}
|
|
nDistance = std::abs(A_coeff * C.x + B_coeff * C.y + C_coeff) / std::sqrt(A_coeff * A_coeff + B_coeff * B_coeff);
|
return nDistance;
|
}
|
|
CPoint CGlass_Data::RotatePoint(CPoint p, double angle)
|
{
|
double rad = angle * M_PI / 180.0;
|
double cosAngle = cos(rad);
|
double sinAngle = sin(rad);
|
|
CPoint ptRot;
|
ptRot.x = static_cast<int>(round(p.x * cosAngle - p.y * sinAngle));
|
ptRot.y = static_cast<int>(round(p.x * sinAngle + p.y * cosAngle));
|
return ptRot;
|
}
|
|
CPoint CGlass_Data::TransformToGlobal(DimensionDir eDir, CPoint localPoint)
|
{
|
int nGlassSizeY = m_pGlassRecipe->m_SideParam[DIMENSION_A].m_nSidePanelSize_um;
|
int nGlassSizeX = m_pGlassRecipe->m_SideParam[DIMENSION_B].m_nSidePanelSize_um;
|
|
std::map<CString, CPoint> corners = {
|
{_T("C1"), {0, 0}},
|
{_T("C2"), {nGlassSizeX, 0}},
|
{_T("C3"), {nGlassSizeX, nGlassSizeY}},
|
{_T("C4"), {0, nGlassSizeY}}
|
};
|
|
std::vector<CString> vStrings;
|
TrimString(m_pGlassRecipe->m_SideParam[eDir].m_strPosDirection, vStrings, _T("-"));
|
|
CPoint globalPoint = { 0, 0 };
|
if (vStrings.size() != 3)
|
return globalPoint;
|
|
CSide_Data* pSideData = &m_SideData[eDir];
|
if (!pSideData->m_bFindGlassStartLine)
|
return globalPoint;
|
|
CPoint ptSideEnd = { 0, 0 };
|
for (int i = 0; i < MAX_IMAGE_FRAME - 1; i++)
|
{
|
if (pSideData->m_nSideLineFrame[i + 1] < 0)
|
{
|
ptSideEnd.x = pSideData->m_nSideLineFrame[i];
|
ptSideEnd.y = ((pSideData->m_nGlassEndLine <= 0) ? pSideData->m_nPreGlassEndLine : pSideData->m_nGlassEndLine);
|
break;
|
}
|
}
|
|
double dAngle = atan2(ptSideEnd.y - pSideData->m_nGlassStartLine, ptSideEnd.x - pSideData->m_nSideLineFrame[0]) * 180.0 / M_PI;
|
CPoint ptDefect = RotatePoint(CPoint(localPoint.x - pSideData->m_nSideLineFrame[0], localPoint.y - pSideData->m_nGlassStartLine), 90 - dAngle);
|
ptDefect.x *= static_cast<int>(round(pSideData->m_dPixelSizeX));
|
ptDefect.y *= static_cast<int>(round(pSideData->m_dPixelSizeY));
|
|
if (ptDefect.x < 0 || ptDefect.y < 0)
|
return globalPoint;
|
|
auto itStart = corners.find(vStrings[0]);
|
auto itEnd = corners.find(vStrings[1]);
|
if (itStart == corners.end() || itEnd == corners.end())
|
return globalPoint;
|
|
CPoint ptStart = itStart->second;
|
CPoint ptEnd = itEnd->second;
|
dAngle = atan2(ptEnd.y - ptStart.y, ptEnd.x - ptStart.x);
|
|
globalPoint.x = ptDefect.y * cos(dAngle) - ptDefect.x * sin(dAngle) + ptStart.x;
|
globalPoint.y = ptDefect.y * sin(dAngle) - ptDefect.x * cos(dAngle) + ptStart.y;
|
|
return globalPoint;
|
}
|
|
BOOL CGlass_Data::SetDefect(CDefect* pDefect)
|
{
|
if (pDefect == NULL)
|
return FALSE;
|
|
int nSideIdx = pDefect->m_DefectInfo.m_nScanIdx;
|
|
if(nSideIdx < 0 || MAX_SIDE_COUNT <= nSideIdx)
|
return FALSE;
|
|
CSingleLock localLock(&m_csGlassDefect);
|
localLock.Lock();
|
|
m_nCurDefectIdx_Total++;
|
m_SideData[nSideIdx].m_nTotalDefectCount++;
|
|
if(pDefect->m_bJudge_NG == TRUE)
|
{
|
pDefect->m_nIdx = m_nCurDefectIdx_NG;
|
m_MapDefect_NG.insert(std::make_pair(pDefect->m_nIdx, pDefect));
|
m_nCurDefectIdx_NG++;
|
|
m_SideData[nSideIdx].m_nNgDefectCount++;
|
m_nJudgeDefectCount++;
|
}
|
else
|
{
|
pDefect->m_nIdx = m_nCurDefectIdx_OK;
|
m_MapDefect_OK.insert(std::make_pair(pDefect->m_nIdx, pDefect));
|
m_nCurDefectIdx_OK++;
|
}
|
|
localLock.Unlock();
|
return TRUE;
|
}
|
|
//////////////////////////////////////////////////////////////////////////
|
// Scan
|
void CGlass_Data::SetLoadingTime()
|
{
|
CTime time = CTime::GetCurrentTime();
|
m_tLoadingTime = time;
|
m_strLoadingTime.Format(_T("%04d%02d%02d_%02d%02d%02d"),time.GetYear(),time.GetMonth(),time.GetDay(),time.GetHour(),time.GetMinute(),time.GetSecond());
|
m_strLoadingDayFileName.Format(_T("%04d%02d%02d"),time.GetYear(),time.GetMonth(),time.GetDay());
|
m_strLoadingTimeFileName.Format(_T("%02d%02d%02d"),time.GetHour(),time.GetMinute(),time.GetSecond());
|
}
|
|
void CGlass_Data::SetUnloadingTime()
|
{
|
CTime time = CTime::GetCurrentTime();
|
m_strUnloadingTime.Format(_T("%04d%02d%02d_%02d%02d%02d"),time.GetYear(),time.GetMonth(),time.GetDay(),time.GetHour(),time.GetMinute(),time.GetSecond());
|
}
|
|
void CGlass_Data::SetScanStartTime()
|
{
|
CTime time = CTime::GetCurrentTime();
|
m_strScanStartTime.Format(_T("%04d%02d%02d_%02d%02d%02d"),time.GetYear(),time.GetMonth(),time.GetDay(),time.GetHour(),time.GetMinute(),time.GetSecond());
|
}
|
|
void CGlass_Data::SetScanEndTime()
|
{
|
CTime time = CTime::GetCurrentTime();
|
m_strScanEndTime.Format(_T("%04d%02d%02d_%02d%02d%02d"),time.GetYear(),time.GetMonth(),time.GetDay(),time.GetHour(),time.GetMinute(),time.GetSecond());
|
m_strScanEndTimeFileName.Format(_T("%04d_%02d_%02d"),time.GetYear(),time.GetMonth(),time.GetDay());
|
|
}
|
|
void CGlass_Data::GetStageTheta(int iStage,short &nLongTheta,short &nShortTheta)
|
{
|
nLongTheta = m_nStageLongTheta[iStage];
|
nShortTheta = m_nStageShortTheta[iStage];
|
}
|
|
void CGlass_Data::SetStageTheta(int iStage,BOOL bLong,short nTheta)
|
{
|
if(iStage < 0 || iStage > 1)
|
{
|
g_pLog->DisplayMessage(_T("Stage Theta Index Not Normal : %d"),iStage);
|
return;
|
}
|
|
if(bLong == TRUE)
|
{
|
m_nStageLongTheta[iStage] = nTheta;
|
}
|
else
|
{
|
m_nStageShortTheta[iStage] = nTheta;
|
}
|
}
|