www.pudn.com > buildct.zip > buildctDlg.cpp, change:2004-02-25,size:22495b


// buildctDlg.cpp : implementation file 
// 
 
#include "stdafx.h" 
#include "buildct.h" 
#include "buildctDlg.h" 
#include "DlgOpen.h" 
#include "DlgDraw.h" 
//#include "draw.h" 
#include "chain.h" 
#include "BmpRead.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// CAboutDlg dialog used for App About 
 
class CAboutDlg : public CDialog 
{ 
public: 
	CAboutDlg(); 
 
// Dialog Data 
	//{{AFX_DATA(CAboutDlg) 
	enum { IDD = IDD_ABOUTBOX }; 
	//}}AFX_DATA 
 
	// ClassWizard generated virtual function overrides 
	//{{AFX_VIRTUAL(CAboutDlg) 
	protected: 
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support 
	//}}AFX_VIRTUAL 
 
// Implementation 
protected: 
	//{{AFX_MSG(CAboutDlg) 
	//}}AFX_MSG 
	DECLARE_MESSAGE_MAP() 
}; 
 
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) 
{ 
	//{{AFX_DATA_INIT(CAboutDlg) 
	//}}AFX_DATA_INIT 
} 
 
void CAboutDlg::DoDataExchange(CDataExchange* pDX) 
{ 
	CDialog::DoDataExchange(pDX); 
	//{{AFX_DATA_MAP(CAboutDlg) 
	//}}AFX_DATA_MAP 
} 
 
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) 
	//{{AFX_MSG_MAP(CAboutDlg) 
		// No message handlers 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CBuildctDlg dialog 
 
CBuildctDlg::CBuildctDlg(CWnd* pParent /*=NULL*/) 
	: CDialog(CBuildctDlg::IDD, pParent) 
{ 
	//{{AFX_DATA_INIT(CBuildctDlg) 
	m_status = _T(""); 
	//}}AFX_DATA_INIT 
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32 
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 
} 
 
void CBuildctDlg::DoDataExchange(CDataExchange* pDX) 
{ 
	CDialog::DoDataExchange(pDX); 
	//{{AFX_DATA_MAP(CBuildctDlg) 
//	DDX_Control(pDX, IDC_VIEWANGLE, m_ctlView); 
//	DDX_Control(pDX, IDC_BUTTONBUILDSURFACE3, m_buildFace3); 
//	DDX_Control(pDX, IDC_BUTTONBUILDSURFACE2, m_buildFace2); 
	DDX_Control(pDX, IDC_BUTTONBUILDSURFACE, m_buildFace); 
	DDX_Control(pDX, IDC_BUTTONOLDLINE, m_oldLine); 
	DDX_Control(pDX, IDC_BUTTONFINALLINE, m_finalLine); 
	DDX_Control(pDX, IDC_LISTDATA, m_list); 
	DDX_Text(pDX, IDC_STATUS, m_status); 
	//}}AFX_DATA_MAP 
} 
 
BEGIN_MESSAGE_MAP(CBuildctDlg, CDialog) 
	//{{AFX_MSG_MAP(CBuildctDlg) 
	ON_WM_SYSCOMMAND() 
	ON_WM_PAINT() 
	ON_WM_QUERYDRAGICON() 
	ON_BN_CLICKED(IDC_BUTTONBUILDSURFACE, OnButtonbuildsurface) 
	ON_BN_CLICKED(IDC_BUTTONLOAD, OnButtonload) 
	ON_BN_CLICKED(IDC_BUTTONOLDLINE, OnButtonoldline) 
	ON_BN_CLICKED(IDC_BUTTONFINALLINE, OnButtonfinalline) 
//	ON_BN_CLICKED(IDC_BUTTONBUILDSURFACE2, OnButtonbuildsurface2) 
//	ON_BN_CLICKED(IDC_BUTTONBUILDSURFACE3, OnButtonbuildsurface3) 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CBuildctDlg message handlers 
 
BOOL CBuildctDlg::OnInitDialog() 
{ 
	CDialog::OnInitDialog(); 
 
	// Add "About..." menu item to system menu. 
 
	// IDM_ABOUTBOX must be in the system command range. 
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); 
	ASSERT(IDM_ABOUTBOX  0xF000); 
 
	CMenu* pSysMenu = GetSystemMenu(FALSE); 
	if (pSysMenu != NULL) 
	{ 
		CString strAboutMenu; 
		strAboutMenu.LoadString(IDS_ABOUTBOX); 
		if (!strAboutMenu.IsEmpty()) 
		{ 
			pSysMenu->AppendMenu(MF_SEPARATOR); 
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); 
		} 
	} 
 
	// Set the icon for this dialog.  The framework does this automatically 
	//  when the application's main window is not a dialog 
	SetIcon(m_hIcon, TRUE);			// Set big icon 
	SetIcon(m_hIcon, FALSE);		// Set small icon 
	 
	// TODO: Add extra initialization here 
 
	debugFile.Open ("debug.txt",CFile::modeWrite|CFile::modeCreate); 
		/* 
		CComboBox *Majors = new CComboBox; 
    Majors->Create(WS_CHILD | WS_VISIBLE | 
    WS_VSCROLL | CBS_DROPDOWNLIST, 
    CRect(10, 50, 100, 150), this, 0x5448); 
 
    Majors->AddString("Accounting"); 
    Majors->AddString("Art Education"); 
    Majors->AddString("Finance"); 
    Majors->AddString("Biology"); 
*/ 
	CRect rect; 
	m_buildFace.GetWindowRect (&rect); 
	rect.top -=60; 
	rect.bottom +=50; 
    m_ctlView.Create (WS_CHILD | WS_VISIBLE | 
    WS_VSCROLL | CBS_DROPDOWNLIST, 
    rect, this, 0x5448); 
	this->m_ctlView.AddString ("X正方向"); 
	this->m_ctlView.AddString ("X负方向"); 
	this->m_ctlView.AddString ("Y正方向"); 
	this->m_ctlView.AddString ("Y负方向"); 
	this->m_ctlView.AddString ("Z正方向"); 
	this->m_ctlView.AddString ("Z负方向"); 
    m_ctlView.SetCurSel (0); 
    m_ctlView.EnableWindow (false); 
	return TRUE;  // return TRUE  unless you set the focus to a control 
} 
 
void CBuildctDlg::OnSysCommand(UINT nID, LPARAM lParam) 
{ 
	if ((nID & 0xFFF0) == IDM_ABOUTBOX) 
	{ 
		CAboutDlg dlgAbout; 
		dlgAbout.DoModal(); 
	} 
	else 
	{ 
		CDialog::OnSysCommand(nID, lParam); 
	} 
} 
 
// If you add a minimize button to your dialog, you will need the code below 
//  to draw the icon.  For MFC applications using the document/view model, 
//  this is automatically done for you by the framework. 
 
void CBuildctDlg::OnPaint()  
{ 
	if (IsIconic()) 
	{ 
		CPaintDC dc(this); // device context for painting 
 
		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); 
 
		// Center icon in client rectangle 
		int cxIcon = GetSystemMetrics(SM_CXICON); 
		int cyIcon = GetSystemMetrics(SM_CYICON); 
		CRect rect; 
		GetClientRect(&rect); 
		int x = (rect.Width() - cxIcon + 1) / 2; 
		int y = (rect.Height() - cyIcon + 1) / 2; 
 
		// Draw the icon 
		dc.DrawIcon(x, y, m_hIcon); 
	} 
	else 
	{ 
		CDialog::OnPaint(); 
	} 
} 
 
// The system calls this to obtain the cursor to display while the user drags 
//  the minimized window. 
HCURSOR CBuildctDlg::OnQueryDragIcon() 
{ 
	return (HCURSOR) m_hIcon; 
} 
 
 
void CBuildctDlg::OnButtonbuildsurface()  
{ 
	// TODO: Add your control notification handler code here 
	 
	 
//	MessageBox("Ok"); 
	if(!body.isAvailable ()) 
		doBuildSurface(); 
	CDlgDraw draw; 
 	CBitmap *pBmp=draw.getBitBuf (); 
 
    int sel =m_ctlView.GetCurSel (); 
    body.graphicsDebugPrint (pBmp,sel); 
   //	draw.m_drawInfo=layer2.simplePrint (); 
	draw.m_drawInfo =body.simplePrint (); 
    draw.DoModal (); 
	 
} 
 
void CBuildctDlg::OnButtonload()  
{ 
	// TODO: Add your control notification handler code here 
	CDlgOpen dlg; 
	//dlg.doModal(); 
	dlg.m_dir ="d:\\work\\buildct\\ct"; 
	dlg.m_from =1; 
	dlg.m_to =37; 
	bool error=false; 
	if(dlg.DoModal()==IDOK) 
	{ 
		this->m_list.ResetContent (); 
		for(int i=dlg.m_from ;i=dlg.m_to ;i++) 
		{ 
			CString image; 
			image.Format ("%d",i); 
			CString filename=dlg.m_dir+"\\"+image+".bmp"; 
			CFile mfile;//(dlg.m_dir+"\\"+image+".bmp"); 
			if(mfile.Open(filename,CFile::modeRead)==0) 
			//if(file.GetLength ()<2) 
			{ 
				CString msg="文件不存在\n:"+filename; 
				MessageBox(msg,"发生错误"); 
				//MessageBox("错误: 无法打开有关的hKEY!");  
				m_list.ResetContent (); 
				error=true; 
				break; 
			} 
			m_list.AddString (filename); 
		} 
		this->m_oldLine.EnableWindow (!error); 
		this->m_finalLine.EnableWindow (!error); 
		this->m_buildFace.EnableWindow (!error); 
//		this->m_buildFace2.EnableWindow (!error); 
//		this->m_buildFace3.EnableWindow (!error); 
		m_ctlView.EnableWindow (!error); 
		body.setAvailable (false); 
		 
	 
        //m_ctlView.set 
	 /*	//if(m_cmbAngle.GetCount ()==0) 
	//	{ 
		CComboBox* pCB=(CComboBox*)GetDlgItem(IDC_COMBOANGLE); 
		pCB->AddString("item 1"); 
		pCB->AddString("item 2"); 
		pCB->AddString("item 3"); 
 
		   m_cmbAngle.ResetContent (); 
			this->m_cmbAngle.AddString ("X正方向"); 
			this->m_cmbAngle.AddString ("X负方向"); 
			this->m_cmbAngle.AddString ("Y正方向"); 
			this->m_cmbAngle.AddString ("Y负方向"); 
			this->m_cmbAngle.AddString ("Z正方向"); 
			this->m_cmbAngle.AddString ("Z负方向"); 
	//	} 
		 
		UpdateData(false); 
*/ 
	} 
} 
 
void CBuildctDlg::OnButtonoldline()  
{ 
	// TODO: Add your control notification handler code here 
	CString imagename; 
	int index=m_list.GetCurSel (); 
	if(index==-1) 
	{ 
		MessageBox("你没有选中数据项!"); 
	    return ; 
	} 
	this->m_list.GetText (index,imagename); 
    unsigned char (*buffer)[IMAGEW/8]=new unsigned char[IMAGEH][IMAGEW/8]; 
	Chain data2; 
    LineChain layer2; 
	CBmpRead bmp; 
	int re=bmp.readImage(imagename.GetBuffer (imagename.GetLength ()),"image.txt",buffer); 
    if(re!=0) 
    { 
		MessageBox("\nSorry!Image %s can't be read(%d)!\n\nUsage:\n\tbuildCT imagedirectory\n\nExample:\n\t c:>buildCT ct \n",imagename,re); 
        return; 
    } 
	//提取边界点 
    identifyContour(buffer,&data2); 
	//根据点构造边 
    buildAllEdges(&data2,&layer2); 
    //检查轮廓线拓扑 
    //layer2.checkTopo(); 
    //释放非LINKED的节点所占内存,以节省内存空间 
    data2.freeNotLinked(); 
    // 
 
	CDlgDraw draw; 
	CBitmap *pBmp=draw.getBitBuf (); 
    layer2.graphicsDebugPrint (pBmp); 
	draw.m_drawInfo=layer2.simplePrint (); 
	draw.DoModal (); 
} 
 
void CBuildctDlg::OnButtonfinalline()  
{ 
	// TODO: Add your control notification handler code here 
	CString imagename; 
	int index=m_list.GetCurSel (); 
	if(index==-1) 
	{ 
		MessageBox("你没有选中数据项!"); 
	    return ; 
	} 
	this->m_list.GetText (index,imagename); 
    unsigned char (*buffer)[IMAGEW/8]=new unsigned char[IMAGEH][IMAGEW/8]; 
	Chain data2; 
    LineChain layer2; 
	CBmpRead bmp; 
	int re=bmp.readImage(imagename.GetBuffer (imagename.GetLength ()),"image.txt",buffer); 
    if(re!=0) 
    { 
		MessageBox("\nSorry!Image %s can't be read(%d)!\n\nUsage:\n\tbuildCT imagedirectory\n\nExample:\n\t c:>buildCT ct \n",imagename,re); 
        return; 
    } 
	//提取边界点 
    identifyContour(buffer,&data2); 
	//根据点构造边 
    buildAllEdges(&data2,&layer2); 
    //检查轮廓线拓扑 
    layer2.checkTopo(); 
    //释放非LINKED的节点所占内存,以节省内存空间 
    data2.freeNotLinked(); 
    // 
 
	CDlgDraw draw; 
	CBitmap *pBmp=draw.getBitBuf (); 
    layer2.graphicsDebugPrint (pBmp); 
	draw.m_drawInfo=layer2.simplePrint (); 
	draw.DoModal (); 
} 
 
/* 
根据点构造边 
1. 用折线拟合轮廓点,折线用链表结点间的指针连接表示. 
正常情况下,返回0。 
 
*/ 
int CBuildctDlg::buildAllEdges(Chain *points,LineChain *lines) 
{ 
    if(points==NULL) 
    return -1; 
    if(lines==NULL) 
    return -1; 
    ChainNode *first=points->getFirst(); 
    ChainNode*s=first; 
    ChainNode *p=NULL,*q=NULL; 
    do 
    { 
        //若s为空则不处理。 
        if(s==NULL)break; 
        p=s->getLink(); 
        q=s; 
        do 
        { 
            if(q->getTag()==INIT) 
            points->linkNearestNodes(q,lines); 
            q=q->getNext(); 
        }while(q!=NULL && q!=s); 
        s=p; 
        //若循环则结束 
    }while(s!=NULL && s!=first); 
 
    return 0; 
} 
 
/* 
识别点 
1.扫描一层断层数据,识别轮廓边缘点,结果在points中 
2.用折线拟合轮廓边缘,折线用链表结点间的指针连接表示。 
正常情况下,返回0。 
*/ 
int CBuildctDlg::identifyContour(unsigned char data[][IMAGEW/8],Chain *points) 
{ 
    if(points==NULL) 
    return -1; 
    int a=0; 
    int x1,x2; 
    int count=0; 
    for(int i=0;i<IMAGEH;i++) 
    { 
        ChainNode *line=new ChainNode(0,i); 
        line->setTag(LINEHEAD); 
        for(int j=0;j<IMAGEW;j++) 
        { 
            //int value=getFiltedValue(data,j,i); 
            int value=getValue(data,j,i); 
            // if(value==1)printf("value=1\n"); 
            if(a==0 && value ==1) 
            { 
                x1=j; 
                a=1; 
                count=0; 
                ChainNode *p=new ChainNode(x1,i); 
                line->appendNode(p); 
            } 
            count++; 
            if(value==1 && count>10) 
            { 
                ChainNode *p=new ChainNode(j,i); 
                line->appendNode(p); 
                count=0; 
            } 
            if(a==1 && value==0) 
            { 
                x2=j; 
                a=0; 
                if(count>5) 
                { 
                    ChainNode *p=new ChainNode(x2,i); 
                    line->appendNode(p); 
                } 
            } 
            /* 
            if(value==1) 
            { 
            ChainNode *p=new ChainNode(j,i); 
            line->appendNode(p); 
            }*/ 
 
        } 
        //如果该行没有+值点,则忽略该行,并释放行首结点。 
        if(line->getNextCount()>1) 
        points->append(line); 
        else 
        delete line; 
    } 
 
    return 0; 
    //return 0; 
} 
 
/* 
根据上下两层(layerNum,layerNum+1)断层数据,创建三角面片. 
采用交换对角线法构造三角面片 
正常情况下,返回0。 
 
*/ 
 
int CBuildctDlg::createSurface(int layerNum,ChainNode *upline,ChainNode *downline,Triangle *body) 
{ 
    if(body==NULL || upline==NULL || downline==NULL) 
    { 
        //printf("NULL:body=%d,upline=%d,down=%d",body,upline,downline); 
        return -1; 
    } 
    //printf("createSurface:%d,",layerNum); 
	 
    ChainNode *data1=upline->getNext(); 
    ChainNode *data2=downline->getNext(); 
    if(data1==NULL || data2==NULL )return -1; 
	CString cs; 
	cs.Format ("createSurface<%d-%d>,",data1->getLinkCount (),data2->getLinkCount ()); 
	debugPrint(cs); 
    if(data1->getLinkCount()<2 && data2->getLinkCount()<2) 
    return -1; 
    long tempdist2=MAX*MAX; 
    //data2=data2->getNearestInLink(data1->getX(),data1->getY(),tempdist2); 
	data2=getStartInLine(downline,upline,data1->getX(),data1->getY()); 
    if(data2==NULL) return -1; 
    ChainNode *q1=data1,*p1; 
    ChainNode *q2=data2,*p2; 
	//@1 
	POINT centerup,centerdown; 
	centerup.x =upline->getX (); 
	centerup.y =upline->getY (); 
	centerdown.x =downline->getX (); 
	centerdown.y =downline->getY(); 
	//@2 
	LineHeader *header1=(LineHeader*)upline; 
	LineHeader *header2=(LineHeader*)downline; 
	double ratio=(double)(header1->getPerimeter ())/header2->getPerimeter (); 
    double len1=0.0,len2=0.0; 
    bool isFirst=true; 
    do 
    { 
        p1=q1->getLink(); 
        p2=q2->getLink(); 
        //long dist1=q1->getDistance2(p2->getX(),p2->getY()); 
        //long dist2=q2->getDistance2(p1->getX(),p1->getY()); 
    	/* 
		//@1使用Cook方法 
		long pointto=(p1->getX()-centerup.x)*(p2->getY()-centerdown.y )-((p2->getX()-centerdown.x ))*((p1->getY()-centerup.y )); 
		if(!isFirst) 
		{ 
			if(q1==data1)pointto=-1; 
		    if(q2==data2)pointto=1; 
		} 
		*/ 
		//@2另一种启发式算法,使用累加周长。 
		len1+=sqrt(p1->getDistance2 (q1->getX (),q1->getY ())); 
		len2+=sqrt(p2->getDistance2 (q2->getX (),q2->getY ()))*ratio; 
		if(!isFirst) 
		{ 
			if(q1==data1)len2=0; 
			if(q2==data2)len1=0; 
		} 
		isFirst=false; 
		//if(pointto<0) 
		if(len1>len2) 
        { 
            body->appendFacet(q1->getX(),q1->getY(),layerNum,q2->getX(),q2->getY(),layerNum+1,p2->getX(),p2->getY(),layerNum+1); 
            q2=p2; 
        } 
        else 
        { 
            body->appendFacet(q1->getX(),q1->getY(),layerNum,q2->getX(),q2->getY(),layerNum+1,p1->getX(),p1->getY(),layerNum); 
            q1=p1; 
        } 
    }while(q1!=data1||q2!=data2); 
    return 0; 
} 
/* 
根据上下两层(layerNum,layerNum+1)断层数据,创建三角面片. 
采用交换对角线法构造三角面片 
正常情况下,返回0。 
 
*/ 
 
int CBuildctDlg::createSurface(int layerNum,ChainNode *line,Triangle *body) 
{ 
    if(body==NULL ||line==NULL) 
    { 
        //printf("NULL:body=%d,upline=%d,down=%d",body,upline,downline); 
        return -1; 
    } 
    //printf("createSurface:%d,",layerNum); 
    ChainNode *data=line->getNext(); 
    if(data==NULL )return -1; 
	CString cs; 
	cs.Format ("createSurface<%d>,",data->getLinkCount ()); 
	debugPrint(cs); 
    if(data->getLinkCount()<3) 
    return -1; 
    POINT center; 
	center.x =line->getX (); 
	center.y =line->getY (); 
    ChainNode *q1=data,*p1; 
    do 
    { 
        p1=q1->getLink(); 
        if(p1==NULL)break; 
        body->appendFacet(center.x ,center.y ,layerNum,q1->getX(),q1->getY(),layerNum,p1->getX(),p1->getY(),layerNum); 
 
        q1=p1; 
         
    }while(q1!=data); 
    return 0; 
} 
 
/* 
根据上下两层(layerNum,layerNum+1)断层数据,创建三角面片. 
正常情况下,返回0。 
 
 
*/ 
int CBuildctDlg::buildSurface(int layerNum,LineChain *up,LineChain *down,Triangle *body) 
{ 
    if(up==NULL||down==NULL)return -1; 
    CString cs; 
	cs.Format("layerNum:%d ",layerNum); 
	cs=cs+up->simplePrint (); 
	cs=cs+down->simplePrint (); 
	debugPrint(cs); 
    int i; 
	//处理上未曾被标记的面,作为体的上表面。 
	for(i=0;i<up->getCount();i++) 
    { 
        ChainNode *line1=up->getTheHead(i); 
        //line1->setTag(LINEHEAD); 
		if(line1->getTag ()!=MARKED ) 
		{ 
			createSurface(layerNum,line1,body); 
			//恢复轮廓头标志 
			//line1->setTag (LINEHEAD); 
		} 
		line1->setTag (LINEHEAD); 
    } 
 
	if(up->getCount ()=down->getCount ()) 
	{ 
		for(i=0;i<up->getCount();i++) 
		{ 
			ChainNode *line1=up->getTheHead(i); 
			if(line1->getTag()==LINEHEAD ) 
			{ 
				ChainNode *line2=down->getFittestLine(line1); 
				if(line2==NULL)debugPrint("upNULL."); 
				createSurface(layerNum,line1,line2,body); 
				//对处理过的轮廓线标记 
				if(line2!=NULL) line2->setTag(MARKED); 
				line1->setTag(MARKED); 
			} 
		//	else 
		//	{debugPrint("upMARKED.");} 
			//if(  line1->getNextCount ()=1) 
			//	line1->setTag (MARKED); 
		} 
    }else 
	{ 
		//处理的未标记的下层轮廓线 
		 
		for(i=0;i<down->getCount();i++) 
		{ 
			ChainNode *line2=down->getTheHead(i); 
			if(line2->getTag()==LINEHEAD ) 
			{ 
				ChainNode *line1=up->getFittestLine(line2); 
				if(line2==NULL)debugPrint("downNULL."); 
				createSurface(layerNum,line1,line2,body); 
				if(line1!=NULL) line1->setTag(MARKED); 
				line2->setTag (MARKED); 
			} 
		//	else 
		//	{debugPrint("downMARKED.");} 
		//	if(  line2->getNextCount ()=1) 
		//		line2->setTag (MARKED); 
		} 
    } 
     
    //处理上未曾被标记的面,作为体的下表面 
	for(i=0;i<up->getCount();i++) 
    { 
        ChainNode *line1=up->getTheHead(i); 
        //line1->setTag(LINEHEAD); 
		if(line1->getTag ()!=MARKED) 
		{ 
			createSurface(layerNum,line1,body); 
		} 
    } 
     
    return 0; 
} 
 
/* 
过滤预处理 
*/ 
 
int CBuildctDlg::preFiltering(unsigned char data[][IMAGEW/8]) 
{ 
///    unsigned char tempbuf[IMAGEW/8]; 
    int i,pre=0; 
    int count=0; 
    //过滤单点 
    /* 
    for(i=0;i<IMAGEH;i++) 
    { 
    for(int j=0;j<IMAGEW/8;j++) 
    { 
    if(data[i][j]!=0)data[i][j]=255; 
    } 
    }*/ 
    //去掉相似行 
 
    for(i=1;i<IMAGEH;i++) 
    { 
        count=0; 
        for(int j=0;j<IMAGEW/8;j++) 
        { 
            if(data[i][j]!=data[pre][j])count++; 
        } 
        if(count<1) 
        { 
            for(int j=0;j<IMAGEW/8;j++) 
            { 
                data[i][j]=0; 
            } 
        } 
        else 
        { 
            pre=i; 
        } 
    } 
 
    return 0; 
} 
 
/* 
取一个原始点值. 
*/ 
int CBuildctDlg::getValue(unsigned char data[][IMAGEW/8],int x,int y) 
{ 
	BYTE bit[8]={128, 64, 32, 16, 8, 4, 2, 1}; 
 
    //if(y>50)printf("y=%d\n",y); 
    if(x<0)x=0; 
    if(x>IMAGEW-1)x=IMAGEW-1; 
    if(y<0)y=0; 
    if(y>IMAGEH-1)y=IMAGEH-1; 
    int xa=x/8; 
    int xb=x%8; 
    unsigned char value=(data[y][xa]&bit[xb])!=0?1:0; 
    return value; 
    //return data[y][x]; 
} 
 
/* 
取一个点值, 
value(x,y)=(data(x,y)*7/8+(对x,y周围8个点求和)*1/8)>1?1:0; 
起到简单滤波作用。 
*/ 
 
int CBuildctDlg::getFiltedValue(unsigned char data[][IMAGEW/8],int x,int y) 
{ 
    int v=0; 
    //v=getValue(data,x,y)*7; 
    //v=v+getValue(data,x-1,y-1)+getValue(data,x,y-1)+getValue(data,x+1,y-1)+getValue(data,x-1,y) 
    //+getValue(data,x+1,y)+getValue(data,x-1,y+1)+getValue(data,x,y+1)+getValue(data,x+1,y+1); 
    for(int i=-2;i=2;i++) 
      for(int j=-2;j=2;j++) 
       v+=getValue(data,x+i,y+j); 
        
 
    return v>=3?1:0; 
} 
 
 
 
void CBuildctDlg::doBuildSurface() 
{ 
	CString imagename; 
	unsigned char (*buffer)[IMAGEW/8]=new unsigned char[IMAGEH][IMAGEW/8]; 
	Chain data1,data2; 
    LineChain layer1,layer2; 
	CBmpRead bmp; 
    //Triangle body; 
	CString tempStr="..."; 
	this->updateStatus ("正在计算..."); 
	for(int i=0;i<m_list.GetCount ();i++) 
    { 
        this->m_list.GetText (i,imagename);  
		tempStr=imagename+"..."; 
		this->updateStatus ("解码:"+tempStr); 
        int re=bmp.readImage(imagename.GetBuffer (imagename.GetLength ()),"image.txt",buffer); 
        if(re!=0) 
        { 
	        MessageBox("\nSorry!Image can't be read(%d),Image:"+imagename); 
            break; 
        } 
        //提取边界点 
        identifyContour(buffer,&data2); 
        //根据点构造边 
        buildAllEdges(&data2,&layer2); 
        layer2.setLayerNo(i); 
        //printf("layer count1:%d\n",layer2->getCount()); 
        //检查轮廓线拓扑 
        layer2.checkTopo(); 
        //释放非LINKED的节点所占内存,以节省内存空间 
        data2.freeNotLinked(); 
	//layer2.graphicsDebugPrint(); 
        //layer2.debugPrint(); 
 
        //在相邻两断层间创建三角面片 
        //layer1.simplePrint(); 
        //layer2.simplePrint(); 
        //printf("\n..createSurface:\n"); 
        buildSurface(i-1,&layer1,&layer2,&body); 
        //layer2.erase(); 
        //data2.erase(); 
        layer1.erase(); 
        data1.erase(); 
        data1.setFirst(data2.removeFirst()); 
        layer1.setFirst(layer2.removeFirst()); 
        layer1.setLayerNo(i); 
 
    } 
    layer2.erase(); 
    data2.erase(); 
    layer1.erase(); 
    data1.erase(); 
    delete []buffer; 
	body.setAvailable (true); 
	body.printToFile ("body.txt"); 
    this->updateStatus ("Ready"); 
} 
 
ChainNode * CBuildctDlg::getStartInLine(ChainNode *targetline, ChainNode *line, int x, int y) 
{ 
	//long	pointto=(p1->getX()-centerup.x)*(p2->getY()-centerdown.y )-((p2->getX()-centerdown.x ))*((p1->getY()-centerup.y )); 
	if(targetline==NULL||line==NULL)return NULL; 
	int vx=x-line->getX (); 
	int vy=y-line->getY (); 
	ChainNode *p=NULL; 
    ChainNode *nearest=NULL; 
	POINT center; 
	center.x =targetline->getX (); 
	center.y =targetline->getY (); 
    p=targetline->getNext (); 
	bool avail=false; 
    do 
    { 
        if(p==NULL)break; 
        long pointto=vx*(p->getY()-center.y )-(p->getX()-center.x )*vy ; 
        if(pointto<0 && !avail)avail=true; 
		if((pointto==0)||(pointto>0 && avail)) 
        { 
            nearest=p; 
			break; 
        } 
 
        p=p->getLink(); 
    }while(true);	 
    return nearest; 
} 
 
void CBuildctDlg::debugPrint(CString msg) 
{ 
	msg=msg+"\n"; 
	debugFile.Write (msg.GetBuffer (msg.GetLength ()),msg.GetLength ()); 
 
} 
 
void CBuildctDlg::updateStatus(CString msg) 
{ 
	this->m_status =msg; 
	UpdateData(false); 
 
}