⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dlgbuildtin.cpp

📁 并行TIN生成算法, 基于DeWall算法理论实现
💻 CPP
字号:
// DlgBuildTIN.cpp : implementation file
//

#include "stdafx.h"
#include "TinApp.h"
#include "TinFrm.h"
#include "DlgBuildTIN.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CDlgBuildTIN dialog
typedef struct tagTIN_WORKER {
	TCS_S32	*stop;		// 停止标志
	TCS_V00	*thrd;		// 线程句柄
	TCS_V00	*nven[2];	// 工作事件
	TCS_F64	*P;
	TIN_R	*R;
} TIN_WORKER;
typedef struct tagTIN_MASTER {
	TCS_S32	 *stop;		// 停止标志
	TCS_V00	 *thrd;		// 线程句柄
	TCS_S32	  onnu;		// 线程数目
	TCS_V00	 *onpa;		// 线程参数
	TCS_F64	 *P;
	TCS_S32	  N;
	TIN_R	**R;
} TIN_MASTER;

CDlgBuildTIN::CDlgBuildTIN(CWnd* pParent /*=NULL*/)
	: CDialog(CDlgBuildTIN::IDD, pParent)
{
	m_pts = 0;
	m_num = 0;
	m_dim = 0;

	m_TT = 0;
	m_TN = 0;
	// 分配线程参数
	m_onnu = 2;
	TIN_WORKER *onpa = new TIN_WORKER[m_onnu];
	for (long i = 0; i < m_onnu; i++)
	{
		onpa[i].nven[0] = ::CreateEvent(0, 0, 0, 0);
		onpa[i].nven[1] = ::CreateEvent(0, 0, 1, 0);
		onpa[i].stop = &m_stop;
		onpa[i].thrd = 0;
		onpa[i].R = 0;
	}
	m_onpa = onpa;

	TIN_MASTER *mapa = new TIN_MASTER;
	mapa->stop = &m_stop;
	mapa->onnu = m_onnu;
	mapa->onpa = onpa;
	mapa->thrd = 0;
	m_mapa = mapa;

	//{{AFX_DATA_INIT(CDlgBuildTIN)
	m_dtm = _T("");
	m_dup = 0.01f;
	//}}AFX_DATA_INIT
}

CDlgBuildTIN::~CDlgBuildTIN()
{
	m_stop = 1;
	TIN_MASTER *mapa = (TIN_MASTER*)m_mapa;
	// 等待线程结束
	::WaitForSingleObject(mapa->thrd, INFINITE);
	// 释放资源
	TIN_WORKER *onpa = (TIN_WORKER*)m_onpa;
	for (long i = 0; i < mapa->onnu; i++)
	{
		::CloseHandle(onpa[i].nven[0]);
		::CloseHandle(onpa[i].nven[1]);
	}
	delete []onpa;	delete mapa;
}

void CDlgBuildTIN::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CDlgBuildTIN)
	DDX_Control(pDX, IDC_PROGRESS, m_progress);
	DDX_Text(pDX, IDC_TIME_STATIC, m_dtm);
	DDX_Text(pDX, IDC_DUP_EDIT, m_dup);
	DDV_MinMaxFloat(pDX, m_dup, 0.f, 10.f);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CDlgBuildTIN, CDialog)
	//{{AFX_MSG_MAP(CDlgBuildTIN)
	ON_BN_CLICKED(IDC_BUILD_BUTTON, OnBUILD)
	ON_BN_CLICKED(IDC_STOPB_BUTTON, OnSTOPB)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDlgBuildTIN message handlers

// 工作线程

TCS_U32 WINAPI WorkerThread(LPVOID lpParam)
{
	TIN_WORKER *wopa = (TIN_WORKER*)lpParam;

	while (1)
	{
		::WaitForSingleObject(wopa->nven[0], INFINITE);
		if (*(wopa->stop) == 1)
			break;

		if (wopa->R)
			ConTen2(wopa->R, wopa->P, wopa->stop);

		wopa->R = 0;

		::SetEvent(wopa->nven[1]);
		if (*(wopa->stop) == 1)
			break;
	}

	::SetEvent(wopa->nven[1]);
	wopa->thrd = 0;
	wopa->R = 0;

	return 0;
}
// 控制线程

TCS_U32 WINAPI MasterThread(LPVOID lpParam)
{
	TIN_MASTER *mapa = (TIN_MASTER*)lpParam;

	// 调度线程
	TIN_WORKER *onpa = (TIN_WORKER*)mapa->onpa;
	TCS_V00 **nven = new TCS_V00*[mapa->onnu];
	for (long i = 0; i < mapa->onnu; i++)
		nven[i] = onpa[i].nven[1];

	TCS_F64 *P = mapa->P;
	TCS_S32  N = mapa->N;
	TIN_R **R = mapa->R;
	for (long k = 0; k < N; k++)
	{
		// 等待线程空闲
		TCS_U32 idx = ::WaitForMultipleObjects(mapa->onnu, nven, 0, INFINITE);
		if (idx >= WAIT_OBJECT_0 && idx < WAIT_OBJECT_0 + mapa->onnu)
		{
			idx = idx - WAIT_OBJECT_0;
			onpa[idx].P = P;
			onpa[idx].R = R[k];
			::SetEvent(onpa[idx].nven[0]);
		}
		// 如果中途终止
		if (*(mapa->stop) == 1)
			break;
	}
	// 释放内存资源
	delete []nven;
	// 等待本次任务完成
	for (long i = 0; i < mapa->onnu; i++)
	{
		while (1)
		{
			if (onpa[i].R == 0 || onpa[i].thrd == 0)
				break;
			else
				::Sleep(2);
		}
	}
	// 结束工作线程
	*(mapa->stop) = 1;
	for (long i = 0; i < mapa->onnu; i++)
	{
		::SetEvent(onpa[i].nven[0]);
		::WaitForSingleObject(onpa[i].thrd, INFINITE);
	}
	// 本线程结束
	mapa->thrd = 0;

	return 0;
}

void CDlgBuildTIN::Init(void *pts, long num, long dim, CTcsTan2 *Tan, TIN_T **TT, long *TN, TIN_R **TR, long *RN)
{
	m_pts = pts;
	m_num = num;
	m_dim = dim;

	m_oTan = Tan;

	m_TT = TT;
	m_TN = TN;

	m_TR = TR;
	m_RN = RN;
}

void CDlgBuildTIN::OnBUILD() 
{
	Gray(1);
	m_nProc = 1;

	Build();

	m_nProc = 0;
	Gray(0);
}

void CDlgBuildTIN::Gray(BOOL bGray)
{
	GetDlgItem(IDC_DUP_EDIT)->EnableWindow(!bGray);
	GetDlgItem(IDC_STOPB_BUTTON)->EnableWindow(bGray);
	GetDlgItem(IDC_BUILD_BUTTON)->EnableWindow(!bGray);

/*	CTinFrm* pFrm = (CTinFrm*)AfxGetMainWnd();
	if (pFrm)
	{
		CMenu* pMenu = pFrm->GetMenu();
		long cnt = pMenu->GetMenuItemCount();
		for (long i = 0; i < cnt; i++)
		{
			if (!bGray)
				::EnableMenuItem(pMenu->m_hMenu, i, MF_BYPOSITION | MF_ENABLED);
			else
				::EnableMenuItem(pMenu->m_hMenu, i, MF_BYPOSITION | MF_GRAYED);
		}
		::DrawMenuBar(pFrm->m_hWnd);

		::PeekAndPump();
	}

	pFrm->HideToolButton(bGray);*/
}

void CDlgBuildTIN::OnSTOPB() 
{
	m_oTan->Stop();
	m_nProc = 0;
	m_stop = 1;
}

void CDlgBuildTIN::Build(void)
{
	if (!UpdateData(1))
	{
		AfxMessageBox("请输入[重合点限差]!");
		return;
	}
	m_progress.SetRange32(0, m_num);

	if (m_dim != 2)
		return;
	m_oTan->Make((TCS_F64*)m_pts, m_num, m_dup);
	// 检测构网分区是否完成
	TCS_S32 TN, PN;	TCS_F64 DT;
	while (1)
	{
		if (m_oTan->Done())
			break;
		::Sleep(10);	::PeekAndPump();
#ifdef TSET_SIN
		TN = 0, PN = 0;		m_oTan->Proc(PN, TN);
		m_dtm.Format("%d/%d", PN, TN);	UpdateData(0);
#endif
	}
	TN = 0, PN = 0;	m_oTan->Proc(PN, TN); DT = m_oTan->Time();
	m_dtm.Format("%.2lf/%d/%d", DT, PN, TN);	UpdateData(0);

	TCS_TMB btm;	::_ftime_s(&btm);

	if (*m_TR)
		delete []*m_TR;
	*m_TR = 0;	*m_RN = 0;

	TCS_S32 RN;
	TIN_R **TR = m_oTan->TinR(RN);
	if (1)
	{
		TIN_G *G = m_oTan->TinG();
		// 利用线程调度分区构网
		m_stop = 0;
		TIN_WORKER *onpa = (TIN_WORKER*)m_onpa;
		TIN_MASTER *mapa = (TIN_MASTER*)m_mapa;
		for (long i = 0; i < mapa->onnu; i++)
		{
			onpa[i].R = 0;
			::SetEvent(onpa[i].nven[1]);
			::ResetEvent(onpa[i].nven[0]);
			onpa[i].thrd = ::CreateThread(0, 0, WorkerThread, &onpa[i], 0, 0);
		}
		mapa->P = (TCS_F64*)m_pts;	mapa->N = RN;	mapa->R = TR;
		mapa->thrd = ::CreateThread(0, 0, MasterThread, mapa, 0, 0);

		// 检测进度:完成点数与三角形数
		while (1)
		{
			::Sleep(10);	TN = 0, PN = 0;		m_oTan->Proc(PN, TN);
			m_dtm.Format("%d/%d", PN, TN);	UpdateData(0);
			if (!mapa->thrd)	break;
			::PeekAndPump();
		}
	}

	if (RN)
	{
		TIN_R *R = new TIN_R[RN];
		for (long i = 0; i < RN; i++)
		{
			R[i].ASL = TR[i]->ASL;
			R[i].ATL = TR[i]->ATL;
			R[i].AXI = TR[i]->AXI;
			R[i].AXV = TR[i]->AXV;
			R[i].BSL = TR[i]->BSL;
			R[i].G   = TR[i]->G;
			R[i].S	 = TR[i]->S;
			R[i].SCO[0] = TR[i]->SCO[0];
			R[i].SCO[1] = TR[i]->SCO[1];
		}
		*m_TR = R;	*m_RN = RN;
	}
	delete []TR;

	TCS_TMB etm;	::_ftime_s(&etm);

	// 获得三角形
	if (*m_TT)
		delete [](*m_TT);
	*m_TN = 0;	*m_TT = 0;
	*m_TT = m_oTan->TinT(*m_TN);
	// 检查是否存在重复三角形
	if (0)
	{
		long n = *m_TN;
		TIN_T *T = *m_TT;
		for (long i = 0; i < n - 1; i++)
		{
			for (long k = i + 1; k < n; k++)
			{
				if ((T[i].pid[0] == T[k].pid[0] && T[i].pid[1] == T[k].pid[1] && T[i].pid[2] == T[k].pid[2]) ||
					(T[i].pid[1] == T[k].pid[0] && T[i].pid[2] == T[k].pid[1] && T[i].pid[0] == T[k].pid[2]) ||
					(T[i].pid[2] == T[k].pid[0] && T[i].pid[0] == T[k].pid[1] && T[i].pid[1] == T[k].pid[2]))
				{
					AfxMessageBox("重复三角形!");
					return;
				}
			}
		}
	}
	// 获得指标数据
	DT += (::difftime(etm.time, btm.time) + (etm.millitm - btm.millitm) / 1000.0);
	TN = 0, PN = 0;	m_oTan->Proc(PN, TN);	m_dtm.Format("%.2lf/%d/%d", DT, PN, TN);	UpdateData(0);

	if (!m_nProc)
		AfxMessageBox("构建停止!");
	else
		AfxMessageBox("构建完毕!");
}

void CDlgBuildTIN::OnCancel() 
{
	if (m_nProc)
		return;

	CDialog::OnCancel();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -